How to Configure Caddy as a Reverse Proxy and Static File Server with Automatic HTTPS on Ubuntu Server
Learning how to configure Caddy as a reverse proxy and static file server with automatic HTTPS on Ubuntu Server is one of the best decisions you can make for your web stack. Caddy is a modern web server written in Go. It handles SSL certificates automatically through Let’s Encrypt. You don’t need Certbot. You don’t need manual renewal scripts. Caddy does it all. In this tutorial, you’ll install Caddy on Ubuntu Server, set it up to serve static files, and configure it as a reverse proxy for a backend application. By the end, you’ll have a fully working HTTPS setup with zero certificate headaches.
Prerequisites for Configuring Caddy as a Reverse Proxy on Ubuntu Server
Before you start, make sure you have the following in place.
You will need:
- A fresh Ubuntu Server 22.04 or 24.04 instance
- A non-root user with
sudoprivileges - A registered domain name pointed at your server’s IP address
- Ports 80 and 443 open in your firewall
- A backend app running locally (for example, a Node.js or Python app on port 3000)
You should be comfortable using the Linux terminal. You should know basic file editing with nano or vim. This tutorial assumes you have SSH access to your server. Estimated time to complete: 30 to 45 minutes.
Caddy fetches SSL certificates automatically using the ACME protocol. For this to work, your domain must resolve to your server’s public IP before you start. Check this with a tool like dig yourdomain.com or an online DNS checker. If DNS hasn’t propagated yet, wait before proceeding.
For full details on Caddy’s features, visit the official Caddy documentation.
Step-by-Step Guide to Configure Caddy as a Reverse Proxy and Static File Server with Automatic HTTPS
Related tutorial: How to Configure Redis Object Cache for Wordpress Performance Optimization
Step 1: Update your system packages
Always start with a system update. This ensures you have the latest security patches.
sudo apt update && sudo apt upgrade -y
Step 2: Install Caddy on Ubuntu Server
Caddy isn’t in Ubuntu’s default repositories. You’ll add the official Caddy repository first.
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 caddy -y
Once installed, Caddy starts automatically. Verify it’s running:
sudo systemctl status caddy
You should see active (running) in the output.
Step 3: Configure the firewall
Open ports 80 and 443 using UFW. Caddy needs port 80 for the ACME HTTP challenge and port 443 for HTTPS traffic.
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw reload
Step 4: Create a directory for static files
You’ll serve a static site from /var/www/mysite. Create the directory and add a test page.
sudo mkdir -p /var/www/mysite
echo "Hello from Caddy!
" | sudo tee /var/www/mysite/index.html
Set proper ownership so Caddy can read the files:
sudo chown -R caddy:caddy /var/www/mysite
Step 5: Edit the Caddyfile
The Caddyfile is Caddy’s configuration file. It lives at /etc/caddy/Caddyfile. Open it with nano:
sudo nano /etc/caddy/Caddyfile
Replace the default content with this configuration. Swap yourdomain.com with your actual domain. Swap localhost:3000 with your backend app’s address.
yourdomain.com {
# Serve static files from this directory
root /var/www/mysite
file_server
# Reverse proxy for API or app requests
reverse_proxy /api/ localhost:3000
}
www.yourdomain.com {
redir https://yourdomain.com{uri} permanent
}
This config does three things. It serves static files from /var/www/mysite. It proxies any request starting with /api/ to your backend app. It redirects the www subdomain to the bare domain. Caddy handles HTTPS certificates automatically for both hostnames.
Save the file with Ctrl+O then exit with Ctrl+X.
Step 6: Reload Caddy to apply the configuration
sudo systemctl reload caddy
Caddy will now request SSL certificates from Let’s Encrypt. This takes a few seconds. Check the status again to confirm no errors:
sudo systemctl status caddy
Step 7: Test your setup
Open a browser and navigate to https://yourdomain.com. You should see your “Hello from Caddy!” page served over HTTPS. No browser warnings. No self-signed certificate errors.
Test your reverse proxy by hitting an API endpoint:
curl https://yourdomain.com/api/health
If your backend app is running on port 3000, you’ll get a response from it. Caddy is now acting as the reverse proxy.
Step 8: Enable Caddy to start on boot
Caddy’s systemd service is usually enabled by default. Confirm this:
sudo systemctl enable caddy
Your server will now start Caddy automatically after a reboot.
Troubleshooting Common Caddy Issues on Ubuntu Server
Caddy fails to get a certificate
This usually means your domain doesn’t point to your server yet. Double-check DNS with:
dig +short yourdomain.com
The output should match your server’s public IP. Also make sure port 80 is open. Let’s Encrypt needs it for the HTTP-01 challenge.
Port 80 or 443 is already in use
Another service like Apache or Nginx may be running. Stop it first:
sudo systemctl stop apache2
sudo systemctl stop nginx
Then reload Caddy.
Caddyfile syntax errors
Validate your config before reloading. Run:
caddy validate --config /etc/caddy/Caddyfile
Caddy will tell you exactly which line has a problem.
Backend app not responding through the proxy
Check that your backend app is actually running:
curl http://localhost:3000/api/health
If this fails, your app isn’t running. Start it and try again. Caddy can’t proxy to something that isn’t there.
Logs for deeper debugging
View Caddy’s logs in real time with:
sudo journalctl -u caddy -f
You’ll see certificate requests, connection details, and any errors. This is your best tool for diagnosing issues. The Ubuntu Server documentation is also a great reference for firewall and networking troubleshooting.
Conclusion
You now know how to configure Caddy as a reverse proxy and static file server with automatic HTTPS on Ubuntu Server. You installed Caddy from the official repository, wrote a Caddyfile, served static content, and proxied backend traffic. You also configured automatic SSL through Let’s Encrypt without touching Certbot once.
Caddy’s simplicity makes it a great choice for developers and sysadmins who want HTTPS without the maintenance overhead. From here, you can explore adding basic authentication, rate limiting, or multiple virtual hosts in a single Caddyfile. You can also look into Caddy’s JSON API for dynamic configuration changes. Your server is secure, fast, and ready for production traffic.
