跳转至

第五章:自动 HTTPS

Caddy 最引人注目的特性是自动 HTTPS,本章详细介绍其工作原理和配置方法。

自动 HTTPS 概述

工作原理

┌─────────────────────────────────────────────────┐
│              Caddy 自动 HTTPS 流程               │
├─────────────────────────────────────────────────┤
│                                                 │
│  1. 检测域名配置                                 │
│     └─ Caddyfile 中的域名                        │
│                                                 │
│  2. 自动申请证书                                 │
│     └─ 向 Let's Encrypt 申请                     │
│                                                 │
│  3. 验证域名所有权                               │
│     ├─ HTTP-01 验证(默认)                      │
│     └─ DNS-01 验证(通配符证书)                  │
│                                                 │
│  4. 自动续期                                     │
│     └─ 证书到期前自动续期                         │
│                                                 │
│  5. 自动重定向                                   │
│     └─ HTTP → HTTPS                              │
│                                                 │
└─────────────────────────────────────────────────┘

自动获取证书的条件

Caddy 会自动为满足以下条件的域名获取证书:

  1. 域名不是 localhost
  2. 域名不是 IP 地址
  3. 端口是 80 或 443
  4. 未显式禁用 TLS
  5. 未手动指定证书

基本配置

最简 HTTPS

example.com {
    reverse_proxy localhost:8000
}

Caddy 会自动: - 申请 Let's Encrypt 证书 - 配置 HTTPS - 将 HTTP 重定向到 HTTPS

指定邮箱

{
    email admin@example.com
}

example.com {
    reverse_proxy localhost:8000
}

邮箱用于: - Let's Encrypt 账户注册 - 证书到期提醒

验证方式

HTTP-01 验证(默认)

example.com {
    reverse_proxy localhost:8000
}

要求: - 域名解析到服务器 - 80 端口可访问

DNS-01 验证

适用于: - 内网环境 - 通配符证书 - 80 端口不可用

需要配置 DNS 提供商:

{
    email admin@example.com
    acme_ca https://acme-v02.api.letsencrypt.org/directory
}

*.example.com {
    tls {
        dns cloudflare {env.CLOUDFLARE_API_TOKEN}
    }
    reverse_proxy localhost:8000
}

支持的 DNS 提供商

Caddy 支持众多 DNS 提供商:

提供商 模块名称
Cloudflare cloudflare
Aliyun (阿里云) alidns
Tencent Cloud (腾讯云) tencentcloud
DNSPod dnspod
Godaddy godaddy
AWS Route 53 route53
Azure DNS azure

安装 DNS 插件

# 使用 xcaddy 构建带插件的 Caddy
xcaddy build --with github.com/caddy-dns/cloudflare

阿里云 DNS 示例

*.example.com {
    tls {
        dns alidns {
            access_key_id {env.ALIYUN_ACCESS_KEY_ID}
            access_key_secret {env.ALIYUN_ACCESS_KEY_SECRET}
        }
    }
    reverse_proxy localhost:8000
}

腾讯云 DNS 示例

*.example.com {
    tls {
        dns tencentcloud {
            secret_id {env.TENCENT_SECRET_ID}
            secret_key {env.TENCENT_SECRET_KEY}
        }
    }
    reverse_proxy localhost:8000
}

通配符证书

# 通配符证书需要 DNS 验证
*.example.com {
    tls {
        dns cloudflare {env.CLOUDFLARE_API_TOKEN}
    }
    reverse_proxy localhost:8000
}

多域名证书

example.com, www.example.com, api.example.com {
    reverse_proxy localhost:8000
}

自签名证书

开发环境

localhost {
    tls internal
    reverse_proxy localhost:3000
}

内网环境

internal.example.com {
    tls internal
    reverse_proxy 192.168.1.100:8000
}

自定义 CA

{
    local_certs
}

dev.local {
    tls internal
    reverse_proxy localhost:3000
}

手动证书

使用自己的证书:

