systemd
Systemd
systemctl Commands
sudo systemctl start myapp
sudo systemctl stop myapp
sudo systemctl restart myapp
sudo systemctl reload myapp # Reload config without full restart
sudo systemctl enable myapp # Auto-start on boot
sudo systemctl enable --now myapp # Enable and start immediately
sudo systemctl disable myapp
systemctl status myapp
systemctl is-active myapp
systemctl is-enabled myapp
systemctl show myapp -p MainPID,MemoryCurrent
sudo systemctl daemon-reload # Reload unit files after editing
systemctl list-units --type=service --state=failed
systemctl list-unit-files --type=service
systemctl list-timers
Writing Unit Files
Place system services in /etc/systemd/system/myapp.service.
[Unit]
Description=My Application Server
After=network.target postgresql.service
Wants=postgresql.service
[Service]
Type=simple
User=appuser
Group=appgroup
WorkingDirectory=/opt/myapp
ExecStart=/opt/myapp/bin/server
ExecReload=/bin/kill -HUP $MAINPID
Restart=on-failure
RestartSec=5
StandardOutput=journal
StandardError=journal
SyslogIdentifier=myapp
[Install]
WantedBy=multi-user.target
After creating or editing: sudo systemctl daemon-reload && sudo systemctl enable --now myapp
Service Types
| Type | Behavior | Use Case |
|---|---|---|
| simple | Default. ExecStart process is the main process | Most long-running services |
| forking | Process forks; parent exits. Set PIDFile | Traditional daemons |
| oneshot | Runs and exits. Service is "active" after completion | Setup scripts, migrations |
| notify | Like simple, but sends sd_notify when ready | systemd-aware apps |
| idle | Like simple, but waits until other jobs finish | Low-priority startup tasks |
# Forking example
[Service]
Type=forking
PIDFile=/run/myapp/myapp.pid
ExecStart=/opt/myapp/bin/server --daemonize
# Oneshot example
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/local/bin/setup-iptables.sh
Environment Variables
[Service]
Environment=NODE_ENV=production
Environment=PORT=3000 HOST=0.0.0.0
EnvironmentFile=/etc/myapp/env
EnvironmentFile=-/etc/myapp/env.local # Dash prefix: no error if missing
Environment file (/etc/myapp/env): one VAR=VALUE per line.
Restart Policies
[Service]
Restart=on-failure
RestartSec=5
StartLimitIntervalSec=300 # Rate-limit window
StartLimitBurst=5 # Max restarts within window
| Policy | Clean exit | Unclean signal | Timeout | Watchdog |
|---|---|---|---|---|
| no | - | - | - | - |
| on-failure | - | Yes | Yes | Yes |
| on-abnormal | - | Yes | Yes | Yes |
| always | Yes | Yes | Yes | Yes |
Reset a failed unit: sudo systemctl reset-failed myapp
Resource Limits
[Service]
MemoryMax=512M
MemoryHigh=400M # Throttle before hard limit
CPUQuota=200% # 2 full cores max
CPUWeight=50 # Relative weight (default 100)
LimitNOFILE=65536
LimitNPROC=4096
Dependency Management
[Unit]
# Ordering only (does NOT pull in the dependency)
After=network.target redis.service
Before=nginx.service
# Pull in dependencies
Requires=postgresql.service # Hard: if postgres fails, this fails too
Wants=redis.service # Soft: continues even if redis fails
BindsTo=docker.service # Like Requires + stop when docker stops
# For services needing actual network connectivity
After=network-online.target
Wants=network-online.target
User Services
Place units in ~/.config/systemd/user/. No root required.
# ~/.config/systemd/user/myapp.service
[Unit]
Description=My User Application
[Service]
Type=simple
ExecStart=%h/bin/myapp
Restart=on-failure
Environment=PORT=8080
[Install]
WantedBy=default.target
systemctl --user daemon-reload
systemctl --user enable --now myapp
journalctl --user -u myapp -f
sudo loginctl enable-linger $USER # Run without active login session
%h expands to the user's home directory.
Timers (Cron Replacement)
# /etc/systemd/system/backup.timer
[Unit]
Description=Daily backup timer
[Timer]
OnCalendar=*-*-* 02:00:00
Persistent=true # Run missed executions after downtime
RandomizedDelaySec=900
[Install]
WantedBy=timers.target
# /etc/systemd/system/backup.service
[Unit]
Description=Backup job
[Service]
Type=oneshot
ExecStart=/usr/local/bin/backup.sh
Monotonic timers (relative to boot):
[Timer]
OnBootSec=5min
OnUnitActiveSec=1h # Repeat every hour after last run
OnCalendar examples:
hourly | daily | weekly
Mon,Fri *-*-* 09:00:00 # Mon and Fri at 9 AM
*-*-01 00:00:00 # First of every month
*-*-* *:00/15:00 # Every 15 minutes
Validate: systemd-analyze calendar "Mon,Fri *-*-* 09:00:00"
journalctl Log Querying
journalctl -u myapp -f # Follow
journalctl -u myapp -n 100 # Last 100 lines
journalctl -u myapp --since "1 hour ago" # Time filter
journalctl -u myapp --since "2024-01-15" --until "2024-01-16"
journalctl -u myapp -p err # Priority filter
journalctl -u myapp -b # Current boot only
journalctl -u myapp -o json-pretty -n 10 # JSON output
journalctl -u myapp -o json --no-pager | jq '.MESSAGE'
journalctl -k # Kernel messages
journalctl --disk-usage
sudo journalctl --vacuum-size=500M
sudo journalctl --vacuum-time=7d
Socket Activation
Start services on-demand when a connection arrives.
# /etc/systemd/system/myapp.socket
[Unit]
Description=My App Socket
[Socket]
ListenStream=8080
Accept=no
[Install]
WantedBy=sockets.target
# /etc/systemd/system/myapp.service
[Unit]
Description=My App
Requires=myapp.socket
[Service]
Type=simple
ExecStart=/opt/myapp/bin/server
The service receives the socket as fd 3 (SD_LISTEN_FDS_START). Enable the socket, not the service: sudo systemctl enable --now myapp.socket
Templated Units
Template files use @ in the name. Instance name is %i.
# /etc/systemd/system/myapp@.service
[Unit]
Description=My App instance %i
After=network.target
[Service]
Type=simple
User=appuser
ExecStart=/opt/myapp/bin/server --port %i
Restart=on-failure
[Install]
WantedBy=multi-user.target
sudo systemctl enable --now myapp@8080
sudo systemctl enable --now myapp@8081
Common Service Patterns
Node.js
[Service]
Type=simple
User=nodeapp
WorkingDirectory=/opt/nodeapp
ExecStart=/usr/bin/node server.js
EnvironmentFile=/etc/nodeapp/env
Environment=NODE_ENV=production
LimitNOFILE=65536
Restart=on-failure
RestartSec=5
Python (uvicorn with venv)
[Service]
Type=simple
User=pyapp
WorkingDirectory=/opt/pyapp
ExecStart=/opt/pyapp/venv/bin/python -m uvicorn main:app --host 0.0.0.0 --port 8000
EnvironmentFile=/etc/pyapp/env
Restart=on-failure
Go Binary
[Service]
Type=simple
User=goapp
ExecStart=/usr/local/bin/goservice
EnvironmentFile=/etc/goservice/env
Restart=on-failure
LimitNOFILE=65536
Docker Container
[Unit]
After=docker.service
Requires=docker.service
[Service]
Type=simple
Restart=always
RestartSec=10
ExecStartPre=-/usr/bin/docker stop mycontainer
ExecStartPre=-/usr/bin/docker rm mycontainer
ExecStart=/usr/bin/docker run --rm --name mycontainer -p 8080:80 myimage:latest
ExecStop=/usr/bin/docker stop mycontainer
- prefix on ExecStartPre: don't fail if the command fails (container may not exist).
All patterns need [Unit] with After=network.target and [Install] with WantedBy=multi-user.target.
Debugging Failed Services
systemctl status myapp
journalctl -xeu myapp # Logs with explanations
journalctl -u myapp -b --no-pager # Full boot log
systemd-analyze blame # Time per unit at boot
systemd-analyze critical-chain myapp # Dependency chain timing
systemd-analyze verify myapp.service # Validate unit file syntax
systemd-analyze security myapp # Security audit score
systemctl show myapp -p ExecMainStatus,Result,ActiveState
Common exit codes:
- 200: bad unit file syntax (check ExecStart path, missing
=) - 203: exec format error (missing shebang, wrong architecture)
- 217: user/group doesn't exist
Security Hardening
[Service]
ProtectSystem=strict # Mount / read-only
ProtectHome=true # Hide /home, /root, /run/user
ReadWritePaths=/var/lib/myapp # Whitelist writable paths
PrivateTmp=true # Isolated /tmp
NoNewPrivileges=true # Block privilege escalation
PrivateDevices=true # No physical device access
ProtectKernelTunables=true
ProtectKernelModules=true
ProtectKernelLogs=true
ProtectControlGroups=true
RestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX
SystemCallFilter=@system-service
SystemCallArchitectures=native
# Dynamic user (ephemeral UID, ideal for stateless services)
DynamicUser=true
StateDirectory=myapp # Auto-creates /var/lib/myapp
CacheDirectory=myapp # Auto-creates /var/cache/myapp
LogsDirectory=myapp # Auto-creates /var/log/myapp
# Allow binding ports < 1024 without root
CapabilityBoundingSet=CAP_NET_BIND_SERVICE
AmbientCapabilities=CAP_NET_BIND_SERVICE
Audit: systemd-analyze security myapp (0 = most secure, 10 = least).
Path Units (File Watching)
# /etc/systemd/system/deploy-watcher.path
[Unit]
Description=Watch for deployment triggers
[Path]
PathChanged=/var/deploy/trigger # Trigger on write + close
PathExists=/var/deploy/run-now # Trigger when file appears
PathModified=/var/deploy/config # Trigger on any write
Unit=deploy.service
[Install]
WantedBy=multi-user.target
# /etc/systemd/system/deploy.service
[Service]
Type=oneshot
ExecStart=/usr/local/bin/deploy.sh
sudo systemctl enable --now deploy-watcher.path
Quick Reference: Unit File Specifiers
| Specifier | Meaning |
|---|---|
%i |
Instance name (template units) |
%I |
Unescaped instance name |
%n |
Full unit name |
%h |
User home directory |
%t |
Runtime directory (/run) |
%S |
State directory (/var/lib) |
%C |
Cache directory (/var/cache) |
More from 1mangesh1/dev-skills-collection
curl-http
HTTP request construction and API testing with curl and HTTPie. Use when user asks to "test API", "make HTTP request", "curl POST", "send request", "test endpoint", "debug API", "upload file", "check response time", "set auth header", "basic auth with curl", "send JSON", "test webhook", "check status code", "follow redirects", "rate limit testing", "measure API latency", "stress test endpoint", "mock API response", or any HTTP calls from the command line.
28database-indexing
Database indexing internals, index type selection, query plan analysis, and write-overhead tradeoffs across PostgreSQL, MySQL, and MongoDB. Use when user asks to "optimize queries", "create indexes", "fix slow queries", "read EXPLAIN output", "reduce query time", "index strategy", "database performance", "composite index", "covering index", "partial index", "index bloat", "unused indexes", or needs help diagnosing and resolving database performance problems.
13testing-strategies
Testing strategies, patterns, and methodologies across the full testing spectrum. Use when asked about unit tests, integration tests, e2e tests, test pyramid, mocking, test doubles, TDD, property-based testing, snapshot testing, test coverage, mutation testing, contract testing, performance testing, test data management, CI/CD testing, flaky tests, test anti-patterns, test organization, test isolation, test fixtures, test parameterization, or any testing strategy, approach, or methodology.
10secret-scanner
This skill should be used when the user asks to "scan for secrets", "find API keys", "detect credentials", "check for hardcoded passwords", "find leaked tokens", "scan for sensitive keys", "check git history for secrets", "audit repository for credentials", or mentions secret detection, credential scanning, API key exposure, token leakage, password detection, or security key auditing.
10terraform
Terraform infrastructure as code for provisioning, modules, state management, and workspaces. Use when user asks to "create infrastructure", "write Terraform", "manage state", "create module", "import resource", "plan changes", or any IaC tasks.
10kubernetes
Kubernetes and kubectl mastery for deployments, services, pods, debugging, and cluster management. Use when user asks to "deploy to k8s", "create deployment", "debug pod", "kubectl commands", "scale service", "check pod logs", "create ingress", or any Kubernetes tasks.
10