A domain and a server are two separate systems, and the only thing linking them is a couple of lines in DNS. This guide covers which record to add (A or AAAA), how long propagation genuinely takes, why the server needs open ports before a certificate can exist, and why Caddy beats hand-rolling nginx plus certbot plus a renewal cron job for most setups.
A domain and a server know nothing about each other until you connect them by hand. Pointing a domain at a server means adding a DNS record that tells the internet "this name belongs to this IP." From there, the server itself has to agree to answer for that name and serve it over HTTPS instead of plain http. This guide covers which record to add, how long propagation actually takes, and how to get a reverse proxy running with a certificate that renews itself, in about ten minutes.
In short. In your domain's DNS panel, add an A record with the name
@pointing at the server's IPv4, the same forwww; if the server has an IPv6 address, add a matching pair of AAAA records too. Give the records time to propagate, usually a few minutes to an hour. On the server, install Caddy: it serves the site and obtains a Let's Encrypt certificate on its own, no separate certbot and no cron job for renewal. Check the result withcurl -I https://your-domain.
Layer one is DNS. Records in the domain's zone map its name to an address. A request for site.com first goes to the domain's name servers, they return the IP from an A record (IPv4) or an AAAA record (IPv6), and only then does the browser connect to the server itself.
Layer two is the server. The request arrives with a Host: site.com header. The web server or reverse proxy reads that header, decides which site to serve, and handles the connection, including issuing and renewing the TLS certificate for HTTPS.
Because the two layers don't depend on each other, you can add the DNS record before the server is even configured. The domain will simply point at an address where nobody answers yet, with no errors along the way.
Open the server in the my.hip.hosting panel, on the Information tab, in the Connection block, the same one you'd use to log in over SSH. It lists the IP and a ready-to-copy ssh root@IP line you can pull the address from directly (see Connect to your HIP server for the login itself). What's shown there is the IPv4 address. HIP doesn't necessarily hand out IPv6 on every plan and in every location, so a separate IPv6 field may or may not be there for you. If your server has one, it's on the same tab; if not, everything below still works fine on IPv4 alone.
While you're at it, confirm something on the server is already listening on the port you'll need. Connect over SSH and run:
ss -tlnp
Look for lines with :80 and :443. An empty list is fine at this point, the web server shows up in step 4.
Go to the panel where the domain's DNS is managed. The steps below use Cloudflare as the example; registrar panels label the same fields almost identically.
Add a record:
A@ (the bare domain, site.com; some panels want this field left empty instead of @, or want the full domain name typed out)Auto or 300 seconds while you're setting things upA short TTL won't make this first record show up any faster, it only pays off later: if you change the IP down the line, the new value propagates faster because resolvers won't be holding the old one for as long.
Add a second A record for www pointing at the same IP, so the site opens with and without that prefix. If the server has an IPv6 address, add a matching pair of AAAA records for @ and www.
Type | Name | Value | Why |
|---|---|---|---|
A | | server IPv4 | bare domain over IPv4 |
A | | server IPv4 | www subdomain over IPv4 |
AAAA | | server IPv6 | only if the server has one |
AAAA | | server IPv6 | only if the server has one |
A CNAME can stand in for the second A record. A CNAME record named www with the value site.com tells the world "www is an alias of the main domain," so the IP only needs editing in one place. You can't put a CNAME on the bare domain (@, the zone apex) under the DNS spec, only A or AAAA are allowed there. Some DNS providers, Cloudflare included, offer their own workaround like CNAME flattening at the apex, but that's a provider feature, not a general DNS rule.
A new record isn't visible everywhere at once, DNS servers around the world cache answers for the length of the TTL. A freshly added record usually shows up within a few minutes to an hour; an NS change takes longer, sometimes up to a day, because it's also cached at the top-level domain registry, not just by ordinary resolvers.
Check from your own machine:
dig +short site.com
nslookup site.com
nslookup ships by default almost everywhere: Windows, macOS, most Linux distributions.dig is easier to read but usually isn't preinstalled on Ubuntu or Debian: sudo apt install dnsutils. macOS typically already has it.Once the answer shows your server's IP, the records have applied. To check from multiple countries at once, a site like dnschecker.org works well.
An application (a Node.js or Python site, say) usually listens on a local port like 127.0.0.1:3000. A reverse proxy exposes it on 80 and 443 to the outside world and handles the certificate too.
If the server has a firewall running, sudo ufw status will tell you, allow at least port 80 (Let's Encrypt's standard validation needs it) and port 443 for the HTTPS traffic itself once the certificate exists. Installing a web server doesn't open a port to the outside on its own, it just makes a process listen on that port internally; the firewall is a separate setting entirely (see Secure a fresh VPS for the full walkthrough).
Our pick here is Caddy, not the usual nginx-plus-certbot pairing. The difference isn't cosmetic: Caddy obtains and renews the certificate as part of the same process, while nginx needs a separate tool (certbot) plus a separate renewal job that someone has to set up once and then remember exists. Fewer moving parts means fewer things to quietly break six months from now, once you've forgotten how any of it was wired together.
Caddy | nginx + certbot | |
|---|---|---|
Getting a certificate | built in, fires automatically on start/reload | separate certbot command |
Renewing it | Caddy tracks it on its own | needs a systemd timer or cron job |
Minimal config | a few lines in a Caddyfile | an nginx server block plus certbot setup on top |
Makes more sense when | starting fresh, want fewer steps | nginx already runs other sites, or you need a directive Caddy lacks |
Installing Caddy on Ubuntu from its official repository:
sudo apt update
sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https curl
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-stable.list
sudo apt update
sudo apt install -y caddy
apt has nowhere to fetch the package from;systemd service and keeps running in the background on its own.Open Caddy's config file in a text editor:
sudo nano /etc/caddy/Caddyfile
Clear out the default content and add your domain:
site.com, www.site.com {
reverse_proxy 127.0.0.1:3000
}
Apply the configuration:
sudo systemctl reload caddy
Caddy requests the certificate as soon as it picks up the new config, on reload or on startup, not the moment someone's browser first hits the site. That request needs open ports 80 and 443 and a DNS record that has already propagated; if either is missing, issuance fails, and you'll see it in the log:
journalctl -u caddy -n 50
Check the result:
curl -I https://site.com
A working response looks like your site's headers with no certificate error. The exact status code and protocol version (HTTP/1.1, HTTP/2, or HTTP/3) depend on how the application behind the proxy is set up, not on some fixed guarantee.
If you end up managing many domains and subdomains and reissuing certificates often, keep Let's Encrypt's real limits in mind: no more than 50 new certificates per registered top-level domain per week, and no more than 5 duplicate certificates for the exact same set of names per week. For one or two sites you'll never come close, but automated bulk issuance can hit that wall for real.
The layout is the same: DNS points at the server, ports 80 and 443 are open, a config ties the domain to the application's local port. The difference is that the certificate is issued separately through certbot --nginx, and the reverse-proxy config is written by hand. That's a reasonable choice if you already run nginx for other sites, or need a directive Caddy doesn't have yet. For the full config, proxy headers, and firewall rules, see nginx and ufw in front of your app; for a deeper Caddy setup beyond one domain on one port, see Caddy web server setup.
Every subdomain is its own DNS record. Need api.site.com? Add an A record named api pointing at the same IP (or a CNAME to site.com), and a separate block in the Caddyfile:
api.site.com {
reverse_proxy 127.0.0.1:4000
}
A Telegram bot running on webhooks needs a public HTTPS address for the same reason, usually a subdomain like hook.site.com, set up the same way. A bot on long polling (which keeps asking Telegram's servers for updates instead of receiving them) doesn't need a domain at all.
An A record maps a name to an IP, the "forward" zone. A PTR record does the opposite, mapping an IP back to a name, and it mostly matters for sending mail: receiving servers check it, and without one your messages are more likely to land in spam. A plain website over HTTPS doesn't need it at all. If you're also running mail from this server, the full rundown, including how to set the PTR in the HIP panel and check it with dig -x, lives in Reverse DNS (PTR) and ordering extra IPv4.
Only if you want DNS managed somewhere other than the registrar, Cloudflare being the common example. If you edit records right in the registrar's own panel, leave NS alone.
Usually a few minutes to an hour with a low TTL, sometimes a few hours. An NS change can take up to a day, since it's cached at the registry level, not just by resolvers.
Not a public one from Let's Encrypt. The certificate authority issues certificates for a specific name and has to verify you control it, which requires that name to resolve to your server. On a bare IP the only option is a self-signed certificate, which browsers mark as unsafe.
Yes. Each gets its own DNS records aimed at the same IP and its own block in the Caddyfile or nginx config. The reverse proxy tells them apart using the Host header from the browser's request.
The IP a server gets at order time is generally tied to it and doesn't change on its own, so it's safe to put in DNS. It usually only changes when you order a new server, not from normal use or from reinstalling the OS on the same one.
You can, for DDoS protection and static caching, but the server still needs HTTPS of its own, and Cloudflare's SSL mode should be set to Full (strict), otherwise the leg between Cloudflare and your server stays unencrypted. With the proxy off (grey cloud), it's plain DNS, and everything works exactly as described above.