Git & SSH sitting in a tree…

I do work for a bunch of different clients, who variously use GitLab and GitHub. For many years I put up with the incessant problem of accidentally signing my commits as the wrong user. It’s just so easy to forget to set the right GPG key and email address when you just want to get on with a project. It’s not the end of the world, but it’s annoying.

Often the same thing goes for the SSH keys you use to push and pull from your git repo; it’s a bit too easy to be lazy and use the same SSH key across multiple clients, when a little isolation would be a good idea from a security perspective.

What if you could work some magic so that identities and GPG and SSH keys are set to the right values right from the start, for every project for each of your clients? Read on…

This whole setup reminds me very much of a post I wrote in 2009 (13 years ago!) on the “holy trinity” of DNS, TLS, and virtual host wildcards that allow you to dynamically host vast numbers of previously undefined sites without having to touch your web server config at all, a classic example of convention over configuration.

First of all let me introduce you to .gitconfig. This file usually sits in your home directory, so for me on macOS that’s /Users/marcus/.gitconfig. This file contains your global git defaults, and is an easy-to-read config file in an “ini” style (and no, those are not real values!):

[user]
    name = Marcus Bointon
    email = marcus@example.com
    signingkey = AC34DF5B434BB76
[github]
    user = Synchro
    token = f693251e52043a23fe5fbd955cff56ff
...

You’ll find lots of other sections in here, which you can read about in the git config docs. But we are only really interested in one option: includeIf. This directive conditionally includes another git config file into your settings, and one of the things you can make it conditional upon is the path to your project. This is useful. I typically set up my client’s projects in the macOS default Sites folder within my home directory. Each client gets a folder, and each of their projects lives within that. This provides a tidy location to put a separate .gitconfig file that can be applied to all of their projects. It ends up like this:

~/.gitconfig
~/Sites/
    client1/
        .gitconfig
        project1/
        project2/
    client2/
        .gitconfig
        project1/
        project2/

Each .gitconfig file only needs to include the differences from the defaults that are set in the primary config file that lives in your home dir. To set up the GPG signing key and email for all of their projects, the file would contain this:

[user]
    email = remotedev1@client1.example.net
    signingkey = 434BB76AC34DF5B

Back in our primary file, we would add this conditional statement to automatically pull in this extra config whenever git is operating in this folder:

[includeIf "gitdir:~/Sites/client1/"]
    path = ~/Sites/client1/.gitconfig

And that’s it as far as GPG goes – commits will now be signed with the key and email address that are specific to this client, so when you set up your next project for them, you won’t have to do anything to set it up; it’ll Just Work™.

But what about SSH? The chances are that your client will have asked you for an SSH public key to add to their repo to provide you with sufficient access, but setting the GPG key doesn’t do anything towards selecting an SSH key for that purpose. You could do that using environment variables (which can be quite annoying) before, but fortunately, git 2.10.0 added the core.sshCommand config option that allows us to specify the SSH command that git uses for file transfer operations, and that can include a -i parameter to select an SSH identity (and -C to use compression for a possible speed boost). Add this to your client’s .gitconfig file, using the path to your client-specific identity file (not the public key which has a .pub suffix) like this:

[core]
    sshCommand = "ssh -i ~/.ssh/id_ed25519_client1 -F /dev/null"

Side note: I do hope you’re using Ed25519 keys for SSH; they’re newer, smaller, stronger, and faster than RSA keys, and they’ve been supported in OpenSSH since version 6.5 in 2014, so if your server doesn’t support them, you probably have bigger problems, or maybe you’re just running RHEL… I hope you’ve seen the post-quantum features of OpenSSH 9.0 too. The SSH client config file (usually found in ~/.ssh/config) is also really useful for twiddling per-directory or per-server configs that you can just set and forget.

Once you’ve done that, your commits will now be signed using your clients’ GPG key, and pushed to their repo using their specific ssh key, and you won’t have to change anything when you start new projects for them, so long as you put them in the same folder.

“What about my IDE?”, I hear you ask. Not to worry, most IDEs use your system’s git and ssh configs, so all this should work just fine with PHPStorm, VSCode, etc.

While I’m sure some bright spark can make this even more dynamic to automate this across clients, I find new clients are rare, but projects turn over fast enough for this to be a real win for getting that first commit signed and pushed correctly, first time.

The Good Ship Laravel

I like writing songs about open source, but I’ve never actually released any or posted them publicly, mainly because my singing is fairly terrible, and trying to find others willing and able to sing about these things seems hard! I really liked “the Wellerman” sea shanty craze of 2021, I had a thought that I should make use of the the nautical theme that runs through a lot of Laravel’s nomenclature to write a shanty of my own, that wasn’t just another cover of the Wellerman. It also occurred to me that I could semi-speak the words (in a pirate voice of course!) instead of outright singing, and that made it feel a bit less daunting. I wrote the intro first, and I liked the storytelling aspect, though as intros go it’s quite long. The first verse came quite easily as I built a list of words and kind of ticked them off the list. The timing and rhyming structure is straight Limerick, which makes things very easy. The main melody was just the result of doodling on the keyboard for a bit. I was pleased with the sailor/Taylor rhyme for the chorus, but it took me ages to come up with the rest of it. I had several failing attempts at a melody for the chorus, eventually just singing something that the words fitted, and then turning that into an accordion line, then building out everything else around it.

