简单的 Ollama 部署方案(含 API Key 认证)
你好塞尔达
2025年02月28日 23:12

简单的 Ollama 部署方案(含 API Key 认证)

下面提供一个完整的部署方案,使用 FastAPI 作为代理来保护 Ollama 的本地 LLM 服务,并添加 API Key 认证机制。方案包括步骤说明、配置建议和代码示例。

1. 使用 FastAPI 作为 API 代理

我们将使用 FastAPI 构建一个轻量的 API 服务充当代理(Gateway)。FastAPI 应用将拦截外部请求,先验证 API Key,再将请求转发给后端的 Ollama 服务。这样可以确保只有携带有效 API Key 的请求才能访问 Ollama 的接口。

实现思路:FastAPI 提供高性能的异步 Web 框架,可以方便地定义接口和中间件。我们将在 FastAPI 中定义与 Ollama 服务对应的接口(例如文本生成接口),在处理函数中先检查 API Key 是否正确,然后使用 HTTP 请求将数据转发给本地运行的 Ollama HTTP API,最后把 Ollama 的响应返回给客户端。通过这种代理模式,直接调用 Ollama 接口的请求将被封锁,只有通过 FastAPI 代理且提供正确密钥的请求才会到达 Ollama,提高安全性。

步骤概览

  • 启动 FastAPI 应用作为网关(可以绑定本机某端口,如8000)。

  • FastAPI 的每个受保护路由都会检查请求头中是否携带了正确的 API Key。

  • 若验证通过,FastAPI 内部再向 Ollama 的本地接口发起请求(如使用 requests 或 httpx 库),获取结果。

  • FastAPI 将 Ollama 的响应结果返回给前端调用者。对于未经授权的请求,直接返回 HTTP 401 未授权错误。

通过这种方式,我们无需直接暴露 Ollama 自带的服务端口,客户端只能通过我们定义的安全代理访问模型服务。

2. API Key 认证机制

为了保护接口,我们引入 API Key 认证。具体包含以下几个方面:

  • API Key 的生成:API Key 本质上是服务器提供的一串随机字符串,用于识别和授权客户端。您可以使用高强度的随机算法来生成。例如,在 Python 中可以使用 secrets 模块生成:

  • python

  • 复制

import secretskey = secrets.token_urlsafe(32) print(key)

  • 这将生成一个32字节长度、安全随机的字符串作为API Key。也可以使用 uuid4() 生成UUID字符串,或其他随机数生成器。关键是要足够长、随机,避免容易被猜测。生成后,将该 API Key 安全地提供给需要调用API的客户端。

  • API Key 的存储:服务器需要安全地保存和检索这个密钥以进行校验。常见方式有:

    • 环境变量:推荐将 API Key 保存为环境变量,例如在部署主机上设置 API_KEY="<生成的密钥>"。FastAPI 应用启动时从环境变量读取。这样密钥不会写死在代码中,泄露风险较小。

    • 配置文件:有时会将密钥存入配置文件或 .env 文件,并在启动时加载。但要确保配置文件不会被非授权访问(可通过文件权限或不提交到版本库等方式保护)。

    • 数据库:如果需要支持多个API Key或者需要动态管理,可以将密钥存储在数据库中(比如一张表存储有效的 API Key 列表)。每次请求时查询验证。但对于简单场景,环境变量或配置文件足够且更高效。

    • 硬编码:将密钥直接写在代码里(如全局变量)。不推荐这种方式,因为密钥会明文出现在代码中,一旦代码泄露或被查看,密钥也随之泄露。仅在测试阶段可临时硬编码。

  • API Key 的传递与验证:我们选择通过HTTP请求头来传递API Key,例如使用自定义头部 X-API-Key,或者使用标准的 Authorization 头部携带一个Bearer令牌。客户端调用API时需在请求头附上密钥,格式例如:

makefile 复制 X-API-Key: <您的API密钥>

  • 在 FastAPI 中,我们将在每个受保护的路由处理函数中获取该请求头的值,与服务器保存的正确密钥比对:

    • 若请求未提供此头或密钥不匹配,则返回HTTP 401 Unauthorized响应,拒绝请求。

    • 若密钥验证通过,则继续处理请求并访问后端服务。

通过上述机制,可以简单有效地限制只有持有正确API Key的客户端调用接口。在实施过程中,可以利用 FastAPI 的依赖注入机制编写一个公用的验证函数,将其添加为依赖,从而在多个路由上复用认证逻辑。

3. Ollama 部署步骤

Ollama 简介:Ollama 是一个用于本地运行大型语言模型(LLM)的工具或服务。安装并运行 Ollama 后,它会在本地开启一个 HTTP 接口供我们调用模型推理。根据官方配置,Ollama 默认监听本地端口 11434

dev.to

