Ollama访问限制

Nginx+Basic Auth认证

生成密码文件

1
2
3
4
5
6
7
# 安装工具
yum install httpd-tools -y

# 创建密码文件(用户名 admin)
htpasswd -c /www/server/pass/ollama.pass admin

# 输入密码,比如 MySecurePass123

修改nginx配置文件

在之前配置ollama的反向代理的nginx配置文件中设置Basic Auth认证实现访问限制

1
2
3
4
#BASICAUTH START
auth_basic "Ollama API Auth";
auth_basic_user_file /www/server/pass/ollama.pass;
#BASICAUTH END

重启nginx

1
2
nginx -t
systemctl reload nginx

测试

1
2
3
4
5
# 不带认证 → 401 Unauthorized
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
# CentOS 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();

// ========== CORS 中间件 ==========
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' }));

// Ollama 配置
const OLLAMA_HOST = 'http://127.0.0.1:11434';
const AUTH_USER = 'admin';
const AUTH_PASS = 'MySecurePass123';

// 生成 Basic Auth 头
const basicAuth = 'Basic ' + Buffer.from(`${AUTH_USER}:${AUTH_PASS}`).toString('base64');

// 健康检查
app.get('/health', (req, res) => {
res.json({ status: 'ok' });
});

// 代理 /api/generate
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 });
}
});

// 代理 /api/tags
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
#PROXY-CONF-START
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;
}
#PROXY-CONF-END

重启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}'