1. 46

    1. 24

      Okay, but it’s not a Mastodon instance. It’s a static ActivityPub instance that’s extremely Mastodon-compatible…

      1. 14

        It’s actually a lot closer to what I want: a way of publishing a static blog that makes it easy for Mastodon users to follow.

        The follower count is interesting. The article notes that Mastodon doesn’t check it but misses the fact that Mastodon can’t possibly check it. In a federated system, a single instance shouldn’t let untrusted instances see who on that system is following people for privacy reasons (and may also want to avoid sharing aggregated information if the activity is anonymity sets are sufficiently small). Even if it did, there’s nothing stopping me from creating a Mastodon instance with 10,000,000 accounts all following one person.

        It might be interesting to do some kind of aggregated thing of ‘these 20 instances all have 100+ followers of this account’, presenting something signed by each of those servers’ private keys, which would suggest that a person has a broad set of followers. You could trivially fake this by having a single machine host 20 domains, but then other instances can rely on their own reputation rankings for the following servers and so ignore ones where no one on your instance is following them and so on.

        I guess ‘number of followers’ has become important for ‘influencers’ and so Mastodon needs to present this number, but hopefully the ease with which it can be faked will make it fall out of use if Fediverse things take off.

        It’s a shame that there isn’t something in the various Fediverse protocols for privacy-preserving aggregated analytics, where small instances can nominate one or more systems that will track their reputation and share it with other instances.

        1. 6

          ActivityPub really feels like a step back from RSS/Atom if your use case is hosting a static blog. Instead of just publishing a static XML file, now you need a server that can respond dynamically according to a much more complicated protocol. The server also needs to persist data (the list of followers) and it needs to hit a bunch of other servers whenever the blog is updated.

          This model seems way worse for privacy, too. Following an RSS feed is inherently semi-anonymous, and you can specify your own User-Agent header and use a proxy/VPN if you want to blend into the crowd even more. Following an ActivityPub-based blog without exposing your identity would require even more work than is described in the OP.

          1. 4

            Agreed. I publish a blog, like a normal person, and I wrote a janky Perl script to echo the RSS content to a fedi account. If you know Python you can even dispense with the jank!

            Trying to force SSG blogging into the mold of current ActivityPub just feels like a roundabout way to get a dead blog in a couple of months.

          2. 3

            Following an ActivityPub-based blog without exposing your identity would require even more work than is described in the OP.

            It’s not that much harder, you can just keep polling the outbox like you’d do with an RSS feed. And on the plus side you don’t have to deal with XML and you can paginate instead of getting cut off at an arbitrary number of items.

            curl -s https://universeodon.com/users/georgetakei/outbox\?page\=true | jq -r '.orderedItems[]|select(.type=="Create")|[.published,.object.content]|@tsv'|sed -e 's/<[^>]*>//g'

            1. 2

              Now that you mention it, I think I remember that Mastodon offers a ready-made RSS feed of a user’s outbox?

              Still, though, (1) that statement is true for Mastodon, but probably not for most other ActivityPub software, and (2) even if readers can consume RSS just like they would for “static site” blogs, there’s still a lot of complexity for the publisher.

        2. 2

          Personally, what I’m interested in, is what you wrote (easy for Mastodon users to follow), plus comments via Mastodon. Meaning, I’d like to make it easy for Mastodon users to post replies to my blogposts, which would then be automatically appended into the HTML of the blogpost (that they replied to) as comments. Such that afterwards the page with the comments could still be served as a static HTML.

          Perhaps obviously, it would also need some HTML sanitization, rate-/capacity-limiting, and moderation tools. For moderation, hopefully some kind of a static blocklist of users & servers, checked before appending the comment, might be enough? (Plus a way to purge any matching already-appended comments when I add new entries to the blocklist.) Then, hopefully, the capacity limit would be just a failsafe until I add the offending spammer to the blocklist.

    2. 16

      Back in the day of OStatus you could publish new posts by updating a static Atom/RSS file, since OStatus instances would fall back to polling if you did not implement the push features. I miss that graceful fallback. I’m not convinced you actually can implement ActivityPub with static files, but I would happy to be proven wrong.

      1. 6

        If ActivityPub services actually used the outbox, it would be possible to publish a static ActivityPub site. It’s completely standard-compliant. But, for reasons I still cannot fathom, backfilling has never been implemented in Mastodon and it doesn’t seem like it will be anytime soon.

    3. 5

      $2000 a month for 30,000 users. Is that not a rather low amount of users for that amount of money?

      1. 2

        I guess it depends on how you value your users 😉

        The figures are from a post on Fosstodon’s donation transparency. I’m sure they would appreciate better deals if you can offer them.

    4. 3

      For a single-user Activity Pub instance this sounds like a great idea. There’s no way I’m running thousands of lines of unattended third-party Ruby code on my public facing web server.

    5. 2

      The GET request technically uses the parameter resource=acct:justin@mastodon.jgarr.net but with this static file example we only have one user on the domain so we’ll ignore that part. If you want to have multiple users on the same domain you will have to handle parameters on the server side. Meaning, you can’t do that with static files.

      Since there’s only one query parameter I think you can still do this with static files; you can construct a rewrite rule to turn https://server/.well-known/webfinger?resource=acct:user@domain into https://server/.well-known/webfinger/accts/user@domain which can just be one static file per user.

      In theory this is not compliant because the server should treat ?ignore=this&resource=acct:user@domain as the same as ?resource=acct:user@domain for arbitrary extra keys, which the rewrite rule won’t catch, but in practice this seems very unlikely. There’s probably some smarter tricks than a regular rewrite you could do with .htaccess to make this work but I’m not a web server expert.

      1. 4

        Nginx has the ability to parse the query string for you so that your configuration can depend on specific parameters’ values. My server has something like

        location /.well-known/webfinger {
            if ($arg_resource = "acct:myname@mydomain.social") {
                rewrite .+ /my/static/webfinger/file.json last;

        Other parameters in the query string will simply be ignored.

    6. 1

      why is this tagged apl?

      1. 2

        Closest tag I could find, given that it exchanges JSON like an API (Ah, I understand now, I selected apl by mistake when I intended api)

        1. 3

          apl is a programming language and is not related to web APIs. :)

        2. 1

          There is an api tag.

          Anyway it’s been corrected now by users suggesting it away.

    7. 1

      This implements the reading aspect of ActivityPub, but it could be extended to a more complete experience. I’d like to keep the publicly facing web server as close to static hosting as possible.

      The missing parts are processing incoming events to the user’s inbox and pushing events to other instances from the user’s outbox. These two tasks must not necessarily happen on the web server.

      We assume that the user has some locally installed software on their computer for generating the static ActivityPub files. This workflow looks a lot like a static site generator.

      The publicly facing web server must persist events bound for the user’s inbox. This could be as simple as writing the request to disk. The user would periodically run their local ActivityPub software to fetch the raw unprocessed inbox. After the inbox has been fetched, the server may delete it – kind of like POP3 email.

      When the user has authored a post and is ready to publish, the software builds the static files and uploads it to the web server. After the upload has completed, the software pushes it to the relevant external instances.

      I image that the heavy lifting of a Mastodon instance are bound by the CPU. There are various worker queues for processing the inbox and pushing events from the outbox to external instances. All of this would now happen on the user’s own computer.

      The publicly facing web server has very little business logic. It simply hosts the static files and accepts incoming events for later processing by the user.

    8. 1

      Looks fine to me, providing a way to serve static contents without running a full-blown mastodon server to the activitypub network can mean a lot for the future. The OP’s project doesn’t look more than a bunch of mere responses stored at the compatible endpoints, but this is the gist and a very nice question: does everybody need to run RoR on a VPS to publish their contents?

      1. 4

        The main problem is that ActivityPub is push, not pull. In order to broadcast new posts you need a bit more server-side logic.