Skip to content

Instantly share code, notes, and snippets.

@andyklimczak
Created October 6, 2025 01:05
Show Gist options
  • Select an option

  • Save andyklimczak/91f8bae198587c229fd12a4f4fe6dc1d to your computer and use it in GitHub Desktop.

Select an option

Save andyklimczak/91f8bae198587c229fd12a4f4fe6dc1d to your computer and use it in GitHub Desktop.

Revisions

  1. andyklimczak created this gist Oct 6, 2025.
    56 changes: 56 additions & 0 deletions gistfile1.txt
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,56 @@
    # /etc/systemd/system/myservice.service
    [Unit]
    Description=MyService via Docker Compose
    Wants=network-online.target docker.service
    After=network-online.target docker.service
    ConditionPathExists=/home/myuser/myservice/docker-compose.yml
    AssertPathExists=/home/myuser/myservice

    [Service]
    Type=simple
    User=myuser
    Group=myuser
    WorkingDirectory=/home/myuser/myservice

    # Compose file path once, so Exec lines stay tidy
    Environment="COMPOSE_FILE=/home/myuser/myservice/docker-compose.yml"

    # Sanity checks and optional image refresh
    ExecStartPre=/usr/bin/docker compose version
    ExecStartPre=/usr/bin/docker compose -f ${COMPOSE_FILE} pull --quiet

    # Foreground so systemd tracks the process
    ExecStart=/usr/bin/docker compose -f ${COMPOSE_FILE} up
    # Graceful stop that also removes the stack's network and orphans
    ExecStop=/usr/bin/docker compose -f ${COMPOSE_FILE} down

    # Restart policy and timings
    Restart=on-failure
    RestartSec=5
    TimeoutStartSec=0
    TimeoutStopSec=60
    KillMode=process

    # Let Docker manage its own cgroups
    Delegate=yes

    # Hardening. Be careful not to break the Docker client talking to dockerd.
    NoNewPrivileges=yes
    PrivateTmp=yes
    ProtectControlGroups=yes
    ProtectKernelModules=yes
    ProtectKernelTunables=yes
    ProtectSystem=full
    ProtectHome=read-only

    # Allow writes where your app needs them
    ReadWritePaths=/home/myuser/myservice

    # Docker CLI talks over a Unix socket and may reach the network for pulls
    RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6
    RestrictNamespaces=yes
    RestrictRealtime=yes
    SystemCallFilter=~@clock @debug @module @mount @obsolete @reboot @setuid @swap

    [Install]
    WantedBy=multi-user.target