idkfa - the activitypub everything app proxy
So you’re all in on ActivityPub. You’ve got your microblog, your long form blog, your bookmarks, your photo blog, your video blog, your discussion forum, etc. Each is a different service with a different identity. As more services catch on, users yearn for a single everything app solution to replace this multitude.
Alas, there’s a lot of coding involved in writing the everything app. Doing everything means code that does everything. Fortunately, all this code has already been written. The bad news is it’s split among the aforementioned half dozen services, each with a different language, runtime, interface, etc.
The good news is all these services speak a common language, ActivityPub, and thus we have a shared interface with which to combine them. Enter idkfa, the ActivityPub everything app proxy.
This was supposed to be a fun project to learn swift. That didn’t work, so after aborting and rebooting, it ended up being node javascript. The only dependency is a bundled lodash.js, no npm.
background
ActivityPub supports much more than microblogging. You can post long form articles, or videos, photos, links, whatever. You can of course post all these things as mere status updates, but the experience is better using dedicated services and interfaces, leading to an explosion in services and identities. There’s three forms of complexity to consider.
One, there’s the reader/viewer experience. Checking in on a half dozen services requires opening a half dozen browser tabs.
Two, there’s the writer/poster experience. Authoring new content requires picking which tab to post it to.
Third, there’s the social following problem. What in the heck do you put on your business card when you’ve got more names than the wolf man?
solution
Solving the first two problems is similar in scope. Which is to say enormous. A single application that lets the user meaningfully compose and post notes and articles and videos is extremely complicated. The existing ActivityPub applications are each optimized for their own niche. And there’s considerable variation among them, even in domains like microblogging.
I think it’s a mistake to jam everything together. What if the microblog interface I like doesn’t have a good video player? Or it’s poorly organized for photos? I would be pretty disappointed if I were forced to choose between a combination vi/mplayer or emacs/ffmpeg or nano/vlc. We should instead treat AP servers like plugins, composing a set of servers we like.
So this is where idkfa comes in. Users are free to select the features and interfaces they like for each form of content. But we solve the third problem, of fractal identities. You now have a single convenient identity to put on your business card.
I’m aware of a few prior projects which attempted to solve this problem with auto repeaters. I follow your collation bot, which then sends an Announce (share) for every activity each of your various actors performs. Regrettably, this is a bit messy in the interface for each user, who see everything as a share of a content from some stranger.
Instead, idkfa rewrites activities, interposing itself between servers.
split horizon
idkfa works by creating a two sided proxy. The frontside is public internet facing, and presents a single AP actor. The backside is intranet facing, communicating with a cornucopia of mastohonkoma servers. As activities pass through idkfa it rewrites them to ensure the actor and id fields are consistent. It also handles Follow requests.
The frontside is not magic. It looks like a normal server that sends activities. You can follow it. It can follow you. Previous activities can be fetched. There’s little indication this is anything but a normal server, except the web view is very spartan.
The backside is magic. This is where most of the logic to forward and rewrite activities lives. Most notably, it intercepts all requests made by the mastohonkoma servers, even those to other servers. In this way, idkfa can unify their cacophony into a single stream.
examples
The outbound case is simplest to explain. Whenever idkfa receives a Create on the backside inbox, it replaces the actor with its own, and the id field with a newly generated value. Then it sends this activity to everyone who has followed the frontside actor.
From the outside, you see only a single actor, generating a stream of activities that are unusual only in the sense that Note and Article and Video types are not usually generated by the same software.
The inbound case is much the same, in reverse. When idkfa receives a Create on the frontside inbox, it looks at the sending actor. Then it forwards the activity to the subset of inside servers that are following that actor. We don’t forward every activity to every inside, since they’re probably not expecting it and won’t do much with activities from unfollowed actors.
following
A few more details about following. Following on the frontside works as expected. A Follow request is received, accepted, and then the actor is added to the user’s list of followers.
Following on the backside is a bit different. When a follow request is received, it is presumably for some actor not on this server. We first check if the idkfa actor is already following the target. If so, we simply add the requesting mastohonkoma actor to our following list. If not, we also send a Follow activity from idkfa to the target.
From the outside, you are transparently following all the inside servers at once. From the inside, each server thinks it is following an external actor, but really it receives all activities from idkfa.
security keys
The basis for authentication in ActivityPub is http signatures, using a (usually RSA) key in the actor object. When idkfa talks to an internal server, it needs to impersonate external users, signing the forwarded activities. In order to accomplish this, we also proxy GET requests and watch for objects with public keys, then we replace them with our own key. Inspecting the database of a mastohonkoma server on the inside will reveal that all saved public keys are exactly the same, although the software does not notice.
setup
The setup requirements for the frontside are the typical for any simple web app.
The backside only operates in a particular environment. First, all the mastohonkoma servers need to have their outbound requests redirected to localhost, via pf or similar. Then the TLS interceptor needs to craft certs on the fly, or mastohonkoma needs to have cert checking disabled. This is a bit complicated. I wanted to handle this more transparently in idkfa, but the interceptor was the first feature dropped due to time constraints.
There’s no reason why any of this is beyond the ability of mortals to setup, but if you installed mastohonkoma by copying commands off a wiki, it will be your own fun learning challenge.
not solved
As mentioned above, idkfa doesn’t solve the problem of multiple interfaces for multiple types of content.
The web interface it presents is very basic. The idea here is that you, and by extension your followers, are all in on ActivityPub and would only be viewing content via your home instance anyway.
There’s still some leakage of backend details. Actors are rewritten in the obvious places, but hostnames and URLs appear as followers collections in addressing, attachment URLs, etc.
status
It seems to work in isolation. I haven’t switched to using it for real because I’m already happy using a half dozen different services, and it would be awkward at this point to change that. I also really don’t like javascript?
I initially wanted a fun project to explore swift, so I picked an area I’m familiar with. When that didn’t pan out, I felt I should push through anyway, because the concept itself is still interesting. I set aside a certain amount of time (September) to get this done, and wasted half of it, so it’s a bit late.
Some of the headline features, like TLS transparency, seemed like exciting ways to learn how to get things done in swift. A lot of that got cut from the project with the language switch.
The code is nevertheless available. I believe the central idea is workable.
Tagged: activitypub