How7o
  • Home
  • Tools
  • Prank Screens
  • Learn
  • Blog
  • Contact
Reading: How to Install Caddy Server on Ubuntu (Automatic HTTPS, Drop-in nginx Alternative)
Share
How7oHow7o
Font ResizerAa
  • OS
Search
  • Home
  • Tools
  • Prank Screens
  • Learn
  • Blog
  • Contact
Follow US
© 2024–2026 How7o. All rights reserved.
How7o > Free Laravel, PHP, WordPress & Server Tutorials > Server Management > How to Install Caddy Server on Ubuntu (Automatic HTTPS, Drop-in nginx Alternative)
Server Management

How to Install Caddy Server on Ubuntu (Automatic HTTPS, Drop-in nginx Alternative)

how7o
By how7o
Last updated: May 24, 2026
8 Min Read
Caddy server — automatic HTTPS, 3-line Caddyfile vs 25-line nginx config
SHARE

Caddy is a modern web server written in Go, with one defining feature: automatic HTTPS. You write a domain name in the config, Caddy provisions a Let’s Encrypt certificate, renews it forever, redirects HTTP to HTTPS, and stays out of your way. No certbot, no separate renewal cron, no certificate copying. This guide shows how to install Caddy on Ubuntu, write a Caddyfile that handles the three most common patterns (static site, reverse proxy, PHP-FPM), and migrate a typical nginx config across.

Contents
  • TL;DR
  • When Caddy beats nginx (and when it doesn’t)
  • Step 1 — Install Caddy from the official apt repo
  • Step 2 — Write the Caddyfile
  • Migrating from nginx (line-by-line comparison)
  • Logs and observability
  • Troubleshooting
    • “Caddy can’t get a certificate”
    • “Caddyfile reload fails after my edit”
    • “PHP-FPM site shows ‘File not found’ errors”
  • Related guides

TL;DR

Add the Caddy apt repo, sudo apt install caddy, edit /etc/caddy/Caddyfile, write one line per site (example.com { reverse_proxy localhost:3000 }), sudo systemctl reload caddy. HTTPS appears automatically within 30 seconds. Logs at journalctl -u caddy.

When Caddy beats nginx (and when it doesn’t)

  • Caddy wins for: small-to-medium sites, hobby self-hosting, dev environments, anywhere you’d rather not write 40 lines of nginx config + certbot dance for a single hostname. Auto-HTTPS is genuinely magic.
  • nginx still wins for: very high-traffic sites (Caddy is fast, but nginx’s tuning is better-documented at the bleeding edge), complex routing requirements, environments with hard nginx expertise on the team, and any setup that requires modules nginx has been compiling for fifteen years (e.g. ngx_brotli, ngx_pagespeed).

Step 1 — Install Caddy from the official apt repo

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

Caddy starts immediately and serves a placeholder page on port 80. Confirm:

sudo systemctl status caddy
caddy version

Step 2 — Write the Caddyfile

sudo nano /etc/caddy/Caddyfile

A Caddyfile for three different patterns:

# Static site
example.com {
    root * /var/www/example.com
    file_server
    encode gzip zstd
}

# Reverse proxy to a Node app
api.example.com {
    reverse_proxy localhost:3000
}

# PHP-FPM site (Laravel, WordPress)
blog.example.com {
    root * /var/www/blog/public
    php_fastcgi unix//run/php/php8.4-fpm.sock
    file_server
}

That’s the entire config — three sites, full HTTPS. Caddy provisions Let’s Encrypt certificates for each hostname, redirects HTTP to HTTPS, terminates TLS, enables gzip + zstd compression, and proxies to the right backend. There is no separate cert config, no rewrite block, no listen 443 ssl directive. Reload:

sudo systemctl reload caddy

Within 30 seconds, all three hostnames are HTTPS. Watch the magic in real time:

journalctl -u caddy -f
Caddy request flow — automatic ACME, TLS termination, ingress to static files / Node / PHP-FPM

Migrating from nginx (line-by-line comparison)

A typical nginx config for a reverse-proxied app with HTTPS:

