Caddy 教程

1. 核心概念

Caddy 是一款现代的、开源的 Web 服务器,以其自动 HTTPS 配置、简洁的配置语法和强大的功能而闻名。它由 Go 语言编写,支持 HTTP/1.1、HTTP/2 和 HTTP/3,并提供了丰富的功能,如反向代理、负载均衡、缓存、安全头等。

1.1 基本概念

  • 自动 HTTPS:Caddy 会自动为网站申请和续期 SSL/TLS 证书,无需手动配置。
  • Caddyfile:Caddy 的配置文件,使用简洁的语法定义服务器行为。
  • 反向代理:将客户端请求转发到后端服务器,并将响应返回给客户端。
  • 负载均衡:将请求分发到多个后端服务器,提高系统的可用性和性能。
  • 中间件:Caddy 的功能扩展,通过中间件提供各种功能。
  • 虚拟主机:在单个 Caddy 实例上托管多个网站。
  • HTTP/3:支持 HTTP/3(QUIC)协议,提供更快的网络传输速度。

1.2 工作原理

  • 配置解析:Caddy 启动时解析 Caddyfile 或 JSON 配置,生成运行时配置。
  • HTTPS 管理:自动为域名申请、配置和续期 SSL/TLS 证书。
  • 请求处理:接收 HTTP 请求,根据配置进行处理,返回响应。
  • 中间件链:使用中间件链处理请求,每个中间件负责特定的功能。
  • 自动重载:当配置文件更改时,自动重载配置,无需手动重启。

2. 安装配置

2.1 安装 Caddy

2.1.1 Windows

Caddy 官方网站 下载 Windows 版本的 Caddy,解压后即可使用。

2.1.2 macOS

使用 Homebrew 安装:

brew install caddy

2.1.3 Linux

使用官方安装脚本:

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

或者使用 Docker:

docker pull caddy:latest
docker run -d --name caddy -p 80:80 -p 443:443 -v $PWD/Caddyfile:/etc/caddy/Caddyfile -v caddy_data:/data caddy

2.2 基本配置

2.2.1 Caddyfile 配置

最简单的配置

# 静态网站托管
example.com {
    root * /var/www/html
    file_server
}

反向代理配置

# 反向代理
example.com {
    reverse_proxy localhost:3000
}

HTTPS 配置

# HTTPS 配置(Caddy 会自动处理证书)
example.com {
    root * /var/www/html
    file_server
    tls admin@example.com
}

2.3 配置管理

2.3.1 启动 Caddy

# 使用默认 Caddyfile 启动
caddy run

# 指定 Caddyfile 启动
caddy run --config /path/to/Caddyfile

# 以守护进程方式运行
sudo systemctl start caddy
sudo systemctl enable caddy

2.3.2 重载配置

# 重载配置
caddy reload

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

2.3.3 停止 Caddy

# 停止 Caddy
caddy stop

# 或者使用系统服务管理
sudo systemctl stop caddy

3. 基本使用

3.1 静态网站托管

配置示例

# 静态网站托管
example.com {
    # 设置网站根目录
    root * /var/www/example.com
    
    # 启用文件服务器
    file_server
    
    # 启用目录索引
    file_server browse
    
    # 自定义错误页面
    handle_errors {
        respond "Error {err.status_code}" {
            status {err.status_code}
        }
    }
}

3.2 反向代理

配置示例

# 反向代理
example.com {
    # 转发到后端服务器
    reverse_proxy localhost:3000
    
    # 配置代理头
    reverse_proxy {
        to 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}
    }
}

3.3 负载均衡

配置示例

# 负载均衡
example.com {
    reverse_proxy {
        # 后端服务器列表
        to localhost:3000 localhost:3001 localhost:3002
        
        # 负载均衡策略(random, least_conn, round_robin)
        lb_policy round_robin
        
        # 健康检查
        health_check /health
    }
}

3.4 虚拟主机

配置示例

# 虚拟主机 1
site1.com {
    root * /var/www/site1
    file_server
}

# 虚拟主机 2
site2.com {
    reverse_proxy localhost:8000
}

# 基于端口的虚拟主机
:8080 {
    root * /var/www/port8080
    file_server
}

4. 高级功能

4.1 缓存配置

配置示例

# 缓存配置
example.com {
    root * /var/www/example.com
    file_server
    
    # 启用缓存
    respond cache {
        # 缓存目录
        cache {
            api  # 启用缓存 API
            default_ttl 1h  # 默认缓存时间
            expiry 24h  # 缓存过期时间
            keys_zone {
                name cache_zone
                size 10m  # 缓存键区大小
            }
            memory {
                max_size 100m  # 内存缓存大小
            }
        }
    }
    
    # 缓存静态资源
    @static {
        file
        path *.css *.js *.jpg *.jpeg *.png *.gif *.ico *.svg
    }
    
    handle @static {
        header Cache-Control "max-age=86400, public"
        file_server
    }
}

4.2 安全配置

配置示例