example.com {
    tls /etc/ssl/certs/example.com.crt /etc/ssl/private/example.com.key
    reverse_proxy localhost:8000
}

证书链

example.com {
    # 证书文件包含完整证书链
    tls /etc/ssl/example.com/fullchain.pem /etc/ssl/example.com/privkey.pem
    reverse_proxy localhost:8000
}

TLS 配置

协议版本

example.com {
    tls {
        protocols tls1.2 tls1.3
    }
    reverse_proxy localhost:8000
}

密码套件

example.com {
    tls {
        ciphers TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
    }
    reverse_proxy localhost:8000
}

曲线设置

example.com {
    tls {
        curves x25519 secp256r1 secp384r1
    }
    reverse_proxy localhost:8000
}

证书管理

查看证书

# 列出证书
caddy list-certificates

# 查看证书详情
caddy trust

证书存储

证书默认存储在:

/var/lib/caddy/.local/share/caddy/certificates/
├── acme-v02.api.letsencrypt.org-directory/
│   ├── example.com/
│   │   ├── example.com.crt
│   │   └── example.com.key
│   └── www.example.com/
│       ├── www.example.com.crt
│       └── www.example.com.key

证书续期

Caddy 自动续期,证书到期前 30 天自动续期。

手动触发续期:

caddy reload --config /etc/caddy/Caddyfile

HTTP 重定向

Caddy 自动将 HTTP 重定向到 HTTPS:

# 自动行为
# http://example.com → https://example.com

自定义重定向

example.com {
    # 禁用自动 HTTPS
    tls off

    redir https://{host}{uri} permanent
}

保留 HTTP

http://example.com {
    reverse_proxy localhost:8000
}

https://example.com {
    reverse_proxy localhost:8000
}

测试环境

使用 Let's Encrypt 测试环境:

{
    acme_ca https://acme-staging-v02.api.letsencrypt.org/directory
}

test.example.com {
    reverse_proxy localhost:8000
}

测试环境特点: - 证书不被浏览器信任 - 无速率限制 - 用于测试配置

常见问题

证书申请失败

检查项:

  1. 域名解析是否正确
  2. 80 端口是否可访问
  3. 防火墙是否放行
  4. 是否达到速率限制
# 检查端口
sudo netstat -tlnp | grep -E '80|443'

# 检查防火墙
sudo ufw status

内网环境

# 使用自签名证书
internal.example.local {
    tls internal
    reverse_proxy localhost:8000
}

端口限制

如果 80/443 端口不可用:

:8443 {
    tls internal
    reverse_proxy localhost:8000
}

完整配置示例

生产环境

{
    email admin@example.com
}

example.com, www.example.com {
    tls {
        dns cloudflare {env.CLOUDFLARE_API_TOKEN}
    }

    # HSTS
    header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"

    reverse_proxy localhost:8000
}

api.example.com {
    tls {
        dns cloudflare {env.CLOUDFLARE_API_TOKEN}
    }

    reverse_proxy localhost:8001
}

开发环境

{
    local_certs
}

localhost {
    tls internal
    reverse_proxy localhost:3000
}

dev.localhost {
    tls internal
    reverse_proxy localhost:3001
}

*.test.localhost {
    tls internal
    reverse_proxy localhost:3002
}

混合配置

{
    email admin@example.com
}

# 公网域名 - 自动证书
example.com {
    reverse_proxy localhost:8000
}

# 内网域名 - 自签名
internal.example.com {
    tls internal
    reverse_proxy 192.168.1.100:8000
}

# 本地开发
localhost {
    tls internal
    reverse_proxy localhost:3000
}

小结

本章介绍了 Caddy 自动 HTTPS 的核心功能:

  • 自动申请和续期 Let's Encrypt 证书
  • 支持 HTTP-01 和 DNS-01 验证
  • 通配符证书配置
  • 开发环境自签名证书
  • 灵活的 TLS 配置选项

Caddy 的自动 HTTPS 功能大大简化了 Web 服务器的配置工作,让开发者可以专注于应用本身。