Skip to content

Comment on I Wrote an Activitypub Server in OCaml: Lessons Learnt, Weekends Lost

Comments

Im looking forward to a solid ActivityPub server written in Go or Rust that can run on modest hardware/small resource Docker hosts.

Im looking forward to a solid ActivityPub server written in Go or Rust that can run on modest hardware/small resource

The "Lightweight" GoLang ActivityPub server is GoToSocial https://github.com/superseriousbusiness/gotosocial

The better-known lightweight servers are Pleroma and fork Akkoma, written in Elixir https://akkoma.dev/AkkomaGang/akkoma/

Some of this info I got via: https://social.treehouse.systems/@ariadne/110226729543740723

There's also Honk[1] which is written in Go but has slightly wacky source and doesn't support the Mastodon API (but does provide an inbuilt web UI.)

[1] https://humungus.tedunangst.com/r/honk

I think there is (was?) an attempt to rewrite Mastodon into Rust but I haven't heard much about it.

A single user Mastodon instance takes an unreasonable amount of resources. I don't know if it's just because of Ruby (Gitlab has the same problem, so it might just be) or because everyone is wasting money on expensive servers, but an RSS feed on steroid shouldn't take this much RAM.

Mastodon itself is designed for "flagship scale" (given lead developers run mastodon.social and mastodon.online, two of the biggest instances and the most "dogfooding" two instances) so it bundles an entire cluster of services: background processors (sidekiq), caches (redis, I think?), database server (postgres), optional ElastiCache, and more. I don't know how much Ruby itself accounts for expensive overhead, but just running all of those other things on a single server vertically for a single user instance is a massive, expensive overhead. (It's clearly built for horizontal scale where your background services and caches and database servers may all be different clusters of VMs/servers over vertical stack efficiency when "scaled down" from the "natural" "mastodon.social scale" that Mastodon is most optimized for.)

It's an interesting optimization problem reminder that scaling factors are different for different needs and not everything scales cleanly to every use case. A single user instance should be able to use a much smaller vertical stack, but scaling down from a wide horizontal stack is not necessarily the best or cheapest place to start when building something like that.

(There are some interesting projects I've seen to build single user instances with much less overhead, shorter vertical stacks. I'm curious to see where those efforts go. In my own usage of Mastodon my "single user" instance gets the benefits of the horizontal scaling Mastodon was built for because my hosting provider does a bunch of work to make sure that they take advantage of that economy of scale to host many small instances for cheaper than trying to run small instances in one-off VMs.)

This is the same problem that plagued mail servers. It takes so many different components which all have their own configurations to optimize (and memory/cpu footprints) that it ends up being too complex for most people to actually run an instance.

I'm also completely positive that a Go or Rust version on a $5 VPS with an in-memory database model (RocksDB, LevelDB, BadgerDB, etc..) could easily handle hundreds of thousands of users and gigs of content each day. It seems like it would be easy to expand that to a multi-node key-value store like TiDB, CockroachDB, etc.. if you needed to grow beyond a single host.

https://github.com/rustodon/rustodon#readme which has an awesome name but you're correct it appears that specific repo stalled out. I didn't check on the 41 forks of it

I've had a go at doing it in Go and the ActivityPub spec is so loosely defined that it's just a real challenge if you intend to actually unmarshal the JSON you receive

It's not completely impossible but you have to be okay with discarding a lot of unknown options or essentially reverse engineering the objects used by the servers you are federated with

That's not to say it's impossible, I was able to crawl the network successfully, but it hints at the reason that Mastodon and Pleroma use dynamic languages

I'd be very interested to see a flexible/complete AP implementation in any statically typed language

Fwiw WriteFreely is implemented in Go with go-fed but -- correct me if I'm wrong -- that library seemed more limited to me than what Pleroma and Mastodon support

I'm surprised you didn't find my library because I managed to create a statically typed vocabulary library for Go that maps the specification verbatim: https://pkg.go.dev/github.com/go-ap/activitypub#Object

It wasn't easy indeed, and it locked me out of some options to support execution time vocabulary extensions, but hey, it works and it's relatively easy to use.

I'm surprised I didn't find it, too! My google-fu must be getting rusty. Thanks for the link, I'll have to have a deep dive when I get the time :)

