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!

1 Like

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:

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

@ijohnson
Can I use this extent this to include core20, and use ubuntu:20.04 as the base too ?

@jamesh
We are building behind a proxy, the stock LXD images are no good to us, as they try and apt-get from places that are restricted.
Is there any way of leveraging LXD for building behind a proxy that doesn’t require making our own LXD images ?

Cheers,
Just

yes this should work fine

Just testing it now - will have to include grabbing the extra core20 base too :slight_smile:

I will report back.

Cheers, Just

I’m curious @ijohnson , why is this magic header required X-Ubuntu-Series: 16 ?
18 or 20 don’t seem to work.

Cheers,
Just

1 Like

That was before we knew we would be able to keep the same device series format for ubuntu core 18 and we wanted to make sure we could break the world for ubuntu core 18/18.04 if needed but we ended up not needing to :slight_smile:

Edit: To be clear that should always be 16 nowadays

1 Like

Makes sense :slight_smile:

Anyway, tested with a base of ubuntu:focal , and including the core20 base. Works great.

This has save me a lot of pain/time actually - so thanks a lot !

Cheers, Just

1 Like

I know Snapcraft will pass through the http_proxy and https_proxy environment variables to the build inside the LXD container. Snap builds on Launchpad rely on a proxy for Internet access, so this is fairly well tested.

If the problem is LXD’s attempts to download images, you might have luck calling systemctl set-environment https_proxy=... before installing the LXD snap in your VM.

I didn’t spend long on it, but the problem seemed to be the apt-get the images did initially. apt does not respect the http_proxy environment variable, you have to set it directly in apt config.

Anyhow, thanks for the response but it’s largely academic now as I have the snapcore Docker files working, and that approach fits in much better with our CI environment generally. Also, if I can use the supported CI runners at this end I don’t have to worry about the proxy.

Thanks all.

Cheers,
Just

1 Like

FWIW, if anyone stumbles on this:

Snapcraft now supports --add-ca-certificates <certificate-path> to support installing new certs into the constructed environment.