GitLab SSH

July 16, 2018

Over the weekend I migrated my home server from an aging Mac mini with far too little RAM to a new server in a handmade wooden case.

Arguably, the bigger part of the move involved migrating all of the various services to Docker to help make management & backups easier. I settled on using nginx-proxy to handle the reverse proxy and SSL for all of the containers, and for the most part everything went smoothly with one big exception: SSH for GitLab.

The whole point of Docker is to lock everything down as much as possible. Most of the containers1 don’t have ports bound to the system and are only accessibly by their own Docker network. This includes port 22, which is an important one.

There are a few obvious options, all with problems:

The Solution

Figuring other people had to have run into this problem before I did some searching around and finally found an article by someone who had the same list requirments I did.

The author did some excellent sleuthing to figure out that you can set up a git user on the host to forward the SSH requests the to git user in the container. The guide is fairly straight-forward and explains the reasoning behind each step, however there were a a couple of small problems I ran into.

Authentication Refused

The most perplexing issue was this line in /var/log/auth.log:

Authentication refused: bad ownership or modes for directory /srv

I’ve seen the error before, but for the .ssh directory or specific files, but never on a top-level directory.

It turns out sshd is resolving the symlink and traveling up the hierarchy to the root of the drive, which can’t have such limited permissions.

After a bit of trial and error the the solution I came up with is to hard link the files in .ssh so sshd is happy with their paths:

ln /srv/gitlab/data/.ssh/* /home/git/.ssh/

This allows both the GitLab container to update the contents as keys are added or removed while keeping the paranoid sshd happy.

  1. The Unifi Controller interacts heavily with the local network, thus requiring a bunch of bound ports. [return]


July 7, 2018

Introducing Capturebot

June 1, 2018

I’ve been working on a new application, called Capturebot, for the last few of months, and it’s finally ready for a public beta.

Capturebot is an image collection validator. It works a lot like a smart album or Finder search, but instead of filtering images for viewing it tests whether collections contain matching images. Capturebot monitors a session in real time and shows what collections have images that meet all of the given criteria. Unlike a smart album, Capturebot lets you drill down into each part of the profile to see how many images pass.

Validations can be set up for ensuring the correct number of selects, testing for an exposure bracket, using regex to match specific file name formats, and much more.

If you’re on a larger set, or are sharing the computer with an art director, the validation session can be shared over the network. This allows you to view the validation on the shoot machine from another computer.

If you’d like to help test go download a copy of Capturebot and be sure to send in any feedback you have.

Code Signing Woes

May 25, 2018

Code signing never goes right for me. I feel like I have a pretty simple process:

  1. Export
  2. Sign with Xcode
  3. Make and sign a DMG
  4. Throw it up on a server
  5. Download it for testing
  6. 🤬

The next obvious step to to Google for the correct incantations of codesign1 and spctl2 to verify that nothing was corrupted during the upload or download. Occasionally I’ll find an error, but usually the app bundle passes without issue.

As it happens, however, the error message is a little misleading. The files on disk are in fact correct, however at runtime the application runs afoul of Gatekeeper. Looking in Console reveals the true culprit:

File /Volumes/Capturebot/ failed on rPathCmd /Applications/

The application is attempting to load a file from outside of its bundle. In this case, a framework built with Swift Package Manager is linked against Xcode’s Swift library rather than the bundled copy.

The fix is straight forward. A quick trip to Build Settings to add @executable_path/../Frameworks to Runtime Search Paths resolves the problem.

  1. codesign --verify --deep --verbose=4 [return]
  2. spctl --assess [return]


February 28, 2018

Apple’s newest product, the HomePod, is quintessential Apple industrial design: minimal as it can be while still having corporeal form. Given that last fact, I decided it would be the perfect product for a contrived little room scene. You know the one: everything perfectly arranged with tasteful design that only exists in a Restoration Hardware catalogue.

As it happened I had access to a nice looking set the weekend the HomePod launched, so all I had to do was show up make it look good and click away.

The star of any photo shoot: the ColorChecker

The star of any photo shoot: the ColorChecker

Unfortunately, I am not a prop stylist. I can get away with a tabletop set and some books, but propping a whole room (especially when you don’t have a whole room’s worth of props) turns out to be a little tricky. I fought the exceedingly minimal industrial loft style for quite some time before deciding to pull the plug and try for an even more minimal style.

The acoustically transparent foam is a moire magnet, which makes downsampling fun.

The acoustically transparent foam is a moire magnet, which makes downsampling fun.

I still wanted the hard light from the room scene, but instead of long shadows from a simulated late-in-the-day sun I kept the shadow small and close.


I always find it fun peel back the base layer of any photo to see all that was done to it.1

Most of the work went into cleaning up all of the damage on the painted stripe in the foam core. Only a hint of the negative fill was needed to add some separation on the left edge.

  1. It’s like a far less interesting version of the ILM Star Wars effects reels. [return]