2.1 Caddyfile简介

2.1.1 什么是Caddyfile

Caddyfile 是 Caddy 的主要配置文件格式,采用简洁直观的语法设计。与传统的 Web 服务器配置文件相比,Caddyfile 更加人性化,易于阅读和编写。

2.1.2 Caddyfile的优势

  1. 简洁语法:使用缩进和关键字,避免复杂的嵌套结构
  2. 自动HTTPS:默认启用HTTPS,无需额外配置
  3. 智能默认值:提供合理的默认配置
  4. 模块化:支持指令和中间件的组合使用
  5. 热重载:支持配置文件的实时重载

2.1.3 基本语法规则

# 这是注释

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

# 全局选项
{
    email admin@example.com
}

语法要点: - 使用花括号 {} 定义块 - 使用缩进表示层级关系 - 指令以关键字开始,后跟参数 - 注释以 # 开始 - 字符串可以用引号包围(可选)

2.2 Caddyfile结构

2.2.1 全局选项块

全局选项块位于文件开头,用花括号包围,不需要地址标识:

{
    # 管理员邮箱(用于Let's Encrypt)
    email admin@example.com
    
    # 默认SNI
    default_sni example.com
    
    # 管理端点
    admin localhost:2019
    
    # 日志配置
    log {
        output file /var/log/caddy/access.log
        format json
    }
    
    # ACME服务器
    acme_ca https://acme-v02.api.letsencrypt.org/directory
    
    # 存储配置
    storage file_system {
        root /var/lib/caddy
    }
}

2.2.2 站点块

站点块定义了特定站点的配置:

# 单个域名
example.com {
    root * /var/www/example
    file_server
}

# 多个域名
example.com, www.example.com {
    root * /var/www/example
    file_server
}

# 端口指定
localhost:8080 {
    respond "Hello, World!"
}

# 通配符
*.example.com {
    root * /var/www/subdomains
    file_server
}

2.2.3 指令和中间件

指令是Caddyfile中的基本配置单元:

example.com {
    # 根目录指令
    root * /var/www
    
    # 文件服务器中间件
    file_server
    
    # 日志中间件
    log {
        output file /var/log/access.log
    }
    
    # 压缩中间件
    encode gzip
    
    # 头部中间件
    header {
        X-Frame-Options DENY
        X-Content-Type-Options nosniff
    }
}

2.3 基本指令详解

2.3.1 root指令

设置站点的根目录:

# 基本用法
root * /var/www/html

# 路径匹配
root /api/* /var/www/api
root /static/* /var/www/static
root * /var/www/default

# 使用变量
root * /var/www/{host}

2.3.2 file_server指令

启用静态文件服务:

# 基本文件服务
file_server

# 启用目录浏览
file_server browse

# 指定索引文件
file_server {
    index index.html index.htm
}

# 隐藏文件
file_server {
    hide .htaccess .git
}

# 路径匹配
file_server /static/*

2.3.3 respond指令

返回静态响应:

# 简单响应
respond "Hello, World!"

# 指定状态码
respond "Not Found" 404

# JSON响应
respond `{"message": "Hello"}` 200 {
    Content-Type application/json
}

# 路径匹配
respond /api/* "API Endpoint" 200

2.3.4 redir指令

配置重定向:

# 基本重定向
redir https://example.com

# 指定状态码
redir https://example.com 301

# 路径重定向
redir /old-path /new-path

# 临时重定向
redir /temp https://temp.example.com 302

# 正则表达式重定向
redir /user/{id} /users/{id} 301

2.3.5 reverse_proxy指令

配置反向代理:

# 基本反向代理
reverse_proxy localhost:3000

# 多个后端
reverse_proxy localhost:3000 localhost:3001 localhost:3002

# 路径匹配
reverse_proxy /api/* localhost:8080

# 负载均衡策略
reverse_proxy localhost:3000 localhost:3001 {
    lb_policy round_robin
}

# 健康检查
reverse_proxy localhost:3000 {
    health_uri /health
    health_interval 30s
}

2.4 路径匹配

2.4.1 匹配语法

Caddy支持多种路径匹配模式:

# 精确匹配
respond /exact "Exact match"

# 前缀匹配
respond /prefix/* "Prefix match"

# 后缀匹配
respond *.jpg "JPEG image"

# 通配符匹配
respond /files/*.{jpg,png,gif} "Image file"

# 正则表达式匹配
respond ~ \/api\/v[0-9]+\/.* "API endpoint"

2.4.2 匹配优先级

匹配按以下优先级进行:

  1. 精确匹配
  2. 最长前缀匹配
  3. 正则表达式匹配
  4. 通配符匹配
example.com {
    # 优先级1:精确匹配
    respond /api "API root"
    
    # 优先级2:长前缀匹配
    respond /api/v2/* "API v2"
    
    # 优先级3:短前缀匹配
    respond /api/* "API general"
    
    # 优先级4:通配符匹配
    respond * "Default response"
}

2.5 变量和占位符

2.5.1 内置变量

Caddy提供了丰富的内置变量:

example.com {
    # 请求相关变量
    respond "Method: {method}, URI: {uri}, Host: {host}"
    
    # 头部变量
    respond "User-Agent: {header.user-agent}"
    
    # 查询参数
    respond "Query: {query.param}"
    
    # 路径变量
    respond "Path: {path}, File: {file}"
    
    # 时间变量
    respond "Time: {time.now}"
}

2.5.2 自定义变量

example.com {
    # 设置变量
    vars {
        app_name "My App"
        version "1.0.0"
    }
    
    # 使用变量
    respond "Welcome to {vars.app_name} v{vars.version}"
}

2.5.3 环境变量

{
    # 全局环境变量
    email {env.ADMIN_EMAIL}
}

example.com {
    # 使用环境变量
    root * {env.DOCUMENT_ROOT}
    
    # 带默认值的环境变量
    respond "Environment: {env.NODE_ENV:development}"
}

2.6 条件配置

2.6.1 基本条件

example.com {
    # 基于请求方法的条件
    @get method GET
    @post method POST
    
    respond @get "GET request"
    respond @post "POST request"
}

2.6.2 复杂条件

example.com {
    # 多条件组合
    @api {
        path /api/*
        method GET POST
    }
    
    # 头部条件
    @mobile {
        header User-Agent *Mobile*
    }
    
    # 查询参数条件
    @debug {
        query debug=true
    }
    
    respond @api "API endpoint"
    respond @mobile "Mobile version"
    respond @debug "Debug mode"
}

2.6.3 否定条件

example.com {
    # 非API请求
    @not_api {
        not path /api/*
    }
    
    # 非移动设备
    @not_mobile {
        not header User-Agent *Mobile*
    }
    
    file_server @not_api
    respond @not_mobile "Desktop version"
}

2.7 实用配置示例

2.7.1 静态网站配置

# 简单静态网站
example.com {
    root * /var/www/example
    file_server
    
    # 启用压缩
    encode gzip
    
    # 安全头部
    header {
        X-Frame-Options DENY
        X-Content-Type-Options nosniff
        Referrer-Policy strict-origin-when-cross-origin
    }
    
    # 缓存静态资源
    @static {
        file
        path *.css *.js *.png *.jpg *.gif *.ico *.svg
    }
    header @static Cache-Control "public, max-age=31536000"
}

2.7.2 SPA应用配置

# 单页应用配置
app.example.com {
    root * /var/www/spa
    
    # API代理
    reverse_proxy /api/* localhost:8080
    
    # 静态文件服务
    @static {
        file
        path *.css *.js *.png *.jpg *.gif *.ico *.svg *.woff *.woff2
    }
    file_server @static
    
    # SPA路由回退
    try_files {path} /index.html
    file_server
}

2.7.3 多环境配置

# 开发环境
dev.example.com {
    reverse_proxy localhost:3000
    
    # 开发环境头部
    header {
        X-Environment "development"
    }
}

# 测试环境
test.example.com {
    reverse_proxy localhost:3001
    
    # 基本认证
    basicauth {
        test $2a$14$Zkx19XLiW6VYouLHR5NmfOFU0z2GTNqq9qB6FY9gZKOOdOoKw6Uw.
    }
    
    header {
        X-Environment "testing"
    }
}

# 生产环境
example.com {
    reverse_proxy localhost:3002
    
    # 生产环境安全配置
    header {
        Strict-Transport-Security "max-age=31536000; includeSubDomains"
        X-Environment "production"
    }
    
    # 访问日志
    log {
        output file /var/log/caddy/access.log {
            roll_size 100mb
            roll_keep 10
        }
    }
}

2.8 配置文件管理

2.8.1 配置文件分割

主配置文件 (Caddyfile):

{
    email admin@example.com
}

# 导入其他配置文件
import sites/*.caddy
import common/security.caddy

站点配置 (sites/example.caddy):

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

通用配置 (common/security.caddy):

(security) {
    header {
        X-Frame-Options DENY
        X-Content-Type-Options nosniff
    }
}

2.8.2 配置片段

定义可重用的配置片段:

# 定义片段
(common_headers) {
    header {
        X-Frame-Options DENY
        X-Content-Type-Options nosniff
        X-XSS-Protection "1; mode=block"
    }
}

(gzip_compression) {
    encode gzip
}

# 使用片段
example.com {
    import common_headers
    import gzip_compression
    
    root * /var/www/example
    file_server
}

api.example.com {
    import common_headers
    
    reverse_proxy localhost:8080
}

2.8.3 环境特定配置

{
    email {env.ADMIN_EMAIL}
}

# 根据环境变量选择配置
{env.DOMAIN:localhost} {
    root * {env.DOCUMENT_ROOT:/var/www}
    
    # 开发环境特定配置
    @dev `{env.NODE_ENV} == "development"`
    header @dev {
        X-Debug-Mode "true"
    }
    
    # 生产环境特定配置
    @prod `{env.NODE_ENV} == "production"`
    header @prod {
        Strict-Transport-Security "max-age=31536000"
    }
    
    file_server
}

2.9 配置验证和调试

2.9.1 语法验证

# 验证配置文件语法
caddy validate

# 验证指定配置文件
caddy validate --config /path/to/Caddyfile

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

# 显示格式化差异
caddy fmt --diff Caddyfile

2.9.2 配置调试

# 显示解析后的配置
caddy config

# 以JSON格式显示配置
caddy config --pretty

# 显示特定适配器的配置
caddy adapt --config Caddyfile

2.9.3 实时配置重载

# 重载配置(不中断服务)
caddy reload

# 重载指定配置文件
caddy reload --config /path/to/Caddyfile

# 强制重载
caddy reload --force

2.10 最佳实践

2.10.1 配置组织

  1. 使用有意义的注释

    # 主站点配置
    example.com {
    # 设置文档根目录
    root * /var/www/example
    
    # 启用文件服务器
    file_server
    
    # 安全头部配置
    header {
        # 防止点击劫持
        X-Frame-Options DENY
        # 防止MIME类型嗅探
        X-Content-Type-Options nosniff
    }
    }
    
    1. 使用配置片段减少重复

      (security_headers) {
      header {
      X-Frame-Options DENY
      X-Content-Type-Options nosniff
      X-XSS-Protection "1; mode=block"
      Referrer-Policy strict-origin-when-cross-origin
      }
      }
      # 在多个站点中重用
      example.com {
      import security_headers
      # 其他配置...
      }
      api.example.com {
      import security_headers
      # 其他配置...
      }
      
  2. 分离环境配置 “`caddyfile

    使用环境变量

    { email {env.ADMIN_EMAIL:admin@example.com} }

{env.DOMAIN:localhost} { root * {env.DOCUMENT_ROOT:/var/www}

# 环境特定的反向代理
reverse_proxy {env.BACKEND_URL:localhost:3000}

}


### 2.10.2 性能优化

1. **启用压缩**
```caddyfile
example.com {
    encode gzip zstd
    # 其他配置...
}
  1. 配置缓存

    example.com {
    @static {
        file
        path *.css *.js *.png *.jpg *.gif *.ico *.svg
    }
    
    
    header @static {
        Cache-Control "public, max-age=31536000, immutable"
    }
    
    # 其他配置...
    }
    
    1. 优化文件服务

      example.com {
      file_server {
      # 预压缩文件
      precompressed gzip br
      # 隐藏敏感文件
      hide .git .env
      }
      }
      

2.10.3 安全配置

  1. 安全头部 caddyfile (security) { header { # HSTS Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" # 防止点击劫持 X-Frame-Options DENY # 防止MIME嗅探 X-Content-Type-Options nosniff # XSS保护 X-XSS-Protection "1; mode=block" # 引用策略 Referrer-Policy strict-origin-when-cross-origin # CSP(根据需要调整) Content-Security-Policy "default-src 'self'" } } 2. 访问控制 caddyfile example.com { # 限制管理路径访问 @admin { path /admin/* } # 基本认证 basicauth @admin { admin $2a$14$Zkx19XLiW6VYouLHR5NmfOFU0z2GTNqq9qB6FY9gZKOOdOoKw6Uw. } # IP白名单 @internal { remote_ip 192.168.1.0/24 10.0.0.0/8 } respond @admin @internal "Admin access allowed" respond @admin "Access denied" 403 }

本章总结

本章我们深入学习了Caddyfile的语法和配置方法:

  1. 基础语法:掌握了Caddyfile的基本语法规则
  2. 文件结构:了解了全局选项块和站点块的组织方式
  3. 核心指令:学习了常用指令的使用方法
  4. 路径匹配:掌握了各种路径匹配模式
  5. 变量系统:学会了使用内置变量和自定义变量
  6. 条件配置:了解了如何基于条件进行配置
  7. 配置管理:学习了配置文件的组织和管理方法
  8. 最佳实践:掌握了配置优化和安全配置的技巧

通过本章的学习,你应该能够: - 编写正确的Caddyfile配置文件 - 使用各种指令配置不同类型的服务 - 组织和管理复杂的配置文件 - 应用安全和性能优化的最佳实践

练习题

基础练习

  1. 基本配置

    • 创建一个简单的静态网站配置
    • 配置多个域名指向同一个站点
    • 添加基本的安全头部
  2. 路径匹配

    • 配置不同路径的不同响应
    • 使用通配符匹配图片文件
    • 实现API路径的反向代理
  3. 变量使用

    • 使用内置变量显示请求信息
    • 配置环境变量的使用
    • 创建自定义变量

进阶练习

  1. 条件配置

    • 基于User-Agent实现移动端重定向
    • 配置基于IP的访问控制
    • 实现基于查询参数的条件响应
  2. 配置片段

    • 创建可重用的安全配置片段
    • 实现通用的压缩配置
    • 组织多站点的共同配置
  3. 性能优化

    • 配置静态资源的缓存策略
    • 启用压缩和预压缩
    • 优化文件服务器配置

实战练习

  1. 多环境配置

    • 创建开发、测试、生产环境的配置
    • 使用环境变量管理不同环境
    • 实现环境特定的功能开关
  2. 复杂站点配置

    • 配置一个包含静态文件、API代理、SPA路由的完整站点
    • 实现多级路径的不同处理策略
    • 添加完整的安全和性能优化配置

下一章我们将学习如何使用Caddy提供静态文件服务,包括高级功能和优化技巧。