明知山没虎

一个游手好闲的人

Caddy完全实战指南:让HTTPS配置不再是噩梦

2025-12-24

前言

作为一个折腾过各种Web服务器的老司机,我可以很负责任地说:Caddy是我用过最省心的Web服务器

如果你还在为Nginx的SSL证书配置头疼,还在为Apache的复杂配置文件抓狂,那你真该试试Caddy。这货的口号就是"HTTPS by default",自动申请和续期SSL证书,配置文件简单到让人怀疑人生。

今天就来全方位聊聊Caddy,从安装到实战,从基础配置到高级技巧,保证让你用完就回不去了。

Caddy是什么鬼?

核心特性

Caddy最牛逼的地方在于:

  • 自动HTTPS:自动申请、配置、续期SSL证书,完全不用你操心

  • 配置简单:告别Nginx那种鬼画符一样的配置文件

  • HTTP/2支持:开箱即用,不需要额外配置

  • 反向代理:内置支持,配置超级简单

  • 插件系统:功能扩展灵活

  • 零停机重载:配置修改后无需重启

与竞品对比

特性

Caddy

Nginx

Apache

Traefik

自动HTTPS

配置复杂度

极简

复杂

复杂

中等

性能

优秀

极佳

良好

优秀

内存占用

极低

中等

学习成本

极低

中等

生态成熟度

新兴

成熟

成熟

新兴

容器友好度

极佳

良好

一般

极佳

简单总结

  • Nginx:性能之王,但配置复杂,SSL证书管理是噩梦

  • Apache:老牌选手,功能全面但笨重,配置更复杂

  • Traefik:容器时代的新贵,服务发现牛逼,但主要针对容器环境

  • Caddy:新手友好,HTTPS自动化,配置简单,但生态相对较新

Ubuntu上安装Caddy

方法一:官方仓库安装(推荐)

# 添加官方仓库
sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https
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

方法二:下载二进制文件

# 下载最新版本(以2.7.6为例)
wget https://github.com/caddyserver/caddy/releases/download/v2.7.6/caddy_2.7.6_linux_amd64.tar.gz

# 解压并安装
tar -xzf caddy_2.7.6_linux_amd64.tar.gz
sudo mv caddy /usr/local/bin/
sudo chmod +x /usr/local/bin/caddy

# 创建用户和目录
sudo groupadd --system caddy
sudo useradd --system --gid caddy --create-home --home-dir /var/lib/caddy --shell /usr/sbin/nologin caddy

# 创建配置目录
sudo mkdir -p /etc/caddy

方法三:使用Snap

sudo snap install caddy

验证安装

caddy version

如果看到版本信息,说明安装成功。

基础配置详解

Caddyfile语法基础

Caddy的配置文件叫Caddyfile,语法简单到令人发指:

# 最简单的静态站点
example.com {
    root * /var/www/html
    file_server
}

就这三行,你就有了一个启用HTTPS的静态网站!

配置文件位置

  • 系统级配置/etc/caddy/Caddyfile

  • 用户级配置~/.config/caddy/Caddyfile

  • 当前目录./Caddyfile

基本语法规则

# 站点块
site.com {
    # 指令1
    # 指令2
}

# 全局选项
{
    # 全局配置
}

# 代码片段(可复用)
(snippet) {
    # 可复用的配置块
}

实战案例集锦

案例1:静态网站托管

# /etc/caddy/Caddyfile
blog.example.com {
    root * /var/www/blog
    file_server
    
    # 启用gzip压缩
    encode gzip
    
    # 自定义404页面
    handle_errors {
        @404 {
            expression {http.error.status_code} == 404
        }
        rewrite @404 /404.html
        file_server
    }
    
    # 缓存静态资源
    @static {
        file
        path *.css *.js *.png *.jpg *.gif *.ico *.woff *.woff2
    }
    header @static Cache-Control max-age=31536000
}

案例2:反向代理

# API服务反向代理
api.example.com {
    reverse_proxy localhost:3000
    
    # 健康检查
    reverse_proxy localhost:3000 {
        health_uri /health
        health_interval 30s
    }
}

# 多个后端负载均衡
app.example.com {
    reverse_proxy localhost:3000 localhost:3001 localhost:3002 {
        # 负载均衡策略
        lb_policy round_robin
        
        # 健康检查
        health_uri /health
        health_interval 10s
        health_timeout 5s
    }
}

案例3:PHP应用(WordPress等)

wordpress.example.com {
    root * /var/www/wordpress
    
    # PHP-FPM配置
    php_fastcgi unix//run/php/php8.1-fpm.sock
    
    # WordPress美化URL
    @wordpress {
        file {
            try_files {path} {path}/ /index.php?{query}
        }
    }
    rewrite @wordpress {http.matchers.file.relative}
    
    # 安全配置
    @forbidden {
        path *.sql *.zip *.tar.gz
    }
    respond @forbidden 403
    
    # 文件服务器
    file_server
}

