F.4: Funkwhale bundle — federated music pod#13
Open
kh0pper wants to merge 1 commit intof3-matrix-dendrite-bundlefrom
Open
F.4: Funkwhale bundle — federated music pod#13kh0pper wants to merge 1 commit intof3-matrix-dendrite-bundlefrom
kh0pper wants to merge 1 commit intof3-matrix-dendrite-bundlefrom
Conversation
First federated-media bundle and the first exerciser of F.0's
storage-translators.funkwhale() S3 wiring. Stacked on F.3 (Matrix-Dendrite).
Funkwhale is a self-hosted music + podcast server that federates over
ActivityPub — remote Mastodon/GoToSocial/Pixelfed users can follow your
channels; your pod can subscribe to remote libraries and keep local audio
caches. Six containers on crow-federation: api (Django/Gunicorn),
celeryworker, celerybeat, internal nginx (Funkwhale's static/media server,
fronted by Caddy on :443), postgres, redis.
Bundle (bundles/funkwhale/):
- manifest.json consent_required with explicit EN/ES text on federation
reach, library cache growth (5-20 GB / 1000 tracks;
hundreds of MB for federated caches), copyright-liability
note, and hardware gate. min_ram_mb=1500 (below the
recommended 3 GB; hard-refused on <8 GB total hosts only
when co-installed with a heavier bundle since the gate is
"effective RAM after committed bundles"). Declares
FUNKWHALE_S3_* env vars as optional — presence activates
the storage-translator wiring below.
- docker-compose.yml funkwhale/funkwhale:1.4 + funkwhale/nginx:1.4 +
postgres:15-alpine + redis:7-alpine. Postgres/redis
isolated to default network; api + nginx on both default
and crow-federation so Caddy reaches nginx:80. AWS_* env
vars passthrough with blank defaults — configure-storage.mjs
populates them in-place when FUNKWHALE_S3_* is set.
Healthchecks on api (2 min start period for Django
migrations) and nginx. mem_limits: api=1500m,
celeryworker=768m, celerybeat=256m, nginx=128m,
postgres=512m, redis=256m. On-disk audio: stored in
/srv/funkwhale/data/media with ~/.crow/funkwhale/data
volume-mount; optional read-only /music for in-place import.
- server/server.js 13 MCP tools matching the plan's federated-media verb
taxonomy: fw_status, fw_list_library, fw_search,
fw_upload_track, fw_follow, fw_unfollow, fw_playlists,
fw_now_playing, fw_block_user, fw_mute_user (inline;
rate-limited), fw_block_domain, fw_defederate (QUEUED via
moderation_actions + Crow notification), fw_media_prune.
Upload accepts file_path OR file_base64+filename and posts
multipart FormData. Bearer-auth via FUNKWHALE_ACCESS_TOKEN
(PAT from Settings → Applications). All z.string() fields
have .max() bounds. loadSharedDeps() pattern borrowed from
GoToSocial so the bundle works both monorepo-mode and
installed-to-~/.crow (shared helpers resolve via try/catch
import; fall back to pass-through wrappers).
- server/index.js stdio transport.
- panel/funkwhale.js + panel/routes.js Crow's Nest panel (status, libraries,
recent listens). XSS-safe (textContent/createElement).
Panel API routes serve /api/funkwhale/{status,libraries,listens}.
- skills/funkwhale.md first-run workflow (superuser, Caddy site, PAT),
upload/search/follow/moderation examples, troubleshooting
(413 payload, celery queue, federated cache disk pressure).
- scripts/post-install.sh waits for api health (up to 180s for first-boot
migrations), detects FUNKWHALE_S3_ENDPOINT, invokes
configure-storage.mjs for the translation, and prints
Caddy + superuser + PAT next steps.
- scripts/configure-storage.mjs imports servers/gateway/storage-translators.js
translate('funkwhale', {...}) and appends a managed block to
the bundle's .env so compose picks up AWS_* on next up. Falls
back to inline mapping if the helper isn't resolvable
(installed-mode).
- scripts/backup.sh pg_dump (custom format) + data dir tar (excludes
__cache__ + static — regenerable). S3-backed audio
explicitly NOT in scope — operator's provider is the
durability layer. Prefers zstd; falls back to gzip.
- package.json MCP + zod deps only.
Integrations with shipped F-series:
- F.0 storage-translators.funkwhale() wires MinIO/S3 at install time when
operator opts in via FUNKWHALE_S3_* in .env. First bundle to exercise
this code path end-to-end.
- F.0 rate limiter content + moderation verbs (upload, follow, search,
block_user, mute_user, block_domain, defederate, media_prune). Read-only
verbs uncapped.
- F.0 hardware gate min_ram_mb + min_disk_mb per manifest schema.
- F.1 federated-media category wiring already present in extensions.js,
nav-registry.js, and i18n keys — no additions needed here.
Human-in-the-loop moderation:
- fw_block_user / fw_mute_user: inline, rate-limited (5/hour).
- fw_block_domain / fw_defederate: QUEUED. Writes pending row into
moderation_actions with 72h expiry + idempotency key; surfaces a Crow
notification with action URL; returns {status: 'queued', action_id,
expires_at} to the AI. Confirmation UI lands with F.11. Same rationale
and implementation as F.1 GoToSocial.
Registry / discovery surface:
- registry/add-ons.json entry inserted before developer-kit to keep
bundles grouped. category: federated-media (existing from F.1 wiring).
- skills/superpowers.md trigger row added between matrix-dendrite and
tutoring (EN + ES intents: funkwhale, federated music, upload track,
follow channel, music library, fediverse audio, podcast, playlist).
- CLAUDE.md Skills Reference entry added after matrix-dendrite.
Verified:
- node --check on all JS files (server, panel, configure-storage)
- bash -n on both shell scripts
- MCP server boots via createFunkwhaleServer() with no env set
- docker compose config parses (with required env vars)
- JSON parse on manifest.json, package.json, registry/add-ons.json
- npm run check passes
Next in the roll-out:
- F.5 Pixelfed (photos, 1.5 GB min)
- F.6 Lemmy (link aggregator, 1 GB min)
- F.7 Mastodon (flagship AP, 3 GB min)
- F.8 PeerTube (heaviest; needs S3 + aggressive transcoding policy)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
First federated-media bundle (category already wired by F.1) and the first exerciser of F.0's
storage-translators.funkwhale()S3 wiring. Stacked on F.3 (Matrix-Dendrite).crow-federation). No host port publish; exposed viacaddy_add_federation_site → funkwhale-nginx:80with theactivitypubprofile.fw_status,fw_list_library,fw_search,fw_upload_track,fw_follow,fw_unfollow,fw_playlists,fw_now_playing,fw_block_user,fw_mute_user(inline/rate-limited),fw_block_domain,fw_defederate(QUEUED viamoderation_actions+ Crow notification),fw_media_prune.FUNKWHALE_S3_*in.envandscripts/configure-storage.mjstranslates through F.0'sstorage-translators.funkwhale()into theAWS_*schema Funkwhale expects, then writes a managed block to the bundle's.envfor compose to pick up.min_ram_mb=1500,recommended=3000— realistic numbers with any federated follow graph. Celery workers + Django API are the hot paths.Test plan
node --checkon all JS files (server, panel, configure-storage.mjs)bash -non both shell scriptscreateFunkwhaleServer()with no env setdocker compose configparses (with required env vars set)npm run checkpassesFUNKWHALE_S3_*, confirm configure-storage.mjs writes the managed block, confirm uploads land in MinIOIntegration notes
servers/gateway/storage-translators.jsfunkwhale()translator. If the mapping needs adjustment per the upstream Funkwhale S3 docs, we fix it here before F.5 (Pixelfed, which uses the sameAWS_*pattern but with aFILESYSTEM_CLOUD=s3activation flag).loadSharedDeps()pattern copied frombundles/gotosocial/server/server.js— works both monorepo-mode and installed-to-~/.crow.developer-kitto keep bundles grouped. No new category/icon wiring needed (both present from F.1).Rollout position
🤖 Generated with Claude Code