How to Run Apache as a Non-Root User

Running the Apache HTTP Server as a non-root user is a critical security best practice that minimizes the potential damage of a server compromise. This article provides a quick overview of why this configuration matters and walks you through the step-by-step process of modifying the Apache configuration files, adjusting file permissions, and managing privileged ports so your web server can operate safely with reduced privileges.

Why Run Apache as a Non-Root User?

By default, the Apache parent process often starts as root so it can bind to privileged ports like 80 (HTTP) and 443 (HTTPS). However, if an attacker exploits a vulnerability in a server running entirely as root, they gain full administrative control over the entire system. Configuring Apache to run its worker processes—or the entire service—under a dedicated, unprivileged user account restricts an attacker’s access strictly to the web server’s isolated environment.

Step 1: Create a Dedicated User and Group

Before changing the configuration, you need a dedicated, non-privileged system user and group for Apache if they do not already exist.

sudo groupadd www-data
sudo useradd -g www-data -s /bin/false -d /var/www www-data

Setting the shell to /bin/false ensures that no one can log into the system directly using this account, adding an extra layer of security.

Step 2: Modify the Apache Configuration File

Next, you need to instruct Apache to use the new user and group. Open your Apache configuration file (usually httpd.conf or apache2.conf located in /etc/httpd/conf/ or /etc/apache2/).

Look for the User and Group directives and update them:

User www-data
Group www-data

Step 3: Adjust File and Directory Permissions

The new non-root user must have permission to read the website files and write to specific logging or cache directories, but it should not own the root configuration files.

Directory/File Path Required Permission Purpose
/var/www/html Read & Execute (rx) Allows Apache to serve web content
/var/log/apache2 or /var/log/httpd Read & Write (rwx) Allows Apache to write error and access logs
/etc/apache2 or /etc/httpd Read-Only to root Prevents the non-root user from modifying server configs

Set the ownership of your web root directory using the following commands:

sudo chown -R root:www-data /var/www/html
sudo chmod -R 755 /var/www/html

Step 4: Handle Privileged Port Restrictions (Optional)

Linux kernels prevent non-root users from binding to ports below 1024. If you plan to start the master Apache process completely as a non-root user (rather than starting as root and dropping privileges to www-data), you have two main options to use ports 80 and 443:

  1. Use setcap (Recommended): Grant the Apache binary specific permission to bind to privileged ports without running as root.
sudo setcap 'cap_net_bind_service=+ep' /usr/sbin/apache2
  1. Port Forwarding: Configure Apache to listen on a non-privileged port like 8080, and use a firewall rule (like iptables or ufw) to redirect incoming traffic from port 80 to 8080.

Step 5: Test and Restart Apache

Always test your configuration for syntax errors before restarting the service to avoid unexpected downtime.

sudo apachectl configtest

If the output reads Syntax OK, restart the Apache service to apply the changes:

sudo systemctl restart apache2

You can verify that the worker processes are running under the unprivileged user by executing ps aux | grep apache2 or ps aux | grep httpd in your terminal.