09 September 2018

BitWarden password manager self-hosted on free Google Cloud instance

BitWarden on free Google Compute Engine

enter image description here
A friend mentioned the BitWarden password manager to me yesterday and I had to confess that I'd never heard of it. I started researching it and was impressed by what I found: it's free, open-source, feature-packed, fully cross-platform (with Windows/Linux/MacOS desktop clients, Android/iOS mobile apps, and browser extensions for Chrome/Firefox/Opera/Safari/Edge/etc), and even offers a self-hosted option.

I wanted to try out the self-hosted setup, and I discovered that the official distribution works beautifully on an n1-standard-1 1-vCPU Google Compute Engine instance - but that would cost me an estimated $25/mo to run after my free Google Cloud Platform trial runs out. And I can't really scale that instance down further because the embedded database won't start with less than 2GB of RAM.

I then came across this comment on Reddit which discussed in somewhat-vague terms the steps required to get BitWarden to run on the free f1-micro instance, and also introduced me to the community-built bitwarden_rs project which is specifically designed to run a BW-compatible server on resource-constrained hardware. So here are the steps I wound up taking to get this up and running.

Spin up a VM

Easier said than done, but head over to https://console.cloud.google.com/ and fumble through:

  1. Creating a new project (or just add an instance to an existing one).
  2. Creating a new Compute Engine instance, selecting f1-micro for the Machine Type and ticking the Allow HTTPS traffic box.
  3. (Optional) Editing the instance to add an ssh-key for easier remote access.

Configure Dynamic DNS

Because we're cheap and don't want to pay for a static IP.

  1. Log in to the Google Domain admin portal and create a new Dynamic DNS record. This will provide a username and password specific for that record.

  2. Log in to GCE instance and run sudo apt-get update followed by sudo apt-get install ddclient. Part of the install process prompts you to configure things... just accept the defaults and move on.

  3. Edit the ddclient config file to look like this, substituting the username, password, and FDQN from Google Domains:

     $ sudo vi /etc/ddclient.conf
         # Configuration file for ddclient generated by debconf
         # /etc/ddclient.conf
  4. sudo vi /etc/default/ddclient and make sure that run_daemon="true":

    # Configuration for ddclient scripts 
    # generated from debconf on Sat Sep  8 21:58:02 UTC 2018
    # /etc/default/ddclient
    # Set to "true" if ddclient should be run every time DHCP client ('dhclient'
    # from package isc-dhcp-client) updates the systems IP address.
    # Set to "true" if ddclient should be run every time a new ppp connection is 
    # established. This might be useful, if you are using dial-on-demand.
    # Set to "true" if ddclient should run in daemon mode
    # If this is changed to true, run_ipup and run_dhclient must be set to false.
    # Set the time interval between the updates of the dynamic DNS name in seconds.
    # This option only takes effect if the ddclient runs in daemon mode.
  5. Restart the ddclient service - twice for good measure (daemon mode only gets activated on the second go because reasons):

    $ sudo systemctl restart ddclient
    $ sudo systemctl restart ddclient
  6. After a few moments, refresh the Google Domains page to verify that your instance's external IP address is showing up on the new DDNS record.

Install Docker

Steps taken from here.

  1. Update apt package index:

    $ sudo apt-get update
  2. Install package management prereqs:

    $ sudo apt-get install \
        apt-transport-https \
        ca-certificates \
        curl \
        gnupg2 \
  3. Add Docker GPG key:

    $ curl -fsSL https://download.docker.com/linux/debian/gpg | sudo apt-key add -
  4. Add the Docker repo:

    $ sudo add-apt-repository \
        "deb [arch=amd64] https://download.docker.com/linux/debian \
        $(lsb_release -cs) \
  5. Update apt index again:

    $ sudo apt-get update
  6. Install Docker:

    $ sudo apt-get install docker-ce

Install Certbot and generate SSL cert

Steps taken from here

  1. Add stretch-backports repo:

    $ sudo add-apt-repository \
        "deb https://ftp.debian.org/debian \
        stretch-backports main"
  2. Install Certbot:

    $ sudo apt-get install certbot -t stretch-backports
  3. Generate certificate:

    $ sudo certbot certonly --standalone -d [FQDN]
  4. Create a directory to store the new certificates and copy them there:

    $ sudo mkdir -p /ssl/keys/
    $ sudo cp -p /etc/letsencrypt/live/[FQDN]/fullchain.pem /ssl/keys/
    $ sudo cp -p /etc/letsencrypt/live/[FQDN]/privkey.pem /ssl/keys/

Set up bitwarden_rs

