之前网上已经有很多文章提到过Ollama API未经授权访问的事情。。其实大概就是很多人把Ollama直接监听到0.0.0.0了。。我估计大多数人也不是错误配置,基本上可以说都只是为了将Ollama与其他的程序进行对接时才这样配置的。因为解决Ollama与其他程序对接问题最简单的办法就是监听0.0.0.0。
但是这就暴露出来一个安全问题,由于Ollama官方一直不愿意(#1053 #8536 #9131)搞个API鉴权的功能出来,这就导致如果把Ollama部署在有公网的机器上,监听0.0.0.0就等于是自杀。。
其实早在这些文章发布前我自己就经历过一次,当时是拿来测试用的,测试完了忘记改回来了,没过几天就被别人拿来白嫖了= =
然后我最近又部署了一个Ollama,没有用Docker,但是对接的Open WebUI是用Docker部署的,又遇到这个问题了,有过上次的教训这次就想彻底解决掉这问题。。
首先在Open WebUI的compose内肯定是要配置host.docker.internal:host-gateway的,这个功能其实就是在容器系统内的hosts文件里添加一行如下配置:
172.17.0.1 host.docker.internal
其中172.17.0.1是宿主机在Docker默认桥接网络中的网关地址。有了这个配置后,容器内部的应用只需请求http://host.docker.internal,就能访问宿主机的服务了。
但是如果宿主机的服务只监听127.0.0.1(环回接口),host.docker.internal能访问到宿主机的这个服务吗?很明显不行啊,因为容器系统内部的127.0.0.1是容器自己,不是宿主机。所以这个时候直接将服务监听到0.0.0.0,那host.docker.internal就能访问到了,但问题就如之前说的Ollama没鉴权,直接暴露在公网会有安全问题。
监听0.0.0.0对于有公网的环境来说不适用,那还有一个办法就是配置Docker容器使用主机网络(Host Network)但是我也不想用这种方案,我还是想用默认的桥接网络。我想到一个办法就是用Socat弄一个端口转发,把172.17.0.1:11434的流量转发到127.0.0.1:11434,可不可行?我也不知道,但是我试了一下确实能用。。。
这里记录下完整的部署过程。安装Docker和需要用到的软件包:
apt -y update apt -y install socat curl nginx python3-certbot-nginx curl -fsSL https://get.docker.com -o get-docker.sh sh get-docker.sh
创建目录和compose文件:
mkdir -p /opt/openwebui && cd /opt/openwebui && nano docker-compose.yml
写入如下内容:
services: openwebui: image: ghcr.io/open-webui/open-webui:main container_name: openwebui extra_hosts: - "host.docker.internal:host-gateway" ports: - "50000:8080" volumes: - open-webui:/app/backend/data volumes: open-webui:
启动Open WebUI:
docker compose up -d
配置NGINX反向代理:
nano /etc/nginx/sites-available/openwebui
写入如下内容:
server { listen 80; server_name openwebui.example.com; location / { proxy_pass http://127.0.0.1:50000; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_buffering off; client_max_body_size 0; proxy_read_timeout 10m; } }
启用站点:
ln -s /etc/nginx/sites-available/openwebui /etc/nginx/sites-enabled/openwebui
签发SSL证书:
certbot --nginx
访问Open WebUI创建管理员账号:
接下来安装Ollama:
curl -L https://ollama.com/download/ollama-linux-amd64.tgz -o ollama-linux-amd64.tgz tar -C /usr -xzf ollama-linux-amd64.tgz
添加一个用户,后续用这个用户来运行Ollama:
useradd -r -s /bin/false -U -m -d /usr/share/ollama ollama usermod -a -G ollama $(whoami)
新建systemd配置文件:
nano /etc/systemd/system/ollama.service
写入如下内容:
[Unit] Description=Ollama Service After=network-online.target [Service] ExecStart=/usr/bin/ollama serve User=ollama Group=ollama Restart=always RestartSec=3 Environment="PATH=$PATH" [Install] WantedBy=multi-user.target
启动并设置Ollama开机自启:
systemctl enable --now ollama
最后用Socat配置一个端口转发,新建systemd配置文件:
nano /etc/systemd/system/socat-ollama.service
写入如下内容:
[Unit] Description=Socat port forward 11434 on 172.17.0.1 to 127.0.0.1:11434 After=network.target [Service] Type=simple ExecStart=/usr/bin/socat TCP4-LISTEN:11434,bind=172.17.0.1,fork,reuseaddr TCP4:127.0.0.1:11434 Restart=always RestartSec=2 LimitNOFILE=4096 [Install] WantedBy=multi-user.target
启动并设置开机自启:
systemctl enable --now socat-ollama
Open WebUI的配置:
测试:
总结:
方案1:Ollama直接监听0.0.0.0,不适用公网环境。
方案2:配置Docker容器使用主机网络,比较简单的解决方案,但降低了Docker网络的隔离性。
方案3:配置一个端口转发,既可以用在公网环境,也不需要使用主机网络,保障了Docker网络的隔离性。
方案4(未实践):搭建One API,然后用One API中转。
方案5(未实践):不确定这种能不能与Open WebUI兼容,https://github.com/ParisNeo/ollama_proxy_server
还有一个方案就是监听在 0.0.0.0 但是端口设置白名单 IP 才能访问,可以用 iptables 或者 nftables 来设置
另外容器里的 hosts 文件不建议直接修改,可以在 compose 文件里添加两行即可
extra_hosts:
– “域名:IP地址”