Skip to content
StealthRDP
VPS Management

How to Point a Domain to Your VPS and Get Free HTTPS

Point a domain to your VPS: add A records, check DNS with dig or nslookup, open ports 80 and 443, then get free HTTPS with Let's Encrypt and Certbot.

Published

9 min readBy StealthRDP Team

This guide shows how to point a domain to your VPS, so that example.com and www.example.com open your site, and how to add HTTPS with a free Let's Encrypt certificate. [1] It is for anyone with a domain and an Ubuntu 24.04 LTS VPS running nginx or Apache, with DNS at the registrar or at Cloudflare. Replace example.com and 203.0.113.10 with your own domain and server address.

What you need before you start

You need four things:

  • Access to the domain's DNS, at the registrar or at Cloudflare if the domain uses Cloudflare's nameservers.
  • SSH access with sudo rights, using an SSH key rather than a root password, as in our SSH hardening checklist.
  • nginx or Apache, installed and running.
  • The server's public IPv4 address, listed with the server's details at your provider. Every StealthRDP Linux VPS has a dedicated IPv4 address.

IPv6 is optional: an AAAA record maps a name to an IPv6 address, so add AAAA records only if the server has one. [2] Still choosing a server? Our guide to sizing a VPS for web hosting helps.

How to point a domain to your VPS with DNS records

To point a domain to your VPS, create A records that map example.com and www.example.com to the server's IPv4 address. [2] Make the change wherever the domain's DNS is hosted.

If the domain already runs a live site or email, note the existing records first. Change only the A, AAAA and CNAME records for @ and www, and leave the rest, such as MX records for email, alone.

1. Add A records for the root domain and www

An A record maps a name to an IPv4 address, and in the name field @ stands for the zone apex, example.com itself. [2]

Type Name Content Proxy status (Cloudflare only)
A @ 203.0.113.10 DNS only, for now
A www 203.0.113.10 DNS only, for now
AAAA @ and www The server's IPv6 address, only if it has one DNS only, for now

Delete any other A or AAAA records on these names, such as a parking page from the registrar.

2. Or point www with a CNAME record

A CNAME record maps a name to another name instead of an address. [2] A CNAME on www that targets example.com follows the root record, so a new server address means editing one record. Use either the A record or the CNAME for www, not both.

On Cloudflare, keep both records on DNS only (grey cloud) until the certificate is issued; the Cloudflare section explains why.

3. Understand TTL before you wait for DNS

TTL (time to live) sets how long DNS resolvers cache an answer before they ask again, so an old answer can linger until its TTL runs out. [2] On Cloudflare, proxied records default to Auto, which is 300 seconds, and DNS-only records use the value you choose. [2] Other providers show their default in the TTL column.

4. Check the records with dig or nslookup

Ask a public resolver, such as Google Public DNS at 8.8.8.8, for both names: use dig on Linux and macOS, and nslookup on Windows. [3]

Linux or macOS
dig -t A example.com @8.8.8.8
dig -t A www.example.com @8.8.8.8
Windows (PowerShell or Command Prompt)
nslookup -type=A example.com 8.8.8.8
nslookup -type=A www.example.com 8.8.8.8

Both names should return 203.0.113.10; ask for AAAA instead of A to check IPv6. If they don't, see the common problems below.

Open ports 80 and 443 with UFW

HTTP normally uses TCP port 80 and HTTPS port 443, and Certbot needs port 80 reachable from the rest of the internet. [4] UFW starts out disabled, with a default policy that denies incoming connections; enabling it can drop existing connections such as your SSH session, and over SSH it asks you to confirm. [5]

Allow SSH before you run sudo ufw enable, or you can lock yourself out of the server. If SSH listens on a port other than 22, allow that port instead.

Allow SSH, HTTP and HTTPS, then switch UFW on
sudo ufw allow 22/tcp
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable
sudo ufw status

To allow an application profile instead of port numbers, sudo ufw app list shows the profiles on your server and sudo ufw app info shows the ports each one opens; quote names that contain spaces. [5] With IPv6 enabled in UFW, the default, each rule covers IPv4 and IPv6. [5] If your provider runs a firewall in front of the server, open the same ports there. [4]

Serve example.com from nginx or Apache

Set up example.com in your web server before you add HTTPS, because Certbot expects a site that already answers over plain HTTP. [4]

nginx: one server block for both names

