LXD Bootstrap - APT Cache


I’ve recently been struggling getting LXD bootstrapping in a snappy fashion with the times getting slower and slower. So on investigating the cloud-init-output.log of the bootstrapped controller, it spends a LOT of time downloading the sources from apt.

Knowing that I’m pretty much downloading the same thing over and over again, @jameinel suggested using an apt-cache. The following is an outline of doing this using a docker image, so that I don’t have to install anything else on to my host system (assuming you’ve already got docker installed!).

The following runs the apt-cache version 3.1-2 in daemon mode.

docker run --name apt-cacher-ng --init -d --restart=always \
 --publish 3142:3142 \
 --volume /srv/docker/apt-cacher-ng:/var/cache/apt-cacher-ng \

Make sure that’s up and running and that you can then see the home page for apt-cacher

Then to get juju to use the cache, copy the url on the index page of cacher (ips can vary) and keep it written down for later. Then locate your lxc server address from lxc info, generally speaking it’ll be the local url (starts with 192.168,) or your bridge address (starts with 10.), copy that and use it later for the template.

Use the following template of clouds.yaml to update your ~/.local/share/juju/clouds.yaml

    type: lxd
    auth-types: [certificate]
    endpoint: ${URL FROM LXC}
        endpoint: ${URL FROM LXC}
      apt-http-proxy: ${URL FROM APT-CACHER}

Then bootstrap the lxd cloud and enjoy your fruits of your labour.

Bonus Points

You can see how much data you’re saving by viewing the stats on the following page


I’ll mention that if you have a general device on your network, you can also configure:

$ cat /etc/apt/apt.conf.d/80aptproxy
Acquire::http::Proxy "http://${URL FROM APT-CACHER}:3142";
Acquire::https::Proxy "http://${URL FROM APT-CACHER}:3142";

I personally have a NUC sitting on the network and point all my containers and my Linux boxes at that cache. That means that day-to-day updates seed the cache, so everything gets happier.

(edited because I missed the --publish 3142:3142 line which you’re already doing)


Indeed, yeah, totally missed that part.


Using Snapped Docker I had to use a path in my home.

So it becomes:

docker run --name apt-cacher-ng --init -d --restart=always \
 --publish 3142:3142 \
 --volume /home/manadart/srv/docker/apt-cacher-ng:/var/cache/apt-cacher-ng \

I had to create that folder first too.


I think one of the reasons why the apt update part of bootstrap gets slow is that the LXD images get stale. There’s an auto-update setting which can be enabled to ensure the images are kept current. Even with an apt cache, the processing of new packages still can take a bit of time.

You can use lxc image edit juju/bionic/amd64 (and same for trusty, xenial, zestry etc) to set the auto-update property of the images Juju uses to true.

I’m not sure why Juju doesn’t ensure this is set true by default. Perhaps we should change that?


I’m pretty sure we do set it to true. We wrote the code to do so, if it isn’t, then it should be considered a bug that we fix.


I’ve written up my approach and code in my juju-lxd-tweaks repo.

It effectively does an auto-cache of the LXD image used by Juju, but it also installs the binary agent for the installed version of Juju and installs dependencies for the charm reactive framework.