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.
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/xxxAfter 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.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
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.)
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
