graham gilbert

Mac administration and assorted nerdity

Using a Proxy Container With Docker for Virtualhosts

| Comments

I’ve been asked a few times over the last few weeks about how you can have multiple services (for example, Munki and Sal) running on the same port on the same server – how we used to do Virtual Hosting when we ran our apps on the host OS. My usual four word answer has been ‘use a proxy container’. How you actually do that has been undocumented – this post hopes to recitfy that.

Let’s consider a usual setup that has Sal and Munki running on the same box. We have two hostnames that both resolve to our Docker server – sal.example.com and munki.example.com, and we have our containers running in a manner similar to the below:

Container layout

Each of our containers is linked to it’s parent:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# Munki server
docker run -d \
-v /usr/local/docker/munki:/munki_repo \
--restart="always" \
--name="munki" \
macadmins/munki

# Postgres container for Sal
docker run -d --name="postgres-sal" \
-v /usr/local/docker/sal/db:/var/lib/postgresql/data \
-e DB_NAME=sal \
-e DB_USER=admin \
-e DB_PASS=password \
--restart="always" \
grahamgilbert/postgres

# Sal Container
docker run -d \
-e ADMIN_PASS=pass \
-e DB_NAME=sal \
-e DB_USER=admin \
-e DB_PASS=password \
--name="sal" \
--link postgres-sal:db \
--restart="always" \
macadmins/sal

# Proxy
docker run -d --name="proxy" \
--link sal:sal \
--link munki:munki \
-v /usr/local/docker/proxy/sites-templates:/etc/nginx/sites-templates \
-v /usr/local/docker/proxy/keys:/etc/ssl/keys \
-p 443:443 \
-p 80:80 \
--restart="always" \
grahamgilbert/proxy

So how does the proxy container know about the other containers? When you link a Docker container to another, a few environment variables are made available to you – there are two we’re interested in:

  • CONTAINERNAME_PORT_EXPOSEDPORTNUMBER_TCP_ADDR
  • CONTAINERNAME_PORT_EXPOSEDPORTNUMBER_TCP_PORT

So in the case of the Sal container, it would be SAL_PORT_8000_TCP_ADDR and SAL_PORT_8000_TCP_PORT. The grahamgilbert/proxy image will simply run over any file named *.tmpl in /etc/nginx/sites-templates and replace the palceholders with the value that’s in the environent variable – here’s my nginx configuration file template for Sal:

nginxlink
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
server {
       listen         80;
       server_name    sal.example.com;
       rewrite        ^ https://$server_name$request_uri? permanent;
}

server {
        listen              443 ssl;
        server_name         sal.example.com;
        ssl_certificate     /etc/ssl/keys/ssl-unified.crt;
        ssl_certificate_key /etc/ssl/keys/sal.key;

        location / {
            proxy_pass http://${SAL_PORT_8000_TCP_ADDR}:${SAL_PORT_8000_TCP_PORT}; # set to your own port
            proxy_redirect off;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
     
            client_max_body_size 10m;
            client_body_buffer_size 128k;
     
            proxy_connect_timeout 90;
            proxy_send_timeout 90;
            proxy_read_timeout 90;
            proxy_buffer_size 4k;
            proxy_buffers 4 32k;
            proxy_busy_buffers_size 64k;
            proxy_temp_file_write_size 64k;
        }
    }

Using this technique, you can have as many containers as you like all serving content on the same port number – just change line 14 above to reflect the exposed ports and names of your Docker containers.

Mac Admin & Developer Conference UK

| Comments

I’m very happy to announce that I will be speaking at the first Mac Admin & Developer Conference UK, held in our very own London on Feburary 9th and 10th, 2016. In addition to some fantastic speakers (I have no idea how they let me in), it’s being sponsored by London Apple Admins (who will be meeting next in early September – we are looking for people who would like to give a short 15-20 minute presentation – get in touch if you’re interested).

Running Puppet Server in Docker Part 3: Hiera

| Comments

In the previous two parts, we went over how to get a basic Puppet Server up and running in Docker and how to deploy your modules using r10k. This time we’ll assign some configuration to our nodes using Hiera.

For a full explanation of what Hiera is, see the Puppetlabs documentation, but essentially, you are using a series of directories and files that are named in a particular way, and then specifying which is the most speccific to your node.

Using the Sal API

| Comments

As previously mentioned, Sal now has an API. You might be wondering what you can do with this wonderous API. This is a simple example of using it to automate building packages to enrol Macs into Sal.

The basic workflow of this script is:

  • Use the API to get a list of all Machine Groups in Sal – this will return JSON (a markup language that is easily parsable with languages like Python)
  • Download the Sal postflight scripts
  • Download the latest Facter installer
  • For each machine group, build a package that will install all of the packages and then set the correct Sal preferences.

You can find the script in this Gist. I’m not going to go through the script line by line, but we’ll cover how to configure it.

First off you will need an API key configuring. Log into Sal as a user with Global Admin privelages and choose the ‘person’ menu at the top right and then choose Settings. From the sidebar, choose API keys and then choose to make a new one. Give it a name so you can recognise it – I called this one “PKG Generator”. You will then be given a public key and a private key. Make a note of them, we’ll need them in the next section.

Configuring the script

Edit the variables at the top to match your environment:

1
2
3
4
5
6
7
# No trailing slash on this one - I was lazy and didn't check for it
SAL_URL = "https://sal.yourcompany.com"
PUBLIC_KEY = "yourpublickeyhere"
PRIVATE_KEY = "yourreallyreallyreallylongprivatekeyhere"
PKG_IDENTIFIER = "com.yourcompany.sal_enrol"
SAL_PKG = "https://github.com/salopensource/sal/releases/download/v0.4.0/sal_scripts.pkg"
FACTER_PKG = "https://downloads.puppetlabs.com/mac/facter-latest.dmg"

There are some caveats with this script:

  • It will spit the packages out in your current directory. Make sure you’ve cd-ed into where you want the packages to be generated.
  • It uses urllib2 to request the information from Sal and to download the packages – this means that there is no verification of the SSL certificates, so make sure you know where you’re connecting to.

All ready to run it?

1
$ sudo python sal_package_generator.py

And you’ll get a directory full of packages that will get your fleet reporting into Sal.

Munki DND

| Comments

I’ve been wanting to get stuck in with a simple Swift project for a while, but couldn’t think of anything suitable for a first project (Imagr was originally going to be that project, but I don’t think it would ever have been made if I chose Swift), until I saw Dr Graham R Pugh’s Do Not Disturb application. I thought it was an excellent idea that could be made even better by being a manu bar app.

Enter Munki DND – it extends Graham’s idea by allowing the administrator to configure the number of hours the user is allowed to suppress notifications for, as well as living in the menu bar so the user can check how long they’ve got until notifications become active again.

You can grab version 0.0.1 of Munki DND from the Releases page on GitHub.