Saturday, October 4, 2014

DDNS with Docker and nsupdate

Many robust and scalable solutions exist for monitoring docker containers and publish their IP addresses into some service discovery solution.  SkyDNS or are such examples.  However I wanted a simpler solution for the few containers I run on my home network server, so I put together the simplest service discovery mechanism possible.

Place the following file in /etc/cron.daily - this has been tested on Ubuntu 14.04:

CONTAINERS=($(docker ps -q))    # fetch all containers
TTL="86400"                     # 1 day

# prepare file
if [ -f $TMPFILE ]; then

  NAME=`docker inspect -f '{{.Name}}' $CONTAINER`
  NAME=${NAME#/} # remove leading / from container name
  IP=`docker inspect -f '{{.NetworkSettings.IPAddress}}' $CONTAINER`
  echo "update add $NAME.$DOMAIN $TTL A $IP" >> $TMPFILE
echo "send" >> $TMPFILE

nsupdate -k $KEY $TMPFILE
exit 0

The script be executed daily. It fetches all containers from docker and publishes their name+domain with their ip address to bind9 DNS server.

If start new containers, you can manually run the script again to update DNS.

Note: this script does not remove DNS names when you stop containers.

Thursday, September 18, 2014

Go on Ubuntu


I have a strong Java background and have messed around with various other languages but never become fluent in any of them.  I guess because I didn't have to.  Perl crossed my path early in my career, then Ruby became popular and later python.
Now I'm looking at Go.  Actually it's the third time or so I'm doing that, and this time there seems to be a click.  What attracts me most is that it's fairly easy to pick up, and... it generates a single executable that can exist on its own without having to install a run-time environment.  I assume that's one of the reasons why it's so popular in the cloud community these days (yes, next to python of course).
Anyway, just a quick write-up so I don't forget how to quickly get started with Go after my next PC refresh.  There's nothing new here... just summarizing few key steps in one place.

The basics

Check the downloads section in the golang website for the latest and download it.

$ cd /tmp
$ wget --no-check-certificate
$ sudo tar -C /usr/local -xzf go1.3.1.linux-amd64.tar.gz

Create a workspace where you want to keep your Go projects

$ cd ~
$ mkdir -p ./workspace/go/src
$ mkdir -p ./workspace/go/bin

Add these lines to your ~/.bashrc file

export PATH=$PATH:/usr/local/go/bin
export GOROOT=$HOME/workspace/go
export PATH=$PATH:/$GOROOT/bin

Syntax highlighting and autocomplete in vi

Once there's good information on various tooling integration in /usr/local/go/misc.  I'm interested in vi.  Based on what's there in /usr/local/go/misc/readme.txt, here is the content of my /etc/vim/vimrc.local file.

" Some Linux distributions set filetype in /etc/vimrc.
" Clear filetype flags before changing runtimepath to force Vim to reload them.
if exists("g:did_load_filetypes")
  filetype off
  filetype plugin indent off
set runtimepath+=/usr/local/go/misc/vim " replace $GOROOT with the output of: go env GOROOT
filetype plugin indent on
syntax on

" Reformat on exit/write of file.
autocmd FileType go autocmd BufWritePre <buffer> Fmt

" Close auto-complete window when exiting edit/insert mode.
autocmd InsertLeave * if pumvisible() == 0|pclose|endif

" Auto-complete braces
inoremap {      {}<Left>
inoremap {<CR>  {<CR>}<Esc>O
inoremap {     {
inoremap {}     {}

inoremap (      ()<Left>
inoremap (<CR>  (<CR>)<Esc>O
inoremap (     (
inoremap ()     ()

inoremap [      []<Left>
inoremap [<CR>  [<CR>]<Esc>O
inoremap [     [
inoremap []     []

And that's it.  You should now see syntax highlighting in vi.  Ctrl+x, ctrl+o opens up auto-complete.

Updated! Initial version of this post had some issues (<> tags where missing)

Tuesday, July 15, 2014

Docker repository for Openhab 1.5.0

I just finished a Docker repository for Openhab 1.5.0 which allows faster deployment.  The repo is available here:

The source code for the repository is available from github:

Assuming you have docker installed on your machine, these are the few steps to take to get openhab up and running.

  1. Create a config directory and store your openhab configuration files there.  This is the content of [OPENHAB_HOME]/configurations and will be injected into the container.  Let's assume you chose /tmp/config.
  2. Add a file called addons.cfg into that same config directory.  This file is used to determine which plugins to enable for your deployment.  Each line in the config file should have the name of the addon jar file to load. My file looks like this:
# cat config/addons.cfg
  1. Run docker:
    docker run --rm -p 80:8080 -v /tmp/config:/opt/openhab/configurations tdeckers/openhab
Now you can access the openhab installation on port 80 of your host.


Tuesday, March 18, 2014

Alarm Clock operates your house

I have my house wired up pretty nicely with all kinds of automation - I'll post details on this later.  Today, I wanted to hook up the alarm clock on my phone.  Basic scenario: when the alarm goes off, turn on the lights and open the shutters.  Let's get to it.

I have a KNX-based home automation system, but most of the advanced scenarios are configured in OpenHAB.  The basic flow for automating this alarm clock scenario is documented here:

Let's go wild and start with the middle part here.  We configure an item in OpenHAB that we can use to trigger the alarm.  Look here for details on adding items in OpenHAB.  We'll add this line:

Switch pWekkerTom "Wekker Tom" {autoupdate="false"}

If you're not familiar with this 'autoupdate' parameter, don't worry about it. It just makes this switch act as a trigger without changing its state.  The scenario would work even without it.

Next we create a rule that catches commands for the pWekkerTom item, and performs whatever actions we want when our alarm goes off.

rule "Wekker Tom"
        Item pWekkerTom received command ON
logInfo("PERSONAL", "Wekker Tom!")
sendCommand(lBMasterGang, 25)
createTimer(now.plusSeconds(45)) [| sendCommand(lBMasterGang, 50)]
createTimer(now.plusSeconds(90)) [| sendCommand(lBMasterGang, 75)]
createTimer(now.plusSeconds(120)) [| sendCommand(shMaster, UP)]

This rule will:

  1. log a note in the openHAB logs
  2. dim lights in the hallway of the bedroom to 25%
  3. after 45 seconds, dim lights to 50%
  4. after 90 seconds, dim lights to 75%
  5. after 120 seconds, move the shutters up
You can completely customize this to your own desires.

Now all is left is a way to have our mobile phone trigger all of the above.  For this purpose, we use the swiss army knife of Android automation: Tasker. (Apologies iPhone users - you're out of luck here.  I'm sure Tasker equivalents exist, I just don't have any experience with them).
We'll use the OpenHAB REST API, so we'll also install the RESTask for Tasker plugin.  This provides a bit more features than the native Tasker HTTP actions.

Once both are installed from the Google Play Store, first go to the Tasks tab in Tasker and create a new Task. in this Task, create an Action by clicking the + sign at the bottom of the screen.  For action category, select Plugin -> RESTask.
In the configuration of the RESTask, fill in these fields:
  • Request Type: POST
  • Host:
  • Basic Auth: <your credetials>
  • Enable custom body: check!
  • Custom body: ON
You can leave most other settings to their defaults, but it depends on your setup.
Save all this goodness.  The last step is to create a profile that ties the alarm clock to the task.
Go to the Profiles tab in Tasker and create a new Profile by clicking the + sign at the bottom of the screen. In event category select Date/Time -> Alarm Clock.
Save this, and then associate this profile with the Task you have created earlier.  Done!

In more detail, this is what we've accomplished: