Skip to Content
DocsOperationsSystem Administrationsystemd & Service Management

systemd & Service Management

systemd is the init system and service manager for Ubuntu 26.04, responsible for bootstrapping the system, managing services, and daemons. Mastering systemd is an essential skill for Ubuntu system administration.

systemctl Basics

Managing Service State

# Start a service sudo systemctl start nginx # Stop a service sudo systemctl stop nginx # Restart a service sudo systemctl restart nginx # Reload configuration (without interrupting the service) sudo systemctl reload nginx # Reload if supported, otherwise restart sudo systemctl reload-or-restart nginx # Check service status systemctl status nginx

Boot Service Management

# Enable a service at boot sudo systemctl enable nginx # Disable a service at boot sudo systemctl disable nginx # Enable and start immediately sudo systemctl enable --now nginx # Prevent a service from being started (including manually) sudo systemctl mask nginx # Remove the mask sudo systemctl unmask nginx

Viewing Service Information

# List all running services systemctl list-units --type=service --state=running # List all installed services systemctl list-unit-files --type=service # List failed services systemctl list-units --failed # View a service's dependencies systemctl list-dependencies nginx # View detailed service properties systemctl show nginx # Check if a service is active systemctl is-active nginx # Check if a service is enabled at boot systemctl is-enabled nginx

Service Unit Files

Unit File Locations

systemd service unit files are stored in the following locations, in order of priority (highest to lowest):

PathDescription
/etc/systemd/system/Custom admin configurations, highest priority
/run/systemd/system/Runtime-generated unit files
/lib/systemd/system/Default unit files installed by packages

Viewing Unit Files

# View a service's unit file contents systemctl cat nginx.service # View the unit file path systemctl show -p FragmentPath nginx.service # Edit a unit file (creates an override) sudo systemctl edit nginx.service # Edit the full unit file sudo systemctl edit --full nginx.service

Unit File Structure

A typical service unit file has three sections:

[Unit] Description=Service description Documentation=https://example.com/docs After=network.target Wants=network-online.target Requires=postgresql.service [Service] Type=simple User=www-data Group=www-data WorkingDirectory=/opt/myapp ExecStartPre=/opt/myapp/pre-start.sh ExecStart=/opt/myapp/start.sh ExecStop=/opt/myapp/stop.sh ExecReload=/bin/kill -HUP $MAINPID Restart=on-failure RestartSec=5 StandardOutput=journal StandardError=journal Environment=NODE_ENV=production EnvironmentFile=/opt/myapp/.env [Install] WantedBy=multi-user.target

Common Service Types

TypeDescription
simpleDefault; the process started by ExecStart is the main process
forkingThe service forks a child process; startup is considered complete when the parent exits
oneshotOne-time task; considered complete when the process exits
notifyThe service notifies systemd via sd_notify when startup is complete
idleSimilar to simple, but waits for other tasks to finish before starting

Restart Policies

OptionDescription
noDo not restart automatically (default)
on-successRestart on normal exit
on-failureRestart on abnormal exit
on-abnormalRestart when killed by signal or timeout
on-abortRestart when killed by an uncaught signal
alwaysAlways restart regardless of exit reason

Creating Custom Services

Example: Node.js Application Service

Create a unit file:

sudo nano /etc/systemd/system/myapp.service

Add the following content:

[Unit] Description=My Node.js Application After=network.target [Service] Type=simple User=nodeapp Group=nodeapp WorkingDirectory=/opt/myapp ExecStart=/usr/bin/node /opt/myapp/server.js Restart=on-failure RestartSec=10 StandardOutput=journal StandardError=journal SyslogIdentifier=myapp Environment=NODE_ENV=production PORT=3000 # Security hardening NoNewPrivileges=yes ProtectSystem=strict ProtectHome=yes ReadWritePaths=/opt/myapp/data PrivateTmp=yes [Install] WantedBy=multi-user.target

Enable and start the service:

# Reload systemd configuration sudo systemctl daemon-reload # Start the service sudo systemctl enable --now myapp.service # Check status systemctl status myapp.service # View logs journalctl -u myapp.service -f

Example: Python Application Service

[Unit] Description=Python Flask Application After=network.target [Service] Type=simple User=flask Group=flask WorkingDirectory=/opt/flask-app ExecStart=/opt/flask-app/venv/bin/gunicorn -w 4 -b 0.0.0.0:8000 app:app Restart=always RestartSec=5 Environment=FLASK_ENV=production [Install] WantedBy=multi-user.target

Example: Service with Watchdog

[Unit] Description=Critical Service with Watchdog After=network.target [Service] Type=notify ExecStart=/opt/critical/run.sh WatchdogSec=30 Restart=on-failure RestartSec=5 # Auto-restart on failure, up to 5 attempts StartLimitIntervalSec=300 StartLimitBurst=5 [Install] WantedBy=multi-user.target

Using Overrides to Modify Existing Services

It is not recommended to directly modify files in /lib/systemd/system/. Instead, use overrides:

# Create an override file sudo systemctl edit nginx.service

This opens an editor where you can add configuration overrides:

[Service] # Add memory limit MemoryMax=512M # Change restart policy Restart=always RestartSec=3

The override file is saved to /etc/systemd/system/nginx.service.d/override.conf.

# View the merged full configuration systemctl cat nginx.service # Reload configuration sudo systemctl daemon-reload sudo systemctl restart nginx

System Management Commands

# View boot time systemd-analyze # View boot time per service (sorted) systemd-analyze blame # View the boot critical chain systemd-analyze critical-chain # View the current default target systemctl get-default # Set the default target sudo systemctl set-default multi-user.target # Command-line mode sudo systemctl set-default graphical.target # Graphical mode # Shutdown and reboot sudo systemctl poweroff sudo systemctl reboot # Suspend and hibernate sudo systemctl suspend sudo systemctl hibernate

Resource Limits

You can set resource limits in service unit files:

[Service] # CPU limit CPUQuota=50% # Memory limit MemoryMax=1G MemoryHigh=800M # I/O limit IOWeight=100 IOReadBandwidthMax=/dev/sda 10M # Process count limit TasksMax=100 # File descriptor limit LimitNOFILE=65535

Troubleshooting

# View the reason a service failed systemctl status myapp.service journalctl -u myapp.service --no-pager -n 50 # Validate unit file syntax systemd-analyze verify /etc/systemd/system/myapp.service # View systemd's own logs journalctl -b _PID=1 # Reset the failure count sudo systemctl reset-failed myapp.service
Last updated on