# 安全配置
example.com {
    root * /var/www/example.com
    file_server
    
    # 安全头
    header {
        # HSTS
        Strict-Transport-Security "max-age=31536000; includeSubDomains"
        
        # X-Content-Type-Options
        X-Content-Type-Options "nosniff"
        
        # X-Frame-Options
        X-Frame-Options "DENY"
        
        # X-XSS-Protection
        X-XSS-Protection "1; mode=block"
        
        # Content-Security-Policy
        Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self';"
    }
    
    # 限制请求方法
    @blocked {
        method PUT DELETE PATCH
    }
    handle @blocked {
        respond "Method not allowed" 405
    }
}

4.3 URL 重写和重定向

配置示例

# URL 重写和重定向
example.com {
    root * /var/www/example.com
    file_server
    
    # 重定向到 HTTPS(Caddy 会自动处理,但可以手动指定)
    @http {
        scheme http
    }
    redir @http https://{host}{uri} permanent
    
    # 重写规则
    @old_path {
        path /old/*
    }
    rewrite @old_path /new{path}
    
    # 重定向规则
    @old_url {
        path /old-url
    }
    redir @old_url /new-url permanent
    
    # 去除尾部斜杠
    @trailing_slash {
        path */
    }
    redir @trailing_slash {path}/ permanent
}

4.4 响应压缩

配置示例

# 响应压缩
example.com {
    root * /var/www/example.com
    file_server
    
    # 启用压缩
    encode {
        gzip
        zstd
    }
    
    # 配置压缩级别
    encode gzip {
        level 5
    }
}

4.5 基本认证

配置示例

