Published

Plausible Community Edition

Privacy-friendly web analytics without cookies: a lightweight script counts pageviews, sources, goals and custom events, and a one-page dashboard shows them. The self-hosted Community Edition is the Elixir app, PostgreSQL for accounts and sites, and ClickHouse for the events.

Resources by load level

What the app itself needs at each level, next to what we recommend for a server that runs only this app.

LevelWhat it meansApp requirementsRecommended
LightEstimateA few sites with up to 100,000 pageviews a month in total, 1–3 people reading the dashboards, a year of stats kept.2.5 vCPU · 3.5 GiB RAM · 10.5 GiB disk3.12 vCPU · 5.7 GiB RAM · 21.62 GiB disk
MediumEstimateUp to 1 million pageviews a month across a dozen sites, goals and custom events, a team of up to 10 on the dashboards, a year of stats kept.4 vCPU · 5.5 GiB RAM · 16.5 GiB disk4.92 vCPU · 8.1 GiB RAM · 28.52 GiB disk
HeavyEstimateUp to 10 million pageviews a month across many sites, with goals, custom properties and Stats API use, a year of stats kept.7 vCPU · 11 GiB RAM · 60.5 GiB disk8.52 vCPU · 14.7 GiB RAM · 79.12 GiB disk

Recommended = app requirements + system baseline + safety headroom, under sizing policy 2026.10.0. Options stay at their defaults. “Estimate” means the sources give no number for that case, so it is worked out from them by the method stated under Components. How the numbers are built

Size it in the Stack Sizer

Ready-to-run files

Support level Supported

Compose template from the official sources; not yet verified by a run.

Create docker-compose

Components

What each component needs at each load level, before baseline and headroom.

vCPU / GiB RAM / GiB disk
ComponentLightMediumHeavySources
Plausible (web app and event ingestion) (app)0.5 / 1 / 11 / 1.5 / 22 / 2 / 4[2][9][25][33]
PostgreSQL (database)1 / 1 / 6.51 / 1 / 6.51 / 1 / 6.5[9][37][40][41][42][43][44][45][46]
ClickHouse (analytics events) (database)1 / 1.5 / 32 / 3 / 84 / 8 / 50[5][24][25][30][36]
How the estimates are worked out
  • Plausible (web app and event ingestion) · Light: The README asks for at least 2 GB of RAM for ClickHouse and Plausible together; ~40 pageviews an hour on average barely load the Elixir app: 1 GiB, half a core. Disk: image 64.8 MB compressed × 3 (0.18 GiB) plus the data volume (time zone data and temporary CSV import and export files under TMPDIR), rounded up to 1 GiB.
  • Plausible (web app and event ingestion) · Medium: About 0.4 pageviews a second on average, with peaks several times that, plus the engagement event each page sends: one core and 1.5 GiB for the ingestion buffers, caches and dashboard requests. Disk: 0.18 GiB image + room for CSV imports and exports in TMPDIR, rounded up to 2 GiB.
  • Plausible (web app and event ingestion) · Heavy: About 4 pageviews a second on average and tens at peaks, each with an engagement event, plus API and dashboard traffic: 2 cores and 2 GiB. Disk: 0.18 GiB image + room for large CSV imports and exports in TMPDIR, rounded up to 4 GiB.
  • PostgreSQL · Light: PostgreSQL holds users, sites, goals and the job queue (job history pruned after 30 days); events live in ClickHouse. Plausible.Repo sets no pool_size, so Ecto's default of 10 connections applies, inside the sidecar's 20. Light preset method: shared_buffers 25% of RAM, 0.5 GiB image + 5 GiB data + 1 GiB WAL.
  • PostgreSQL · Medium: Sites, goals, team members and the job queue stay far below 5 GB; Ecto's default pool of 10 connections stays inside 20. Light preset method: shared_buffers 25% of RAM, 0.5 GiB image + 5 GiB data + 1 GiB WAL.
  • PostgreSQL · Heavy: Traffic volume lands in ClickHouse, not PostgreSQL: account and site data stay far below 5 GB, and Ecto's default pool of 10 connections stays inside 20. Light preset method: shared_buffers 25% of RAM, 0.5 GiB image + 5 GiB data + 1 GiB WAL.
  • ClickHouse (analytics events) · Light: ClickHouse runs on as little as 2 GB only when tuned, and the template cannot apply upstream's 1-thread query profile, so 1.5 GiB and one core. Disk: image 154.9 MB compressed × 3 (0.43 GiB) + a year of events (100,000 pageviews × an assumed 2 stored rows (pageview and engagement event) × 200 B = 0.45 GiB) + ~1 GiB of system log tables at a 3-day TTL + 0.5 GiB server logs, rounded up to 3 GiB.
  • ClickHouse (analytics events) · Medium: Dashboards scan up to ~24 million rows for a year; with every core in use per query, 3 GiB and 2 cores, still well under the 16 GB below which ClickHouse's docs call for tuning. Disk: 0.43 GiB image + 1,000,000 pageviews × 12 × 2 rows × an assumed 200 B (4.47 GiB) + 1.5 GiB system log tables + 0.5 GiB server logs, rounded up to 8 GiB.
  • ClickHouse (analytics events) · Heavy: A year is ~240 million rows; long date ranges and breakdowns read large parts of them, so 4 cores and 8 GiB, half the 16 GB under which the docs call for tuning. Disk: 0.43 GiB image + 10,000,000 pageviews × 12 × 2 rows × an assumed 200 B (44.7 GiB) + 2 GiB system log tables + 0.5 GiB server logs, rounded up to 50 GiB.

