API Key 泄露是 AI Agent 部署中最头疼的事,轻则额度被刷爆,重则数据库被拖库。在主机选的运维实战中,见过太多因为直接把密钥写死在 `docker-compose.yml` 里导致被盗用的案例。别等到收到巨额账单才后悔,今天就聊聊如何通过环境变量、Docker Secrets 和权限隔离,把你的 n8n、Ollama 等服务锁死在安全笼子里。

API Key 泄露的常见场景与风险
很多新手在部署 AI Agent 时,习惯把 OpenAI 或 DeepSeek 的 Key 直接贴在配置文件里。这不仅是坏习惯,更是埋雷。最惨痛的教训通常来自三种情况:代码误传到 GitHub 公开仓库、使用了包含敏感信息的公共镜像、或者直接把 `docker inspect` 的结果截图发到群里求助。
一旦 Key 泄露,攻击者不需要攻破你的服务器,就能直接利用你的额度消耗资源,甚至利用你的 Agent 权限读取内部数据。对于生产环境,必须假设配置文件随时可能被读取,因此核心策略是“不落地、不硬编码、权限最小化”。
基础防御:环境变量与 .env 文件隔离
最基础的防线是拒绝硬编码。在 Docker 部署中,永远不要把 Key 写在 `docker-compose.yml` 的 `environment` 字段里。正确的做法是使用 `.env` 文件,并将其加入 `.gitignore`。
在项目目录下创建 `.env` 文件:
OPENAI_API_KEY=sk-proj-xxxxxxxxxxxxxxxxxxxx
N8N_ENCRYPTION_KEY=your-random-encryption-string
在 `docker-compose.yml` 中引用:
yaml
services:
n8n:
image: n8nio/n8n
env_file:
– .env # 自动加载文件中的变量
这样,你的配置文件里只有变量名,没有具体的 Key。即便你把 `docker-compose.yml` 发给别人,也不会造成泄露。记得给 `.env` 文件设置严格的权限,只允许所有者读取:
chmod 600 .env
进阶隔离:Docker Secrets 与文件挂载
虽然 `.env` 方便,但在容器运行时,环境变量依然可以通过 `/proc/<pid>/environ` 被读取。更稳妥的方案是利用 Docker 的文件挂载机制,将 Key 作为文件注入容器,AI Agent 运行时读取文件内容。
这种方式在 Docker Swarm 模式下被称为 Secrets,在单机 Compose 中可以通过只读挂载实现。
1. 创建存放 Key 的独立目录:
mkdir -p /data/secrets
echo "sk-proj-xxxxxxxxxxxxxxxxxxxx" > /data/secrets/openai_key
chmod 600 /data/secrets/openai_key
2. 在 docker-compose.yml 中挂载为只读文件:
yaml
services:
ai-agent:
image: your-agent-image
volumes:
– /data/secrets/openai_key:/run/secrets/openai_api_key:ro # :ro 表示只读
3. 应用程序内读取文件:
你的代码需要支持读取文件路径。例如 Python 中:
python
with open('/run/secrets/openai_api_key', 'r') as f:
api_key = f.read().strip()
这样,API Key 仅以文件形式存在于容器内存和挂载点中,排查问题时误发环境变量的风险大大降低。
权限最小化:拒绝 Root 裸奔与网络隔离
除了保护 Key 本身,还要限制 Key 被盗用后的破坏力。这涉及两个层面:容器内部权限和网络访问控制。
1. 非 Root 用户运行
默认情况下,Docker 容器以 root 身份运行。如果攻击者通过 RCE 漏洞拿到容器 Shell,就能轻易读取所有密钥文件。在 `docker-compose.yml` 中指定用户 ID:
yaml
services:
n8n:
image: n8nio/n8n
user: "1000:1000" # 使用普通 UID 运行,避免 root
2. 网络隔离与私有网络
不要把所有服务都暴露在宿主机的 0.0.0.0 端口上。比如 Ollama 通常只需要被 n8n 调用,不需要对外提供服务。
创建一个内部网络:
yaml
networks:
backend:
driver: bridge
services:
ollama:
image: ollama/ollama
networks:
– backend
n8n:
image: n8nio/n8n
ports:
– "5678:5678" # 只有 n8n 对外暴露
networks:
– backend
这样,n8n 可以通过 `http://ollama:11434` 访问 Ollama,但外部扫描器根本扫不到 Ollama 的端口。
实战:为 n8n 和 Ollama 配置安全隔离
以典型的 n8n 调用 Ollama 为例,演示一套安全配置方案。
n8n 的环境变量注入
n8n 需要连接外部 API(如 OpenAI)以及自身的加密 Key。全部使用环境变量注入:
yaml
services:
n8n:
image: n8nio/n8n
restart: always
environment:
– N8N_BASIC_AUTH_ACTIVE=true
– N8N_BASIC_AUTH_USER=admin
– N8N_BASIC_AUTH_PASSWORD=strong_password_here
– N8N_ENCRYPTION_KEY=${N8N_ENCRYPTION_KEY} # 从 .env 读取
– OPENAI_API_KEY=${OPENAI_API_KEY} # 从 .env 读取
env_file:
– .env
volumes:
– n8n_data:/home/node/.n8n
Ollama 的端口限制与访问控制
Ollama 涉及模型文件,体积大且权限敏感。建议将其限制在内部网络,并通过 n8n 中转请求。
yaml
ollama:
image: ollama/ollama
restart: always
volumes:
– ollama_data:/root/.ollama
networks:
– ai_network
n8n:
networks:
– ai_network
depends_on:
– ollama
networks:
ai_network:
driver: bridge
配置完成后,n8n 中配置 Ollama 地址为 `http://ollama:11434`。这样即使 Ollama 存在未授权访问漏洞,外部也无法直接触达。
老鸟叮嘱
部署 AI Agent 时,安全配置往往比功能实现更容易被忽视。这里有几点实战经验:
1.定期轮换 Key:养成习惯,每 30-90 天更换一次 API Key,特别是怀疑日志可能泄露过之后。
2.限制 API 权限:在 OpenAI 或 DeepSeek 后台,为 Agent 创建专用的 Key,并限制其额度或仅赋予特定模型权限,不要使用全权 Master Key。
3.日志脱敏:配置日志驱动(如 Loki 或 Fluentd)时,务必设置过滤规则,防止 API Key 被打印到 Stdout 或持久化日志中。
4.别信默认密码:n8n、Open WebUI 等工具安装后第一件事就是改密码,并开启 Basic Auth 或反向代理层面的 Auth 验证。
FAQ
Q1:如果发现 API Key 已经泄露,第一步该做什么?
A:立即去服务商后台撤销(Revoke)该 Key,生成新 Key。不要试图修改密码,API Key 一旦生成通常无法修改,只能作废重置。
Q2:Docker Compose 非 Swarm 模式能用 Secrets 吗?
A:Docker Compose 规范 V3.1+ 支持 `secrets` 字段,但在非 Swarm 模式下,它实际上只是把文件挂载到容器内的 `/run/secrets/` 目录,功能上是一样的,可以放心用。
Q3:本地部署的 Ollama 需要配置 API Key 吗?
A:Ollama 本身不强制要求 API Key,但如果你通过 n8n 或其他 Agent 调用它,建议在反向代理层(如 Nginx)加一层 Basic Auth,防止被局域网内的其他设备蹭用。
Q4:如何检查容器内的环境变量是否安全?
A:运行 `docker exec -it <container_id> env` 查看环境变量,运行 `docker inspect <container_id>` 查看挂载详情。如果能看到明文 Key,说明该 Key 对拥有宿主机 root 权限的人是可见的,这是正常的,但要通过文件权限确保普通用户无法读取。
Q5:生产环境推荐用什么工具管理密钥?
A:如果是大规模集群,推荐 HashiCorp Vault;如果是单机或少量 VPS,使用 `.env` 配合 `chmod 600` 和 Docker 文件挂载是最性价比的方案。
做好密钥管理和权限隔离,你的 AI Agent 才能跑得稳且睡得着。安全不是可选项,是部署的第一步。
转载请注明出处:https://www.zhujixuan.com/jishujiaocheng/10251.html 商家投稿邮箱:zhujixuanblog@qq.com
