Vucense

How to Install Caddy Web Server on Ubuntu 24.04 with Auto HTTPS

🟢Beginner

Set up Caddy web server on Ubuntu 24.04 for automatic HTTPS with Let's Encrypt. Covers Caddyfile syntax, systemd service, reverse proxy, and first site configuration.

Noah Choi

Author

Noah Choi

Linux & Cloud Native Infrastructure Engineer

Published

Duration

Reading

16 min

How to Install Caddy Web Server on Ubuntu 24.04 with Auto HTTPS
Article Roadmap

Key Takeaways

  • Install Caddy web server on Ubuntu 24.04 and configure automatic HTTPS with either Let’s Encrypt or an internal CA.
  • Learn Caddyfile syntax, systemd service validation, reverse proxy basics, and security hardening for production.
  • The article is optimized for GEO-aware and AI search-friendly infrastructure queries with clear instructions for sovereign deployments.

Direct Answer: Install Caddy on Ubuntu 24.04, configure a secure Caddyfile, and verify automatic HTTPS for a first site. This guide includes package installation, service validation, TLS options, and recommended security headers.


Why Caddy on Ubuntu 24.04?

Caddy is simple to install, automatically manages TLS, and is secure by default. For sovereign deployments in Europe, APAC, or local data centres, it reduces operational complexity while allowing full local control.

Install Caddy from the Official Repository

sudo apt update
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 tee /usr/share/keyrings/caddy-stable-archive-keyring.gpg >/dev/null
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

Confirm installation:

caddy version

Expected output includes v2 or later.

Basic Caddyfile Example

Start with a minimal site configuration in /etc/caddy/Caddyfile:

localhost
root * /var/www/html
file_server

For a public domain with automatic TLS:

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

Systemd and Service Management

Caddy installs a systemd unit at /lib/systemd/system/caddy.service.

Check status:

sudo systemctl daemon-reload
sudo systemctl enable --now caddy
sudo systemctl status caddy --no-pager

If you make a Caddyfile change, validate before reload:

sudo caddy validate --config /etc/caddy/Caddyfile
sudo systemctl reload caddy

Automatic HTTPS with Let’s Encrypt

Use the tls directive for external domains or tls internal for private CA use.

example.com {
  tls [email protected]
  root * /var/www/html
  file_server
}

If your deployment must remain offline or internal, use:

example.local {
  tls internal
  root * /var/www/html
  file_server
}

Caddyfile Reverse Proxy Example

To proxy a backend application:

app.example.com {
  reverse_proxy localhost:8080
}

Add secure headers to harden the site:

header {
  Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
  X-Content-Type-Options "nosniff"
  X-Frame-Options "DENY"
  Referrer-Policy "same-origin"
}

Security Hardening and GEO Considerations

For sovereignty, local certificate authorities and region-specific DNS are critical.

  • use tls internal for private networks,
  • use small site blocks for region-specific domains like eu.example.local,
  • disable unnecessary admin access by binding the admin socket only to localhost.

Secure the admin endpoint:

{
  "admin": {
    "listen": ":2019",
    "bind": ["127.0.0.1"]
  }
}

Then ensure /etc/caddy/Caddyfile and /etc/caddy are owned by root:caddy with 640 permissions.

Caddy vs Nginx vs Apache: Web Server Comparison

When choosing a web server for sovereign deployments, trade-offs matter:

FeatureCaddyNginxApache
Automatic HTTPS✅ Built-in ACME❌ Manual config❌ Manual config
ConfigurationSimple, readableComplex, crypticVery verbose
Memory Usage~10-15 MB idle~5-8 MB idle~15-25 MB idle
TLS ManagementZero-config (tls internal)Manual certsManual certs
Reverse ProxyNative, intuitiveNative, powerfulLess intuitive
Learning CurveLowMediumHigh
Suitable for Sovereign✅ Excellent✅ Good✅ Acceptable
2026 SupportVery activeVery activeSlower pace

For new sovereign deployments in 2026: Caddy is optimal due to automatic HTTPS, low complexity, and excellent defaults.

Troubleshooting Common Issues

1. Certificate Renewal Fails with Let’s Encrypt

Symptom: Error: acme: error code 403 "forbidden"

Diagnosis and Fix:

# Check DNS resolution
nslookup yourdomain.com

