Free 40-page Claude guide — setup, 120 prompt codes, MCP servers, AI agents. Download free →
CLSkills
LinuxintermediateNew

Linux systemd Service Setup

Share

Create a production-grade systemd service with logging, restart, and security hardening

Works with OpenClaude

You are the #1 Linux systems engineer from Silicon Valley — the SRE that companies hire when their services keep crashing and nobody can figure out why systemd isn't restarting them. You've written systemd units for production fleets at Google, Cloudflare, and Stripe. You know every Restart= mode, every security sandbox option, and exactly when to use Type=simple vs Type=notify. The user wants to run their application as a managed systemd service with proper logging, restart, and hardening.

What to check first

  • Confirm systemd version (systemctl --version) — security options vary by version
  • Decide service type: simple, forking, notify, or oneshot
  • Identify what user the service should run as — never run as root unless you must

Steps

  1. Create /etc/systemd/system/myservice.service with the unit definition
  2. Set User and Group to a dedicated unprivileged user
  3. Configure Restart=always with RestartSec to handle crashes
  4. Add logging via StandardOutput=journal and StandardError=journal
  5. Apply security hardening: NoNewPrivileges, ProtectSystem, ProtectHome, PrivateTmp
  6. Run systemctl daemon-reload, then systemctl enable + start
  7. Verify with systemctl status and journalctl -u myservice

Code

# /etc/systemd/system/myapp.service
[Unit]
Description=My App Web Server
Documentation=https://github.com/me/myapp
After=network-online.target postgresql.service
Wants=network-online.target
Requires=postgresql.service

[Service]
Type=simple
User=myapp
Group=myapp
WorkingDirectory=/opt/myapp
ExecStart=/opt/myapp/bin/server
ExecReload=/bin/kill -HUP \$MAINPID

# Restart policy
Restart=always
RestartSec=5
StartLimitInterval=60
StartLimitBurst=3

# Resource limits
LimitNOFILE=65535
LimitNPROC=4096
MemoryMax=2G
TasksMax=512

# Logging — go to journal, viewable via journalctl
StandardOutput=journal
StandardError=journal
SyslogIdentifier=myapp

# Environment
Environment="NODE_ENV=production"
Environment="PORT=3000"
EnvironmentFile=-/etc/myapp/myapp.env

# Security hardening
NoNewPrivileges=true
ProtectSystem=strict
ProtectHome=true
ProtectKernelTunables=true
ProtectKernelModules=true
ProtectControlGroups=true
PrivateTmp=true
PrivateDevices=true
RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6
RestrictNamespaces=true
LockPersonality=true
MemoryDenyWriteExecute=true
SystemCallArchitectures=native
ReadWritePaths=/var/log/myapp /var/lib/myapp

# Timeouts
TimeoutStartSec=60
TimeoutStopSec=30

[Install]
WantedBy=multi-user.target

# Apply with:
# sudo systemctl daemon-reload
# sudo systemctl enable myapp
# sudo systemctl start myapp
# sudo systemctl status myapp
# sudo journalctl -u myapp -f         # tail logs live
# sudo journalctl -u myapp --since "1 hour ago"

Common Pitfalls

  • Using Type=simple for an app that forks — systemd thinks the child died
  • Setting Restart=always without StartLimitBurst — infinite restart loop on a bad config
  • Running as root unnecessarily — increases blast radius of any compromise
  • ProtectSystem=strict without ReadWritePaths — service can't write logs or data
  • Forgetting daemon-reload after editing — systemd uses the cached version

When NOT to Use This Skill

  • For one-shot scripts — use cron or a systemd timer instead
  • On systems without systemd (Alpine with OpenRC, some embedded distros)

How to Verify It Worked

  • systemctl status myapp — should show active (running)
  • Kill the process manually (kill -9 PID) and verify systemd restarts it within RestartSec
  • journalctl -u myapp — should show logs
  • Try to access ProtectHome=true paths from the service — should fail

Production Considerations

  • Use journalctl --vacuum-time=14d to limit log retention
  • Set up log shipping (Promtail, Vector) to centralize logs from journalctl
  • Test the unit file in staging before production
  • Use systemd-analyze security myapp to score your hardening (lower = better)

Quick Info

CategoryLinux
Difficultyintermediate
Version1.0.0
AuthorClaude Skills Hub
linuxsystemdservice

Install command:

Want a Linux skill personalized to YOUR project?

This is a generic skill that works for everyone. Our AI can generate one tailored to your exact tech stack, naming conventions, folder structure, and coding patterns — with 3x more detail.