Deploying a Vite App Behind Caddy: Automatic HTTPS in Five Minutes
Point one DNS record at your VPS, write a five-line Caddyfile, and Caddy obtains and renews TLS certificates for your Vite app automatically.
Netbay Infrastructure Team
Netbay Engineering
On this page
A Vite build produces a folder of static files, which means the only server-side job is to serve them over HTTPS. Caddy does that with a config file short enough to memorize and certificate management short enough to forget: it obtains and renews Let's Encrypt certificates on its own, with no certbot timer and no renewal hooks. Five minutes of setup is a realistic budget, including the TLS part most guides skip.
Start with DNS and two open ports
Create an A record for app.example.com pointing at your VPS IP. Caddy needs port 80 reachable for the ACME HTTP challenge and port 443 for actual traffic. On a fresh Ubuntu box, open both and install Caddy from its official repository:
sudo ufw allow 80,443/tcp
sudo apt-get 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-get update && sudo apt-get install caddy
caddy versionThe package installs a systemd service that starts Caddy on boot, which is one less thing to wire up by hand.
The whole site configuration
app.example.com {
root * /var/www/app/html
encode gzip zstd
try_files {path} /index.html
file_server
header /assets/* Cache-Control "public, max-age=31536000, immutable"
}Five lines and a cache header. The site address at the top is a public hostname, and that is the entire TLS configuration: Caddy sees the DNS name, obtains a certificate on the first request, and renews it forever. try_files with the {path} placeholder serves real files first and falls back to index.html for client-side routes, exactly the SPA contract Nginx users configure with more typing. encode turns on gzip and zstd compression. The header directive gives hashed Vite assets a year-long immutable cache while index.html keeps its default revalidation behavior.
Validate, reload, verify
caddy validate --config /etc/caddy/Caddyfile
sudo systemctl reload caddy
curl -sI https://app.example.com/ | head -n 5validate catches typos before a reload takes the site down. The curl output should show HTTP/2 200, and the very first hit may pause for a few seconds while Caddy completes the ACME challenge behind the scenes. If issuance fails, the Caddy logs state the reason — in practice it is almost always DNS that has not propagated yet or port 80 still blocked by a provider firewall you forgot is separate from ufw.
What happens while you sleep
Caddy stores certificates under /var/lib/caddy, renews them at two-thirds of their lifetime, and swaps them in without dropping connections. Plain HTTP requests redirect to HTTPS automatically. There is no timer to babysit and no deploy script that must remember TLS. The operational rules reduce to two: keep port 80 open, and keep DNS pointing at the box. Break either one and Caddy tells you in its logs exactly which one.
The takeaway: one DNS record, a five-line Caddyfile, and systemctl reload. That is the entire deployment story for a Vite app, certificate automation included.
Netbay VPS plans ship with DDoS protection and High-Speed SSD storage, and an Ubuntu 24.04 instance is live in under a minute — netbayhosts.in.
Keep reading
Follow along on a real VPS
Deploy Linux in under 60 seconds
These guides are written against Ubuntu, Debian, and RHEL-family images — the same ones on NetBay.
Deploy an instance