Skip to content

SJang1/siliconbeest

Repository files navigation

SiliconBeest logo

SiliconBeest

Serverless Fediverse platform on Cloudflare Workers.

SiliconBeest is a fully-featured Mastodon API-compatible social networking server built entirely on the Cloudflare developer platform. It federates with the wider Fediverse via ActivityPub and can be deployed to a global edge network with zero traditional server infrastructure.

Warning: Do not change your instance domain after federating. ActivityPub actor URIs contain the domain and are permanent identifiers across the Fediverse. Changing the domain after other servers have cached your actors will break all existing federation relationships, followers, and conversations. Choose your domain carefully before launch.


Deploy Your Own Instance

SiliconBeest is a GitHub Template Repository. Deploy your own Fediverse instance in minutes:

  1. Click "Use this template" on this repository
  2. Create Cloudflare resources:
    /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/SJang1/siliconbeest/HEAD/scripts/install.sh)"
  3. Set the output values as GitHub Secrets & Variables
  4. Run the Deploy workflow -- done!

Full deployment guide: English | 한국어


Documentation


Features

Mastodon API Compatibility

  • Full Mastodon API v1/v2 -- works with existing clients (Tusky, Elk, Ice Cubes, Ivory, Mona, etc.)
  • Accounts, statuses, timelines, notifications, conversations, lists, filters, polls, tags, bookmarks, favourites, search
  • Admin API for moderation (accounts, reports, domain blocks, domain allows, IP blocks, email domain blocks, rules, settings, announcements, custom emojis, relays, measures)

Federation (powered by Fedify)

  • Fedify v2.3.3 -- TypeScript ActivityPub framework handling the protocol layer (signatures, WebFinger, NodeInfo, delivery)
  • @fedify/cfworkers -- Cloudflare Workers adapter (KV store + Queue message dispatcher)
  • ActivityPub server-to-server protocol
  • HTTP Signatures (draft-cavage-http-signatures-12) -- RSA-SHA256 signing, handled by Fedify
  • RFC 9421 double-knock -- modern HTTP Message Signatures for delivery, handled by Fedify
  • Linked Data Signatures -- signing and verification for relay forwarding
  • Ed25519 Object Integrity Proofs (FEP-8b32) -- ed25519-jcs-2022 cryptosuite
  • Activity forwarding with original signature preservation
  • Collection pagination (OrderedCollection / OrderedCollectionPage)
  • Activity idempotency -- deduplication of incoming activities
  • Instance actor for relay and instance-level activities

Interoperability

  • Misskey extensions -- emoji reactions (EmojiReact), _misskey_content, _misskey_quote
  • FEP-8b32 -- Object Integrity Proofs (Ed25519)
  • FEP-8fcf -- Followers Collection Synchronization
  • FEP-67ff -- FEDERATION.md
  • FEP-e232 -- Quote Posts (quoteUri)
  • Featured collections (pinned posts) via Add/Remove
  • Custom emoji (local and remote)
  • Relay support (admin-managed subscriptions)

Authentication and Security

  • OAuth 2.0 + PKCE -- standards-compliant authorization flows with scope enforcement
  • TOTP two-factor authentication (RFC 6238)
  • WebAuthn / Passkeys -- passwordless authentication
  • OAuth scope enforcement -- Mastodon-compatible hierarchical scope checking on all endpoints
  • Token hashing -- access tokens stored as SHA-256 hashes, never plaintext
  • Domain block enforcement -- blocked domains rejected at federation inbox level
  • HTML sanitization -- allowlist-based sanitizer on both local and remote content
  • CSP headers -- Content-Security-Policy, X-Content-Type-Options, X-Frame-Options on all responses
  • Rate limiting -- KV-backed sliding window on auth, registration, and admin endpoints
  • Registration control -- open, approval-required, or closed
  • Email domain blocks -- prevent signups from blocked email domains

Real-Time and Notifications

  • WebSocket streaming -- live timeline updates via Cloudflare Durable Objects
  • Web Push notifications -- VAPID (RFC 8292) + RFC 8291 encryption

Content

  • URL preview cards -- OpenGraph metadata fetching
  • Media uploads -- R2 storage with async thumbnail processing
  • Polls -- create and vote
  • Content warnings and sensitive media flags
  • HTML sanitization and content parsing (mentions, hashtags, links)

