我正在使用 vaultwarden docker 容器,它基本上需要反向代理来提供 SSL。
该容器为 Websockets 运行单独的 Web 服务器,因为 Rust 的 rocket 不支持同一端口上的 Web 套接字。
VaultWarden 的说明如下:
- 将 /notifications/hub 端点路由到 WebSocket 服务器,默认端口为 3012,确保传递 Connection 和 Upgrade 标头
- 将其他所有内容(包括 /notifications/hub/negotiate)路由到标准 Rocket 服务器,默认端口为 80
我该如何配置我的 nginx 反向代理来支持此设置?
我的配置如下:
docker-compose.yml
version: '3'
services:
vaultwarden:
image: vaultwarden/server:1.25.2
volumes:
- /srv/vaultwarden/vaultwarden:/data/
restart: always
environment:
- WEBSOCKET_ENABLED=true
nginx:
image: nginx:1.23.1
volumes:
- /srv/vaultwarden/nginx/templates:/etc/nginx/templates
- /srv/vaultwarden/nginx/ssl:/etc/nginx/ssl
ports:
- "443:443"
environment:
- NGINX_PORT=443
nginx的:
server {
listen ${NGINX_PORT} ssl http2 default;
server_name _;
# SSL
ssl_certificate /etc/nginx/ssl/server.crt;
ssl_certificate_key /etc/nginx/ssl/server.key;
# Web sockets
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-Forwarded-Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
location / {
proxy_pass http://vaultwarden;
}
}
我可以做:
- 直接在 vaultwarden 容器上公开端口 3012?
- 那么 nginx 配置是什么样的?
- 在 nginx 容器上公开端口 3012,并通过 proxy_passing 将其传递到 vaultwarden 容器?
- 那会是什么样子的?
答案1
经过一番挖掘,我发现了以下内容:
如果您将WEBSOCKET_ENABLED=true
环境变量传递给 vaultwarden 容器(如我在上面的docker-compose.yml
文件中所做的那样),则容器将启动 2 个服务器:
- 端口 80 上的 Web 服务器
- 端口 3012 上的 Websocket 服务器
客户端上没有任何东西表明要连接到端口 3012。客户端尝试在上设置 websocket /notifications/hub
。与常规 Web 服务器的端口相同。
您无需在docker-compose.yml
文件中公开任何容器上的 3012 端口。您只需要在 nginx 配置文件中进行以下操作:
location = /notifications/hub {
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_set_header Host $host;
proxy_pass http://vaultwarden:3012;
}
这将透明地让 nginx 将所有请求重定向到/notifications/hub
vaultwarden 容器上的端口 3012。
由于 nginx 和 vaultwarden 都在同一个docker-compose.yml
文件中,因此它们位于同一个内部网络中,并且 nginx 容器已经可以访问 vaultwarden 容器上的所有端口。您无需在任何地方允许此端口。
客户端不知道 Web 套接字内部使用的是不同的端口。端口转换全部在服务器端进行。
答案2
我建议在 nginx 中公开端口 3012:
nginx:
image: nginx:1.23.1
volumes:
- /srv/vaultwarden/nginx/templates:/etc/nginx/templates
- /srv/vaultwarden/nginx/ssl:/etc/nginx/ssl
ports:
- "443:443"
- "3012:3012"
environment:
- NGINX_PORT=443
nginx 上 WebSockets 的代理传递可能有点棘手。我曾经很难正确设置它(请参阅这个帖子)——我还在那里为 WebSockets 自定义了一个 URL/端点。
通常,WS 代理的工作方式有以下几种:(1) 您有用于 WebSocket 连接的自定义端点,或 (2) WS 通过根/
,但使用的端口与 HTTP 不同,或 (3) 它的工作方式更像 socket.io (即,每个端点/URL 也是 WS 连接的单独端点)。文档中写道:
将 /notifications/hub 端点路由到 WebSocket 服务器,默认端口为 3012,确保传递 Connection 和 Upgrade 标头
将其他所有内容(包括 /notifications/hub/negotiate)路由到标准 Rocket 服务器,默认端口为 80
因此我猜测 nginx 配置中应该是这样的:
# WebSocket support
location ~ ^/notifications/hub/ {
proxy_pass http://vaultwarden:3012;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_set_header Host $host;
}
# HTTP proxy
location / {
proxy_pass http://vaultwarden;
}
但它需要一些测试。
我希望这能对你有所帮助。