Add Rybbit - #32
Open
ClaydeCode wants to merge 1 commit into
Open
Conversation
Privacy-focused web/product analytics (AGPL-3.0). 6-container stack behind an internal caddy path-routing proxy: /api/* -> backend:3001, / -> client:3002. ClickHouse + Postgres + Redis backing services. Config (Caddyfile, ClickHouse XMLs) ships as sidecar files bind-mounted via fs.installation_dir (immich .env precedent), not heredoc injection. Mixed access (dashboard private, /api public for tracking ingestion), always_on, minimum_portal_size m. Template is best-effort and needs a live smoke test (same-origin client routing, ClickHouse enable_json_type, caddy split) before it can be trusted. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
ClaydeCode
force-pushed
the
feat/add-rybbit
branch
from
July 7, 2026 11:21
c5b3c2c to
bace50a
Compare
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.
Rybbit — Add to Freeshard app store
Upstream: https://github.com/rybbit-io/rybbit
Homepage: https://rybbit.com
License: AGPL-3.0 (foss)
Image:
ghcr.io/rybbit-io/rybbit-client:v2.7.0(entrypoint is acaddy:2.10.0proxy in front of it)Last release: 2026-07-07 (v2.7.0)
Preview zip (after CI): https://storageaccountportab0da.blob.core.windows.net/app-store/preview/feat/add-rybbit/all_apps/rybbit/rybbit.zip
What is it
Open-source, privacy-friendly web and product analytics — a self-hostable Google Analytics / Plausible alternative.
Rybbit gives you real-time visitor dashboards, funnels, user journeys, sessions, retention, and event tracking without cookies and without shipping your visitors' data to a third party. A lightweight (~18 KB) tracking script is GDPR/CCPA-friendly and needs no cookie banner. Fully self-contained stack: Next.js dashboard, Node API, ClickHouse for event storage, Postgres for app/auth data, Redis for sessions and jobs. AGPL-3.0; self-hosting is free with no license keys or mandatory cloud services.
Integration decisions
Entrypoint = internal caddy proxy. Rybbit has no single container serving both UI and API. The browser calls same-origin
/api/*(must reachbackend:3001) and everything else (must reachclient:3002). Freeshard routes one subdomain to one port, so acaddy:2.10.0container (container_name: rybbit, port 80) does the path split, reproducing upstream's own Caddyfile. TheCaddyfileships as a sidecar file in the app folder, bind-mounted read-only via{{ fs.installation_dir }}/Caddyfile(immich.envprecedent).Access = mixed paths.
""(dashboard) → private (pairing gates it; better-auth login sits behind pairing; no auth-proxy header support upstream)./api/→ public because the tracking snippet (/api/script.js) and event ingestion must be reachable by visitors of the tracked sites. Backend enforces better-auth on dashboard-data endpoints, matching rybbit's own cloud model.Lifecycle =
always_on: true. Rybbit is an event collector; idle shutdown would drop incoming events from tracked sites.minimum_portal_size: "m"(d2-8, 8 GB). Idle ~2–3 GB exceedss(4 GB);l(16 GB) pads against bias-small policy.mis the compromise — headroom over idle without the largest tier. Smoke test should confirm it holds under ingestion load.Secrets = static (librechat precedent; no random generator in Freeshard templates).
BETTER_AUTH_SECRET+ DB/Redis passwords are fixed values; DBs live on an isolated internalrybbitnetwork and the app is single-tenant + private-gated.user: "0:0"on backend + clickhouse (write to root-ownedfs.app_databind mounts → EACCES otherwise; librechat/vikunja precedent). Client is stateless, left default.ClickHouse config shipped as sidecar files
clickhouse/config.d/rybbit.xml(listen 0.0.0.0, quieter logging) +clickhouse/users.d/rybbit.xml(default-user password +enable_json_typeprofile), bind-mounted into the image's config dirs. Default entrypoint picks them up — nocommandoverride.Telemetry disabled (
DISABLE_TELEMETRY=true). No shared-media volumes (analytics app).Soft warnings
l(ClickHouse is RAM-hungry, always-on stack). Deployed atmas a compromise; watch memory under load.Rejected image candidates
rybbit/*— no official/verified-publisher image; upstream README + compose point to ghcr.io/rybbit-io (org match + docs-linked).rybbit-backend— supporting API service, not the web entrypoint.caddy:2.10.0— upstream's generic proxy, used as the routing entrypoint, not the app identity.Notes from research
Full compose topology, auth model, inter-service env wiring, and deployment quirks are captured in
.add-app-scratch/research_notes.mdin the worktree. Key points:docker execbootstrap (no exit-j).DISABLE_SIGNUPleftfalseso the owner can register; pairing gates the dashboard.NEXT_PUBLIC_BACKEND_URL); prebuilt ghcr client should call relative/api(same-origin) — must verify it doesn't hit a hardcoded cloud URL.--maxmemory-policy noeviction+ AOF (set).Checklist (from agents.md)
just new-app rybbitghcr.io/rybbit-io/rybbit-client, tagv2.7.0) — all 6 stack images verifieddocker-compose.yml.templatesetapp_meta.jsonset (app_version,name,pretty_name,icon,entrypoints,paths,lifecycle,store_info)upstream_reposetupdate_check.pypresent (implemented —latest_github_release)minimum_portal_sizeset (m)always_onsetdocker manifest inspectpassed (all 6 images)Follow-ups
Must smoke-test on a live shard before trusting this template:
/api(same-origin) and not a hardcoded cloud URL. If it bakes an absolute URL, the client image may need rebuilding withNEXT_PUBLIC_BACKEND_URL=https://rybbit.<domain>.enable_json_typeis the correct setting name for ClickHouse 25.4 and that rybbit's schema migrations succeed against it./api/*→backend and/→client both resolve, and admin registration completes through the private dashboard.DISABLE_SIGNUP=truepost-registration if leaving the dashboard private isn't deemed enough.