Back to tutorials
Tutorial

Set up Caddy Server on Ubuntu 24.04

In this tutorial, we'll learn how to set up Caddy Server on Ubuntu 24.04. Caddy is a modern, open-source web server written in Go, manages HTTPS certificates.

By Anurag Singh
Updated on Oct 30, 2025
Category: Tutorial
Share article
Set up Caddy Server on Ubuntu 24.04

In this tutorial, we'll learn how to set up Caddy Server on Ubuntu 24.04.

What is Caddy?

Caddy is a modern, open-source web server written in Go. It’s designed to be simple, secure, and fully automated. What makes Caddy special is that it automatically manages HTTPS certificates using Let’s Encrypt — no manual setup or renewal needed. It can serve static websites, act as a reverse proxy for backend apps, and handle load balancing with clean, human-readable configuration. In short, Caddy turns complex server management into a one-file setup that just works.

Prerequisites

Before we begin, ensure we have the following:

  • An Ubuntu 24.04 dedicate server or KVM VPS.
  • Basic Linux Command Line Knowledge.
  • A domain name, pointing A record to server IP.

Set up Caddy Server on Ubuntu 24.04

Step 1: Update the system

sudo apt update && sudo apt upgrade -y

Keep our system fresh so packages work properly.

Step 2: Install Caddy

Caddy provides an official repository. Run these commands to add it and install:

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 -y caddy

Caddy starts automatically after installation. Check its status:

sudo systemctl status caddy

Press q to exit the status screen.

Step 3: Add our website files

Let’s create a simple site directory.

sudo mkdir -p /var/www/example
sudo nano /var/www/example/index.html

Add a small test page:

<h1>Welcome to Our Website</h1>
<p>This site is powered by Caddy Server with HTTPS.</p>

Save and exit (Ctrl + O, Enter, Ctrl + X).

Step 4: Configure Caddy

Open the main configuration file:

sudo nano /etc/caddy/Caddyfile

Replace its content with this simple setup:

example.com {
    root * /var/www/example
    file_server
}

Important: Replace example.com with our real domain that points to the server’s public IP address.

Step 5: Allow HTTP and HTTPS traffic

If we’re using ufw (Ubuntu firewall):

sudo ufw allow 80,443/tcp
sudo ufw reload

Step 6: Reload Caddy

sudo systemctl reload caddy
  • Caddy will automatically fetch an SSL certificate from Let’s Encrypt and enable HTTPS.
  • We can check it by visiting our domain in a browser:
https://example.com

If the domain points correctly, we’ll see our test page with a lock icon — meaning SSL is working.

Step 7: Check Logs (if needed)

If the site doesn’t load:

sudo journalctl -u caddy -f

This shows what’s going on in real-time.

List active certificates and expiry:

sudo caddy list-certs

Manually trigger a reload without downtime:

sudo systemctl reload caddy
# or
sudo caddy reload --config /etc/caddy/Caddyfile

Certificate renewals are automatic; list-certs shows expiry dates for verification.

Simple proxy with header forwarding and websockets

example.com {
    reverse_proxy {
        to localhost:3000
        header_up X-Forwarded-Proto {scheme}
        header_up X-Forwarded-For {remote}
        header_up Host {host}
    }
}

This preserves original host/protocol and supports WebSocket upgrades automatically.

Reverse proxy with path match (proxy only /api)

example.com {
    handle_path /api/* {
        reverse_proxy localhost:8080
    }
    handle {
        root * /var/www/html
        file_server
    }
}

Simple load balancing

api.example.com {
    reverse_proxy lb1.internal:8080 lb2.internal:8080 {
        health_path /healthz
        health_interval 10s
    }
}

These patterns are standard and cover most proxy needs: path routing, static file fallback, websockets, and backend pools.

Using DNS provider for wildcard certs (short practical note)

If we need *.example.com, do the DNS challenge. Two options:

  • Download a Caddy binary with the DNS provider module from the Caddy download page.
  • Build a custom Caddy with xcaddy including caddy-dns/<provider>.

Then configure provider credentials (example Cloudflare) in env or config and use tls directive:

example.com, *.example.com {
    tls {
        dns cloudflare {env.CLOUDFLARE_API_TOKEN}
    }
    reverse_proxy ... 
}

Consult the provider docs for exact environment variables and plugin names.

Security & production tips

  • Run Caddy as the packaged caddy user (default) — do not run as root. Package takes care of that.
  • Use a short health_path for backends so Caddy can detect failed backends and avoid routing to them.
  • Keep backups of /etc/caddy/Caddyfile and any TLS-related environment variables for DNS plugins.
  • For strict compliance environments, pin ACME issuer or use a private CA via tls directive.

Conclusion

We set up Caddy from the official repo, created a Caddyfile for reverse proxying apps and static content, confirmed automatic HTTPS behavior, covered wildcard/DNS challenge considerations, and included checks and production tips. Caddy removes a lot of the friction around TLS and reverse proxies; for most web apps it’s a lighter, simpler alternative to manual cert management and complex Nginx configs. Use the examples above as copy-paste templates and adapt headers/backends to our stack.

Set up Caddy Server on Ubuntu 24.04 | HostMyCode