NGINX — Web Server & Configuration

35 minLesson 13 of 16

Learning Objectives

  • Install and manage the NGINX service
  • Understand NGINX configuration syntax (directives and contexts)
  • Serve static content and configure virtual hosts
  • Set up dynamic routing with location blocks
  • Configure access and error logging

What is NGINX?

NGINX is a high-performance web server that also functions as a reverse proxy and load balancer. Compared to Apache:

FeatureNGINXApache
ArchitectureEvent-driven, asyncProcess/thread per connection
Static filesExtremely fastGood
Config syntaxClean, compactXML-like
Memory usageLowHigher
Concurrent connectionsExcellentGood

Installation

sudo apt update
sudo apt install nginx -y
 
# Start and enable
sudo systemctl enable nginx
sudo systemctl start nginx
 
# Verify
sudo systemctl status nginx
curl http://localhost

Configuration Structure

NGINX configs live in /etc/nginx/:

/etc/nginx/
├── nginx.conf              # Main config
├── conf.d/                 # Additional configs (auto-loaded)
├── sites-available/        # Virtual host configs
├── sites-enabled/          # Active virtual hosts (symlinks)
├── mime.types              # File type mappings
└── modules-enabled/        # Loaded modules

Configuration Syntax

NGINX uses directives and contexts (blocks):

# Simple directive
worker_processes auto;
 
# Block directive (context)
events {
    worker_connections 768;
}
 
http {
    server {
        listen 80;
        server_name example.com;
 
        location / {
            root /var/www/html;
        }
    }
}

Main Contexts

ContextPurpose
eventsConnection handling settings
httpHTTP server configuration
serverVirtual host definition
locationURL path matching

Serving Static Content

Basic Static Site

# /etc/nginx/conf.d/mysite.conf
server {
    listen 80;
    server_name mysite.example.com;
    root /var/www/mysite;
    index index.html;
 
    location / {
        try_files $uri $uri/ =404;
    }
}

Create the site:

sudo mkdir -p /var/www/mysite
echo "<h1>Welcome to NextGen Playground</h1>" | sudo tee /var/www/mysite/index.html

Validate and Reload

# Always validate before reloading
sudo nginx -t
 
# Reload configuration (no downtime)
sudo nginx -s reload

Virtual Hosts

Host multiple sites on one server:

# Site 1: /etc/nginx/conf.d/app.conf
server {
    listen 80;
    server_name app.nextgenplayground.org;
    root /var/www/app;
}
 
# Site 2: /etc/nginx/conf.d/docs.conf
server {
    listen 80;
    server_name docs.nextgenplayground.org;
    root /var/www/docs;
}

Each domain serves different content from the same server.

Location Blocks

Control how different URLs are handled:

server {
    listen 80;
    server_name mysite.com;
    root /var/www/mysite;
 
    # Exact match
    location = /health {
        return 200 "OK\n";
    }
 
    # Prefix match
    location /api {
        proxy_pass http://localhost:3000;
    }
 
    # Regex match
    location ~* \.(jpg|png|gif|css|js)$ {
        expires 30d;
        access_log off;
    }
 
    # Default fallback
    location / {
        try_files $uri $uri/ /index.html;
    }
}

Match Priority

  1. = /exact — Exact match (highest priority)
  2. ^~ /prefix — Preferential prefix
  3. ~ regex — Case-sensitive regex
  4. ~* regex — Case-insensitive regex
  5. /prefix — Standard prefix (lowest)

NGINX Variables

Built-in variables available in configs:

VariableValue
$hostRequest hostname
$uriRequest URI
$argsQuery string
$remote_addrClient IP
$request_methodGET, POST, etc.
$schemehttp or https
location /debug {
    return 200 "Host: $host\nURI: $uri\nIP: $remote_addr\n";
}

try_files Directive

Check multiple paths before returning an error:

# Try the URI, then as directory, then 404
try_files $uri $uri/ =404;
 
# SPA fallback (React, Vue, Angular)
try_files $uri $uri/ /index.html;
 
# Custom error page
location / {
    try_files $uri $uri/ /not_found;
}
location /not_found {
    return 404 "Page not found\n";
}

Redirects and Rewrites

# Redirect (client sees new URL)
location = /old-page {
    return 301 /new-page;
}
 
# Temporary redirect
location = /maintenance {
    return 307 /coming-soon.html;
}
 
# Rewrite (internal, client doesn't see change)
rewrite ^/blog/(.*)$ /articles/$1 last;

Logging

Access Logs

# Default location
access_log /var/log/nginx/access.log;
 
# Per-site logging
server {
    access_log /var/log/nginx/mysite_access.log;
}
 
# Disable for specific location
location /health {
    access_log off;
    return 200 "OK";
}

Error Logs

# Set minimum level (debug, info, notice, warn, error, crit, alert, emerg)
error_log /var/log/nginx/error.log warn;

Reading Logs

# Follow access log in real-time
sudo tail -f /var/log/nginx/access.log
 
# Search for errors
sudo grep "500" /var/log/nginx/access.log
 
# Count requests by IP
sudo awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head

MIME Types

Include the standard MIME types file:

http {
    include /etc/nginx/mime.types;
    default_type application/octet-stream;
}

Summary

  • NGINX is event-driven, fast, and memory-efficient
  • Config uses directives and contexts (http, server, location)
  • sudo nginx -t validates config; sudo nginx -s reload applies it
  • Virtual hosts serve multiple sites from one server
  • Location blocks match URLs with exact, prefix, or regex patterns
  • try_files checks multiple paths before returning errors
  • Logs go to /var/log/nginx/ — monitor them regularly

Next Steps

Next, we'll configure NGINX as a reverse proxy and load balancer — essential for production architectures.