🌐

用 Caddy + Nginx 反向代理本地 LLM API

将 Ollama 或 vLLM 的 API 通过 Caddy 或 Nginx 反向代理到公网,配合自定义域名和 SSL 证书实现安全的远程调用。支持鉴权、流量限制、日志记录。

API Caddy Nginx 代理 SSL

本地运行的 Ollama 或 vLLM 只能在局域网内访问。本教程教你用反向代理将其暴露到公网,支持自定义域名、自动 HTTPS(Let's Encrypt)、API 密钥鉴权。适用于远程开发、团队共享、移动端调用等场景。

为什么需要反向代理

直接暴露本地端口的问题:

反向代理解决以上所有问题:

对比项 Caddy Nginx Cloudflare Tunnel
配置难度 ⭐ 最简单 ⭐⭐⭐ 中等 ⭐ 最简单
自动 HTTPS ✅ 内置 ❌ 需额外配置 ✅ 内置
需要公网 IP
API 鉴权 插件/中间件 ngx_http_auth_request Access Policy

方案一:Caddy(推荐)

Caddy 是最简单的方式,配置文件只需 5 行就能实现自动 HTTPS + 反向代理。

安装 Caddy

$
# Ubuntu/Debian 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.gpg curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy.list sudo apt update && sudo apt install caddy

编写 Caddyfile

# /etc/caddy/Caddyfile

# Ollama API(完整 OpenAI 兼容)
api.ollama.example.com {
    reverse_proxy localhost:11434
    encode gzip
    log {
        output file /var/log/caddy/ollama.log
    }
}

# vLLM API
api.vllm.example.com {
    reverse_proxy localhost:8000
    encode gzip
    log {
        output file /var/log/caddy/vllm.log
    }
}

启动 Caddy

$
sudo caddy fmt --overwrite /etc/caddy/Caddyfile sudo systemctl enable --now caddy
Caddy 自动 HTTPS 生效!
Caddy 会自动从 Let's Encrypt 申请 SSL 证书。访问 https://api.ollama.example.com 即可看到 Ollama 的 API 响应。

方案二:Nginx

安装 Nginx

$
sudo apt update && sudo apt install -y nginx certbot python3-certbot-nginx

配置反向代理

创建 /etc/nginx/sites-available/ollama

server {
    listen 80;
    server_name api.ollama.example.com;

    location / {
        proxy_pass http://127.0.0.1:11434;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_cache_bypass $http_upgrade;

        # 超时设置(LLM 响应可能很慢)
        proxy_read_timeout 300s;
        proxy_connect_timeout 75s;
        proxy_send_timeout 300s;

        # 关闭请求体大小限制
        client_max_body_size 100M;
    }

    access_log /var/log/nginx/ollama_access.log;
    error_log /var/log/nginx/ollama_error.log;
}

启用站点并申请 SSL

$
sudo ln -s /etc/nginx/sites-available/ollama /etc/nginx/sites-enabled/ sudo nginx -t sudo systemctl reload nginx # 申请 SSL 证书 sudo certbot --nginx -d api.ollama.example.com

自动续期 SSL

$
sudo certbot renew --dry-run
💡
Certbot 自动续期
Certbot 会自动添加 cron job 到 /etc/cron.d/certbot。SSL 证书每 90 天自动续期,无需手动操作。

API 密钥鉴权

如果不想公开 API,需要添加鉴权。

Nginx + HTTP Basic Auth

$
# 创建密码文件 sudo apt install -y apache2-utils sudo htpasswd -bc /etc/nginx/.htpasswd admin your_secure_password # 修改 Nginx 配置,在 location 内添加: # auth_basic "Restricted API"; # auth_basic_user_file /etc/nginx/.htpasswd; sudo nginx -t && sudo systemctl reload nginx

Nginx + Bearer Token

使用 Lua 模块实现 Bearer Token 验证:

server {
    listen 80;
    server_name api.ollama.example.com;

    # 验证 Bearer Token
    location / {
        if ($http_authorization !~ "^Bearer sk-ollama-secret-key-12345") {
            return 401 '{"error": "Unauthorized"}';
        }

        proxy_pass http://127.0.0.1:11434;
        proxy_http_version 1.1;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

Caddy + Basic Auth

api.ollama.example.com {
    basic_auth {
        admin JDJhJDEwJEVCc0wuUUtxcG9LUXVNZVlxLkRLTGg=
    }
    reverse_proxy localhost:11434
}

客户端调用方式

$
# curl 调用 curl https://api.ollama.example.com/v1/chat/completions \ -H "Authorization: Bearer sk-ollama-secret-key-12345" \ -H "Content-Type: application/json" \ -d '{"model": "llama3.2:3b", "messages": [{"role": "user", "content": "Hello"}]}'

Cloudflare Tunnel(零部署)

如果你没有公网服务器或不想暴露端口,Cloudflare Tunnel 是最简单方案。零配置、不需要公网 IP。

安装 cloudflared

$
# Linux curl -L https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64 -o cloudflared chmod +x cloudflared sudo mv cloudflared /usr/local/bin/ # macOS brew install cloudflare/cloudflare/cloudflared

创建 Tunnel

$
# 登录 Cloudflare(浏览器会自动打开) cloudflared tunnel login # 创建隧道 cloudflared tunnel create ollama-proxy # 查看隧道 ID cloudflared tunnel list

配置 Tunnel

# ~/.cloudflared/config.yml
tunnel: <TUNNEL_ID>
credentials-file: ~/.cloudflared/<TUNNEL_ID>.json

ingress:
  - hostname: api.ollama.example.com
    service: http://localhost:11434
  - service: http_status:404

启动 Tunnel

$
# 前台运行测试 cloudflared tunnel run ollama-proxy # 后台运行 cloudflared service install
💡
Zero Trust 策略
在 Cloudflare Zero Trust Dashboard 中可以给 Tunnel 绑定 Access Policy,只允许特定邮箱/IP 访问,或添加 OTP 验证。

测试与验证

测试本地 Ollama

$
curl http://localhost:11434/api/tags

测试公网 API

$
# 测试 OpenAI 兼容端点 curl https://api.ollama.example.com/v1/models \ -H "Authorization: Bearer sk-ollama-secret-key-12345" # 测试完整对话 curl https://api.ollama.example.com/v1/chat/completions \ -H "Authorization: Bearer sk-ollama-secret-key-12345" \ -H "Content-Type: application/json" \ -d '{ "model": "llama3.2:3b", "messages": [{"role": "user", "content": "Say hello in 5 words"}], "max_tokens": 20 }'

测试 Claude App 接入

$
# 在 Claude Desktop 中配置 # File: ~/Library/Application Support/Claude/claude_desktop_config.json { "mcpServers": { "ollama": { "command": "ollama", "args": ["serve"], "env": { "OLLAMA_HOST": "https://api.ollama.example.com" } } } }

安全注意事项

⚠️
暴露本地服务到公网的风险
请务必配置 API 鉴权!没有鉴权的 LLM API 可能被他人滥用,产生额外费用或被用于生成有害内容。

安全清单

防火墙配置

$
# 只允许本地访问 Ollama 端口 sudo ufw allow 80/tcp sudo ufw allow 443/tcp sudo ufw deny 11434/tcp sudo ufw enable
Advertisement