Edent@mastodon.social
Edent@mastodon.social

🆕 blog! “ActivityPub Server in a Single PHP File”

Any computer program can be designed to run from a single file if you architect it wrong enough! I wanted to create the simplest possible Fediverse server which can be used as an educational tool to show how ActivityPub / Mastodon works. The design goals were: Upload a single PHP file to the server. No […]

👀 Read more: shkspr.mobi/blog/2024/02/activ

#ActivityPub #mastodon #php

|
Embed
Progress spinner
In reply to
davidhall
davidhall

@Edent I will certainly be taking a look at that!

Hats off 🎩😜

|
Embed
Progress spinner
ahnlak@kavlak.uk
ahnlak@kavlak.uk

@Edent great stuff; I'd seen the previous Symfony-based iteration on Github, and my first thought was "I bet you can get that down to a simple single file install" 🙂

|
Embed
Progress spinner
julian@fietkau.social
julian@fietkau.social

@Edent Nice work! It looks similar to my own self-study one-file ActivityPub server in Python. I think the structure of the protocols lends itself to implementing single-actor servers as a learning experience.

I know you're saying it's quick & dirty in some ways, but if it's intended as a learning tool for others, do you want feedback on it? There's one bad assumption in there that I think would be better if it was cleaned up.

|
Embed
Progress spinner
Edent@mastodon.social
Edent@mastodon.social

@julian all feedback welcome!

|
Embed
Progress spinner
julian@fietkau.social
julian@fietkau.social

@Edent Then I'll make it short: The assumption that a server has a shared inbox at /inbox does not generalize, as even the existence of a shared inbox is not mandated by anything.

What you'd need to do is when someone follows, you fetch their actor data and store at minimum their inbox and/or shared inbox.

For sending, I build a set of all shared inboxes that occur more than once, and use the individual inboxes for the rest.

|
Embed
Progress spinner
Edent@mastodon.social
Edent@mastodon.social

@julian interesting! Thanks.
How difficult do you think that is to implement? I'm wary of making something too complicated - but I'd like to point to a simple solution if possible.

|
Embed
Progress spinner
julian@fietkau.social
julian@fietkau.social

@Edent In my code I do the "fetch actor on follow and store inboxes" strategy I mentioned, and then at the point I want to send a post, I do this:

fietkau.software/DailyRucks.gi

The code is a bit opaque. I keep a map of shared inboxes to individual inboxes that have already been added to the send list, and if a shared inbox appears a second time, I remove the previous individual inbox from the send list and add the shared inbox.

|
Embed
Progress spinner
oook@im-in.space
oook@im-in.space

@Edent nice, I was thinking of writing a simple #activitypub server for a single account that would use an #rss xml file as a source. Pretty sure this has already been done anyway.

|
Embed
Progress spinner
janboddez@indieweb.social
janboddez@indieweb.social

@oook Like this? github.com/dariusk/rss-to-acti 😉 @Edent

|
Embed
Progress spinner
Edent@mastodon.social
Edent@mastodon.social

By popular demand, my demo ActivityPub server now also shows how to attach images to a Note.

View @example for an example.

Get the code at gitlab.com/edent/activitypub-s

|
Embed
Progress spinner
Edent@mastodon.social
Edent@mastodon.social

But the one thing I can't figure out…

When I mention "@ example @ example.viii.fi", it shows as:

@example

Which links back to the user's website, rather than showing their info within Mastodon.

Which arcane #ActivityPub or #MastodonAPI field do I need to have in my JSON file to fix this?

|
Embed
Progress spinner
robb@social.lol
robb@social.lol

@Edent When I hit it in Ivory I see the info loaded

|
Embed
Progress spinner
Edent@mastodon.social
Edent@mastodon.social

@robb nice! Would you mind following (temporarily) and telling me if it backfills the previous posts?

|
Embed
Progress spinner
robb@social.lol
robb@social.lol

@Edent followed but I can tell you now it won’t.

My instance doesn’t know about those previous posts, only ones that have been sent after I’ve followed.

|
Embed
Progress spinner
fallenhitokiri@social.screamingatmyscreen.com
fallenhitokiri@social.screamingatmyscreen.com

@Edent @example I think it works as expected using Ivory on iOS?

@example profile opening in ivory

