Using Caddy to HTTPS all the things

Caddy is a lightweight web server that amongst it’s features, has integration with LetsEncrypt to automatically request certificates. This means that you now have absolutely no excuse anymore to run your apps over plain old HTTP anymore. Let me be clearer. If you are running web services over HTTP, regardless of whether it touches the internet or not, you are doing it wrong.

Read more →

Loading LaunchAgents as root

There are times when you will need to load a LaunchAgent when a script is running as root - when you are running a postinstall script from a package or when you are loading the LaunchAgent via your management tool of choice (Puppet, Munki, Jamf Pro), for example.

All of these example are assuming you have a LaunchAgent at /Library/LaunchAgents/com.company.example.plist.

Loading a LaunchAgent

launchagent_load.sh
#!/bin/bash
# get console UID
consoleuser=`/usr/bin/stat -f "%Su" /dev/console | /usr/bin/xargs /usr/bin/id -u`
/bin/launchctl bootstrap gui/$consoleuser /Library/LaunchAgents/com.company.example.plist
launchagent_load.py
#!/usr/bin/python
from pwd import getpwnam
import subprocess
import sys
from SystemConfiguration import SCDynamicStoreCopyConsoleUser
username = (SCDynamicStoreCopyConsoleUser(None, None, None) or [None])[0]
if username is None:
# Exit if there isn't anyone logged in
sys.exit()
uid = getpwnam(username).pw_uid
subprocess.call(['/bin/launchctl', 'bootstrap', 'gui/{}'.format(uid), '/Library/LaunchAgents/com.company.example.plist'])

Unloading a LaunchAgent

launchagent_unload.sh
#!/bin/bash
# get console UID
consoleuser=`/usr/bin/stat -f "%Su" /dev/console | /usr/bin/xargs /usr/bin/id -u`
/bin/launchctl bootout gui/$consoleuser /Library/LaunchAgents/com.company.example.plist
launchagent_unload.py
#!/usr/bin/python
from pwd import getpwnam
import subprocess
import sys
from SystemConfiguration import SCDynamicStoreCopyConsoleUser
username = (SCDynamicStoreCopyConsoleUser(None, None, None) or [None])[0]
if username is None:
# Exit if there isn't anyone logged in
sys.exit()
uid = getpwnam(username).pw_uid
subprocess.call(['/bin/launchctl', 'bootout', 'gui/{}'.format(uid), '/Library/LaunchAgents/com.company.example.plist'])

The Python version may look more complicated, but is slightly more robust as it is retrieving the current username using Apple’s frameworks and I have also allowed for the script not to fail if there isn’t a user logged in.

Something something commercial, something something opensource

Thanks to everyone who came to my session at MacAd.UK. I will link the video here when it is available, but in the meantime here are the slides.

Pocket Mac admin's guide to London

It’s less than three weeks now until I give my talk about our journey from commercial management tools to open source nirvana at MacADUK - and whilst I’m very excited about the conference and all the fantastic speakers, I know some of you are equally as excited about visiting London. So, here’s my pocket Mac Admin’s guide to London (views are my own etc etc)

Read more →

Imagr with target disk mode

Imagr is a great tool when you’re wanting to deploy machines quickly in your office. But sometimes you will want to deploy machines when you’re in a smaller remote site, or a site where security concerns mean you can’t have servers. Imagr is flexible enough to handle this, and with a little creativity, we can deploy at these sites as easily as we can at our offices with NetBoot.

Setup

The first thing you are going to want to do it get your Imagr repo onto your own machine. I would recommend having your repo in a central repository - git fat works well, so does putting everything on an S3 bucket and using the aws cli tools to sync it down. We use an S3 bucket, as we can ship read only credentials to the machines that are performing the imaging. This guide will assume you are using S3, but you can substitute that aspect for whichever method you wish to sync your files.

Read more →