A guide to why Xeams should not run as root on Linux, and how to migrate an existing installation to a dedicated, unprivileged service account.
Older Linux installations of Xeams ran the application as the root user. This was
originally necessary because Xeams' SMTP service listens on privileged ports below 1024
(most notably port 25), and on Linux only root is normally allowed to bind those
ports. Running the entire mail server process as root, however, is more privilege
than the application actually needs, and it carries real risk.
| Benefit | Explanation |
|---|---|
| Reduced blast radius | If Xeams, a library it depends on, or a plugin were ever compromised, the attacker only gains the privileges of the unprivileged service account — not full control of the machine. |
| Principle of least privilege | Xeams only actually needs one narrow capability: the ability to bind ports below
1024. Modern Linux lets you grant exactly that one capability to a process without
granting root, via systemd's AmbientCapabilities. |
| Safer file system access | A non-root Xeams process can only read and write files it has explicitly been given permission to, limiting the damage from bugs, misconfiguration, or malicious email content. |
| Compliance and security audits | Many security review checklists and compliance frameworks flag any long-running network-facing service that executes as root. Running Xeams as a dedicated account removes this finding. |
| Consistent with modern best practice | Nearly every production-grade Linux service (nginx, Postfix, MySQL, PostgreSQL, etc.) runs under its own unprivileged system account. Xeams follows the same model. |
CAP_NET_BIND_SERVICE, the ability to
bind ports below 1024 — without granting full root access. systemd can apply this
capability automatically whenever the service starts, so Xeams keeps the ability to listen on
port 25 while running as an ordinary, unprivileged user for everything else.
systemd
(the default init system on current Ubuntu, RHEL, CentOS, Rocky Linux, Fedora, Debian,
and Linux Mint releases).ntServiceCommand setting in config/AppConfig.xml is
currently blank, it will be set so that Xeams' own "restart myself" feature keeps working
once it is no longer running as root. An existing non-default value is left untouched.sudo) access to run the migration script.Log in to the Xeams server and obtain root privileges:
sudo -i
Download ChangeToNonRoot.sh to the server, then make it executable:
chmod +x ChangeToNonRoot.sh
Run the script:
./ChangeToNonRoot.sh
Read the introductory banner, which explains exactly what the script will and will not do, then confirm to proceed:
Continue? [y/N]: y
Confirm (or change) the existing Xeams installation directory. The default is
/opt/Xeams:
Existing Xeams installation directory [/opt/Xeams]:
Choose the OS user Xeams should run as. The default is xeams, and the
script creates this account for you (with a proper home directory) if it doesn't
already exist:
OS user to run Xeams as [xeams]:
The script then automatically:
systemd unit
and/or /etc/init.d/xeams).systemd service that runs Xeams as that user, granting it
CAP_NET_BIND_SERVICE so it can still bind privileged ports such as SMTP
port 25.sudoers rule so Xeams' built-in restart
feature keeps working under the new account.Uninstall.sh (which only knew how to remove the
root-based service) with one that matches the new non-root setup, preserving the
original as Uninstall.sh.old.Confirm the service is active and running under the new account:
systemctl status xeams.service
Confirm the process itself is owned by the new user, not root:
ps -o user,pid,cmd -C java
Confirm Xeams is still reachable on its usual ports (including SMTP port 25) and that the web interface loads normally.
| Action | Command |
|---|---|
| Start | systemctl start xeams.service |
| Stop | systemctl stop xeams.service |
| Restart | systemctl restart xeams.service |
| Status | systemctl status xeams.service |
| View logs | journalctl -u xeams.service -n 50 |
| Uninstall | /opt/Xeams/Uninstall.sh (path may differ if you installed elsewhere) |
ntServiceCommand
setting may be populated so self-restart keeps working.
systemd service grants the process
CAP_NET_BIND_SERVICE, a targeted Linux capability that allows binding
ports below 1024 without full root privileges.
/opt/Xeams?
/opt/Xeams, but you can point it at any existing installation path.
systemd's AmbientCapabilities to grant
the privileged-port permission. If systemd is not detected, the script
exits without making any changes, and Xeams continues running as it did before.