Caddy 配置基础 #

Caddyfile 概述 #

Caddyfile 是 Caddy 的配置文件,使用简洁直观的 DSL(领域特定语言)语法。相比 Nginx 或 Apache 的配置文件,Caddyfile 更加简洁易读。

基本结构 #

caddyfile
# 全局选项块(可选)
{
    email admin@example.com
    debug
}

# 站点块
example.com {
    # 指令
    root * /var/www/html
    file_server
}

# 另一个站点块
sub.example.com {
    reverse_proxy localhost:3000
}

全局选项块 #

全局选项块位于文件顶部,影响所有站点:

caddyfile
{
    # 管理员邮箱(用于 Let's Encrypt)
    email admin@example.com
    
    # 调试模式
    debug
    
    # 日志格式
    log {
        output file /var/log/caddy/global.log
        format json
    }
    
    # 存储配置
    storage file_system {
        root /var/lib/caddy
    }
    
    # 证书颁发机构
    acme_ca https://acme-v02.api.letsencrypt.org/directory
    
    # 本地开发使用测试 CA
    # acme_ca https://acme-staging-v02.api.letsencrypt.org/directory
}

常用全局选项 #

选项 说明 示例
email ACME 账户邮箱 email admin@example.com
debug 启用调试日志 debug
admin 管理 API 配置 admin offadmin :2019
log 全局日志配置 log { output file /var/log/caddy.log }
storage 证书存储后端 storage file_system { root /data }
acme_ca ACME CA 地址 acme_ca https://acme-v02.api.letsencrypt.org/directory

站点地址 #

站点地址定义了服务器监听的地址:

caddyfile
# 域名(自动 HTTPS)
example.com { }

# 多个域名(共享配置)
example.com, www.example.com { }

# 通配符域名
*.example.com { }

# 端口指定
example.com:8080 { }

# 仅 HTTP(本地开发)
:80 { }
:8080 { }

# 本地地址
localhost { }
127.0.0.1 { }

# 所有接口
: { }

地址格式说明 #

格式 说明 HTTPS
example.com 域名 ✅ 自动
example.com:8080 带端口域名 ❌ 需手动
:80 仅端口 ❌ 无
localhost 本地地址 ⚠️ 自签名
*.example.com 通配符域名 ✅ DNS 验证

指令(Directives) #

指令是 Caddyfile 的核心,定义了如何处理请求:

常用指令概览 #

caddyfile
example.com {
    # 根目录
    root * /var/www/html
    
    # 静态文件服务
    file_server
    
    # 反向代理
    reverse_proxy localhost:3000
    
    # 压缩
    encode gzip zstd
    
    # 日志
    log {
        output file /var/log/caddy/access.log
    }
    
    # 基础认证
    basicauth {
        admin $2a$14$Zkx...
    }
    
    # 响应
    respond "Hello, World!"
    
    # 重写
    rewrite * /index.html
    
    # 重定向
    redir https://example.com{uri}
    
    # 模板
    templates
    
    # 头部操作
    header {
        X-Custom-Header "value"
        -Server
    }
}

指令执行顺序 #

Caddy 按照特定顺序执行指令:

text
1. log          - 日志记录
2. header       - 头部操作
3. encode       - 编码压缩
4. rewrite      - URL 重写
5. redir        - 重定向
6. handle       - 条件处理
7. handle_path  - 带路径剥离的处理
8. route        - 自定义顺序
9. basicauth    - 基础认证
10. request_body- 请求体处理
11. reverse_proxy- 反向代理
12. php_fastcgi - PHP FastCGI
13. file_server - 静态文件服务
14. templates   - 模板处理
15. respond     - 直接响应

自定义执行顺序 #

使用 route 指令自定义顺序:

caddyfile
example.com {
    route {
        # 按照书写顺序执行
        header X-Custom "value"
        rewrite * /index.html
        file_server
    }
}

匹配器(Matchers) #

匹配器用于精确控制指令应用于哪些请求:

匹配器语法 #

caddyfile
# 命名匹配器
@name {
    # 匹配条件
}

