实战案例集合
本章提供了各种实际应用场景的完整配置示例,帮助您快速上手 Caddy 的实际部署。
🌐 静态网站托管
个人博客网站
caddyfile
# 个人博客配置
blog.example.com {
# 安全头
header {
Strict-Transport-Security "max-age=31536000; includeSubDomains"
X-Content-Type-Options nosniff
X-Frame-Options DENY
X-XSS-Protection "1; mode=block"
Referrer-Policy strict-origin-when-cross-origin
}
# 压缩
encode gzip zstd
# 缓存策略
@static path *.css *.js *.png *.jpg *.gif *.ico *.woff *.woff2
header @static Cache-Control "public, max-age=31536000, immutable"
@html path *.html
header @html Cache-Control "public, max-age=3600"
# 根目录
root * /var/www/blog
# 文件服务器
file_server {
precompressed gzip br
hide .htaccess .env
}
# 自定义错误页面
handle_errors {
@404 expression {http.error.status_code} == 404
handle @404 {
rewrite * /404.html
file_server
}
}
}
# 重定向 www 到非 www
www.blog.example.com {
redir https://blog.example.com{uri} permanent
}
多语言静态站点
caddyfile
example.com {
# 根据 Accept-Language 头重定向
@chinese header Accept-Language *zh*
redir @chinese /zh{uri} 302
@english header Accept-Language *en*
redir @english /en{uri} 302
# 语言特定路径
handle /zh/* {
root * /var/www/site/zh
rewrite * {path}
try_files {path} {path}/ {path}/index.html /zh/index.html
file_server
}
handle /en/* {
root * /var/www/site/en
rewrite * {path}
try_files {path} {path}/ {path}/index.html /en/index.html
file_server
}
# 默认语言(英文)
handle {
root * /var/www/site/en
try_files {path} {path}/ {path}/index.html /index.html
file_server
}
}
🚀 单页应用 (SPA)
React/Vue/Angular 应用
caddyfile
app.example.com {
# API 代理
handle /api/* {
reverse_proxy localhost:3000 {
header_up Host {upstream_hostport}
header_up X-Real-IP {remote_host}
header_up X-Forwarded-For {remote_host}
header_up X-Forwarded-Proto {scheme}
}
}
# 静态资源
handle /static/* {
root * /var/www/app
file_server {
precompressed gzip br
}
# 长期缓存
header Cache-Control "public, max-age=31536000, immutable"
}
# SPA 路由处理
handle {
root * /var/www/app
# 尝试文件,如果不存在则返回 index.html
try_files {path} {path}/ /index.html
file_server
# HTML 文件短期缓存
@html path *.html
header @html Cache-Control "public, max-age=300"
}
# 压缩
encode gzip zstd
# 安全头
header {
X-Content-Type-Options nosniff
X-Frame-Options DENY
X-XSS-Protection "1; mode=block"
}
}
PWA 应用
caddyfile
pwa.example.com {
# Service Worker 特殊处理
@sw path /sw.js /service-worker.js
header @sw {
Cache-Control "no-cache, no-store, must-revalidate"
Service-Worker-Allowed "/"
}
# Manifest 文件
@manifest path /manifest.json
header @manifest {
Content-Type "application/manifest+json"
Cache-Control "public, max-age=86400"
}
# 静态资源缓存
@static path *.css *.js *.png *.jpg *.gif *.ico *.woff *.woff2
header @static Cache-Control "public, max-age=31536000, immutable"
# 压缩
encode gzip zstd
# 根目录
root * /var/www/pwa
# SPA 路由
try_files {path} {path}/ /index.html
file_server {
precompressed gzip br
}
}
🔄 反向代理场景
微服务架构
caddyfile
{
email admin@example.com
}
# API 网关
api.example.com {
# 用户服务
handle /users/* {
reverse_proxy user-service-1:8080 user-service-2:8080 {
lb_policy round_robin
health_uri /health
health_interval 30s
}
}
# 订单服务
handle /orders/* {
reverse_proxy order-service-1:8080 order-service-2:8080 {
lb_policy least_conn
health_uri /health
health_interval 30s
}
}
# 支付服务
handle /payments/* {
reverse_proxy payment-service:8080 {
health_uri /health
health_interval 15s
}
}
# 认证服务
handle /auth/* {
reverse_proxy auth-service:8080
}
# 全局中间件
header {
X-API-Gateway "Caddy"
X-Request-ID {uuid}
Access-Control-Allow-Origin "https://app.example.com"
Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS"
Access-Control-Allow-Headers "Content-Type, Authorization"
}
# 限流
rate_limit {
zone api {
key {header.authorization}
events 1000
window 1h
}
}
# 默认响应
respond "API Gateway" 200
}
# 前端应用
app.example.com {
reverse_proxy frontend:3000
}
# 管理后台
admin.example.com {
basicauth {
admin $2a$14$hgl486...
}
reverse_proxy admin-panel:8080
}
WordPress 多站点
caddyfile
# 主站点
example.com {
reverse_proxy wordpress:80 {
header_up Host {upstream_hostport}
header_up X-Real-IP {remote_host}
header_up X-Forwarded-For {remote_host}
header_up X-Forwarded-Proto {scheme}
}
}
# 子站点
blog.example.com {
reverse_proxy wordpress-blog:80 {
header_up Host {upstream_hostport}
header_up X-Real-IP {remote_host}
header_up X-Forwarded-For {remote_host}
header_up X-Forwarded-Proto {scheme}
}
}
# 商店站点
shop.example.com {
reverse_proxy wordpress-shop:80 {
header_up Host {upstream_hostport}
header_up X-Real-IP {remote_host}
header_up X-Forwarded-For {remote_host}
header_up X-Forwarded-Proto {scheme}
}
}
# 静态资源 CDN
cdn.example.com {
root * /var/www/cdn
# 长期缓存
header Cache-Control "public, max-age=31536000, immutable"
# 压缩
encode gzip zstd
file_server {
precompressed gzip br
}
}
🔐 企业级应用
内网应用代理
caddyfile
{
email admin@company.com
# 内网 CA 证书
local_certs
}
# 内网应用门户
portal.company.local {
# 基于 IP 的访问控制
@internal remote_ip 192.168.0.0/16 10.0.0.0/8
@external not remote_ip 192.168.0.0/16 10.0.0.0/8
# 外网用户需要 VPN 认证
handle @external {
respond "Access denied. VPN required." 403
}
# 内网用户正常访问
handle @internal {
root * /var/www/portal
file_server
}
}
# ERP 系统
erp.company.local {
@internal remote_ip 192.168.0.0/16
handle @internal {
# LDAP 认证(需要插件)
auth_portal {
backends {
ldap_backend {
method ldap
realm local
servers {
ldap://ldap.company.local:389
}
attributes {
name givenName
surname sn
username sAMAccountName
member_of memberOf
}
username "CN=caddy,OU=Service Accounts,DC=company,DC=local"
password "service_password"
search_base_dn "DC=company,DC=local"
search_filter "(&(|(sAMAccountName=%s)(mail=%s))(objectclass=person))"
}
}
}
reverse_proxy erp-server:8080
}
respond @external "Access denied" 403
}
# 监控系统
monitoring.company.local {
@admin remote_ip 192.168.1.0/24 # 管理员网段
@user remote_ip 192.168.0.0/16 # 普通用户网段
# 管理员全权限
handle @admin {
reverse_proxy grafana:3000
}
# 普通用户只读权限
handle @user {
reverse_proxy grafana:3000 {
header_up X-WEBAUTH-USER "readonly"
}
}
respond "Access denied" 403
}
多租户 SaaS 应用
caddyfile
{
email admin@saas-platform.com
}
# 主平台
saas-platform.com {
reverse_proxy platform:3000
}
# 租户子域名
*.saas-platform.com {
@tenant header Host ~^([^.]+)\.saas-platform\.com$
# 提取租户 ID
vars tenant_id {re.tenant.1}
# 路由到租户特定的后端
reverse_proxy tenant-app:8080 {
header_up X-Tenant-ID {vars.tenant_id}
header_up Host saas-platform.com
}
}
# 自定义域名支持
{$CUSTOM_DOMAIN} {
# 从数据库查询租户信息(需要自定义插件)
@valid_domain {
# 这里需要自定义逻辑验证域名
}
handle @valid_domain {
reverse_proxy tenant-app:8080 {
header_up X-Custom-Domain {host}
}
}
respond "Domain not configured" 404
}
🛡️ 安全加固案例
高安全性网站
caddyfile
secure.example.com {
# 强制 TLS 1.3
tls {
protocols tls1.3
ciphers TLS_AES_256_GCM_SHA384 TLS_CHACHA20_POLY1305_SHA256
curves x25519
}
# 严格的安全头
header {
Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"
Content-Security-Policy "default-src 'none'; script-src 'self'; style-src 'self'; img-src 'self'; font-src 'self'; connect-src 'self'; base-uri 'self'; form-action 'self'"
X-Frame-Options DENY
X-Content-Type-Options nosniff
X-XSS-Protection "1; mode=block"
Referrer-Policy no-referrer
Permissions-Policy "camera=(), microphone=(), geolocation=(), payment=(), usb=()"
-Server
-X-Powered-By
}
# 严格的访问控制
@admin path /admin/*
handle @admin {
# 双因素认证(需要插件)
basicauth {
admin $2a$14$hgl486...
}
# IP 白名单
@allowed_admin remote_ip 203.0.113.0/24
respond @allowed_admin {
root * /var/www/admin
file_server
}
respond "Access denied" 403
}
# 输入验证
@suspicious {
query *<script* *javascript:* *vbscript:*
query *union+select* *1=1* *'or'1'='1*
path */etc/passwd* */proc/self/environ*
header User-Agent *sqlmap* *nikto* *w3af*
}
handle @suspicious {
respond "Invalid request" 400
}
# 限流
rate_limit {
zone secure {
key {remote_host}
events 50
window 1m
}
}
# 正常内容
handle {
root * /var/www/secure
file_server {
hide .* *.bak *.config *.log
}
}
}
API 安全网关
caddyfile
api-secure.example.com {
# CORS 预检请求
@cors_preflight method OPTIONS
handle @cors_preflight {
header {
Access-Control-Allow-Origin "https://trusted-app.example.com"
Access-Control-Allow-Methods "GET, POST, PUT, DELETE"
Access-Control-Allow-Headers "Content-Type, Authorization, X-API-Key"
Access-Control-Max-Age "86400"
}
respond "" 204
}
# API 密钥验证
@no_api_key not header X-API-Key *
respond @no_api_key "API key required" 401
# 速率限制(基于 API 密钥)
rate_limit {
zone api_key {
key {header.x-api-key}
events 1000
window 1h
}
}
# 请求大小限制
request_body {
max_size 1MB
}
# 内容类型验证
@invalid_content_type {
method POST PUT PATCH
not header Content-Type application/json*
}
respond @invalid_content_type "Invalid Content-Type" 400
# 安全头
header {
X-Content-Type-Options nosniff
X-Frame-Options DENY
Cache-Control "no-cache, no-store, must-revalidate"
Access-Control-Allow-Origin "https://trusted-app.example.com"
-Server
}
# 代理到后端
reverse_proxy localhost:3000 {
header_up X-Forwarded-For {remote_host}
header_up X-Real-IP {remote_host}
header_up X-API-Gateway "Caddy-Secure"
}
}
🔧 开发环境配置
本地开发代理
caddyfile
{
local_certs
admin localhost:2019
}
# 前端开发服务器
app.localhost {
reverse_proxy localhost:3000
}
# 后端 API
api.localhost {
reverse_proxy localhost:8080
}
# 数据库管理工具
db.localhost {
reverse_proxy localhost:8081
}
# 文档站点
docs.localhost {
root * ./docs
file_server browse
}
# 静态文件服务
static.localhost {
root * ./public
file_server browse
}
# 测试环境
test.localhost {
reverse_proxy localhost:3001
}
多项目开发环境
caddyfile
{
local_certs
}
# 项目 A
project-a.localhost {
handle /api/* {
reverse_proxy localhost:3000
}
handle {
reverse_proxy localhost:8080 # 前端开发服务器
}
}
# 项目 B
project-b.localhost {
handle /api/* {
reverse_proxy localhost:3001
}
handle {
reverse_proxy localhost:8081
}
}
# 共享服务
services.localhost {
handle /redis/* {
reverse_proxy localhost:8082 # Redis 管理界面
}
handle /mongo/* {
reverse_proxy localhost:8083 # MongoDB 管理界面
}
handle /mail/* {
reverse_proxy localhost:8084 # 邮件测试工具
}
}
这些实战案例涵盖了 Caddy 的主要应用场景。您可以根据自己的需求调整和组合这些配置。 🎯