Automating LXC container creation with Ansible

LXC is a Linux container technology that I use for both development and production setups hosted on Debian.

This type of container acts a lot like a lightweight virtual machine, and can be administered with standard linux tools. When configured over SSH, you should be able to use the same scripts against either an LXC container or VM without noticing the difference.

This setup will provision “privileged” containers behind a NAT, which is a setup that is most useful for a developer workstation. A setup in a server rack would be more likely to use “unprivileged” containers on a host bridge, which is slightly more complex to set up. The good news is that the guest container will behave very similarly once it’s provisioned, so developers shouldn’t need to adapt their code to those details either.

Manual setup of an LXC container

You need to know how to do something manually before you can automate it.

The best reference guide for this is the current Debian documentation. This is a shorter version of those instructions, with only the parts we need.


Everything you need for LXC is in the lxc Debian package:

$ sudo apt-get install lxc
The following additional packages will be installed:
  bridge-utils debootstrap liblxc1 libpam-cgfs lxcfs python3-lxc uidmap
Suggested packages:
  btrfs-progs lvm2
The following NEW packages will be installed:
  bridge-utils debootstrap liblxc1 libpam-cgfs lxc lxcfs python3-lxc uidmap
0 upgraded, 8 newly installed, 0 to remove and 0 not upgraded.
Need to get 1,367 kB of archives.
After this operation, 3,762 kB of additional disk space will be used.
Do you want to continue? [Y/n] y


Enable the LXC bridge, and start it up:

echo 'USE_LXC_BRIDGE="true"' | sudo tee -a /etc/default/lxc-net
$ sudo systemctl start lxc-net

This gives you an internal network for your containers to connect to. From there, they can connect out to the Internet, or communicate with each-other:

$ ip addr show
3: lxcbr0:  mtu 1500 qdisc noqueue state DOWN group default qlen 1000
    link/ether 00:16:3e:00:00:00 brd ff:ff:ff:ff:ff:ff
    inet scope global lxcbr0
       valid_lft forever preferred_lft forever


Instruct LXC to attach a NIC to this network each time you make a containers:

$ sudo vi /etc/lxc/default.conf

Replace that file with: = veth = lxcbr0 = up = 00:16:3e:xx:xx:xx

You can then create a ‘test1’ box, using the Debian image online. Note the output here indicates that the container has no SSH server or root password.

$ sudo lxc-create --name test1 --template=download -- --dist=debian --release=stretch --arch=amd64
Setting up the GPG keyring
Downloading the image index
Downloading the rootfs
Downloading the metadata
The image cache is now ready
Unpacking the rootfs

You just created a Debian container (release=stretch, arch=amd64, variant=default)

To enable sshd, run: apt-get install openssh-server

For security reason, container images ship without user accounts
and without a root password.

Use lxc-attach or chroot directly into the rootfs to set a root password
or create user accounts.

The container is created in a stopped state. Start it up now:

$ sudo lxc-start --name test1 

It now appears with an automatically assigned IP.

$ sudo lxc-ls --fancy
test1 RUNNING 0         - -    

Set up login access

Start by getting your SSH public key ready. You can locate at ~/.ssh/ You can use ssh-keygen to create this if it doesn’t exist.

To SSH in, you need to install an SSH server, and get this public key into the /root/authorized_keys file in the container.

$ sudo lxc-attach --name test1
root@test1:/# apt-get update
root@test1:/# apt-get -y install openssh-server
root@test1:/# mkdir -p ~/.ssh
root@test1:/# echo "ssh-rsa (public key) user@host" >> ~/.ssh/authorized_keys

Type exit or press Ctrl+D to quit, and try to log in from your regular account over SSH:

$ ssh root@
The authenticity of host ' (' can't be established.
ECDSA key fingerprint is SHA256:EWH1zUW4BEZUzfkrFL1K+24gTzpd8q8JRVc5grKaZfg.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '' (ECDSA) to the list of known hosts.
Linux test1 4.14.0-3-amd64 #1 SMP Debian 4.14.13-1 (2018-01-14) x86_64

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.

Any you’re in. You may be surprised how minimal the LXC images are by default, but the full power of Debian is available from apt-get.