Frontend

  • Internationalization -- 12 language packs with lazy loading (en, ko, ja, zh-CN, zh-TW, es, fr, de, pt-BR, ru, ar, id)
  • Dark mode -- system-aware and manual toggle
  • Responsive design -- mobile-first with Tailwind CSS
  • Admin dashboard -- accounts, reports, domain blocks, rules, settings, announcements, relays, custom emojis, federation

Operations

  • Email -- dedicated email-sender worker consuming from a queue, SMTP via worker-mailer (password reset, notifications)
  • Sentry integration -- optional error tracking (admin opt-in)

Architecture

SiliconBeest runs as 3 Cloudflare Workers:

                        Clients (Mastodon apps, web)
                                   |
                                   v
                     +---------------------------+
                     |    Cloudflare CDN / Edge   |
                     +---------------------------+
                                   |
                                   v
              +---------------------------------------+
              |          siliconbeest (main)           |
              |   Hono API server + Vue 3 SPA frontend |
              |                                       |
              |  - Mastodon API v1/v2                  |
              |  - OAuth 2.0 + PKCE + WebAuthn        |
              |  - Fedify (ActivityPub federation)     |
              |  - Admin API with rate limiting        |
              |  - WebSocket streaming (Durable Objs)  |
              |  - Vue 3 SPA (Tailwind, Pinia, i18n)  |
              +---------------------------------------+
                    |     |      |       |
                    v     v      v       v
              +-----+ +----+ +--------+ +------------------+
              |  D1 | | R2 | |   KV   | |  Durable Objects |
              | SQL | |blob | |cache/  | |  (StreamingDO)   |
              | DB  | |store| |session | |  WebSocket live  |
              +-----+ +----+ +--------+ +------------------+

         +----------------------------+   +-----------------------------+
         | siliconbeest-queue-consumer|   | siliconbeest-email-sender   |
         |                            |   |                             |
         |  - Federation delivery     |   |  - SMTP via worker-mailer   |
         |  - Timeline fanout         |   |  - Password reset emails    |
         |  - Notifications           |   |  - Notification emails      |
         |  - Media processing        |   +-----------------------------+
         |  - Web Push sending        |               |
         +----------------------------+          +--------+
                |            |                   | Queue  |
          +------+     +------+                 | email  |
          | Queue |     | Queue |                +--------+
          | fed.  |     | int.  |
          +------+     +------+

The main worker enqueues email jobs to the email queue via its QUEUE_EMAIL producer binding. The email-sender worker consumes from that queue and sends mail via SMTP using worker-mailer.

A packages/shared/ directory contains code shared between workers:

  • crypto/ -- Consolidated HTTP signature signing/verification and PEM key management (used by both the main worker and queue consumer)
  • types/ -- Shared Mastodon API base type definitions (used by both server and frontend)

Tech Stack

Layer Technology
API Server Hono + Chanfana + Zod on Cloudflare Workers
Federation Fedify v2.3.3 + @fedify/cfworkers
Frontend Vue 3 + Vite + Tailwind CSS + Headless UI
Database Cloudflare D1 (SQLite)
Object Store Cloudflare R2
Cache/Session Cloudflare KV
Job Queues Cloudflare Queues
Streaming Cloudflare Durable Objects (Hibernatable WS)
Auth bcryptjs, OAuth 2.0, TOTP (RFC 6238)
Web Push VAPID (RFC 8292) + RFC 8291 encryption
Email worker-mailer (SMTP)
IDs ULID (time-sortable)
i18n vue-i18n (frontend) + custom (API errors)
Error Track Sentry (optional)
Testing Vitest + @cloudflare/vitest-pool-workers

Quick Start

Prerequisites

  • Node.js 25+
  • Wrangler CLI >= 4.x (pnpm add -g wrangler)
  • A Workers Enabled Cloudflare account
  • A domain managed by Cloudflare (for custom domain deployment)

1. Clone and Install

git clone https://github.com/SJang1/siliconbeest.git
cd siliconbeest

# Install dependencies for all sub-projects
pnpm install

2. Interactive Setup

The setup script creates all Cloudflare resources, generates cryptographic keys, and configures your instance:

./scripts/setup.sh

It will prompt for:

Setting Description Example
Project prefix Resource naming prefix myserver (default: siliconbeest)
Instance domain Your Fediverse domain social.example.com
Instance title Display name My Fediverse Server
Registration mode open / approval / closed open
Admin email Administrator email admin@example.com
Admin username Administrator handle admin
Admin password Administrator password (hidden input)
Sentry DSN Error tracking (optional) https://...@sentry.io/...

The script automatically:

  • Creates D1 database, R2 bucket, KV namespaces (CACHE, SESSIONS, FEDIFY_KV), Queues
  • Generates VAPID key pair (ECDSA P-256) for Web Push and stores in D1 settings
  • Generates OTP encryption key for 2FA secrets
  • Updates all wrangler.jsonc files with resource IDs
  • Sets secrets via wrangler secret put
  • Applies D1 database migrations
  • Creates the admin user account
  • Writes siliconbeest/.env with VAPID public key and optional Sentry DSN

3. Deploy

# Deploy with custom domain routing (recommended)
./scripts/deploy.sh --domain social.example.com

# Or deploy to *.workers.dev subdomains (for testing)
./scripts/deploy.sh

4. Cloudflare Bot Protection (CRITICAL)

Without this step, federation is completely broken.

Cloudflare's Bot Fight Mode blocks ActivityPub traffic (403 to /users/*, /inbox). You must create a WAF Skip rule -- see scripts/README.md for full instructions.


Updating an Existing Instance

# Full update: git pull -> install deps -> type check -> tests -> migrations -> deploy
./scripts/update.sh

# With specific branch
./scripts/update.sh --branch release/v0.2.0

# Preview changes without deploying
./scripts/update.sh --dry-run

See scripts/README.md for all update options and flags.


Project Structure

siliconbeest/
  siliconbeest/                 # Main app — API server (Hono) + Vue 3 SPA frontend
    server/worker/              #   Hono API server (Mastodon API, OAuth, ActivityPub)
    server/worker/federation/   #   Fedify inbox/outbox, dispatchers, helpers
    server/worker/middleware/    #   Auth, rate limiting, CORS, scope enforcement
    server/worker/endpoints/    #   All API route handlers
    src/                        #   Vue 3 frontend (components, views, stores, i18n)
    migrations/                 #   D1 database migrations (22 files)
    test/worker/                #   API server tests (55 files)
    test/                       #   Vue frontend tests (11 files)
  siliconbeest-queue-consumer/  # Async job processor (federation + internal queues)
  siliconbeest-email-sender/    # Email sender (SMTP via worker-mailer)
  scripts/                      # Setup, deploy, and maintenance scripts
  docs/                         # Architecture docs, security audit, migration guides
  FEDERATION.md                 # Federation capabilities (FEP-67ff)

See each sub-project README for details:


Testing

cd siliconbeest

# API worker tests (55 test files, 805 tests)
pnpm exec vitest run --config vitest.worker.config.ts

# Vue frontend tests (11 test files)
pnpm exec vitest run

# Both suites
pnpm exec vitest run --config vitest.worker.config.ts && pnpm exec vitest run
Suite Test Files Coverage Areas
Worker 55 Auth (suspension, scopes), OAuth (PKCE, approval flow, token hashing), accounts, statuses, timelines, notifications, search, lists, markers, media, bookmarks, favourites, blocks/mutes, conversations, filters, tags, polls, reports, admin (accounts, roles, domain blocks, rules, announcements, relays, custom emojis), ActivityPub, federation (Fedify dispatchers, inbox processing, delivery, domain block enforcement), collection pagination, activity idempotency, featured collections, emoji reactions, custom emojis, quote posts, WebFinger, NodeInfo, content parsing, serializers, sanitization, ULID, instance, discovery, passwords, WebAuthn, proxy (SSRF), email verification, email domain blocks, scope enforcement
Vue 11 Stores (auth, ui, statuses, timelines), components (Avatar, LoadingSpinner, StatusActions, FollowButton), API client, i18n, router guards

Scripts Quick Reference

All scripts read resource names from scripts/config.sh. Customize by setting PROJECT_PREFIX or creating scripts/config.env (see scripts/config.env.example).

