认证方式

先说结论:Ollama 本身不提供内置的认证机制。但这不代表你不能给 API 加认证。

这一章我们聊聊几种常见的认证方案,以及如何实现。

默认情况

默认安装的 Ollama,API 是没有任何认证的:

curl http://localhost:11434/api/version

任何人只要能访问这个地址,就能调用所有 API。

这在本地开发时没问题,但如果要部署到生产环境,就需要考虑安全性了。

为什么需要认证?

几个常见的安全风险:

数据泄露

API 暴露在公网,任何人都能调用你的模型,消耗你的算力。

滥用风险

没有限制,可能被用来生成垃圾内容、刷量等。

合规问题

某些场景下,需要记录谁在什么时候调用了什么接口。

方案一:网络层限制

最简单的方式,限制谁能访问。

本地访问

只监听本地回环地址:

OLLAMA_HOST=127.0.0.1:11434 ollama serve

这样只有本机的程序能访问 API。

内网访问

限制在内网范围:

OLLAMA_HOST=10.0.0.1:11434 ollama serve

配合防火墙规则:

# 只允许特定 IP 访问
sudo ufw allow from 10.0.0.0/8 to any port 11434

VPN/隧道

通过 VPN 或 SSH 隧道访问:

# SSH 隧道
ssh -L 11434:localhost:11434 user@server

然后本地连接:

curl http://localhost:11434/api/version

方案二:反向代理认证

这是最常用的方案。在 Ollama 前面加一层反向代理,由代理负责认证。

Nginx Basic Auth

最简单的 HTTP Basic 认证:

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

    location / {
        auth_basic "Ollama API";
        auth_basic_user_file /etc/nginx/.htpasswd;
        
        proxy_pass http://127.0.0.1:11434;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

创建密码文件:

sudo htpasswd -c /etc/nginx/.htpasswd admin
# 输入密码

调用时带上认证信息:

curl -u admin:password http://ollama.example.com/api/version

API Key 认证

更灵活的方式,用 API Key:

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

    location / {
        if ($http_x_api_key != "your-secret-key") {
            return 401;
        }
        
        proxy_pass http://127.0.0.1:11434;
    }
}

调用时在 Header 中传递:

curl -H "X-API-Key: your-secret-key" http://ollama.example.com/api/version

多 API Key 管理

如果需要给不同用户分配不同的 Key,可以用 Lua 或外部认证服务:

# 使用 auth_request 模块
location / {
    auth_request /auth;
    
    proxy_pass http://127.0.0.1:11434;
}

location = /auth {
    internal;
    proxy_pass http://auth-service:8080/validate;
    proxy_pass_request_body off;
    proxy_set_header X-Original-URI $request_uri;
    proxy_set_header X-API-Key $http_x_api_key;
}

方案三:应用层认证

在你的应用代码中实现认证逻辑。

Python 示例

from fastapi import FastAPI, Header, HTTPException
import httpx

app = FastAPI()

VALID_KEYS = {"key-1", "key-2", "key-3"}

@app.api_route("/{path:path}", methods=["GET", "POST", "DELETE"])
async def proxy(path: str, x_api_key: str = Header(None)):
    if x_api_key not in VALID_KEYS:
        raise HTTPException(status_code=401, detail="Invalid API Key")
    
    async with httpx.AsyncClient() as client:
        response = await client.request(
            method=request.method,
            url=f"http://localhost:11434/{path}",
            content=await request.body(),
        )
        return response.json()

Node.js 示例

const express = require('express');
const { createProxyMiddleware } = require('http-proxy-middleware');

const app = express();

const validKeys = new Set(['key-1', 'key-2', 'key-3']);

app.use((req, res, next) => {
    const apiKey = req.headers['x-api-key'];
    if (!validKeys.has(apiKey)) {
        return res.status(401).json({ error: 'Invalid API Key' });
    }
    next();
});

app.use('/', createProxyMiddleware({
    target: 'http://localhost:11434',
    changeOrigin: true
}));

app.listen(3000);

方案四:OAuth 2.0 / JWT

对于需要对接现有认证系统的场景,可以用 OAuth 2.0 或 JWT。

JWT 验证示例

# 需要 nginx-plus 或 openresty
# 这里展示思路

location / {
    access_by_lua_block {
        local jwt = require "resty.jwt"
        local token = ngx.var.http_authorization
        
        if not token then
            ngx.exit(401)
        end
        
        local jwt_obj = jwt:verify("secret-key", token)
        if not jwt_obj.verified then
            ngx.exit(401)
        end
    }
    
    proxy_pass http://127.0.0.1:11434;
}

HTTPS 加密

认证信息如果不加密传输,等于没有。生产环境务必启用 HTTPS。

Let's Encrypt 免费证书

sudo certbot --nginx -d ollama.example.com

自签名证书

测试环境可以用自签名证书:

openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
  -keyout /etc/nginx/ollama.key \
  -out /etc/nginx/ollama.crt

Nginx 配置:

server {
    listen 443 ssl;
    server_name ollama.example.com;

    ssl_certificate /etc/nginx/ollama.crt;
    ssl_certificate_key /etc/nginx/ollama.key;

    location / {
        auth_basic "Ollama API";
        auth_basic_user_file /etc/nginx/.htpasswd;
        
        proxy_pass http://127.0.0.1:11434;
    }
}

认证方案选择

方案复杂度适用场景
网络层限制内网、个人使用
Basic Auth小团队、简单场景
API Key多用户、需要区分身份
OAuth/JWT企业级、对接现有系统

最佳实践

不要硬编码密钥

把密钥放在环境变量或配置文件中:

export OLLAMA_API_KEY="your-secret-key"

定期轮换密钥

定期更换 API Key,降低泄露风险。

记录访问日志

记录谁在什么时候调用了什么接口:

log_format api_log '$remote_addr - $http_x_api_key [$time_local] '
                   '"$request" $status $body_bytes_sent';
access_log /var/log/nginx/ollama.log api_log;

限制请求频率

防止滥用:

limit_req_zone $http_x_api_key zone=api_limit:10m rate=10r/s;

location / {
    limit_req zone=api_limit burst=20 nodelay;
    proxy_pass http://127.0.0.1:11434;
}