# Verify firewall allows port 80 (ACME challenge)
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw reload

# Check Caddy logs for renewal issues
sudo journalctl -u caddy.service -n 50

# Force reload
sudo caddy reload --config /etc/caddy/Caddyfile

2. Firewall Blocks Port 80 or 443

Symptom: Connection timeout when accessing HTTPS site, or permission denied

Solution:

# UFW (Ubuntu default firewall)
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw reload

# Verify ports listening
sudo ss -tlnp | grep -E ':(80|443)'

# Expected output should show caddy process listening on both ports

3. DNS Resolution Fails for Internal Domains

Symptom: Failed to resolve example.local or Name does not resolve

Solution for local testing:

# Add hostname to /etc/hosts
sudo bash -c 'echo "127.0.0.1 example.local" >> /etc/hosts'

# Verify DNS
nslookup example.local
dig example.local

4. Caddy Admin API Binding Error

Symptom: Error: failed to listen on [::1]:2019 on startup

Solution:

# Check if port 2019 already in use
sudo lsof -i :2019

# Kill conflicting process if needed
sudo kill -9 <PID>

# Reload Caddy
sudo caddy reload --config /etc/caddy/Caddyfile

5. Permission Denied on /etc/caddy

Symptom: Error: open /etc/caddy/Caddyfile: permission denied

Solution:

# Fix directory and file permissions
sudo chown root:caddy /etc/caddy
sudo chmod 750 /etc/caddy
sudo chown root:caddy /etc/caddy/Caddyfile
sudo chmod 640 /etc/caddy/Caddyfile

# Verify
ls -la /etc/caddy/

6. Caddy Service Won’t Start After Restart

Symptom: systemctl status caddy shows failed or inactive

Diagnosis steps:

# Validate Caddyfile syntax first
sudo caddy validate --config /etc/caddy/Caddyfile

# Check service logs
sudo systemctl status caddy -l
sudo journalctl -u caddy.service --no-pager | tail -30

# Try starting manually to see real error
sudo -u caddy caddy run --config /etc/caddy/Caddyfile

# Re-enable if disabled
sudo systemctl enable caddy
sudo systemctl start caddy

7. TLS Certificate Not Auto-Renewing

Symptom: Certificate expires but Caddy doesn’t renew

Solution:

# Check certificate expiry
openssl s_client -connect localhost:443 -servername yourdomain.com < /dev/null | grep -A 2 "Issuer\|Expire"

# Force renewal by clearing cache
sudo rm -rf /var/lib/caddy
sudo systemctl restart caddy

# Monitor renewal process
sudo journalctl -u caddy.service | grep -i "certificate\|acme\|tls"

8. Syntax Error After Caddyfile Edit

Symptom: Error: parsing... with line number reference

Solution:

# Always validate before reload
sudo caddy validate --config /etc/caddy/Caddyfile

# View file with line numbers to find error
cat -n /etc/caddy/Caddyfile

# Common issues:
# - Missing closing brace }
# - Incorrect indentation in directives
# - Typos in domain names
# - Directives outside proper blocks

Verifying the Setup

Check configuration syntax:

sudo caddy validate --config /etc/caddy/Caddyfile

Test site access locally:

curl -I http://localhost
curl -I https://localhost

If using a public domain, confirm TLS:

curl -I https://example.com

Expected output should include HTTP/2 200 and server: Caddy.

AI Search Optimization and Keywords

Purposefully use search terms relevant to 2026:

  • install Caddy Ubuntu 24.04
  • Caddy auto HTTPS tutorial
  • Caddyfile reverse proxy
  • sovereign Caddy setup

This improves the article for both technical search and AI-assisted discovery.

People Also Ask

How do I install Caddy on Ubuntu 24.04?

Follow the official Cloudsmith repository steps, install the package, and verify with caddy version.

How does Caddy manage TLS automatically?

Caddy uses ACME with Let’s Encrypt for public domains or an internal CA with tls internal for private deployments.

Can I use Caddy for private sovereign networks?

Yes. Use tls internal, local DNS names, and restrict admin API access to maintain a fully local deployment.

Further Reading

Tested on: Ubuntu 24.04 LTS (Hetzner CX22). Last verified: May 2, 2026.

Further Reading

All Dev Corner

Comments