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