On Ubuntu, nginx keeps each server block in /etc/nginx/sites-available and enables it with a link in /etc/nginx/sites-enabled; list both names on the server_name line. [6]

/etc/nginx/sites-available/example.com
server {
    listen 80;
    listen [::]:80;
    server_name example.com www.example.com;

    root /srv/example.com/html;
    index index.html;

    location / {
        try_files $uri $uri/ =404;
    }
}
Create a test page, enable the site and reload nginx
sudo mkdir -p /srv/example.com/html
echo "example.com works" | sudo tee /srv/example.com/html/index.html
sudo ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx

Apache: the virtual host equivalent

On Apache, a virtual host in /etc/apache2/sites-available uses ServerName for example.com and ServerAlias for www.example.com; start from a copy of the default file and enable it with a2ensite. [7]

Copy the default virtual host
sudo cp /etc/apache2/sites-available/000-default.conf /etc/apache2/sites-available/example.com.conf
/etc/apache2/sites-available/example.com.conf
<VirtualHost *:80>
    ServerName example.com
    ServerAlias www.example.com
    DocumentRoot /var/www/example.com
</VirtualHost>

Restarting Apache affects every site on the server. If others are live, check the new file first and keep your SSH session open.

Create a test page, enable the site and restart Apache
sudo mkdir -p /var/www/example.com
echo "example.com works" | sudo tee /var/www/example.com/index.html
sudo a2ensite example.com
sudo systemctl restart apache2.service

Open http://example.com and http://www.example.com: both should show the test page.

Get free HTTPS with Let's Encrypt and Certbot

Certbot gets a certificate from Let's Encrypt and can set up nginx or Apache to serve it. [4]

1. Install Certbot as a snap

The Certbot site strongly recommends the snap for most users. It needs snapd; remove any Certbot package installed with apt first, so the certbot command runs the snap. [4]

Install Certbot on Ubuntu 24.04
sudo apt-get remove certbot
sudo snap install --classic certbot
sudo ln -s /snap/bin/certbot /usr/local/bin/certbot

2. Get the certificate and switch on HTTPS

The plugin for your web server gets the certificate and edits the configuration to serve it, turning on HTTPS in one step. [4]

nginx
sudo certbot --nginx
Apache
sudo certbot --apache

Answer Certbot's questions and include both names, since one certificate can hold several. [1] To edit the configuration yourself instead, run sudo certbot certonly --nginx, which only gets the certificate. [4] Then open https://example.com and look for the lock icon. [4]

3. Test automatic renewal

Certbot installs a cron job or systemd timer that renews certificates before they expire, so you do not run it again unless your configuration changes. [4] Test renewal now, and again after changes to DNS, the firewall or Cloudflare:

Test renewal and find the timer
sudo certbot renew --dry-run
systemctl list-timers

How long Let's Encrypt certificates last

Let's Encrypt's default certificates are valid for 90 days. [1] From 10 February 2027, certificates it issues or renews will be valid for 64 days by default, with the last 90-day certificates expected to expire on 11 May 2027, and Let's Encrypt plans a 45-day default for 2028. [8] If you wrote your own cron job with a fixed interval, Let's Encrypt advises renewing at about two thirds of the lifetime instead and checking scripts for hard-coded numbers such as 60, 80 or 83. [8]

Use Full (strict) when Cloudflare's proxy is on

When Cloudflare's proxy is on, set the SSL/TLS encryption mode to Full (strict). The mode controls the connection from visitors to Cloudflare and the one from Cloudflare to your server. [9]

Mode Cloudflare to your server Server certificate checked
Flexible Plain HTTP, not encrypted No
Full Same protocol the visitor used No
Full (strict) Same protocol the visitor used Yes
Strict (SSL-Only Origin Pull) Always HTTPS Yes

Avoid Flexible: the browser shows HTTPS, but traffic between Cloudflare and your server is not encrypted, and Cloudflare itself strongly recommends Full or Full (strict). [9] It also clashes with the HTTP-to-HTTPS redirect a Certbot setup can add. [4] Cloudflare asks your server over plain HTTP, the server redirects to HTTPS, and the browser loops. [9] Full (strict) checks the server's certificate, which can come from a public CA such as Let's Encrypt. [9]

Cloudflare will not move a zone from Full (strict) back to Full if the certificate expires, so renewal has to keep working. [9] The simplest order is certificate first, proxy second.

