diff --git a/.gitignore b/.gitignore
index 7ae0e8facdc822a30c45041ada503111b7a29b1d..539a2ec05c1c5561450e0a2b463601aac4aa608b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -11,3 +11,4 @@ webextension.go
 webext/node_modules
 webext/dist/*
 dist
+*.xpi
diff --git a/Dockerfile b/Dockerfile
index 0b01637fa706ec4f83947cc5d7e7ff0def1b6314..b9da3a9281428e2bc079aa0310910b29bb6540bf 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,39 +1,87 @@
+FROM bitnami/minideb:stretch as build
+
+RUN install_packages \
+      curl \
+      ca-certificates \
+      git \
+      autoconf \
+      automake \
+      g++ \
+      protobuf-compiler \
+      zlib1g-dev \
+      libncurses5-dev \
+      libssl-dev \
+      pkg-config \
+      libprotobuf-dev \
+      make
+
+# Install Golang
+ENV GOROOT=/go
+ENV GOPATH=/go-home
+ENV PATH=$GOROOT/bin:$GOPATH/bin:$PATH
+RUN curl -L -o go.tar.gz https://dl.google.com/go/go1.9.2.linux-amd64.tar.gz
+RUN mkdir -p $GOPATH/bin
+RUN tar -C / -xzf go.tar.gz
+
+ENV BASE=$GOPATH/src/browsh/interfacer
+WORKDIR $BASE
+ADD interfacer $BASE
+
+# Install `dep` the current defacto dependency manager for Golang
+RUN $BASE/contrib/setup_dep.sh
+
+# Install the tool to convert the web extenstion file into a Go-compatible binary
+RUN go get -u gopkg.in/shuLhan/go-bindata.v3/...
+
+# Build Browsh
+RUN dep ensure
+RUN $BASE/contrib/build_browsh.sh
+
+
+###########################
+# Actual final Docker image
+###########################
 FROM bitnami/minideb:stretch
 
-RUN install_packages xvfb libgtk-3-0 curl ca-certificates bzip2 libdbus-glib-1-2 procps
+ENV HOME=/app
+WORKDIR /app
+
+COPY --from=build /go-home/src/browsh/interfacer/browsh /app/browsh
+
+RUN install_packages \
+      xvfb \
+      libgtk-3-0 \
+      curl \
+      ca-certificates \
+      bzip2 \
+      libdbus-glib-1-2 \
+      procps
 
+# Block ads, etc. This includes porn just because this image is also used on the
+# public SSH demo: `ssh brow.sh`.
 RUN curl -o /etc/hosts https://raw.githubusercontent.com/StevenBlack/hosts/master/alternates/fakenews-gambling-porn-social/hosts
 
+# Don't use root
 RUN useradd -m user --home /app
+RUN chown user:user /app
 USER user
-ENV HOME=/app
-WORKDIR /app
-
-# These are needed to detect versions
-ADD .travis.yml .
-ADD ./webext/manifest.json .
 
 # Setup Firefox
-ENV PATH="/app/bin/firefox:${PATH}"
-ADD ./interfacer/contrib/setup_firefox.sh .
+ENV PATH="${HOME}/bin/firefox:${PATH}"
+ADD .travis.yml .
+ADD interfacer/contrib/setup_firefox.sh .
 RUN ./setup_firefox.sh
-RUN rm ./setup_firefox.sh && rm .travis.yml
-
-# Setup Browsh
-ADD ./interfacer/contrib/setup_browsh.sh .
-ADD ./interfacer/src/browsh/version.go .
-RUN VERSION_FILE=version.go ./setup_browsh.sh
-RUN rm ./setup_browsh.sh && rm version.go
+RUN rm setup_firefox.sh && rm .travis.yml
 
 # Firefox behaves quite differently to normal on its first run, so by getting
 # that over and done with here when there's no user to be dissapointed means
 # that all future runs will be consistent.
 RUN TERM=xterm script \
-      --return \
-      -c "/app/browsh" \
-      /dev/null \
-      >/dev/null & \
-      sleep 10
+  --return \
+  -c "/app/browsh" \
+  /dev/null \
+  >/dev/null & \
+  sleep 10
 
 CMD ["/app/browsh"]
 
diff --git a/README.md b/README.md
index 0b1f0dd58825856b6e4df5b617cc986755ac6e91..bedc330c0c2782a722b58c316717aee59c22afd2 100644
--- a/README.md
+++ b/README.md
@@ -59,7 +59,7 @@ package manager. The current Golang version being used is stored in `.travis.yml
 
 You'll then need to install the project dependencies. For the webextension, just
 run: `npm install` inside the `webext/` folder. For the CLI client you will first
-need to install `dep`, there is a script for this in `interfacer/contrib/setup_go.sh`.
+need to install `dep`, there is a script for this in `interfacer/contrib/setup_dep.sh`.
 I don't fully understand Golang's best practices, but it seems you are forced to
 keep your Go project's code under `$GOPATH/src`, you might be able to get away
 with symlinks. Anyway, to install the dependencies use: `dep ensure` inside the
@@ -74,6 +74,13 @@ Then the ideal setup for development is:
     webextension everytime webpack rebuilds it: (in `webext/dist`)
     `web-ext run --verbose`
 
+## Building a Browsh release
+If you'd like to build Browsh for a new package manager, or for any other reason,
+you can use the script at `interfacer/contrib/build_browsh.go` as a guide. Note
+you won't be able to build the web extension as Mozilla only allows one canonical
+version of web extensions per version number. So the build script downloads the
+official web extension `.xpi` file from the Mozilla archives.
+    
 ## Tests
 
 For the webextension: in `webext/` folder, `npm test`    
diff --git a/contrib/release_if_new_version.sh b/contrib/release_if_new_version.sh
index cf8d162efcc3c1e3fe14d8057bfb9d266544463a..b4cd5fba99ab5567b5a9a10b1a0a77480cbc8963 100755
--- a/contrib/release_if_new_version.sh
+++ b/contrib/release_if_new_version.sh
@@ -4,7 +4,7 @@ set -e
 
 PROJECT_ROOT=$(git rev-parse --show-toplevel)
 
-browsh_version=$($PROJECT_ROOT/contrib/get_browsh_version.sh)
+browsh_version=$($PROJECT_ROOT/interfacer/contrib/get_browsh_version.sh)
 latest_tagged_version=$(git tag --sort=v:refname --list 'v*.*.*' | tail -n1 | sed -e "s/^v//")
 
 echo "Browsh version: $browsh_version"
diff --git a/interfacer/contrib/build_browsh.sh b/interfacer/contrib/build_browsh.sh
new file mode 100755
index 0000000000000000000000000000000000000000..4cad18647fa09bd890a104fd5ad31b778d25656e
--- /dev/null
+++ b/interfacer/contrib/build_browsh.sh
@@ -0,0 +1,30 @@
+#!/bin/bash
+
+# This is for building a production version of Browsh.
+# To build Browsh during development see:
+#   https://github.com/browsh-org/browsh#contributing
+
+# This script depends on Golang and go-bindata
+# `go get -u gopkg.in/shuLhan/go-bindata.v3/...`
+
+set -e
+
+INTERFACER_ROOT=$(readlink -m "$( cd "$(dirname "$0")" ; pwd -P )"/../)
+
+version_file=$INTERFACER_ROOT/src/browsh/version.go
+line=$(cat $version_file | grep 'browshVersion')
+version=$(echo $line | grep -o '".*"' | sed 's/"//g')
+
+base='https://github.com/browsh-org/browsh/releases/download'
+release_url="$base/v$version/browsh-${version}-an.fx.xpi"
+
+xpi_file=$INTERFACER_ROOT/browsh.xpi
+destination=$INTERFACER_ROOT/src/browsh/webextension.go
+
+curl -L -o $xpi_file $release_url
+
+XPI_FILE=$xpi_file BIN_FILE=$destination \
+  $INTERFACER_ROOT/contrib/xpi2bin.sh
+
+cd $INTERFACER_ROOT
+go build -o browsh src/main.go
diff --git a/contrib/get_browsh_version.sh b/interfacer/contrib/get_browsh_version.sh
similarity index 100%
rename from contrib/get_browsh_version.sh
rename to interfacer/contrib/get_browsh_version.sh
diff --git a/interfacer/contrib/setup_browsh.sh b/interfacer/contrib/setup_browsh.sh
deleted file mode 100755
index 0b98d7e0372116db50692ef4f7e8e7e6b61356d5..0000000000000000000000000000000000000000
--- a/interfacer/contrib/setup_browsh.sh
+++ /dev/null
@@ -1,22 +0,0 @@
-#!/bin/bash
-
-# I suspect this will be mostly used by automated CI.
-# For example; in creating the Browsh Docker image. We don't actually build
-# Browsh in the Dockerfile because that would require signing the webextension
-# again, which can't be done as only one canonical release of a webextension is
-# allowed by MDN per semantic version. It's actually quite good to not have to
-# repeat the build process (having done so in Travis after successfully
-# passing tests). So we simply just download the already built binary.
-
-set -e
-
-# This will typically be run inside Docker where we don't have the original
-# source code.
-line=$(cat $VERSION_FILE | grep 'browshVersion')
-version=$(echo $line | grep -o '".*"' | sed 's/"//g')
-
-base='https://github.com/browsh-org/browsh/releases/download'
-release_url="$base/v$version/browsh_${version}_linux_amd64"
-
-curl -L -o browsh $release_url
-chmod a+x browsh
diff --git a/interfacer/contrib/setup_go.sh b/interfacer/contrib/setup_dep.sh
similarity index 100%
rename from interfacer/contrib/setup_go.sh
rename to interfacer/contrib/setup_dep.sh
diff --git a/interfacer/contrib/xpi2bin.sh b/interfacer/contrib/xpi2bin.sh
new file mode 100755
index 0000000000000000000000000000000000000000..9c7d9e3729f831b3fef4d47a39f6cc0a78217bd9
--- /dev/null
+++ b/interfacer/contrib/xpi2bin.sh
@@ -0,0 +1,15 @@
+#!/bin/bash
+set -e
+
+INTERFACER_ROOT=$(readlink -m "$( cd "$(dirname "$0")" ; pwd -P )"/../)
+
+go-bindata -version
+go-bindata \
+  -nocompress \
+  -prefix $INTERFACER_ROOT \
+  -pkg browsh \
+  -o $BIN_FILE \
+  $XPI_FILE
+
+ls -alh $INTERFACER_ROOT/src/browsh/webextension.go
+echo "go-bindata exited with $(echo $?)"
diff --git a/interfacer/src/browsh/firefox.go b/interfacer/src/browsh/firefox.go
index 607144a5d2c41f79491ffc7345e559f73e890cb7..da6d6c1ee6f5ff20a552f3753a9e1b2743c39df3 100644
--- a/interfacer/src/browsh/firefox.go
+++ b/interfacer/src/browsh/firefox.go
@@ -220,7 +220,7 @@ func firefoxMarionette() {
 // Install the Browsh extension that was bundled with `go-bindata` under
 // `webextension.go`.
 func installWebextension() {
-	data, err := Asset("/webext/dist/web-ext-artifacts/browsh.xpi")
+	data, err := Asset("/browsh.xpi")
 	if err != nil {
 		Shutdown(err)
 	}
diff --git a/interfacer/src/browsh/version.go b/interfacer/src/browsh/version.go
index b650fdeb2a7beaaf19d04d165e2306120d4a2bf8..da8bdc569860507377e1112015c9e9f993e88fc5 100644
--- a/interfacer/src/browsh/version.go
+++ b/interfacer/src/browsh/version.go
@@ -1,3 +1,3 @@
 package browsh
 
-var browshVersion = "1.4.8"
+var browshVersion = "1.4.9"
diff --git a/webext/contrib/bundle_webextension.sh b/webext/contrib/bundle_webextension.sh
index 6221f9e2b1cc1ebb191a8c3da7cfae580196510c..af68d9155f409dfaad9a71f8ff057c3ade2a40a9 100755
--- a/webext/contrib/bundle_webextension.sh
+++ b/webext/contrib/bundle_webextension.sh
@@ -22,7 +22,7 @@ ls -alh .
 $NODE_BIN/web-ext build --overwrite-dest
 ls -alh web-ext-artifacts
 
-version=$($PROJECT_ROOT/contrib/get_browsh_version.sh)
+version=$($PROJECT_ROOT/interfacer/contrib/get_browsh_version.sh)
 
 xpi_file=browsh-$version-an+fx.xpi
 zip_file=browsh-$version.zip
@@ -51,13 +51,5 @@ cp -f $source_file $bundle_file
 
 echo "Bundling $source_file to $destination using internal path $bundle_file"
 
-go-bindata -version
-go-bindata \
-  -nocompress \
-  -prefix $PROJECT_ROOT \
-  -pkg browsh \
-  -o $destination \
-  $bundle_file
-
-ls -alh $PROJECT_ROOT/interfacer/src/browsh/webextension.go
-echo "go-bindata exited with $(echo $?)"
+XPI_FILE=$bundle_file BIN_FILE=$destination \
+  $PROJECT_ROOT/interfacer/contrib/xpi2bin.sh