Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

nginx Setup

Overview

nginx (pronounced “engine-x”) is a web server that can serve static files and act as a reverse proxy for backend applications. In a typical setup:

Internet
    │
    ▼
┌─────────────────────────────┐
│         nginx               │
│                             │
│  :80 (HTTP) ──► redirect    │
│  :443 (HTTPS) ──┬──► static files (/var/www/)
│                 └──► proxy to localhost:3000
└─────────────────────────────┘

nginx handles:

  • SSL/TLS termination (HTTPS)
  • Serving static files efficiently
  • Proxying requests to backend applications
  • Load balancing (if needed)

Prerequisites

  • VPS setup completed (see VPS Setup)
  • UFW configured (see UFW Setup)
  • Domain name pointed to your VPS IP (optional, but required for SSL)

Installation

Update package list and install nginx:

sudo apt update
sudo apt install -y nginx

Check the installed version:

nginx -v

Enable nginx to start on boot and start it now:

sudo systemctl enable nginx
sudo systemctl start nginx

Verify it’s running:

sudo systemctl status nginx

Firewall Rules

nginx needs ports 80 (HTTP) and 443 (HTTPS) open. Allow both with a single command (see UFW Setup for details):

sudo ufw allow 'Nginx Full'

Test Installation

Open your browser and visit:

http://<vps-ip>

You should see the default nginx welcome page. This confirms nginx is installed and the firewall is configured correctly.

Important Directories

nginx organizes configuration files in a specific structure:

PathDescription
/etc/nginx/nginx.confMain configuration file (rarely edited directly)
/etc/nginx/sites-available/Store all site configurations here
/etc/nginx/sites-enabled/Symlinks to enabled sites (nginx only reads this)
/var/www/Default location for website files
/var/log/nginx/Access and error logs

The sites-available/sites-enabled pattern lets you easily enable or disable sites without deleting configurations.

Server Block (Virtual Host)

A server block defines how nginx handles requests for a specific domain. Each domain gets its own configuration file.

Create a Configuration File

sudo vim /etc/nginx/sites-available/<domain>

Static Site Configuration

For serving HTML, CSS, and JavaScript files:

server {
    listen 80;
    listen [::]:80;

    server_name <domain>;

    root /var/www/<domain>;
    index index.html;

    location / {
        try_files $uri $uri/ =404;
    }

    access_log /var/log/nginx/<domain>.access.log;
    error_log /var/log/nginx/<domain>.error.log;
}
DirectivePurpose
listen 80Accept HTTP connections on port 80
listen [::]:80Same for IPv6
server_nameThe domain this block responds to
rootDirectory containing website files
indexDefault file to serve for directory requests
try_filesTry the URI as a file, then as a directory, then return 404

Create Web Root and Test Page

Create the directory for your website files:

sudo mkdir -p /var/www/<domain>
sudo chown -R $USER:$USER /var/www/<domain>

Create a simple test page:

echo "<h1>Welcome to <domain></h1>" > /var/www/<domain>/index.html

Enable the Site

Create a symlink from sites-available to sites-enabled:

sudo ln -s /etc/nginx/sites-available/<domain> /etc/nginx/sites-enabled/

Test the configuration for syntax errors:

sudo nginx -t

If the test passes, reload nginx to apply changes:

sudo systemctl reload nginx

Visit http://<domain> to see your test page.

Reverse Proxy

A reverse proxy forwards requests to a backend application (e.g., Node.js, Python, Go) running on localhost.

Client Request
      │
      ▼
┌─────────────┐     ┌─────────────────┐
│   nginx     │ ──► │  Your App       │
│   :443      │     │  localhost:3000 │
└─────────────┘     └─────────────────┘

Reverse Proxy Configuration

server {
    listen 80;
    server_name <domain>;

    location / {
        proxy_pass http://localhost:3000;
        proxy_http_version 1.1;
        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;
    }
}
DirectivePurpose
proxy_passURL of the backend application
proxy_http_version 1.1Use HTTP/1.1 for upstream connections
Host $hostPass the original Host header to the backend
X-Real-IPPass the client’s real IP address
X-Forwarded-ForChain of proxy IPs
X-Forwarded-ProtoOriginal protocol (http or https)

WebSocket Support

If your backend uses WebSockets (real-time connections), add these headers:

        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_cache_bypass $http_upgrade;

This tells nginx to upgrade the connection from HTTP to WebSocket when requested.

Serving Multiple Applications

You can serve multiple applications under one domain using different location blocks. Each location can serve static files or proxy to different backend applications.

domain.com/     →  /var/www/<domain> (static files)
domain.com/app  →  localhost:3000     (backend app)

Example Configuration

server {
    listen 443 ssl;
    server_name <domain>;
    
    # Main site serves static files
    location / {
        root /var/www/<domain>;
        try_files $uri $uri/ =404;
    }
    
    # App at /app subpath
    location /app {
        proxy_pass http://localhost: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;
    }
}

Trailing Slash in proxy_pass

The trailing slash in proxy_pass changes how nginx forwards requests:

Without trailing slash - preserves the full path:

location /app {
    proxy_pass http://localhost:3000;
}
# Request: domain.com/app/page → Backend receives: /app/page

With trailing slash - strips the location prefix:

location /app {
    proxy_pass http://localhost:3000/;
}
# Request: domain.com/app/page → Backend receives: /page

Use the trailing slash when your backend application serves from root. Without the trailing slash, your application must handle requests with the /app prefix included.

Application Configuration

Your application must be configured to handle its base path. If using the trailing slash in proxy_pass, your app serves from root as normal. Without the trailing slash, configure your app to serve from /app. If routes return 404 or assets fail to load, check this configuration.

Test by visiting https://<domain>/app in your browser.

Common Commands

CommandDescription
sudo nginx -tTest configuration syntax
sudo systemctl reload nginxApply config changes (no downtime)
sudo systemctl restart nginxFull restart
sudo systemctl stop nginxStop nginx
sudo tail -f /var/log/nginx/access.logWatch access logs in real-time
sudo tail -f /var/log/nginx/error.logWatch error logs in real-time

Always run nginx -t before reloading to catch syntax errors.