Hollo 0.8.0: Scalable workers, Mastodon 4.5 quote post API support, and smarter federation #449
dahlia
announced in
Announcements
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
-
Hollo is a single-user, headless ActivityPub server. It exposes a Mastodon-compatible API with no built-in frontend, so you can connect any Mastodon client of your choice. It's built on Fedify and is designed for people who want to run their own fediverse presence without operating a full multi-user instance.
Version 0.8.0 is a substantial release. The headline additions are support for separating web and worker processes for better scalability, support for the quote post API introduced in Mastodon 4.5 (so Mastodon clients that implement it work with Hollo), and a set of improvements to how Hollo handles remote actors over time. There's also a new thumbnail cleanup tool contributed by a community member, and quite a few smaller fixes and compatibility improvements throughout.
Separating web and worker processes
Previously, Hollo ran everything in a single process: the web server, the Fedify message queue, and the import worker. That works fine for a quiet instance, but for accounts with thousands of followers, a single post can generate thousands of outbox messages, and processing those federation jobs in the same process as the web server could noticeably slow down API responses.
You can now run web and worker processes separately using the
NODE_TYPEenvironment variable. Set it towebfor the web server,workerfor background jobs (the Fedify message queue and import worker), or leave it at the defaultallfor the existing single-process behavior. Both processes share the same PostgreSQL database, which handles message passing viaLISTEN/NOTIFY. The documentation covers setup for Docker Compose, systemd, and manual deployments. (#350)Mastodon 4.5 quote post API support
Hollo has had quote post support for a while, but the API shape it used was based on Fedibird's earlier format. Mastodon 4.5 introduced its own quote post API, and Mastodon clients that implement it can now use it with Hollo. This is purely a client API compatibility change; it doesn't affect how quotes are federated over ActivityPub.
The
quotefield on status objects now uses the Mastodon 4.5Quoteentity format ({ state, quoted_status }) instead of the old flat Fedibird-style format. The oldquote_idfield is still there for backward compatibility.Alongside the format change, there are several new endpoints and fields:
quoted_status_idparameter onPOST /api/v1/statuses(the Mastodon 4.5 way to create quotes, alongside the existingquote_id)quotes_countandquote_approvalfields on status objectsGET /api/v1/statuses/:id/quotesfor paginated quote listingsPOST /api/v1/statuses/:id/quotes/:quoting_status_id/revoketo let you revoke quotes of your postsNote that the
quote_approval_policyparameter from Mastodon 4.5, which lets you control who can quote your posts, is not implemented. All public and unlisted posts are freely quotable for now.Smarter handling of remote actors
Three related improvements land in this release, all aimed at keeping remote actor data accurate and avoiding wasted work.
Automatic profile refresh: When Hollo receives an
AnnounceorCreate(Note)activity, it now checks whether the sending actor's cached profile is stale and, if so, refreshes it in the background. Remote actor data (avatars, display names, bios) used to update only when the remote server sent an explicitUpdateactivity, which many servers do infrequently. The staleness threshold defaults to 7 days and is configurable viaREMOTE_ACTOR_STALENESS_DAYS. If you want Hollo to check for stale profiles on all activity types (likes, reactions, follows, etc.), setREFRESH_ACTORS_ON_INTERACTION=true. (#348)Cleanup on permanent delivery failure: When outbound activity delivery fails permanently, Hollo now cleans up the relevant records. A
404 Not Foundresponse removes the follower relationship so future activities stop going there; a410 Gonedeletes the remote account record entirely (and its associated data via cascade), since the actor is explicitly marked as gone. Previously, these dead destinations would just accumulate indefinitely.Inbox handling for deleted actors: Using Fedify 2.1.0's unverified activity hooks, Hollo now responds to
Deleteactivities with202 Acceptedwhen the signing key fetch returns410 Gone, rather than letting the remote server retry delivery forever for an actor that's already been deleted.Remote replies scraping in the background
Hollo scrapes reply threads from remote servers to fill in conversation context. This used to happen synchronously during post ingestion, meaning a slow or very deep remote reply collection could hold up the entire federation processing pipeline. Reply scraping is now a background job with per-origin throttling and
429 Too Many Requestsbackoff. Several new environment variables let you control the behavior:REMOTE_REPLIES_SCRAPE_DEPTH,REMOTE_REPLIES_SCRAPE_MAX_ITEMS,REMOTE_REPLIES_SCRAPE_INTERVAL_SECONDS,REMOTE_REPLIES_SCRAPE_BACKOFF_SECONDS, andREMOTE_REPLIES_SCRAPE_COOLDOWN_SECONDS. (#445, #447)Reduced idle memory usage
Based on actual memory measurements, a number of heavy dependencies are now loaded lazily rather than at startup. Shiki (used for code block syntax highlighting in Markdown) loads only when rich text formatting is actually needed. S3 storage code no longer loads at startup for filesystem deployments. Web server and worker code paths are imported only by the process type that needs them. Preview card scraping, media processing, and authentication helpers also load on demand. The result is a noticeably smaller baseline memory footprint, especially for single-user instances on filesystem storage. (#435)
Production build with tsdown
Hollo now ships compiled JavaScript in its Docker images rather than running TypeScript via
tsxat runtime. Atsdown-powered build step runs in a builder stage and produces the JavaScript files that the runtime image runs with Node.js directly. Thepnpm prodandpnpm workerscripts now execute the compiled output rather than transpiling on the fly. (#357)Thumbnail cleanup
A new dashboard page at
/thumbnail_cleanuplets you mass-delete cached thumbnails from remote posts that your account hasn't bookmarked, liked, reacted to, shared, or quoted before a given cutoff date. The original posts, the media relationships, and alt texts are all preserved; only the cached image files are removed. This can free up a meaningful amount of storage on instances that have been federating for a while. (#409, #436)Other changes
/:handle/tagged/:tag. TheGET /api/v1/accounts/:id/statusesendpoint also applies the existingtaggedquery parameter correctly now. (Option to view tagged posts from only the profile user #420)GET /api/v1/preferences, so clients like Phanpy can honor it. (Content warnings always collapsed in Phanpy —reading:expand:spoilersappears hardcoded tofalse#425)404 Not Found. Fixed. (Official Mastodon iOS App Throws Errors on Local and Following Tabs #421, Add stub endpoints for trends and suggestions #427)WHERE INconditions across status, context, quote, and timeline queries. (Optimize follower visibility queries for better performance #173, Optimize follower visibility queries #448)FEDIFY_DEBUG=trueto enable an embedded real-time ActivityPub trace dashboard at/__debug__/. Intended for development use only.Thanks to contributors
This release includes contributions from two community members:
Thank you both.
Beta Was this translation helpful? Give feedback.
All reactions