maxuru ~ % cat haproxy/run-as-non-root
Run HAProxy as a non-root user
/etc/haproxy/haproxy.cfgglobal user haproxy group haproxy chroot /var/lib/haproxyMost distribution packages set these already. The job here is usually to confirm it rather than to change it.
Why it matters
Section titled “Why it matters”HAProxy starts as root because it has two things to do that require it: bind
ports below 1024, and read TLS private keys that should not be readable by
anyone else. Having done both, it drops privileges — the process that then spends
its life parsing untrusted bytes off the network runs as haproxy, not root.
That split is what makes the parsing bugs survivable. HAProxy’s CVE history is mostly memory-safety and protocol-handling issues in exactly that code path; whether such a bug is a bad day or a total host compromise is decided by which user the worker was running as when it hit.
If user and group are absent, HAProxy keeps root for the whole process
lifetime. The config is valid and the service works, so nothing draws attention
to it.
chroot
Section titled “chroot”chroot confines the worker to a directory after privileges are dropped, so a
process that gets hijacked cannot see the filesystem. HAProxy’s documentation is
explicit that the jail must be empty and non-writable by anyone — an empty
directory is the whole point, since there is nothing inside it to abuse.
sudo mkdir -p /var/lib/haproxysudo chown root:root /var/lib/haproxysudo chmod 755 /var/lib/haproxyOwned by root and empty. Do not put the socket, certificates or logs inside it; HAProxy opens all of those before it chroots, so they belong in their normal locations.
Keys and permissions
Section titled “Keys and permissions”Because the key is read before the drop, the private key does not need to be
readable by the haproxy user — and should not be:
sudo chown root:root /etc/haproxy/certs/site.pemsudo chmod 400 /etc/haproxy/certs/site.pemThis is the same two-process reasoning as Apache and nginx: the privileged parent reads the secret at startup so the unprivileged worker never holds it.
Related
Section titled “Related”- Configure TLS on HAProxy — the key the parent reads at startup.
- Protect the runtime API socket — which user should own it.