Nginx+Basic Auth认证
生成密码文件
1 2 3 4 5 6 7
| yum install httpd-tools -y
htpasswd -c /www/server/pass/ollama.pass admin
|
修改nginx配置文件
在之前配置ollama的反向代理的nginx配置文件中设置Basic Auth认证实现访问限制
1 2 3 4
| auth_basic "Ollama API Auth"; auth_basic_user_file /www/server/pass/ollama.pass;
|
重启nginx
1 2
| nginx -t systemctl reload nginx
|
测试
1 2 3 4 5
| curl https://ollama.eucalyptus.cc/api/tags
curl https://admin:MySecurePass123@ollama.eucalyptus.cc/api/tags
|
后端Node.js代理
但是这样的话再前端调用的时候需要把账号和密码写到前端js中,还是有泄露的风险,这时我们可以使用后端代理。前端 JS 直接调用后端代理,后端代理内部带 Basic Auth 访问 Ollama。
架构图
1 2 3 4 5 6 7 8 9
| 用户浏览器 → Hexo 博客页面 → JS 调用 https://ollama.eucalyptus.cc ↓ ECS Nginx (无认证,或简单限流) ↓ Node.js 代理 (localhost:3001) ↓ 带 Basic Auth 调 Ollama (127.0.0.1:11434) ↓ frps → frp隧道 → 本地虚拟机 Ollama
|
部署步骤
ecs安装node.js
1 2 3 4 5 6 7
| curl -fsSL https://rpm.nodesource.com/setup_18.x | bash - yum install -y nodejs
node -v npm -v
|
创建代理服务
1 2 3 4
| mkdir -p /opt/ollama-proxy cd /opt/ollama-proxy npm init -y npm install express node-fetch@2
|
创建proxy.js
记得配置CORS,不然会出现跨域访问的问题
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
| const express = require('express'); const fetch = require('node-fetch');
const app = express();
app.use((req, res, next) => { res.header('Access-Control-Allow-Origin', 'https://blog.eucalyptus.cc'); res.header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS'); res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept, Authorization'); if (req.method === 'OPTIONS') { return res.sendStatus(204); } next(); });
app.use(express.json({ limit: '10mb' }));
const OLLAMA_HOST = 'http://127.0.0.1:11434'; const AUTH_USER = 'admin'; const AUTH_PASS = 'MySecurePass123';
const basicAuth = 'Basic ' + Buffer.from(`${AUTH_USER}:${AUTH_PASS}`).toString('base64');
app.get('/health', (req, res) => { res.json({ status: 'ok' }); });
app.post('/api/generate', async (req, res) => { try { const response = await fetch(`${OLLAMA_HOST}/api/generate`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': basicAuth }, body: JSON.stringify(req.body), timeout: 60000 });
if (!response.ok) { const text = await response.text(); return res.status(response.status).json({ error: text }); }
const data = await response.json(); res.json(data);
} catch (err) { console.error('Proxy error:', err); res.status(500).json({ error: err.message }); } });
app.get('/api/tags', async (req, res) => { try { const response = await fetch(`${OLLAMA_HOST}/api/tags`, { headers: { 'Authorization': basicAuth } }); const data = await response.json(); res.json(data); } catch (err) { res.status(500).json({ error: err.message }); } });
const PORT = 3001; app.listen(PORT, '127.0.0.1', () => { console.log(`Ollama proxy running on http://127.0.0.1:${PORT}`); });
|
用PM2守护进程
1 2 3 4 5 6 7 8 9 10 11 12
| npm install -g pm2
pm2 start proxy.js --name ollama-proxy
pm2 startup pm2 save
pm2 status pm2 logs ollama-proxy
|
修改ollama反向代理nginx的配置文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| location ^~ / { proxy_pass http://127.0.0.1:3001; proxy_set_header Host $http_host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Real-Port $remote_port; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-Host $host; proxy_set_header X-Forwarded-Port $server_port; proxy_set_header REMOTE-HOST $remote_addr; proxy_connect_timeout 60s; proxy_send_timeout 600s; proxy_read_timeout 600s; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $connection_upgrade; }
|
重启nginx
1 2
| nginx -t systemctl reload nginx
|
测试验证
1 2 3 4 5 6 7
| curl http://127.0.0.1:3001/health
curl -X POST http://127.0.0.1:3001/api/generate \ -H "Content-Type: application/json" \ -d '{"model":"qwen2.5:0.5b","prompt":"你好","stream":false}'
|