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 sudo privileges
  • 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.

Similar Posts