。我们的FastAPI代理将调用这个本地接口。部署 Ollama 的步骤如下:

  • 安装 Ollama:根据您所使用的平台安装 Ollama。

    • 在 macOS 上,可以通过 Homebrew 安装:brew install ollama,或从官方网站下载可执行文件。Mac 版的 Ollama 也提供一个应用程序界面,启动后会在后台运行服务。

    • 在 Linux 上,可以通过官方网站提供的安装脚本或Deb包安装 Ollama。也可以使用 Docker 镜像运行 Ollama(官方提供了 ollama/ollama 镜像)。

    • 在 Windows 上,参考 Ollama 官方文档进行安装(可能需要 WSL 或 Docker 来运行Linux版本,或使用Windows原生版本如果有提供)。

  • 下载/加载模型:安装完成后,使用 ollama pull <模型名称> 下载所需的模型(如 ollama pull llama2 或其他模型名称)。确保模型已经被加载,Ollama 才能处理相应请求。

  • 运行 Ollama 服务:启动 Ollama 的本地服务。有两种方式:

  1. 命令行直接运行:执行命令 ollama serve 启动后台服务。默认情况下,它会在本地主机 (127.0.0.1) 的11434端口启动HTTP服务​

github.com

。您可以通过设置环境变量来修改监听地址,例如:bash 复制 export OLLAMA_HOST="127.0.0.1:11435" ollama serve

  1. 上述方式将 Ollama 服务改为监听 127.0.0.1:11435​

github.com

  1. 。若要允许局域网/公网访问,也可以将主机设为 0.0.0.0(如 OLLAMA_HOST="0.0.0.0:11434"),但一般不建议直接开放 Ollama 端口给外部。

  2. 操作系统服务:在某些平台上,Ollama 安装后会作为系统服务或应用自动运行(例如 macOS 安装应用后通常自动在11434端口提供服务,因此无需手动 ollama serve)。可以通过 ollama status 或 ollama ps 等命令确认服务是否在运行。

  3. 验证 Ollama 服务:Ollama 启动后,我们可以在服务器本机上测试其API是否工作。例如,使用 curl 测试文本生成接口:

bash 复制 curl http://localhost:11434/api/generate -d '{ "model": "<模型名称>", "prompt": "Hello, world!", "stream": false }'

  • 若一切正常,Ollama 会返回生成的文本结果(以JSON格式返回,因为请求中 stream 参数为 false 时,响应就是一个完整的 JSON 对象​

dev.to

  • )。以上命令仅用于本地测试,实际部署中我们不会直接暴露该接口。

完成以上步骤后,Ollama 的模型推理服务就在本机运行了。接下来,我们让 FastAPI 去调用 http://localhost:11434/api/generate 这样的内部接口来获得结果。

4. 反向代理(可选)

为了加强安全性和提升性能,我们可以在 FastAPI 之前再加一层 Nginx 作为反向代理服务器。此步骤不是必须的,但在生产环境中是常见做法:

  • 用途:Nginx 可以用于承载域名、处理TLS/SSL加密、做负载均衡以及提供更高效的静态资源服务等。将其作为反向代理,可以把来自公网的请求转发给内部的 FastAPI 服务,从而隐藏 FastAPI 和 Ollama 所在的端口。同时Nginx可以限制访问来源、提供基本的DDOS防护等。

  • 部署:在服务器上安装 Nginx 后,可以编写一个站点配置,将指定的请求转发:

    • 监听公网端口(例如80或443)。

    • 转发路径 / 下的所有HTTP请求到本地 FastAPI 服务端口(例如127.0.0.1:8000)。

    • 设置所需的头信息转发,如 Host、X-Real-IP 等。

  • 示例配置:以下是一个简化的 Nginx 配置示例(假设 FastAPI 运行在本机 8000 端口):

