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.

@nstanke
Copy link
Author

nstanke commented Jun 28, 2021 via email

@MilesTEG1
Copy link

I forget to tell that I run DSM 7 RC on my Synology :)

@Autonomous120
Copy link

@MilesTEG1
Sorry dude. The server.ReverseProxy.conf still locate in /etc/nginx/app.d/ when running at DSM 6.2.4-25556. I just put enable_ws.sh file into the folder which contains a whitespace and cause the script interrupted then received an error code 127. The issue has been fixed by modifying the path, thanks.

@xedoc64
Copy link

xedoc64 commented Jul 2, 2021

Hi,

i can't get it working to add the needed include in /etc/nginx/app.d/server.ReverseProxy.conf. It seems that the sed does nothing (or the grep is failing). This happens with the original script as well with the new one from MilesTEG1. Does someone have a hint for me?

@xedoc64
Copy link

xedoc64 commented Jul 2, 2021

Damn it, now its working. It really depends in which folder the script is stored. I didn't had any spaces or special chars in the folder name but it seems that there where permissions which leaded into the error.

@RonV42
Copy link

RonV42 commented Jul 15, 2021

I translated the French to English, also I had to cleanup from the old method after the DSM 7 upgrade. Disabled the cron job. When into the proxy settings for Vaultwarden made one change (port number) saved, then made the change back (original port number) and saved. This reset the files back to default. After that this shell script worked like a champ in DSM 7. Validated the syntax of the cron job and restarted.

#!/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 {
    proxy_pass http://$IP_NAS:$PORT_CONT;
    proxy_set_header Upgrade \$http_upgrade;
    proxy_set_header Connection \"upgrade\";
}