This container is not configured to start on boot. For that, you would add this line to /var/lib/lxc/test1/config: = 1


To stop the test1 container and then delete it permanently, run:

sudo lxc-stop --name test1
sudo lxc-destroy --name test1

Automated setup of LXC containers with Ansible

Now that the basic steps have been done manually, I’ll show you how to Ansible to create a set of LXC containers. If you haven’t used it before, Ansible is an automation tool for managing computers. At its heart, it just logs into machines and runs things. These scripts are an approximate automation of the steps above, so that you can create 10 or 100 containers at once if you need to.

I use this method on a small project that I maintain on GitHub called ansible-live, which bootstraps a containerized training environment for Ansible.

Host setup

You need a few packages and config files on the host. In addition to the lxc package, we need lxc-dev and the lxc-python2 python package to manage the containers from Ansible:

- hosts: localhost
  connection: local
  become: true
  - interface: lxcbr0

  - name: apt lxc packages are installed on host
    apt: name={{ item }}
    - lxc
    - lxc-dev
    - python-pip

  - copy:
      dest: /etc/default/lxc-net
      content: |

  - copy:
      dest: /etc/lxc/default.conf
      content: | = veth = {{ interface }} = up = 00:16:3e:xx:xx:xx

  - service:
      name: lxc-net
      state: started

  - name: pip lxc packages are installed on host
      name: "{{ item }}"
    - lxc-python2
    run_once: true

This can be executed with this command:

ansible-playbook setup.yml --ask-become-pass --diff

Container creation

Add a file called inventory to specify the containers to use. These are two IP addresses in the range of the LXC network.

deb1 ansible_host=
deb2 ansible_host=

For local work, I find it easier to set an IP address with Ansible and use the /etc/hosts file, which is why IP addresses are included here. Without it, you need to wait for each container to boot, then detect its IP address before you can log in.

Add this to setup.yml

- hosts: all
  connection: local
  become: true
  - interface: lxcbr0
  - name: Load in local SSH key path
      my_ssh_key: "{{ lookup('env','HOME') }}/.ssh/"

  - name: interface device exists
    command: ip addr show {{ interface }}
    changed_when: false
    run_once: true

  - name: Local user has an SSH key
    command: stat {{ my_ssh_key }}
    changed_when: false
    run_once: true

  - name: containers exist and have local SSH key
    delegate_to: localhost
      name: "{{ inventory_hostname }}"
      container_log: true
      template: debian
      state: started
      template_options: --release stretch
        - " = veth"
        - " = up"
        - " = {{ interface }}"
        - " = {{ ansible_host }}/24"
        - " = auto"
      container_command: |
        if [ ! -d ~/.ssh ]; then
          mkdir ~/.ssh
          echo "{{ lookup('file', my_ssh_key) }}" | tee -a ~/.ssh/authorized_keys
          sed -i 's/dhcp/manual/' /etc/network/interfaces && systemctl restart network

In the next block of setup.yml, use keyscan to get the SSH keys of each machine as it becomes available.

- hosts: all
  connection: local
  become: false
  serial: 1
  - wait_for: host={{ ansible_host }} port=22

  - name: container key is up-to-date locally
    shell: ssh-keygen -R {{ ansible_host }}; (ssh-keyscan {{ ansible_host }} >> ~/.ssh/known_hosts)

Lastly, jump in via SSH and install python. This is required for any follow-up configuration that uses Ansible.

- hosts: all
  gather_facts: no
  - ansible_user: root
  - name: install python on target machines
    raw: which python || (apt-get -y update && apt-get install -y python)

Next, you can execute the whole script to create the two containers.

ansible-playbook setup.yml --ask-become-pass --diff

Scaling to hundreds of containers

Now that you have created two containers, it is easy enough to see how you would make 20 containers by adding a new inventory:

for i in {1..20}; do echo deb$(printf "%03d" $i) ansible_host=10.0.3.$((i+1)); done | tee inventory ansible_host= ansible_host= ansible_host=

And then run the script again:

ansible-playbook -i inventory setup.yml --ask-become-pass

