image

NGINX Configuration Beginner’s Guide

Published : November 4, 2025
Last Updated : November 4, 2025
Published In : Technical Guide

Your website loads slowly. Traffic spikes crash your server. You need a solution that handles thousands of visitors without breaking a sweat.

NGINX solves these problems. It is a high-performance web server that also works as a reverse proxy, load balancer, and HTTP cache. Whether you run a personal blog or a business application, NGINX delivers speed and reliability while using minimal server resources.

This guide teaches you NGINX configuration from scratch. Practical configurations you can use immediately.

What Is NGINX and Why Use It?

NGINX (pronounced engine x) is a web server that handles high traffic efficiently. Unlike traditional servers that create a new thread for each visitor, NGINX uses an event-driven model. One worker process handles multiple connections simultaneously without consuming excessive memory.


Apache creates a separate worker for each visitor. With 10,000 visitors, you need 10,000 workers. NGINX uses a handful of workers that juggle all connections. The difference shows in your server bill and site speed.


NGINX does four main jobs. It serves static files like HTML, CSS, images, and JavaScript directly to browsers. It acts as a reverse proxy by forwarding requests to backend applications. It balances traffic across multiple servers to prevent overload. It caches responses to reduce load on your backend systems.


The configuration is straightforward once you understand the basics.

Understanding NGINX Directives

Directives are instructions that tell NGINX what to do. Every directive follows this format:

				
					directive_name value;
				
			

The semicolon is not optional. Forget it, and NGINX refuses to start.

Directives live in different contexts. The main context affects your entire NGINX installation. The HTTP block contains web server settings. Server blocks define individual websites. Location blocks handle specific URL patterns.

More specific directives override general ones. A location directive beats a server directive. This hierarchy lets you set defaults and override them where needed.

				
					http {
    gzip on;
    
    server {
        listen 80;
        server_name example.com;
        
        location /api/ {
            gzip off;
        }
    }
}

				
			

Here, gzip is enabled globally but disabled for /api/ URLs. Location overrides HTTP.

Configuration File Hierarchy

NGINX organizes configuration in a clear hierarchy. Understanding this structure prevents conflicts.


The main context sits at the top. Define the user NGINX runs as, worker processes, and error logging here.

				
					user www-data;
worker_processes auto;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;

				
			

The worker_processes auto directive creates one worker per CPU core.

The events block controls connection handling.

				
					events {
    worker_connections 1024;
}

				
			

Each worker process handles 1,024 simultaneous connections. On a four-core server with auto workers, you handle 4,096 concurrent visitors.

The HTTP block contains all web server configuration.

				
					http {
    include /etc/nginx/mime.types;
    default_type application/octet-stream;
    
    server {
        listen 80;
        server_name example.com;
        
        location / {
            root /var/www/html;
        }
    }
}

				
			

Server blocks define virtual hosts. Location blocks handle specific URI patterns within a website.

