Why Nginx Returns 403 for a Next.js Site and How to Fix It with SELinux

A developer deployed a Next.js build on a new server using Nginx 1.26, encountered a 403 Forbidden error due to permission and SELinux restrictions, and resolved the issue by adjusting file ownership, permissions, and SELinux context to allow Nginx to serve the static files.

Liangxu Linux
Liangxu Linux
Liangxu Linux
Why Nginx Returns 403 for a Next.js Site and How to Fix It with SELinux

After finishing a weekend project, the author tried to host a Next.js static site on a server that already ran Nginx 1.26. The original Nginx configuration was removed, a new document root was created, and the following minimal server block was added:

server {
    listen       80;
    server_name  xxx.com;
    access_log  /var/log/nginx/host.access.log  main;
    root   /xxx/xxx;
    index  index.html index.htm;
}

After restarting Nginx with systemctl restart nginx, the browser displayed a clear 403 Forbidden page.

Investigation showed the error log contained Permission denied, indicating a file‑system permission problem. The directory was created by the root user, while the Nginx worker processes run as the nginx user, so the worker could not read the files.

Running ps aux | grep nginx confirmed the user under which Nginx runs. The fix was to change ownership and permissions of the document root:

sudo chown -R nginx:nginx /xxx/xxx
sudo chmod -R 755 /xxx/xxx

After applying these commands, ls -l /xxx/xxx showed the expected permissions (e.g., -rw-r--r-- 1 root root 4096 Nov 25 14:00 index.html), but the 403 error persisted.

Root Cause: SELinux Enforcement

Even with correct Unix permissions, SELinux was in Enforcing mode, blocking Nginx from accessing the files. The status can be checked with getenforce, which returns one of three modes: Enforcing, Permissive, or Disabled.

Two remediation paths exist: disable SELinux entirely, or adjust the security context of the web files. Disabling can be done by editing /etc/selinux/config and setting SELINUX=disabled, then rebooting.

To keep SELinux enabled, the appropriate context for web content is httpd_sys_content_t. Applying it to the document root resolves the access denial: chcon -R -t httpd_sys_content_t /xxx/xxx After changing the context and restarting Nginx, the site loads correctly and the 403 error disappears.

Final Thoughts

This case illustrates that when deploying static sites with Nginx, both traditional Unix permissions and SELinux policies must be considered. Checking the Nginx user, setting proper ownership (e.g., nginx:nginx) and permissions (755), and ensuring the correct SELinux context are essential steps for a successful deployment.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

nextjs
Liangxu Linux
Written by

Liangxu Linux

Liangxu, a self‑taught IT professional now working as a Linux development engineer at a Fortune 500 multinational, shares extensive Linux knowledge—fundamentals, applications, tools, plus Git, databases, Raspberry Pi, etc. (Reply “Linux” to receive essential resources.)

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.