How To

Install Nginx on Ubuntu 26.04 LTS with Let’s Encrypt SSL

Nginx 1.28 on Ubuntu 26.04 ships with HTTP/3 compiled in, OpenSSL 3.5, and a dedicated UFW profile for QUIC traffic. The package structure is simpler too: just nginx and nginx-common, no more choosing between nginx-full and nginx-core.

Original content from computingforgeeks.com - post 165868

This guide covers installing Nginx, setting up virtual hosts, configuring UFW, and securing everything with a free Let’s Encrypt certificate using Certbot 4.0. All commands tested on a live Ubuntu 26.04 server. For context on what’s changed in the base OS, see the Ubuntu 26.04 LTS new features overview.

Verified working: April 2026 on Ubuntu 26.04 LTS (Resolute Raccoon), Nginx 1.28.3, Certbot 4.0.0, OpenSSL 3.5.5

Prerequisites

  • Ubuntu 26.04 LTS server with a public IP (or a private IP behind a reverse proxy). Nginx is also available on other platforms, including Nginx on Void Linux
  • A registered domain name pointing to your server’s IP address
  • A user with sudo privileges

For the Let’s Encrypt section, you’ll need a real domain. We use app.example.com as a placeholder throughout the guide.

Install Nginx

Nginx 1.28.3 is available in Ubuntu 26.04’s main repository:

sudo apt update
sudo apt install -y nginx

That’s it. Two packages (nginx and nginx-common), about 652 KB to download. The service starts automatically.

Confirm the version:

nginx -v

Ubuntu 26.04 ships Nginx 1.28:

nginx version: nginx/1.28.3 (Ubuntu)

Check that the service is running:

sudo systemctl status nginx

The service starts automatically after install:

● nginx.service - A high performance web server and a reverse proxy server
     Loaded: loaded (/usr/lib/systemd/system/nginx.service; enabled; preset: enabled)
     Active: active (running)
   Main PID: 21027 (nginx)
      Tasks: 5 (limit: 3519)
     Memory: 4.4M

Nginx starts 4 worker processes (matching the CPU core count) with the new worker_cpu_affinity auto setting that pins each worker to a core.

Test the Default Page

Verify Nginx is serving traffic:

curl -sI http://localhost

Nginx returns a 200:

HTTP/1.1 200 OK
Server: nginx/1.28.3 (Ubuntu)
Content-Type: text/html
Content-Length: 615

If you open your server’s IP in a browser, you’ll see the Nginx welcome page. The 26.04 default page now includes color-scheme: light dark for dark mode support in browsers.

Nginx default welcome page on Ubuntu 26.04
Nginx 1.28.3 default welcome page on Ubuntu 26.04

The default page confirms Nginx is serving traffic. Now let’s look at the config structure before creating virtual hosts.

Nginx Configuration Layout

Ubuntu keeps Nginx configs in the standard Debian layout:

PathPurpose
/etc/nginx/nginx.confMain config (workers, gzip, SSL defaults)
/etc/nginx/sites-available/Virtual host configs (one file per site)
/etc/nginx/sites-enabled/Symlinks to active sites
/etc/nginx/conf.d/Additional global config snippets
/etc/nginx/snippets/Reusable config fragments
/var/log/nginx/Access and error logs
/var/www/html/Default document root

Create a Virtual Host

Create the document root for your site:

sudo mkdir -p /var/www/app.example.com/html

Add a test page:

echo '<html><body><h1>app.example.com</h1><p>Running on Nginx 1.28.3, Ubuntu 26.04</p></body></html>' | sudo tee /var/www/app.example.com/html/index.html

Create the virtual host configuration:

sudo vi /etc/nginx/sites-available/app.example.com

Add the following server block:

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

    server_name app.example.com;

    root /var/www/app.example.com/html;
    index index.html;

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

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

Enable the site by creating a symlink:

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

Test the configuration for syntax errors:

sudo nginx -t

No syntax errors:

nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

Reload Nginx to apply:

sudo systemctl reload nginx

The virtual host is live. Now open the firewall to allow web traffic.

Configure UFW Firewall

Ubuntu 26.04 includes UFW app profiles for Nginx. Check what’s available:

sudo ufw app list

The QUIC profile is new for Ubuntu 26.04:

Available applications:
  Nginx Full
  Nginx HTTP
  Nginx HTTPS
  Nginx QUIC
  OpenSSH

The Nginx QUIC profile is new for Ubuntu 26.04, reflecting HTTP/3 support in this build. For a standard web server setup, allow both HTTP and HTTPS along with SSH:

sudo ufw allow 'Nginx Full'
sudo ufw allow OpenSSH
sudo ufw --force enable

Verify the rules:

sudo ufw status

Both HTTP and HTTPS are allowed:

Status: active

To                         Action      From
--                         ------      ----
80,443/tcp (Nginx Full)    ALLOW IN    Anywhere
22/tcp (OpenSSH)           ALLOW IN    Anywhere
80,443/tcp (Nginx Full (v6)) ALLOW IN    Anywhere (v6)
22/tcp (OpenSSH (v6))      ALLOW IN    Anywhere (v6)

For a more detailed reference on UFW rules, see our UFW firewall commands guide.

Secure with Let’s Encrypt SSL

