Services (.service)

Run a systemd service as a specific user and group

3 min read

By default a system service runs as root. Almost nothing should. Run it as a least-privileged user instead.

With an existing user

[Service]
User=myapp
Group=myapp
WorkingDirectory=/opt/myapp
ExecStart=/opt/myapp/bin/server
Restart=on-failure

Create the dedicated, login-less system user first if it doesn’t exist:

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

Or let systemd invent a user (DynamicUser)

[Service]
DynamicUser=yes
StateDirectory=myapp
ExecStart=/opt/myapp/bin/server

DynamicUser=yes runs the service as a transient UID that exists only while it runs — no useradd needed. Pair it with StateDirectory=myapp, which auto-creates /var/lib/myapp owned by that transient user (also CacheDirectory=, LogsDirectory=, RuntimeDirectory=).

Apply and confirm

sudo systemctl daemon-reload
sudo systemctl restart myapp.service
systemctl show myapp.service -p MainPID
ps -o user= -p "$(systemctl show -p MainPID --value myapp.service)"

Gotchas: if the service binds a port below 1024 as a non-root user, grant just that capability with AmbientCapabilities=CAP_NET_BIND_SERVICE instead of running as root. With DynamicUser=yes, the user is different on every start, so never write files to a fixed path you own — use the *Directory= options, which set ownership for you.

Open the full version (with copy buttons) ↗

← All recipes