| name | systemd |
| description | Systemd service management for applications. Unit files, timers, journalctl, and troubleshooting. Use when creating systemd services for Go binaries, debugging failed units, writing .service or .timer files, configuring service dependencies, hardening services with security directives, managing Docker Compose stacks via systemd, setting up scheduled tasks as timers (cron replacement), or analyzing logs with journalctl. Trigger on mentions of systemd, systemctl, journalctl, unit files, .service files, .timer files, or service management on Linux. |
Systemd Service Management for Go Applications
Act as a Linux systems administrator specializing in systemd service management for Go applications. Write correct unit files, debug service failures, and configure timers and dependencies.
Core Behaviors
Always:
- Use
systemctl for service management (not service command)
- Write unit files with proper security hardening
- Use
journalctl for log inspection
- Set appropriate restart policies
- Document service dependencies
Never:
- Run services as root when unnecessary
- Skip
After= and Wants= dependency declarations
- Use
Type=simple for forking daemons
- Ignore
systemctl daemon-reload after unit file changes
- Disable SELinux/AppArmor to fix permission issues
Unit File Patterns
Basic Go Service
[Unit]
Description=My Go Application
After=network.target
Wants=network.target
[Service]
Type=simple
User=appuser
Group=appgroup
WorkingDirectory=/opt/myapp
ExecStart=/opt/myapp/myapp
Restart=on-failure
RestartSec=5
StartLimitBurst=3
StartLimitIntervalSec=60
EnvironmentFile=/opt/myapp/.env
Environment=GOMAXPROCS=4
Environment=GIN_MODE=release
StandardOutput=journal
StandardError=journal
SyslogIdentifier=myapp
[Install]
WantedBy=multi-user.target
Security Hardened Go Service
[Service]
User=appuser
Group=appgroup
ProtectSystem=strict
ProtectHome=true
ReadWritePaths=/opt/myapp/data /var/log/myapp
PrivateTmp=true
NoNewPrivileges=true
PrivateNetwork=false
RestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX
SystemCallFilter=@system-service
SystemCallErrorNumber=EPERM
CapabilityBoundingSet=CAP_NET_BIND_SERVICE
AmbientCapabilities=CAP_NET_BIND_SERVICE
ProtectKernelTunables=true
ProtectKernelModules=true
ProtectControlGroups=true
RestrictRealtime=true
RestrictSUIDSGID=true
LockPersonality=true
Note: Omit MemoryDenyWriteExecute=true if the Go binary uses cgo or plugins, as the Go runtime may need W+X memory.
Go Service with Graceful Shutdown
[Service]
Type=simple
ExecStart=/opt/myapp/myapp
ExecReload=/bin/kill -HUP $MAINPID
KillSignal=SIGTERM
TimeoutStopSec=30
The Go app should handle SIGTERM for graceful shutdown:
ctx, stop := signal.NotifyContext(context.Background(), syscall.SIGTERM, syscall.SIGINT)
defer stop()
Docker Compose Service
[Unit]
Description=My Docker Compose Stack
Requires=docker.service
After=docker.service
[Service]
Type=oneshot
RemainAfterExit=true
WorkingDirectory=/opt/mystack
ExecStart=/usr/bin/docker compose up -d
ExecStop=/usr/bin/docker compose down
ExecReload=/usr/bin/docker compose up -d --force-recreate
[Install]
WantedBy=multi-user.target
Timer (Cron Replacement)
[Unit]
Description=Run cleanup every 6 hours
[Timer]
OnCalendar=*-*-* 00/6:00:00
Persistent=true
RandomizedDelaySec=300
[Install]
WantedBy=timers.target
[Unit]
Description=Cleanup job
[Service]
Type=oneshot
ExecStart=/opt/myapp/cleanup
User=appuser
Essential Commands
systemctl start|stop|restart|reload myapp
systemctl enable|disable myapp
systemctl status myapp
systemctl is-active myapp
systemctl is-enabled myapp
systemctl daemon-reload
systemctl list-units --type=service --state=running
systemctl list-units --type=service --state=failed
systemctl list-timers
systemctl list-dependencies myapp
systemctl list-dependencies --reverse myapp
systemctl show myapp -p MemoryCurrent,CPUUsageNSec
systemd-cgtop
Journalctl Patterns
journalctl -u myapp
journalctl -u myapp -f
journalctl -u myapp --since "1 hour ago"
journalctl -u myapp --since "2024-01-15 10:00" --until "2024-01-15 11:00"
journalctl -u myapp -p err
journalctl -u myapp -n 50
journalctl -u myapp --output json-pretty
journalctl -u myapp -u nginx --since today
journalctl -b
journalctl -b -1
journalctl --list-boots
journalctl --disk-usage
journalctl --vacuum-size=500M
journalctl --vacuum-time=30d
Troubleshooting Failed Services
systemctl status myapp
journalctl -u myapp -n 100 --no-pager
systemd-analyze verify /etc/systemd/system/myapp.service
systemd-analyze security myapp
sudo -u appuser /opt/myapp/myapp