Using multipass To Create A WriteFreely Dev VM

If you've ended up at this blog post, you're probably like me: you've found a change you'd like to make to WriteFreely, but you can't (or don't want to) install all of its development dependencies on your machine. This guide will show you how to use multipass to set up a WriteFreely development VM so that you don't need to make changes to your host.

Note: If you run into any problems with this guide, feel free to reach out to me on the fediverse, I'm I can't promise I'll be able to help, but I will at the very least be sympathetic.

Updated (2019/08/19): This guide was updated to use multipass shell <vm> instead of multipass exec <vm> /bin/bash. This is more idiomatic, and avoids some known bugs.


That's it! We're going to do everything else inside our VM.

Creating our development VM

This is pretty simple:

$ multipass launch bionic --name writefreely-dev --mem 4G

This is going to fetch the latest Ubuntu 18.04 LTS (Bionic Beaver) image and create a VM named writefreely-dev from it, giving that VM 4GB of memory. (If you want to name your VM something different, go ahead! But: don't forget to use that name in later steps.)

(This step can sometimes take a while, if the Ubuntu data centre is under heavy network load (which it often is!). Don't worry if the progress is slow because that is, unfortunately, normal.)

Installing prerequisites in our development VM

First, let's get a shell in our development VM:

$ multipass shell writefreely-dev

<... long MOTD content ...>


Again, nice and simple!

OK, so now we can go and look at the Prerequisites section of the WriteFreely Development Setup guide and see what we need:

OK, so let's do these one at a time.

Installing Go 1.10+

We're going to use the go snap to install Go:

$ sudo snap install --classic go
go 1.12.9 from Michael Hudson-Doyle (mwhudson) installed


$ go version
go version go1.12.9 linux/amd64

Great, nailed it! On to the next thing.

Installing node.js

From my testing so far, node.js 8.x is sufficient for WriteFreely so we can just use the Ubuntu packages for it (make sure to install both nodejs and npm; unlike upstream, they don't come bundled together in Ubuntu):

$ sudo apt update
$ sudo apt install -y nodejs npm
$ node -v
$ npm -v

OK, prerequisites sorted, on to getting our WriteFreely development environment set up.

(Side note: apt update might tell you that there are upgrades available; you may as well apply those by running sudo apt upgrade.)

Setting up our WriteFreely development environment

Nobody wants to have to run their IDE or editor inside of their development VM, so we're going to have a WriteFreely tree on our host that we mount into the development VM.

(Note that these instructions diverge from the Development Setup guide because we're splitting things across host and VM.)

On the host

Let's start by cloning the WriteFreely repo. You can put this wherever you want (I use ~/personal_dev), just make sure to make a note of the path to the repo for the next step. Run this command:

$ git clone \

Now, we want to create the directory for multipass to mount to (multipass should handle this itself, I think, so I'll be filing a bug in the near future):

multipass exec writefreely-dev -- \
    mkdir -p go/src/

Next, we're going to ask multipass to mount the host's directory into the directory we just created in our development VM:

$ multipass mount \
    ~/personal_dev/writefreely \

And we can check that that's worked:

$ multipass exec writefreely-dev -- \
    head -n1 go/src/
# Contributing to WriteFreely

Great! So now we have a WriteFreely tree that we can easily edit from our host, mounted in to our VM so we can actually run WriteFreely there.

(BTW, did you notice that we used multipass exec to run mkdir and head directly within the VM? If you don't need a full shell, use exec.)

Oh, there's one last piece of information we need to grab before we jump into installing and configuring WriteFreely: the IP address of our development VM. You can find this by running multipass list:

$ multipass list
Name                  State           IPv4             Image
writefreely-dev       Running     Ubuntu 18.04 LTS

In my case, the address is Make a note of yours!

In our VM

OK, let's get back in the VM:

$ multipass shell writefreely-dev

And let's change to our mounted directory:

$ cd go/src/

We're now basically at the point after the first two commands in the “Setting up” section of the Development Setup guide, and we are effectively going to run through those commands in sequence. However, as we aren't running our development server on our host, there are a couple of specific choices we need to make.

First, though, let's install all of our dependencies and compile WriteFreely. To do that, we first need to do a little bit of house-keeping. Go will install binaries into ~/go/bin, and we need to make sure that those binaries are available to run by adding them to our PATH. We'll also modify .bashrc so that we don't have to remember to do this every time we log in:

$ export PATH=$PATH:~/go/bin
$ echo 'export PATH=$PATH:~/go/bin' >> ~/.bashrc

We can then install our dependencies and compile WriteFreely:

$ export GO111MODULE=on
# Save ourselves some time next time we login
$ echo 'export GO111MODULE=on' >> ~/.bashrc

$ make build

This will take a couple of minutes. (GO111MODULE=on is required to be set, and we also add it to our .bashrc so we don't have to remember this every time.)

Once this is complete, we're ready to configure our development WriteFreely instance by running:

$ make install

This is going to prompt you with a few questions. The important answers are:

Other than those, you can just accept the defaults. (Of course, make sure you remember your username/password, you'll need them to log in to your development site once it's running.)

We're very, very close to having a running site! The last change we need to make is to configure the development server to accept connections from our host. (The default configuration will only accept connections from the machine that it's running on, which is a very sensible default if you're running this on your host directly, but doesn't work for us.)

To do this, open up config.ini in your editor of choice (in or out of the VM, either should work fine) and change the bind value to “”. After editing, that line should look like this:

bind                 =

And now, finally, in our VM, we can start the development server:

$ make run

This will print out a bunch of logging with the line Serving on towards the end. Once you see that, you should be able to browse to the Public URL you configured before (http://<IP ADDRESS>:8080, remember?) and see your development instance!

Log in using the username/password you configured during make install and start making WriteFreely even better!