Two-Factor Authentication the right way

About two-factor authentication:

You may or may not use two-factor authentication (2FA) on your important online identities (like Google, Facebook, Twitter, or any other ‘personal’ account).

Photo showing two-factor authentication

So, whenever you log into one of those accounts you are prompted for two things next to your username, namely your password and two-factor token.

In Theory:

Why does this token create an extra benefit? Let’s look at some of the different flavours of authentication:

  • Something your know (like a password). This is one of the most common means of online authentication. You fill in a piece of text only known by you, so the system can verify that you are who you say you are.
  • Something you have (like a smartcard, also called a Security Token). This form is used a lot more in offline environments. If you take a bank for example, the Something you have can be your ATM-card. And they combine it with Something you know, namely your PIN.
  • Something you are (like a fingerprint). This form is sometimes found on certain laptops, and can even be used to configure two-factor login with PAM under linux.

So, two-factor authentication is a combination of above named flavours. Because it’s a combination, it’s sometimes called ‘multi-factor authentication’.

In practice:

Previous situation:

I used to have two-factor setup only on a select few important accounts for me. Although it worked out, I was kind of scared for losing my phone, since losing it, means losing access to the generated that creates the OTP (One Time Password) tokens.

When you set your account up, you usually get the option of generating a few ‘scratch-codes’. These codes are not bound by time, but can be used in case of an emergency. However, I needed a place to store the codes.

I used to store them in my password manager, but I wasn’t too happy about that, since it would break the multiple factors of something I know, and something I have stored together.

Current situation:

You may have read my blogpost about the YubiKey Neo which I use for PGP subkeys. One other thing the Neo can do, is using NFC. If you are familiar with Google Authenticator on your mobile device, Yubico offers a slightly patched alternative called Yubico Authenticator. It does things very similar, altough it requires NFC of the YubiKey to show the OTPs. One benefit of this is that I can use it on any device which has the Yubico Authenticator installed.

This photo is taken from the Yubico blog https://www.yubico.com/2013/09/yubikey-neo-oath-applet/

This photo belongs to Yubico

The same problem I had in the past still stands unfortunately, what if I lose my YubiKey? Well, for PGP, I can create new subkeys, but for OTPs, I can’t, since I don’t know the secret.

I’ve found a trick online which is so simple that I feel stupid not thinking about it before, whenever you set up two-factor authentication, you usually get a nice QR-code that you would scan to transfer the secret onto your device. You then enter one of the OTPs to confirm the generator works properly.

I have an old iPhone 4 laying around which wasn’t used anymore since it’s too slow now-a-days, however I still have Google Authenticator installed. I setup all of my codes again for the YubiKey, and at the same time scanned the QR-codes with my iPhone, and verified that both generate the same keys before confirming the new secret. That way I always have a ‘backup’ of my secrets.

I store this phone together with my USB-stick containing the PGP master-key, and only use it in emergencies.

Conclusion:

I now have a separation of something I know and something I have, while avoiding the risk of losing the something I have. Since I have a backup of on my old iPhone. On the other hand, I don’t even have to keep my phone with me, since the YubiKey works universally on any device that has the Yubico Authenticator.

If you have any questions or feedback, I’d love to hear from you in the comments below. Please let me know if you have made similar setups :)

PS. I am in no way affiliated with Yubico, I’m just a happy customer! :)

YubiKey Neo with PGP subkeys

I have been using PGP keys for some time, using them to sign and/or encrypt my e-mails (I use Mozilla Thunderbird with the Enigmail plugin for this).

I’ve been wanting to create a setup where I use these keys for more then just e-mail, for encrypting files or as SSH authentication for example. This also includes the ‘pass‘ tool, which utilizes a combination of git and pgp as a password manager in a powerful way.

As an owner of a YubiKey Standard ($25 and only for OTP purposes), I’ve known about the more expensive models (like the $50 YubiKey Neo), as I know of the existance of OpenPGP smartcards in the world. An important difference is, quite a few smartcards allow for only 1024bits keys, while the YubiKey allows 2048bit keys.

I went for the YubiKey Neo, got it in the mail, and started playing with it. I thought, might as well make a tutorial blogpost over this to help anyone who is considering such a setup.

