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.
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:
ip -brief address
ss -lntp
nginx -TConfirm 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:
dig A yaang.cloud +short
dig AAAA yaang.cloud +shortDNS 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:
sudo install -d -m 0755 /var/www/yaang/currentStart with a minimal server block:
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:
sudo nginx -t
sudo systemctl reload nginxIf 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:
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:
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:
curl -4 -I https://yaang.cloud/
curl -6 -I https://yaang.cloud/
openssl s_client -connect yaang.cloud:443 -servername yaang.cloud </dev/nullFrom 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.