# 基本认证
example.com {
    root * /var/www/example.com
    file_server
    
    # 基本认证
    basicauth * {
        # 用户名和密码(密码使用 caddy hash-password 生成)
        admin {$HASHED_PASSWORD}
    }
    
    # 只对特定路径启用认证
    @protected {
        path /admin/*
    }
    handle @protected {
        basicauth {
            admin {$HASHED_PASSWORD}
        }
        file_server
    }
}

5. 最佳实践

5.1 配置最佳实践

  • 使用环境变量:在配置文件中使用环境变量,避免硬编码敏感信息。
  • 模块化配置:将复杂的配置分解为多个小文件,提高可读性和可维护性。
  • 使用注释:在配置文件中添加注释,说明配置的目的和功能。
  • 保持配置简洁:只配置必要的选项,避免冗余配置。
  • 使用标准端口:使用标准的 HTTP(80)和 HTTPS(443)端口,避免使用非标准端口。

5.2 性能优化

  • 启用 HTTP/3:启用 HTTP/3(QUIC),提高网络传输速度。
  • 启用压缩:启用 gzip 或 zstd 压缩,减少传输数据量。
  • 配置缓存:为静态资源配置合理的缓存策略,减少重复请求。
  • 优化 TLS:使用现代的 TLS 配置,提高安全性和性能。
  • 使用负载均衡:对于高流量网站,使用负载均衡分散请求。
  • 调整工作进程:根据服务器硬件,调整 Caddy 的工作进程数。

5.3 安全最佳实践

  • 保持 Caddy 更新:及时更新 Caddy 到最新版本,修复安全漏洞。
  • 使用强密码:为基本认证使用强密码,并定期更换。
  • 限制访问:使用 IP 限制、基本认证等方式限制对敏感路径的访问。
  • 配置安全头:设置适当的安全头,如 HSTS、X-Content-Type-Options 等。
  • 监控日志:定期检查 Caddy 日志,及时发现异常情况。
  • 使用防火墙:配置防火墙,限制对 Caddy 端口的访问。

6. 实用应用案例

6.1 企业网站托管

场景:托管企业官网,提供静态内容和动态应用,自动配置 HTTPS。

配置

# 企业网站托管
example.com {
    # 设置网站根目录
    root * /var/www/example.com
    
    # 启用文件服务器
    file_server
    
    # 自动 HTTPS 配置
    tls admin@example.com
    
    # 启用 HTTP/3
    servers {
        protocol {
            experimental_http3
        }
    }
    
    # 安全头
    header {
        Strict-Transport-Security "max-age=31536000; includeSubDomains"
        X-Content-Type-Options "nosniff"
        X-Frame-Options "DENY"
        X-XSS-Protection "1; mode=block"
        Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self';"
    }
    
    # 压缩
    encode gzip zstd
    
    # 静态资源缓存
    @static {
        file
        path *.css *.js *.jpg *.jpeg *.png *.gif *.ico *.svg *.woff *.woff2 *.ttf *.eot
    }
    
    handle @static {
        header Cache-Control "max-age=2592000, public"
        file_server
    }
    
    # 动态内容反向代理
    @api {
        path /api/*
    }
    
    handle @api {
        reverse_proxy localhost:8000 {
            header_up Host {host}
            header_up X-Real-IP {remote_host}
            header_up X-Forwarded-For {remote_host}
            header_up X-Forwarded-Proto {scheme}
        }
    }
    
    # 自定义错误页面
    handle_errors {
        @404 {
            expression {err.status_code} == 404
        }
        respond @404 "Page not found" 404
        
        @500 {
            expression {err.status_code} >= 500
        }
        respond @500 "Internal server error" 500
    }
}

6.2 API 网关

场景:作为 API 网关,转发请求到不同的后端服务,提供认证、限流等功能。

配置

# API 网关
api.example.com {
    # 自动 HTTPS
    tls admin@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"
    }
    
    # 压缩
    encode gzip zstd
    
    # 认证中间件
    @auth {
        not path /public/*
    }
    
    handle @auth {
        # 验证 API 密钥
        request_header Authorization {
            not has "Bearer"
            respond "Unauthorized" 401
        }
        
        # 这里可以添加更复杂的认证逻辑
    }
    
    # 后端服务 1
    @service1 {
        path /service1/*
    }
    
    handle @service1 {
        reverse_proxy localhost:8001 {
            header_up Host {host}
            header_up X-Real-IP {remote_host}
            header_up X-Forwarded-For {remote_host}
            header_up X-Forwarded-Proto {scheme}
        }
    }
    
    # 后端服务 2
    @service2 {
        path /service2/*
    }
    
    handle @service2 {
        reverse_proxy localhost:8002 {
            header_up Host {host}
            header_up X-Real-IP {remote_host}
            header_up X-Forwarded-For {remote_host}
            header_up X-Forwarded-Proto {scheme}
        }
    }
    
    # 健康检查
    @health {
        path /health
    }
    
    handle @health {
        respond "OK" 200
    }
}

6.3 微服务架构中的前端代理

场景:在微服务架构中,作为前端代理,将请求转发到不同的微服务。

配置

# 微服务架构中的前端代理
app.example.com {
    # 自动 HTTPS
    tls admin@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"
    }
    
    # 压缩
    encode gzip zstd
    
    # 前端应用
    root * /var/www/frontend
    file_server
    
    # 前端路由处理(单页应用)
    try_files {path} /index.html
    
    # API 路由
    @api {
        path /api/*
    }
    
    handle @api {
        reverse_proxy localhost:8080 {
            header_up Host {host}
            header_up X-Real-IP {remote_host}
            header_up X-Forwarded-For {remote_host}
            header_up X-Forwarded-Proto {scheme}
        }
    }
    
    # 认证服务
    @auth {
        path /auth/*
    }
    
    handle @auth {
        reverse_proxy localhost:8081 {
            header_up Host {host}
            header_up X-Real-IP {remote_host}
            header_up X-Forwarded-For {remote_host}
            header_up X-Forwarded-Proto {scheme}
        }
    }
    
    # 静态资源缓存
    @static {
        file
        path *.css *.js *.jpg *.jpeg *.png *.gif *.ico *.svg *.woff *.woff2 *.ttf *.eot
    }
    
    handle @static {
        header Cache-Control "max-age=2592000, public"
        file_server
    }
}

6. 总结

Caddy 是一款现代化的 Web 服务器,以其自动 HTTPS 配置、简洁的配置语法和强大的功能而受到越来越多开发者的喜爱。它不仅适合托管静态网站,还可以作为反向代理、API 网关等角色,为各种 Web 应用场景提供解决方案。

通过本教程的学习,您应该已经掌握了 Caddy 的核心概念、安装配置、基本使用、高级功能和最佳实践。在实际应用中,您可以根据具体的需求,灵活配置 Caddy,以满足不同场景的要求。

6.1 核心优势

  • 自动 HTTPS:Caddy 会自动为网站申请和续期 SSL/TLS 证书,无需手动配置。
  • 简洁的配置语法:Caddyfile 使用简洁、直观的语法,易于学习和使用。
  • 现代化特性:支持 HTTP/2、HTTP/3、QUIC 等现代 Web 协议。
  • 强大的功能:内置反向代理、负载均衡、缓存、安全头等功能。
  • 跨平台:支持 Windows、macOS、Linux 等多种操作系统。
  • 高性能:由 Go 语言编写,具有良好的性能和并发处理能力。
  • 开源免费:开源软件,免费使用。

6.2 应用前景

随着 Web 技术的不断发展,对 Web 服务器的要求也越来越高。Caddy 作为一款现代化的 Web 服务器,在以下场景中有着广泛的应用前景:

  • 静态网站托管:为个人博客、企业官网等提供简单、安全的托管方案。
  • API 网关:作为微服务架构中的 API 网关,管理服务间的通信。
  • 反向代理:为后端应用提供反向代理服务,实现负载均衡、安全防护等功能。
  • 开发环境:在开发环境中快速搭建本地服务器,支持 HTTPS。
  • 边缘服务器:在边缘节点部署,提供内容分发、缓存等功能。

通过不断学习和实践 Caddy 的功能和最佳实践,您可以充分发挥 Caddy 的优势,构建高性能、可靠、安全的 Web 服务。

« 上一篇 Apache HTTP Server 教程 下一篇 » HAProxy 教程