← Back to technical notes

Servers & networking / 2026-07-22

From DNS to HTTPS: Deploying a Verifiable Nginx Site on Ubuntu 24.04

Connect DNS, IPv4/IPv6, Nginx, TLS and external validation across one complete request path—and preserve a clear rollback when a layer fails.

Tested environmentUbuntu 24.04 · Nginx 1.28.0
Last verified2026-07-22
DifficultyIntermediate
RiskMedium
Technical environments change. Check versions, back up data and prepare a rollback for live services before following any procedure.

The goal and the request path

An HTTPS request crosses DNS, the client network, IPv4 or IPv6 routing, firewalls, the Nginx listener, certificate selection and finally the site files. A break at any layer may look like the same generic browser failure.

The goal here is to make every layer independently verifiable. Change one variable at a time; changing DNS, firewall rules and Nginx together makes the result difficult to explain or reproduce.

Pre-deployment checks

Record the current state before touching a live host:

bash
ip -brief address
ss -lntp
nginx -T

Confirm that:

  • you control the domain;
  • the server has usable public IPv4 and IPv6 addresses, or a planned reverse-proxy entry point;
  • TCP 80 and 443 are allowed through the host firewall, cloud security rules and upstream routing;
  • the current Nginx configuration is backed up and restorable.

A successful request from the server itself does not prove public reachability. Include an external network, such as mobile data, in the final test.

Configure DNS

Use an A record for IPv4 and an AAAA record for IPv6. Publish AAAA only when the complete IPv6 path works; a broken IPv6 path may be preferred by some clients.

After propagation, inspect both answers:

bash
dig A yaang.cloud +short
dig AAAA yaang.cloud +short

DNS proves only where the name points. It does not prove that a port is open or that Nginx is serving the intended virtual host.

Create a minimal HTTP site

Prepare an isolated document root. The deployment account owns the files while Nginx only needs read access:

bash
sudo install -d -m 0755 /var/www/yaang/current

Start with a minimal server block:

nginx
server {
    listen 80;
    listen [::]:80;
    server_name yaang.cloud www.yaang.cloud;

    root /var/www/yaang/current;
    index index.html;

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

Test before reloading:

bash
sudo nginx -t
sudo systemctl reload nginx

If the syntax test fails, do not force a restart. You can validate the virtual host locally before DNS is ready by supplying its Host header:

bash
curl -I -H 'Host: yaang.cloud' http://127.0.0.1/

Add TLS and HTTPS

The certificate must cover every public hostname. Let an automated ACME client manage renewal, and never place a private key inside the document root or source repository.

The essential HTTPS structure is:

nginx
server {
    listen 443 ssl;
    listen [::]:443 ssl;
    http2 on;
    server_name yaang.cloud www.yaang.cloud;

    root /var/www/yaang/current;
    index index.html;

    ssl_certificate     /path/to/fullchain.pem;
    ssl_certificate_key /path/to/private-key.pem;

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

server {
    listen 80;
    listen [::]:80;
    server_name yaang.cloud www.yaang.cloud;
    return 308 https://$host$request_uri;
}

Run nginx -t again and reload only after it passes. Exercise the certificate renewal process once so you know the renewed certificate can be loaded safely.

Validate each layer

Test IPv4, IPv6, response headers and certificate selection separately:

bash
curl -4 -I https://yaang.cloud/
curl -6 -I https://yaang.cloud/
openssl s_client -connect yaang.cloud:443 -servername yaang.cloud </dev/null

From an external network, verify that:

  • HTTP redirects to HTTPS as intended;
  • the certificate hostname, lifetime and chain are correct;
  • IPv4 and IPv6 return the same site;
  • a missing path returns 404 instead of another virtual host;
  • access and error logs show no unexpected failures.

Common breakpoints

DNS is correct but the connection times out: inspect cloud rules, the host firewall, upstream port forwarding and provider restrictions.

IPv4 works but IPv6 fails: inspect the AAAA record, host address, default route, firewall and the [::]:443 listener.

The wrong site appears: inspect server_name, configuration order and the default virtual host—not only the document files.

The certificate does not match: verify the requested hostname, certificate SAN entries and the certificate path selected by that server block.

Rollback

Keep the previous site directory, previous Nginx configuration, certificate paths and an archived nginx -T output. Restore the last known configuration, run nginx -t, then reload. For a content-only failure, switch current back to the previous static release.

The finish line is not “configuration written.” It is a reproducible result for every path and a known way back to the state before the change.