Ports

Public ports are meant to be reached from outside the stack, usually through a reverse proxy; internal ones stay on the stack's own network.

ComponentPortExposurePurposeSources
Plausible (web app and event ingestion)8000/tcpPublic, through a proxyDashboard, tracking script, event API (/api/event) and Stats API (HTTP; put behind TLS)[7][13]
PostgreSQL5432/tcpInternal onlyPostgreSQL connections from Plausible (accounts, sites, job queue)[13][45]
ClickHouse (analytics events)8123/tcpInternal onlyClickHouse HTTP interface: Plausible writes and queries events here[13][18]
ClickHouse (analytics events)9000/tcpInternal onlyClickHouse native protocol (clickhouse-client); not used by Plausible[15][18]
ClickHouse (analytics events)9004/tcpInternal onlyClickHouse MySQL wire protocol, on by default; not used by Plausible[18]
ClickHouse (analytics events)9005/tcpInternal onlyClickHouse PostgreSQL wire protocol, on by default; not used by Plausible[18]
ClickHouse (analytics events)9009/tcpInternal onlyClickHouse interserver replication port; unused on a single node[15][18]

Every port in the catalog, with conflicts between apps

User and permissions (UID/GID)

The user each container's process runs as, and the paths it writes to. A bind mount for one of these paths must be writable by that UID:GID.

ComponentUID:GIDUserStarts as rootWrites toSources
Plausible (web app and event ingestion)Derived999:65534plausibleNo/var/lib/plausible[7][33]
PostgreSQL999:999postgresYes, prepares its directories, then drops to this user/var/lib/postgresql/var/run/postgresql[38][39][45]
ClickHouse (analytics events)101:101clickhouseYes, prepares its directories, then drops to this user/var/lib/clickhouse/var/log/clickhouse-server[15][16]
  • Plausible (web app and event ingestion): The Dockerfile adds user plausible (uid 999) to Alpine's nogroup (gid 65534) and sets USER 999; the image config confirms User 999. /var/lib/plausible is created world-writable for arbitrary uids, so a new named volume works; TMPDIR points inside it.

Storage growth

How much each component's data grows per month at each load level, on top of the disk in the profile. A value marked Assumption is ANAROQ's stated assumption, not a figure from the sources; the notes say what it rests on.