I hope you get to it. The library itself contains more than just the vocabulary part and I would be glad of more eyeballs on the problem. :D

Here's the implementation described in OP: https://github.com/Gopiandcode/ocamlot

OCaml is a statically-typed language. It falls somewhere between Go and Haskell on the spectrum of type 'strength'.

I'd be very interested to see a flexible/complete AP implementation in any statically typed language

Try Honk[1] or GotoSocial[2]?

[1] https://humungus.tedunangst.com/r/honk [2] https://github.com/superseriousbusiness/gotosocial

Neither is flexible, nor strives for completion. They are both implementations that try to map the ActivityPub vocabulary on an existing web-application domain.

They are not ActivityPub servers, but web-apps that use the ActivityPub vocabulary to federate, which is what I meant in the grandparent post when I mentioned the classic mistake of ActivityPub implementers. :D

Well, there is one already as the reference implementation for a suite of libraries I wrote. You can find it at https://github.com/go-ap/fedbox. (Contributions welcome)

Does it only support C2S as the API? Are there any clients which actually support C2S rather than the Mastodon API?

It does support server to server, but currently it does not play well with Mastodon due to its limited support of HTTP Signatures algorithms. I didn't get bothered enough by this yet to actually fix it on my side.

And there are a number of clients that work with this specific brand of client to server ActivityPub but I wrote all of them. The one that can be seen on the internet is a link aggregator similar to HN and (old) reddit, you can find a demo instance at https://brutalinks.tech.

It does support server to server

Ah, sorry, I should have said "client API" rather than just API there.

ActivityPub has a section which deals with how clients and servers should communicate with each other (called Client to Server - C2S - in the spec). So it's the same vocabulary and operations with slightly different side effects, but most servers don't implement it because it's not "specified enough". That's why developers generally just use the Mastodon API.

[client apis / c2s / mastodon]

Yep, I know. That's why I was asking if there was any support other than C2S because that does somewhat limit your server to "basically zero client support" which reduces its usefulness as an example somewhat?

There are several websites out there which hope to list many ActivityPub servers (and clients) in many (programming) languages, and other implemtnation aspects...Like, here's an oldie but goodie website: https://fediverse.party/en/miscellaneous/ ...There are other wbsites of course.

Just select your desired lang. and review! Now, of course, it might be early days for some languages (e.g. for Rust, etc.)...But, one reason why some languages are used over others...is due to ease of deploying on VPCs and VPC-like hosts (...historically the land that php ruled ;-)

Enjoy, and I hope you find what you're looking for!

Ocaml code compiles to native binaries, just like Go/Rust.

Why specifically those languages? Others can also target modest hardware/small resource Docker hosts.

Pleroma (written in Elixir) is one of the lighter, Mastodon-compatible AP servers available. I recently read a post (a toot actually, but I hate that term) by a Mastodon administrator observing that that Pleroma is often a common thread to problematic Fediverse instances because it can run on cheap VPS boxes on throwaway domains. Spammers/griefers can cause a lot of moderation problems for the same amount as a Twitter Blue subscription.

It is dubious endorsement, but I think it shows how much more efficient Pleroma is than other popular, easy-to-use-OOTB AP servers: 9 out of 10 price-conscious griefers use and endorse Pleroma

Sure, Zig, Nim, D, Erlang, etc.. could also do this, but Go and Rust are both big enough and just about as fast and low memory as anything that is available.

Java can be faster than Go, but not by much and I've always seen it to use 5-10x the memory.

Scripting languages like Typescript, Python, PHP and Ruby can't hold a candle to the speed of Rust and Go while also using significantly more memory. They also don't natively support multiple cores / threads.

Rust and Go represent the most approachable middle ground on all accounts of familiarity, performance (allocs and calculation speed), and large communities with libraries covering whatever you could want.

I mean, nothing beats C (yet), but that isn't actually what most devs are writing web services in. Rust overs better guarantees, but even that is too complex for the masses so Go is probably the next largest community that still offers great performance.

Java, PHP, Python & Node.js have massive market share, yet none of them are as ideal for the job.

AboutSource Built by g1lg1l

Hackerly is an independent reader for Hacker News, built on the public HN API. Not affiliated with Y Combinator.