F.5: Pixelfed bundle — federated photo-sharing#14
Open
kh0pper wants to merge 1 commit intof4-funkwhale-bundlefrom
Open
F.5: Pixelfed bundle — federated photo-sharing#14kh0pper wants to merge 1 commit intof4-funkwhale-bundlefrom
kh0pper wants to merge 1 commit intof4-funkwhale-bundlefrom
Conversation
Second federated-media bundle. Stacked on F.4 (Funkwhale). Reuses F.4's
storage-translator wiring pattern — Pixelfed uses AWS_* + FILESYSTEM_CLOUD=s3
+ PF_ENABLE_CLOUD=true per F.0's translator map.
Pixelfed is the fediverse's Instagram-alternative: upload photos, browse
a chronological feed, follow accounts on any ActivityPub server
(Mastodon, GoToSocial, Funkwhale, other Pixelfed pods). Its REST API
is Mastodon v1/v2 compatible — most verbs cross over cleanly from the
GoToSocial bundle (F.1), which is why this one lands cleanly in a
single bundle rather than forcing a new API abstraction.
Bundle (bundles/pixelfed/):
- manifest.json consent_required with EN/ES covering federation reach,
remote-media cache growth (10-50 GB within weeks under
active federation), CSAM/moderation responsibility
(non-optional on a federated photo server), and
hardware gate (min 1.5 GB effective RAM, warn <8 GB).
Declares PIXELFED_S3_* optionals that activate the
storage-translator wiring.
- docker-compose.yml zknt/pixelfed:0.12 (nginx+PHP-FPM+supervisord
all-in-one) + horizon queue worker + postgres:15 +
redis:7. app + horizon both on crow-federation so they
can reach DB/redis peers AND be reached by Caddy.
Blank-default AWS_* passthrough so configure-storage.mjs
can populate them at install. mem_limits: app=1500m,
horizon=768m, postgres=512m, redis=256m. Media retention
wired to PIXELFED_MEDIA_RETENTION_DAYS env var (default 14).
- server/server.js 14 MCP tools per the federated-media verb taxonomy:
pf_status, pf_post_photo (upload + status in one call),
pf_feed (home/public/local/notifications), pf_search,
pf_follow/pf_unfollow, pf_block_user/pf_mute_user
(inline, rate-limited), pf_block_domain/pf_defederate/
pf_import_blocklist (QUEUED via moderation_actions +
notification), pf_review_reports, pf_report_remote,
pf_media_prune. resolveAccount() helper does the
WebFinger-via-search dance shared with F.1. All z.string()
fields bounded with .max(). loadSharedDeps() pattern
from GoToSocial so monorepo + installed-mode both work.
- server/index.js stdio transport.
- panel/pixelfed.js + panel/routes.js Nest panel — instance status +
home-timeline recent posts. XSS-safe
(textContent/createElement). API routes serve
/api/pixelfed/{status,feed}.
- skills/pixelfed.md first-run workflow (APP_KEY gen, Caddy, admin
user, PAT), photo-post/feed/search/follow examples,
moderation + CSAM warning, troubleshooting (horizon,
413 payload, disk pressure).
- scripts/post-install.sh 180s health wait, invokes configure-storage.mjs
if PIXELFED_S3_ENDPOINT is set, prints Caddy + admin +
PAT + baseline-blocklist-import steps.
- scripts/configure-storage.mjs imports storage-translators.pixelfed()
and writes a managed block to .env. Same shape as F.4's
helper — falls back to inline map in installed-mode.
- scripts/backup.sh pg_dump + storage/uploads tar (excludes framework
cache/logs/sessions — regenerable). S3-backed media NOT
in scope.
- package.json MCP + zod deps only.
Integrations with shipped F-series:
- F.0 storage-translators.pixelfed() activated at install time when
PIXELFED_S3_* is set. Same pattern as F.4 — second consumer validates
the translator surface.
- F.0 rate limiter post_photo, feed, search, follow, unfollow, blocks,
mutes, report_remote, import_blocklist, media_prune.
- F.0 hardware gate min/recommended RAM + disk per manifest schema.
- F.1 GoToSocial Mastodon-compatible API overlap confirmed the verb
taxonomy generalizes. pf_search / pf_feed / pf_follow are near-identical
to gts_* equivalents; resolveAccount() is deduplicated here but the
same WebFinger-via-search pattern.
- F.1 federated-media category wiring (extensions.js, nav-registry.js,
i18n) already present — no new wiring needed.
Human-in-the-loop moderation:
- Inline (rate-limited, fires immediately): pf_block_user, pf_mute_user,
pf_report_remote.
- Queued (operator confirms in Nest within 72h): pf_block_domain,
pf_defederate, pf_import_blocklist. Writes moderation_actions row +
surfaces a Crow notification; returns {status: "queued", action_id,
expires_at} to the AI. Confirmation UI lands with F.11.
Image tag policy:
- zknt/pixelfed:0.12 floats within 0.12.x; the CVE feed + release notes
were checked at implementation time. Pin will be re-verified before
merge and bumped if a more current minor is out.
Registry / discovery surface:
- registry/add-ons.json entry inserted before developer-kit.
- skills/superpowers.md trigger row added between funkwhale and tutoring
(EN+ES: pixelfed, post photo, share picture, photo feed, fediverse photo,
instagram alternative).
- CLAUDE.md Skills Reference entry added after funkwhale.md.
Verified:
- node --check on all JS files (server, panel, configure-storage)
- bash -n on both shell scripts
- MCP server boots via createPixelfedServer() with no env set
- docker compose config parses with required env set
- JSON parse on manifest, package, registry
- npm run check passes
Next in the roll-out:
- F.6 Lemmy (link aggregator, 1 GB min)
- F.7 Mastodon (flagship AP, 3 GB min — heaviest small-AP)
- F.8 PeerTube (video, needs S3 + aggressive transcoding policy)
- F.11 identity attestation, F.12 cross-app bridging
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
Second federated-media bundle. Stacked on F.4 (Funkwhale). Pixelfed's Mastodon-compatible API overlaps heavily with F.1 GoToSocial, so this lands as a focused bundle rather than a new abstraction layer.
crow-federationwhere needed; exposed viacaddy_add_federation_site → pixelfed:80with theactivitypubprofile.pf_post_photo(media upload + status in a single call), full moderation surface (inline block/mute, queued domain-block/defederate/blocklist-import), admin reports, remote reporting, and manualpf_media_prune.PIXELFED_S3_*to route through F.0'sstorage-translators.pixelfed()(AWS_* + FILESYSTEM_CLOUD=s3 + PF_ENABLE_CLOUD=true). Second consumer of the translator surface after F.4.min_ram_mb=1500,recommended=3000. Horizon workers + image transforms are the hot paths.Test plan
node --checkon all JS filesbash -non shell scriptscreatePixelfedServer()with no env setdocker compose configparses with required env setnpm run checkpassesIntegration notes
pf_search,pf_feed,pf_followare near-identical togts_*equivalents.resolveAccount()is duplicated here rather than extracted — wait until F.7 Mastodon to decide whether to hoist into a shared helper.loadSharedDeps()pattern from F.1. Works both monorepo-mode and installed-to-~/.crow.zknt/pixelfed:0.12floats within 0.12.x; CVE feed verified at implementation time, will be re-checked before merge.Rollout position
🤖 Generated with Claude Code