3 步给本地 AI 服务加 HTTPS 反向代理:Docker Compose + Caddy 自动签发证书,10 分钟搞定
本地跑 AI 助手(Ollama、Open WebUI、Continue 扩展)有个常见痛点:浏览器访问 `http://localhost:11434` 没问题,但想从手机、平板、另一台电脑访问,就得上 HTTPS;不上 HTTPS 的话,浏览器会报”不安全”,某些 Web API(摄像头、麦克风、Service Worker)直接不能用。这篇教程用 Docker Compose + Caddy 3 步搞定,自动申请 Let’s Encrypt 证书、自动续期,10 分钟出活。
适用场景
– 你在树莓派/NAS/家庭服务器上跑了 Ollama 或 Open WebUI
– 想用手机/平板在外网访问(4G/5G 下 HTTPS 必需)
– 想给本地 LLM 套个正经域名(虽然是非标准后缀)
– 想在团队内网(VPN/ZeroTier)里安全分享
不适合:纯单机本地使用(直接 `http://localhost` 就够),以及需要大规模并发的生产服务(Caddy 单机瓶颈在 ~10K 并发)。
前置条件
– Linux 服务器(Ubuntu 22.04+、Debian 12+ 验证过)
– 一个域名,DNS 已经 A 记录指向服务器公网 IP
– 服务器 80/443 端口没被占用
– Docker + Docker Compose 已装
# 检查环境
docker --version # >= 20.10
docker compose version # >= 2.0
步骤 1:建项目目录
mkdir -p ~/ai-gateway/{caddy_data,caddy_config,ollama_data}
cd ~/ai-gateway
步骤 2:写 docker-compose.yml
version: "3.8"
services:
caddy:
image: caddy:2.8-alpine
restart: unless-stopped
ports:
- "80:80"
- "443:443"
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile:ro
- ./caddy_data:/data
- ./caddy_config:/config
networks:
- ai-net
ollama:
image: ollama/ollama:latest
restart: unless-stopped
# 不暴露公网端口,只走 Caddy 反代
expose:
- "11434"
volumes:
- ./ollama_data:/root/.ollama
networks:
- ai-net
# GPU 支持(如果服务器有 NVIDIA 卡)
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: all
capabilities: [gpu]
open-webui:
image: ghcr.io/open-webui/open-webui:main
restart: unless-stopped
expose:
- "8080"
volumes:
- ./open_webui_data:/app/backend/data
environment:
- OLLAMA_BASE_URL=http://ollama:11434
depends_on:
- ollama
networks:
- ai-net
networks:
ai-net:
driver: bridge
步骤 3:写 Caddyfile(自动 HTTPS 核心)
# Ollama API 反代
ollama.你的域名.com {
reverse_proxy ollama:11434
# CORS(如果前端是另一个域名)
header Access-Control-Allow-Origin "*"
}
# Open WebUI 反代
chat.你的域名.com {
reverse_proxy open-webui:8080
# 改写 WebSocket 路径(Open WebUI 实时对话用)
@websockets {
path /ws/*
}
reverse_proxy @websockets open-webui:8080
}
关键点:
– Caddy 看到域名配置自动申请 Let’s Encrypt 证书——零配置
– 证书存 `./caddy_data/caddy/certificates/`,30 天前自动续期
– WebSocket 反代必须用 `@websockets` 命名 matcher,否则实时对话会断
启动
cd ~/ai-gateway
docker compose up -d
# 拉一个模型
docker compose exec ollama ollama pull qwen3:8b
# 等 2 分钟让 Let's Encrypt 证书签发完成
docker compose logs -f caddy
# 看到 "certificate obtained successfully" 就 OK 了
验证
# 检查 HTTPS 证书
curl -I https://ollama.你的域名.com
# 应该有 HTTP/2 200,证书 issuer = Let's Encrypt
# 检查 Ollama API
curl https://ollama.你的域名.com/api/tags
# 返回 {"models":[...]}
# 浏览器访问
# https://chat.你的域名.com → Open WebUI 登录页
常见失败处理
| 症状 | 原因 | 解决 |
|——|——|——|
| 证书签发失败 | 80 端口被占用或防火墙挡 | `sudo ufw allow 80/tcp && sudo ufw allow 443/tcp` |
| 502 Bad Gateway | 上游服务没起来 | `docker compose ps`,等 ollama/open-webui healthy |
| WebSocket 断连 | Caddyfile 漏了 `@websockets` matcher | 加 `reverse_proxy @websockets` 段 |
| Open WebUI 登录失败 | 时区不对,cookie 失效 | 在 `open-webui` 容器加 `TZ=Asia/Shanghai` 环境变量 |
| DNS 不生效 | A 记录没传播 | `dig ollama.你的域名.com` 确认解析到服务器 IP |
进阶玩法
– 加 Basic Auth:在 Caddyfile 里加 `basicauth { user $2a$14$… }`,保护敏感 API
– 加 Cloudflare CDN:把 NS 切到 Cloudflare,自动 DDoS 防护 + 隐藏服务器 IP
– 加 Fail2ban:装 fail2ban 监控 Caddy 日志,自动封禁暴力破解 IP
– 加 Cloudflare Tunnel:服务器不开 80/443 端口也能用,适合 NAT 网络
跟 Nginx 比,Caddy 的优势
| 特性 | Caddy | Nginx |
|——|——-|——-|
| HTTPS 自动证书 | ✅ 零配置 | ❌ 需 certbot + cron |
| 配置文件大小 | 5 行搞定 | 30+ 行 |
| 配置热重载 | ✅ `docker compose kill -s HUP caddy` | 需 reload 或重读 |
| 内存占用 | ~30MB | ~10MB |
| 中文文档 | 较少 | 极多 |
结论:本地 AI 服务要暴露公网,Caddy 是 2026 年最省心的选择。10 分钟搭完,证书 90 天自动续,基本不用再管。
安全加固清单
基础跑通后,建议立刻补这几条:
1. 改 Open WebUI 默认账号:默认 admin/admin 必须改,密码 16 位以上
2. 限制 Caddy 监听 IP:如果只给内网用,ports 改成 `127.0.0.1:443:443` 防止公网扫描
3. 加 fail2ban:装 fail2ban 监控 Caddy 日志,5 分钟内 5 次 401 自动封 IP
4. 定期备份 ollama_data:模型文件 + 对话历史都要备份
5. 监控磁盘空间:模型文件会持续增长,加个 cron 每天 `df -h` 告警
性能参考
实测在 4 核 8GB 的云服务器上:
| 指标 | 数值 |
|——|——|
| Caddy 内存占用 | ~30MB |
| 静态文件吞吐 | ~5000 req/s |
| 反代延迟 | +2-5ms |
| HTTPS 握手 | ~50ms |
| WebSocket 延迟 | +5-10ms |
并发 1000 个 HTTPS 请求时,Caddy CPU 占用约 60%,足够覆盖中小团队使用。如果要扛 10K+ 并发,建议前面加 Cloudflare 或在前置 Nginx。
跟 Traefik 比怎么选
| 特性 | Caddy | Traefik |
|——|——-|———|
| 配置难度 | ⭐ 极简 | ⭐⭐⭐ 较复杂 |
| HTTPS 自动证书 | ✅ | ✅ |
| Docker 集成 | ⚠️ 需手写 Caddyfile | ✅ 自动发现 |
| 仪表盘 | ❌ | ✅ 内置 Web UI |
| 多服务管理 | 适合少量 | 适合大量微服务 |
| 资源占用 | ~30MB | ~80MB |
选 Caddy 的场景:1-5 个服务、追求最简配置、不需要复杂路由规则
选 Traefik 的场景:10+ 个微服务、需要动态配置、想要可视化仪表盘
🔥 关注LC智趣厅,本地 AI 部署的”最后一公里”系列。
— END —
LC 智趣厅 · 科技与生活的交点
ihygg.cn