Using Nix to consolidate an environment

I use thumbsup to manage my gallery site. Since the site is entirely static, I use exiftool to store the description and tags as metadata in the images themselves. To simplify managing the metadata I wrote a small Symfony application that writes and updates the metadata from CSV files.

The workflow is straightforward enough, but the code deployment on my laptop looked like a messy bedroom. The Symfony application lived in one directory. My fork of thumbsup, supporting custom album covers, was hanging out within .nvm, tied to given versions of NodeJS. My customization of the cards theme lived in a separate directory, passed by argument to the Symfony application. This was messy and unsustainable.

I’ve used Nix for several other projects, and this felt like a good use case for getting everything in once place. In this case, I would centralize in the Symfony directory. First step: adding all the relevant packages:

Read More

The Ann Arbor Railroad in Mt. Pleasant

I’m back in Mt. Pleasant for Thanksgiving and after watching the Lions dispatch the Bears (not handily, but never mind that) I went out for a short bike ride through Mill Pond Park. The main bike trail comes out at Broadway opposite the old Ann Arbor Railroad station, now the Mountain Town Station brewery and restaurant. I’ve photographed it many times over the years, but tonight the fading light felt really special.

Once a station; now a restaurant

I grew up in Mt. Pleasant, Michigan, a county seat and college town of about 20,000 people that hasn’t seen a passenger train in over 70 years (and counting). We had two railroads: the Ann Arbor Railroad main line, running northwest from Toledo, Ohio, up to Frankfort, Michigan, and a branch line of the Chesapeake and Ohio Railway (originally Pere Marquette), running northeast from Mt. Pleasant up to Coleman.

Read More

A warehouse in Albany

This past week Amtrak suspended travel between Albany and New York because of a deteriorating parking garage in Hell’s Kitchen. Service has resumed, but it’s a reminder of how fragile infrastructure can be in the United States. This is also the second time in about a year that a privately-owned building threatened the Empire Corridor, and the last time it happened it nearly wrecked my vacation plans.

Back in August 2022, I needed a break, and I drew up a plan to visit my sister up in northern New York and a friend in Boston. I’d take the first Burlington-bound Ethan Allen Express up to Middlebury, where my sister could pick me. After a few days, take the Essex-Charlotte ferry over to Vermont, and take the Ethan Allen Express back down to New York City. A day or two in Brooklyn, then an Acela round-trip to Boston.

The first portent of doom was waking up to see a missed call from Amtrak. Amtrak doesn’t call me unless there’s a problem with my train:

Read More

Remembering Mark Hoolihan

Mark Hoolihan passed away on August 24, 2019, at the age of 49. I didn’t know him well. He was an adjunct at Kalamazoo College my senior year. I took one class, an evening seminar in Jewish History.

Winter terms at Kalamazoo were rough. I imagine they still are. The college was on quarters (trimesters); the winter term started the first week of January and ran ten weeks, plus exam week. Spring break came after, followed by the spring term. January and February in Michigan are cold and dark. I can remember a February where it snowed two days out of three and the sun never broke through the overcast.

The winter of 2005 I had to overload and take four classes instead of the usual three. I had a political science course (“Modern liberalism and its critics”), Advanced German, French Revolution, and the Jewish History seminar with Hoolihan, which met in the evenings.

Read More

Piecing together Indian Trails ticket pricing

I’ve written before about the various challenges I have reaching Mt. Pleasant, Michigan, from the East Coast. I never wrote it up, but back in January 2022 I went the long way round, taking Amtrak to Kalamazoo via Chicago, then Indian Trails buses to Grand Rapids, Lansing, and finally Mt. Pleasant. It worked, but looping through Chicago effectively adds a day to the itinerary.

Since then, Indian Trails has stopped interlining with Greyhound and started interlining with the Trailways system. Greyhound is in a real race-to-the-bottom ever since Flix bought it, but that’s another matter. I figured I’d give the Toledo connections another look. I’ve resisted mating up Amtrak’s Thruway Motorcoach with the Lansing-Mt. Pleasant bus because it meant a 4-5 hour layover in Lansing.

Good and bad news here. The good news is that there is Barons Bus/Indian Trails itinerary between Toledo and Mt. Pleasant. Eight hours and two transfers (Detroit and Lansing). The departure time from Toledo is 9:50 AM, which is a healthy buffer for a delayed Amtrak train. The bad/weird news is a bizarre pricing overage from the Trailways ticketing platform.