# nginx — ~25 lines
server {
    listen 80;
    server_name api.example.com;
    return 301 https://$host$request_uri;
}
server {
    listen 443 ssl http2;
    server_name api.example.com;

    ssl_certificate /etc/letsencrypt/live/api.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/api.example.com/privkey.pem;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers HIGH:!aNULL:!MD5;

    location / {
        proxy_pass http://localhost:3000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

The same thing in a Caddyfile:

# Caddy — 3 lines
api.example.com {
    reverse_proxy localhost:3000
}

Caddy’s reverse_proxy directive sets all the standard proxy headers automatically. HTTPS, redirects, certificate management — all defaults.

Logs and observability

Caddy logs go to systemd-journald by default. Tail with:

journalctl -u caddy -f

For per-site access logs, add an explicit block:

example.com {
    root * /var/www/example.com
    file_server
    log {
        output file /var/log/caddy/example.com.log
        format json
    }
}

Troubleshooting

“Caddy can’t get a certificate”

Almost always DNS or firewall. Caddy uses HTTP-01 challenge by default, which means Let’s Encrypt connects to your server on port 80. Your domain must resolve to the server’s public IP, and the server must accept inbound TCP 80 from the internet. journalctl -u caddy shows the exact ACME error.

“Caddyfile reload fails after my edit”

Validate syntax before reloading: caddy validate --config /etc/caddy/Caddyfile. Common mistakes are missing closing braces and indentation that confuses the parser (Caddy doesn’t enforce indentation but mixed tabs and spaces can cause issues).

“PHP-FPM site shows ‘File not found’ errors”

The socket path varies by PHP version: /run/php/php8.4-fpm.sock on Ubuntu 24.04 with PHP 8.4. Check what’s actually there: ls /run/php/. Update the php_fastcgi directive to match.

Does Caddy support HTTP/3?

Yes, out of the box on Caddy 2.6+. HTTP/3 is enabled by default for HTTPS sites; clients that support it (Chrome, Firefox, Safari 14+) negotiate up to HTTP/3 automatically. You’ll see the protocol in browser DevTools’ Network tab.

Can I use Caddy as a load balancer?

Yes. The reverse_proxy directive accepts multiple upstreams: reverse_proxy localhost:3000 localhost:3001 localhost:3002. Default load-balancing policy is round-robin; you can switch to least-connections, IP-hash, or weighted with one extra line. For complex L7 load balancing, HAProxy or nginx remain the experts.

Will Caddy work behind Cloudflare?

Yes, but you need to enable the Real-IP plugin so Caddy sees the original client IP from Cloudflare’s CF-Connecting-IP header instead of treating every request as coming from Cloudflare’s edge IPs. Add servers { trusted_proxies cloudflare } to the Caddyfile.

Can I migrate certificates from certbot to Caddy?

Don’t migrate — let Caddy provision its own. Caddy stores certificates in /var/lib/caddy/.local/share/caddy/certificates/ separately from certbot’s /etc/letsencrypt/. The first time you start Caddy for a hostname, it provisions fresh — takes about 30 seconds. Your existing certbot certs stay in place until you uninstall certbot.

Does Caddy support custom rate limiting?

Not in the standard build — rate limiting requires a plugin. Caddy is modular: build with extra modules via xcaddy, or use Caddy plus an external rate-limiter like Varnish. For typical hobby use, Cloudflare’s free rate-limit rules in front of Caddy are usually enough.

How does Caddy’s performance compare to nginx?

Within 10-15% on most workloads, with Caddy slightly behind on raw requests-per-second at extreme load. For sites under 10K requests/sec, the difference is invisible. The performance gap closes further with HTTP/3 enabled, where Caddy is on par or ahead of nginx because nginx’s HTTP/3 support is newer and less optimised. Pick based on config simplicity, not benchmarks.

Related guides

  • Install Apache on Ubuntu — the other major web-server alternative.
  • nginx reverse proxy for Node.js — the traditional setup Caddy simplifies.
  • Let’s Encrypt with Certbot — the manual certificate flow Caddy replaces.
  • Configure nginx for WordPress — for the nginx side of the comparison.

Caddy’s full documentation is at caddyserver.com/docs, including the Caddyfile reference and the JSON config API.

TAGGED:configurationinstallationNginxperformanceUbuntu

Sign Up For Daily Newsletter

Be keep up! Get the latest breaking news delivered straight to your inbox.
[mc4wp_form]
By signing up, you agree to our Terms of Use and acknowledge the data practices in our Privacy Policy. You may unsubscribe at any time.
Share This Article
Facebook Copy Link Print
Previous Article Cloudflare Tunnel — outbound-only connection from server, no inbound port forward How to Install Cloudflare Tunnel on Ubuntu (Expose Local Services, No Port Forwarding)
Next Article Tailscale mesh — peer-to-peer connections between devices, coordination server How to Install Tailscale on Ubuntu (Zero-Config Mesh VPN for Self-Hosters)
Leave a Comment

Leave a Reply Cancel reply

You must be logged in to post a comment.

FacebookLike
XFollow
PinterestPin
InstagramFollow
Most Popular
Bun runtime — faster JS toolkit replacing npm in Laravel projects
How to Install Bun Runtime on Ubuntu (And Use It in a Laravel Project)
May 24, 2026
Tailscale mesh — peer-to-peer connections between devices, coordination server
How to Install Tailscale on Ubuntu (Zero-Config Mesh VPN for Self-Hosters)
May 24, 2026
Caddy server — automatic HTTPS, 3-line Caddyfile vs 25-line nginx config
How to Install Caddy Server on Ubuntu (Automatic HTTPS, Drop-in nginx Alternative)
May 24, 2026
Cloudflare Tunnel — outbound-only connection from server, no inbound port forward
How to Install Cloudflare Tunnel on Ubuntu (Expose Local Services, No Port Forwarding)
May 24, 2026
WireGuard encrypted tunnel between server and clients with lock icons
How to Set Up WireGuard VPN on Ubuntu (Server, Linux Client, and iOS)
May 24, 2026

You Might Also Like

Install Composer on Ubuntu — terminal with composer-setup.php and PHP elephant icon
Web Development

How to Install Composer on Ubuntu: Step-by-Step Guide

8 Min Read
Comment in a .gitignore file with the # character
Web Development

How to Comment in a .gitignore File

4 Min Read
WooCommerce product view counter — meta-based counter with increment and display hooks
Web Development

How to Display a Product View Counter in WooCommerce Without a Plugin

7 Min Read
Check if GD library is installed in PHP (phpinfo and extension_loaded)
Web Development

How to Check if GD Library Is Installed in PHP (3 Easy Methods)

5 Min Read
How7o

We provide tips, tricks, and advice for improving websites and doing better search.

Tools

  • Age Calculator
  • Word Counter
  • Image Upscaler
  • Password Generator
  • QR Code Generator
  • See all tools→

Pranks

  • Fake Blue Screen Prank
  • Hacker Typer
  • Fake iMessage Generator
  • Windows XP Crash Prank
  • Windows 11 Update Prank
  • See all prank screens →

Company

  • About Us
  • Blog
  • Contact
  • Privacy Policy
  • Terms of Service
  • Sitemap
© 2024–2026 How7o. All rights reserved.
Welcome Back!

Sign in to your account

Username or Email Address
Password

Lost your password?