Skip to content

Instantly share code, notes, and snippets.

@nstanke
Last active March 5, 2024 14:43
Show Gist options
  • Save nstanke/3949ae1c4706854d8f166d1fb3dadc81 to your computer and use it in GitHub Desktop.
Save nstanke/3949ae1c4706854d8f166d1fb3dadc81 to your computer and use it in GitHub Desktop.
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

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

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

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

@MilesTEG1
Copy link

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

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

@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

👍

@nstanke
Copy link
Author

nstanke commented May 13, 2022 via email

@MilesTEG1
Copy link

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 ;)

@RonV42
Copy link

RonV42 commented Oct 20, 2022

Thanks @MilesTEG1 I have changed the lines in the shell script to use your new proxy header commands and now it works fine with the later versions of Vaultwarden. I didn't have to change the reverse proxy setting on my Synolgoy so I left that old configuration in place.

I can now be happy it's working for syncing the clients though websockets.


#!/bin/bash
##==============================================================================================
##                                                                                            ##
##                       Script vaultwarden__Enable_Websocket-DSM_7.sh                        ##
##                                                                                            ##
##          Source : https://gist.github.com/nstanke/3949ae1c4706854d8f166d1fb3dadc81         ##
##                                                                                            ##
##==============================================================================================
##                                                                                            ##
##   This script allows you to route what cannot be done with the reverse-proxy               ##
##   from DSM (Synology) to make Websocket notifications work                                 ##
##   Doc. vaultwarden :                                                                       ##
##        Route the /notifications/hub endpoint to the WebSocket server, by default           ##
##        at port 3012, making sure to pass the Connection and Upgrade headers.               ##
##        (Note the port can be changed with WEBSOCKET_PORT variable)                         ##
##        https://github.com/dani-garcia/vaultwarden/wiki/Enabling-WebSocket-notifications    ##
##                                                                                            ##
##==============================================================================================
##                                                                                            ##
##                            Principle of Task schedule to create                            ##
##                                                                                            ##
## It is necessary to run the script regularly because all changes made in the interface      ##
## DSM Reverse-Proxy graph will modify the configuration file. The same applies to            ##
## even when the NAS reboots.                                                                 ##
##                                                                                            ##
##==============================================================================================
##                                                                                            ##
##        /!\      The online IP address 47 must be changed to the NAS IP     /!\             ##
##                                                                                            ##
##==============================================================================================
##                                                                                            ##
## Script launch parameters :                                                                 ##
## bash /volume1/docker/bitwarden/enable_ws.sh vault.example.com 5555 5556                    ##
##                                                                                            ##
## -- vault.example.com = Vaultwarden domain name (that of DSM's Reverse Proxy)               ##
## -- 5555 = Port exposed ROCKET_PORT by Docker (Same as DSM Reverse Proxy)                   ##
## -- 5556 = Port exposed WEBSOCKET_PORT by Docker                                            ##
##                                                                                            ##
##==============================================================================================

LOC_DIR="/etc/nginx"
part1=0
part2=0
MY_DOMAIN=$1
PORT_ACCES=$2
PORT_CONT=$3
IP_NAS="192.168.10.200"

echo -e "\n$(date "+%R:%S - ") Script vaultwarden__Enable_Websocket.sh to enable Websockets Notifications"

f_affiche_parametre() {
  echo "          bash /volume1/docker/_Scripts-DOCKER/vaultwarden__Enable_Websocket.sh vault.example.com 5555 5556 "
  echo "                           -- vault.example.com = Vaultwarden domain name (that of DSM's Reverse Proxy) "
  echo "                           -- 5555 = Port exposed ROCKET_PORT by Docker (Same as DSM Reverse Proxy)"
  echo "                           -- 5556 = Port exposed WEBSOCKET_PORT by Docker"
}

if [ ! $# -eq 3 ]; then
  if [ $# -eq 0 ]; then
    # No parameters were provided. We will display the list of what can be used.
    echo "$(date "+%R:%S - ") No parameters provided! Review the script call :"
    f_affiche_parametre
  else
    echo "$(date "+%R:%S - ") The number of parameters provided is not correct! Review the script call :"
    f_affiche_parametre
  fi
  echo -e "$(date "+%R:%S - ") Failed to launch !!!!!!!!! script\n"
  exit 1
fi

echo "$(date "+%R:%S - ") Executing commands..."


#############################################################################################################
## Start of file creation/editing part
##
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


# Note : with DSM7, the path of the server file. ReverseProxy.conf has changed 
#         DSM6.2  = /etc/nginx/app.d/server.ReverseProxy.conf
#         DSM7    = /etc/nginx/sites-enabled/server.ReverseProxy.conf
if ! grep -q "websocket.locations.vaultwarden" /etc/nginx/sites-enabled/server.ReverseProxy.conf; then

  # Functional commands with DSM6.2.x, but no longer with DSM 7.0 (RC)
  #sed -i "/$1;/ a\ include $LOC_DIR/websocket.locations.vaultwarden;" /etc/nginx/app.d/server.ReverseProxy.conf
  #if nginx -t 2>/dev/null; then synoservicecfg --reload nginx; else exit 1; fi

  # Functional commands with DSM 7 (RC)
  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
  mv /etc/nginx/sites-enabled/server.ReverseProxy.conf.new /etc/nginx/sites-enabled/server.ReverseProxy.conf

  if nginx -t 2>/dev/null; then synosystemctl reload nginx; else exit 1; fi

  part2=1 # Variable to indicate that this part has been executed

fi
##
## End of file creation/editing part
#############################################################################################################

if [ $part1 -eq 1 ]; then
  echo "$(date "+%R:%S - ")    -- The file $LOC_DIR/websocket.locations.vaultwarden already existed, it was deleted and then recreated."
else
  echo "$(date "+%R:%S - ")    -- The file $LOC_DIR/websocket.locations.vaultwarden did not exist, it was created."
fi
if [ $part2 -eq 1 ]; then
  echo "$(date "+%R:%S - ")    -- !!!!!! --->  The change in the /etc/nginx/sites-enabled/server file. ReverseProxy.conf did not exist. It was written."
  echo "$(date "+%R:%S - ")    -- !!!!!! --->  The /etc/nginx/sites-enabled/server file. ReverseProxy.conf had to be reset after a reboot or when changing the reverse-proxy in DSM."
else
  echo "$(date "+%R:%S - ")    -- Editing the /etc/nginx/sites-enabled/server file. ReverseProxy.conf was already performed during a previous run. No changes are therefore necessary."
fi

echo "$(date "+%R:%S - ") Script vaultwarden__Enable_Websocket.sh Finished"

exit

@Animizio
Copy link

Hey I'm using the latest script posted above and now the sync works fine for me on all devices. But smtp settings for mail sendings has only errors now. could this proxy stuff be the cause for that problem? Because I know the mail feature worked well for me time ago.

@JohannCR
Copy link

JohannCR commented Jan 29, 2023

Hi,
Script doesn't work for me...
DSM 7.1.1-42962
Docker 20.10.3-1308
Script executes ok, but no change I still get status.Websocket connection failed, "there was an error in the transport".
Anyone has any pointer ?
Thanks

Edit : Solved ! It was my adblocker (adguard) that was at fault ! I now have sync functionnning on my devices, so it's good !
I'm still seing that error in chrome on PC, but as long as my phone is synced it doesn"t matter.
Thanks a lot for the script

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