This produces 20 machines after a few minutes.

The processes running during this setup were mostly rync (copying the container contents), plus the network waiting to retrieve python many times. If you need to optimise to frequent container spin-ups, LXC supports
storage back-ends that have copy-on-write, and you can cache package installs with a local webserver, or build some packages into the template.

Running these 20 containers plus a Debian desktop, I found that my computer was using just 2.9GB of RAM, so I figured I would test 200 empty containers at once.

for i in {1..200}; do echo deb$(printf "%03d" $i) ansible_host=10.0.3.$((i+1)); done > inventory
ansible -i inventory setup.yml

It took truly a very long time to add Python to each install, but the result is as you would expect:

$ sudo lxc-ls --fancy
NAME               STATE   AUTOSTART GROUPS IPV4       IPV6 RUNNING 0         -   - RUNNING 0         -   - RUNNING 0         -   -    
... RUNNING 0         - - RUNNING 0         - - RUNNING 0         - -    

The base resource usage of an idle container is absolutely tiny, around 13 megabytes — the system moved from 2.9GB to 5.4GB of RAM used when I added 180 containers. Containers clearly have a lower overhead than VM’s, since no RAM has been reserved here.

Software updates

The containers are updated just like regular VM’s-

apt-get update
apt-get dist-upgrade


In this setup, the container’s contents is stored under /var/lib/lxc/. As long as the container is stopped, you get at it safely with tar or rsync to make a full copy:

$ sudo tar -czf deb001.20180209.tar.gz /var/lib/lxc/
$ rsync -avz /var/lib/lxc/

Full-machine snapshots are also available on the Ceph or LVM back-ends, if you use those.


The same Ansible module can be used to delete all of these machines in a few seconds.

- hosts: all
  connection: local
  become: true
  - name: Containers do not exist
    delegate_to: localhost
      name: "{{ inventory_hostname }}"
      state: absent
ansible-playbook -i inventory teardown.yml --ask-become-pass


Hopefully this post has given you some insight into one way that Linux containers can be used. I have found LXC to be a great technology to work with for standalone setups, and regularly use the same scripts to configure either an LXC container or a VM’s depending on the target environment.

The low resource usage also means that I can run fairly complex setups on a laptop, where the overhead of large VM’s would be prohibitive.

I don’t think that LXC is directly comparable to full container ecosystems like Docker, since they are geared towards different use cases. These are both useful tools to know, and have complementary strengths.

Using custom fonts to add new glyphs to an Epson printer

I develop a printer driver for ESC/POS receipt printers, and we regularly get feature requests for encoding text in the Chinese, Japanese and Korean languages (“CJK”).

I have recently been looking for a way to add support for these on receipt printers that have no native ability to render them, and thought I would write a bit about some progress so far.

I previously wrote a bit about printing individual bitmaps for each character, where here I am aiming to print entire scripts.


Programmers usually deal with text in UTF-8, but receipt printers don’t. Instead, they still use a series of legacy code pages to represent non-ASCII text. Mapping arbitrary text to something understood by these printers is a huge challenge.

The escpos-php driver will automatically map a lot of western scripts to these code pages. However, if you attempt to send an example string like “日本語” to escpos-php currently, the driver will substitute it with “???”, since it doesn’t know how to convert them to ESC/POS.

On some printers, there are native commands to print Japanese, but for a driver project, we need something with broad compatibility. So, I decided to try to get this working on an Epson TM-T20 variant which has no CJK fonts.

I started by making a new standalone test script, which converts text input into ESC/POS using a cut-down version of the escpos-php printer driver.

$text = file_get_contents("php://stdin");
$connector = new FilePrintConnector("php://stdout");
$printer = new Printer($connector);
$printer -> text($text);
$printer -> cut();
$printer -> close();

I then modified this to print arbitrary UTF-8 text with a local bitmap font. These next sections go through some of the things I had to write to get it all working.

Character representation

I decided to start with the GNU Unifont project, because it ships fixed-width binary fonts in a text format that can be parsed without a font library, is freely licensed, and has excellent coverage.

