2.1 Caddyfile简介
2.1.1 什么是Caddyfile
Caddyfile 是 Caddy 的主要配置文件格式,采用简洁直观的语法设计。与传统的 Web 服务器配置文件相比,Caddyfile 更加人性化,易于阅读和编写。
2.1.2 Caddyfile的优势
- 简洁语法:使用缩进和关键字,避免复杂的嵌套结构
- 自动HTTPS:默认启用HTTPS,无需额外配置
- 智能默认值:提供合理的默认配置
- 模块化:支持指令和中间件的组合使用
- 热重载:支持配置文件的实时重载
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 匹配优先级
匹配按以下优先级进行:
- 精确匹配
- 最长前缀匹配
- 正则表达式匹配
- 通配符匹配
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 配置组织
使用有意义的注释
# 主站点配置 example.com { # 设置文档根目录 root * /var/www/example # 启用文件服务器 file_server # 安全头部配置 header { # 防止点击劫持 X-Frame-Options DENY # 防止MIME类型嗅探 X-Content-Type-Options nosniff } }
使用配置片段减少重复
(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 # 其他配置... }
分离环境配置 “`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
# 其他配置...
}
配置缓存
example.com { @static { file path *.css *.js *.png *.jpg *.gif *.ico *.svg } header @static { Cache-Control "public, max-age=31536000, immutable" } # 其他配置... }
优化文件服务
example.com { file_server { # 预压缩文件 precompressed gzip br # 隐藏敏感文件 hide .git .env } }
2.10.3 安全配置
- 安全头部
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的语法和配置方法:
- 基础语法:掌握了Caddyfile的基本语法规则
- 文件结构:了解了全局选项块和站点块的组织方式
- 核心指令:学习了常用指令的使用方法
- 路径匹配:掌握了各种路径匹配模式
- 变量系统:学会了使用内置变量和自定义变量
- 条件配置:了解了如何基于条件进行配置
- 配置管理:学习了配置文件的组织和管理方法
- 最佳实践:掌握了配置优化和安全配置的技巧
通过本章的学习,你应该能够: - 编写正确的Caddyfile配置文件 - 使用各种指令配置不同类型的服务 - 组织和管理复杂的配置文件 - 应用安全和性能优化的最佳实践
练习题
基础练习
基本配置
- 创建一个简单的静态网站配置
- 配置多个域名指向同一个站点
- 添加基本的安全头部
路径匹配
- 配置不同路径的不同响应
- 使用通配符匹配图片文件
- 实现API路径的反向代理
变量使用
- 使用内置变量显示请求信息
- 配置环境变量的使用
- 创建自定义变量
进阶练习
条件配置
- 基于User-Agent实现移动端重定向
- 配置基于IP的访问控制
- 实现基于查询参数的条件响应
配置片段
- 创建可重用的安全配置片段
- 实现通用的压缩配置
- 组织多站点的共同配置
性能优化
- 配置静态资源的缓存策略
- 启用压缩和预压缩
- 优化文件服务器配置
实战练习
多环境配置
- 创建开发、测试、生产环境的配置
- 使用环境变量管理不同环境
- 实现环境特定的功能开关
复杂站点配置
- 配置一个包含静态文件、API代理、SPA路由的完整站点
- 实现多级路径的不同处理策略
- 添加完整的安全和性能优化配置
下一章我们将学习如何使用Caddy提供静态文件服务,包括高级功能和优化技巧。