# 使用匹配器
directive @name {
    # 配置
}

# 内联匹配器
directive /path {
    # 配置
}

路径匹配器 #

caddyfile
example.com {
    # 精确路径
    @exact path /exact
    
    # 路径前缀
    @prefix path /api/*
    
    # 多个路径
    @multiple path /api/* /admin/*
    
    # 路径后缀
    @static path *.css *.js *.png
    
    # 使用
    header @static Cache-Control "public, max-age=31536000"
}

方法匹配器 #

caddyfile
example.com {
    # 单个方法
    @get method GET
    
    # 多个方法
    @api method GET POST PUT DELETE
    
    # 使用
    respond @get "GET request"
}

主机匹配器 #

caddyfile
example.com {
    # 单个主机
    @api host api.example.com
    
    # 多个主机
    @subdomains host sub1.example.com sub2.example.com
    
    # 通配符
    @wildcard host *.example.com
}

头部匹配器 #

caddyfile
example.com {
    # 检查头部存在
    @hasHeader header Content-Type
    
    # 检查头部值
    @json header Content-Type application/json
    
    # 正则匹配
    @mobile header User-Agent *Mobile*
    
    # 使用
    respond @json "JSON request"
}

查询参数匹配器 #

caddyfile
example.com {
    # 检查参数存在
    @hasParam query param
    
    # 检查参数值
    @search query q=*keyword*
    
    # 多个参数
    @api query version=v1 type=json
    
    # 使用
    respond @search "Search query"
}

表达式匹配器 #

caddyfile
example.com {
    # 使用 CEL 表达式
    @mobile expression {header.User-Agent} matches 'Mobile'
    
    @admin expression {path} startsWith('/admin') && {method} == 'POST'
    
    @complex expression {
        {path} matches '^/api/v[0-9]+'
        && {header.Content-Type} == 'application/json'
        && {method} in ['GET', 'POST']
    }
    
    # 使用
    respond @mobile "Mobile device"
}

组合匹配器 #

caddyfile
example.com {
    # AND 组合(默认)
    @apiAnd {
        path /api/*
        method GET POST
    }
    
    # OR 组合
    @staticOr {
        path *.css *.js
        path /static/*
    }
    
    # 否定
    @notApi not path /api/*
    
    # 复杂组合
    @complex {
        path /api/*
        not {
            path /api/public/*
        }
        method POST
        header Content-Type application/json
    }
}

处理块(Handle Blocks) #

handle 指令 #

caddyfile
example.com {
    # API 路径
    handle /api/* {
        reverse_proxy localhost:3000
    }
    
    # 静态文件
    handle /static/* {
        root * /var/www/static
        file_server
    }
    
    # 默认处理
    handle {
        root * /var/www/html
        file_server
    }
}

handle_path 指令 #

handle_path 会剥离匹配的路径前缀:

caddyfile
example.com {
    # /api/users -> /users
    handle_path /api/* {
        reverse_proxy localhost:3000
    }
}

handle_errors 指令 #

caddyfile
example.com {
    root * /var/www/html
    file_server
    
    # 错误处理
    handle_errors {
        respond "{http.error.status_code} {http.error.status_text}"
    }
    
    # 特定错误码处理
    handle_errors 404 {
        respond "Page not found" 404
    }
    
    handle_errors 5xx {
        respond "Server error" 500
    }
}

变量 #

内置变量 #

caddyfile
example.com {
    # 常用内置变量
    respond "Host: {host}
URI: {uri}
Path: {path}
Method: {method}
Remote IP: {remote_host}
Scheme: {scheme}
"
}

常用内置变量列表 #

变量 说明 示例
{host} 请求主机 example.com
{uri} 完整 URI /path?query=value
{path} 路径 /path
{query} 查询字符串 query=value
{method} 请求方法 GET
{remote_host} 客户端 IP 192.168.1.1
{scheme} 协议 https
{file} 文件名 index.html
{dir} 目录 /path/to/

自定义变量 #

caddyfile
example.com {
    # 定义变量
    vars {
        siteName "My Site"
        apiVersion "v1"
    }
    
    # 使用变量
    header X-Site-Name {siteName}
    respond "Welcome to {siteName}"
}

环境变量 #

caddyfile
example.com {
    # 使用环境变量
    respond "Domain: {$DOMAIN}"
    
    # 带默认值
    respond "Port: {$PORT:8080}"
}

片段(Snippets) #

定义片段 #

caddyfile
# 定义可复用片段
(ssl) {
    protocols tls1.2 tls1.3
    ciphers TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
}

(logging) {
    log {
        output file /var/log/caddy/access.log
        format json
    }
}

(compression) {
    encode gzip zstd
}

使用片段 #

caddyfile
example.com {
    import ssl
    import logging
    import compression
    
    root * /var/www/html
    file_server
}

sub.example.com {
    import ssl
    import logging
    
    reverse_proxy localhost:3000
}

带参数的片段 #

caddyfile
# 定义带参数片段
(proxy) {
    reverse_proxy {args[0]} {
        header_up Host {host}
        header_up X-Real-IP {remote_host}
    }
}

# 使用
example.com {
    import proxy localhost:3000
}

注释 #

caddyfile
# 这是单行注释

example.com {
    # 注释可以出现在任何位置
    
    root * /var/www/html  # 行尾注释
    
    # file_server  # 注释掉指令
}

配置文件拆分 #

主配置文件 #

caddyfile
# /etc/caddy/Caddyfile
{
    email admin@example.com
}

# 导入站点配置
import sites/*.caddyfile
import sites/*/*.caddyfile

站点配置文件 #

caddyfile
# /etc/caddy/sites/example.caddyfile
example.com {
    root * /var/www/example
    file_server
    encode gzip
}
caddyfile
# /etc/caddy/sites/api.caddyfile
api.example.com {
    reverse_proxy localhost:3000
}

JSON 配置 #

Caddy 原生使用 JSON 配置,Caddyfile 会被转换为 JSON:

查看 JSON 配置 #

bash
# 将 Caddyfile 转换为 JSON
caddy adapt --config Caddyfile

# 保存 JSON 配置
caddy adapt --config Caddyfile --pretty > caddy.json

使用 JSON 配置运行 #

bash
caddy run --config caddy.json

JSON 配置示例 #

json
{
  "apps": {
    "http": {
      "servers": {
        "srv0": {
          "listen": [":443"],
          "routes": [
            {
              "match": [
                {
                  "host": ["example.com"]
                }
              ],
              "handle": [
                {
                  "handler": "subroute",
                  "routes": [
                    {
                      "handle": [
                        {
                          "handler": "file_server",
                          "root": "/var/www/html"
                        }
                      ]
                    }
                  ]
                }
              ],
              "terminal": true
            }
          ]
        }
      }
    }
  }
}

配置验证 #

验证语法 #

bash
# 验证 Caddyfile 语法
caddy validate --config Caddyfile

# 验证并显示 JSON
caddy adapt --config Caddyfile --validate

格式化 Caddyfile #

bash
# 格式化 Caddyfile
caddy fmt --overwrite Caddyfile

# 检查格式
caddy fmt --check Caddyfile

完整示例 #

静态网站 #

caddyfile
example.com {
    root * /var/www/html
    file_server
    encode gzip
    
    log {
        output file /var/log/caddy/access.log
    }
    
    # 自定义错误页面
    handle_errors {
        file_server {
            status 404
        }
    }
}

反向代理 #

caddyfile
example.com {
    reverse_proxy localhost:3000 {
        header_up Host {host}
        header_up X-Real-IP {remote_host}
        header_up X-Forwarded-For {remote_host}
        header_up X-Forwarded-Proto {scheme}
    }
}

多站点配置 #

caddyfile
{
    email admin@example.com
}

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

api.example.com {
    reverse_proxy localhost:3000
}

admin.example.com {
    basicauth {
        admin $2a$14$Zkx...
    }
    reverse_proxy localhost:8080
}

下一步 #

现在你已经掌握了 Caddyfile 的基本语法,接下来学习 基本命令 了解如何管理 Caddy 服务!

最后更新:2026-03-28