Nginx 403 Forbidden Error: Solving Permission Issues When Serving Files from User Home Directory


2 views

After setting up Nginx on Arch Linux with a dedicated nginx user, I encountered a frustrating 403 Forbidden error despite correct file ownership. Here's what the configuration looked like:

# /etc/nginx/nginx.conf
user nginx nginx;

# Virtual host configuration
server {
    location / {
        root /home/lamnk/sites/host.com;
        index index.html;
    }
}

The directory permissions showed:

$ ls -la /home/lamnk/sites/host.com
-rw-r--r-- 1 nginx nginx 21 Jan 12 index.html

The critical insight came when checking parent directory permissions using namei:

$ namei -l /home/lamnk/sites/host.com
drwx------ lamnk users /home/lamnk

Nginx couldn't traverse the home directory because:

  1. The /home/lamnk directory had 700 permissions (drwx------)
  2. Only the owner (lamnk) had execute (x) permission
  3. Nginx worker processes running as nginx user couldn't access the path

Here are three reliable approaches to resolve this:

1. Change Home Directory Permissions (Simple)

chmod 711 /home/lamnk
chmod +x /home/lamnk/sites

2. Move Webroot Outside Home Directory (Recommended)

# Create standard web directory
sudo mkdir -p /srv/http/host.com
sudo chown nginx:nginx /srv/http/host.com

# Update Nginx config
root /srv/http/host.com;

3. ACL-based Solution (Advanced)

setfacl -m u:nginx:x /home/lamnk
setfacl -m u:nginx:rx /home/lamnk/sites
setfacl -R -m u:nginx:r /home/lamnk/sites/host.com

Use this command to test permissions as the nginx user:

sudo -u nginx stat /home/lamnk/sites/host.com/index.html

Check Nginx error logs for confirmation:

tail -f /var/log/nginx/error.log

When dealing with home directory access:

  • Never use 777 permissions
  • Consider creating a dedicated /srv/http structure
  • Regularly audit permissions with namei -l
  • Use ACLs for fine-grained control rather than opening up permissions

Recently while configuring Nginx on Arch Linux, I encountered a puzzling scenario where Nginx couldn't access files despite having matching user ownership. Here's the complete picture:

# Nginx config (/etc/nginx/nginx.conf)
user nginx nginx;

# Directory structure
$ ls -la /home/lamnk/sites/host.com
total 12
drwxr-xr-x 2 lamnk http  4096 Jan 12 09:37 .
drwxr-xr-x 3 lamnk users 4096 Jan 12 09:36 ..
-rw-r--r-- 1 nginx nginx   21 Jan 12 09:37 index.html

The error appeared in Nginx's error log:

2016/01/12 17:28:23 [error] 31914#0: *2 open() "/home/lamnk/sites/host.com/index.html" 
failed (13: Permission denied), client: 171.233.242.40, 
server: host.com, request: "GET /index.html HTTP/1.1", host: "host.com"

The paradox: Nginx runs as user nginx, the file is owned by nginx, yet access is denied.

Examining parent directories revealed the issue:

$ namei -l /home/lamnk/sites/host.com
f: /home/lamnk/sites/host.com
drwxr-xr-x root  root  /
drwxr-xr-x root  root  home
drwx------ lamnk users lamnk
drwxr-xr-x lamnk users sites
drwxr-xr-x lamnk http  host.com

The critical finding: The home directory /home/lamnk has permissions drwx------ (700), meaning only the owner (lamnk) has access.

For Nginx to access a file, it needs:

  1. Execute permission on all parent directories
  2. Read permission on the file itself

Even though the target file is owned by nginx, Nginx can't traverse the path because:

/home/lamnk - 700 (only lamnk can access)
/home/lamnk/sites - 755 (world-executable)
/home/lamnk/sites/host.com - 755 (world-executable)

Option 1: Change home directory permissions

chmod 755 /home/lamnk

This is generally not recommended for security reasons.

Option 2: Move webroot outside home directory

sudo mkdir -p /var/www/host.com
sudo chown -R nginx:nginx /var/www/host.com

Then update Nginx config:

location / {
    root /var/www/host.com;
    index index.html;
}

Option 3: Create a dedicated user group

sudo groupadd webdev
sudo usermod -aG webdev lamnk
sudo usermod -aG webdev nginx
chown -R lamnk:webdev /home/lamnk/sites
chmod -R 750 /home/lamnk/sites

The most maintainable solution is using standard web directories:

# Create proper web directory
sudo mkdir -p /srv/http/host.com
sudo chown -R nginx:nginx /srv/http/host.com
sudo chmod -R 755 /srv/http/host.com

# Alternative for multiple users
sudo mkdir -p /srv/http/host.com
sudo chown -R lamnk:nginx /srv/http/host.com
sudo chmod -R 775 /srv/http/host.com

This follows Linux Filesystem Hierarchy Standard while maintaining security.

Useful commands for diagnosis:

# Check effective permissions
sudo -u nginx ls -l /home/lamnk/sites/host.com

# Test actual access
sudo -u nginx cat /home/lamnk/sites/host.com/index.html

# Verify directory traversal
namei -l /path/to/file