First off, you need GnuPG installed, which is available in package-managers among Unix-like distro’s. I am demonstrating this on OSX, but should work fairly similar on other operating systems.

$ brew install gpg2

When first starting gpg, it will generate two things in your $GNUPGHOME directory (by default ~/.gnupg)

gpg: keyring `/Users/myusername/.gnupg/secring.gpg’ created
gpg: keyring `/Users/myusername/.gnupg/pubring.gpg’ created
gpg: /Users/myusername/.gnupg/trustdb.gpg: trustdb created

These files serve the basis of all keys GnuPG will deal with from this point on.

When first inserting the YubiKey and listing information from GnuPG, it will look something like this

$ gpg –card-status
Application ID …: D2760001XXXX000006036XXXXX0000
Version ……….: 2.0
Manufacturer …..: Yubico
Serial number ….: 036XXXXX
Name of cardholder: [not set]
Language prefs …: [not set]
Sex …………..: unspecified
URL of public key : [not set]
Login data …….: [not set]
Signature PIN ….: forced
Key attributes …: 2048R 2048R 2048R
Max. PIN lengths .: 127 127 127
PIN retry counter : 3 3 3
Signature counter : 0
Signature key ….: [none]
Encryption key….: [none]
Authentication key: [none]
General key info..: [none]

Ofcourse, I’ve censored a few things here and there, but note the highlighted information. I can put three keys of 2048bit RSA on this device. Why are there three? And how do they differ?

Traditionally you can generate a PGP key and use it for whatever you like, signing, encrypting, authentication. Doesn’t really matter. Up until the point that your key may be compromised.

For prevent this, we are going to create a master key which can sign other keys, and three subkeys for Signing, Encryption and Authentication. The three subkeys will be integrated into the YubiKey, while the master key will live on an USB-stick stashed in a secret place.

To generate the master key, I’ve taken a bootable live debian image with no network attached, and mounted another USB-stick which I pointed out as the GNUPGHOME directory.

$ export GNUPGHOME=/media/user/USBSTICK/gnupghome
$ mkdir $GNUPGHOME

To generate the master key:

$ gpg –expert –gen-key
gpg (GnuPG/MacGPG2) 2.0.27; Copyright (C) 2015 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Please select what kind of key you want:
(1) RSA and RSA (default)
(2) DSA and Elgamal
(3) DSA (sign only)
(4) RSA (sign only)
(7) DSA (set your own capabilities)
(8) RSA (set your own capabilities)
Your selection? 8

Possible actions for a RSA key: Sign Certify Encrypt Authenticate
Current allowed actions: Sign Certify Encrypt

(S) Toggle the sign capability
(E) Toggle the encrypt capability
(A) Toggle the authenticate capability
(Q) Finished

Your selection? S

Possible actions for a RSA key: Sign Certify Encrypt Authenticate
Current allowed actions: Certify Encrypt

(S) Toggle the sign capability
(E) Toggle the encrypt capability
(A) Toggle the authenticate capability
(Q) Finished

Your selection? E

Possible actions for a RSA key: Sign Certify Encrypt Authenticate
Current allowed actions: Certify

(S) Toggle the sign capability
(E) Toggle the encrypt capability
(A) Toggle the authenticate capability
(Q) Finished

Your selection? Q
RSA keys may be between 1024 and 4096 bits long.
What keysize do you want? (2048) 4096
Requested keysize is 4096 bits
Please specify how long the key should be valid.
0 = key does not expire
<n> = key expires in n days
<n>w = key expires in n weeks
<n>m = key expires in n months
<n>y = key expires in n years
Key is valid for? (0) 0
Key does not expire at all
Is this correct? (y/N) y

GnuPG needs to construct a user ID to identify your key.

Real name: Dennis de Greef
Email address: dennis@example.com
Comment:
You selected this USER-ID:
“Dennis de Greef <dennis@example.com>”

Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? O
You need a Passphrase to protect your secret key.

We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, utilize the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.
gpg: key AAB98B2F marked as ultimately trusted
public and secret key created and signed.