So the first issue to solve was to do with font sizes:

  • Unifont contains characters that are 8 or 16 pixels wide, that cover the entire Unicode Basic Multilingual Plane (BMP), at 16 characters tall.
  • ESC/POS supports a fixed 12×24 or a smaller 9×17 font.
  • ESC/POS fonts are submitted in a 24 pixel tall format regardless of print area.

Since the characters would be surrounded by too much whitespace in the “Font A” (12×24) representation, I settled on printing in “Font B” (9×17), leaving a one-pixel space underneath, and to the right of each character. These pictures show how the glpyhs (grey) are laid out in the available print area (unused print area in white), in the available memory (unused memory in red).

Note that wider characters have a two-pixel dead-zone on the right. The non-printable 7 pixels at the bottom of the images are ignored by the printer.

The format on the printer for each character stores bits in a column-major format, while most raster formats are row-major, so I wrote a quick converter to rotate the bits. The converter code is not very concise, so I’ll just share a screen capture here. The full code is linked at the end of this post.

Lastly, the output size on paper was tiny, so I set the printer to double the size, which results in text that is around 50% larger than the default output.

Storage of fonts

There is only space for 95 single-width characters in an ESC/POS font, but the scripts are much larger than this.

I treated the font as a queue in this implementation. During the print-out, new characters are added to the font as necessary, and the font is re-written from the front as space runs out. This is also known as a FIFO cache eviction policy.


I converted the string input to an array of Unicode code points to avoid canonicalisaton issues.

