Waterhole
Collaborative moderation for Mastodon registration requests.
Herds that roam apart all come down to the same waterhole to keep watch together. Waterhole is that place for
Mastodon instances that approve their signups by hand: each instance is a herd.
Features
- No new account needed: sign in with your Mastodon account.
- The registration queue gets mirrored in Waterhole, and a decision (approve/reject) gets sent back to your Mastodon instance.
- Real-time collaboration on registration requests with other moderators of your Mastodon instance.
- No automatic decision-making: Waterhole helps your moderators make decisions but never makes them for you.
- Automatic advisory flags so your moderators quickly get a grasp of the request, each with its own help. Advisory flags include, among others:
- throwaway addresses
- who receives the address's mail: inboxes built for AI agents or software tests, disposable mail services, Amazon SES inbound, and the big mail providers
- datacenter networks
- templated reasons for joining
- bursts of look-alike signups
- reapplications (remembered for the retention period, 90 days by default)
- Network details for the signup IP: country, network (ASN), iCloud Private Relay, and Tor relays.
- Translate the reason for joining with one click, right in your browser: the language gets detected and translated on your device, so the reason never leaves it (in browsers with built-in translation, currently Chrome).
- Push notifications tell you when requests are waiting, if your Waterhole has them enabled. Opt in per browser and choose how often, about which requests and at what time of day. Messages contain only a count, so your browser vendor's push service learns nothing about applicants or your instance.
- Claim a request, so other moderators see that someone is working on it.
- Add notes to a request or vote on it.
- Power through big queues: filters, search, sorting by risk, keyboard shortcuts and bulk actions help you tackle the next spam wave.
- Create watchwords (including regular expressions) that flag and highlight matching requests.
- Create email templates for a quick follow-up question or a rejection email. They open, filled in for the applicant, in your own email client.
- One Waterhole can serve multiple Mastodon instances. Each has its own registration queue, watchwords, and email templates. They can opt in to share limited data with each other to catch spam waves that hit several instances.
- Mastodon instance administrators must allow Waterhole (with a DNS TXT record), so moderators cannot use it without their permission.
- Privacy first, built with the GDPR in mind:
- decided requests are deleted automatically after the retention period (90 days by default), and any request can be purged by hand
- moderators consent before their data is processed
- a ready-made privacy notice for instance administrators to add to their own privacy policy
- shared data is limited: email addresses are only compared as keyed hashes, and only the instance's domain is revealed
- Progressive Enhancement: A basic version of Waterhole is accessible without JavaScript, and advanced features are progressively enhanced.
- Host your own Waterhole and set deployment-wide options like the admission policy (open to all, with a blocklist, or allowlist only) and an optional sync of the IFTAS Do Not Interact list.
Interested? We host a Waterhole that is open to all: start at waterhole.toot.io.
Host your own
Tech Stack
- Ruby on Rails (with Solid Cable, Solid Queue, Solid Cache, and Turbo)
- PostgreSQL
Configuration
Every setting is documented in .env.production.sample.
cp .env.production.sample .env.production
Then fill in the secrets. This needs only openssl, so it works for Docker Compose, too.
It fills the empty secret lines in .env.production and never overwrites a key that is already set:
alnum() { openssl rand -base64 48 | tr -dc 'A-Za-z0-9' | head -c 32; }
sed -i.bak \
-e "s/^SECRET_KEY_BASE=\$/&$(openssl rand -hex 64)/" \
-e "s/^ACTIVE_RECORD_ENCRYPTION_PRIMARY_KEY=\$/&$(alnum)/" \
-e "s/^ACTIVE_RECORD_ENCRYPTION_DETERMINISTIC_KEY=\$/&$(alnum)/" \
-e "s/^ACTIVE_RECORD_ENCRYPTION_KEY_DERIVATION_SALT=\$/&$(alnum)/" \
-e "s/^WATERHOLE_SHARING_HMAC_KEY=\$/&$(openssl rand -hex 32)/" \
.env.production && rm .env.production.bak
With Ruby at hand, bin/rails waterhole:secrets prints the same keys to paste in instead.
Moderators can also opt in to push notifications about their queue, if you set the optional
WATERHOLE_VAPID_* pair. Generate it with bin/rails waterhole:vapid, or under Docker Compose with
docker compose run --rm web bin/rails waterhole:vapid. Keep it stable: changing it ends every browser's
subscription. Add the push paragraphs from the template to your privacy policy first: changing your copy
asks every moderator to consent again and starts each instance's terms grace period.
- Outside a container, Rails reads
.env.production at boot.
- In a container, the same variables are passed in (see Deployment below).
- Variables already set in the environment always win over the file.
[!warning]
Back up the encryption keys with the database. Without them, stored access
tokens, OAuth client secrets, and applicant emails cannot be read.
When your Waterhole is open to the public, you need to provide it with some legalese.
We have provided templates in config/legal as a starting point.
Waterhole reads the documents from WATERHOLE_LEGAL_DIR (default storage/legal).
With Docker Compose, that is the legal folder next to docker-compose.yml, which the
Deployment steps set up. Without Docker, run:
This is the beginning of the README. Read the rest at the original. Read the full README ↗