GiB per month
ComponentLightMediumHeavySources
Plausible (web app and event ingestion)Assumption000[2][9]
PostgreSQLAssumption0.0050.010.02[9]
ClickHouse (analytics events)Assumption0.0370.3733.725[30][32]
What the growth figures rest on
  • Plausible (web app and event ingestion): The data volume holds time zone data and temporary CSV import and export files, which are replaced rather than accumulated; stats live in ClickHouse.
  • PostgreSQL: Accounts, sites, goals and invitations grow slowly; the Oban job history is pruned after 30 days, so the job queue stays level. An assumed few MB a month, more with more sites and users.
  • ClickHouse (analytics events): Monthly pageviews (100,000, 1 million, 10 million) × an assumed 2 stored rows each (the pageview and, since v3.0.0, an engagement event) × an assumed 200 B compressed per row with its session data. CE keeps events with no retention limit, so this adds up for as long as the instance runs; system log tables stay bounded by their TTL.

Upgrade and rollback

How to move to a new version safely, and how to go back if it fails.

Back up first

Migrations change both databases: first take a pg_dump of plausible_db, then stop the stack and archive the ClickHouse event-data volume, and keep the .env. [2][29]DerivedThe wiki shows pg_dump for PostgreSQL; for ClickHouse it gives no backup procedure, so a cold copy of its volume with the stack stopped is the safe equivalent.

Upgrade steps

  1. Read the CHANGELOG and the release notes of every version between yours and the new one: each release carries its own upgrade instructions, and security fixes are not backported. [28][30]
  2. Change the pinned community-edition tag, then run docker compose pull and docker compose up -d. The start command creates the databases if needed and runs the PostgreSQL and ClickHouse migrations before the app listens; follow docker compose logs -f plausible until it is ready. [2][8][28]
  3. Change the ClickHouse tag only to the one the new release's compose.yml pins, as v3.0.0 did (24.3 to 24.12). A PostgreSQL major upgrade needs a dump and restore, as the PostgreSQL upgrade guide shows. [26][27][29]DerivedThe upgrade guide covers the Plausible image; the ClickHouse step follows from upstream changing the ClickHouse tag in its compose.yml at v3.0.0.

Roll back

Restore the PostgreSQL dump and the ClickHouse volume from before the upgrade and pin the image back to the previous tag. Both are needed: an older release cannot read tables a newer migration has changed. [8][28]DerivedThe wiki recommends pinning a patch version so a known tag can be restored; migrations only run forward, so the data has to go back with it.

Known breaking changes

  • In 3.0.0: The official compose moved ClickHouse from 24.3.3.102 to 24.12. The tracker sends an engagement event with scroll depth (sd) and engaged time (e), which custom script proxies must pass on; time on page is computed from it. /api/health is soft-deprecated in favour of /api/system/health/live and /ready, and internal stats routes dropped the legacy filter format. [26][27][30]
  • In 2.1.0: ECTO_IPV6 and ECTO_CH_IPV6 are deprecated (connections try IPv6, then IPv4), DATABASE_SOCKET_DIR is soft-deprecated, imports from Universal Analytics are gone, and 'is' filters no longer take wildcards. [30]
  • In 2.0.0: The IP_BLOCKLIST variable and its firewall plug were removed, and changing a site's domain needs a numeric-ID data migration. [30]

Limits

  • CE is a long-term release published about twice a year and lacks some Cloud features: marketing funnels, user journeys, ecommerce revenue goals, SSO and the sites API. Bot filtering is basic (User-Agent and referrer spam only), and support is community-only. [32]
  • ClickHouse needs a CPU with SSE 4.2 (or NEON on ARM) and is tuned upstream for small machines with XML files the template cannot mount; only the server settings among them are applied here, so plan RAM by the presets rather than the README's 2 GB. [5][24][25]
  • The template writes no mail settings. Without SMTP_HOST_ADDR, Plausible tries to deliver invitations, password resets and reports itself over port 25, which many providers block or flag as spam; add an SMTP relay to the .env for email to work. [13]

