How to Install and Configure Nginx on Ubuntu VPS (Step-by-Step)

How to Install and Configure Nginx on Ubuntu VPS (Step-by-Step)

Nginx is the world’s most popular web server β€” powering over 34% of all active websites as of 2025. It’s fast, lightweight, handles massive concurrent connections with minimal memory, and doubles as a reverse proxy, load balancer, and HTTP cache. If you’re running an Ubuntu VPS, Nginx is almost certainly the right web server for you.

This guide covers everything from a fresh Nginx installation to production-ready configuration: server blocks, SSL certificates, Gzip compression, security headers, rate limiting, and performance tuning. By the end, your VPS will be serving web traffic the right way.

Nginx vs Apache: Why Choose Nginx in 2025?

If you’ve used shared hosting before, you’ve probably encountered Apache. Here’s why most VPS users choose Nginx instead:

Nginx Apache
Architecture Event-driven, asynchronous Process/thread per request
Concurrent connections Handles thousands easily Memory grows with connections
Static file serving ⚑ Very fast Slower
Memory usage Low Higher
Config syntax Clean, block-based .htaccess (per-directory)
Reverse proxy Built-in, excellent Requires extra modules
Best for High-traffic sites, APIs, proxying Shared hosting, .htaccess flexibility

The bottom line: on a VPS where every MB of RAM counts, Nginx’s efficiency gives you far more headroom than Apache.

Requirements

  • Ubuntu VPS running 22.04 LTS or 24.04 LTS
  • Root or sudo access via SSH
  • A domain name (optional but recommended for SSL setup)
  • Basic Linux command line knowledge

πŸ’‘ VPS.DO Tip: All VPS.DO Ubuntu VPS plans ship with KVM virtualization and full root access, making them ideal for a clean Nginx setup from scratch. View Ubuntu VPS Plans β†’


Step 1: Update Your Ubuntu VPS

Always start with a fully updated system before installing new software:

sudo apt update && sudo apt upgrade -y

Step 2: Install Nginx

Nginx is available in Ubuntu’s default repositories. Install it with a single command:

sudo apt install nginx -y

Start the service and enable it to launch automatically on reboot:

sudo systemctl start nginx
sudo systemctl enable nginx

Confirm it’s running:

sudo systemctl status nginx

You should see Active: active (running). Open your browser and visit your VPS IP address β€” you’ll see the default Nginx welcome page confirming everything is working.

Step 3: Configure the Firewall

Allow web traffic through UFW:

sudo ufw allow 'Nginx Full'
sudo ufw allow OpenSSH
sudo ufw enable
sudo ufw status

Nginx Full opens both port 80 (HTTP) and port 443 (HTTPS). You can also use Nginx HTTP or Nginx HTTPS individually if needed.


Understanding the Nginx Directory Structure

Before making changes, it helps to understand how Nginx organizes its files on Ubuntu:

Path Purpose
/etc/nginx/nginx.conf Main configuration file β€” global settings
/etc/nginx/sites-available/ All server block configs (active or not)
/etc/nginx/sites-enabled/ Symlinks to active configs
/etc/nginx/snippets/ Reusable config fragments
/var/www/html/ Default web root
/var/log/nginx/ Access and error logs

The best practice is to create individual config files in sites-available/ and activate them with symlinks to sites-enabled/. Never edit the default config directly for production sites.


Step 4: Create Your First Server Block

Let’s set up Nginx to serve a website for yourdomain.com. First, create the web root:

sudo mkdir -p /var/www/yourdomain.com/html
sudo chown -R $USER:$USER /var/www/yourdomain.com/html
sudo chmod -R 755 /var/www/yourdomain.com

Create a test page:

nano /var/www/yourdomain.com/html/index.html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Welcome to yourdomain.com</title>
</head>
<body>
  <h1>Nginx is working on VPS.DO!</h1>
</body>
</html>

Now create the server block config:

