Skip to content

Running Nginx as Non-Root User

A guide to replace system nginx with a user-level nginx instance, without sudo for daily operations.

1. Allow nginx to bind to privileged ports (80/443)

Terminal window
sudo setcap 'cap_net_bind_service=+ep' /usr/bin/nginx

Verify: getcap /usr/bin/nginx


2. Give user access to Let’s Encrypt certs

Terminal window
sudo setfacl -m u:$USER:rx /etc/letsencrypt/
sudo setfacl -m u:$USER:rx /etc/letsencrypt/live/
sudo setfacl -m u:$USER:rx /etc/letsencrypt/archive/
sudo setfacl -R -m u:$USER:rx /etc/letsencrypt/live/yourdomain.com/
sudo setfacl -R -m u:$USER:rx /etc/letsencrypt/archive/yourdomain.com/

4. Disable system nginx

sudo systemctl stop nginx
sudo systemctl disable nginx

5. Create user systemd service

Terminal window
mkdir -p ~/.config/systemd/user/
nano ~/.config/systemd/user/nginx.service
[Unit]
Description=Nginx HTTP Server
After=network.target
[Service]
Type=forking
PIDFile=/tmp/nginx.pid
ExecStart=/usr/bin/nginx
ExecReload=/usr/bin/nginx -s reload
ExecStop=/usr/bin/nginx -s stop
PrivateTmp=false
[Install]
WantedBy=default.target

Check your nginx path first with which nginx and update accordingly.


6. Enable and start the service

Terminal window
systemctl --user daemon-reload
systemctl --user enable nginx
systemctl --user start nginx
systemctl --user status nginx

7. Allow user services to run without being logged in

Terminal window
sudo loginctl enable-linger $USER

Without this, user services stop when you log out.


Useful commands

Terminal window
# Reload config
systemctl --user reload nginx
# Stop/start
systemctl --user stop nginx
systemctl --user start nginx
# View logs
tail -f /tmp/nginx-error.log
tail -f /tmp/nginx-access.log
# Test config
/usr/bin/nginx -t