gpg: checking the trustdb
gpg: 3 marginal(s) needed, 1 complete(s) needed, PGP trust model
gpg: depth: 0 valid: 1 signed: 0 trust: 0-, 0q, 0n, 0m, 0f, 1u
pub 4096R/AAB98B2F 2015-07-26
Key fingerprint = 69B2 F1E7 3A1F C011 D81C 802E 732D F32A AAB9 8B2F
uid [ultimate] Dennis de Greef <dennis@example.com>

So what we just did, was create an 4096bits RSA key with the only capability of signing other keys (we switched off Signing and Encryption). We set the expire date to never, since this key will forever be secret (stashed away somewhere). And if the key would somehow be compromised, we can use a revocation certificate (I’ll come back to that later).

It also asked for a passphrase, be sure to put in a strong password in here.

NOTE: Be sure to put in your valid e-mail address. If you want more e-mail addresses known, you can add them with adduid in the GPG edit-key mode.

Before proceeding, we want to create a backup of our master key to a plaintext format

$ gpg -a –export-secret-keys AAB98B2F > $GNUPGHOME/../masterkey.txt
$ cat $GNUPGHOME/../masterkey.txt
—–BEGIN PGP PRIVATE KEY BLOCK—–
Version: GnuPG/MacGPG2 v2

lQc+BFW0xnwBEADZ3q/nBuybiVZK9kbmoH2q3nccds0bS7l2iW4r7aT4Wm16z8RV
[…]

So, next we need to generate some subkeys to be able to perform the other capabilities.

$ gpg –expert –edit-key AAB98B2F
pub 4096R/AAB98B2F created: 2015-07-26 expires: never usage: C
trust: ultimate validity: ultimate
[ultimate] (1). Dennis de Greef <dennis@example.com>

gpg> addkey
Key is protected.

You need a passphrase to unlock the secret key for
user: “Dennis de Greef <dennis@example.com>”
4096-bit RSA key, ID AAB98B2F, created 2015-07-26

Please select what kind of key you want:
(3) DSA (sign only)
(4) RSA (sign only)
(5) Elgamal (encrypt only)
(6) RSA (encrypt only)
(7) DSA (set your own capabilities)
(8) RSA (set your own capabilities)
Your selection? 8

Possible actions for a RSA key: Sign Encrypt Authenticate
Current allowed actions: Sign Encrypt

(S) Toggle the sign capability
(E) Toggle the encrypt capability
(A) Toggle the authenticate capability
(Q) Finished

Your selection? E

Possible actions for a RSA key: Sign Encrypt Authenticate
Current allowed actions: Sign

(S) Toggle the sign capability
(E) Toggle the encrypt capability
(A) Toggle the authenticate capability
(Q) Finished

Your selection? Q
RSA keys may be between 1024 and 4096 bits long.
What keysize do you want? (2048) 2048
Requested keysize is 2048 bits
Please specify how long the key should be valid.
0 = key does not expire
<n> = key expires in n days
<n>w = key expires in n weeks
<n>m = key expires in n months
<n>y = key expires in n years
Key is valid for? (0) 5y
Key expires at Fri Jul 24 13:45:33 2020 CEST
Is this correct? (y/N) y
Really create? (y/N) y
We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, utilize the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.

pub 4096R/AAB98B2F created: 2015-07-26 expires: never usage: C
trust: ultimate validity: ultimate
sub 2048R/A1EFF93C created: 2015-07-26 expires: 2020-07-24 usage: S
[ultimate] (1). Dennis de Greef <dennis@example.com>

gpg>

We now have created a subkey for signing. Repeat this process for Encryption and Authentication, and we have a master key with 3 subkeys for different capabilities. Type ‘save‘ to save your changes.

pub 4096R/AAB98B2F created: 2015-07-26 expires: never usage: C
trust: ultimate validity: ultimate
sub 2048R/A1EFF93C created: 2015-07-26 expires: 2020-07-24 usage: S
sub 2048R/4A71FF50 created: 2015-07-26 expires: 2020-07-24 usage: E
sub 2048R/77409C9F created: 2015-07-26 expires: 2020-07-24 usage: A
[ultimate] (1). Dennis de Greef <dennis@example.com>

It is good practice to generate a revocation certificate in case you lose your key. Store this in a safe place, possibly printed out on paper.

