Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Synology Bitwarden_rs Websocket setup without SSH
#!/bin/bash
LOC_DIR="/etc/nginx"
if [ ! -f $LOC_DIR/ws.locations ]; then
echo """
location /notifications/hub {
proxy_pass http://localhost:$3;
proxy_set_header Upgrade \$http_upgrade;
proxy_set_header Connection "upgrade";
}
location /notifications/hub/negotiate {
proxy_pass http://localhost:$2;
}
""" >> $LOC_DIR/ws.locations
fi
if ! grep -q "ws.locations" /etc/nginx/app.d/server.ReverseProxy.conf; then
sed -i "/$1;/ a\ include $LOC_DIR/ws.locations;" /etc/nginx/app.d/server.ReverseProxy.conf
if nginx -t 2>/dev/null; then synoservicecfg --reload nginx; else exit 1; fi
fi

Synology Bitwarden_rs Websocket Setup

Below steps allow you to setup Websocket support for your Bitwarden_rs installation running on Synology Diskstation. You can do all steps using the GUI so there is no SSH Access needed.

Prerequisites

  • Working HTTPS Reverse proxy Setup (Control Panel -> Application Portal -> Reverse Proxy)
  • Set Enviourment Variable WEBSOCKET_ENABLED=true in your Bitwarden container and expose the container port 3012 to a local port, in my case 5556.

Upload script

  1. Download enable_ws.sh
  2. Upload the script "enable_ws.sh" onto your Diskstation. I would recommand putting it in your Bitwarden directory. In my case /volume1/docker/bitwarden

Create scheduled Task

Control Panel -> Task Scheduler -> Create -> Scheduled Task -> User-defined Script

Make sure to amend the command according to your setup.

  • /volume1/docker/bitwarden/enable_ws.sh = Full path to previously uploaded script
  • vault.example.com = Hostname of your Bitwarden_rs as configured in the Reverse Proxy
  • 5555 = Exposed ROCKET_PORT by Docker (The same as in your Reverse Proxy setup)
  • 5556 = Exposed WEBSOCKET_PORT by Docker

Run Command (My example):

bash /volume1/docker/bitwarden/enable_ws.sh vault.example.com 5555 5556

  General Settings
      Task -> Enable BW WS
      User -> root
      Enabled -> Tick
  Schedule
      Run on the following days -> Daily
      Frequency -> Every hour
  Task Settings:
      (Optional) Enable Notifications
      Run Command: <Paste Command Crafted Above> 

Save and run the new task by selecting Run. Login into your Webvault and confirm in your web browsers developer console that the connection to wss:// succeded.

@MilesTEG1
Copy link

MilesTEG1 commented Dec 12, 2021

@ClusterDuckster I don't understand what's going wrong with the script, I just check on my server.ReverseProxy.conf and the line include /etc/nginx/websocket.locations.vaultwarden; is only present on my vaulwarden section...
How did you configure your reverse-proxy ?

Mine is configured with vault.mydomain.tld on the 443 port outside, and 888 port inside on the NAS IP.

The sed command :

sed -r "s#^([[:blank:]]*server_name[[:blank:]]*${MY_DOMAIN}[[:blank:]]*;[[:blank:]]*)\$#\1\n\n\tinclude ${LOC_DIR}/websocket.locations.vaultwarden;#" /etc/nginx/sites-enabled/server.ReverseProxy.conf > /etc/nginx/sites-enabled/server.ReverseProxy.conf.new

is only searching for the line server_name vault.mydomain.tld in the conf file.
There no need to search with a port...
So, your configuration must be different, and I didn't understand what varies form mine...
Can you develop, please ?

@ClusterDuckster
Copy link

ClusterDuckster commented Dec 12, 2021

@MilesTEG1 Ahhhhh Thank you for your feedback!

I just realized that my setup is probably kind of uncommon (and most probably kind of faulty). I am using the same domain on my DSM for different applications but on different ports. I have another Reverse Proxy on a little vServer that routes the applications based on it's subdomain. I like to think that it is a little more secure because I open ports on my home network to just that vServer. It looks a little like that:

Vaultwarden:

  1. vServer - https://bitwarden.mydomain.com:443
  2. DSM reverse proxy - https://private.mydomain.com:5557
  3. Docker - http://localhost:5555

Other application:

  1. vServer - https://application2.mydomain.com:443
  2. DSM reverse proxy - https://private.mydomain.com:6667
  3. Docker - http://localhost:6665

