How to Build a Snap Behind a Proxy With SSL Bump In a Vagrant VM

Hey everybody!

I just had the need to build a snap behind an HTTP proxy with SSL Bump in a Vagrant VM that can’t use multipass ( because it doesn’t support the multipass virtualization inside the VM ). I figured out how to do it so I figured I’d post the instructions here in case anybody ever needed to do the same thing!

So the first issue I ran into in the Vagrant VM ( Ubuntu 18.04 ) was that I couldn’t use Multipass. If I remember correctly it was because it needed KVM virtualization and I didn’t have it in my VM. The solution ( or, more accurately, a solution ) is to use Docker. So the first step is to install Docker:

# Using apt
$ sudo apt install docker.io
# Or using Snap
$ sudo snap install docker

After you install Docker you will need to configure Docker for your proxy. You do this by creating a systemd service dropin file that looks like this:

http-proxy.conf:

[Service]
Environment="HTTP_PROXY=http://name:password@123.456.789.100:1234"
Environment="HTTPS_PROXY=http://name:password@123.456.789.100:1234"

This config file must be placed in:

  • For the snap: /etc/systemd/system/snap.docker.dockerd.service.d/http-proxy.conf
  • Or for the apt package: /etc/systemd/system/docker.service.d/http-proxy.conf

After that reload the systemd configuration and restart Docker:

  • For the snap:
    • systemctl daemon-reload
    • snap restart docker
  • Or for the apt package:
    • systemctl daemon-reload
    • systemctl restart docker

Now that we have Docker installed we are going to run the snapcraft container and mount our project and our proxy’s SSL bump certificate into the container:

$ cd /path/to/my/snap/project
$ docker run -it --rm -v $(pwd):/project -v /path/to/proxy/cert.crt:/usr/local/share/ca-certificates/proxyca.crt snapcore/snapcraft bash
# Now we are inside of the snapcraft container

OK, now that we are inside of the snapcraft container, we could build our snap except for the fact that snapcraft does not trust our HTTP proxy’s certificate. We have to hijack the cacert.pem files that snapcraft will use to verify sites that it connects to:

# Replace all `cacert.pem` files in the snapcraft snap with our proxy cert file
# that we mounted in.
$ for cert in $(find /snap/snapcraft/current/ -name cacert.pem); do cp /usr/local/share/ca-certificates/proxyca.crt $cert; done
# Switch to our snap project dir
$ cd /project
# Build the snap
$ snapcraft
# Exit the container
$ exit

Now you should have yoursnapname_version_arch.snap in your project directory. You can install the snap like so:

$ snap install ./yoursnapname_version_arch.snap --dangerous --devmode

Congratulations! :tada: You’re snapped!

Thanks for the write up!

Out of curiosity, did you try using LXD instead of multipass? Or building directly on host (ie the VM)? Maybe you couldn’t use the host because your base is different that the VM?

1 Like

I tried LXD once, but I can’t remember why it didn’t work. It may have been because of the need to setup the trust for the CA cert. Doing snapcraft build --use-lxd probably wouldn’t allow me to hack in the extra certificates like I could when using the Docker container.

Edit: Maybe the --shell option to snapcraft build would allow for adding the certificate, actually. :man_shrugging: I just have a lot of experience with Docker so this was the first solution I was able to get to work. :slight_smile:

I didn’t even know that was possible. All of the examples I’ve seen so far needed either multipass, Docker, or LXD.

1 Like

You may have trouble using the snapcore/snapcraft docker image if you’re building snaps targeting the core18 base snap. If you want something a bit more future proof, it’s probably better to look at one of:

  1. ensure the VM matches the base your snap is using (i.e. Ubuntu 16.04 if you’re using core, or 18.04 if you’re using core18), then run snapcraft --destructive-mode. If the VM will be discarded after the build, then it doesn’t matter that this could install packages on the host VM.

  2. install LXD in the VM and use snapcraft --use-lxd.

(1) would make it trivial to inject your proxy settings and private CA certificate. I doubt it would happen for the container in (2), but it seems like a reasonable feature request. It seems like it would be desirable for both LXD and Multipass backends.

1 Like

Could that be solved simply by changing the base image of the docker container to ubuntu:18.04?

I opened a feature request:

https://bugs.launchpad.net/snapcraft/+bug/1859046

Yes, that’s the recommended way to build snaps based on core18 in docker. See https://snapcraft.io/docs/t/creating-docker-images-for-snapcraft/11739

1 Like

There’s still classes of snaps that you simply can’t build in a Docker image. Anything that uses build-snaps (or use a plugin that relies on build-snaps) will fail to build.

The Docker containers are great if your infrastructure is built around that system (e.g. Gitlab CI) and your project doesn’t use build-snaps. But if you’ve got the choice, LXD or destructive-mode on a clean VM are going to be more versatile.

2 Likes