Files
OnlineJudge/deploy/caddy/Caddyfile
yuetsh 92e1c2b75d refactor(deploy): 容器内 nginx 换成 Caddy
TLS 和域名由前面的 Nginx Proxy Manager 负责,容器里这层只做静态文件
和反代,用 Caddy 配置更短,也消掉了两个坑:add_header 不继承、
entrypoint 里 __IP_HEADER__ 的 sed 替换。

- deploy/nginx/ 四个配置文件合并成一个 deploy/caddy/Caddyfile
- Dockerfile 去掉 nginx 包,改从官方镜像拷 Caddy 静态二进制
- supervisord 的 nginx 程序换成 caddy,跑在非特权的 server 账号下
- entrypoint 删掉自签证书、http_locations.conf 软链、IP header sed

行为对齐:body 上限写 200MiB 才等于 nginx 的 200M;心跳和 /assets/
继续不记访问日志;安全头、缓存策略、gzip 覆盖范围保持不变。

两处行为变化:
- 访问日志变成 JSON,路径 /data/log/caddy_access.log
- X-Accel-Buffering 是 nginx 私有头,AI 的 SSE 改由 flush_interval -1
  保证不缓冲,上线需实测

FORCE_HTTPS 和 LOWER_IP_HEADER 两个环境变量随之作废,真实 IP 改由
trusted_proxies + {client_ip} 从 NPM 的 XFF 解析。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-05 09:50:46 -06:00

78 lines
2.2 KiB
Caddyfile
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{
admin off
servers {
# TLS 由前面的 Nginx Proxy Manager 终止,转发进来是明文 http。
# 只信任内网来源的 X-Forwarded-For{client_ip} 才解析得出学生的真实 IP。
trusted_proxies static private_ranges
}
}
# 站点地址只写端口Caddy 就不会去申请证书auto-HTTPS 自动关闭)。
:8000 {
encode gzip
# 和 NPM 那一层的 client_max_body_size 保持一致,上传测试用例压缩包用得上。
# 必须写 MiBCaddy 的 MB 按 10^6 算200MB 比 nginx 的 200M 小了将近 10M。
request_body {
max_size 200MiB
}
# Caddy 的 header 会跨层叠加,不像 nginx 的 add_header 一旦在子块出现就不再继承,
# 所以这里写一次就够,下面各 handle 里只管自己的 Cache-Control。
header {
X-XSS-Protection "1; mode=block"
X-Frame-Options SAMEORIGIN
X-Content-Type-Options nosniff
}
log {
output file /data/log/caddy_access.log {
roll_size 10MiB
roll_keep 10
}
}
# 判题机心跳每秒一次;静态资源量大且带永久缓存。两者都不记访问日志。
@nolog path /api/judge_server_heartbeat/ /assets/*
log_skip @nolog
handle /api/* {
reverse_proxy 127.0.0.1:8080 {
header_up X-Real-IP {client_ip}
# AI 分析走 SSE。X-Accel-Buffering 是 nginx 专有的Caddy 不认,
# 这里显式关掉响应缓冲,保证流式输出逐块下发。
flush_interval -1
}
}
handle /ws/* {
reverse_proxy 127.0.0.1:8080 {
header_up X-Real-IP {client_ip}
}
}
# 头像、上传文件、站点图标,实际落在 /data/public 下。
handle /public/* {
root * /data
file_server
}
# 构建产物文件名带内容 hash内容一变文件名就变可以永久缓存。
# 命中后浏览器直接读磁盘,不再发条件请求。
handle /assets/* {
root * /app/dist
header Cache-Control "public, max-age=31536000, immutable"
file_server
}
# index.html 引用着带 hash 的文件名,必须每次回源校验,
# 否则发新版后学生刷不到。no-cache 是"缓存但每次校验",命中走 304。
handle {
root * /app/dist
header Cache-Control "no-cache"
try_files {path} /index.html
file_server
}
}