Cycling X-Clacks-Overhead output in Mastodon

“We keep that name moving in the Overhead,” he said, and it seemed to Princess that the wind in the shutter arrays above her blew more forlornly, and the everlasting clicking of the shutters grew more urgent. “He’d never have wanted to go home. He was a real linesman. His name is in the code, in the wind, in the rigging, and the shutters. Haven’t you ever heard the saying ‘Man’s not dead while his name is still spoken’?”

~Terry Pratchett, “Going Postal.”

X-Clacks-Overhead is a “standard” HTTP header, of a sort, that serves as a digital memorial to people system administrators wish to commemorate. Mastodon’s glitch-soc fork actually has, as part of its default configuration, an X-Clacks-Overhead preconfigured to Natalie Nguyen. This is set up in config/environments/production.rb.

I have a few commemorations of my own I’d like to do, but I’m not at all interested in pulling Natalie’s off my wire. At the same time, I recognize there’s a bit of a challenge to adding an unlimited number of commemoriations; sooner or later, I’m going to end up with a very large header.

I’ve hacked my Mastodon node to select a random name from an array for each emitted response. In this way, I can grow my list to arbitrary length, should I choose to do so. This involved adding some middleware to intercept outgoing responses and stitch in a new header.

Shoutout to Akshay’s Blog for helping me get oriented on Rails middleware.

About Rails Middleware

The Rails middleware API (technically, the Rack middleware API) is relatively straightforward. It involves creating a class that supports two things:

  • an initialize(app) method, where you get an app passed in. Your app should retain this.
  • a call(env) method, which will be called when it is time to process a request. call acts as a daisy-chain: you can manipulate the environment, allow the request to continue to be processed by calling @app.call(env), then alter the response by making changes before returning the response object (an array of [status, headers, response]).

So the change we’ll do is relatively straightforward: we’ll create a new middleware and attach it to the Mastodon app to choose X-Clacks-Overhead values.

Let’s start with the new file.

lib/x_clacks_overhead.rb

# frozen_string_literal: true

# Middleware selects an elemnt from @header_names to vend as the
# X-Clacks-Overhead header. Replaces the current header with the selected one.
class XClacksOverheadMiddleware
  def initialize(app)
    @app = app
    @header_names = [
      'Theodore Tomczak',
      'Theresa Tomczak',
      'Natalie Nguyen',
    ]
  end

  def call(env)
    status, headers, response = @app.call(env)
    headers['X-Clacks-Overhead'] = "GNU #{@header_names.sample}"
    [status, headers, response]
  end
end

Nothing too fancy and there is room for improvement; we should be pulling @header_names from a config instead of requiring changes to the implementation to add names.

Now to use these, we just need to patch up the main application, which is at config/application.rb.

--- a/config/application.rb
+++ b/config/application.rb
@@ -52,6 +52,7 @@ require_relative '../lib/active_record/database_tasks_extensions'
 require_relative '../lib/active_record/batches'
 require_relative '../lib/simple_navigation/item_extensions'
 require_relative '../lib/http_extensions'
+require_relative '../lib/x_clacks_overhead'

 Dotenv::Railtie.load

@@ -204,6 +205,7 @@ module Mastodon
     config.middleware.use PublicFileServerMiddleware if Rails.env.development? || Rails.env.test? ||
ENV['RAILS_SERVE_STATIC_FILES'] == 'true'
     config.middleware.use Rack::Attack
     config.middleware.use Mastodon::RackMiddleware
+    config.middleware.use XClacksOverheadMiddleware

     config.to_prepare do
       Doorkeeper::AuthorizationsController.layout 'modal

Finally, we can go ahead and patch out the default value in config/environments/production.rb

--- a/config/environments/production.rb
+++ b/config/environments/production.rb
@@ -152,7 +152,6 @@ Rails.application.configure do
     'X-Frame-Options'        => 'DENY',
     'X-Content-Type-Options' => 'nosniff',
     'X-XSS-Protection'       => '0',
-    'X-Clacks-Overhead'      => 'GNU Natalie Nguyen',
     'Referrer-Policy'        => 'same-origin',
   }

After saving all changes and doing sudo systemctl restart mastodon-web, we can reload the UI and confirm that we’re now getting different values for X-Clacks-Overhead.

The X-Clacks-Overhead now reads ‘GNU Theodore Tomczak’

Who Cares?

There’s certainly a train of thought that says this is frivolous. At the end of the day, who cares what the X-Clacks-Overhead says? It’s invisiible metadata to almost everybody; nobody sees HTTP headers, not when the system is working.

I can kind of see that point of view. Except…

I never met Natalie Nguyen. She died before I ever stood up this server, far away from here. She went by ‘Tipsy Tentacle’ and was known by many online and in real life in the Mastodon community. She was gone way too soon. And I only know any of this because glitch.social’s maintainer added her name to the Clacks header and I stumbled across it while wrapping my head around how Mastodon works.

Theodore Tomczak worked for a steel company. As a young man, he was drafted into World War II and joined the Allied forces in Anzio. He was the father of four children and a devoted husband. He could be cranky and had a temper sometimes. He once dressed as Santa Claus and paraded around the house after dark putting presents under the tree; one of his grandchildren saw him and believed in Santa until high school.

Theresa Tomczak married a poor young man whom she loved when he survived the war. She managed a team of technicians for the state retirement program. She was a faithful believer in Christ who almost never had a bad word to say about anyone she knew. She was blessed with seven grandchildren in her later years. She once taught one of her grandsons that there are some things in life you can’t fix, no matter how hard you worry about them, and when that happens the best thing to do is to fix something you can, even if it’s as simple as emptying the dishes in the sink.

We are, all of us, brief creatures, and the ripples we make in our lives grow thinner with the passage of time. It is likely, because this is how history goes, that there will come a day that nobody remembers any of this.

But it is not today.

Comments