$chrArray = preg_split('//u', $text, -1, PREG_SPLIT_NO_EMPTY);
$codePoints = array_map("IntlChar::ord", $chrArray);
foreach($codePoints as $char) {
  $this -> writeChar($char);

The IntlChar class is provided by an extension which is very useful but not widespread, which limits the portability of this code.


I got the list of languages from the sidebar of a Wikipedia article to use as a test string, since it contains short strings in a large number of scripts.

cat test.txt | php unifont-example.php > /dev/usb/lp0

The output contains a large number of correctly rendered scripts, including the CJK output, which was not previously possible on my printer.



Previously, I have tried generating small images from system fonts to send text to the printer. This is quite costly in terms of processing and data transfer, and the printer is unable to format or wrap the text for you.

Storing glyphs in the custom font area involves transferring less raster data, and allows most text formatting commands to be used.


These characters are a different size to the native printer fonts, so we can’t mix them on the same line. This means that we can’t use this code to implement an automatic fallback in escpos-php. However, it may appear in a future version as an alternative “PrintBuffer”, which can be explicitly enabled by developers who are not interested in using the native fonts.

The esc2html utility is not able to emulate custom fonts, so the output cannot currently be rendered without an Epson printer.

Also, we simply printed a stream of characters, which is not really how text works. To implement Unicode, we need to be able to join and compose characters, and respect bi-directional text. Unicode text layout is not trivial at all.

Get the code

The full script is available in the escpos-snippets repo on GitHub, where I store prototypes of new functionality that is not yet ready for prime-time.

On running deployments via GitHub

TL;DR; – GitHub can be pretty unreliable, depend on it at your peril.

GitHub was down for about 20 minutes today. I happened to be logged in so I’ll share a few screen captures.

The status page and twitter showed no activity for the first nine minutes of the outage, but were then updated with erroneous information.

Meanwhile, the website started displaying unicorns.

If you are logged into GitHub regularly, you might know that this is not a rare event. I don’t have any data on how often GitHub is actually broken, but based on that status page, I’m not sure that know either.

Why I don’t deploy via GitHub

Around May 2013, a website that I maintained started rendering incorrectly because of a bug in my code: I had made some MySQL fields TEXT type, which have a limited size, and part of the application had exceeded the limit, resulting in truncated pages.

This app is written in PHP, and my deployment workflow at the time involved pushing up a change to GitHub, then then triggering a git pull on the server, which ran an update script to bring everything up to speed.

In this case, I was on mobile internet, so I diagnosed the problem and prepared a hotfix on my laptop. When I tried to push it to GitHub, it was offline. I ended up logging in and running a few ALTER TABLE statements over SSH, which is a long shot from the robust deployment pipeline I had envisaged.

There are some emerging SaaS products that offer to deploy directly from GitHub. For example, I use Travis CI extensively for open source, and you can hook it up with deployment keys.

This stuff seems really cool, but I imagine that an error message containing rainbow unicorns would not be very funny if you wanted to fix something in a hurry. This particular app is still deployed with a git pull, but I’ve started to avoid mixing deployment with version control, so that I can run a build and deploy anywhere in case of emergency.

How to set up Docker containers in Travis CI

This post outlines a method for using Docker for testing on Travis CI. It may be useful to you if you are a web application developer who uses GitHub.

I use this setup in my web-based word puzzle generator, so that every change is spun up and tested with a web browser before it is merged.

I got the idea for writing this from a few lines in the docker-compose documentation, which suggested that Docker is an easy way to perform automated testing over a running application:

$ docker-compose up -d
$ ./run_tests
$ docker-compose down

This snippet was missing some setup and an example app, but these three lines do all the heavy lifting.

The Docker setup

In order to focus on the Docker setup, I made a server which simply responds to TCP requests on port 5000 with the text “Hello World”.

This file is called, and sits in a directory called foo_server:

while true; do
  # Send 'Hello World' to anybody who connects on port 5000
  echo "Hello World" | nc -l 5000

Alongside it, I added a Dockerfile to instruct docker to execute this tiny ‘application’ in a container, after installing the dependencies. This machine is built from the Docker-official Debian image:

FROM debian
ADD . /usr/share/test-server
WORKDIR /usr/share/test-server
RUN apt-get update && apt-get install --assume-yes netcat-openbsd
CMD ./

Lastly, a .dockerignore file is used to avoid loading the Dockerfile to the container:

# Ignore docker files

In the directory above, a simple test script, is used to see that the server is returning the expected output:

set -e
expected="Hello World"
actual=`nc -v localhost 5000`
echo "Expecting: $expected"
echo "Server says: $actual"
if [ "$expected" != "$actual" ]; then
  echo "Test failed"
  exit 1
  echo "Test passed"
  exit 0

Alongside the test file, a file called docker-compose.yml instructs Docker to create a container out of the foo_server example, and forward port to it.

version: '2'
    build: foo_server
     - "5000:5000"
    container_name: foo_1

To try it out for yourself, you need a relatively recent version of Docker and docker-compose. The versions provided in Debian were not new enough to execute the examples, but the Docker project provides repos containing newer builds for Debian & Ubuntu. For my distro, the install was:

curl -sSL "" | sudo -E apt-key add -
echo "deb debian-stretch main" | sudo tee -a /etc/apt/sources.list
sudo apt-get update
sudo apt-get install docker-engine
sudo pip install docker-compose

The versions this got me were docker 1.11.2, and docker-compose 1.7.1. Straight after the install, I could deploy & test an example locally:

$ docker-compose up --build -d
$ ./
$ docker-compose down

The CI setup

I’ll assume that if you’re reading this, you are familiar with the basics of Travis CI. The large block of code below is the .travis.yml file to set up the test machine, then execute the tests against a container.

# Use Ubuntu 'trusty' distribution
sudo: required
dist: trusty

  # Update docker-engine using Ubuntu 'trusty' apt repo
  - >
    curl -sSL "" |
     sudo -E apt-key add -
  - >
    echo "deb ubuntu-trusty main" |
     sudo tee -a /etc/apt/sources.list
  - sudo apt-get update
  - >
    sudo apt-get -o Dpkg::Options::="--force-confdef" \
     -o Dpkg::Options::="--force-confold" --assume-yes install docker-engine
  - docker version
  # Update docker-compose via pip
  - sudo pip install docker-compose
  - docker-compose version

  - docker-compose up --build -d

  - ./

  - docker-compose down

Note: This uses Travis CI’s trusty distribution, which at the time of writing is the newest stable build platform available on Travis CI. This shipped an outdated version of Docker, which had to be installed over. Because the existing Docker was configured, I had to override a debconf prompt, which is why the apt addon syntax was not used to set up dependencies.


The build result for each commit is displayed in Travis CI:


Under this, the output of the passing test script is shown, showing what has been set up:


Using this setup in practice

Moving this from a demo setup to a real setup would be fairly simple:

  1. Replace the installation with a real software stack
  2. Replace the server run with a command to serve the application (such as a Apache HTTP, Tomcat or Node)
  3. Replace the tests with real tests (such as Cucumber or Selenium).

The example in the pre-amble installs a LAMP stack and tests it with Selenium in its CI build.

If your application is a bit larger, your only extra complexity will come from running multiple containers with docker-compose.

Get the code

All of these scripts in a working CI example are available on GitHub:

How to compile a C++11 app on Travis CI

I have recently been adding Travis CI builds to code that I host on GitHub, so that I don’t need to host my own build infrastructure.

To users, this just means that there is a green badge at the top of the README, but not much else:


To build a simple C++ project, I added in this .travis.yml file:

langauge: cpp
sudo: false

      - libusb-1.0-0-dev

  - make

Unfortunately, on this infrastructure, the default build tools are currently ancient, and installed on Ubuntu Precise (12.04):

$ make
g++ src/missile.cpp examples/basic-sync/basic-sync.cpp -o bin/basic-sync -lpthread -lusb-1.0 -std=c++11 -Wall
cc1plus: error: unrecognized command line option ‘-std=c++11’
cc1plus: error: unrecognized command line option ‘-std=c++11’

Option 1: Update the toolchain

There is some structures you can use to install an extra repository and some named packages, instead of using apt-get directly.

langauge: cpp
sudo: false

    - ubuntu-toolchain-r-test
    - gcc-4.8
    - g++-4.8
    - libusb-1.0-0-dev

  - make

Because the old version was still installed, I had to refer to the exact version in the Makefile, as in:

g++-4.8 src/missile.cpp examples/basic-sync/basic-sync.cpp -o bin/basic-sync -lpthread -lusb-1.0 -std=c++11 -Wall

Option 2: Update the platform

You can also change to a more recent Ubuntu distribution. Presumably Ubuntu Precise is only the default because existing builds use it.

If you need to build C++11 apps on Travis CI, then builds will work under Ubuntu Trusty (14.04), which happens to be the newest distribution currently available:

langauge: cpp
sudo: required
dist: trusty

      - libusb-1.0-0-dev

  - make

How to edit emulator flags in Android Studio

I’ve recently updated to the new IntelliJ-based Android studio 2.1.

I ran into some issues attempting to launch a “hello world” project in the emulator, which I’m writing up here for the benefit of others.

For context, I run Debian GNU/Linux Jessie on an AMD64 box, with Radeon graphics card, using the free drivers.

The OpenGL error


When attempting to launch a simple project with the emulator, the emulator died with the following message:

Cannot launch AVD in emulator.
libGL error: unable to load driver:
libGL error: driver pointer missing
libGL error: failed to load driver: radeonsi
libGL error: unable to load driver:
libGL error: failed to load driver: swrast
X Error of failed request:  GLXBadContext
  Major opcode of failed request:  155 (GLX)
  Minor opcode of failed request:  6 (X_GLXIsDirect)
  Serial number of failed request:  49
  Current serial number in output stream:  48
libGL error: unable to load driver:
libGL error: driver pointer missing
libGL error: failed to load driver: radeonsi
libGL error: unable to load driver:
libGL error: failed to load driver: swrast
X Error of failed request:  GLXBadContext
  Major opcode of failed request:  155 (GLX)
  Minor opcode of failed request:  6 (X_GLXIsDirect)
  Serial number of failed request:  49
  Current serial number in output stream:  48
libGL error: unable to load driver:
libGL error: driver pointer missing
libGL error: failed to load driver: radeonsi
libGL error: unable to load driver:
libGL error: failed to load driver: swrast
X Error of failed request:  BadValue (integer parameter out of range for operation)
  Major opcode of failed request:  155 (GLX)
  Minor opcode of failed request:  24 (X_GLXCreateNewContext)
  Value in failed request:  0x0
  Serial number of failed request:  33
emulator: WARNING: VM heap size set below hardware specified minimum of 228MB
emulator: WARNING: Setting VM heap size to 384MB
  Current serial number in output stream:  34
QObject::~QObject: Timers cannot be stopped from another thread

The console logs that the command being executed is:

/home/mike/Android/Sdk/tools/emulator -netdelay none -netspeed full -avd Nexus_5X_API_23

Fixing on the command-line

Quick list of things that didn’t work:

  • Installing more libraries via apt-get
    apt-get install libstdc++6 xserver-xorg-video-radeon
  • Pre-loading libraries
    LD_PRELOAD='/usr/lib64/' /home/mike/Android/Sdk/tools/emulator -netdelay none -netspeed full -avd Nexus_5X_API_23
  • Attempting to understand LibGL’s debug output
    LIBGL_DEBUG=verbose /home/mike/Android/Sdk/tools/emulator -netdelay none -netspeed full -avd Nexus_5X_API_23

But the solution turned out to be this very specific flag:

$ ./emulator -help | grep libstdc++
    -use-system-libs               Use system libstdc++ instead of bundled one

So launching the emulator from the CLI worked for me, using this command:

/home/mike/Android/Sdk/tools/emulator -netdelay none -netspeed full -avd Nexus_5X_API_23

Fixing in the IDE

So this was fantastic progress, but without being able to launch this emulator from Android Studio, the development environment wasn’t really integrated yet.

Apparently there used to be a feature for adding command-line flags to the emulator, but this is now gone.

So, adapting a post here, I jumped in and replaced the emulator binary into a wrapper to inject some flags.

 $ cd ~/Android/Sdk/tools/
$ mv emulator emulator.0
$ touch emulator
$ chmod +x emulator

I then opened up the emulator in a text editor and punched in this:

set -ex
$0.0 $@ -use-system-libs




Convert a PC to a HTPC with Debian and Kodi

I recently converted an old workstation to run as a home-theatre PC (HTPC). I’ve noted down the setup here for others who are making an installation like this. Some steps depend on using a radeon chipset, and will need to be adjusted for your computer.


First up, Desktop ‘towers’ are not a good form-factor for sitting in TV cabinets. If your PC is this sort of size, then source a small form-factor case and power supply, and load the computer’s components into it:


I also used a Logitech k400r keyboard and mouse for wireless input.

Install Debian and apps

Write the latest copy of Debian Stable to a CD or flash drive (this is version 8.3 at time of writing), and install it on the computer. Check “Debian Desktop environment” / GNOME during setup.

After installation, open a terminal, and type “su” to get root privileges.


Edit the software sources to include ‘contrib’ and ‘non-free’, as well as ‘jessie-backports’.

nano /etc/apt/sources.list
deb jessie main contrib non-free
deb-src jessie main contrib non-free

deb jessie/updates main contrib non-free
deb-src jessie/updates main contrib non-free

# jessie-updates, previously known as 'volatile'
deb jessie-updates main contrib non-free
deb-src jessie-updates main contrib non-free

# jessie-backports
deb jessie-backports main contrib non-free
deb-src jessie-backports main contrib non-free

Update sources and install Kodi:

apt-get install --install-suggests kodi

Also install the firmware packages that you may need.

apt-get install firmware-linux-free firmware-amd-graphics



sudo allows you to run commands as root from your regular user account. Install the package and add yourself to the sudo group:

apt-get install sudo
usermod -a -G sudo mike

To apply the change, log out and back in again. The rest of this guide assumes you are logged in as yourself, and will use sudo where necessary.

Auto-start Kodi

Open the tweak tool, and locate the list of startup programs.


Add Kodi to the list, log out, log in, and Kodi will launch automatically.


For a PC attached to a TV, user permissions are not so importnat, so set the user to log in automatically.

sudo nano /etc/gdm3/daemon.conf

Un-comment this block and enter your username:

# Enabling automatic login
#  AutomaticLoginEnable = true
#  AutomaticLogin = user1

Plymouth start-up screen

Install plymouth and configure grub to change the Debian boot sequence (a menu with timeout, followed by lots of text) into a graphical splash screen. This takes a bit of configuration.

sudo apt-get install plymouth

Set it up according to these instructions:

sudo nano /etc/initramfs-tools/modules

Set drm correctly for your chipset:

radeon modeset=1

Configure grub:

sudo nano /etc/default/grub

Update grub, set the theme in Plymouth:

sudo update-grub2
sudo /usr/sbin/plymouth-set-default-theme --list
sudo /usr/sbin/plymouth-set-default-theme joy

Run update-initramfs to apply the changes

sudo update-initramfs -u


Samba will let you share folders over your network. A basic folder with guest read/write is simple to set up:

sudo apt-get install nautilus-share samba libpam-smbpass winbind
sudo usermod -a -G sambashare mike

Log out, and back in to apply the group change, and then share the Public folder over the network by right-clicking on it and opening the “Sharing Options”:


Gnome will warn that the folder as shared if you open it:


Test the setup by typing smb://localhost into the address bar:


Overscan correction

In my case, I was able to set the TV to treat the input as a “PC” input. If that doesn’t work for you, then use xrandr in a login script:

Find the name of your input:

xrandr --query

Set underscan (get the horizontal and vertical values by trial and error):

xrandr --output HDMI-0 --set underscan on
xrandr --output HDMI-0 --set "underscan hborder" 32 --set "underscan vborder" 16

Kodi plugins

Add these as needed. The Australian catchup TV plugins repository from GitHub worked well.

Kodi RSS

The RSS feed shows Kodi updates by default, and is part of your user profile.


Edit the configuration file, and adjust the paths to your news sources of choice.


Boot speed

Readahead is the tool of choice for boot speed optimisation. Install it, and reboot.

sudo apt-get install readahead
sudo touch  /.readahead_collect
sudo reboot

Desktop Apps

If you quit Kodi, you are dropped back to the GNOME desktop. These apps are simply to improve the desktop user experience.

Google Chrome

Download the .deb file for Chrome from Google, install with dpkg, and then clean up dependencies:

dpkg -i google-chrome-stable_current_amd64.deb 
apt-get -f install


Download and extract the Firefox for Linux tarball from Mozilla.

Move it to /usr/share, and change the owner to match other applications there.

mv firefox /usr/share/
cd /usr/share/
ls -Ahl
chown root:root firefox
chown -R root:root firefox

Find the main menu editor, and add Firefox to the menu.


Firefox Web Browser



Test the new icon by searching:


Auto-clear browser profiles

Because you don’t need a password to log in to the user account, you can add this as a bit of insurance so that your box wont remember any passwords or sessions.

crontab -e

This job removes the Firefox and Chrome user profiles each boot.

@reboot rm --preserve-root -Rf -- ~/.config/google-chrome ~/.cache/google-chrome ~/.mozilla/firefox ~/.cache/mozilla/firefox


For file format support, best to have another media player:

sudo apt-get install vlc


You should now have a PC which boots into Kodi for media and TV, and lets you quit into a desktop to browse the web or run regular desktop apps.



On the 1GB RAM / dual core workstation, it still took around 45 seconds from the BIOS handing over control to Kodi being ready.

Update 2017-12-29: Re-installing this setup on an SSD shortened this time to 21 seconds. This includes boot, login, and an application start.

Fix merge conflicts in git with Meld

When you’re writing code collaboratively, there’s plenty of situations when you need to combine two sets of changes.

This could happen, for example, if Bob and yourself both fix different bugs by making edits to the same file.


This post assumes that your source code is tracked in git.

First up, install meld. The Meld homepage has instructions for other platforms, but on Debian/Ubuntu, it’s just:

sudo apt-get install meld

Now tell git to use it as a tool:

git config --global merge.tool meld

Once you have a merge conflict, you can then fire up Meld like this:

git mergetool

For each file, you will get a 3-way diff. Click the arrows on the sides to move the code you want into the middle:


Once you’ve saved the file and closed Meld, you will be prompted on the command-line. You just tell it whether you’ve successfully merged the file, until it stops giving you new files to merge.

After this, commit the changes:

git commit


Simpler usage

If you don’t use git, you can simply call Meld from the command-line as well. This shows you differences between files in a similar window, and lets you move blocks of code around as well:

meld foo.c bar.c