Setup Juju on local LXD

Juju allows deploying charm/bundles on different clouds, including public clouds like AWS, Azure, Google or on the local host.

We explain here how to install Juju and then to use it for deploying applications on LXD containers the local host.

Install the software

We assume you have a VM running Ubuntu Xenial (16.04), where to install the Juju controller. Follow the steps in the Quick Start Guide on VM if you don’t have one.

For installing Juju on a different platform, see the Getting Started with Juju.

Login to your node and do the following.

Install Juju and ZFS (a highly efficient and feature-rich filesystem and logical volume manager) by doing this:

$ sudo add-apt-repository -u ppa:juju/stable
$ sudo apt-get update
$ sudo apt install juju zfsutils-linux

Create an LXD container

In order to isolate the Juju controller from other services on your VM, we suggest to install it on a separate LXD container.

Ensure you are member of the lxd group:

$ newgrp lxd

Initialize LXD containers:

$ sudo lxd init

You will be asked a few questions, for which you should accept the default answer by pressing ENTER except for the size of the loop device:

Name of the storage backend to use (dir or zfs) [default=zfs]:
Create a new ZFS pool (yes/no) [default=yes]?
Name of the new ZFS pool [default=lxd]:
Would you like to use an existing block device (yes/no) [default=no]?
Size in GB of the new loop device (1GB minimum) [default=10GB]: 20
Would you like LXD to be available over the network (yes/no) [default=no]?

The bridge network will then be configured via a second round of questions. Except in the case where the randomly chosen subnet may conflict with an existing one in your local environment, it is fine to accept all the default answers. IPv6 networking (the last question) is not required for Juju.

LXD is now configured to work with Juju.


LXD adds iptables (firewall) rules to allow traffic to the subnet/bridge it created. If you subsequently add/change firewall settings (e.g. with ufw), ensure that such changes have not interfered with Juju’s ability to communicate with LXD.

On Xenial you will need to do this for networking communications to work properly within containers:

$ sudo iptables -I FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu

Create a controller

Before you can start deploying applications, Juju needs to bootstrap a controller for the LXD configuration we created. The controller manages both the environment and the models you create to host the applications.

The juju bootstrap command is used to create the controller. The command expects a name (for referencing this controller) and a cloud to use. The LXD ‘cloud’ is known as ‘localhost’ to Juju.

For our LXD localhost cloud, we will create a controller called ‘lxd-local’:

$ juju bootstrap localhost lxd-local

This may take a few minutes as LXD must download an image for Xenial. A cache will be used for subsequent containers.

Once the process has completed you can check that the controller has been created:

$ juju controllers

This will return a list of the controllers known to Juju, which at the moment is the one we just created:

Use --refresh flag with this command to see the latest information.

Controller  Model    User   Access     Cloud/Region         Models  Machines    HA  Version
lxd-local*  default  admin  superuser  localhost/localhost       2         1  none  2.0.2

A newly-created controller has two models: The ‘controller’ model, which should be used only by Juju for internal management, and a ‘default’ model, which is ready for actual use.

The following command shows the currently active controller, model, and user:

$ juju whoami

In our example, the output should look like this:

Controller:  lxd-local
Model:       default
User:        admin

Deploy applications

Juju is now ready to deploy applications from among the hundreds included in the Juju charm store.

Testing the model

It is a good idea to test your new model. Let’s deploy a MediaWiki site:

$ juju deploy cs:bundle/mediawiki-single

This will fetch a ‘bundle’ from the Juju store. A bundle is a pre-packaged set of applications, in this case ‘MediaWiki’, and a database to run it with. Juju will install both applications and add a relation between them - this is part of the magic of Juju: it isn’t just about deploying software, Juju also knows how to connect it all together.

Installing shouldn’t take long. You can check on how far Juju has got by running the command:

$ juju status

When the applications have been installed, the output of the above command will look something like this:

$ juju status
Model    Controller  Cloud/Region         Version
default  lxd-local    localhost/localhost  2.0.2

App        Version  Status   Scale  Charm      Store       Rev  OS      Notes
mediawiki           unknown      1  mediawiki  jujucharms    3  ubuntu
mysql               unknown      1  mysql      jujucharms   29  ubuntu

Unit          Workload  Agent  Machine  Public address  Ports  Message
mediawiki/0*  unknown   idle   0   80/tcp
mysql/0*      unknown   idle   1

Machine  State    DNS            Inst id        Series  AZ
0        started  juju-9fb5d2-0  trusty
1        started  juju-9fb5d2-1  trusty

Relation  Provides   Consumes  Type
db        mediawiki  mysql     regular
cluster   mysql      mysql     peer

From the status output, we can see that the IP address for the MediaWiki site we have created is Open a browser and enter that address to see the site.


Note: To remove all the applications in the model you just created, it is often quickest to destroy the model with the command juju destroy-model default and then create a new model, by doing juju add-model default.