Tutoriel Linux

Caddy: publish a web service in HTTPS with a minimal Caddyfile

Débutant3 min de lecture

Your application listens on 127.0.0.1:3000. Locally, it responds. From the public domain, it is not yet properly exposed.

Caddy can serve as a reverse proxy in front of this web service and manage HTTPS with an automatic TLS certificate. On a Debian or Ubuntu VPS, start by checking the backend, freeing the public ports, setting up a minimal Caddyfile, and then controlling the HTTPS response from the outside.

Linux server connected to the Internet through a protected HTTPS proxy
Caddy connects a local service to the web via HTTPS.

Check the domain, the backend, and the ports

Before starting Caddy, the domain name must reach this server. Also check the IPv6 records: an old AAAA entry pointing to another machine is enough to block the certificate issuance.

Keep an SSH session open before touching the firewall or an existing proxy.

dig +short A app.example.net
dig +short AAAA app.example.net
curl -I http://127.0.0.1:3000/
sudo ss -lntp '( sport = :80 or sport = :443 )'

Replace app.example.net with your name. The A and AAAA records must point to the public address of the VPS. curl -I should return the expected code from the application, often 200 or 302.

If the backend does not respond on the local loop, first fix the application. Caddy will not repair a stopped service or a wrong internal URL.

ss lists the processes already attached to ports 80 and 443. Do not reflexively stop Nginx or Apache: first choose the proxy that holds these ports, then migrate cleanly if necessary.

Create a reverse proxy Caddyfile

Install Caddy from the package designed for your distribution, then open /etc/caddy/Caddyfile. For a local HTTP service, this block is sufficient:

app.example.net {
    reverse_proxy 127.0.0.1:3000
}

The first line is the public name. reverse_proxy forwards requests to the application listening on 127.0.0.1:3000.

With a real domain, Caddy requests a publicly recognized certificate and renews it automatically. The application stays behind the proxy and does not need to listen on the Internet.

On the same VPS, keep 127.0.0.1 for the backend. This avoids opening the application port on the network.

If the backend lives in another VM or on another host, use an explicit private address and filter the traffic between the machines.

Validate the Caddyfile before reload

Do not reload a modified Caddyfile blindly. Validate the syntax, reload the service, then check its state and logs.

sudo caddy validate --config /etc/caddy/Caddyfile --adapter caddyfile
sudo systemctl reload caddy
sudo systemctl status caddy --no-pager
sudo journalctl -u caddy -n 50 --no-pager

caddy validate must complete without errors. systemctl reload caddy applies the configuration without a complete restart of the daemon when the service accepts reloads.

After the reload, systemctl status should show active. If the certificate is not issued or if the backend refuses the connection, journalctl points to the useful error: DNS, occupied port, firewall, or missing local service.

Test HTTPS from another machine

The local test on the VPS is not enough. Execute the request from a machine that goes through the Internet or from an external probe.

curl -I https://app.example.net/
curl -v https://app.example.net/ -o /dev/null

The first curl should display the expected HTTP code. With -v, check the certificate name, the TLS negotiation, and any possible redirections.

To diagnose an HTTP response, the guide Curl under Linux helps read the headers. The check of open ports helps spot a listening conflict. The page on systemd services completes the daemon check before a restart.

A reverse proxy Caddy encrypts the traffic between the browser and the server, but it does not replace the application authentication. Before exposing an admin panel, add some protection or limit access by IP, VPN, or application rule.