$ gpg –output $GNUPGHOME/../revocation-certificate.txt –gen-revoke AAB98B2F

sec 4096R/AAB98B2F 2015-07-26 Dennis de Greef <dennis@example.com>

Create a revocation certificate for this key? (y/N) y
Please select the reason for the revocation:
0 = No reason specified
1 = Key has been compromised
2 = Key is superseded
3 = Key is no longer used
Q = Cancel
(Probably you want to select 1 here)
Your decision? 1
Enter an optional description; end it with an empty line:
> This revocation certificate is generated during key creation and should be used in emergencies only
>
Reason for revocation: Key has been compromised
This revocation certificate is generated during key creation and should be used in emergencies only
Is this okay? (y/N) y

You need a passphrase to unlock the secret key for
user: “Dennis de Greef <dennis@example.com>”
4096-bit RSA key, ID AAB98B2F, created 2015-07-26

ASCII armored output forced.
Revocation certificate created.

Please move it to a medium which you can hide away; if Mallory gets
access to this certificate he can use it to make your key unusable.
It is smart to print this certificate and store it away, just in case
your media become unreadable. But have some caution: The print system of
your machine might store the data and make it available to others!

Like the description says, store this away somewhere safe, and only use it when your master keys needs to be revoked.

Now we want to make a few backups in plaintext of our master key including the subkeys

$ gpg -a –export-secret-keys AAB98B2F > $GNUPGHOME/../mastersubkeys.txt
$ cat $GNUPGHOME/../mastersubkeys.txt
—–BEGIN PGP PRIVATE KEY BLOCK—–
Version: GnuPG/MacGPG2 v2

lQc+BFW0xnwBEADZ3q/nBuybiVZK9kbmoH2q3nccds0bS7l2iW4r7aT4Wm16z8RV
[…]

And for the subkeys

$ gpg -a –export-secret-subkeys AAB98B2F > $GNUPGHOME/../subkeys.txt
$ cat $GNUPGHOME/../subkeys.txt
—–BEGIN PGP PRIVATE KEY BLOCK—–
Version: GnuPG/MacGPG2 v2

lQIVBFW0xnwBEADZ3q/nBuybiVZK9kbmoH2q3nccds0bS7l2iW4r7aT4Wm16z8RV

Now we can setup the YubiKey to contain personal information and our subkeys. Make sure the device is in OTP/CCID or CCID mode.

$ brew install yubikey-personalization
$ ykpersonalize -m82

Now edit the card to personalise it.

$ gpg –card-edit

gpg/card> admin
Admin commands are allowed

gpg/card> passwd
gpg: OpenPGP card no. D2760001XXXX000006036XXXXX0000 detected

1 – change PIN
2 – unblock PIN
3 – change Admin PIN
4 – set the Reset Code
Q – quit

Your selection? 3
PIN changed.

1 – change PIN
2 – unblock PIN
3 – change Admin PIN
4 – set the Reset Code
Q – quit

Your selection? 1
PIN changed.

1 – change PIN
2 – unblock PIN
3 – change Admin PIN
4 – set the Reset Code
Q – quit

Your selection? q

gpg/card> name
Cardholder’s surname: De Greef
Cardholder’s given name: Dennis

gpg/card> lang
Language preferences: en

gpg/card> url
URL to retrieve public key: https://dennisdegreef.net/aab98b2f.txt

gpg/card> sex
Sex ((M)ale, (F)emale or space): m

gpg/card> login
Login data (account name): dennisdegreef

gpg/card> list

Application ID …: D2760001XXXX000006036XXXXX0000
Version ……….: 2.0
Manufacturer …..: Yubico
Serial number ….: 036XXXXX
Name of cardholder: Dennis De Greef
Language prefs …: en
Sex …………..: male
URL of public key : https://dennisdegreef.net/aab98b2f.txt
Login data …….: dennisdegreef
Signature PIN ….: forced
Key attributes …: 2048R 2048R 2048R
Max. PIN lengths .: 127 127 127
PIN retry counter : 3 3 3
Signature counter : 0
Signature key ….: [none]
Encryption key….: [none]
Authentication key: [none]
General key info..: [none]

gpg/card> quit

Next, we want to embed the subkeys into the card.