Read More

Managing your WordPress revisions

We had interesting problem where the front page of a site in our multisite couldn’t load in the editing interface. The root cause was that the page had too many revisions and PHP ran out of memory. The presentation was a little unusual–no rich text editors displayed on the page. We used trepmal’s wp revisions WP-CLI plugin to resolve the immediate issue.

The problem

Our main multisite is built on Advanced Custom Fields with the Classic Editor. The individual site in question dates to 2016, and had over 400 revisions when we started having problems with it. We attach the rich text editor to the content areas toward the end of the rendering process. The reported issue (that we verified) is that the rich-text editors weren’t rendering on the visual pane and that the text pane wasn’t loading at all. The text was still in the textarea and selectable, although not visible (white on white).

Read More

A day at the train show

It’s the second weekend in November which means it was time for the Allentown Train Meet. These train shows are a mecca for train enthusiasts of all stripes. The lion’s share of the vendors are selling model railroading supplies, but there are plenty of dealers selling books, videos, or memorabilia. As always, there were several live model railroad setups going. I didn’t see an N scale one this year, which was a little disappointing. I didn’t buy any china this year, but I did find a good mix of stuff for my layout, books, and videos.

Media

The Lehigh Valley NRHS chapter had a table and I picked up two short histories, History of the Lehigh Valley Transit Company and Short Trolley Routes in the Lehigh Valley. They threw in a back number “Lehigh Lines”, their newsletter, for free. I’m not a member of the chapter though I probably should be. I have another book in this series, the history of the Lehigh & New England Railroad edited by Randolph Kulp, and I was impressed with the quality. It can be hard to find good information about the interurban era in the United States.

Read More

Nix flake with Node and PHP

Brief note on a nix flake that supports Node 20 and PHP 7.4. My use case is deploying an AWS CDK project that supports a Moodle 3.11 environment. I’m not version-limited on the Node version for CDK, but I need to start with PHP 7.4 to support the Moodle package code, though I’ll be moving to PHP 8.1 soon.

Here’s the flake.nix in its entirety:

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
38
39
40
41
42
43
44
45
46
{
description = "Example JavaScript development environment for Zero to Nix";

# Flake inputs
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs?ref=nixos-unstable";
phps.url = "github:fossar/nix-phps";
};

# Flake outputs
outputs = { self, nixpkgs, phps }:
let
# Systems supported
allSystems = [
"x86_64-linux" # 64-bit Intel/AMD Linux
"aarch64-linux" # 64-bit ARM Linux
"x86_64-darwin" # 64-bit Intel macOS
"aarch64-darwin" # 64-bit ARM macOS
];

# Helper to provide system-specific attributes
forAllSystems = f: nixpkgs.lib.genAttrs allSystems (system: f {
pkgs = import nixpkgs { inherit system; };
});
in
{
# Development environment output
devShells = forAllSystems ({ pkgs }: {
default = pkgs.mkShell {
# The Nix packages provided in the environment
packages = with pkgs; [
nodejs_20 # Node.js 18, plus npm, npx, and corepack
yarn
phps.packages.${system}.php74
phps.packages.${system}.php74.packages.composer
];

shellHook = ''
yarn
npx aws-cdk --version
php -v
'';
};
});
};
}

Read More

This blog post was written with Hexo and Nix

A few weeks ago I was at HighEdWeb 2023 in Buffalo and caught a talk (“Maybe some other time Docker: Fast, declarative and reproducible developer environments using Nix”) from Jason Woodward about Nix. Nix is many things, including an OS, but he focused on Nix-the-package-manager and that’s what I’m going to (briefly) discuss here.

To grossly oversimplify, Nixpkgs is a collection of tens of thousands of packages precompiled for various platforms. Each version of each package can be referenced by hash. Using a nix flake, you can specify which packages should be associated with your project. The nix develop command will then use path magic to load the specified packages into your shell. When you exit from the shell the paths are unloaded.

I moved this blog to hexo about a year ago. My authoring environment needs a few things: a reasonable version of node, hexo server running in the background to serve pages, and hexo generate --watch to catch changes as I write. My old process involved manually kicking those processes off. Before I could do that, I had to run nvm use to leverage the .nvmrc file at the root of my project directory to ensure that I had the correct version of node active, including the global reference for hexo.

Read More