Crisp answer: systemd is the init system and service manager on all modern Linux distributions. It's PID 1, starts all services, and manages the system lifecycle. Everything it manages is a "unit."
Unit types:
| Suffix | Type | Purpose |
|---|---|---|
.service |
Service | A long-running daemon or one-shot task |
.target |
Target | A group of units, like a runlevel |
.socket |
Socket | Socket-activated service (starts on first connection) |
.timer |
Timer | Like cron, but tracked in journald |
.mount |
Mount | A filesystem mount |
.device |
Device | A kernel device |
.path |
Path | Watches a filesystem path, activates on change |
systemctl — the main control tool:
# Service management
systemctl status nginx # Detailed status: active, inactive, failed
systemctl start nginx # Start now
systemctl stop nginx # Stop now
systemctl restart nginx # Stop + start
systemctl reload nginx # Reload config without restart (if supported)
systemctl enable nginx # Start automatically at boot
systemctl disable nginx # Don't start at boot
systemctl is-active nginx # Returns active/inactive/failed
systemctl is-enabled nginx # Returns enabled/disabled
systemctl is-failed nginx # Returns failed/active
# Listing units
systemctl list-units # All active units
systemctl list-units --state=failed # Only failed units
systemctl list-units --type=service # Only services
systemctl list-unit-files # All installed units + enabled state
# System targets
systemctl get-default # Default target (usually multi-user or graphical)
systemctl set-default multi-user.target # Change default
systemctl isolate rescue.target # Switch to rescue mode NOW (emergency)
# Reload systemd after editing unit files
systemctl daemon-reload # Re-read unit files from disk
Unit file anatomy:
Unit files live in:
/lib/systemd/system/— package-installed (don't edit)/etc/systemd/system/— local overrides (edit these)/run/systemd/system/— runtime-generated
# /etc/systemd/system/myapp.service
[Unit]
Description=My Application Server
Documentation=https://docs.myapp.com
After=network-online.target postgresql.service
Requires=postgresql.service # Hard dependency (fails if postgres fails)
Wants=redis.service # Soft dependency (starts redis, won't fail if redis fails)
[Service]
Type=simple # simple|forking|oneshot|notify|dbus
User=myapp
Group=myapp
WorkingDirectory=/opt/myapp
EnvironmentFile=/etc/myapp/env # Load environment variables from file
ExecStart=/opt/myapp/bin/server --port 8080
ExecReload=/bin/kill -HUP $MAINPID # How to reload
Restart=on-failure # Restart if exits non-zero
RestartSec=5 # Wait 5s before restart
StartLimitIntervalSec=60 # Over 60s window...
StartLimitBurst=3 # ...allow max 3 restarts
KillMode=mixed # Send SIGTERM to main, then SIGKILL after timeout
TimeoutStopSec=30 # Wait 30s for graceful shutdown
# Security hardening
NoNewPrivileges=yes
ProtectSystem=strict # /usr, /boot, /etc read-only
PrivateTmp=yes # Isolated /tmp
[Install]
WantedBy=multi-user.target # Enable under this target
Dependency types:
| Directive | Meaning |
|---|---|
Requires= |
Hard: if the listed unit fails, this unit also fails |
Wants= |
Soft: tries to start the listed unit, continues if it fails |
After= |
Ordering: start after the listed units (not a dependency, just order) |
Before= |
Ordering: start before the listed units |
BindsTo= |
Stops this unit if the bound unit stops |
PartOf= |
This unit is stopped/restarted when the listed unit is |
Conflicts= |
Cannot run simultaneously with the listed unit |
journalctl — the log viewer:
systemd captures all service output into a structured binary journal (replacing syslog for most services on modern distros).
journalctl # All logs (old first)
journalctl -r # Reverse (newest first)
journalctl -f # Follow (like tail -f)
journalctl -n 100 # Last 100 lines
journalctl -u nginx # Logs for specific service
journalctl -u nginx -f # Follow nginx logs
journalctl -u nginx --since "1 hour ago"
journalctl -u nginx --since "2025-06-01 10:00:00" --until "2025-06-01 11:00:00"
journalctl -p err # Only errors (emerg/alert/crit/err)
journalctl -p err -u nginx # Errors from nginx
journalctl -b # Current boot only
journalctl -b -1 # Previous boot
journalctl --list-boots # List all boots with IDs
journalctl -k # Kernel messages (like dmesg)
journalctl --disk-usage # How much space journal is using
journalctl --vacuum-size=500M # Trim journal to 500MB
journalctl -o json-pretty # JSON output for parsing
Override files (drop-ins):
Instead of editing the original unit file (which gets overwritten by updates), use a drop-in:
systemctl edit nginx # Creates /etc/systemd/system/nginx.service.d/override.conf
# Or manually:
mkdir -p /etc/systemd/system/nginx.service.d/
cat > /etc/systemd/system/nginx.service.d/memory.conf << EOF
[Service]
MemoryMax=512M
Restart=always
EOF
systemctl daemon-reload
systemctl restart nginx
Target dependencies (how startup ordering works):
systemctl list-dependencies multi-user.target # What does this target pull in?
systemctl list-dependencies nginx --reverse # What depends on nginx?
What to say in the interview:
"systemd is PID 1 — everything on the system is its child. I work with it daily: systemctl status to see what's wrong, restart to recover a service, daemon-reload after editing unit files. For logs, journalctl -u with -f to follow and --since to narrow down timeframes. The unit file dependencies are important: After= is just ordering, Requires= is a hard dependency that will stop both services if one fails. For production hardening, I always add NoNewPrivileges and PrivateTmp to service unit files — easy wins that limit the blast radius of a compromised service."