Split configuration across files for easier management.

				
					http {
    include /etc/nginx/conf.d/*.conf;
    include /etc/nginx/sites-enabled/*;
}

				
			

This keeps each site in its own file. Enable or disable sites without editing the main configuration.

 

HTTP Block Essentials

The HTTP block holds global settings that apply to all websites unless overridden in server blocks.

Start with performance settings.

				
					http {
    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    keepalive_timeout 65;
    types_hash_max_size 2048;
}

				
			

The sendfile directive uses your kernel to send files directly, improving performance.

Enable compression to reduce bandwidth.

				
					http {
    gzip on;
    gzip_vary on;
    gzip_comp_level 6;
    gzip_types text/plain text/css text/xml text/javascript 
               application/json application/javascript application/xml+rss;
}

				
			

Level 6 balances CPU usage and compression. Do not compress already compressed files like images, videos, or PDFs.

Add security headers.

				
					http {
    server_tokens off;
    add_header X-Frame-Options "SAMEORIGIN" always;
    add_header X-Content-Type-Options "nosniff" always;
    add_header X-XSS-Protection "1; mode=block" always;
}

				
			

The server_tokens directive hides your NGINX version number from error pages and headers.

Server Blocks and Domain Configuration

Server blocks define how NGINX handles different domains. Each server block configures one website.

Here is a basic HTTP server.

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

				
			

The listen directive specifies the port. Double colon syntax enables IPv6. Production servers should handle both IPv4 and IPv6.

For production, use HTTPS with HTTP/2.

				
					server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name example.com www.example.com;
    
    ssl_certificate /etc/nginx/ssl/example.com.crt;
    ssl_certificate_key /etc/nginx/ssl/example.com.key;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_session_cache shared:SSL:50m;
    add_header Strict-Transport-Security "max-age=31536000" always;
    
    root /var/www/example.com;
    index index.html;
}

				
			

HTTP/2 allows multiplexing multiple requests over a single connection. The ssl_certificate should include your certificate chain. The Strict-Transport-Security header tells browsers to always use HTTPS for one year.

Redirect HTTP to HTTPS automatically.

				
					server {
    listen 80;
    listen [::]:80;
    server_name example.com www.example.com;
    return 301 https://$server_name$request_uri;
}

				
			

The 301 status code indicates a permanent redirect.

Canonicalize your domain. Choose www or non-www, then redirect the other.

				
					server {
    listen 443 ssl http2;
    server_name www.example.com;
    return 301 https://example.com$request_uri;
}

				
			

To redirect non-www to www instead, reverse the server_name values.

The server_name directive accepts multiple domains separated by spaces. Wildcards work at the start or end.

				
					server_name *.example.com;
				
			

This matches any subdomain like blog.example.com or api.example.com.

When multiple server blocks could match a request, NGINX follows priority. Exact matches win, then longest wildcard, then first matching regular expression.

Make sure your firewall allows traffic.

				
					sudo ufw allow 80/tcp
sudo ufw allow 443/tcp

				
			

Without open ports, visitors cannot reach your site.

Location Blocks for Path Management

Location blocks define how NGINX handles specific URIs. NGINX processes location blocks in priority order.

Exact matches come first.

				
					location = /favicon.ico {
    access_log off;
    log_not_found off;
}

				
			

This matches only /favicon.ico exactly. It is the fastest match type.

Prefix matches without modifiers come next.

				
					location /images/ {
    root /var/www/static;
    expires 30d;
}

				
			

This matches any URI starting with /images/.

Priority prefix matches stop further searching.

				
					location ^~ /api/ {
    proxy_pass http://backend_api;
}

				
			

If this prefix matches, NGINX skips regex checking.

Case sensitive regex matches use tilde.

				
					location ~ \.php$ {
    fastcgi_pass unix:/var/run/php-fpm.sock;
    include fastcgi_params;
}

				
			

Case insensitive regex uses tilde asterisk.

				
					location ~* \.(jpg|jpeg|png|gif|ico|svg)$ {
    expires 1y;
    add_header Cache-Control "public, immutable";
}

				
			

Understanding root versus alias matters. With root, the location path gets appended.

				
					location /static/ {
    root /var/www/data;
}

				
			

A request to /static/style.css looks for /var/www/data/static/style.css.

With an alias, the location path gets replaced.

				
					location /static/ {
    alias /var/www/files/;
}

				
			

A request to /static/style.css looks for /var/www/files/style.css. Notice the trailing slash.

The try_files directive checks files in order.

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

				
			

First tries the exact URI as a file, then as a directory, then returns 404.

 

Reverse Proxy Basics

NGINX excels at forwarding requests to backend applications. Define backend servers in an upstream block.

				
					upstream backend_app {
    server 192.168.1.10:3000;
}

server {
    listen 80;
    server_name example.com;
    
    location / {
        proxy_pass http://backend_app;
        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;
    }
}

				
			

The proxy_pass directive sends requests to your backend. Setting headers ensures the backend receives correct client information.

For load balancing across multiple servers, list them all.

				
					upstream backend_app {
    server 192.168.1.10:3000;
    server 192.168.1.11:3000;
    server 192.168.1.12:3000;
}


				
			

NGINX distributes requests evenly using round robin. Add health checks so NGINX stops routing to failed servers.

				
					upstream backend_app {
    server 192.168.1.10:3000 max_fails=3 fail_timeout=30s;
}

				
			

After three failed attempts, NGINX marks the server down for 30 seconds.

 

Testing and Troubleshooting

When things go wrong, check logs first. Error log lives at /var/log/nginx/error.log. Access log is at /var/log/nginx/access.log.

Always test configuration before reloading.

				
					sudo nginx -t
				
			

This validates syntax and configuration. Fix any errors before proceeding.

Reload configuration without dropping connections.

				
					sudo nginx -s reload
				
			

NGINX starts new workers with updated configuration, then gracefully shuts down old workers.

Check which version you run.

				
					nginx -v
				
			

For compile options and modules, use capital V.

				
					nginx -V

				
			

If changes do not take effect, verify you edited the correct file and reloaded NGINX. Check for syntax errors. Look for conflicting directives in different files.

If you get 413 Request Entity Too Large errors, increase the limit.

				
					client_max_body_size 50M;
				
			

If you see client IPs as 127.0.0.1 behind a load balancer, configure the real IP module.

				
					set_real_ip_from 192.168.1.0/24;
real_ip_header X-Forwarded-For;

				
			

Quick Start on Your Server

Installing NGINX on Ubuntu or Debian is straightforward.

				
					sudo apt update
sudo apt install nginx

				
			

Start NGINX and enable it to run on boot.

				
					sudo systemctl start nginx
sudo systemctl enable nginx

				
			

Verify NGINX runs.

				
					sudo systemctl status nginx
				
			

The default configuration serves a welcome page. Visit your server IP to confirm.

Create a basic configuration for your site in /etc/nginx/sites-available/yourdomain.com.

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

				
			

Enable the site by creating a symbolic link to sites-enabled. This links your configuration file without copying it.

				
					sudo ln -s /etc/nginx/sites-available/yourdomain.com /etc/nginx/sites-enabled/

				
			

Test and reload.

				
					 sudo mkdir -p /opt/bitwarden/backups
sudo chown bitwarden:bitwarden /opt/bitwarden/backups

				
			

For HTTPS, use Let’s Encrypt with Certbot for free SSL certificates.

				
					sudo apt install certbot python3-certbot-nginx
sudo certbot --nginx -d yourdomain.com

				
			

Certbot automatically configures NGINX for HTTPS and sets up certificate renewal.


Common Troubleshooting Scenarios

NGINX fails to start after a configuration change

Run nginx -t to identify the syntax error. The output shows the file and line number. Common causes include missing semicolons, unclosed braces, or invalid directive names.

				
					sudo nginx -t
				
			

# nginx: [emerg] unexpected “}” in /etc/nginx/sites-enabled/example.com:15

The error points to line 15. Check for missing semicolons on previous lines.

Port 80 or 443 already in use

Another process occupies the port. Find what is using it:

				
					sudo lsof -i :80
sudo lsof -i :443

				
			

Common culprits include Apache running alongside NGINX. Stop the conflicting service or change NGINX to listen on different ports.

Permission denied errors

NGINX cannot access files or directories. Check file permissions:

				
					ls -la /var/www/example.com
				
			

NGINX runs as the www-data user by default. Ensure www-data can read files and access directories:

				
					sudo chown -R www-data:www-data /var/www/example.com
sudo chmod -R 755 /var/www/example.com

				
			

SSL certificate errors

Certificate path incorrect or certificate expired. Verify certificate files exist:

				
					sudo ls -la /etc/nginx/ssl/

				
			

Check certificate expiration:

				
					sudo openssl x509 -in /etc/nginx/ssl/example.com.crt -noout -dates

				
			

For Let’s Encrypt certificates, check Certbot logs:

				
					sudo tail -f /var/log/letsencrypt/letsencrypt.log
				
			

502 Bad Gateway with upstream services

Backend application not running or unreachable. Verify backend listens on the configured port:

				
					sudo netstat -tlnp | grep 3000
				
			

Check application logs for errors. Verify that the proxy_pass URL matches the backend address and port exactly.

Test backend connectivity:

				
					curl http://localhost:3000

				
			

504 Gateway Timeout

Backend responds too slowly. Increase proxy timeouts:

				
					location / {
    proxy_pass http://backend;
    proxy_connect_timeout 60s;
    proxy_send_timeout 60s;
    proxy_read_timeout 60s;
}

				
			

Investigate why the backend is slow. Check backend application logs and server resources.

Worker process crashes

Check error logs for segmentation faults or core dumps:

				
					sudo tail -100 /var/log/nginx/error.log

				
			

Common causes include third-party modules with bugs, insufficient system resources, or corrupted configurations. Disable recently added modules to isolate the issue.

High memory usage

Check worker process memory:

				
					ps aux | grep nginx
				
			

Large SSL session caches consume memory. Reduce cache size:

				
					ssl_session_cache shared:SSL:10m;
				
			

Reduce worker_connections if memory is constrained:

				
					events {
    worker_connections 512;
}

				
			

Logs not rotating

Log files grow too large. Verify logrotate configuration:

				
					sudo cat /etc/logrotate.d/nginx
				
			

Manually rotate logs:

				
					sudo logrotate -f /etc/logrotate.d/nginx
				
			

DNS resolution fails for upstream servers

NGINX cannot resolve backend hostnames. Add resolver directive:

				
					resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;

				
			

Or use IP addresses in upstream blocks instead of hostnames.


Cannot bind to privileged port (below 1024)

NGINX must run as root to bind to ports 80 and 443. Check NGINX starts with sudo or as a system service. The master process runs as root, worker processes run as www-data.

Verify systemd service configuration:

				
					sudo systemctl cat nginx

				
			

Common Questions

 

How do I host multiple websites on one server?

Create a server block for each domain in /etc/nginx/sites-available/. Give each its own server_name and root directory. Enable them by symlinking to sites-enabled and reload.

 

How do I improve page load speed?

Enable gzip compression in your HTTP block. Set cache headers for static assets using expires directives. Use sendfile for efficient file serving. For caching, use proxy_cache_path to define cache storage and proxy_cache in location blocks to reduce backend load. Consider a CDN for global delivery.

 

What should I do if NGINX will not start?

Run nginx -t to check for configuration errors. The output shows the file and line number of any issues. Review error logs at /var/log/nginx/error.log for specific messages. Common causes include port conflicts, missing SSL certificates, syntax errors like missing semicolons, or permission issues. Access logs are in /var/log/nginx/access.log. Use tail -f to watch logs in real time.

 

How do I reload NGINX without downtime?

Run sudo nginx -s reload. NGINX starts new workers with updated configuration while old workers finish serving current requests.

 

How do I test my SSL configuration?

Visit ssllabs.com/ssltest and enter your domain. Aim for an A or A+ rating. The test identifies weak ciphers, protocol issues, and certificate problems.

 

Why do my static files return 404 errors?

Check your root or alias paths for typos. Verify files exist in the specified directory. Ensure NGINX has read permissions on files and execute permissions on directories. The www-data user must be able to read your files.


About the Author Peter French is the Managing Director at Virtarix, with over 17 years in the tech industry. He has co-founded a cloud storage business, led strategy at a global cloud computing leader, and driven market growth in cybersecurity and data protection.

Other posts

image
November 4, 2025
Published in : Technical Guide
NGINX Configuration Beginner’s Guide

Learn to configure NGINX from scratch. This guide explains directives, server blocks & practical setups to speed up your website & improve server performance.

image
October 31, 2025
Published in : Technical Guide
Self-Hosted Email Server: Complete Setup and Management Guide

Learn to set up and manage your own secure, GDPR-compliant email server with Mailcow, Postfix, and Dovecot. Full control, privacy, and deliverability.

image
October 28, 2025
Published in : Technical Guide
Linux Command Line: Tips and Tricks

Unlock the power of the Linux command line with this guide. Learn essential commands for navigation, file management, system monitoring, and troubleshooting.

Listed on WHTop.com Listed on WHTop.com

© 2025 : Virtarix. All Rights Reserved