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.
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]
dig -t A example.com @8.8.8.8
dig -t A www.example.com @8.8.8.8nslookup -type=A example.com 8.8.8.8
nslookup -type=A www.example.com 8.8.8.8Both 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.
sudo ufw allow 22/tcp
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable
sudo ufw statusTo 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]
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;
}
}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 nginxApache: 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]
sudo cp /etc/apache2/sites-available/000-default.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.
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.serviceOpen 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]
sudo apt-get remove certbot
sudo snap install --classic certbot
sudo ln -s /snap/bin/certbot /usr/local/bin/certbot2. 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]
sudo certbot --nginxsudo certbot --apacheAnswer 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:
sudo certbot renew --dry-run
systemctl list-timersHow 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.
- Get the certificate while both records are on DNS only.
- Switch both records to Proxied.
- On the SSL/TLS Overview page, choose Full (strict); if the zone uses Automatic SSL/TLS, select Custom first. [9]
- Run
sudo certbot renew --dry-runagain.
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
- FAQ — Let's Encrypt (accessed 2026-11-03)
- DNS record types — Cloudflare Docs (accessed 2026-11-03)
- Troubleshooting — Google Public DNS (accessed 2026-11-03)
- Certbot instructions: Nginx on Linux (snap) — Certbot (EFF) (accessed 2026-11-03)
- ufw(8): program for managing a netfilter firewall — Ubuntu Manpages (accessed 2026-11-03)
- How to configure nginx — Ubuntu Server documentation (accessed 2026-11-03)
- How to configure Apache2 settings — Ubuntu Server documentation (accessed 2026-11-03)
- 64-Day Certificate Lifetimes Coming Feb 2027 — Let's Encrypt (accessed 2026-11-03)
- Encryption modes — Cloudflare Docs (accessed 2026-11-03)
- Rate Limits — Let's Encrypt (accessed 2026-11-03)
Continue learning
VPS Control Panels and Management Tools: 6 Compared
Compare VPS control panels such as Plesk, cPanel, Webmin, Virtualmin and DirectAdmin on price, features and skill level, and learn how to choose one.
High Availability VPS: How to Design Automated Failover
Design a high availability VPS setup with redundancy, replication, automated failover and monitoring, and see how VPS and cloud compare for uptime.
Server Uptime Monitoring: 7 Tools to Compare
Compare server uptime monitoring tools, what to look for in alerts and checks, and when a self-hosted uptime monitor is enough.