Choose Full (strict) only after the certificate is installed and the renewal dry run passes.

  1. Get the certificate while both records are on DNS only.
  2. Switch both records to Proxied.
  3. On the SSL/TLS Overview page, choose Full (strict); if the zone uses Automatic SSL/TLS, select Custom first. [9]
  4. Run sudo certbot renew --dry-run again.

With the proxy already on, issuing can still work: in Full and Full (strict), Cloudflare reaches your server over HTTP when the request is HTTP, so Certbot's port 80 check can pass through. [9] Strict (SSL-Only Origin Pull) always connects over HTTPS, so it fails until the certificate exists. [9] If issuing fails, switch the records back to DNS only, get the certificate, then turn the proxy on again.

With the proxy on, the server's IP still answers anyone who knows it. To close that gap, allow only Cloudflare IPs on ports 80 and 443.

Common problems and how to fix them

Most failures come down to DNS, the firewall or too many retries.

DNS has not updated yet. An old address means a resolver is still serving a cached answer, which it can keep until the TTL runs out. [2] After a change of DNS servers or registrar, Google Public DNS can return old answers too, and its Flush Cache tool clears them. [3]

A wrong or missing record. Look for a typo in the address, a leftover registrar record, a missing www record, or edits made at a DNS host the domain no longer uses. A missing www record also blocks HTTPS, because every name in the request must pass validation. [10] Remove AAAA records unless the server really answers on that IPv6 address.

Port 80 is blocked. Let's Encrypt says failed HTTP-01 validations usually come from network or firewall settings that stop its servers from reaching yours. [10] Check sudo ufw status and your provider's firewall, and keep port 80 open after the switch to HTTPS, because Certbot's nginx and Apache plugins rely on it. [4]

Too many failed attempts. An account can fail validation for the same name 5 times an hour; the allowance refills at one every 12 minutes, and until then Let's Encrypt refuses new orders for that name. [10] It also issues at most 5 certificates for the exact same set of names every 7 days, and reinstalling the client while troubleshooting is a common way to hit that. [10] Let's Encrypt cannot reset a limit early, and revoking certificates does not reset it either, so fix the cause before you retry; for tests, it recommends its staging environment, which has much higher limits. [10]

If the domain and certificate work but the page shows 502 Bad Gateway, work through our guide to fixing 502 Bad Gateway.

FAQ

How long does it take for a domain to point to a new VPS?

It depends on the records' TTL and on what resolvers have already cached. On Cloudflare, proxied records default to a TTL of 300 seconds and DNS-only records use the value you set, and a resolver can keep an old answer until its TTL runs out. [2]

Should www be an A record or a CNAME?

Either works. An A record points www straight at the server's IPv4 address, while a CNAME points it at another name such as example.com, so it follows that record if the address changes. [2]

Is Let's Encrypt free?

Yes. Let's Encrypt does not charge a fee for its certificates, and its default certificates are valid for 90 days. [1]

How long are Let's Encrypt certificates valid?

Default certificates are valid for 90 days today. [1] From 10 February 2027, new and renewed certificates will be valid for 64 days by default, and Let's Encrypt plans a 45-day default in 2028. [8]

Which Cloudflare SSL/TLS mode should I use with Let's Encrypt?

Use Full (strict). It validates your server's certificate, which can come from Let's Encrypt, while Flexible leaves the connection between Cloudflare and your server unencrypted. [9]

Sources & references
  1. FAQ — Let's Encrypt (accessed 2026-11-03)
  2. DNS record types — Cloudflare Docs (accessed 2026-11-03)
  3. Troubleshooting — Google Public DNS (accessed 2026-11-03)
  4. Certbot instructions: Nginx on Linux (snap) — Certbot (EFF) (accessed 2026-11-03)
  5. ufw(8): program for managing a netfilter firewall — Ubuntu Manpages (accessed 2026-11-03)
  6. How to configure nginx — Ubuntu Server documentation (accessed 2026-11-03)
  7. How to configure Apache2 settings — Ubuntu Server documentation (accessed 2026-11-03)
  8. 64-Day Certificate Lifetimes Coming Feb 2027 — Let's Encrypt (accessed 2026-11-03)
  9. Encryption modes — Cloudflare Docs (accessed 2026-11-03)
  10. Rate Limits — Let's Encrypt (accessed 2026-11-03)

Continue learning