location /notifications/hub/negotiate {
    proxy_pass http://$IP_NAS:$PORT_ACCES;
}
""" >>$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

@coalfield
Copy link

coalfield commented Jul 15, 2021

Thanks for doing this @MilesTEG1 @RonV42. I too am on DSM 7 but would like to make the changes required manually if possible, only so if anything goes wrong in future I have understand what I am doing.

What is the end result of the script? Trying to look at the code so far it looks like

It creates a file in /etc/nginx/ called websocket.locations.vaultwarden containing

location /notifications/hub {
    proxy_pass http://IP:WS-PORT;
    proxy_set_header Upgrade \$http_upgrade;
    proxy_set_header Connection \"upgrade\";
}

location /notifications/hub/negotiate {
    proxy_pass http://IP:BW-PORT;
}

And then adds

include /etc/nginx/websocket.locations.vaultwarden;

this file to /etc/nginx/sites-enabled/server.ReverseProxy.conf

EDIT:

Ran the script as I think I know what it was doing from the above, noting I had to sudo su after SSHing in to get permissions.
Works absolutely perfectly. Thank you!

@RonV42
Copy link

RonV42 commented Jul 16, 2021

@coalfield Your coments were correct on the process the script takes and the outputs. I also did what you did to verify. I put pauses into the script, verifyed the actions to files, and confirmed that it was making the right edits to the server.ReverseProxy.conf file. It's good to have a fallback if something does happen in the future.

@MilesTEG1
Copy link

@RonV42 👍 Well done for the translation.
You should edit this line :

##        /!\      The online IP address 47 must be changed to the NAS IP     /!\             ##

to :

##        /!\      The online IP address in line 47 must be changed to the NAS IP     /!\     ##

😃

@SirDanc3lot
Copy link

SirDanc3lot commented Oct 21, 2021

Hi there and thanks for all the research!

Just to be sure and before anything else; If the internal container ROCKET_PORT is 1111, the local mapped port is 2222, and the WAN port is 3333, so the reversed proxy is doing HTTPS://WANIP:3333->HTTP://LANIP:2222, i should be using the command : bash /volume1/docker/vaultwarden/enable_ws.sh mynas.mydomain.com 3333 3012?
(all three WAN/LAN/Docker port numbers for the WEBSOCKET_PORT are the same: 3012 in my config)

If so, then perhaps someone may know why i'm getting this error in my vaultwarden.log:
2021-10-22 00:30:38.655][vaultwarden::api::notifications][ERROR]
###########################################################
'/notifications/hub' should be proxied to the websocket server or notifications won't work.
Go to the Wiki for more info, or disable WebSockets setting WEBSOCKET_ENABLED=false.
###########################################################################################

And although it 'seems' to work, as the developer console of firefox gives: "Information: WebSocket connected to wss://mynas.mydomain,com:3333/notifications", changing an item in the Firefox extension or in the iOS app, syncs immediately to the webvault, but not the reverse. Neither does it livesync from extension to iOS or vice versa. only after manual sync...

I checked for /etc/nginx/websocket.locations.vaultwarden and if /etc/nginx/websocket.locations.vaultwarden gets added to /etc/nginx/sites-enabled/server.ReverseProxy.conf and its all there...

Thanks in advance for any feedback!

@SirDanc3lot
Copy link

SirDanc3lot commented Oct 22, 2021

OK after more trial and error debugging: the Firefox extention was connected via local LAN IP address. Switched to domainname and it works flawlessly! both on LAN and on WAN. Only thing that doesnt work is iOS app receiving. Sending is instant though. So the log error seems to be iOS related and only push towards iOS (15.0.2). Probably a bug on either side.

@ClusterDuckster
Copy link

Hi guys and thanks for the script :)

I recently hosted another application on my NAS and needed a reverse proxy for that, too. I noticed that the script adds the websocket include statement to all DSM Reverse Proxy entries in the nginx configuration file. I updated the script to only add the include statement to the reverse proxy part for vaultwarden. The next text part to identify the vaultwarden part was the Reverse Proxy Source Port (most probably your https port). For that I added the Source Port as a parameter. Also I made the the IP_NAS variable into a parameter, since it is a configuration value from my point of view.

#!/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 in line 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                                            ##
## -- 5557 = Port your DSM Reverse Proxy listens on (Source port)"                            ##
## -- 192.168.0.123 = IP of your Synology NAS                                                 ##
##                                                                                            ##
##==============================================================================================

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

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 5557 192.168.0.123 "
  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 target/destination port)"
  echo "                           -- 5556 = Port exposed WEBSOCKET_PORT by Docker"
  echo "                           -- 5557 = Port your DSM Reverse Proxy listens on (Source port)"
  echo "                           -- 192.168.0.123 = IP of your Synology NAS"
}

if [ ! $# -eq 5 ]; 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 {
    proxy_pass http://$IP_NAS:$PORT_CONT;
    proxy_set_header Upgrade \$http_upgrade;
    proxy_set_header Connection \"upgrade\";
}

location /notifications/hub/negotiate {
    proxy_pass http://$IP_NAS:$PORT_ACCES;
}
""" >>$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" $LOC_DIR/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), but also applies it to other DSM reverse proxies
  # 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

  # DSM 7, only updates the server block which is listening for the vaultwarden reverse proxy source port (should be an https a port, otherwise the ssl part in the regex needs to be changed) (added new parameters)
  # Info: I am a total noob with sed, so switched to awk, which I am also a noob at, but it seemed easier to implement looking 2 lines behind.
  awk "
    \$0 ~ /^[[:blank:]]*server_name[[:blank:]]*${MY_DOMAIN}[[:blank:]]*;[[:blank:]]*\$/ && second_last ~ /^[[:blank:]]*listen[[:blank:]]*\[::\]:${PORT_HTTPS}[[:blank:]]*ssl;[[:blank:]]*\$/ {
      print
      print \"\n\tinclude ${LOC_DIR}/websocket.locations.vaultwarden\" 
      next
    }1

    {
      second_last = last
      last = \$0
    }
  " $LOC_DIR/sites-enabled/server.ReverseProxy.conf > $LOC_DIR/sites-enabled/server.ReverseProxy.conf.new
  mv $LOC_DIR/sites-enabled/server.ReverseProxy.conf.new $LOC_DIR/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

@MilesTEG1
Copy link

@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

@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

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

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

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