BYOPM is a portable Password Manager implementation based on VaultWarden, an unofficial implementation of BitWarden and a Raspberry PI Zero. It’s a self hosted solution, with full functionality, which is activated by just plugging the device on your computer. Bitwarden’s Official browser addons and extensions are also supported, and the device has been tested both on Windows (10 and 11) and Linux (Debian Based).
Updated 18th of April 2023
Today I tried to create another device, although Docker was not installing and was returning:
E: Sub-process /usr/bin/dpkg returned an error code (1)
The solution was to run apt full-upgrade
instead of just apt upgrade
and reboot
the device before running docker’s installation script. These commands are now included in the procedure which follows.
Updated 7th of December 2022
Following @GZX comment regarding the "Failed to fetch" issue while trying to use the Desktop App, I found that many users have the same issue when using self-signed certificates. The same error appears in Chrome if you try logging in using the addon while you have never before signed in through the web page. For Chrome there is a solution for importing the certificate but unfortunately for the Desktop App I couldn’t find a workaround. The only solution is to use a certificate from a free (Let’s Encrypt or Cloudflare ) or paid Trust Authority.
Updated 2nd of November 2022
As @Vic mentioned at the comments section the device is not using an official Bitwarden docker image, but the compatible VaultWarden Rust Server by Daniel Garcia. If you have any issues which you want to report, do that in the appropriate section.
In reply to @WJCarpenter I am also attaching a gif of the device in action, where you can see the small piece of the acrylic rod which is used for covering the led indicator hole:
How it works
Plug BYOPM to your computer using a micro usb cable, after about a minute a new network device will be automatically created and appear as connected. BYOPM hosts a Vaultwarden instance which is required for managing your passwords and also emulates an ethernet network interface card in order to be accessible from your computer without any configuration. Vaultwarden is then accessbible using your browser at https://byopm.local.
Bill of Materials
1) Raspberry Pi Zero (Any version will be OK, but if you want to print the official BYOPM case avoid the H versions which include the 2.54mm pin header)
2) Tactile Push Button 6 x 6 x 6 mm (amazon.com)
3) Raspberry PI Case [optional] (thingiverse)
4) 3 x M2 x 6 mm screws [optional]
5) 3 mm length x 3 mm diameter transparent acrylic rod (if you plan to print the custom case) [amazon.com] (https://www.amazon.com/Weststone-acrylic-Transparent-Standard-Tolerance/dp/B07YMSQXKG)
Schematic
Pay special attention when soldering the tactile switch to the board. It must be aligned with top cover’s hole and you must remove all the excess of soldering material from the bottom side of the Raspberry board.
Preparation
The following steps executed on a Raspberry PI Zero W Rev. 1.1 (Model: 9000c1), running the official Raspberry OS Lite released on September 22nd 2022 ( 32-bit system, Debian 11, Kernel version: 5.15).
SD-Card preparation
Using the official Raspberry PI Imager tool configure your SD Card as follows:
-
Click on CHOOSE OS
-
Select the 32 bit Image of Raspberry PI OS
-
Connect your SD Card to your Computer, using a card reader or a USB adapter and click on CHOOSE STORAGE
-
Select your SD CARD (WARNING: Make sure that the storage you selected is indeed your Raspberry PI’s SD Card to avoid any unwanted data loss)
-
Click on the GEAR Button located bottom right.
-
Type byopm as hostname, enable SSH, set your own username and password and configure your wireless LAN (you can skip Wi-Fi configuration if you will configure the device using the Serial Console).
-
Save your configuration and click the WRITE button.
-
When your SD Card is ready the following message will appear.
-
Finally, click CONTINUE, remove the SD card from your computer and re-plug it to appear as a USB Removable Storage.
-
Navigate to the Removable Storage and edit the config.txt file:
-
Append the following commands to enable the ShutDown Button functionality and the Serial Console [optional] (It is recommended to enable the Serial Console as a redundant communication link):
enable_uart=1 dtoverlay=gpio-shutdown
-
Save the file and safely remove your SD Card.
Initial Raspberry PI Configuration
Place your SD card back to the Raspberry PI and plug the power cable. Establish a terminal connection to your Raspberry either using SSH (use byopm.local as hostname) or Serial Console.After establishing the connection and logging in:
Update your distribution using the commands :
sudo apt update
sudo apt full-upgrade -y
sudo reboot
Install dnsmasq and nginx:
sudo apt install -y dnsmasq nginx
Install Docker:
curl -sSL https://get.docker.com | sh
Add your user to the docker group, replace your username:
sudo usermod -aG docker USERNAME_HERE
Apply the new group to the user.
exec su -l USERNAME_HERE
You will be prompted for your password in order to apply the new group.
Pull the Docker Image of Vaultwarden:
docker pull vaultwarden/server:latest
Create a self-signed certificate
This self-signed certificate will last for 730 days and will be stored in the /etc/ssl/certs/. The Private key will be store in the /etc/ssl/private/ directory. While generating the certificate you will be asked to provide some details, pick your country code from this list, skip everything else and type byopm.local as Common Name.
sudo openssl req -x509 -nodes -days 730 -newkey rsa:4096 -keyout /etc/ssl/private/nginx-bitwarden.key -out /etc/ssl/certs/nginx-bitwarden.crt
Create a Diffie-Helman group
This is used to help improve the security of your device’s SSL connections and is the most time consuming procedure. Unfortunately due to the low resources of Raspberry PI Zero, this is taking about 20 minutes to complete.
sudo openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048
Configuring NGINX hosting
Nginx is the webserver which will host the Vaultwarden web interface. It was installed but currently working with the default configuration, a new configuration must created to enable Vaultwarden functionality.
Remove the default nginx configuration
sudo rm /etc/nginx/sites-enabled/default
Make a new nginx configuration
sudo nano /etc/nginx/sites-enabled/bitwarden.conf
with the following content:
server {
listen 80;
listen [::]:80;
server_name byopm.local;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
server_name byopm.local;
ssl_certificate /etc/ssl/certs/nginx-bitwarden.crt;
ssl_certificate_key /etc/ssl/private/nginx-bitwarden.key;
ssl_dhparam /etc/ssl/certs/dhparam.pem;
# Send functionality of BW allows up to 100MB
client_max_body_size 128M;
location / {
proxy_pass http://0.0.0.0:8080;
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;
}
location /notifications/hub {
proxy_pass http://0.0.0.0:3012;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
location /notifications/hub/negotiate {
proxy_pass http://0.0.0.0:8080;
}
}
Restart NGINX
sudo systemctl restart nginx.service
Configuring VaultWarden
Create a random Admin token
To access the administration interface you will need to provide an admin token. You can create this token using this function:
openssl rand -base64 48
It’s a good idea after making any configuration changes to disable the administration access by re-running the container without an admin token.
Run the Vaultwarden Docker container
Replace your Admin token and use the following command to run the Vaultwarden Docker container
sudo docker run -d --name vaultwarden \
-e ADMIN_TOKEN=[ADMIN_TOKEN_FROM_PREVIOUS_STEP_HERE] \
--restart=always \
-v /bw-data/:/data/ \
-p 127.0.0.1:8080:80 \
-p 127.0.0.1:3012:3012 \
vaultwarden/server:latest
Confirm that the container is running:
docker ps
Configure Vaultwarden’s web interface
- Navigate to https://byopm.local/admin, you will get a warning about the self-signed certificate. This is because browsers only trust certificates from specific authorities which can validate. Self-signed certificates is a workaround to avoid paying, while maintaining a secure connection between server and client.
- Click Advanced
- Click Accept the Risk and continue
- Enter the Admin Token you generated before and Click Enter
- At the General settings tab make sure that Domain URL is https://byopm.local and click Save at the end of the page.
- Verify that web interface will indeed use the specific domain by visiting https://byopm.local/app-id.json, and under ids the https://byopm.local exist.
Not configuring the Domain URL, may result in "Failed to fetch" Error while using or configuring Vaultwarden.
- Now navigate to https://byopm.local click on Create Account and create a new account.
Configure Raspberry PI to act as a Network Interface Card (Ethernet Gadget)
Raspberry PI, will act as a Network Interface Card and will also host a DNS Server using dnsmasq. Every time the device connects on a computer, it will automatically create a new Network connection and provide the computer with a specific IP.
Configure the Network Interface
sudo nano /etc/network/interfaces
and append
auto lo
iface lo inet loopback
auto usb0
allow-hotplug usb0
iface usb0 inet static
address 10.18.1.19
netmask 255.255.255.0
Configure the DHCP and DNS Server
sudo nano /etc/dnsmasq.conf
and append
dhcp-range=10.18.1.20,10.18.1.21,12h
dhcp-option=option:dns-server,10.18.1.19
port=53
domain-needed
bogus-priv
listen-address=127.0.0.1,10.18.1.19
expand-hosts
domain = local
local=/local/
Replace Server’s IP for proper resolving
sudo nano /etc/hosts
and replace
127.0.0.1 byopm
with
10.18.1.19 byopm.local byopm
Configure Raspberry to act as an Ethernet Gadget
-
Create the gadget script.
sudo mkdir -p /etc/novamostra sudo nano /etc/novamostra/gadget.sh
and insert the following content:
#!/bin/bash #October 2022 #This file is part of BYOPM. #Copyright (c) novamostra.com GADGET_DIR="nm_ether" VENDOR_ID="0x1d6b" PRODUCT_ID="0x0104" HOST="00:dc:c8:f7:75:14" SELF="00:dd:dc:eb:6d:a1" modprobe libcomposite mkdir -p /sys/kernel/config/usb_gadget/$GADGET_DIR cd /sys/kernel/config/usb_gadget/$GADGET_DIR echo $VENDOR_ID > idVendor echo $PRODUCT_ID > idProduct echo 0x0100 > bcdDevice echo 0x0200 > bcdUSB echo 0xEF > bDeviceClass echo 0x02 > bDeviceSubClass echo 0x01 > bDeviceProtocol mkdir -p strings/0x409 # English language strings echo "nm_nic_01" > strings/0x409/serialnumber echo "novamostra" > strings/0x409/manufacturer echo "byopm" > strings/0x409/product mkdir -p configs/c.1/strings/0x409 echo "Config 1: RNDIS network" > configs/c.1/strings/0x409/configuration echo 250 > configs/c.1/MaxPower echo 0x80 > configs/c.1/bmAttributes mkdir -p functions/rndis.usb0 # set up mac address of remote device echo $HOST > functions/rndis.usb0/host_addr # set up local mac address echo $SELF > functions/rndis.usb0/dev_addr # Force windows configuration echo "1" > os_desc/use echo "0xcd" > os_desc/b_vendor_code echo "MSFT100" > os_desc/qw_sign mkdir -p functions/rndis.usb0/os_desc/interface.rndis echo RNDIS > functions/rndis.usb0/os_desc/interface.rndis/compatible_id echo 5162001 > functions/rndis.usb0/os_desc/interface.rndis/sub_compatible_id ln -s functions/rndis.usb0 configs/c.1/ ln -s configs/c.1/ os_desc udevadm settle -t 5 || : ls /sys/class/udc > UDC
-
Give executing permission
sudo chmod +x /etc/novamostra/gadget.sh
-
Create the service
sudo nano /lib/systemd/system/nm_gadget.service
and insert the following content
[Unit] Description=Novamostra Ethernet Gadget Before=network-pre.target Wants=network-pre.target [Service] ExecStart=/usr/bin/bash /etc/novamostra/gadget.sh [Install] WantedBy=multi-user.target
-
Enable the service to automatically start on boot.
sudo systemctl enable nm_gadget.service
-
Disable the DHCPCD service to avoid any network conflicts.
sudo systemctl disable dhcpcd.service
-
Enable the Ethernet Gadget and disable the Wi-Fi module
In order to avoid any conflicts and keep the device as secure as possible, when the network setup finish, we have to disable the dhcpd service and the WiFi and Bluetooth connections of the device.sudo nano /boot/config.txt
and append:
dtoverlay=dwc2 dtoverlay=disable-wifi dtoverlay=disable-bt
-
Power off Raspberry PI
sudo poweroff
-
Verify connections
Disconnect all cables from your BYOPM device and connect only a micro USB cable from your computer to the appropriate port: (Notice that Raspberry PI has 2 micro USB ports but only one is a configured USB port, the other one is only for Powering the device).
Usage
Every time you connect the BYOPM to a computer, a new network adapter will appear as connected.
with the following settings:
Without any further configuration you will be able to access through your browser the https://byopm.local and use your own Bitwarden instance. For better functionality I recommend installing Bitwarden’s addons to the devices you plan to use your device and configure it as follows.
Bitwarden Firefox Addon
To install the official Bitwarden Firefox Addon, go to addon’s page and click Add to Firefox
When the installation complete, the addon will launch automatically (if not click the image next to Firefox’s menu icon), and click Settings on the top left side of the addon.
In the Settings window, set the Server url to https://byopm.local, and click Save
Next login using the credentials of the account you created to the prior setup.
The configuration is similar for the Chrome’s Bitwarden Extension
Chrome Warning: If for any reason the addon/extension fails to login (Error "Failed to fetch"), try first login using the normal web interface by navigating to https://byopm.local. After login through the web interface download and import the certificate to Chrome, this will solve the issue.
Code
The code is available on github
3d Files
BYOPM consists of 2 3d printed parts (top and bottom):
Both of them are available on thingiverse
Final Thoughts
- After completing the configuration, your device will also be available using SSH. Just plug it on your computer and use the byopm.local hostname to access it.
- It is recommended to always POWER OFF the device before removing it from the host computer. Use the Power Button and wait until the Status Indicator turn off.
Database Backup
WARNING: SD cards have a maximum number of read and writes. Storing your passwords on an SD card without any backup will soon result in lost passwords and possible lock outs. Always backup your database. In the current configuration is located in /bw-data/db.sqlite3
Wow. I was actually thinking about building a backup for my Bitwarden. That’s pretty interesting idea.
This is not what you’re doing. You’re pulling the Docker image of Vaultwarden, which is a reimplementation of Bitwarden server, but is not a Bitwarden image.
Please refer to Vaultwarden as Vaultwarden to avoid confusion. People may report Vaultwarden bugs to the Bitwarden project, where they won’t be able to help them.
Thanks for mentioning this, I updated the post accordingly.
What is the acrylic rod used for? I’m trying to visualize it from the description, but I can’t quite grok it.
The acrylic is just for covering the status indicator hole, take a look at the updated section where I attached a gif of the device in action
How to connect power? In the case, I see only a hole for the mini HDMI connector.
The device does not require any extra power. The hole you see is not for the mini HDMI but for the micro USB connector. You connect the device to your computer using a standard micro USB cable and the power from the port is enough to power the device.
Is there any way to connect to an Android phone to use BYOPM to manage credentials?
The current implementation only tested on Linux and Windows. Also I am not sure if all Android Devices support OTG and specifically the Ethernet device.
I love it, a bit complicated for me, but I will give it a try for sure!
How do I enable this device on a Mac? I can see the device under USB in system info but the interface doesn’t show up as a network adapter.
Unfortunately I don’t have an Apple Device and I know for sure that is a bit different to use the USB Gadget without the need of drivers on a Mac. If I make any process on this I will update the post accordingly.
I tried this twice but never a network adapter appeared?
What Operating System do you have on the host computer?
i install byopm on a zero w
Yes but what Operating System do you have on the computer you are connecting BYOPM to? Also are you using the correct port on the BYOPM? It should be the port nearest to the middle of the board. The micro usb at the edge of Zero W is only for powering the device.
The connected computer is windows, and I am using the USB port at the middle.
Ok, this is how to troubleshoot.
Note: During my tests, I realized that if you don’t use a good quality SD card the system may take more than 3 minutes to be ready. Using a Samsung PRO Class 10 micro SD my system is ready to use in about a minute and a half after plugging it to the USB port.
Is this compatible with the Windows Desktop Bitwarden app? I would like to use biometrics to login, this requites the desktop app in conjunction with the chrome plugin.
I get “Failed to Fetch” even though the desktop app is pointed to the local BYOPM server https://byopm.local
I am able to login to the web instance and the plugin is able to reach the local server, just not the desktop app.
Thanks
Unfortunately, this error is due to the self signed certificate. If you intend to use the desktop app you can follow the same procedure but instead either use a free service, like Let’s Encrypt or Cloudflare or a paid one to generate certificates from a Trusted Root Certificate provider.
Hi, I jut made my PasswordManager and it’s working perfectly fine on Laptop/Desktop. I was wondering that is their any way of connecting the this hardware to android application “BitWarden”, in same WiFi Network and also in other Network.
Unfortunately this Password Manager is not built for this purpose but it meant to be portable. If you want your Password Manager to be accessible over Internet you should deploy Bitwarden on a cloud vps (maybe aws, azure etc) or Self host it on a Raspberry/local device in your local network. The procedure is almost the same, you should just skip the steps of Configuring Raspberry PI to act as a Network Interface Card (Ethernet Gadget)
I just like the helpful information you provide in your articles