Ubuntu 26.04 ships Certbot 4.0 with the Nginx plugin. Install both:

sudo apt install -y certbot python3-certbot-nginx

Certbot 4.0 automatically creates a systemd timer for certificate renewal on install. Verify it’s active:

sudo systemctl list-timers | grep certbot

Request a certificate for your domain. Certbot’s Nginx plugin handles the configuration changes automatically:

sudo certbot --nginx -d app.example.com --non-interactive --agree-tos -m [email protected]

Certbot will:

  • Verify domain ownership via HTTP-01 challenge
  • Obtain the certificate from Let’s Encrypt
  • Modify your Nginx vhost to add SSL listeners on port 443
  • Add an HTTP to HTTPS redirect

After Certbot finishes, your site will be accessible at https://app.example.com with a valid certificate.

Test that automatic renewal works:

sudo certbot renew --dry-run

If the dry run passes, your certificates will renew automatically before they expire. For a deeper dive into Certbot configuration across different web servers, see our Let’s Encrypt SSL certificate guide.

Enable HTTP/2

Nginx 1.28 on Ubuntu 26.04 has HTTP/2 support compiled in but it’s only active on SSL listeners. After Certbot adds your SSL configuration, verify that the listen 443 ssl directive is present:

grep -E 'listen.*443' /etc/nginx/sites-enabled/app.example.com

In Nginx 1.28, HTTP/2 is enabled by default when SSL is configured. You no longer need to add http2 to the listen directive manually (that syntax was deprecated in Nginx 1.25.1). If you want to explicitly control it, add this inside your server block:

http2 on;

HTTP/2 is handled. The next step is tuning Nginx for production traffic.

Production Tuning

The default nginx.conf on Ubuntu 26.04 is reasonable, but a few tweaks help on production servers. Our Nginx vs Apache vs Caddy performance benchmark shows where Nginx gains the most from tuning. Edit the main config:

sudo vi /etc/nginx/nginx.conf

Key settings to adjust:

# Increase connections per worker (default is 768)
events {
    worker_connections 2048;
    multi_accept on;
}

http {
    # Hide server version from responses
    server_tokens off;

    # Expand gzip to cover more content types
    gzip on;
    gzip_vary on;
    gzip_proxied any;
    gzip_comp_level 4;
    gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript image/svg+xml;

    # Client body and timeouts
    client_max_body_size 64m;
    client_body_timeout 12;
    client_header_timeout 12;
    send_timeout 10;
    keepalive_timeout 65;

    # Security headers (add to http block or individual server blocks)
    add_header X-Frame-Options "SAMEORIGIN" always;
    add_header X-Content-Type-Options "nosniff" always;
    add_header Referrer-Policy "strict-origin-when-cross-origin" always;
}

Test and reload:

sudo nginx -t && sudo systemctl reload nginx

Nginx picks up the tuning changes on reload without dropping active connections.

Nginx as a Reverse Proxy

When running application servers (Node.js, Python, Go) behind Nginx, configure a reverse proxy block. Here’s a typical setup for an app running on port 3000:

sudo vi /etc/nginx/sites-available/app.example.com

Replace the static file serving with a proxy pass:

server {
    listen 80;
    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;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
}

The Upgrade and Connection headers enable WebSocket proxying, which many modern frameworks need. A common use case for this pattern is running WordPress with Nginx on Ubuntu as a high-performance frontend.

sudo nginx -t && sudo systemctl reload nginx

That covers both static file serving and reverse proxy configurations. Here are the commands you’ll use most often.

Useful Nginx Commands

CommandWhat it does
sudo nginx -tTest config syntax without reloading
sudo systemctl reload nginxApply config changes (zero-downtime)
sudo systemctl restart nginxFull restart (brief downtime)
sudo nginx -TDump the full effective config
tail -f /var/log/nginx/error.logWatch error log in real time
tail -f /var/log/nginx/access.logWatch access log in real time

Does Nginx 1.28 on Ubuntu 26.04 support HTTP/3?

Yes. Nginx 1.28.3 on Ubuntu 26.04 is compiled with --with-http_v3_module and there’s a dedicated Nginx QUIC UFW profile. To enable HTTP/3, add listen 443 quic; alongside your existing SSL listener and open UDP port 443 with sudo ufw allow 443/udp.

What TLS versions does Nginx use by default on Ubuntu 26.04?

The default nginx.conf sets ssl_protocols TLSv1.2 TLSv1.3; with ssl_prefer_server_ciphers off;. TLS 1.0 and 1.1 are disabled out of the box. This matches current security best practices.

How many worker processes should I configure?

The default worker_processes auto; sets one worker per CPU core. For most servers, this is optimal. On a 4-core server, you’ll see 4 worker processes. Each worker handles up to worker_connections simultaneous connections (768 by default, increase to 2048+ for busy sites).

Related Articles

Databases How To Install MongoDB 5 on Ubuntu 22.04|20.04|18.04 Ubuntu Install Jira on Ubuntu 24.04 / Rocky Linux 10 Desktop How To Install Firefox Browser on Ubuntu 22.04|20.04 Email Install Zimbra Zextras Carbonio CE on Ubuntu 20.04

Leave a Comment

Press ESC to close