
Any process can be run as a non-root user service.
The first criteria to have a service as a non-root user is to have the service be kept running even when the user is not logged in.
However, having a web server places an additional challenge – port 80 and port 443 which are basically the http
and the https
ports need to be bound by a user with administrative privileges because they are lower ports.
1. Keep non-root user service running
For this we use Linux’s loginctl command which is used to control the systemd
login manager.
This is used in with the enable-linger
option. From the page linked above –
When enabled for a specific user, a user manager is spawned for the user at boot and kept around after logouts. This allows users who are not logged in to run long-running services.
The command to be run is –
sudo loginctl enable-linger <user name>
2. Set capability to run on lower ports
To allow caddy to run on port 80 and 443, run the following command –
sudo setcap 'cap_net_bind_service=+ep' /usr/bin/caddy
This is explained in more detail in this answer.
Essentially, we are allowing a program (caddy, in this case), to bind to low-numbered ports via the set capability
command. The setcap
man page is here with the details of the effective (e) and permitted (p) values here.
3. creating a caddy service unit
For non-root users, the service unit files should be in ~/.config/systemd/user
folder. In this case, we create a caddy.service
file under that folder with the following –
# /home/<username>/.config/systemd/user/caddy.service [Unit] Description=Caddy web server (user) After=network.target [Service] ExecStart=/usr/bin/caddy run --config /path/to/caddy_config_file --adapter caddyfile ExecReload=/usr/bin/caddy reload --config /path/to/caddy_config_file --adapter caddyfile Restart=on-failure TimeoutStopSec=5s LimitNOFILE=1048576 [Install] WantedBy=default.target
Before we run this as a service, it’s always a good practice to test the command manually, by running –
/usr/bin/caddy run --config /path/to/caddy_config_file --adapter caddyfile
4. Reload user systemd manager and start the service
If this works and everything looks fine, then we can reload the user systemd manager by
systemctl --user daemon-reload
Enable and start the caddy service
systemctl --user enable caddy
systemctl --user start caddy
Check the status to confirm that everything is running smoothly –
systemctl --user status caddy
Leave a Reply