So DSM is listening on private.mydomain.com for both of my apps, that is why I needed that workaround. When I started, I wanted to skip the DSM reverse proxy, but I realized that I wanted to have the communication between my DSM and my Server encrypted, so I added the DSM reverse proxy to just upgrade my Docker applications from http to https.
If you have any suggestions to my setup I always appreciate those :)

@MilesTEG1
Copy link

MilesTEG1 commented Dec 13, 2021

Hi, @ClusterDuckster ,
This is indeed an uncommon setup.
I don't know exactly what does a vServer, but it seems it plays the role of a reverse proxy, no ?
The reverse proxy is intended for functionning with various domaine name, pointing to some IP/port combination inside.
Working with the same domaine name for each services, require to use differents ports.

Why are you using a Vserver before the reverse proxy ? For me it redundant to what can do a reverse proxy...
If I were you, I'll choose only one of them.

@ClusterDuckster
Copy link

ClusterDuckster commented Dec 21, 2021

Hi @MilesTEG1,

a vServer is just a virtual Server I rented which is outside of my network. and it plays the role of a reverse Proxy.
The Reason for the vServer reverse Proxy:

  • static IP
  • ip is not shared with other machines
  • kind of DMZ maybe? Like having the entry point to my webservice outsite of my network

The Reason for the DSM reverse Proxy:

  • https (since vaultwarden only does http)

I now thought about using own subdomains for apllications in my home network instead of ports, but I think I would get problems if I want to host something on something else like a rasperry pi. The problem I think of is port forwarding. Let's say my DSM reverse proxy is reachable under https://vaultwarden.mydomain.com:443 (just standard https port) and I am hosting another application on a raspberry pi https://application2.mydomain.com:443. On my Router I want to set my port forwarding for application2 to the raspberry pi, but it uses the same port as vaultwarden. I suppose you could reverse proxy that also over the NAS but in my head it would be nicer to have the raspberry pi function on his own without having to rely on the NAS.

Is my point valid, or am I missing something? Or would it be good practice to just route everything in my network over the DSM reverse proxy and my concerns are invalid?

@MilesTEG1
Copy link

MilesTEG1 commented Dec 21, 2021

Let's say my DSM reverse proxy is reachable under https://vaultwarden.mydomain.com:443 (just standard https port) and I am hosting another application on a raspberry pi https://application2.mydomain.com:443. On my Router I want to set my port forwarding for application2 to the raspberry pi, but it uses the same port as vaultwarden. I suppose you could reverse proxy that also over the NAS but in my head it would be nicer to have the raspberry pi function on his own without having to rely on the NAS.

That's all the point to use a reverse proxy.
All your connexion are forwarded to the reverse proxy, and only it redirect to the right machin:port.
In my opinion, your installation is too complex, and doesn't give any security advantages...

If you're not using a 4G internet connexion for your home internet, you should only use the NAS, or the r-pi as a reverse-proxy.
You forward 443, and eventually 80 port to it, and let it managed the rest.
For the static IP, you can set up a dynDNS (I have a DynHost with OVH on my router), in my opininon, static IP isn't the thing you have to worry about.
For the second point "ip is not shared with other machines", I don't understand the logic in that...
And the third, about DMZ ? What, why ? I don't understand too... You have a router with a firewall, right ?

@ClusterDuckster
Copy link

ClusterDuckster commented Dec 22, 2021

Thank you MilesTEG1, I also believe that my previous setup was just based on some of my personal misconceptions as I am still learning.
I will update my setup with your suggestions in mind!

@MilesTEG1
Copy link

MilesTEG1 commented Apr 21, 2022

@RonV42 @ClusterDuckster @ all_others

I'm wondering if it could be possible to add with the script a restriction IP sources for the https://vaut.domain.tld/admin page ?
My idea is to restrict this page to only LAN ips like 192.168.0.0/24 and only VPN IP (VPN Server on DSM or SRM) like 192.168.10.0/24.
But I don't know if it possible, and how to do it.
Some of you do have an idea ?

Thanks in advance :)

@Autonomous120
Copy link

Autonomous120 commented May 11, 2022

Issue report:
Upgraded to DSM 7.1-42661 Update 1, the script doesn't work.

@MilesTEG1
Copy link

MilesTEG1 commented May 11, 2022

Issue report: Upgraded to DSM 7.1-42661 Update 1, the script doesn't work.

Witch one ?
Mine (or the translated version by @RonV42), or the one from @ClusterDuckster ?

The original script from @nstanke didn't work since DSM7.

@Autonomous120
Copy link

Autonomous120 commented May 12, 2022

I checked and confirm the script is translated version by @RonV42

The error message in Bitwarden.app (by pressing F12) shows that:

WebSocket connection to 'wss://vault.xxxx.com:8001/notifications/hub?access_token=xxxx' failed: Error during WebSocket handshake: Unexpected response code: 504
WebSocketTransport.js:99
Utils.js:218 [2022-05-12T12:08:52.520Z] Error: Failed to start the connection: Error: There was an error with the transport.
e.log @ Utils.js:218
zone.js:3083 20:08:52.536 › Error: There was an error with the transport.
    at WebSocket.o.onerror [as __zone_symbol__ON_PROPERTYerror] (vendor.js:2)
    at WebSocket.T (vendor.js:2)
    at e.invokeTask (vendor.js:2)
    at Object.onInvokeTask (vendor.js:2)
    at e.invokeTask (vendor.js:2)
    at t.runTask (vendor.js:2)
    at t.invokeTask [as invoke] (vendor.js:2)
    at b (vendor.js:2)
    at WebSocket.v (vendor.js:2)
i.<computed> @ zone.js:3083

websocket.locations.vaultwarden:


location /notifications/hub {
    proxy_pass http://192.168.11.11:8002;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
}

location /notifications/hub/negotiate {
    proxy_pass http://192.168.11.11:8000;
}


docker-compose_vaultwarden.yml:

#---
#Docker-compose file for Vaultwarden
#--- 
version: '3'
services:
  vaultwarden:
    container_name: vaultwarden
    restart: always
    image: vaultwarden/server:latest
    environment: 
    - TZ=Asia/Hong_Kong
    - LOG_FILE=/maintenance/vaultwarden.log
    - WEBSOCKET_ENABLED=true

    volumes:
    - /volume1/docker/Public/Vaultwarden/data:/data
    - /volume1/docker/Public/Vaultwarden/maintenance:/maintenance
    
    ports:
    - 8000:80
    - 8002:3012
    
    network_mode: "bridge"

Reverse proxy setting for vaultwarden:
Source: https://vault.xxxx.com:8001
Destination: http://localhost:8000

Running script parameters:
bash /volume1/docker/Public/Vaultwarden/websocket/enable_ws.sh vault.xxxx.com 8000 8002

I just recollected what I have done in recent days:

  1. Upgraded to DSM 7.1-42661 Update 1
  2. Enabled IPv6 in DSM, automatic mode, while enabled DHCPv6 stateless on my router.
  3. Switched network mode of docker container - AdguardHome from macvlan mode to host mode, and confirm that no port conflicting.

Wish those information could help.

@MilesTEG1
Copy link

MilesTEG1 commented May 12, 2022

Hello @Autonomous120
I just check on my Bitwarden .app, it seems the websocket works :
image

Maybe your problem is with IPv6 ?
I don't have my NAS in IPv6...
I have AdGuard Home too, in macvlan.
In AdGH, I've got a rewriting of my vaultwarden url to the LAN IP NAS.

@Autonomous120
Copy link

Autonomous120 commented May 13, 2022

@MilesTEG1
Good news! The script back to work again!
Here is my solution:

  1. Enter the DSM control panel.
  2. Navigate to Network → General → Advanced Settings
  3. Make sure the ‘Enable Multiple Gateways’ unchecked.

@MilesTEG1
Copy link

MilesTEG1 commented May 13, 2022

👍

@nstanke
Copy link
Author

nstanke commented May 13, 2022

@MilesTEG1
Copy link

MilesTEG1 commented Jul 17, 2022

Hello,
I'll may do a fork when I'll have some time 😃

But for now, I had to investigate why my setup doesn't work anymore with the last version (1.25.1) of VaultWarden. I had errors saying that WebSocket connection to xxxxxxxxxxxxxxxxxxx (anonymous) @ WebSocketTransport.js:99 when 1.25.0 works fine...

I had to add some things in the websocket.locations.vaultwarden file.
Here what I have now :

if [ -f $LOC_DIR/websocket.locations.vaultwarden ]; then
  rm $LOC_DIR/websocket.locations.vaultwarden
  part1=1
fi
echo """
location /notifications/hub/negotiate {
    proxy_http_version 1.1;
    proxy_set_header \"Connection\" \"\";
    
    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_pass http://$IP_NAS:$PORT_ACCES;
}

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_set_header X-Real-IP \$remote_addr;
    proxy_set_header Forwarded \$remote_addr;
    proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto \$scheme;
    proxy_pass http://$IP_NAS:$PORT_CONT;
}

""" >>$LOC_DIR/websocket.locations.vaultwarden

And I had to remove entries for the websocket for the location / (in DSM, remove the two lines in the reverse proxy configuration to have only this :
image

And now, WebSockets Notifications works again ;)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment