You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Open Analytics (https://github.com/OpenLabs-so/openanalytics), an AGPL-3.0,
privacy-first web analytics stack, as one Compose template: fourteen
containers (eleven long-running, three one-shots that exit by design), four
generated domains, every secret generated by template.toml. The signing
keypairs and the 32-byte credential keyring cannot come from the template's
generators (their halves must match across services), so a keygen one-shot
creates them inside the stack, idempotently.
All four domains deliberately route to the in-stack Caddy edge service: it
deletes client-settable identity headers (CF-Connecting-IP and family) before
the collector, the api or the realtime stream read them; without that, any
visitor can pick their own rate-limit bucket or write their own country into
the analytics. Please keep that shape in review.
Tested (per CONTRIBUTING)
Fresh Dokploy on a 4 GB Hetzner instance (x86-64, Ubuntu 26.04), 2026-08-20:
Import, then deploy: twelve images pulled (about 2 GB), fourteen containers,
the three one-shots exited 0, the rest healthy, web last.
Enabled HTTPS with Let's Encrypt on the four domains and redeployed (the
template format has no certificate field); certificates issued within a
minute.
Created the first account, added a site, installed the snippet on a real
page: the pageview landed in the realtime dashboard.
node generate-meta.js --check passes with the blueprint added.
Notes
Images are version-pinned (v0.5.0) and pulled from GHCR; nothing builds at
deploy time.
The geo database is DB-IP City Lite (CC BY 4.0), fetched by a one-shot on
the first deploy; attribution ships in-product.
Tested this on a Dokploy instance (imported the blueprint as-is, fresh volumes). Summary: it works end to end, no changes needed from my side.
Upstream / legitimacy
OpenLabs-so/openanalytics is young (created 2026-08-11) but substantive: 100+ commits from 3 human contributors, 11 tagged releases (v0.1.0 → v0.5.0), CI + leak-scan workflows green, AGPL-3.0, live site at getopen.so, 33 forks spread evenly over the last two weeks. PR author has a GitHub account since 2022 and is the release author upstream.
All 9 pinned images (ghcr.io/openlabs-so/openanalytics/{clickhouse,valkey,migrate,query-gateway,api,collector,realtime,worker,web}:v0.5.0) are public: manifest → 200 without auth.
Conventions
No ports/container_name/external networks, per-template meta.json with a real logo, every secret generated by template.toml, images pinned to v0.5.0. generate-meta.js --check, validate-docker-compose.ts and validate-template.ts all pass. The ../files/Caddyfile mount matches how Dokploy materialises [[config.mounts]].
Nit (non-blocking): expose: ['80'] on edge is redundant (Traefik routes by container port anyway).
Deploy evidence (14 containers, done in ~270 s)
11 long-running containers running + healthy (edge has no healthcheck), RestartCount 0 on all of them; the three one-shots keygen, geoip, migrate exited 0.
Through Traefik (4 generated domains, all hitting edge):
app: GET /login → 200 «Open Analytics»
api: GET /health → 200 {"status":"ok","service":"api",...}; GET / → JSON 404 from the api itself (expected)
collector: GET /health → 200, GET /oa.js → 200 text/javascript
realtime: GET /health → 200
Signup path works: POST {api}/api/auth/sign-up/email → 200 (user created).
One thing worth stating in the description / docs: the compose hardcodes https:// for AUTH_BASE_URL, AUTH_TRUSTED_ORIGINS and the NEXT_PUBLIC_* URLs. On a plain-HTTP deploy (the default generated domains before enabling HTTPS), the dashboard cannot log in — the api answers 403 {"code":"INVALID_ORIGIN"} to requests with an http:// origin (verified). So HTTPS must be enabled on all four domains before first use. That is documented in the template.toml comment and in DOKPLOY.md, so this is just a heads-up for users, not a blocker; the author already tested the Let's Encrypt path.
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
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.
What this adds
Open Analytics (https://github.com/OpenLabs-so/openanalytics), an AGPL-3.0,
privacy-first web analytics stack, as one Compose template: fourteen
containers (eleven long-running, three one-shots that exit by design), four
generated domains, every secret generated by template.toml. The signing
keypairs and the 32-byte credential keyring cannot come from the template's
generators (their halves must match across services), so a keygen one-shot
creates them inside the stack, idempotently.
All four domains deliberately route to the in-stack Caddy
edgeservice: itdeletes client-settable identity headers (CF-Connecting-IP and family) before
the collector, the api or the realtime stream read them; without that, any
visitor can pick their own rate-limit bucket or write their own country into
the analytics. Please keep that shape in review.
Tested (per CONTRIBUTING)
Fresh Dokploy on a 4 GB Hetzner instance (x86-64, Ubuntu 26.04), 2026-08-20:
the three one-shots exited 0, the rest healthy,
weblast.template format has no certificate field); certificates issued within a
minute.
page: the pageview landed in the realtime dashboard.
node generate-meta.js --checkpasses with the blueprint added.Notes
v0.5.0) and pulled from GHCR; nothing builds atdeploy time.
the first deploy; attribution ships in-product.
https://github.com/OpenLabs-so/openanalytics/blob/main/infra/selfhost/DOKPLOY.md