Caddy 快速入门

2025-06-25 18:55:00
丁国栋
原创 10

Caddy Web服务器介绍与常用配置

Caddy简介

Caddy是一个现代化的、开源的Web服务器和反向代理服务器,具有以下特点:

  • 自动HTTPS:自动获取和更新Let's Encrypt证书
  • 简洁配置:使用Caddyfile语法,配置简单直观
  • 高性能:基于Go语言编写,性能优秀
  • 无依赖:单一静态二进制文件,无需额外依赖
  • 支持HTTP/2和HTTP/3
  • 丰富的插件生态系统

Caddy常用配置文件示例

以下是一个包含多种常用功能的Caddyfile配置示例,涵盖了Nginx中常见的反向代理功能:

# 全局配置
{
    # 设置默认HTTP端口为8080,HTTPS端口为8443
    http_port 80
    https_port 443
    auto_https on  # 如果不需要自动HTTPS可以关闭,on改为off
    # 自动HTTPS设置
    email your-email@example.com  # 用于Let's Encrypt通知
    acme_ca https://acme-staging-v02.api.letsencrypt.org/directory  # 测试用CA,生产环境可移除
    # acme_ca https://acme-v02.api.letsencrypt.org/directory  # 生产环境CA
    # 性能调优
    servers {
        protocol {
            experimental_http3   # 启用HTTP/3
        }
    }
    # 全局日志设置
    log {
        output file /var/log/caddy/global.log {
            roll_size 100MiB
            roll_keep 10
            roll_keep_for 720h
        }
        format json
    }
}
# 示例1: 基本反向代理
example.com:80 {
    # 记录访问日志
    log {
        output file /var/log/caddy/example.com.access.log
        format json
    }
    # 反向代理到本地服务
    reverse_proxy localhost:3000 {
        # 负载均衡策略
        lb_policy first
        # 健康检查
        health_uri /health
        health_interval 10s
        health_timeout 5s
    }
}
# 示例2: 带路径重写的反向代理
api.example.com {
    # 站点特定日志
    log {
        output file /var/log/caddy/api.example.com.access.log {
            roll_size 50MiB
            roll_keep 5
            roll_keep_for 168h
        }
        format "{ts} {remote}:{remote_port} {host} {method} {uri} {proto} {status} {size} {latency} {>User-Agent}"
    }
    reverse_proxy /api/* http://localhost:8000 {
        # 重写路径,去掉/api前缀
        rewrite /api/* /{path}
        # 设置代理请求头
        header_up X-Real-IP {remote_host}
        header_up X-Forwarded-For {remote_host}
        header_up X-Forwarded-Proto {scheme}
        header_up Host {host}
        # 传输超时设置
        transport http {
            read_timeout 30s
            write_timeout 30s
            dial_timeout 30s
        }
    }
}
# 示例3: 静态文件服务与安全头设置
static.example.com {
    # 静态文件服务
    root * /var/www/static
    # 安全相关HTTP头
    header {
        # 安全头
        X-Content-Type-Options "nosniff"
        X-Frame-Options "DENY"
        X-XSS-Protection "1; mode=block"
        Referrer-Policy "strict-origin-when-cross-origin"
        Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' cdn.example.com; style-src 'self' 'unsafe-inline'"
        # 缓存控制
        Cache-Control "public, max-age=604800"
        # 移除服务器信息
        -Server
    }
    # 文件压缩
    encode gzip zstd
    # 文件浏览(可选)
    file_server browse
    # 另一个日志输出(如审计日志)
    log {
        output file /var/log/caddy/example.com.audit.log
        format json {
            timestamp: "{ts}"
            client_ip: "{remote}"
            method: "{method}"
            path: "{path}"
            query: "{query}"
            status: "{status}"
            request_size: "{request.size}"
            response_size: "{size}"
            latency: "{duration}"
            headers: {
                user_agent: "{>User-Agent}"
                referer: "{>Referer}"
                x_forwarded_for: "{>X-Forwarded-For}"
            }
        }
    }
}
# 示例4: WebSocket代理与速率限制
ws.example.com {
    # WebSocket反向代理
    reverse_proxy /chat/* localhost:8080 {
        # WebSocket支持
        header_up Connection {>Connection}
        header_up Upgrade {>Upgrade}
        # 保持活动连接
        transport http {
            keepalive 30
        }
    }
    # 速率限制
    rate_limit /chat/* 10 1m burst 20
}
# 示例5: 多站点与重定向
www.example.com {
    # 重定向到非www
    redir https://example.com{uri} permanent
}
example.com {
    # 基本认证(保护管理区域)
    @admin path /admin/*
    basicauth @admin {
        admin $2a$10$5WzZ5v5z5z5z5z5z5z5z.
    }
    # 错误页面处理
    handle_errors {
        @404 {
            expression {http.error.status_code} == 404
        }
        respond @404 "Custom 404 Page" 404
    }
}
# 示例6: 基于IP的访问控制
internal.example.com {
    # 只允许内网IP访问
    @allowed_ips {
        remote_ip 192.168.1.0/24 10.0.0.0/8
    }
    reverse_proxy @allowed_ips localhost:4000
    # 拒绝其他IP
    respond @allowed_ips 403
}
# 示例7: 缓存代理
cache.example.com {
    reverse_proxy https://backend.example.com {
        # 缓存设置
        cache {
            # 缓存键
            key {path} {query}
            # 缓存时间
            ttl 1h
            # 缓存状态码
            status_header X-Cache-Status
            cache_status pass
        }
    }
}
# 示例8: PHP处理
php.example.com {
    # 网站根目录
    root * /var/www/php-site
    # 文件服务器
    file_server
    # 启用压缩
    encode gzip zstd
    # PHP 处理配置
    php_fastcgi unix//run/php/php8.2-fpm.sock {
        # FastCGI 参数
        split .php
        index index.php
        # 环境变量
        env SCRIPT_FILENAME /var/www/php-site{path}
        env PATH /usr/local/bin:/usr/bin:/bin
        # 超时设置
        read_timeout 60s
        write_timeout 60s
        # 连接池设置
        connect_timeout 5s
        pool_size 10
    }
    # 安全头设置
    header {
        X-Content-Type-Options "nosniff"
        X-Frame-Options "SAMEORIGIN"
        Referrer-Policy "strict-origin-when-cross-origin"
        # 移除 PHP 版本信息
        -X-Powered-By
    }
    # 错误页面处理
    handle_errors {
        @phpErrors {
            expression {http.error.status_code} >= 500
        }
        respond @phpErrors "PHP Error Occurred" 500
    }
    # 日志记录
    log {
        output file /var/log/caddy/php-site.log
        format json
    }
}
# 示例9: Laravel处理
laravel.example.com {
    root * /var/www/laravel/public
    # 处理静态文件
    @static {
        file {
            try_files {path} {path}/ /index.php?{query}
        }
    }
    file_server @static
    # Laravel 路由处理
    php_fastcgi unix//run/php/php8.2-fpm.sock {
        split .php
        index index.php
        env SCRIPT_FILENAME /var/www/laravel/public/index.php
    }
    # 重写规则
    try_files {path} /index.php?{query}
}
# 示例10: WordPress
wordpress.example.com {
    root * /var/www/wordpress
    file_server
    php_fastcgi unix//run/php/php8.2-fpm.sock {
        split .php
        index index.php index.html
        env SCRIPT_FILENAME /var/www/wordpress{path}
    }
    # WordPress 永久链接支持
    try_files {path} /index.php?{query}
    # 上传限制
    client_max_body_size 64M
    # 安全头
    header {
        X-XSS-Protection "1; mode=block"
        Content-Security-Policy "default-src 'self' https: data: 'unsafe-inline' 'unsafe-eval'"
    }
} 

Caddy与Nginx功能对比

功能 Nginx配置 Caddy配置
反向代理 proxy_pass reverse_proxy
负载均衡 upstream + proxy_pass reverse_proxy + lb_policy
WebSocket代理 proxy_set_header特殊头 自动检测或显式设置头
路径重写 rewriteproxy_pass中路径 rewrite指令
静态文件服务 root + location root + file_server
HTTP头设置 add_header header指令
访问控制 allow/deny remote_ip匹配器
速率限制 limit_req rate_limit指令
自动HTTPS 需要额外配置 内置自动HTTPS

注意事项

  1. Caddy会自动管理HTTPS证书,无需手动配置
  2. Caddyfile更改后无需手动重启,Caddy会自动重新加载配置
  3. 生产环境中建议移除acme_ca测试配置
  4. 可以使用caddy fmt --overwrite命令格式化Caddyfile
  5. Caddy的插件系统可以扩展功能,如需要额外功能可安装相应插件

Caddy以其简洁的配置和自动化的HTTPS功能,成为Nginx的一个现代替代方案,特别适合需要快速部署和安全默认值的场景。

Caddy 自定义 Access 日志格式配置指南

Caddy 提供了灵活的日志配置功能,允许您自定义访问日志的格式和内容。以下是详细的配置方法:

基础日志配置

1. 简单自定义格式

example.com {
    log {
        output file /var/log/caddy/access.log
        format "{remote} - {user} [{ts}] \"{method} {uri} {proto}\" {status} {size} \"{>Referer}\" \"{>User-Agent}\""
    }
}

2. JSON 格式日志

example.com {
    log {
        output file /var/log/caddy/access.json
        format json {
            time: "{ts}"
            ip: "{remote}"
            method: "{method}"
            uri: "{uri}"
            status: "{status}"
            size: "{size}"
            referer: "{>Referer}"
            user_agent: "{>User-Agent}"
            duration: "{duration}"
        }
    }
}

完整日志配置示例

{
    # 全局日志设置
    log {
        output file /var/log/caddy/global.log {
            roll_size 100MiB
            roll_keep 10
            roll_keep_for 720h
        }
        format json
    }
}
example.com {
    # 站点特定日志
    log {
        output file /var/log/caddy/example.com.access.log {
            roll_size 50MiB
            roll_keep 5
            roll_keep_for 168h
        }
        format "{ts} {remote}:{remote_port} {host} {method} {uri} {proto} {status} {size} {latency} {>User-Agent}"
    }
    # 另一个日志输出(如审计日志)
    log {
        output file /var/log/caddy/example.com.audit.log
        format json {
            timestamp: "{ts}"
            client_ip: "{remote}"
            method: "{method}"
            path: "{path}"
            query: "{query}"
            status: "{status}"
            request_size: "{request.size}"
            response_size: "{size}"
            latency: "{duration}"
            headers: {
                user_agent: "{>User-Agent}"
                referer: "{>Referer}"
                x_forwarded_for: "{>X-Forwarded-For}"
            }
        }
    }
    # 站点配置...
    reverse_proxy localhost:3000
}

可用日志变量(占位符)

Caddy 提供了丰富的日志变量,以下是最常用的:

变量 描述
{ts} 时间戳 (RFC3339 格式)
{time} 时间戳 (自定义格式)
{remote} 客户端 IP 地址
{remote_port} 客户端端口
{host} 请求的主机名
{method} HTTP 方法 (GET, POST 等)
{uri} 完整请求 URI
{path} 请求路径
{query} 查询字符串
{proto} HTTP 协议版本
{status} 响应状态码
{size} 响应体大小 (字节)
{duration} 请求处理时长 (秒)
{latency} 延迟 (人类可读格式)
{request.size} 请求体大小 (字节)
{>Header-Name} 请求头 (如 {>User-Agent})
{<Header-Name} 响应头
{labels} 路由标签
{vars} 变量
{err} 错误信息

高级日志配置技巧

1. 条件日志记录

example.com {
    log {
        output file /var/log/caddy/important.log
        format "{remote} - {method} {uri} - {status}"
        # 只记录状态码 >=400 的请求
        condition {
            status >= 400
        }
    }
}

2. 自定义时间格式

example.com {
    log {
        output file /var/log/caddy/access.log
        format "{time:2006-01-02 15:04:05} {remote} \"{method} {uri} {proto}\" {status}"
    }
}

3. 日志轮转配置

log {
    output file /var/log/caddy/access.log {
        roll_size 100MiB  # 日志文件达到100MB时轮转
        roll_keep 10      # 保留10个旧日志文件
        roll_keep_for 720h # 保留30天的日志
        roll_local_time   # 使用本地时间而不是UTC
        roll_compress     # 压缩旧日志
    }
    format combined
}

4. 多日志输出

example.com {
    # 访问日志
    log {
        output file /var/log/caddy/access.log
        format combined
    }
    # 错误日志
    log {
        output file /var/log/caddy/errors.log
        format "{ts} {err}"
        level ERROR
    }
    # 发送到syslog
    log {
        output syslog 127.0.0.1:514
        format "{remote} {method} {uri} {status}"
    }
}

预设日志格式

Caddy 内置了几种常见日志格式预设:

  1. common:

    {remote} - {user} [{ts}] "{method} {uri} {proto}" {status} {size}
  2. combined:

    {remote} - {user} [{ts}] "{method} {uri} {proto}" {status} {size} "{>Referer}" "{>User-Agent}"
  3. json:

    {
       "timestamp": "{ts}",
       "remote_ip": "{remote}",
       "method": "{method}",
       "uri": "{uri}",
       "status": "{status}",
       "size": "{size}"
    }

使用预设格式:

example.com {
    log {
        output file /var/log/caddy/access.log
        format combined
    }
}

通过以上配置,可以灵活地自定义 Caddy 的访问日志格式,满足各种监控、分析和审计需求。

Caddy安装

适用于 Debian/Ubuntu 系统

sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https curl
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-stable.list
sudo apt update
sudo apt install caddy

Caddy官方文档

https://caddyserver.com/docs/api

https://caddyserver.com/docs/caddyfile

https://caddyserver.com/docs/

https://caddyserver.com/docs/getting-started

https://caddyserver.com/docs/install#install

https://caddyserver.com/docs/caddyfile/options

https://caddyserver.com/docs/caddyfile/directives

发表评论
博客分类