All guides
VPS
18 min read

Connect a Domain and HTTPS to a VPS

Point DNS, configure an Nginx virtual host or reverse proxy, issue a Let's Encrypt certificate, and verify renewal without hiding common failure modes.

Published August 3, 2026 Updated August 9, 2026 Reviewed by Victus Cloud

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

Typical records
NameTypeValueUse
@A203.0.113.10Apex domain to public IPv4
wwwCNAMEexample.comwww follows the apex
@AAAAYour configured IPv6Add only when end-to-end IPv6 works
appA/AAAA or CNAMEChosen targetOptional 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.

Query public DNS from a client with dig installedbash
dig +short A example.com
dig +short AAAA example.com
dig +short CNAME www.example.com

Query 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

Ubuntu package and firewall setupbash
sudo apt update
sudo apt install nginx
sudo ufw allow 'Nginx Full'
sudo nginx -t
systemctl status nginx --no-pager

If 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.

/etc/nginx/sites-available/example.com for static contentnginx
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;
    }
}
Enable and validatebash
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 nginx

Create 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.

Replace the static location when proxying a local appnginx
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

Certbot with Ubuntu packagesbash
sudo apt install certbot python3-certbot-nginx
sudo certbot --nginx -d example.com -d www.example.com

Certbot'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

End-to-end checksbash
curl -I http://example.com
curl -I https://example.com
sudo certbot certificates
sudo certbot renew --dry-run
systemctl list-timers | grep certbot

Expect 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

Common failures
FailureCheckLikely correction
Domain does not resolveAuthoritative nameservers and A/AAAA answerEdit the delegated zone; wait according to prior TTL
Connection timed outPublic IP, route, host/provider firewallsOpen intended ports or correct address
Default Nginx pageHost header, enabled server block, server_nameEnable correct block and reload after nginx -t
502 Bad GatewayLocal app status, bind address, port, Nginx error logStart/fix app or correct proxy_pass
Certificate validation failsDNS, CAA, port 80, proxy/CDN behaviorMake requested names directly reachable or use DNS-01
HTTPS works for apex but not wwwDNS and certificate SAN listPoint 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.

References

Frequently asked questions

Why does Certbot HTTP validation fail?

The requested hostname must resolve publicly to the VPS and port 80 must reach the validation server block. Also check CAA records, IPv6, and any DNS proxy.

Should I create an AAAA record for my VPS?

Only if IPv6 is configured and reachable end to end. A broken AAAA record can make the site fail for clients that prefer IPv6.

Related guides