Using the container image available here

  1. Let's just get it up and running first:

    $ sudo docker run -d --name bitwarden \
        -e ROCKET_TLS={certs='"/ssl/fullchain.pem", key="/ssl/privkey.pem"}' \
        -e ROCKET_PORT='8000' \
        -v /ssl/keys/:/ssl/ \
        -v /bw-data/:/data/ \
        -v /icon_cache/ \
        -p \
  2. At this point you should be able to point your web browser at https://[FQDN] and see the BitWarden login screen. Click on the Create button and set up a new account. Log in, look around, add some passwords, etc. Everything should work just fine (with a few exceptions).

  3. Unless you want to host passwords for all of the Internet you'll probably want to disable signups at some point by adding the env option SIGNUPS_ALLOWED=false. And you'll need to set DOMAIN=https://[FQDN] if you want to use U2F authentication:

    $ sudo docker stop bitwarden
    $ sudo docker rm bitwarden
    $ sudo docker run -d --name bitwarden \
        -e ROCKET_TLS={certs='"/ssl/fullchain.pem",key="/ssl/privkey.pem"'} \
        -e ROCKET_PORT='8000' \
        -e SIGNUPS_ALLOWED=false \
        -e DOMAIN=https://[FQDN] \
        -v /ssl/keys/:/ssl/ \
        -v /bw-data/:/data/ \
        -v /icon_cache/ \
        -p \

Install bitwarden_rs as a service

So we don't have to keep manually firing this thing off.

  1. Create a script to stop, remove, update, and (re)start the bitwarden_rs container:

    $ sudo vi /usr/local/bin/start-bitwarden.sh
        docker stop bitwarden
        docker rm bitwarden
        docker pull mprasil/bitwarden
        docker run -d --name bitwarden \
                -e ROCKET_TLS={certs='"/ssl/fullchain.pem",key="/ssl/privkey.pem"'} \
                -e ROCKET_PORT='8000' \
                -e SIGNUPS_ALLOWED=false \
                -e DOMAIN=https://[FQDN] \
                -v /ssl/keys/:/ssl/ \
                -v /bw-data/:/data/ \
                -v /icon_cache/ \
                -p \
    $ sudo chmod 744 /usr/local/bin/start-bitwarden.sh
  2. And add it as a systemd service:

    $ sudo vi /etc/systemd/system/bitwarden.service
        Description=BitWarden container
        ExecStop=/usr/bin/docker stop bitwarden
    $ sudo chmod 644 /etc/systemd/system/bitwarden.service
  3. Try it out:

    $ sudo systemctl start bitwarden
    $ sudo systemctl status bitwarden
        ● bitwarden.service - BitWarden container
           Loaded: loaded (/etc/systemd/system/bitwarden.service; enabled; vendor preset: enabled)
           Active: deactivating (stop) since Sun 2018-09-09 03:43:20 UTC;   1s ago
          Process: 13104 ExecStart=/usr/local/bin/bitwarden-start.sh (code=exited, status=0/SUCCESS)
         Main PID: 13104 (code=exited, status=0/SUCCESS); Control PID:  13229 (docker)
            Tasks: 5 (limit: 4915)
           Memory: 9.7M
              CPU: 375ms
           CGroup: /system.slice/bitwarden.service
                     └─13229 /usr/bin/docker stop bitwarden
        Sep 09 03:43:20 bitwarden bitwarden-start.sh[13104]: Status: Image is up to date for mprasil/bitwarden:latest
        Sep 09 03:43:20 bitwarden bitwarden-start.sh[13104]:        ace64ca5294eee7e21be764ea1af9e328e944658b4335ce8721b99a33061d645


If all went according to plan, you've now got a highly-secure open-source full-featured cross-platform password manager running on an Always Free Google Compute Engine instance resolved by Google Domains dynamic DNS. Very slick!

18 July 2018

Zolo Liberty True Wireless In-Ear Headphones

I listen to a lot of music at work - easily 4-6 hours every day. For the past nine months, I’ve been using (and loving) the much-maligned Google Pixel Buds to get through the day. For the last week, though, I’ve been wearing the Zolo Liberty True Wireless In-Ear Headphones from Anker’s audio brand. These truly-wireless Bluetooth headphones sound great and have incredible stamina, but how do they compare to my beloved Pixel Buds?


Many have complained about the Pixel Buds’ one-size-fits-all approach, and those users will be pleased to learn that the Zolo Liberty headphones come with liquid silicone tips in four different sizes. Also included are GripFit “Jackets” in four sizes which can be slipped over the body of the earbuds to further adjust the fit. After selecting the best combination of tips and jackets for my ears, I gently pushed the Liberty headphones into my ears and rotated them to the rear as instructed to lock them securely in place. It’s a very solid fit, and these earbuds aren’t going to fall out even with heavy jostling from working out.

That said, fitment is a very personal metric to quantify, and every pair of ears is different. While the GripFit EarTips and Jackets provided a very secure fit, none of the various combinations I tried were particularly comfortable for me. The truly wireless design of the Zolo Liberty headphones means that each earbud needs to contain its own battery, Bluetooth radio, and other electronics, while the wire tethering the two Pixel Buds allows the left side to house the battery while the right holds the radio, touch sensor, and other electrical bits. The result is that the Liberty headphones are considerably bulkier and heavier than the Pixel Buds. I truly could forget that I was wearing the Pixel Buds, but I always felt the Libertys in my ears and often experienced a bit of soreness after extended listening sessions. Your mileage will likely vary, but the Pixel Buds are far more comfortable for me.

17 March 2018

Portable 45W Power for the Google Pixelbook!

I've been using a Google Pixelbook as my primary computing device for five months now. The Pixelbook has a ton of great qualities: it's unbelievably quick, has an incredible build quality, runs Android apps, packs a fantastic touchscreen that folds flat for tablet usage, and (with developer mode + crouton) can handle just about everything I need to do on a computer. I have also been pleased with the battery life; depending on what I'm doing, I tend to get 6-7 hours of use out of a charge.

Of course, even with great battery life it doesn't hurt to have backup power available - and the convenience of dual USB-C ports should make that pretty easy to accomplish, right? I should just be able to grab any power bank which advertises 30W or 45W USB Power Delivery and get started charging on the go, right? 

Unfortunately, it hasn't worked out to be that easy. I've been quietly and casually testing USB-C PD power banks for a month or two now, trying to find one which worked reliably with my Pixelbook. I don't have the skills, knowledge, or resources to do compliance testing like Nathan or Benson, but I used a Plugable USB-C power meter to monitor the current flow and make sure that it didn't drift wildly out of spec. I probably tested a half-dozen power banks before finding one that actually works to my satisfaction. 

I didn't encounter any that I'd consider dangerous; they just didn't work. Some would only draw power from the Pixelbook. One wouldn't pass any power when the Pixelbook was connected. One apparently provided enough power to activate the meter but the measured flow was 0V @ 0A. A few would constantly reboot; one only did so while the meter was connected and seemed to charge the Pixelbook okay without the pass-through meter in-line but that was still clearly incorrect behavior. Without a PD sniffer I don't know why these power banks didn't work but my hunch is negotiation problems. 

All of which brings me to the reason for this post: I found one that works! 

This is the ZMI PowerPack 20000, a 20000mAh battery pack with 45W USB PD output. I was a bit apprehensive since I hadn't heard of the brand before but this has succeeded where power banks from brands like Anker, RAVPower, and dodocool let me down.

While testing the ZMI power bank, I measured a pretty consistent 14.4V @ 2.7A - which exactly matches what my meter reports from the 45W wall charger that came with the Pixelbook. 

It charged the Pixelbook from 67%-87% in about 25 minutes. (The charging rate dropped from 45W (14.4V @ 2.7A) to 30W (14.4V @ 1.8A) somewhere around 85% so that did slow things a little bit. Again, I've observed the same behavior with the original charger). 

As a bonus, the ZMI power bank also has a USB 2.0 hub mode which works great for USB mice and USB storage drives - while still charging the Pixelbook at the appropriate rate.

In subsequent charging tests the ZMI power bank has continued to perform predictably. Again, I'm not able to comment on any of the PD negotiation traffic or USB spec compliance but it seems to me that it is doing exactly what it's supposed to. I haven't had any problems with the power bank trying to charge from the Pixelbook, failing to charge the Pixelbook, or trying to push an unexpected voltage/amperage combination. 

Consistent 45W charging in a small form factor with the added benefit of USB hub functionality at a reasonable $70 price makes the ZMI PowerPack 20000 an easy recommendation.

11 September 2017

Anker PowerLine+ 6ft USB-C to USB 2.0 Cable [2-pack!]

I've long been a fan of Anker's high-quality PowerLine+ cables, and I am pleased to report that the fine tradition continues in the brand's USB-C to USB-A cables for modern Android devices. Today I'm specifically looking at the Anker PowerLine+ 6-foot USB-C to USB 2.0 Cable 2-Pack which I've been using (and abusing!) for the past week or so.

Users familiar with PowerLine+ cables already know that these are some of the most durable cables available. They feature an aramid fiber core for added strength and are wrapped end-to-end with double-braided nylon for extra protection (and, let's be honest here, a pretty cool look). The nylon provides a great smooth feel to the cable and, more importantly, keeps it from getting kinked or knotted. You can fold, wrap, or roll these cables without worrying about them getting damaged or holding permanent bends.

The connectors on either end are built to last as well, featuring a laser-welded metal construction with reinforced stress points to help resist splitting apart like some inferior cables. This is then shrouded in a two-piece protective shell consisting of tough plastic around the connector itself with a soft and flexible boot to reduce stress at the critical junction between cable and connector.

24 October 2016

Anker PowerCore+ 10050: Great balance of power and size

Confession time: I’m a portable charger hoarder. I’ve been compulsively collecting them for years, and have drawers full of the ones I bought, used for a few weeks, and then replaced with something better. Different sizes and features work better for different scenarios, so lately I’ve been carrying an Anker PowerCore 5000 for a bit of ultra-portable juice while on the go or the massive Anker PowerCore+ 26800 while away from extended periods away from The Grid. Of course, the smaller one really only provides enough power for a single extra charger, while the larger is just simply too big to put in a pocket for a quick outing.

Enter the Anker PowerCore+ 10050. To me, this is the Goldilocks of Anker’s portable chargers - packing enough power to recharge my Nexus 6P a couple of times in a surprisingly compact form factor. Like its big brother, the PowerCore+ 10050 features a sturdy aluminum shell finished in a smooth matte black. This model is roughly the same size as my wallet packed with a bunch of unused rewards and loyalty cards, and the curved sides and rounded edges make it easy and snag-free to tuck into a large pocket or bag.

Many other portable chargers leave you guessing at how much of a charge remains (“three lights, so that’s somewhere between 66.67% and 100%?”), but the round button on the side of the PowerCore+ features a ring of ten tiny white LEDs. Just tap the button and the ring will illuminate to indicate the current capacity in 10% increments. The ring also animates while the PowerCore+ is charging in order to quickly convey the status.

24 September 2016

Anker PowerCore+ 26800: Power to get through the week

As I sit down on Friday evening to type up a quick review, my Nexus 6P lets me know its battery level has dipped below 10%. Any other day, I’d be frustrated - but today, I’m immensely pleased. You see, I haven’t plugged my phone into a wall charger, car charger, or even random USB port since Sunday morning.

No, I didn’t install some magical new battery-extending application, manually enable Airplane Mode, or even activate Android’s built-in Battery Saver. Instead, I powered my phone solely off of Anker’s high-capacity PowerCore+ 26800 for five full work days and nights. Nexus devices aren’t exactly known for their stamina, and I use my phone heavily - so trust me when I say getting a week of use without a wall charger is quite a feat.

Of course, all of that juice does come with a price - or, more accurately, two. First, the PowerCore+ 26800 is a well-designed, pleasantly contoured, surprisingly slim brick. It’s big, and it’s heavy. This isn’t a power pack you’ll be likely to slip into your pants pocket for on-the-go Pokemon GO power (unless you’re still wearing JNCO’s, I suppose). And while the included PowerPort+ 1 wall charger uses Quick Charge 3.0 technology to rapidly charge up the battery pack, “rapidly” becomes a very relative term when talking about powering a 26,800mAh behemoth. I know Anker advertises a 6.5-hour charge time, but my experience suggests planning on closer to 8 or 9 hours. Neither of these points are really problems with the unit, they’re just the nature of such a beast and should be kept in mind and planned for.

31 August 2016

Anker Dashboard and Windshield Phone Mount: Secure Mobile Device Mount

It took me the better part of a year (and no small number of purchases) to test and land on the best phone mount to use in my car, and I eventually settled on a generic adjustable mount which fits securely in my CD tray. It’s a pretty good setup for my car (Subaru BRZ), which has a shallowly-sloped windshield far away from my driving position. It’s not a great solution for other cars, though, so I always struggle to come up with a good mount to use when in my wife’s car or a rental while on vacation.

So I was excited to be offered the opportunity to try out the Anker Dashboard and Windshield Car Mount. The mount arrived just before I embarked on a cross-country roadtrip, so I got to put it through an excellent real-world test.

Like all Anker products, the mount arrived in friendly easy-to-open packaging. Included within were the expandable phone holder, sturdy adjustable arm with suction cup base, brief welcome guide, and Anker product feedback card.

Assembling the mount is a breeze. The two pieces are attached by a ball-and-socket joint, so simply unscrew the large plastic nut from the socket on the back of the phone holder, slide it over the protruding ball on the end of the adjustable arm, and screw the nut back down. The joint allows the phone holder to swivel in any direction to accommodate any phone orientation you desire, but the proximity to the squared-off end of the arm prevents the holder from tilting more than ~30° or so in any one direction. As a result, only about 60° of the arm’s impressive 260° rotation range is actually useful if you intend to have your phone’s display roughly perpendicular to the ground. I didn’t encounter any mounting problems due to this limitation, but you may run into trouble if you attempt a more extreme mounting angle.