案例4:SPA应用(Vue/React等)

spa.example.com {
    root * /var/www/spa/dist
    
    # 尝试文件,如果不存在则返回index.html(SPA路由)
    try_files {path} /index.html
    
    # 启用压缩
    encode gzip
    
    # API代理
    handle /api/* {
        reverse_proxy localhost:3000
    }
    
    file_server
}

案例5:多域名配置

# 主站
example.com, www.example.com {
    redir https://example.com{uri} permanent
}

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

# 子域名
*.example.com {
    @blog host blog.example.com
    handle @blog {
        root * /var/www/blog
        file_server
    }
    
    @api host api.example.com
    handle @api {
        reverse_proxy localhost:3000
    }
    
    # 默认处理
    respond "Subdomain not found" 404
}

案例6:HTTPS重定向和安全配置

# 全局配置
{
    # 自定义ACME CA(可选)
    acme_ca https://acme-v02.api.letsencrypt.org/directory
    
    # 邮箱(用于Let's Encrypt通知)
    email admin@example.com
}

# HTTP自动重定向到HTTPS
http://example.com {
    redir https://example.com{uri} permanent
}

https://example.com {
    root * /var/www/html
    
    # 安全头
    header {
        # HSTS
        Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
        
        # XSS保护
        X-Content-Type-Options nosniff
        X-Frame-Options DENY
        X-XSS-Protection "1; mode=block"
        
        # CSP
        Content-Security-Policy "default-src 'self'"
        
        # 移除服务器信息
        -Server
    }
    
    file_server
}

高级特性深度解析

1. 自动HTTPS工作原理

Caddy的自动HTTPS基于Let's Encrypt,工作流程:

  1. 域名验证:使用ACME协议进行域名所有权验证

  2. 证书申请:自动向Let's Encrypt申请SSL证书

  3. 证书安装:自动配置SSL证书

  4. 自动续期:证书到期前自动续期

# 自定义ACME设置
{
    acme_ca https://acme-v02.api.letsencrypt.org/directory
    acme_ca_root /path/to/ca-cert.pem
    email your-email@example.com
}

2. 模块系统

Caddy采用模块化架构,可以通过插件扩展功能:

# 查看已安装模块
caddy list-modules

# 使用xcaddy构建自定义版本
go install github.com/caddyserver/xcaddy/cmd/xcaddy@latest

# 构建包含插件的Caddy
xcaddy build \
    --with github.com/caddy-dns/cloudflare \
    --with github.com/mholt/caddy-webdav

3. API管理

Caddy提供强大的API来动态管理配置:

# 启用管理API
caddy run --config /etc/caddy/Caddyfile --adapter caddyfile

# 获取当前配置
curl localhost:2019/config/

# 动态添加站点
curl -X POST "localhost:2019/load" \
    -H "Content-Type: text/caddyfile" \
    --data-binary @new-site.caddyfile

4. 日志配置

{
    log {
        output file /var/log/caddy/access.log {
            roll_size 100mb
            roll_keep 10
        }
        format json
    }
}

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

性能优化技巧

1. 启用HTTP/2推送

example.com {
    root * /var/www/html
    
    # HTTP/2服务器推送
    push /css/style.css
    push /js/app.js
    
    file_server
}

2. 缓存配置

example.com {
    root * /var/www/html
    
    # 静态资源缓存
    @static {
        file
        path *.css *.js *.png *.jpg *.gif *.ico *.woff *.woff2
    }
    header @static {
        Cache-Control "public, max-age=31536000, immutable"
        ETag
    }
    
    # HTML文件缓存
    @html {
        file
        path *.html
    }
    header @html Cache-Control "public, max-age=3600"
    
    file_server
}

3. 压缩配置

example.com {
    root * /var/www/html
    
    # 自定义压缩配置
    encode {
        gzip 6
        minimum_length 1024
        match {
            header Content-Type text/*
            header Content-Type application/json
            header Content-Type application/javascript
            header Content-Type application/xhtml+xml
            header Content-Type application/atom+xml
            header Content-Type image/svg+xml
        }
    }
    
    file_server
}

4. 连接复用

{
    servers {
        listener_wrappers {
            http_redirect
        }
        idle_timeout 30s
        read_timeout 10s
        write_timeout 10s
    }
}

监控和运维

1. 服务管理

# 启动Caddy服务
sudo systemctl start caddy

# 开机自启
sudo systemctl enable caddy

# 查看状态
sudo systemctl status caddy

# 重新加载配置
sudo systemctl reload caddy

# 查看日志
sudo journalctl -u caddy -f

2. 配置验证

# 验证配置文件语法
caddy validate --config /etc/caddy/Caddyfile

# 测试配置并显示最终配置
caddy adapt --config /etc/caddy/Caddyfile

3. 健康检查

example.com {
    # 健康检查端点
    handle /health {
        respond "OK" 200
    }
    
    # 指标端点(配合Prometheus使用)
    handle /metrics {
        metrics
    }
    
    reverse_proxy localhost:3000
}

4. 日志分析

# 安装日志分析工具
sudo apt install goaccess

# 分析访问日志
goaccess /var/log/caddy/access.log -o /var/www/html/report.html --log-format=CADDY

安全最佳实践

1. SSL/TLS配置强化

{
    # 全局TLS配置
    tls {
        protocols tls1.2 tls1.3
        ciphers TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
    }
}

example.com {
    # 站点级TLS配置
    tls {
        protocols tls1.3
    }
    
    root * /var/www/html
    file_server
}

2. 访问控制

admin.example.com {
    # IP白名单
    @allowed {
        remote_ip 192.168.1.0/24 10.0.0.0/8
    }
    
    # 基本认证
    basicauth @allowed {
        admin $2a$14$Zkx19XLiW6VYouLHR5NmfOFU0z2GTNqq9qfyXpA/U6Dj5eLQVTnOm
    }
    
    reverse_proxy localhost:3000
}

3. 防火墙配置

# UFW配置
sudo ufw allow ssh
sudo ufw allow http
sudo ufw allow https
sudo ufw enable

# 或者使用iptables
sudo iptables -A INPUT -p tcp --dport 80 -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 443 -j ACCEPT

容器化部署

Docker Compose示例

version: '3.8'

services:
  caddy:
    image: caddy:2-alpine
    container_name: caddy
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile
      - ./site:/srv
      - caddy_data:/data
      - caddy_config:/config
    environment:
      - ACME_AGREE=true

  app:
    image: nginx:alpine
    container_name: app
    restart: unless-stopped
    volumes:
      - ./html:/usr/share/nginx/html

volumes:
  caddy_data:
  caddy_config:

对应的Caddyfile:

example.com {
    reverse_proxy app:80
}

static.example.com {
    root * /srv
    file_server
}

故障排查指南

常见问题及解决方案

1. SSL证书申请失败

# 检查域名DNS解析
nslookup example.com

# 检查80端口是否开放
sudo netstat -tlnp | grep :80

# 查看详细错误日志
sudo journalctl -u caddy -f

2. 配置文件语法错误

# 验证配置
caddy validate --config /etc/caddy/Caddyfile

# 格式化配置文件
caddy fmt --overwrite /etc/caddy/Caddyfile

3. 反向代理连接失败

# 检查后端服务状态
curl localhost:3000

# 检查网络连接
telnet localhost 3000

4. 性能问题

# 检查进程资源使用
top -p $(pgrep caddy)

# 分析访问日志
tail -f /var/log/caddy/access.log

迁移指南

从Nginx迁移

Nginx配置:

server {
    listen 80;
    server_name example.com;
    return 301 https://$server_name$request_uri;
}

server {
    listen 443 ssl http2;
    server_name example.com;
    
    ssl_certificate /path/to/cert.pem;
    ssl_certificate_key /path/to/key.pem;
    
    location / {
        proxy_pass http://localhost:3000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

对应的Caddy配置:

example.com {
    reverse_proxy localhost:3000
}

是不是简单到令人发指?

从Apache迁移

Apache配置:

<VirtualHost *:80>
    ServerName example.com
    DocumentRoot /var/www/html
    
    RewriteEngine On
    RewriteCond %{HTTPS} off
    RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
</VirtualHost>

<VirtualHost *:443>
    ServerName example.com
    DocumentRoot /var/www/html
    
    SSLEngine on
    SSLCertificateFile /path/to/cert.pem
    SSLCertificateKeyFile /path/to/key.pem
</VirtualHost>

对应的Caddy配置:

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

总结

Caddy的优势总结:

适合使用Caddy的场景

  • 新项目:配置简单,上手快

  • 小型网站:功能够用,维护简单

  • 容器环境:云原生友好

  • 个人项目:免费SSL证书,省心省力

  • API网关:反向代理配置简单

不太适合的场景

  • 超高并发:性能不如Nginx(虽然差距在缩小)

  • 复杂配置:某些高级功能可能需要插件

  • 企业环境:生态成熟度相对较低

最佳实践建议

  1. 配置文件管理:使用版本控制管理Caddyfile

  2. 监控告警:配置日志监控和SSL证书到期提醒

  3. 备份策略:定期备份配置和SSL证书数据

  4. 安全加固:定期更新版本,配置防火墙

  5. 性能测试:在生产环境前进行压力测试

Caddy真的是个好东西,特别是对于不想在Web服务器配置上浪费时间的开发者。自动HTTPS、简单配置、零停机重载,这些特性让运维工作轻松不少。

虽然在极高并发场景下可能不如Nginx,但对于大多数应用来说,Caddy的性能完全够用,而且能大大降低配置和维护成本。

如果你还在纠结用什么Web服务器,不妨试试Caddy,说不定会让你爱上它的简洁和强大。