Hosting an AASA File on Your Ghost Blog

Hosting an AASA File on Your Ghost Blog
Hosting an apple-app-site-association file via your Ghost blog

I recently started blogging again after a long hiatus. The only things I really cared about were:

  1. I need to be able to self-host it.
  2. It needs to not be WordPress.

And so I discovered Ghost, which has been mostly great. The lack of a user interface for configuring email is silly. And the freely available themes are less than stellar. But I'm not paying for anything. Anyway.

The topic at hand is hosting the apple-app-site-association file on your self-hosted Ghost-infested domain. Let's dig in.

Let's say you're using Ghost on your domain (self-hosted), and Ghost is the actual web server (you don't have nginx sitting in front of it), then by all accounts it is impossible for you to host a .well-known/apple-app-site-association file. I asked Grok and ChatGPT to help me figure out a way (in addition to a bunch of web searches I did myself). The closest I came was to change the routes.yaml file, but Ghost requires all requests to end with a /, and that is not compatible with what your app will require (no trailing slash). Close, but not quite.

Of course, if you are using nginx, then you can just pop the apple-app-site-association file in Ghost's content/files/ directory (or wherever) and then do a rewrite rule (not a redirect rule!), and you're golden.

location ~ ^/\.well-known/apple-app-site-association$ {
    rewrite ^ /content/files/apple-app-site-association break;
    types {}
    default_type application/json;
}

No such luck in my case though, because I'm not using nginx for my blog. I've got Cloudflare handling HTTPS termination, so Ghost can function as a simple HTTP web server. I didn't want to complicate matters by putting nginx in the mix.

Because Cloudflare sits between the internet and my self-hosted Ghost server, I was able to make use of their Rules system to implement something similar to what one can achieve with nginx. I created a rewrite rule that matches a target path of:

/.well-known/apple-app-site-association

which is what your app is going to request, but which Ghost cannot serve, and I rewrite it to:

/content/files/apple-app-site-association

Much like the nginx rewrite rule. The only difference I've noticed between this Cloudflare Rule solution and the nginx solution is that it gets a generic content-type of application/octet-stream (which will probably still work fine) instead of application/json. For the sake of being able to go to sleep tonight and not be obsessing over details, I renamed the file in Ghost to include a .json extension and then updated the Cloudflare rule accordingly:

/content/files/application-app-site-association.json

And then Ghost adds the appropriate content-type to the response, and we're all good.

Both Grok and ChatGPT insist that there's no way to host a file without a trailing /, but surely – you think – each blog page has a bevy of css and js file references that don't end with slashes. Possibly part of the problem is that I can't host the AASA file from an arbitrary directory – it needs to be /.well-known/.... And if we want to host arbitrary files, they need to be in the Ghost content directory, which won't work for our AASA use case.


Unrelated, but worth sharing: Linus Torvalds is my spirit animal. Also, it's not an exact quote; more of a paraphrase. Source is here, which is an article based on a The Linux Foundation keynote presentation video.

Subscribe to A garage sale for your mind

Don’t miss out on the latest posts. Sign up now to get access to the library of members-only posts.
[email protected]
Subscribe