Script What it does
./scripts/setup.sh Interactive first-time setup (creates resources, keys, admin)
./scripts/deploy.sh --domain social.example.com Deploy with custom domain routing
./scripts/update.sh Pull, test, migrate, redeploy (production updates)
./scripts/backup.sh Backup D1 + R2 data
./scripts/migrate.sh Apply D1 database migrations
./scripts/seed-admin.sh Create an admin user account
./scripts/delete-account.sh AP-compliant account deletion (sends Delete to all peers)
./scripts/generate-vapid-keys.sh Generate/rotate VAPID key pair
./scripts/configure-domain.sh Set up Workers Routes for a custom domain
./scripts/sync-config.sh Sync Cloudflare resource IDs → wrangler.jsonc (new machine/recovery)

See the full scripts documentation for all options and flags.


Secrets and Environment Variables

Secrets (stored in Cloudflare, never in code)

Secret Workers Set by
OTP_ENCRYPTION_KEY worker setup.sh
SETUP_SECRET worker setup.sh / install.sh
SENTRY_DSN (optional) worker manual: wrangler secret put SENTRY_DSN

VAPID keys are stored in the D1 settings table (keys: vapid_public_key, vapid_private_key) and managed via the Admin settings page or setup.sh. They are not set as environment secrets.

Environment Variables (in wrangler.jsonc)

Variable Description Default
INSTANCE_DOMAIN Your instance domain siliconbeest.com
INSTANCE_TITLE Instance display name SiliconBeest
REGISTRATION_MODE open / approval / closed open
SKIP_SIGNATURE_VERIFICATION Explicit true / false override for inbound HTTP signature verification; GitHub Actions reads this from GitHub Environment Variables during deploy false

Observability drains (optional): to forward the main worker's logs/traces to an OTLP backend such as Sentry, first create Logs/Traces destinations under Workers & Pages → Observability in the Cloudflare dashboard — each destination holds the OTLP endpoint URL and any auth headers (for Sentry: header x-sentry-auth with value sentry sentry_key=<public key>; copy both from Sentry's Client Keys (DSN) → OpenTelemetry (OTLP) page). Then set OBSERVABILITY_LOGS_DESTINATIONS / OBSERVABILITY_TRACES_DESTINATIONS (comma-separated destination names) as GitHub Environment Variables — or in scripts/config.env for manual deploys. sync-config.sh writes them into the observability.logs / observability.traces blocks of the main worker's wrangler.jsonc.

Frontend Environment (siliconbeest/.env)

Variable Description Required
VITE_INSTANCE_DOMAIN Instance domain (for meta tags) Yes
VITE_VAPID_PUBLIC_KEY VAPID public key (for Web Push) Yes
VITE_SENTRY_DSN Sentry DSN for error tracking (CI deploys read the SENTRY_CLIENT_DSN GitHub Variable instead) No
VITE_SENTRY_FEEDBACK true shows the Sentry user-feedback widget (requires VITE_SENTRY_DSN; CI deploys read the SENTRY_FEEDBACK_ENABLED GitHub Variable) No

Local Development

# Terminal 1 -- Main app: API worker + Vue frontend (port 8787)
cd siliconbeest && pnpm exec wrangler dev

# Terminal 2 -- Queue consumer
cd siliconbeest-queue-consumer && pnpm exec wrangler dev

# Terminal 3 -- Email sender
cd siliconbeest-email-sender && pnpm exec wrangler dev

# Terminal 4 -- Vue frontend dev server with HMR (port 5173, optional)
cd siliconbeest && pnpm run dev

For local D1, apply migrations first:

cd siliconbeest && pnpm exec wrangler d1 migrations apply siliconbeest-db --local

Cost Estimate

Estimated cost with a Workers Enabled account:

Resource 100 users/mo 1000 users/mo
Workers requests ~1.5M (incl.) ~15M ($1.50)
D1 reads ~300K (incl.) ~3M (incl.)
D1 writes ~30K (incl.) ~300K (incl.)
R2 storage ~1 GB ($0.02) ~10 GB ($0.15)
KV operations ~500K (incl.) ~5M (incl.)
DO requests ~300K (incl.) ~3M ($0.30)
Queues ~100K (incl.) ~1M (incl.)
Total ~$5/mo ~$7/mo

Contributing

See the contributing guide for development setup, coding guidelines, test commands, database migration rules, and the pull request checklist: English | 한국어.


License

GNU Affero General Public License v3.0 (AGPL-3.0)

This is the standard license for Fediverse server software. Any modified version deployed as a network service must make its source code available.

Releases

Sponsor this project

Packages

Used by

Contributors

Languages