User and Group Isolation in systemd

Configure User=, Group=, DynamicUser=, and SupplementaryGroups= in systemd services. Learn how to create dedicated service users and isolate services from each other.

Operational Guides

Detailed Explanation

Running Services as Non-Root Users

Running services as root is a security risk. Systemd makes it easy to run services as dedicated users with minimal privileges.

Basic User/Group Configuration

[Service]
User=myapp
Group=myapp

The user and group must exist on the system. Create them before enabling the service:

sudo useradd --system --no-create-home --shell /usr/sbin/nologin myapp

The flags ensure:

  • --system: Creates a system user (UID below 1000)
  • --no-create-home: No home directory
  • --shell /usr/sbin/nologin: Cannot log in interactively

DynamicUser — Ephemeral Users

DynamicUser=yes creates a temporary user that exists only while the service runs:

[Service]
DynamicUser=yes
ExecStart=/usr/local/bin/myapp
StateDirectory=myapp
CacheDirectory=myapp
LogsDirectory=myapp

Benefits:

  • No need to create users manually during installation
  • User IDs are allocated from a dedicated range (61184-65519)
  • Automatic cleanup when the service stops
  • Forced ProtectSystem=strict and ProtectHome=read-only

Pair with StateDirectory=, CacheDirectory=, and LogsDirectory= because DynamicUser restricts filesystem access.

SupplementaryGroups

Grant access to additional resources via supplementary groups:

[Service]
User=myapp
Group=myapp
SupplementaryGroups=ssl-cert docker

Common supplementary groups:

  • ssl-cert: Access to SSL certificates in /etc/ssl/private/
  • docker: Access to the Docker socket
  • adm: Access to log files in /var/log/
  • audio, video: Access to hardware devices

File Ownership Preparation

Ensure the service user owns its data directories:

sudo mkdir -p /opt/myapp/data
sudo chown -R myapp:myapp /opt/myapp/data

Or let systemd manage it with StateDirectory=:

[Service]
StateDirectory=myapp
# Creates /var/lib/myapp/ owned by the service user

Systemd-Managed Directories

Directive Creates Typical Use
StateDirectory= /var/lib/{name}/ Persistent data
CacheDirectory= /var/cache/{name}/ Cached data
LogsDirectory= /var/log/{name}/ Log files
RuntimeDirectory= /run/{name}/ Sockets, PID files
ConfigurationDirectory= /etc/{name}/ Configuration

These directories are created with correct ownership before ExecStart runs and are the recommended approach for managing service data.

Combining with Hardening

[Service]
User=myapp
Group=myapp
NoNewPrivileges=yes
ProtectSystem=strict
ProtectHome=yes
ReadWritePaths=/opt/myapp/data
PrivateTmp=yes

This creates a service that runs as a dedicated user with minimal filesystem access and no ability to escalate privileges.

Use Case

Setting up proper process isolation for multiple services on the same server, ensuring each service runs as a dedicated user with access only to its own data directories and required system resources.

Try It — Systemd Unit File Generator

Open full tool