Running a Web Server binary on TCP:80 without being root…
Hi Ausländer,
A quick post on how to run a simple web server on port TCP:80 using a regular user/group…
I wanted to run a simple yet powerful little Web Server binary and this bound to a regular user/group. Here is the Web Server I wanted to run: https://github.com/mjpclab/go-http-file-server
This is how I’ve solved it. First, we need a systemd service entry:
userland@host:~$ cat /etc/systemd/system/ghfs.service
[Unit]
Description=GHFS Web Server Service
Wants=network.target
After=syslog.target network-online.target
[Service]
ExecStart=/usr/local/bin/ghfs.sh
Restart=on-failure
RestartSec=20
User=ghfs-usr
Group=ghfs-grp
AmbientCapabilities=CAP_NET_BIND_SERVICE
[Install]
WantedBy=multi-user.target
The important directive here being AmbientCapabilities=CAP_NET_BIND_SERVICE in order to give our service process the capability to use ports < 1024, but no other root privileges. After what, we obviously need our ghfs starting /usr/local/bin/ghfs.sh bash script:
userland@host:~$ cat /usr/local/bin/ghfs.sh
#!/bin/bash
echo "Starting the Go Http File Server service"
/usr/local/bin/ghfs -L /var/log/ghfs/ghfs.log -E - -r /var/www/public/ --upload-dir /var/www/public/ --global-delete --global-mkdir --global-archive
Let’s now make sure that our previously created ghfs-usr / ghfs-grp user/group have the correct rights onto our served root directory:
sudo chown -R ghfs-usr:ghfs-grp /var/www/public/
And finally, let’s make sure that our ghfs-usr user has the correct rights to write the requested server log file:
sudo setfacl -R -m u:ghfs-usr:rwX /var/log/ghfs/
A quick verification of our standings:
userland@host:~$
userland@host:~$
userland@host:~$ systemctl status ghfs.service
● ghfs.service - GHFS Web Server Service
Loaded: loaded (/etc/systemd/system/ghfs.service; enabled; preset: enabled)
Active: active (running) since Sun 2025-07-13 20:47:56 CEST; 6min ago
Main PID: 2577315 (ghfs.sh)
Tasks: 10 (limit: 9451)
Memory: 9.5M
CPU: 77ms
CGroup: /system.slice/ghfs.service
├─2577315 /bin/bash /usr/local/bin/ghfs.sh
└─2577316 /usr/local/bin/ghfs -L /var/log/ghfs/ghfs.log -E - -r /var/www/public/ --upload-dir /var/www/public/ --global-delete --global-mkdir --global-archive
userland@host:~$
userland@host:~$
userland@host:~$ ps -aux | grep ghfs
ghfs-usr 2577315 0.0 0.0 6936 3432 ? Ss 20:47 0:00 /bin/bash /usr/local/bin/ghfs.sh
ghfs-usr 2577316 0.0 0.1 1234412 13560 ? Sl 20:47 0:00 /usr/local/bin/ghfs -L /var/log/ghfs/ghfs.log -E - -r /var/www/public/ --upload-dir /var/www/public/ --global-delete --global-mkdir --global-archive
...
userland@host:~$
userland@host:~$
userland@host:~$ sudo ss -ntel | perl -pne 'if(/uid:(\d+)/){@a=getpwuid($1);s/uid:(\d+)/user:$a[0]/}' | grep '*:80'
LISTEN 0 4096 *:80 *:* user:ghfs-usr ino:2547196 sk:8 cgroup:/system.slice/ghfs.service v6only:0 <->
userland@host:~$
userland@host:~$
And that’s it…
Hope this helps.
obruno