$ gpg –edit-key AAB98B2F
gpg (GnuPG/MacGPG2) 2.0.27; Copyright (C) 2015 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Secret key is available.

pub 4096R/AAB98B2F created: 2015-07-26 expires: never usage: C
trust: ultimate validity: ultimate
sub 2048R/A1EFF93C created: 2015-07-26 expires: 2020-07-24 usage: S
sub 2048R/4A71FF50 created: 2015-07-26 expires: 2020-07-24 usage: E
sub 2048R/77409C9F created: 2015-07-26 expires: 2020-07-24 usage: A
[ultimate] (1). Dennis de Greef <dennis@example.com>

gpg> toggle

sec 4096R/AAB98B2F created: 2015-07-26 expires: never
ssb 2048R/A1EFF93C created: 2015-07-26 expires: never
ssb 2048R/4A71FF50 created: 2015-07-26 expires: never
ssb 2048R/77409C9F created: 2015-07-26 expires: never
(1) Dennis de Greef <dennis@example.com>

gpg> key 1

sec 4096R/AAB98B2F created: 2015-07-26 expires: never
ssb* 2048R/A1EFF93C created: 2015-07-26 expires: never
ssb 2048R/4A71FF50 created: 2015-07-26 expires: never
ssb 2048R/77409C9F created: 2015-07-26 expires: never
(1) Dennis de Greef <dennis@example.com>

gpg> keytocard
Signature key ….: [none]
Encryption key….: [none]
Authentication key: [none]

Please select where to store the key:
(1) Signature key
(3) Authentication key
Your selection? 1

You need a passphrase to unlock the secret key for
user: “Dennis de Greef <dennis@example.com>”

4096-bit RSA key, ID AAB98B2F, created 2015-07-26
sec 4096R/AAB98B2F created: 2015-07-26 expires: never
ssb* 2048R/A1EFF93C created: 2015-07-26 expires: never
card-no: 0123 00000042
ssb 2048R/4A71FF50 created: 2015-07-26 expires: never
ssb 2048R/77409C9F created: 2015-07-26 expires: never
(1) Dennis de Greef <dennis@example.com>

gpg> key 1

sec 4096R/AAB98B2F created: 2015-07-26 expires: never
ssb 2048R/A1EFF93C created: 2015-07-26 expires: never
card-no: 0123 00000042
ssb 2048R/4A71FF50 created: 2015-07-26 expires: never
ssb 2048R/77409C9F created: 2015-07-26 expires: never
(1) Dennis de Greef <dennis@example.com>

gpg> key 2

sec 4096R/AAB98B2F created: 2015-07-26 expires: never
ssb 2048R/A1EFF93C created: 2015-07-26 expires: never
card-no: 0123 00000042
ssb* 2048R/4A71FF50 created: 2015-07-26 expires: never
ssb 2048R/77409C9F created: 2015-07-26 expires: never
(1) Dennis de Greef <dennis@example.com>

gpg> keytocard
Signature key ….: EFA4 D5F7 95E0 4392 E42A 59CE DFE1 6372 72D2 245B
Encryption key….: [none]
Authentication key: [none]

Please select where to store the key:
(2) Encryption key
Your selection? 2

You need a passphrase to unlock the secret key for
user: “Dennis de Greef <dennis@example.com>”
4096-bit RSA key, ID AAB98B2F, created 2015-07-26

sec 4096R/AAB98B2F created: 2015-07-26 expires: never
ssb 2048R/A1EFF93C created: 2015-07-26 expires: never
card-no: 0123 00000042
ssb* 2048R/4A71FF50 created: 2015-07-26 expires: never
card-no: 0123 00000042
ssb 2048R/77409C9F created: 2015-07-26 expires: never
(1) Dennis de Greef <dennis@example.com>

gpg> key 2

sec 4096R/AAB98B2F created: 2015-07-26 expires: never
ssb 2048R/A1EFF93C created: 2015-07-26 expires: never
card-no: 0123 00000042
ssb 2048R/4A71FF50 created: 2015-07-26 expires: never
card-no: 0123 00000042
ssb 2048R/77409C9F created: 2015-07-26 expires: never
(1) Dennis de Greef <dennis@example.com>

gpg> key 3

