Written by

on August 25, 2015

Managing my personal server using juju

I have a personal server (actually a digital ocean droplet) that I use to host my private git repositories, bip irc client and blog. Until now this was a manually set up ubuntu instance that I set up to update automatically and would ssh into every once in a while to check the logs and update configurations. In other words, not very optimal.

Since I spend my work hours contributing to juju - a service orchestration tool for the cloud, I decided to try it out managing just a single server running the services I need:

git over ssh

bip irc proxy

serve my static blog

The manual provider

Although juju does not natively support digital ocean as a machine instance provider, there is a plugin that makes it relatively easy to create, manage digital ocean instances and deploy services on them. However, since I was planning to use a single digital ocean droplet to run all my services, I decided to go with the manual provider.

The manual provider allows you to use juju to control a machine instance that was not bootstrapped using juju. Instead of an EC2 instance, this can be your home server, NUC or a manually created digital ocean droplet.

Assuming that you’ve just created your digital ocean droplet using their web console, do start managing that instance with juju, add the following section to your ~/.juju/environments.yaml file:

digitalocean: type: manual bootstrap-host: <DROPLET-IP-ADDRESS> bootstrap-user: root

Once this is done, you can bootstrap the juju state server:

$ juju switch digitalocean $ juju bootstrap

As the bootstrap process completes, you can check the status of your environment:

$ juju status environment: digitalocean machines: "0": agent-state: started agent-version: 1.25-alpha1.1 dns-name: <IP-ADDRESS> instance-id: 'manual:' series: vivid hardware: arch=amd64 cpu-cores=1 mem=489M state-server-member-status: has-vote services: {}

Deploying to lxc

Since juju does not under normal circumstances deploy multiple services to the same server, a way around this is to deploy to lxc containers. This will allow me to run both the juju state server and all the services I need on a single digital ocean droplet, keeping my costs down.

Deploying is simple:

$ juju deploy apache2 --to lxc:0

The --to parameter in this case specifies that the service should be deployed to an lxc container on the macine 0 .

Exposing the containers

Using lxc containers to run services has a serious drawback. Even after exposing the services, they will not be accessible on the machines external network interface. The problem is that you need NAT (network address translation) to map ports on the host to ports on specific lxc containers. One limitation is that you won’t be able to, e.g. run two containers with http servers.

Although there is a juju plugin for handling NAT on digital ocean droplets, it seems to have bitrotted. So for now we’ll ssh into the server and set up port forwarding manually:

$ juju ssh 0 $ sudo iptables -t nat -A PREROUTING -p tcp --dport <HOST-PORT> -j DNAT --to-destination <CONTAINER-IP_ADDRESS>:<CONTAINER-PORT> $ sudo iptables -t nat -A POSTROUTING -j MASQUERADE

Using juju-gui

Although using the juju command to manage the environment is easy, sometimes it is helpful to see your whole deployment in a single image. This is where juju-gui comes into the picture (no pun intended). It is deployed as another charm:

$ juju deploy juju-gui --to lxc:0 $ juju expose juju-gui

Since the gui enables us to do more than just see the whole environment at a glance, exposing it openly is probably not a good idea. We are going to use sshuttle to access juju-gui via the digital ocean server.

sshuttle -r [DROPLET-IP-ADDRESS] 10.0.3.0/24

Assuming that public key authentication with the server is setup, this should just work. 10.0.3.0/24 here is the subnet we want to route. If your lxc machines are assigned to a different address space (as indicated by juju stat ), change the subnet appropriately.