06 — System Services
A service (daemon) is a program that runs in the background, waiting to handle requests. Nginx serves web pages, SSH lets you log in remotely, cron runs scheduled jobs — all run as services.
What is a Daemon?
A daemon is a process that:
- Starts at boot (usually)
- Runs in the background
- Has no attached terminal (detached from /dev/tty)
- Waits for something to happen (network request, timer, file change)
SSH server: sshd → listens on port 22, spawns shell when you connect
Web server: nginx → listens on port 80/443, serves pages when you request
Database: postgres → listens on port 5432, runs queries when apps connect
Print: cupsd → queues print jobs
DNS: systemd-resolved → answers DNS queries
systemd — The Service Manager
systemd is the init system on most modern Linux distros. It:
- Starts services at boot
- Keeps services running (restarts on failure)
- Provides logging (journald)
- Manages sockets, timers, mounts
systemctl — The Main Command
# Start (run now) / Stop / Restart a service:
sudo systemctl start nginx
sudo systemctl stop nginx
sudo systemctl restart nginx
# Restart only if already running (reload config without full restart):
sudo systemctl reload nginx
# Enable (start at boot) / Disable:
sudo systemctl enable nginx
sudo systemctl disable nginx
# Check status (is it running? any errors?):
sudo systemctl status nginx
# ● nginx.service - A high performance web server
# Loaded: loaded (/etc/systemd/system/nginx.service; enabled)
# Active: active (running) since Sat 2025-06-06 10:00:00 UTC; 1 day 3h agoEnable vs Start
enable = create symlinks so service starts at boot
start = run it right now
You almost always want BOTH: enable AND start
# Common pattern when installing nginx:
sudo systemctl enable --now nginx
# Equivalent to:
sudo systemctl enable nginx
sudo systemctl start nginxChecking Service State
systemctl status nginx
systemctl is-active nginx # active or inactive
systemctl is-enabled nginx # enabled or disabled
# List all services:
systemctl list-units --type=service
systemctl list-units --type=service --state=running
# Show failed services:
systemctl --failedViewing Logs for a Service
# All logs for a service:
sudo journalctl -u nginx
# Follow logs (like tail -f):
sudo journalctl -u nginx -f
# Last 20 lines:
sudo journalctl -u nginx -n 20
# Since a time:
sudo journalctl -u nginx --since "1 hour ago"
sudo journalctl -u nginx --since "2025-06-06 10:00"Common Service Operations
# Stop a misbehaving service:
sudo systemctl stop nginx
# Force-restart a hung service:
sudo systemctl kill -s SIGKILL nginx
sudo systemctl restart nginx
# Mask (completely disable, can't be started manually either):
sudo systemctl mask nginx
# Unmask to restore:
sudo systemctl unmask nginx
# Reload systemd after creating a new service file:
sudo systemctl daemon-reload
# (then systemctl restart your-service)Service Files
A service file tells systemd how to run your service.
# Location:
/etc/systemd/system/ # user-created services
/run/systemd/system/ # runtime-generated
/lib/systemd/system/ # packages install here (symlinked to /etc/systemd/system)
# View an existing service file:
systemctl cat nginxAnatomy of a Service File
[Unit]
Description=My Web Application
# Start after network is ready:
After=network.target
# Required by:
Wants=network.target
[Service]
Type=simple # simple = one process (most common)
# Type=oneshot # runs once and exits (like a cron job)
# Type=forking # parent exits after spawning child (legacy)
ExecStart=/usr/local/bin/myapp
WorkingDirectory=/opt/myapp
Restart=always # restart on failure
RestartSec=5 # wait 5 seconds before restarting
User=myapp
Group=myapp
# Environment:
Environment=NODE_ENV=production PORT=3000
[Install]
WantedBy=multi-user.target
# graphical.target = boot to GUI
# multi-user.target = boot to CLIUseful Service File Options
[Service]
# Restart policies:
Restart=no # never restart
Restart=on-success # restart only on clean exit (exit code 0)
Restart=on-failure # restart on non-zero exit
Restart=always # always restart
# Environment:
Environment=PORT=3000
EnvironmentFile=/etc/myapp/env
# Resource limits:
MemoryMax=512M
CPUQuota=50%
LimitNOFILE=65536
# Security hardening:
NoNewPrivileges=true
ProtectSystem=strict
ReadOnlyPaths=/
ReadWritePaths=/var/log/myapp
PrivateTmp=true
# Logging:
StandardOutput=journal
StandardError=journalTimers (cron Alternative)
systemd timers trigger services on a schedule, like cron but with journal integration and dependencies.
# /etc/systemd/system/backup.timer
[Unit]
Description=Run backup daily at 3am
[Timer]
OnCalendar=*-*-* 03:00:00
Persistent=true # catch up if system was off
[Install]
WantedBy=timers.targetsudo systemctl enable --now backup.timer
systemctl list-timersQuick Reference
# Core commands
systemctl start nginx
systemctl stop nginx
systemctl restart nginx
systemctl reload nginx
systemctl status nginx
systemctl enable nginx
systemctl disable nginx
systemctl enable --now nginx # enable + start
systemctl disable --now nginx # disable + stop
systemctl mask nginx # cannot be started
systemctl unmask nginx # restore
systemctl daemon-reload # reload unit files
# Check state
systemctl is-active nginx
systemctl is-enabled nginx
systemctl --failed
# Logs
journalctl -u nginx
journalctl -u nginx -f
journalctl -u nginx --since "1 hour ago"
# List services
systemctl list-units --type=service
systemctl list-units --type=service --state=running