sudo nano /etc/nginx/sites-available/yourdomain.com
server {
    listen 80;
    listen [::]:80;

    server_name yourdomain.com www.yourdomain.com;
    root /var/www/yourdomain.com/html;
    index index.html index.htm index.php;

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

    access_log /var/log/nginx/yourdomain.com.access.log;
    error_log  /var/log/nginx/yourdomain.com.error.log;
}

Enable the site and test:

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

Visit http://yourdomain.com and your page should load. βœ…


Step 5: Add Free SSL with Let’s Encrypt

HTTPS is mandatory in 2025 β€” for security, SEO rankings, and user trust. Certbot makes it free and automatic:

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

Certbot will automatically modify your Nginx config to add HTTPS and set up HTTP-to-HTTPS redirects. Test auto-renewal:

sudo certbot renew --dry-run

Your site is now accessible over HTTPS with a 90-day auto-renewing certificate. βœ…


Step 6: Performance Tuning β€” Nginx Global Settings

The default Nginx configuration is conservative. For a production VPS, optimize the main config file:

sudo nano /etc/nginx/nginx.conf

Key settings to tune in the http block:

http {
    ##
    # Basic Settings
    ##
    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    keepalive_timeout 65;
    types_hash_max_size 2048;
    server_tokens off;  # Hide Nginx version for security

    ##
    # Gzip Compression
    ##
    gzip on;
    gzip_vary on;
    gzip_proxied any;
    gzip_comp_level 6;
    gzip_types text/plain text/css text/xml application/json
               application/javascript application/rss+xml
               application/atom+xml image/svg+xml;

    ##
    # Buffer sizes
    ##
    client_body_buffer_size      128k;
    client_max_body_size         10m;
    client_header_buffer_size    1k;
    large_client_header_buffers  4 4k;
    output_buffers               1 32k;
    postpone_output              1460;

    ##
    # Timeouts
    ##
    client_header_timeout  3m;
    client_body_timeout    3m;
    send_timeout           3m;
}

Test and reload after every change:

sudo nginx -t && sudo systemctl reload nginx

Step 7: Security Headers

Add HTTP security headers to protect your visitors and improve security scores. Add these inside your server block (or in a shared snippet):

server {
    # ... existing config ...

    # Security headers
    add_header X-Frame-Options "SAMEORIGIN" always;
    add_header X-XSS-Protection "1; mode=block" always;
    add_header X-Content-Type-Options "nosniff" always;
    add_header Referrer-Policy "no-referrer-when-downgrade" always;
    add_header Content-Security-Policy "default-src 'self' http: https: data: blob: 'unsafe-inline'" always;
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
}

You can verify your security headers at securityheaders.com after applying these changes.


Step 8: Rate Limiting

Rate limiting protects your server from abuse, brute-force attacks, and DDoS attempts. Add this to your http block in nginx.conf:

# Define a rate limit zone (10 requests per second per IP)
limit_req_zone $binary_remote_addr zone=general:10m rate=10r/s;

Then apply it in your server block:

location / {
    limit_req zone=general burst=20 nodelay;
    try_files $uri $uri/ =404;
}

For login pages, use a stricter limit:

location /wp-login.php {
    limit_req zone=general burst=5 nodelay;
    include snippets/fastcgi-php.conf;
    fastcgi_pass unix:/var/run/php/php8.3-fpm.sock;
}

Step 9: Static File Caching

Tell browsers to cache static assets (images, CSS, JavaScript) locally to reduce server load and speed up repeat visits:

location ~* \.(jpg|jpeg|png|gif|ico|css|js|woff2|svg|ttf)$ {
    expires 30d;
    add_header Cache-Control "public, no-transform";
    access_log off;
}

Step 10: Nginx as a Reverse Proxy

One of Nginx’s most powerful use cases is acting as a reverse proxy β€” sitting in front of a backend application (Node.js, Python, PHP-FPM, etc.) and forwarding requests to it. This lets you run multiple apps on different ports behind a single public IP:

server {
    listen 80;
    server_name app.yourdomain.com;

    location / {
        proxy_pass http://127.0.0.1:3000;  # Your Node.js app port
        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;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_cache_bypass $http_upgrade;
    }
}

This pattern is used for Node.js apps, Python (Gunicorn/uvicorn), Ruby (Puma), and any other HTTP server running on a local port.


Step 11: WordPress-Optimized Nginx Config

If you’re running WordPress, use this production-ready server block:

server {
    listen 443 ssl http2;
    server_name yourdomain.com www.yourdomain.com;
    root /var/www/yourdomain.com/html;
    index index.php index.html;

    # SSL (managed by Certbot)
    ssl_certificate /etc/letsencrypt/live/yourdomain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/yourdomain.com/privkey.pem;
    include /etc/letsencrypt/options-ssl-nginx.conf;

    # Security
    server_tokens off;
    add_header X-Frame-Options SAMEORIGIN;
    add_header X-Content-Type-Options nosniff;

    # WordPress permalinks
    location / {
        try_files $uri $uri/ /index.php?$args;
    }

    # PHP processing
    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/var/run/php/php8.3-fpm.sock;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
    }

    # Deny access to sensitive files
    location ~ /\.(ht|git) {
        deny all;
    }

    # Static file caching
    location ~* \.(css|gif|ico|jpeg|jpg|js|png|woff2)$ {
        expires max;
        log_not_found off;
    }

    # Block xmlrpc.php abuse
    location = /xmlrpc.php {
        deny all;
    }

    access_log /var/log/nginx/yourdomain.com.access.log;
    error_log  /var/log/nginx/yourdomain.com.error.log;
}

Useful Nginx Commands Reference

Command Action
sudo nginx -t Test config for syntax errors
sudo systemctl reload nginx Reload config without downtime
sudo systemctl restart nginx Full restart (brief downtime)
sudo systemctl stop nginx Stop Nginx
sudo nginx -v Show Nginx version
sudo tail -f /var/log/nginx/error.log Watch error log in real time
sudo tail -f /var/log/nginx/access.log Watch access log in real time

Troubleshooting Common Nginx Issues

502 Bad Gateway

This means Nginx can’t reach the backend. Check that PHP-FPM (or your app server) is running and that the socket path in your config matches the actual socket file:

sudo systemctl status php8.3-fpm
ls /var/run/php/

403 Forbidden

Usually a permissions issue. The Nginx process (running as www-data) needs read access to your web root:

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

Config changes not taking effect

Make sure you ran sudo nginx -t (no errors) and then sudo systemctl reload nginx. Also clear your browser cache or test with curl:

curl -I http://yourdomain.com

Nginx won’t start β€” port already in use

Something else is listening on port 80 or 443. Find and stop it:

sudo lsof -i :80
sudo systemctl stop apache2  # If Apache is the culprit

Final Thoughts

Nginx is the backbone of modern web infrastructure, and for good reason β€” it’s fast, efficient, and incredibly flexible. With the configuration patterns in this guide, your Ubuntu VPS is now ready to serve static sites, WordPress installations, Node.js apps, and anything else you throw at it, all with HTTPS, security headers, and performance tuning in place.

The best part? All of this runs comfortably on VPS.DO’s entry-level plans. A $20/month Ubuntu VPS with 2 vCPU, 4 GB RAM, and a 1 Gbps port can handle thousands of concurrent Nginx connections without breaking a sweat.

Need help configuring Nginx for a specific use case? VPS.DO’s technical support team is available 24/7. Submit a ticket β†’


Related articles you might find useful:

Fast β€’ Reliable β€’ Affordable VPS - DO It Now!

Get top VPS hosting with VPS.DO’s fast, low-cost plans. Try risk-free with our 7-day no-questions-asked refund and start today!