The instrumentation was very simple – it’s a sea shanty so we need simple folk instruments – accordion and cajon, and then a plucked upright bass to fill it out. In the final chorus I threw in some lovely blatty brass and a bit of piccolo, since the top end was kind of empty.

The Logic Pro arrangement

I recorded the vocals for the intro in July 2021, but re-recorded them later for consistency. I sang the first (lowest) line of the chorus vocals, and then did something I’ve done before – copy the track, and then use Logic’s Flex Pitch editor to shift notes around to make harmonies, generally upwards, since I’d sung a low line to start with. Having found harmonies that worked, I then re-sang the new line, as a heavily edited one doesn’t sound quite right, especially when pitch shifts are quite large. I then repeated the process for a second time, giving me a three-part harmony for the chorus. Flex Pitch let me correct pitch, but also timing – the harmonies sound so much better when they line up in time too. The low line was only possible for me to sing because at the time I was recovering from COVID and a very nasty sore throat, so while I was feeling much better, my voice was much deeper then usual, and I could hit much lower notes! Overall I found the singing much easier than the other things I’ve tried to sing because it was pitched much more comfortably for my voice.

If you like this song, you might like to have a listen to my later creation, “Tailwind“.

Software & Hardware

  • Apple Logic Pro X
  • Behringer UMC404HD USB audio interface
  • Aston Element dynamic microphone
  • Adam Audio TR5V monitors
  • KRK RP10S subwoofer
  • Arturia Minilab Mk II MIDI keyboard
  • Behringer DSP8024 Ultra-Curve Pro (room correction)
  • Mackie Big Knob passive volume control

Instruments & effects

  • Accordion, cajon, upright bass, piccolo, seagulls and waves from Logic’s standard sample library
  • Brass section from Logic’s Studio Horns instrument
  • Rowing boat sample I found from some ancient soundfonts collection
  • iZotope RX7 noise reduction
  • SSL Channel Strip (EQ, compression)
  • Logic standard compressor, EQ, de-esser
  • Logic “Space Designer” reverb
  • One of Logic’s default mastering configs for final output
Intro:
I was cast adrift in development seas
a shiver of bugs a’circlin’ me
Naught but a pair of oars and my IDE
to keep my app from drownin’

I spied at last a distant sail
I signalled for ‘elp to that caravel
As she hove to I made out her name;
’Twas the good ship Laravel!

Verse 1:
Gather ye round my developers
and I’ll spin you a yarn most eloquent
A tale of passport and breeze,
socialite and jetstream
a cloud full of vapor and elegance

We’ve resources and models and more
Controllers and actions galore
Fortified with some rum,
and a sack of enums,
we’ll build an app clients will adore


Chorus:
Train your telescope on that far horizon
Don’t get marooned on development island
We’re gonna build an app so well
On the good ship Laravel

Get on board now, every sailor
dance to the tune of cap’n Taylor
You’ve never built an app so well as
On the good ship Laravel

Verse 2:

With livewire on top of your scripts
and laracasts dishing out tips
We’ve got the best pest
to chase the rats from your tests
and artisan helping you ship

The framework’s the star, that’s for sure
but there’s packages of treasure to explore
but the best bit’s the crew,
and you can join too –
everyone’s welcome aboard

Chorus2:
Train your telescope on that far horizon
Don’t get marooned on development island
We’re gonna build an app so well
On the good ship Laravel

Get on board now, every sailor
dance to the tune of cap’n Taylor
You’ve never built an app so well as
On the good ship Laravel
The good ship Laravel

An explanation for non-Laravel folk!

A shiver is the collective noun for sharks. An IDE is an integrated development environment such as PHPStorm or VS Code; think MS Word, but for programming. An app, in this context, is a web application built in PHP. Sail is the name of a Laravel feature for managing local development environments. A caravel is a 15th century Portuguese sailing boat, exactly the kind of vessel that a stranded pirate might encounter, and also the word that gave inspiration for Laravel‘s name. “Hove to” is a sailing manoeuvre used to more or less stop a boat by pointing the sails in opposing directions, very useful when picking up castaways. A yarn is a story, often nautical, and a thread, but it’s also the name of a Javascript package manager. Eloquent is the name of Laravel’s database abstraction layer. Passport, Breeze, Socialite, and Jetstream are all Laravel features for building authentication workflows. Real clouds are made of vapor, but Laravel’s serverless service is called Vapor, and runs in the cloud. Elegance? Well, it mostly rhymes with eloquent, and is something that any framework aspires to. Models, controllers, actions, and resources are all important parts of a typical web app built in an object-oriented style; I was planning to have a line about “plundering” to go with resources, but that didn’t make it. Fortify is another Laravel authentication feature, but rum is a traditional source of income for pirates, on top of its role in providing Dutch courage. Enums are a common programming language feature, but notable because they were added natively to PHP 8.1 recently. Telescope is an in-app debugging utility. Horizon is a queue monitoring extension. Cap’n Taylor is of course Taylor Otwell, the creator of Laravel. Livewire is a toolkit for building dynamic, interactive web interfaces for Laravel apps. Laracasts provides an amazing library of training material for Laravel and related technologies, and also a great forum. Pest is a relatively new system for building automated tests that Laravel uses. Artisan is a command line tool that helps automate numerous development tasks. The crew is Laravel’s development team, but also the enormous and diverse community of developers that make Laravel far greater than a typical framework – it’s home for many of us!