Nginx Setup and Troubleshooting Reference
Table of Contents
- Initial Setup Goal
- Configuration Files
- Creating a Main Personal Webpage
- Certbot SSL for a New Domain
- Simple HTML Content Example
- Troubleshooting 404 and Permission Errors
- Logs and Error Diagnosis
- Permission Denied (13) Issue
- Root Directory Permissions
- Why It Worked After Adjusting Permissions
Initial Setup Goal
User:
I’m using my Ubuntu VPS with Nginx and a reverse proxy set up as per these configuration files. I need assistance in creating a main personal webpage accessible via nasserhub.net. I have an application running in the /opt/open-webui folder at https://webui.nasserhub.net/. I want the webpage to be simple, as I plan to add to it later. It should be in a location that is easy for a non-root user to access, develop, and update. Thanks!
Configuration Files
/etc/nginx/nginx.conf
user www-data;
worker_processes auto;
pid /run/nginx.pid;
error_log /var/log/nginx/error.log;
include /etc/nginx/modules-enabled/*.conf;
events {
worker_connections 768;
# multi_accept on;
}
http {
##
# Basic Settings
##
sendfile on;
tcp_nopush on;
types_hash_max_size 2048;
# server_tokens off;
# server_names_hash_bucket_size 64;
# server_name_in_redirect off;
include /etc/nginx/mime.types;
default_type application/octet-stream;
##
# SSL Settings
##
ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
##
# Logging Settings
##
access_log /var/log/nginx/access.log;
##
# Gzip Settings
##
gzip on;
# gzip_vary on;
# gzip_proxied any;
# gzip_comp_level 6;
# gzip_buffers 16 8k;
# gzip_http_version 1.1;
# gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
##
# Virtual Host Configs
##
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
}
/etc/nginx/sites-available/webui.conf
server {
server_name webui.nasserhub.net;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
listen [::]:443 ssl ipv6only=on; # managed by Certbot
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/webui.nasserhub.net/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/webui.nasserhub.net/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}
server {
if ($host = webui.nasserhub.net) {
return 301 https://$host$request_uri;
} # managed by Certbot
listen 80;
listen [::]:80;
server_name webui.nasserhub.net;
return 404; # managed by Certbot
}
We want to add a new site at nasserhub.net
while leaving webui.nasserhub.net
intact.
Creating a Main Personal Webpage
Step-by-Step Guide
-
Create a non-root user (already done, user =
nasser
). -
Create a directory for the website (already done at
/home/nasser/websites/nasserhub.net/public
). -
Set ownership and permissions:
sudo chown -R nasser:www-data /home/nasser/websites/nasserhub.net sudo chmod -R 755 /home/nasser/websites/nasserhub.net
-
Create an Nginx server block for
nasserhub.net
. Example file:
/etc/nginx/sites-available/nasserhub.conf
:server { # Redirect HTTP to HTTPS listen 80; listen [::]:80; server_name nasserhub.net www.nasserhub.net; return 301 https://nasserhub.net$request_uri; } server { listen 443 ssl http2; listen [::]:443 ssl http2; server_name nasserhub.net www.nasserhub.net; # SSL certificate paths (assuming certs are obtained for nasserhub.net) ssl_certificate /etc/letsencrypt/live/nasserhub.net/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/nasserhub.net/privkey.pem; include /etc/letsencrypt/options-ssl-nginx.conf; ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # Root directory for your site root /home/nasser/websites/nasserhub.net/public; index index.html index.htm; location / { try_files $uri $uri/ =404; } }
-
Enable the site:
sudo ln -s /etc/nginx/sites-available/nasserhub.conf /etc/nginx/sites-enabled/nasserhub.conf sudo nginx -t sudo systemctl reload nginx
-
Place or update web files in
/home/nasser/websites/nasserhub.net/public/
.
Certbot SSL for a New Domain
If you only have certificates for webui.nasserhub.net
, you need new ones for nasserhub.net
.
-
Temporary HTTP server block (if needed) for Certbot HTTP challenge:
server { listen 80; listen [::]:80; server_name nasserhub.net www.nasserhub.net; root /home/nasser/websites/nasserhub.net/public; location ~ /.well-known/acme-challenge { allow all; } location / { try_files $uri $uri/ =404; } }
-
Obtain certificate via Certbot:
sudo certbot --nginx -d nasserhub.net -d www.nasserhub.net
or
sudo certbot certonly --webroot \ -w /home/nasser/websites/nasserhub.net/public \ -d nasserhub.net -d www.nasserhub.net
-
Update your
nasserhub.conf
with the correct SSL paths, then reload.
Simple HTML Content Example
To avoid the default 404
page, create a simple index.html
in /home/nasser/websites/nasserhub.net/public
:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Welcome to Nasserhub.net</title>
</head>
<body style="margin: 1rem; font-family: Arial, sans-serif;">
<h1 style="color: #2f4f4f;">I'm Still Alive and Breathing!</h1>
<p>
This page is here to let you know the server is online and working. More content coming soon!
</p>
<hr>
<footer style="font-size: 0.9rem; color: #555;">
© 2025 Nasser Hub
</footer>
</body>
</html>
Troubleshooting 404 and Permission Errors
If you see 404 Not Found
in your browser but you do have an index.html
file, it can be:
- The Nginx config isn’t loaded or symlinked properly.
- The wrong server block is serving the domain (e.g., the default site overshadowing your custom config).
- A permission or ownership issue in the file path.
Logs and Error Diagnosis
Use:
sudo tail -f /var/log/nginx/access.log /var/log/nginx/error.log
- access.log lines show if the request matched a server block and what code was returned (
200 OK
,404
, etc.). - error.log lines show “permission denied” or “no such file/directory” details.
Example:
[crit] 93933#93933: *9054 stat() "/home/nasser/websites/nasserhub.net/public/" failed (13: Permission denied)
means Nginx can’t traverse the directory path.
Permission Denied (13) Issue
If logs say “Permission denied”:
- Check each directory in the path for the execute (x) bit for
www-data
or for “others.” - Example chain:
/home/nasser
→websites
→nasserhub.net
→public
. - Run
ls -ld
on each directory to confirm. For instance, if/home/nasser
isdrwxr-x---
(750), then “others” can’t enter.
Root Directory Permissions
Example:
/home/nasser => drwxr-x---
/home/nasser/websites => drwxrwxr-x
/home/nasser/websites/nasserhub.net => drwxr-xr-x
/home/nasser/websites/nasserhub.net/public => drwxr-xr-x
Nginx (www-data
) can’t read /home/nasser
if it’s drwxr-x---
. Changing it to drwxr-xr-x
(755) fixes that.
sudo chmod 755 /home/nasser
Why It Worked After Adjusting Permissions
By granting “others” execute (and read) permission on /home/nasser
(making it 755
), you allowed the Nginx worker process (running as www-data
) to traverse into the deeper paths (/websites/nasserhub.net/public
) and read index.html
. This removed the “Permission denied” errors, and your site finally returned a 200 OK response.