Caddy: automatic HTTPS
Caddy is a web server that obtains and renews Let's Encrypt TLS certificates by itself — no certbot, no manual cron jobs. In this article you'll install Caddy on your mHost VPS, describe a site in a Caddyfile with automatic HTTPS, and set up reverse_proxy so Caddy accepts HTTPS traffic from the outside and forwards it to your application.
What you'll need
- An mHost Linux VPS: Ubuntu 22.04/24.04, Debian 11/12, or AlmaLinux/Rocky Linux 8/9.
- SSH access — as root or a user with sudo.
- A domain name whose A record points to the server's IP address (mHost VPS are IPv4-only, so no AAAA record is needed).
- Open ports 80 and 443 — without them Caddy can't obtain a certificate (details in Step 2).
Step 1. Check that the domain points to the server
Automatic HTTPS only works when the certificate authority (Let's Encrypt or ZeroSSL) can reach your server through that exact domain — so DNS must already point to it before you start Caddy.
- Find your server's IP address — in the VMmanager 6 panel / my.mhost.ee, or right on the server:
``bash curl -4 ifconfig.me ``
- Check where the domain points (replace
example.comwith your own):
``bash dig +short example.com A ``
If dig isn't installed, install the DNS utilities package:
``bash sudo apt install -y dnsutils # Ubuntu/Debian sudo dnf install -y bind-utils # AlmaLinux/Rocky ``
- Compare the
digoutput with the server's IP address — they must match.
Step 2. Open ports 80 and 443
Port 80 is needed for the HTTP-01 domain challenge and the automatic HTTP-to-HTTPS redirect, port 443 for HTTPS itself and the TLS-ALPN challenge. Caddy uses both ports by default — there's nothing extra to configure inside Caddy — but the server's firewall must let them through.
Ubuntu and Debian (ufw)
sudo ufw allow 80/tcp
sudo ufw allow 443/tcpAlmaLinux and Rocky Linux (firewalld)
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --reloadStep 3. Install Caddy
There's no ready-made VMmanager 6 recipe for Caddy, so we install the package manually from the official repository. For the full list of what you can set up in one click, see "Ready-made VMmanager 6 recipes".
Ubuntu and Debian
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 chmod o+r /usr/share/keyrings/caddy-stable-archive-keyring.gpg
sudo chmod o+r /etc/apt/sources.list.d/caddy-stable.list
sudo apt update
sudo apt install caddyAlmaLinux and Rocky Linux
sudo dnf install -y dnf-plugins-core
sudo dnf copr enable @caddy/caddy
sudo dnf install caddyThe package creates a systemd service and already starts Caddy. Enable it to start on boot and check its status:
sudo systemctl enable --now caddy
sudo systemctl status caddyStep 4. A minimal Caddyfile with automatic HTTPS
Caddy's configuration lives in /etc/caddy/Caddyfile. Open it in an editor:
sudo nano /etc/caddy/CaddyfileReplace the contents with a minimal site block — the domain name in the block's header is all Caddy needs to turn on automatic HTTPS:
example.com {
respond "Caddy on mHost works over HTTPS!"
}Replace example.com with your own domain (the same one you checked in Step 1) and save the file. There's no certbot, no separate certificates, no renewal cron job to set up — on the first request to the site, Caddy will obtain a certificate from Let's Encrypt itself (falling back to ZeroSSL if that fails) and keep renewing it before it expires.
How to apply the changes and check the result is covered in Steps 6 and 7 below.
Step 5. A reverse_proxy example — proxying to an application
If you already have your own application running on the server (Node.js, Python, Java, etc.) listening on a local port, replace the block from Step 4 with this one:
example.com {
reverse_proxy localhost:3000
}Replace 3000 with the port your application actually listens on. Caddy will accept HTTPS traffic from the outside and forward it to that port over plain HTTP inside the server. Save the file and move on to Step 6 to apply the changes.
Step 6. Validate the config and reload it
After any change to /etc/caddy/Caddyfile, first check the syntax, then reload the configuration without stopping the service:
sudo caddy validate --config /etc/caddy/Caddyfile
sudo systemctl reload caddyvalidate catches configuration errors before they're applied, and reload picks up the changes on the fly — without dropping existing connections or any site downtime, unlike restart.
If something goes wrong, check the service logs:
sudo journalctl -u caddy -fStep 7. Check that HTTPS works
curl -I https://example.comYou should see a response like HTTP/2 200 with no certificate errors. On the very first request, Caddy may delay the response by a few seconds while it obtains the certificate.
What's next
You can add more blocks to /etc/caddy/Caddyfile for other domains — each with its own reverse_proxy or other directives — and Caddy will automatically issue a certificate for each of them too. After every edit, repeat Step 6 (validate + reload). If a new site uses ports other than 80/443, open them the same way as in Step 2 — see "Setting up the UFW firewall" for details.