Security

  • Serve Plausible over HTTPS from a reverse proxy with BASE_URL set to https://<domain>; cookies are marked secure only for an https BASE_URL, and the proxy must pass WebSocket upgrades on /live/websocket. [13][14][30]
  • On first launch anyone who reaches the instance can register the owner account, whatever DISABLE_REGISTRATION says. Create it right after the first start; afterwards only invited people can sign up (invite_only, the CE default). [12][13]
  • ClickHouse's default user has no password and the compose turns off the image's localhost-only lock (CLICKHOUSE_SKIP_USER_SETUP=1) so Plausible can connect. Never publish ports 8123, 9000, 9004 or 9005; the template keeps them inside the stack. [2][16][19]
  • Without TOTP_VAULT_KEY, the key that encrypts users' 2FA secrets is derived from SECRET_KEY_BASE. Keep SECRET_KEY_BASE in the backup and never rotate it casually, or existing 2FA setups stop working. [9][13]

Backup

  • Back up three things together: a pg_dump of plausible_db (users, sites, goals), the ClickHouse event-data volume (every pageview and event, copied with the stack stopped), and the .env (SECRET_KEY_BASE and the database password). [2][13][29]
  • For a portable copy of a site's stats, use Site Settings > Imports & Exports: the CSV export includes properties since v3.1.0 and can be imported into another Plausible instance or the Cloud. [30][32]

Latest release

Newest upstream release
Plausible Community Edition 3.2.1 [28][30][35]
This profile was checked against

Plausible Community Edition 3.2.1

This profile was checked against the newest release.

Checked on
14 Oct 2026
State
Checked within the last 90 days
Where releases are published
GitHub Releases

Latest releases of every app

Version

Profile status
Published
Checked against release
Plausible Community Edition 3.2.1
Profile version
1.0.0
Figures verified
14 Oct 2026
Catalog release
2026.10.10
Sizing policy
2026.10.0
Compose file
Unverified

Sources

  1. Docker Docs: Control startup order in Compose (pg_isready healthcheck, service_healthy) (Official docs · read 11 Oct 2026)
  2. community-edition repository: compose.yml at v3.2.1 (postgres:16-alpine; clickhouse-server:24.12-alpine, 4 XML mounts, nofile 262144; plausible: db createdb, db migrate, run; TMPDIR) (Official Compose · read 14 Oct 2026)
  3. community-edition repository: clickhouse/logs.xml at v3.2.1 (logger warning, query_log TTL 30 days, removes metric, async metric, query_thread, text, trace, session, part logs) (Official Compose · read 14 Oct 2026)
  4. community-edition repository: clickhouse/low-resources.xml at v3.2.1 (mark_cache_size 524288000) (Official Compose · read 14 Oct 2026)
  5. community-edition repository: clickhouse/default-profile-low-resources-overrides.xml at v3.2.1 (max_threads 1, max_block_size 8192, max_download_threads 1, parallel parsing and formatting off) (Official Compose · read 14 Oct 2026)
  6. community-edition repository: clickhouse/ipv4-only.xml at v3.2.1 (listen_host 0.0.0.0, against 'Listen [::]:9000 failed' warnings) (Official Compose · read 14 Oct 2026)
  7. plausible/analytics repository: Dockerfile at v3.2.1 (alpine:3.22.2, user plausible uid 999 in nogroup, /var/lib/plausible world-writable VOLUME, LISTEN_IP 0.0.0.0, EXPOSE 8000, no HEALTHCHECK) (Official repository · read 14 Oct 2026)
  8. plausible/analytics repository: rel/docker-entrypoint.sh at v3.2.1 ('run' starts the release, 'db <script>' runs createdb.sh or migrate.sh) (Official repository · read 14 Oct 2026)
  9. plausible/analytics repository: config/runtime.exs at v3.2.1 (HTTP_PORT 8000; SECRET_KEY_BASE ≥ 32 bytes; TOTP key derived from it; DISABLE_REGISTRATION invite_only; no Repo pool_size) (Official repository · read 14 Oct 2026)
  10. plausible/analytics repository: lib/plausible_web/router.ex at v3.2.1 (GET /api/system/health/live and /api/system/health/ready; /api/health kept for old checks) (Official repository · read 14 Oct 2026)
  11. plausible/analytics repository: Api.SystemController at v3.2.1 (liveness returns ok; readiness runs SELECT 1 on PostgreSQL and ClickHouse and checks caches, 500 until all are ok) (Official repository · read 14 Oct 2026)
  12. plausible/analytics repository: MaybeDisableRegistration plug at v3.2.1 (registration stays open on first launch, whatever DISABLE_REGISTRATION says) (Official repository · read 14 Oct 2026)
  13. Plausible CE wiki: Configuration (BASE_URL, SECRET_KEY_BASE ≥ 64 bytes; TOTP_VAULT_KEY optional; DISABLE_REGISTRATION invite_only; HTTP_PORT 8000; database URLs; SMTP) (Official docs · read 14 Oct 2026)
  14. Plausible CE wiki: Reverse Proxy (HTTP_PORT 8000 on loopback, proxy to it, /live/websocket needs the Upgrade headers, domain must match BASE_URL) (Official docs · read 14 Oct 2026)
  15. ClickHouse repository: Dockerfile.alpine at v24.12.6.70-stable (alpine, busybox wget; clickhouse uid/gid 101; VOLUME /var/lib/clickhouse; EXPOSE 9000 8123 9009; no HEALTHCHECK) (Official repository · read 14 Oct 2026)
  16. ClickHouse repository: docker entrypoint.sh at v24.12.6.70-stable (-- args go to clickhouse-server, as its own '-- --listen_host'; wget --spider /ping; chown, then uid 101; SKIP_USER_SETUP) (Official repository · read 14 Oct 2026)
  17. ClickHouse repository: docker/server/docker_related_config.xml at v24.12.6.70-stable (listen_host :: and 0.0.0.0 with listen_try 1) (Official repository · read 14 Oct 2026)
  18. ClickHouse repository: config.xml at v24.12.6.70-stable (logger trace, 10 × 1000M files; ports 8123, 9000, 9004, 9005, 9009; most system log tables without TTL) (Official repository · read 14 Oct 2026)
  19. ClickHouse repository: programs/server/users.xml at v24.12.6.70-stable (user default with an empty password, default profile without overrides) (Official repository · read 14 Oct 2026)
  20. ClickHouse repository: base/base/argsToConfig.cpp at v24.12.6.70-stable (each --key=value argument becomes a config layer; dotted keys address nested elements) (Official repository · read 14 Oct 2026)
  21. ClickHouse repository: src/Interpreters/SystemLog.cpp at v24.12.6.70-stable (without an engine element, a system table is MergeTree with PARTITION BY, the '<table>.ttl' setting as TTL, and ORDER BY) (Official repository · read 14 Oct 2026)
  22. ClickHouse repository: src/Loggers/Loggers.cpp at v24.12.6.70-stable (logger.level, default trace, sets the level of every logger and so of what reaches text_log) (Official repository · read 14 Oct 2026)
  23. ClickHouse repository: programs/server/Server.cpp at v24.12.6.70-stable (loggers built from the full config at start; a config reload resets log levels from the config files only) (Official repository · read 14 Oct 2026)
  24. ClickHouse Docs: Using less than 16GB of RAM (32 GB recommended; 2 GB needs tuning: 500 MB mark cache, 1 thread; disable asynchronous_metric_log, metric_log, text_log, trace_log) (Official docs · read 14 Oct 2026)
  25. community-edition repository: README.md at v3.2.1 (CPU with SSE 4.2 or NEON; at least 2 GB RAM for ClickHouse and Plausible; SECRET_KEY_BASE ≥ 64 bytes; first user at BASE_URL) (Official docs · read 14 Oct 2026)
  26. community-edition repository: compose.yml at v2.1.5 (clickhouse/clickhouse-server:24.3.3.102-alpine) (Official Compose · read 14 Oct 2026)
  27. community-edition repository: compose.yml at v3.0.0 (clickhouse/clickhouse-server:24.12-alpine) (Official Compose · read 14 Oct 2026)
  28. Plausible CE wiki: Upgrade (pin a patch version, recommended; security fixes are not backported; read each release's instructions; pull the new tag and docker compose up -d) (Official docs · read 14 Oct 2026)
  29. Plausible CE wiki: Upgrade PostgreSQL (from 12 or later to 16 or later with pg_dump and psql; Plausible stopped meanwhile) (Official docs · read 14 Oct 2026)
  30. plausible/analytics repository: CHANGELOG.md at v3.2.1 (v3.0.0 engagement events and /api/health soft-deprecation; v3.1.0 full site exports; v2.1.0 removals; v2.0.0 IP_BLOCKLIST removed) (Release notes · read 14 Oct 2026)
  31. plausible/analytics repository: LICENSE.md at v3.2.1 (GNU AGPL v3) (Official repository · read 14 Oct 2026)
  32. Plausible: Self-hosted web analytics (CE AGPLv3, twice a year; no funnels, journeys, revenue goals, SSO, sites API; basic bot filtering; Plausible Analytics Cloud is managed) (Official docs · read 14 Oct 2026)
  33. GHCR manifest of ghcr.io/plausible/community-edition:v3.2.1 (linux/amd64): 64,805,743 B compressed in its layers; built 2026-05-15 from plausible/analytics e4f5a87, user 999 (Measurement · read 14 Oct 2026)
  34. GHCR blob sha256:2d35ebdb… of community-edition:v3.2.1 (linux/amd64, Alpine 3.22.2 base layer): contains usr/bin/wget -> /bin/busybox (Measurement · read 14 Oct 2026)
  35. GHCR tags of ghcr.io/plausible/community-edition (newest release v3.2.1; v3.2, v3 and latest move with it) (Official repository · read 14 Oct 2026)
  36. Docker Hub: clickhouse/clickhouse-server tag 24.12.6.70-alpine (linux/amd64 154,945,233 B compressed; same digest as 24.12-alpine) (Official repository · read 14 Oct 2026)
  37. Ecto Docs: Ecto.Repo (pool_size defaults to 10) (Official docs · read 14 Oct 2026)
  38. docker-library/postgres: 18/trixie Dockerfile (postgres uid/gid 999, VOLUME /var/lib/postgresql) (Official repository · read 14 Oct 2026)
  39. docker-library/postgres: 18/trixie docker-entrypoint.sh (chown PGDATA, then gosu postgres) (Official repository · read 14 Oct 2026)
  40. PostgreSQL 18 documentation: 19.4 Resource Consumption (Official docs · read 10 Oct 2026)
  41. PostgreSQL 18 documentation: 19.3 Connections and Authentication (Official docs · read 10 Oct 2026)
  42. PostgreSQL 18 documentation: 19.10 Vacuuming (autovacuum settings) (Official docs · read 10 Oct 2026)
  43. PostgreSQL 18 documentation: 19.5 Write Ahead Log (max_wal_size) (Official docs · read 10 Oct 2026)
  44. PostgreSQL 18 documentation: 51.2 How Connections Are Established (Official docs · read 10 Oct 2026)
  45. Docker Official Image postgres: documentation (docker-library/docs) (Official docs · read 10 Oct 2026)
  46. Docker Hub: library/postgres tag 18.6 (compressed image sizes) (Official repository · read 10 Oct 2026)

All self-hosted apps