sec 4096R/AAB98B2F created: 2015-07-26 expires: never
ssb 2048R/A1EFF93C created: 2015-07-26 expires: never
card-no: 0123 00000042
ssb 2048R/4A71FF50 created: 2015-07-26 expires: never
card-no: 0123 00000042
ssb* 2048R/77409C9F created: 2015-07-26 expires: never
(1) Dennis de Greef <dennis@example.com>

gpg> keytocard
Signature key ….: EFA4 D5F7 95E0 4392 E42A 59CE DFE1 6372 72D2 245B
Encryption key….: A22D 5135 CCFC 947C 8925 9E77 A11F 46D4 35F4 CC42
Authentication key: [none]

Please select where to store the key:
(3) Authentication key
Your selection? 3

You need a passphrase to unlock the secret key for
user: “Dennis de Greef <dennis@example.com>”
4096-bit RSA key, ID AAB98B2F, created 2015-07-26

sec 4096R/AAB98B2F created: 2015-07-26 expires: never
ssb 2048R/A1EFF93C created: 2015-07-26 expires: never
card-no: 0123 00000042
ssb 2048R/4A71FF50 created: 2015-07-26 expires: never
card-no: 0123 00000042
ssb* 2048R/77409C9F created: 2015-07-26 expires: never
card-no: 0123 00000042
(1) Dennis de Greef <dennis@example.com>

gpg> save
$

NOTE: This article is a work in progress, we still need to send the keys to the keyserver, so everyone will know the public keys of our generated master key (which will validate all the subkeys as well).

Developing inside Vagrant with Docker-Compose

I’ve been following the Docker movement for quite some time now, and have seen examples of Docker-Compose passing along, so I thought, why not try and setup a nice development environment where I would develop an application that uses Docker-Compose.

For all you tl;dr’s, perform:

git clone --recursive https://github.com/dennisdegreef/blog-docker-compose-infrastructure 
cd blog-docker-compose-infrastructure
vagrant up

DISCLAIMER: This example is just to setup a docker-compose setup for development, and is currently using Symfony’s build-in webserver, which isn’t recommended for production! This is also just a try-out.

For this example, I am creating a simple Symfony application, which needs Redis instance.

First, we need a vagrant plugin to be able to use docker-compose as a provisioner

# vagrant plugin install vagrant-docker-compose

Next, we need to set up a Vagrantfile inside our infrastructure repository, and configure it using the docker provisioner. The provisioner itself will install Docker inside the vagrantbox and build the base image, on which we ‘base’ our own Dockerfile

# Vagrantfile
config.vm.provision :docker do |d|
    d.build_image "/vagrant/docker/base", args: "-t link0/base"
end

Now, we want to create an docker-compose.yml file to provide the structure and requirements of our application. This setup explains docker-compose to build the ‘frontend’ image, start it with port 80 exposed, and the current directory linked as /srv

# docker-compose.yml
frontend:
  build: link0/example-frontend
  ports:
    - "80:8000"
  volumes:
    - .:/srv
  links:
    - redis
redis:
  image: redis

Now that we have the docker-compose.yml, we can instruct Vagrant to use that structure upon provisioning.

config.vm.provision :docker_compose, yml: "/vagrant/docker-compose.yml", run: "always"

But before we can run `vagrant up`, we need to add our frontend application into the infrastructure project. I like to use git submodules for this.

git submodule add git@github.com:dennisdegreef/blog-docker-compose-frontend.git frontend

Now we can try it out, see if it works :)

vagrant up

It still breaks with the following error message

Building frontend...
Cannot locate specified Dockerfile: Dockerfile

This is because our frontend application has no Dockerfile to describe how it should be running. Let’s add one.

# blog-docker-compose-frontend/Dockerfile
FROM link0/base:latest
MAINTAINER Dennis de Greef <github@link0.net>

COPY start.sh /start.sh

CMD [ "/start.sh" ]
#!/usr/bin/env bash
# blog-docker-compose-frontend/start.sh
cd /srv/frontend;
/srv/frontend/composer.phar install && \
/srv/frontend/app/console server:run 0.0.0.0:8000

And when you now run

vagrant up

And point your browser to http://192.168.42.10/ You should be able to see ‘Hello Docker-Compose’.

You can check (tail) the logs using the following command

vagrant ssh -c 'docker logs -f vagrant_frontend_1'

If some things are unclear, please let me know in the comments.

Microservices at home

Lately I’ve been playing around with the ESP8266 chipset which is an IoT (Internet of Things) platform which couples digital IO pins with a WIFI connection (I will make another post about this, and link it later on).

ESP8266 ESP-12

ESP8266 ESP-12

What I like about IoT, is that everything is connected and reacting upon each-other. The thing I dislike though, is that the trend seems to be that every piece of hardware has a callback to the mothership (the company selling the equipment).

For example, I have a Philip Hue lighting system. The Hue-bridge device provides a REST-API so you can configure your lights just the way you want automatically. On the other hand, whenever you link it to the MeetHue system, it creates a callback to Philips so you can control your lights using the app, outside your WIFI network. The Nest thermostat does something similar.

Philips Hue Lighting system

Philips Hue Lighting system

When I first came in contact with the ESP8266, it was running the alternative firmware called NodeMCU. This firmware enables you to run Lua code on the chip with a few libraries at hand, including an MQTT client.

This was the first time i’d heard of MQTT, but after a quick google found out that this is ‘just a’ Message Queue like I know from RabbitMQ. The presence of this client library opened my eyes to lots of possibilities for IoT applications inside my home without the need of passing my home internet gateway.

A few examples that I’ve been playing around with

  • Controlling a WS2812B LED strip (driver included in NodeMCU :D)
  • Reading a temperature and humidity sensor from different places in my house
  • Reading out gas and electra readings from my Smart Meter using the P1-data port
  • Controlling the air circulation system inside my house (which runs on an NRF-remote)
  • Controlling 433Mhz equipment like power outlets (now controlled by a remote)

If I can use the MQTT protocol as a layer on top of all API’s and hardware, this would be kind of similar to how Microservices work.

MQTT Sequence Diagram

MQTT Sequence Diagram

After setting up an MQTT server (I use Mosquitto, since it supports the MQTT-3.1.1 protocol in the latest versions on my RaspberryPi2), I’ve build some small microservices to start playing with this concept:

I think i’m only at the start of everything that is possible, but i’ll post updates on the expansion of my Microservice network at home.

Please let me know what you think, if you have any questions or feedback. I’m getting really excited about the subject!

Nginx unable to bind, address already in use.

Just now, I added a vhost to my nginx configuration on a machine I administer, restart nginx, and am baffled about the following error message:

Starting nginx: nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)

This is weird… nginx was running just fine up until now, and suddenly won’t start. I tried checking if it was still running, which it wasn’t, tried looking at netstat to see if any other processes are bound to that port.

# netstat -platune

This is weird. Let’s see if I can bind to port 80 myself with ‘nc’.

# nc -v -l 80

It can bind to the port just fine, let’s see if I can connect.

# telnet example.com 80
Trying 203.0.113.128...
telnet: connect to address 203.0.113.128: Connection refused
Trying 2001:db8:c0ld:c0:ff:ee::1...
telnet: connect to address 2001:db8:c0ld:c0:ff:ee::1: No route to host
telnet: Unable to connect to remote host

This is weird, the port is open, but it won’t connect. This must be my firewall interfering. After stopping the firewall, the same behaviour persisted.

After trying out some of my google skills, I stumble upon the following post on StackOverflow: http://stackoverflow.com/a/15101745/359664

It seems that because of IPv6, the port is unable to bind.

After rewriting my nginx vhosts’s to the following format, nginx is willing to start and everything is online again.

This makes me wonder, what is happening with my IPv6 traffic?

My IPv4 address is assigned through a DHCP server, and my IPv6 is assigned by a similar concept, namely SLAAC.

I can ping the outside world, and I can ping the machine from the outside.

# ping ipv6.google.com

Let’s check the same things on IPv6.

# ip6tables-save

This looks fine to me… oh wait… Port 80 is not allowed in here… I must have only allowed it in the IPv4 configuration.

After configuring the IPv6 firewall correctly (which you should always do, don’t forget about it is a lesson 😉

I’m still baffled why the IPv6 isn’t working…