nginx 复制 server { listen 80; server_name example.com; # 将example.com替换为您的域名或服务器IP location / { proxy_pass http://127.0.0.1:8000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } }

  • 上述配置监听80端口的所有请求,并将其转发到本地8000端口(FastAPI)。proxy_set_header 指令确保客户端的 Host 和 IP 信息传递给后端。您可以根据需要增加其它设置,比如启用SSL(listen 443 并配置证书),开启 gzip 压缩,连接超时等。

  • : 如果没有使用FastAPI代理,直接让Nginx转发到 Ollama 默认11434端口也是可行的​

restack.io

  • ;但那样将绕过API Key认证。因此在本方案中,Nginx应当代理到FastAPI,由FastAPI执行认证和调用模型。另请确保 Ollama 服务本身仍只监听本地接口,以免被绕过直接访问。

通过Nginx这一层,我们的架构将更加健壮:客户端 -> Nginx (反向代理) -> FastAPI (API网关,验证API Key) -> Ollama (LLM服务)。

5. 示例代码

下面提供一个完整的 FastAPI 应用示例代码,演示如何实现 API Key 验证并将请求转发给 Ollama 后端。可以将此代码保存为 main.py 并运行:

python 复制 import os import requests from fastapi import FastAPI, Header, HTTPException, status app = FastAPI() # 从环境变量获取 API Key(如果不存在则使用默认值,仅供示例,不建议明文写密钥) API_KEY = os.getenv("API_KEY", "SAMPLE_KEY_123456") # 通用的API Key校验函数 def verify_api_key(provided_key: str): """校验请求提供的 API Key 是否正确""" if not provided_key or provided_key != API_KEY: return False return True @app.post("/generate") def generate_text(model: str = None, prompt: str = None, stream: bool = False, x_api_key: str = Header(None)): """ 转发请求到 Ollama 的文本生成接口。 请求参数: - model: 使用的模型名称(如"llama2"等) - prompt: 提示词文本 - stream: 是否以流式方式返回 - x_api_key: 请求头中的API密钥 """ # 1. 验证 API Key if not verify_api_key(x_api_key): raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="无效的 API Key") # 2. 构造转发给 Ollama 的请求体 if not model or not prompt: raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="请求参数不完整") payload = { "model": model, "prompt": prompt, "stream": stream } try: # 3. 调用 Ollama 本地接口 resp = requests.post("http://localhost:11434/api/generate", json=payload, timeout=30) except requests.exceptions.RequestException as e: # 调用失败的情况 raise HTTPException(status_code=status.HTTP_502_BAD_GATEWAY, detail=f"调用 Ollama 出错: {str(e)}") # 4. 将 Ollama 的响应结果返回给客户端 # 假设 stream=False,则 Ollama 返回 JSON 格式结果 # 这里直接透传其 JSON 响应;若 stream=True,考虑逐步流式转发(此处简化处理) if resp.status_code == 200: return resp.json() else: # 将错误状态和信息返回 raise HTTPException(status_code=resp.status_code, detail=resp.text)

代码说明

  • 我们定义了一个全局变量 API_KEY 来存储服务器认可的密钥值(实际应用中应通过环境变量或安全存储注入)。然后定义了 verify_api_key 函数用于比对请求提供的密钥是否匹配。

  • 在 /generate 路由中,使用 Header 参数获取请求头中的 X-API-Key(FastAPI会将连字符转为下划线参数名 x_api_key)。首先调用 verify_api_key 校验之。如果验证失败,则抛出 HTTP 401 异常拒绝请求。

  • 如果密钥正确,继续处理业务逻辑:检查必须的请求参数 model 和 prompt 是否提供。如果没有,返回 400 错误。

  • 构造请求负载 payload,包括模型名称、提示词、以及是否流式输出标志。

使用 requests.post 向 Ollama 的本地接口发送请求。这里假设 Ollama 服务跑在默认的 http://localhost:11434/api/generate 路径下​dev.to

  • 。请求超时时间设为30秒,可以根据模型响应时间调整。

  • 如果调用成功(状态码200),将 Ollama 返回的 JSON 内容直接返回给API调用者。若 Ollama 返回错误状态码,则将错误透传为HTTP异常。此外,我们简单处理了非流式响应的情况;如果 stream=True,为了简化示例,没有实现实时流转发,实际应用中可以采用服务端推送等方式将流式结果逐步发送给客户端。

如何运行:确保 Ollama 服务已在本机11434端口启动,并设置好环境变量 API_KEY(如导出您生成的密钥)。然后使用 Uvicorn 启动 FastAPI 应用,例如:

bash 复制 uvicorn main:app --host 0.0.0.0 --port 8000

这将启动 FastAPI 服务监听8000端口(0.0.0.0 表示接受任意网络接口的连接)。现在,部署架构如下:

  • 客户端对外调用 FastAPI 提供的接口(例如向 http://<服务器IP或域名>:8000/generate 发送POST请求,Header中包含 X-API-Key: <密钥>,Body包含 model 和 prompt 等参数)。

  • FastAPI 验证密钥,转发请求给本地 Ollama 服务,并将 Ollama 应答返回给客户端。

  • (可选)如果配置了Nginx反向代理,例如将443端口的HTTPS请求转发到8000端口,则客户端实际上通过Nginx间接访问FastAPI,更安全。

客户端请求示例:假设您的API Key为 SAMPLE_KEY_123456,模型名称为llama2,想请求的提示词为"Hello", 可以使用 curl 测试 FastAPI 接口:

curl -X POST http://<服务器IP>:8000/generate \ -H "Content-Type: application/json" \ -H "X-API-Key: SAMPLE_KEY_123456" \ -d '{"model": "llama2", "prompt": "Hello", "stream": false}'

若密钥正确且服务正常,您将获得 Ollama 返回的JSON结果。例如:

{ "model": "llama2", "created": 1698765432, "response": "Hello! How can I assist you today?" }

以上就是简单的 Ollama 部署方案及其实现。通过FastAPI代理和API Key认证,我们为本地LLM服务增加了一道安全网。根据需要,您还可以扩展此方案,例如将 API Key 换成更复杂的 JWT 验证、为 FastAPI 添加更多路由(如健康检查接口)、或使用SSL证书提高通信安全性等。