|
Embed
Progress spinner
robb@social.lol
robb@social.lol

@Edent It does fill in the post number and other info, but clicking on posts won’t show anything. For that, I need to visit the profile

|
Embed
Progress spinner
Edent@mastodon.social
Edent@mastodon.social

@fallenhitokiri @example
Hmmm. It really should show an avatar image as well.
Something else to look into.

|
Embed
Progress spinner
pixelcode@social.tchncs.de
pixelcode@social.tchncs.de

@Edent Sad that the site isn't particularly Tor-friendly :/

When visiting the URL from OP, I had to solve several Google reCAPTCHAs because the server considered the Tor exit node to be spam

|
Embed
Progress spinner
jelemux@social.tchncs.de
jelemux@social.tchncs.de

@Edent in the client I use (Megalodon), it opens correctly. However, I get what you're discribing with some posts from users of other fedi servers. I did not yet make the effort to find out which ones, though.

|
Embed
Progress spinner
Edent@mastodon.social
Edent@mastodon.social

@jelemux interesting. Thanks 🙂

|
Embed
Progress spinner
Edent@mastodon.social
Edent@mastodon.social

@pixelcode it's my website. I'm not sad about it at all.

It was the only way I could cut down on spam & abuse. My website is available on the open Internet.

|
Embed
Progress spinner
elbosso@mastodon.social
elbosso@mastodon.social

@Edent also seems to work ok with mastodon on android

|
Embed
Progress spinner
evan@cosocial.ca
evan@cosocial.ca

@Edent good for you!

|
Embed
Progress spinner
chris@galegale.online
chris@galegale.online

@Edent I've often wondered how hard would it be to make a PHP port of Mastodon. Setting up the Ruby version can be a pain.

|
Embed
Progress spinner
chris@galegale.online
chris@galegale.online

@Edent is there an article anywhere that shows / explains the full workflow that a mastodon server does?

|
Embed
Progress spinner
Edent@mastodon.social
Edent@mastodon.social

@chris best place is probably activitypub.rocks/

|
Embed
Progress spinner
mapache@hachyderm.io
mapache@hachyderm.io

@Edent @example check this out ... maho.dev/2024/02/a-guide-to-im

TLDR; Depends on who implements the actor, the uri/url field is used by mastodon as the profile one. Like @blog

|
Embed
Progress spinner
Edent@mastodon.social
Edent@mastodon.social

I've now added HTTP Message Signature verification to my demo #ActivityPub server.

gitlab.com/edent/activitypub-s

Currently the entire server is a 32KB single PHP file.

Feedback welcome! It is designed to be a learning tool to show how all the different parts of ActivityPub work.

|
Embed
Progress spinner
Edent@mastodon.social
Edent@mastodon.social

OK! My tiny #ActivityPub server can now follow users from other instances!

Still under 40KB of well-documented PHP.

gitlab.com/edent/activitypub-s

You can follow and message the test user a @example

|
Embed
Progress spinner
rimu@mastodon.nzoss.nz
rimu@mastodon.nzoss.nz

@Edent I enjoyed the little jokes in the comments :)

Looks like you've got the hang of it. It's all just learning the quirks of different implementations, now!

|
Embed
Progress spinner
AlanBell@mastodon.ie
AlanBell@mastodon.ie

@Edent @example my follow request is awaiting approval. Is this a feature or something gone wrong?

|
Embed
Progress spinner
dan@m.danq.me
dan@m.danq.me

@Edent @example "Adequately". Nice. 😁

|
Embed
Progress spinner
milosz@adventurousbeastie.eu
milosz@adventurousbeastie.eu

@Edent @example I liked the part about the requirements. 👍

|
Embed
Progress spinner
Edent@mastodon.social
Edent@mastodon.social

@AlanBell If you refresh, it should show as approved.
I think it's because I have the profile saying it is manual - but it isn't.

|
Embed
Progress spinner
Edent@mastodon.social
Edent@mastodon.social

@AlanBell scratch that - it looks like I couldn't retrieve your public key.
Let me have a dig.

|
Embed
Progress spinner
Edent@mastodon.social
Edent@mastodon.social

@AlanBell I *think* it is because @masto_ie_support uses authorised fetch. So my server can't retrieve your public key without signing the request.
I'll see if I can adjust that on my side.

|
Embed
Progress spinner