1. What Nginx Does

Nginx is a web server and reverse proxy.

Common roles:

  • Serve static files: HTML, CSS, JS, images

  • Reverse proxy to apps: Go, Node.js, PHP, Python, ttyd, code-server

  • Handle HTTPS/TLS certificates

  • Route many domains on one server

  • Add authentication, caching, compression, and headers

Typical flow:

Browser
  ↓ HTTPS
Nginx
  ↓ proxy_pass / static file / FastCGI
Application or files

2. Install Nginx

On Ubuntu/Debian:

sudo apt update
sudo apt install nginx

Check status:

systemctl status nginx

Enable on boot:

sudo systemctl enable nginx

Start / restart / reload:

sudo systemctl start nginx
sudo systemctl restart nginx
sudo systemctl reload nginx

Use reload when only the configuration changed. It is safer than a restart.


3. Main File Structure

Common Ubuntu layout:

/etc/nginx/
├── nginx.conf
├── sites-available/
│   └── example.com
├── sites-enabled/
│   └── example.com -> ../sites-available/example.com
├── conf.d/
└── snippets/

Important paths:

/var/www/html              default web root
/var/log/nginx/access.log  access log
/var/log/nginx/error.log   error log
/etc/nginx/nginx.conf      main config

4. Basic Static Website

Create directory:

sudo mkdir -p /srv/www/example
sudo nano /srv/www/example/index.html

Example config:

server {
    listen 80;
    server_name example.com www.example.com;
 
    root /srv/www/example;
    index index.html;
 
    location / {
        try_files $uri $uri/ =404;
    }
}

Enable it:

sudo ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx

5. Reverse Proxy Example

For an app running on port 3000:

server {
    listen 80;
    server_name app.example.com;
 
    location / {
        proxy_pass http://127.0.0.1:3000;
 
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

This means:

User visits app.example.com
Nginx receives request
Nginx forwards request to localhost:3000
App responds
Nginx sends response back to user

6. HTTPS with Certbot

Install Certbot:

sudo apt install certbot python3-certbot-nginx

Request certificate:

sudo certbot --nginx -d example.com -d www.example.com

Test renewal:

sudo certbot renew --dry-run

Certbot usually edits the Nginx config automatically.


7. Useful Commands

Test config:

sudo nginx -t

Reload config:

sudo systemctl reload nginx

Show active config:

sudo nginx -T

Watch logs:

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

Check listening ports:

sudo ss -tulpn | grep nginx

8. Basic Security

Hide unused default site:

sudo rm /etc/nginx/sites-enabled/default

Use firewall:

sudo ufw allow 'Nginx Full'
sudo ufw enable

For basic authentication:

sudo apt install apache2-utils
sudo htpasswd -c /etc/nginx/.htpasswd username

Nginx config:

location / {
    auth_basic "Restricted";
    auth_basic_user_file /etc/nginx/.htpasswd;
 
    proxy_pass http://127.0.0.1:3000;
}

9. How Nginx Works Internally

Nginx has a master process and worker processes.

Master process
  ├── reads config
  ├── opens ports
  ├── manages workers
  └── reloads config gracefully
 
Worker processes
  ├── accept client connections
  ├── read requests
  ├── serve files or proxy requests
  └── write responses

Nginx is event-driven.

Instead of creating one thread per connection, each worker handles many connections using an event loop.

Simplified:

Worker waits for events:
- new connection
- data available
- upstream response ready
- client ready to receive data

This is why Nginx handles many simultaneous connections efficiently.


10. Request Processing Flow

Example request:

GET https://notes.example.com/page

Nginx roughly does:

1. Accept TCP connection
2. Handle TLS if HTTPS
3. Read HTTP request
4. Choose matching server block by server_name
5. Choose matching location block
6. Serve file or proxy to backend
7. Send response
8. Keep connection alive or close it

11. Server Block Matching

Nginx chooses a server block based on:

server_name
listen port

Example:

server {
    listen 80;
    server_name notes.example.com;
}

If no exact match is found, Nginx uses the default server for that port.


12. Location Matching

Common location types:

location / {
}

Matches everything.

location /api/ {
}

Matches paths starting with /api/.

location = /exact {
}

Matches exact path only.

location ~ \.php$ {
}

Regex match.


13. Static File vs Reverse Proxy

Static website:

root /srv/www/site;
 
location / {
    try_files $uri $uri/ =404;
}

Reverse proxy:

location / {
    proxy_pass http://127.0.0.1:3000;
}

PHP site:

location ~ \.php$ {
    include snippets/fastcgi-php.conf;
    fastcgi_pass unix:/run/php/php8.3-fpm.sock;
}

14. Important Concepts

root

Maps URL path to filesystem path.

root /srv/www/site;

Request:

/about.html

File:

/srv/www/site/about.html

try_files

Tries files in order.

try_files $uri $uri/ /index.html;

Useful for single-page apps.

proxy_pass

Forwards request to another service.

proxy_pass http://127.0.0.1:8080;

upstream

Defines backend group.

upstream myapp {
    server 127.0.0.1:3000;
    server 127.0.0.1:3001;
}
 
server {
    location / {
        proxy_pass http://myapp;
    }
}

15. Mental Model

Think of Nginx as a traffic controller.

Domain name decides server block.
URL path decides location block.
Location decides action:
- serve file
- proxy to app
- pass to PHP-FPM
- reject
- redirect
- require password

For personal servers:

One VPS
One public IP
Many domains
Nginx routes each domain to the right app or folder

Example:

notes.example.com → static Quartz files
lab.example.com   → ttyd service
root.example.com  → admin ttyd service
intro.example.com → static Hugo site

16. Troubleshooting Checklist

When Nginx does not work:

  1. Check DNS points to the server.

  2. Check firewall allows port 80/443.

  3. Check Nginx is running.

  4. Run sudo nginx -t.

  5. Check correct server_name.

  6. Check config is enabled in sites-enabled.

  7. Check backend app is running.

  8. Check logs.

Useful commands:

curl -I http://example.com
curl -I https://example.com
sudo nginx -t
sudo systemctl status nginx
sudo journalctl -u nginx -xe
sudo tail -f /var/log/nginx/error.log

17. Key Takeaway

Nginx is not just a web server.

It is the front door of the server.

It receives public traffic, decides where each request should go, protects services, handles HTTPS, and lets many apps share one machine cleanly.