Why trust this guide
By Victus Cloud · Reviewed by Victus Cloud · No individual author claimed. Verify paths, versions, and backups before changing a live service.
Evidence-led, product-agnostic
Understand the request path before changing DNS
A browser resolves your domain through DNS to an IP address, connects to port 80 or 443, negotiates TLS for HTTPS, and sends an HTTP request whose host name lets the web server choose a site. For a reverse proxy, Nginx terminates TLS and forwards the request to an application listening on a private local port. Each layer can fail independently, so test them in order rather than repeatedly changing all of them.
Verify the current Victus service
Public IP assignment, IPv6, network-firewall controls, PTR records, managed DNS, and panel installers vary by product and plan. Confirm the current panel and plan. This guide assumes a self-managed Ubuntu VPS with sudo access; it does not imply that Victus manages your web server or certificate.
Collect prerequisites and keep a rollback note
- A domain you control and access to its authoritative DNS provider.
- The VPS public IPv4 address and, only if configured and reachable, its IPv6 address.
- A supported Ubuntu release, sudo access, current patches, and a working SSH recovery path.
- An application already tested locally on the VPS, or static files ready to serve.
- Ports 80 and 443 permitted by host and provider firewalls and not occupied unexpectedly.
- A maintenance plan if the domain currently serves production traffic elsewhere.
Use example values as placeholders. example.com and 203.0.113.10 are reserved for documentation; substitute your domain and real address. If migrating a live site, lower DNS TTL well before the move, keep the old service available during propagation, and copy data before switching. DNS changes are cached according to prior TTLs and recursive resolver behavior; ‘propagation’ is not a single global timer.
1. Publish only the DNS records your VPS can answer
| Name | Type | Value | Use |
|---|---|---|---|
| @ | A | 203.0.113.10 | Apex domain to public IPv4 |
| www | CNAME | example.com | www follows the apex |
| @ | AAAA | Your configured IPv6 | Add only when end-to-end IPv6 works |
| app | A/AAAA or CNAME | Chosen target | Optional application subdomain |
Do not add an AAAA record merely because a field exists. Many clients prefer IPv6; a broken IPv6 route can make the site appear intermittently unavailable. Preserve unrelated MX, TXT, CAA, DKIM, and verification records. A DNS proxy/CDN changes where clients connect and may alter certificate validation and source addresses; start with direct DNS unless you understand and intend that layer.
dig +short A example.com
dig +short AAAA example.com
dig +short CNAME www.example.comQuery the authoritative name servers if normal answers are stale, and check that you edited the zone actually delegated by the registrar. If CAA records exist, they must authorize your chosen certificate authority. DNSSEC failures can produce SERVFAIL; do not disable DNSSEC casually—correct the delegation and signatures with your DNS provider.
2. Install Nginx and create a specific server block
sudo apt update
sudo apt install nginx
sudo ufw allow 'Nginx Full'
sudo nginx -t
systemctl status nginx --no-pagerIf UFW is not in use, do not enable it remotely without first allowing SSH. If a provider firewall exists for your plan, open TCP 80 and 443 there too. Check sudo ss -lntp when another process occupies a port. Do not solve a bind conflict by killing an unknown production process; identify the service and choose an intentional architecture.
server {
listen 80;
listen [::]:80;
server_name example.com www.example.com;
root /var/www/example.com/html;
index index.html;
location / {
try_files $uri $uri/ =404;
}
}sudo mkdir -p /var/www/example.com/html
sudo ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/example.com
sudo nginx -t
sudo systemctl reload nginxCreate files with appropriate ownership rather than making the web root world-writable. Remove the default site only when you know no other service needs it. Validate with curl -I http://example.com and inspect Nginx access/error logs. An HTTP response from the wrong site usually means the request reached Nginx but no server_name matched or an unexpected default server handled it.
3. Reverse-proxy an application safely
Bind the application to loopback when only Nginx should reach it. Confirm curl http://127.0.0.1:3000 works on the VPS before adding the proxy. The application should have its own unprivileged service user and a supervised service manager. Do not expose the application port publicly as a workaround for an Nginx error.
location / {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
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;
}Applications differ: WebSockets, streaming, large uploads, timeouts, trusted-proxy settings, and path prefixes may need explicit configuration. Do not blindly add permissive CORS headers or trust every forwarded header. Nginx overwrites the headers above, but the application must be configured to trust only the intended proxy path. Run sudo nginx -t before every reload.
4. Issue the certificate only after HTTP works
sudo apt install certbot python3-certbot-nginx
sudo certbot --nginx -d example.com -d www.example.comCertbot's HTTP-01 validation requires public DNS to point to this VPS and port 80 to reach it. Every requested name must resolve correctly. Read the proposed Nginx changes and use a real monitored contact address. If port 80 cannot be exposed or a wildcard certificate is required, use a supported DNS-01 plugin or another deliberate ACME client workflow; do not paste broad DNS API credentials into shell history.
5. Verify HTTPS, redirects, and renewal
curl -I http://example.com
curl -I https://example.com
sudo certbot certificates
sudo certbot renew --dry-run
systemctl list-timers | grep certbotExpect HTTP either to serve intentionally or redirect to HTTPS, and HTTPS to return the correct application. Inspect the certificate names and expiry in a browser or with an independent TLS tool. A successful dry run checks the renewal path at that moment; continue monitoring renewal failures and certificate age. Keep port 80 available if HTTP-01 renewal depends on it. Do not add HSTS until HTTPS is stable for every required subdomain because cached HSTS can make rollback harder.
Troubleshoot by layer
| Failure | Check | Likely correction |
|---|---|---|
| Domain does not resolve | Authoritative nameservers and A/AAAA answer | Edit the delegated zone; wait according to prior TTL |
| Connection timed out | Public IP, route, host/provider firewalls | Open intended ports or correct address |
| Default Nginx page | Host header, enabled server block, server_name | Enable correct block and reload after nginx -t |
| 502 Bad Gateway | Local app status, bind address, port, Nginx error log | Start/fix app or correct proxy_pass |
| Certificate validation fails | DNS, CAA, port 80, proxy/CDN behavior | Make requested names directly reachable or use DNS-01 |
| HTTPS works for apex but not www | DNS and certificate SAN list | Point and request every intended hostname |
Use logs around the exact timestamp: journalctl -u nginx, /var/log/nginx/error.log, application logs, and Certbot logs. Redact cookies, authorization headers, query secrets, IP addresses where required, and private keys before sharing. Never upload /etc/letsencrypt/live/.../privkey.pem to support or a public issue.
Operate the site after launch
Monitor DNS resolution, HTTP status, application health, disk space, Nginx and application service state, certificate expiry, renewals, and backups. Apply Ubuntu, Nginx, runtime, and application updates through a tested process. Back up application data and configuration independently; a certificate can be reissued, but customer data may be irreplaceable. Document registrar, DNS provider, records, certificate method, application port, service unit, and rollback.
If the site is moving from another host, compare both origins directly before the switch, preserve the old service until caches age out, and avoid database writes to two independent copies. Plan a final synchronization or read-only window. DNS plus TLS is not a one-click guarantee; following the layers produces a setup you can explain and recover.