SSD Nodes Learn
How to do am Matt ConnorBy Matt Connor · Updated 2026-07-24

how to run services without root access

Running services as root fit give attacker full server access. Use a dedicated unprivileged user or use systemd DynamicUser to lock down your system.

Why you no suppose run everything as root

Root fit do anything for the machine: e fit read every file, change any setting, or delete the whole system. If you run service as root, you dey give all that power to that service. If the service get bug wey attacker fit use, dem no go just get the service, dem go get root, and root na the whole server. If you run am as unprivileged user, you go lock the damage inside. Bug for service wey run as limited account go only give attacker wetin that account fit touch, and dat one suppose be almost nothing.

Na dis one be principle of least privilege: give every part of the system exactly the access e need to do im job, and nothing more. Na di best way to limit di blast radius of compromise, and for modern server, e no cost you anything to do am.

A dedicated account per service

Di classic way na to create separate system user for every service, one wey go only own dat service files and no fit log in. System account for web app fit look like dis:

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

Every flag dey matter. --system make am be service account, no be human login. --no-create-home skip di home directory wey e no need. --shell /usr/sbin/nologin mean say even if attacker somehow get di account, e no fit open shell with am. Di account dey exist only to own one process and im files.

Den give dat user only di files e need, and nothing more:

sudo chown -R appsvc:appsvc /opt/myapp

Now di service dey read and write im own directory and e no get business anywhere else for di disk. If e ever get exploit, di files wey attacker fit change go limited to /opt/myapp; di account fit still read anything wey be world-readable, but e no fit modify di rest of di system.

Let systemd run it as that user

Once di account don exist, tell systemd to run di service as am. For di unit file, one line dey do am:

[Service]
ExecStart=/opt/myapp/bin/server
User=appsvc
Group=appsvc

User=appsvc mean say di process go start with dat account limited privileges instead of root. Na di normal, well-known way to run application under systemd, and e worth doing for every service wey you write unit for.

Or skip di account entirely with DynamicUser

systemd fit go one step further and create throwaway user for you, one wey dey exist only while di service dey run. Set DynamicUser=yes and you no go manage any account at all:

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

At start, systemd dey allocate unused user ID; at stop, e dey release am. Di service go also get private /tmp, wey be read-only view of most of di filesystem, and writable state directory under /var/lib/myapp wey StateDirectory= dey set up and hand to am. For self-contained service wey only need im own state directory, DynamicUser=yes na di easiest way to get strong isolation, because no long-lived account for attacker to target at all.

To write units by hand fit hard, and to get di hardening directives correct na di real value. Di generator for the systemd service and timer guide fit fill these options for you so di unit go correct di first time.

How this fits with di rest

Least privilege na one layer, and e dey work with di others instead of to replace dem. A default-deny firewall dey control wetin fit reach di service; running am as unprivileged user dey control wetin di service fit do if e get breach; and hardened SSH dey keep attackers off di box from di start. No single one of dem dey enough, and together dem mean say bug for one service no go turn to compromise for di whole server.

Before you move on, check di hardening checklist for di whole box and generate personalized copy to work from:

ToolVPS hardening checklist

FAQ

Why I no suppose run a service as root?

Because root fit do anything for di machine, so if service wey run as root get exploit, e go hand di attacker di whole server, no be just di service. Running di service as limited, unprivileged account go lock di damage inside wetin dat account fit access. Reserve root for administration, and run every long-running service as restricted user.

How I take create user wey no fit log in?

Run sudo useradd --system --no-create-home --shell /usr/sbin/nologin NAME. Di nologin shell mean say di account no fit open interactive session even if dem steal im credentials, --system mark am as service account, and --no-create-home skip di home directory wey e no need. Give am ownership of only im own files with chown.

Wetin be systemd DynamicUser?

DynamicUser=yes tell systemd to create temporary user for di service wey dey exist only while e dey run, so you no go need manage long-lived account. E also give di service private /tmp, wey be mostly read-only filesystem view, and managed state directory. Na di easiest way to run self-contained service under throwaway, low-privilege identity.

Running as non-root user dey replace firewall?

No. Dem dey protect different things. Running as unprivileged user dey limit wetin service fit do if e get breach, while firewall dey limit wetin fit reach di service at all. Use both, along with hardened SSH, so each layer go cover wetin di others no fit cover.

Which files di service user suppose own?

Only di files wey di service actually need, and nothing more. Give di account ownership of im own working directory and im data, and leave everything else owned by root. Good pattern na sudo chown -R svc-app:svc-app /opt/svc-app for di application directory, while configuration under /etc go stay owned by root and e go only be readable by di service. Di goal na say if di process ever get compromise, di files e fit change go limited to im own data, no be di rest of di system.

#security#least-privilege#systemd#users#hardening#linux