mirror of
https://github.com/Dokploy/templates.git
synced 2026-07-24 15:25:23 +02:00
* fix: meta.json of Poke blueprint The current github/docs links was broken before: https://codeberg.org/ashley/poke after: https://codeberg.org/ashleyirispuppy/poke * fix: broken links in some blueprints * Add openhabittracker blueprint * fix(affinepro): update to current AFFiNE images The template pinned ghcr.io/toeverything/affine-graphql:stable-780dd83, an ephemeral per-commit tag on the old image name that has since been removed from GHCR, so the template could no longer pull and deploy. - Switch both app and migration services to ghcr.io/toeverything/affine:stable, the rolling stable tag recommended by the official self-host compose, so the template no longer rots when per-commit tags are garbage-collected - Move postgres to pgvector/pgvector:pg16 and set AFFINE_INDEXER_ENABLED=false, matching the current upstream self-host compose requirements - Add postgres/redis healthchecks and proper depends_on conditions so the self-host-predeploy migration job runs only once the database is ready, and the server starts only after migrations complete successfully Closes #777 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(cockpit): persist config and storage volumes per upstream docs The template mounted `html:/var/www/html` (freezing the app code from the first deploy) and `data:/var/www/html/storage/data`, which misses uploaded assets (stored under `storage/uploads`) and cache. Per the official Cockpit persistent-storage docs, mount `config:/var/www/html/config` and `storage:/var/www/html/storage` instead. Closes #549 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(kener): define REDIS_URL and drop unused databases Kener v4 requires Redis for its BullMQ queues, caching and scheduler, so the app crashed on startup with "REDIS_URL is not defined in environment variables" right after printing that it was running (issue #976). The template also spun up both a postgres and a mariadb container while DATABASE_URL pointed at SQLite, so neither database was ever used (issue #282). Changes, aligned with the upstream docker-compose.yml (rajnandan1/kener): - Add a redis:7-alpine service with a healthcheck and persistent volume, wire REDIS_URL=redis://redis:6379 and make kener depend on redis being healthy - Remove the unused postgres and mysql services plus their env vars and generated passwords; keep SQLite (upstream default) persisted in the kener_db volume - Set ORIGIN to https://<domain> instead of http://localhost:3000 so CSRF protection works behind the generated domain - Drop the stale /app/uploads bind mount (kener v4 only persists /app/database) and the obsolete compose version key Deploy-tested on a Dokploy instance: migrations and seed complete, schedulers start, "Kener version 4.1.2 is running!", HTTP 200 on the generated domain, both containers stable. Closes #976 Closes #282 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(homarr): use named volume for /appdata and hex encryption key - Replace the relative bind mount `../homarr/appdata:/appdata` with a named volume `homarr_appdata:/appdata` so the data survives cleanups and can be backed up through Dokploy volume backups. - Generate SECRET_ENCRYPTION_KEY with `${hash:64}` instead of `${password:64}`: homarr requires a 64-character hex string (`openssl rand -hex 32`) and the password helper emits non-hex characters (g-z). Closes #738 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(logto): fix postgres role error and update to 1.41.0 The postgres healthcheck ran pg_isready without -U while POSTGRES_USER was set to logto, so every probe attempted to connect as role "postgres" and spammed FATAL: role "postgres" does not exist. Pass -U logto -d logto explicitly and set POSTGRES_DB. Also fix LOGTO_ENDPOINT pointing at the admin domain instead of the main domain, update Logto 1.27.0 -> 1.41.0, use ${password:32} for the generated password, drop the ephemeral host port publishing and add restart policies. Closes #130 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(gitlab-ce): serve on the generated domain (remove removed unicorn config, pin omnibus) The template set unicorn['worker_processes'] / unicorn['worker_timeout'] in GITLAB_OMNIBUS_CONFIG. Unicorn was removed in GitLab 14.0, so on current gitlab-ce images `gitlab-ctl reconfigure` aborts with "Removed configurations found in gitlab.rb" and GitLab never starts serving — the generated domain returned 502 Bad Gateway (issue #380). Rewrite the template as the official all-in-one Omnibus setup: - pin gitlab/gitlab-ce:19.1.2-ce.0 instead of :latest - external_url http://<domain> with nginx listen_port 80 / listen_https false (TLS terminates at Traefik) - set gitlab_rails['initial_root_password'] from a generated template password - puma single mode + prometheus monitoring off to keep memory reasonable - drop the external postgres/redis containers (Omnibus bundles and manages its own) and the broken ports entries ("2224" published a random host port while sshd listens on 22) Verified on a live Dokploy instance: domain serves the GitLab sign-in page and root login with the generated password works. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(zitadel): wire EXTERNALDOMAIN/PORT/SECURE to the generated domain Zitadel resolves its instance from the external domain/port/scheme, so the template's ZITADEL_EXTERNALPORT=8080 made every generated URL (OIDC issuer, login redirects) point at http://<domain>:8080 instead of the domain served by Traefik, ending in {"code":5,"message":"Not Found"} (#516). - Expose ZITADEL_EXTERNALDOMAIN / ZITADEL_EXTERNALPORT / ZITADEL_EXTERNALSECURE as template env vars, defaulting to the generated domain over HTTP (port 80, secure=false) so the routed domain and Zitadel's external config always match; HTTPS users flip them to 443/true in the Env tab. - Pin image to v4.16.0 (was latest) and keep the built-in login v1 via ZITADEL_DEFAULTINSTANCE_FEATURES_LOGINV2_REQUIRED=false so no separate login-v2 container is needed. - Add the official readiness healthcheck, drop the unused /app/data volume, bogus SMTP env keys, published port and obsolete compose version key. Closes #516 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(immich): update to v3.0.2 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(automatisch): switch to official image and wire up DOMAIN to fix Bad Gateway - Replace unofficial dockeriddonuts/automatisch:2.0 mirror (stale since Nov 2024) with the official automatischio/automatisch:0.15.0 image - Define DOMAIN in template.toml [config.env]: the compose referenced ${DOMAIN} but it was never provided, so HOST resolved empty and the app generated localhost URLs for the web app and webhooks - Set API_URL/WEB_APP_URL so generated URLs don't carry the internal :3000 port behind Traefik - Add postgres healthcheck and gate the app on service_healthy to avoid the boot-time migration race; worker now starts after main (official compose order) - Drop unnecessary published port and no-op REDIS_* env on the redis service - Bump meta.json version to 0.15.0 Closes #97 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(signoz): fix ClickHouse hostname resolution and IPv6 binding - Override the ClickHouse image's config.d/docker_related_config.xml, which listens on the IPv6 wildcard address ([::]) first and fails to bind on hosts without IPv6 support; listen on 0.0.0.0 (IPv4) only and disable the internal DNS cache so transient startup DNS failures for zookeeper-1/clickhouse are not cached (issue #534). - Set hostname: clickhouse (instead of container_name) so the server identifies itself as the cluster host declared in cluster.xml. - Remove the explicit signoz-net network: Dokploy attaches its own networks automatically and the repo validator rejects explicit networks; a fixed-name shared network also breaks service DNS across deployments. - Fix mount mismatch: template.toml created files/signoz/prometheus.xml while the compose mounts ../files/signoz/prometheus.yml, so Docker silently mounted a directory as the signoz prometheus config. - Give the otel-collector domain its own generated host: both domains previously shared the same host and path "/", creating two conflicting Traefik routers where one service randomly won. Closes #534 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(infisical): update to v0.162.6 - Bump image from v0.135.0-postgres to v0.162.6 (upstream dropped the -postgres tag suffix after v0.146.0; plain tags are the postgres build) - Remove the db-migration service: the standalone image runs database migrations automatically on boot (auto-start-migrations), matching the official docker-compose.prod.yml which no longer ships that service - Generate ENCRYPTION_KEY (${hash:32}) and AUTH_SECRET (${base64:32}) per deployment instead of shipping hardcoded example secrets - Fix SITE_URL to http://${main_domain} (no :8080; the domain is proxied) - Refresh SMTP env names (SMTP_FROM_ADDRESS/SMTP_FROM_NAME; SMTP_SECURE was removed upstream) and drop unused CLIENT_* env placeholders that were never passed to the container Closes #215 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix: add databasus (postgresus renamed upstream) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(evolutionapi): enable integration flags and update version Adds the integration enable env flags introduced in Evolution API v2.3.x (N8N_ENABLED, OPENAI_ENABLED, EVOAI_ENABLED, DIFY_ENABLED, TYPEBOT_ENABLED, CHATWOOT_ENABLED) so integrations no longer fail with 'N8n is disabled', and pins the image to v2.3.7 instead of latest. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(rybbit): update to v2.7.0 The template shipped rybbit v1.5.1, which is no longer supported and is vulnerable to known React2Shell exploits (see #659). Update to the latest stable release v2.7.0 and align the stack with the upstream docker-compose: - Pin ghcr.io/rybbit-io/rybbit-backend and rybbit-client to v2.7.0 - Add the redis service now required by the backend (session tracking and BullMQ queues), with password auth, AOF persistence and noeviction policy per upstream - Drop the DOMAIN_NAME env var (only used by the upstream Caddy webserver, which Dokploy replaces with Traefik) - Add DISABLE_TELEMETRY env and generate BETTER_AUTH_SECRET as base64 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(phpmyadmin): raise PHP upload limit so SQL imports over 2MB work Without UPLOAD_LIMIT the phpMyAdmin image keeps PHP's default 2M post_max_size/upload_max_filesize, so importing any SQL file larger than 2MB fails with 'POST Content-Length exceeds the limit of 2097152 bytes' followed by a session_start error page. - Add UPLOAD_LIMIT (512M) and MAX_EXECUTION_TIME (600) env vars, configurable from the template env - Wire the previously unused MYSQL_DATABASE env var into the compose file, replacing the hardcoded 'tu_base_de_datos' placeholder, and default it to 'phpmyadmin' instead of the system 'mysql' schema Closes #236 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(openpanel): pin verified 2.2.1 images and fix ClickHouse interserver host - Pin lindesvard/openpanel-api|dashboard|worker to 2.2.1 (verified working end-to-end on a Dokploy instance) instead of the mutable :2 tag, so a future broken 2.x release cannot silently break the template again — which is how #615 originated when 2.0.0 shipped. - Fix interserver_http_host to match the actual service name (op-ch), aligning with upstream self-hosting config. - Set meta.json version to the pinned 2.2.1. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(wordpress): route loopback requests through Traefik to fix cURL error 28 WordPress resolves its own public domain to the server's public IP from inside the container, so REST API / WP-Cron / Site Health loopback requests depend on hairpin NAT, which times out (cURL error 28) on many hosts. Pin the site domain to the dokploy-traefik container IP in /etc/hosts at startup (with retries, since Traefik joins the compose network shortly after the container starts) so loopback traffic stays inside the Docker network for both HTTP and HTTPS. No-op fallback when dokploy-traefik is not resolvable. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(minio): migrate to pgsty/minio community fork (upstream is source-only and archived) MinIO Inc. stopped publishing Docker images and pre-built binaries in October 2025 and archived the minio/minio repository in February 2026. The official minio/minio image is frozen at RELEASE.2025-09-07T16-13-09Z and no longer receives security fixes (the fix for CVE-2025-62506 was never published as an image). - Switch image to pgsty/minio:RELEASE.2026-06-18T00-00-00Z, the actively maintained community fork (drop-in replacement, AGPLv3, same env vars, same /data on-disk format, restores the full web console) - Route the S3 API (port 9000) through its own generated domain instead of publishing host port 9000, per repo conventions - Update meta.json links/description to point at the maintained fork Closes #469 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(nextcloud-aio): drop AIO branding, keep template id, pin nextcloud 33.0.6 The template ships plain nextcloud + mariadb + redis + cron, not the nextcloud/all-in-one mastercontainer. Display name and description no longer claim AIO; folder id is kept as nextcloud-aio to avoid breaking existing installs. Image pinned to the current stable tag (33.0.6). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * feat: add MailCatcher NG template Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * docs: add per-template setup instructions (supabase, trigger.dev) Adds instructions.md files for the Supabase and Trigger.dev templates and renders them in the template browser as a new Instructions tab in the template dialog (fetched from blueprints/<id>/instructions.md, rendered with a small dependency-free markdown component). Also removes the placeholder blueprints/ackee/instructions.md so it does not surface as an empty Instructions tab. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * feat: add Weblate template Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * feat: add Synapse (Matrix homeserver) template Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * feat: add Dify template Dify 1.15.0 (open-source LLM app development platform): api + worker + worker_beat + web + pgvector PostgreSQL (also used as the vector store) + redis + sandbox + ssrf_proxy (squid) + plugin_daemon, fronted by an internal nginx gateway that mirrors the upstream path routing. Closes #88 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * feat: add Sim Studio template Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * feat: add Steedos template Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * feat: add Silex template Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * feat: add SpacetimeDB template Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * feat: add CertMate template Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * feat: add PostHog template Based on the official hobby deployment, trimmed to run on a single server: Django web + Celery worker, Node plugin-server (CDP, ingestion, session replay, recording API), Rust capture/replay-capture/ feature-flags/hypercache, livestream, Caddy path router, Postgres, Redis, Redpanda (Kafka), ZooKeeper, ClickHouse and MinIO. Images are pinned to a tested master commit (PostHog no longer publishes tagged releases); an init container fetches the matching ClickHouse configuration, Kafka table schemas, funnel UDF binaries and the GeoIP database at the same pinned ref. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * feat: add Markup template Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * feat: add Frappe LMS template Adds a Frappe LMS (Frappe Learning) template based on the erpnext-v16 blueprint pattern (configurator + create-site + workers + scheduler + websocket + mariadb + 3x redis). Pins ghcr.io/frappe/lms:v2.52.0, the latest upstream image that ships the lms app (v2.52.1+ images are currently published without any apps baked in). The image does not bundle the payments app, so create-site clears lms's required_apps before install; paid-course checkout is unavailable, everything else works. The backend is gated on a create-site completion marker so gunicorn workers never serve (and cache) a half-installed site during the 3-6 minute first boot. Closes #517 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * feat: add TREK template Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * feat: add Oryx (SRS) media streaming template Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix: stop plugins service crash loop (logs-redis TLS default) In production images LOGS_REDIS_TLS/TRACES_REDIS_TLS default to true, so the logs-ingestion consumer (part of the plugin-server default mode) kept attempting a TLS handshake against the plaintext Redis, timed out every ~11s and killed the process after 10 errors (restart loop every ~2.5 min). Constrain the plugins service to the capability groups this template ships (cdp_workflows, realtime_cohorts, feature_flags) and pin the redis TLS flags to false as belt-and-braces. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * feat: add n8n queue mode template n8n running in queue mode (EXECUTIONS_MODE=queue): main instance for the editor/webhooks, a scalable pool of workers (deploy.replicas driven by the N8N_WORKER_REPLICAS env var), Redis (Bull) as the queue broker and PostgreSQL as the database. Pinned to the current stable n8nio/n8n:2.30.4. Closes #455 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * feat: add bonfire template Bonfire (social flavour) — federated social networking toolkit. App + PostGIS + Meilisearch, mirroring upstream's reference deployments. Closes #125 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * feat: add dagu blueprint Dagu is a self-contained workflow engine with a Web UI for scheduling and orchestrating jobs as DAGs defined in declarative YAML. - Pin ghcr.io/dagucloud/dagu:2.10.7 and expose the Web UI on port 8080 - Set DAGU_HOST=0.0.0.0 so the service is reachable through the proxy - Enable basic auth with a generated per-deploy admin password - Persist /var/lib/dagu (DAGs, logs, run history) in a named volume Claude-Session: https://claude.ai/code/session_01CRNT6sa2q2P9rUTokeoGhQ * feat: add OneUptime template Adds OneUptime (open-source observability platform: uptime monitoring, status pages, incident management, on-call, logs/traces/metrics) as a template, following upstream's current single-app architecture (app + nginx ingress + postgres + redis + clickhouse + probe). Closes #514 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * feat: add Mailu template Mailu 2024.06 mail server: front (nginx), admin, imap (dovecot), smtp (postfix), antispam (rspamd), Roundcube webmail and redis. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * feat(templates): add systemprompt (#1032) * feat(templates): add systemprompt * fix header comment: accurate in both repos * chore: normalize template tags to kebab-case (#987) * feat: adds `check-links.js` to find broken links (#983) * feat: add struxa template (#1037) * feat: add struxa template Adds a Dokploy blueprint for Struxa (github.com/struxadotcloud/struxa), a self-hosted, open-source server management panel. Deploys the published GHCR images (dashboard, watchkeeper, migrate) plus MySQL and MinIO sidecars. The web service generates its RS256 JWT keypair at startup via Node's built-in crypto module, since no Dokploy template helper covers RSA key generation. * fix: pin struxa images to latest floating tag struxa's release workflow pushes a latest floating tag alongside version tags on every stable release, matching the convention used by ~44% of existing blueprints (version: "latest" in meta.json). * fix: generate a 64-char DATABASE_ENCRYPTION_KEY Dokploy's runtime \${hash:N} helper produces N hex characters, not N bytes (the templates repo's local preview helpers.ts models it as byte count, which is inconsistent with the platform). struxa's env schema requires DATABASE_ENCRYPTION_KEY to be >=64 chars (it's hex decoded to a 32-byte AES-256 key), so \${hash:32} only produced half the required length. Confirmed against other blueprints (sim, chatwoot, outline) which all use \${hash:64} for 64-char secrets. * fix: address Copilot review comments - Add explicit \`version: "3.8"\` to docker-compose.yml, matching the documented template format. - Pin minio/minio to a specific RELEASE tag (used elsewhere in the repo: plane, posthog) instead of the floating latest tag. - Default BETTER_AUTH_URL/APP_URL/CORS_ORIGIN to http://, matching repo convention for Dokploy-fronted apps (TLS terminates at the proxy). * fix: rename web service to struxa AGENTS.md convention: the primary Docker service name should match the blueprint folder name. Renamed the web/dashboard service from "web" to "struxa" in docker-compose.yml and updated template.toml's config.domains.serviceName to match. * Add PodFetch template (#1035) * Add PodFetch template * Use env array syntax in template.toml * Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> * Address review: match version to image tag, expose admin_username variable, dark-mode friendly logo --------- Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> * fix(docker): share plugins and themes volumes across containers (#990) * feat(directus): upgrade template to Directus 12.1.1 (#986) * feat(directus): upgrade template to Directus 12.1.1 * feat(directus): add commented S3 env variables to template.toml --------- Co-authored-by: Zakher Masri <46135573+zaaakher@users.noreply.github.com> Co-authored-by: zakher <zakhermasri@gmail.com> Co-authored-by: Jinjinov <dzindzinovic@gmail.com> Co-authored-by: Claude Fable 5 <noreply@anthropic.com> Co-authored-by: Stephan Fitzpatrick <stephan@knowsuchagency.com> Co-authored-by: Mauricio Siu <mauricio@dokploy.com> Co-authored-by: Edward Burton <ejb503@gmail.com> Co-authored-by: Marko Kostich <markokosticdev@gmail.com> Co-authored-by: Jakub Krzyżanowski <jakubkrzyz.kontakt@gmail.com> Co-authored-by: SamTV12345 <40429738+SamTV12345@users.noreply.github.com> Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> Co-authored-by: Mafly <110502739+Nekoplii@users.noreply.github.com>
647 lines
22 KiB
YAML
647 lines
22 KiB
YAML
# PostHog self-hosted ("hobby" deployment, trimmed for a single VPS).
|
|
# Based on https://github.com/PostHog/posthog/blob/master/docker-compose.hobby.yml
|
|
# Omitted vs upstream hobby (heavy/optional): Temporal + Elasticsearch (data
|
|
# warehouse / batch exports), browserless (image exports / heatmap screenshots),
|
|
# personhog, cymbal + error-tracking/logs/traces ingestion, capture-ai and
|
|
# capture-logs. Everything needed for product analytics, feature flags,
|
|
# surveys, session replay and the CDP pipeline is included.
|
|
|
|
x-logging: &default-logging
|
|
driver: json-file
|
|
options:
|
|
max-size: "50m"
|
|
max-file: "3"
|
|
|
|
x-django-env: &django-env
|
|
# Postgres
|
|
DATABASE_URL: postgres://posthog:posthog@db:5432/posthog
|
|
PGHOST: db
|
|
PGUSER: posthog
|
|
PGPASSWORD: posthog
|
|
PERSONS_DB_WRITER_URL: postgres://posthog:posthog@db:5432/posthog
|
|
PERSONS_DB_READER_URL: postgres://posthog:posthog@db:5432/posthog
|
|
# ClickHouse (users match docker/clickhouse/users.xml from the PostHog repo)
|
|
CLICKHOUSE_HOST: clickhouse
|
|
CLICKHOUSE_DATABASE: posthog
|
|
CLICKHOUSE_SECURE: "false"
|
|
CLICKHOUSE_VERIFY: "false"
|
|
CLICKHOUSE_API_USER: api
|
|
CLICKHOUSE_API_PASSWORD: apipass
|
|
CLICKHOUSE_APP_USER: app
|
|
CLICKHOUSE_APP_PASSWORD: apppass
|
|
CLICKHOUSE_LOGS_CLUSTER_HOST: clickhouse
|
|
CLICKHOUSE_LOGS_CLUSTER_SECURE: "false"
|
|
# Redis / Kafka
|
|
REDIS_URL: redis://redis7:6379/
|
|
KAFKA_HOSTS: kafka:9092
|
|
FLAGS_REDIS_ENABLED: "false"
|
|
# Object storage (MinIO)
|
|
OBJECT_STORAGE_ENABLED: "true"
|
|
OBJECT_STORAGE_ENDPOINT: http://objectstorage:19000
|
|
OBJECT_STORAGE_PUBLIC_ENDPOINT: ${POSTHOG_SITE_URL}
|
|
OBJECT_STORAGE_ACCESS_KEY_ID: object_storage_root_user
|
|
OBJECT_STORAGE_SECRET_ACCESS_KEY: object_storage_root_password
|
|
OBJECT_STORAGE_FORCE_PATH_STYLE: "true"
|
|
# Session replay storage
|
|
SESSION_RECORDING_V2_S3_ENDPOINT: http://objectstorage:19000
|
|
SESSION_RECORDING_V2_S3_ACCESS_KEY_ID: object_storage_root_user
|
|
SESSION_RECORDING_V2_S3_SECRET_ACCESS_KEY: object_storage_root_password
|
|
RECORDING_API_URL: http://recording-api:6738
|
|
# App
|
|
SITE_URL: ${POSTHOG_SITE_URL}
|
|
SECRET_KEY: ${POSTHOG_SECRET_KEY}
|
|
ENCRYPTION_SALT_KEYS: ${POSTHOG_ENCRYPTION_SALT_KEYS}
|
|
DEPLOYMENT: hobby
|
|
IS_BEHIND_PROXY: "true"
|
|
DISABLE_SECURE_SSL_REDIRECT: "true"
|
|
# "false" so login works over plain HTTP; set to "true" once the domain uses HTTPS
|
|
SECURE_COOKIES: ${POSTHOG_SECURE_COOKIES}
|
|
CDP_API_URL: http://plugins:6738
|
|
FEATURE_FLAGS_SERVICE_URL: http://feature-flags:3001
|
|
LIVESTREAM_HOST: ${POSTHOG_SITE_URL}/livestream
|
|
API_QUERIES_PER_TEAM: '{"1": 100}'
|
|
OTEL_SDK_DISABLED: "true"
|
|
OTEL_EXPORTER_OTLP_ENDPOINT: ""
|
|
|
|
services:
|
|
# One-shot: fetches the ClickHouse configuration, Kafka table schemas and
|
|
# funnel UDFs from the PostHog repo (pinned to the same commit as the app
|
|
# image) plus the GeoLite2 GeoIP database. Idempotent across redeploys.
|
|
init-assets:
|
|
image: alpine:3.21
|
|
restart: on-failure
|
|
logging: *default-logging
|
|
entrypoint: /bin/sh
|
|
command:
|
|
- -c
|
|
- |
|
|
set -e
|
|
apk add --no-cache git curl brotli >/dev/null
|
|
if [ ! -f /assets/.ok-${POSTHOG_VERSION} ]; then
|
|
echo "Fetching PostHog repo assets @ ${POSTHOG_VERSION}"
|
|
rm -rf /tmp/ph && mkdir -p /tmp/ph && cd /tmp/ph
|
|
git init -q .
|
|
git remote add origin https://github.com/PostHog/posthog.git
|
|
git sparse-checkout set --no-cone /docker/clickhouse/ /posthog/idl/ /posthog/user_scripts/
|
|
git -c protocol.version=2 fetch -q --depth 1 --filter=blob:none origin ${POSTHOG_VERSION}
|
|
git checkout -q FETCH_HEAD
|
|
rm -rf /assets/clickhouse /assets/idl /assets/user_scripts /assets/.ok-*
|
|
cp -r docker/clickhouse /assets/clickhouse
|
|
cp -r posthog/idl /assets/idl
|
|
cp -r posthog/user_scripts /assets/user_scripts
|
|
touch /assets/.ok-${POSTHOG_VERSION}
|
|
echo "Repo assets ready"
|
|
fi
|
|
if [ ! -s /share/GeoLite2-City.mmdb ]; then
|
|
echo "Downloading GeoLite2 database"
|
|
curl -sL --http1.1 https://mmdbcdn.posthog.net/ | brotli --decompress --output=/share/GeoLite2-City.mmdb
|
|
chmod 644 /share/GeoLite2-City.mmdb
|
|
fi
|
|
echo "init-assets done"
|
|
volumes:
|
|
- posthog-assets:/assets
|
|
- geoip-data:/share
|
|
|
|
db:
|
|
image: postgres:15.12-alpine
|
|
restart: unless-stopped
|
|
logging: *default-logging
|
|
environment:
|
|
POSTGRES_USER: posthog
|
|
POSTGRES_DB: posthog
|
|
POSTGRES_PASSWORD: posthog
|
|
healthcheck:
|
|
test: ["CMD-SHELL", "pg_isready -U posthog"]
|
|
interval: 5s
|
|
timeout: 10s
|
|
retries: 30
|
|
start_period: 10s
|
|
volumes:
|
|
- postgres-data:/var/lib/postgresql/data
|
|
- ../files/db-init:/docker-entrypoint-initdb.d:ro
|
|
|
|
redis7:
|
|
image: redis:7.2-alpine
|
|
restart: unless-stopped
|
|
logging: *default-logging
|
|
command: redis-server --maxmemory-policy allkeys-lru --maxmemory 200mb
|
|
healthcheck:
|
|
test: ["CMD", "redis-cli", "ping"]
|
|
interval: 5s
|
|
timeout: 10s
|
|
retries: 10
|
|
volumes:
|
|
- redis-data:/data
|
|
|
|
# Required by ClickHouse for distributed DDL (docker/clickhouse/config.xml
|
|
# points at zookeeper:2181)
|
|
zookeeper:
|
|
image: zookeeper:3.7.0
|
|
restart: unless-stopped
|
|
logging: *default-logging
|
|
environment:
|
|
ZOO_AUTOPURGE_PURGEINTERVAL: 1
|
|
ZOO_AUTOPURGE_SNAPRETAINCOUNT: 3
|
|
volumes:
|
|
- zookeeper-data:/data
|
|
- zookeeper-datalog:/datalog
|
|
|
|
# Kafka API provided by Redpanda (as upstream), tuned down for small servers
|
|
kafka:
|
|
image: docker.io/redpandadata/redpanda:v25.1.9
|
|
restart: unless-stopped
|
|
logging: *default-logging
|
|
command:
|
|
- redpanda
|
|
- start
|
|
- --kafka-addr internal://0.0.0.0:9092
|
|
- --advertise-kafka-addr internal://kafka:9092
|
|
- --rpc-addr kafka:33145
|
|
- --advertise-rpc-addr kafka:33145
|
|
- --mode dev-container
|
|
- --smp 1
|
|
- --memory 1G
|
|
- --reserve-memory 0M
|
|
- --overprovisioned
|
|
- --set redpanda.empty_seed_starts_cluster=false
|
|
- --seeds kafka:33145
|
|
- --set redpanda.auto_create_topics_enabled=true
|
|
volumes:
|
|
- redpanda-data:/var/lib/redpanda/data
|
|
healthcheck:
|
|
test: ["CMD-SHELL", "curl -f http://localhost:9644/v1/status/ready || exit 1"]
|
|
interval: 5s
|
|
timeout: 10s
|
|
retries: 30
|
|
start_period: 20s
|
|
|
|
# One-shot: pre-creates the Kafka topics that consumers check at startup
|
|
kafka-init:
|
|
image: docker.io/redpandadata/redpanda:v25.1.9
|
|
restart: on-failure
|
|
logging: *default-logging
|
|
entrypoint: /bin/sh
|
|
depends_on:
|
|
kafka:
|
|
condition: service_healthy
|
|
command:
|
|
- -c
|
|
- |
|
|
set -e
|
|
TOPICS="clickhouse_events_json \
|
|
clickhouse_ai_events_json \
|
|
clickhouse_heatmap_events \
|
|
clickhouse_ingestion_warnings \
|
|
events_plugin_ingestion \
|
|
events_plugin_ingestion_dlq \
|
|
events_plugin_ingestion_overflow \
|
|
events_plugin_ingestion_async \
|
|
events_plugin_ingestion_historical \
|
|
ingestion-clientwarnings-main-1 \
|
|
heatmaps_ingestion \
|
|
session_recording_snapshot_item_events \
|
|
session_recording_snapshot_item_overflow \
|
|
clickhouse_groups \
|
|
clickhouse_person \
|
|
clickhouse_person_distinct_id \
|
|
clickhouse_app_metrics2 \
|
|
log_entries \
|
|
clickhouse_tophog"
|
|
for topic in $$TOPICS; do
|
|
rpk topic create "$$topic" --brokers kafka:9092 -p 1 -r 1 2>/dev/null \
|
|
|| rpk topic list --brokers kafka:9092 | grep -q "$$topic"
|
|
done
|
|
echo "Kafka topics ready"
|
|
|
|
clickhouse:
|
|
image: clickhouse/clickhouse-server:26.6.1.1193
|
|
restart: unless-stopped
|
|
logging: *default-logging
|
|
depends_on:
|
|
init-assets:
|
|
condition: service_completed_successfully
|
|
zookeeper:
|
|
condition: service_started
|
|
kafka:
|
|
condition: service_started
|
|
entrypoint: /bin/bash
|
|
command:
|
|
- -c
|
|
- |
|
|
set -e
|
|
cp /assets/clickhouse/config.xml /etc/clickhouse-server/config.xml
|
|
cp /assets/clickhouse/config.d/default.xml /etc/clickhouse-server/config.d/default.xml
|
|
cp /assets/clickhouse/users.xml /etc/clickhouse-server/users.xml
|
|
cp /assets/clickhouse/user_defined_function.xml /etc/clickhouse-server/user_defined_function.xml
|
|
mkdir -p /var/lib/clickhouse/format_schemas /var/lib/clickhouse/user_scripts
|
|
cp -r /assets/idl/. /var/lib/clickhouse/format_schemas/
|
|
cp -r /assets/user_scripts/. /var/lib/clickhouse/user_scripts/
|
|
chmod -R 755 /var/lib/clickhouse/user_scripts
|
|
chown -R clickhouse:clickhouse /var/lib/clickhouse/format_schemas /var/lib/clickhouse/user_scripts || true
|
|
# Materialize system log tables (system.crash_log is required by the
|
|
# custom_metrics ClickHouse migration), mirroring upstream init-db.sh
|
|
(
|
|
i=0
|
|
while [ $$i -lt 90 ]; do
|
|
if clickhouse-client --query "SELECT 1" >/dev/null 2>&1; then
|
|
clickhouse-client --query "SYSTEM FLUSH LOGS" && echo "system logs flushed" && break
|
|
fi
|
|
sleep 2
|
|
i=$$((i+1))
|
|
done
|
|
) &
|
|
exec /entrypoint.sh
|
|
environment:
|
|
CLICKHOUSE_SKIP_USER_SETUP: 1
|
|
KAFKA_HOSTS: kafka:9092
|
|
volumes:
|
|
- posthog-assets:/assets:ro
|
|
- clickhouse-data:/var/lib/clickhouse
|
|
healthcheck:
|
|
test: ["CMD-SHELL", "wget --no-verbose --tries=1 --spider http://localhost:8123/ping || exit 1"]
|
|
interval: 5s
|
|
timeout: 10s
|
|
retries: 30
|
|
start_period: 30s
|
|
|
|
# Django app: runs migrations, then serves the API + UI on :8000
|
|
web:
|
|
image: posthog/posthog:${POSTHOG_VERSION}
|
|
restart: unless-stopped
|
|
logging: *default-logging
|
|
command: ["sh", "-c", "./bin/migrate && exec ./bin/docker-server"]
|
|
depends_on:
|
|
db:
|
|
condition: service_healthy
|
|
redis7:
|
|
condition: service_healthy
|
|
clickhouse:
|
|
condition: service_healthy
|
|
kafka:
|
|
condition: service_healthy
|
|
kafka-init:
|
|
condition: service_completed_successfully
|
|
objectstorage:
|
|
condition: service_started
|
|
environment:
|
|
<<: *django-env
|
|
NGINX_UNIT_APP_PROCESSES: 2
|
|
healthcheck:
|
|
test: ["CMD-SHELL", "curl -fs http://localhost:8000/_health || exit 1"]
|
|
interval: 30s
|
|
timeout: 10s
|
|
retries: 15
|
|
start_period: 600s
|
|
|
|
# Celery worker + scheduler
|
|
worker:
|
|
image: posthog/posthog:${POSTHOG_VERSION}
|
|
restart: unless-stopped
|
|
logging: *default-logging
|
|
command: ./bin/docker-worker-celery --with-scheduler
|
|
depends_on:
|
|
db:
|
|
condition: service_healthy
|
|
redis7:
|
|
condition: service_healthy
|
|
clickhouse:
|
|
condition: service_healthy
|
|
kafka:
|
|
condition: service_healthy
|
|
web:
|
|
condition: service_started
|
|
environment:
|
|
<<: *django-env
|
|
POSTHOG_SKIP_MIGRATION_CHECKS: "1"
|
|
WEB_CONCURRENCY: 2
|
|
|
|
# Node plugin server: CDP (destinations, webhooks, transformations)
|
|
plugins:
|
|
image: posthog/posthog-node:${POSTHOG_NODE_VERSION}
|
|
restart: unless-stopped
|
|
logging: *default-logging
|
|
depends_on:
|
|
db:
|
|
condition: service_healthy
|
|
redis7:
|
|
condition: service_healthy
|
|
kafka:
|
|
condition: service_healthy
|
|
clickhouse:
|
|
condition: service_started
|
|
kafka-init:
|
|
condition: service_completed_successfully
|
|
init-assets:
|
|
condition: service_completed_successfully
|
|
environment:
|
|
# Run only the pipelines this template ships (CDP destinations/workflows,
|
|
# realtime cohorts, feature-flag evaluation). The default mode would also
|
|
# start the logs/error-tracking ingestion consumers, which this template
|
|
# intentionally omits.
|
|
NODEJS_CAPABILITY_GROUPS: cdp_workflows,realtime_cohorts,feature_flags
|
|
SITE_URL: ${POSTHOG_SITE_URL}
|
|
SECRET_KEY: ${POSTHOG_SECRET_KEY}
|
|
ENCRYPTION_SALT_KEYS: ${POSTHOG_ENCRYPTION_SALT_KEYS}
|
|
DATABASE_URL: postgres://posthog:posthog@db:5432/posthog
|
|
PERSONS_DATABASE_URL: postgres://posthog:posthog@db:5432/posthog
|
|
BEHAVIORAL_COHORTS_DATABASE_URL: postgres://posthog:posthog@db:5432/posthog
|
|
CYCLOTRON_DATABASE_URL: postgres://posthog:posthog@db:5432/posthog
|
|
KAFKA_HOSTS: kafka:9092
|
|
REDIS_URL: redis://redis7:6379/
|
|
CDP_REDIS_HOST: redis7
|
|
CDP_REDIS_PORT: 6379
|
|
# TLS for these defaults to "true" in production images; this stack's
|
|
# Redis is plaintext (a TLS handshake against it hangs until timeout and
|
|
# crash-loops the process if these consumers ever run).
|
|
LOGS_REDIS_HOST: redis7
|
|
LOGS_REDIS_TLS: "false"
|
|
TRACES_REDIS_HOST: redis7
|
|
TRACES_REDIS_TLS: "false"
|
|
COOKIELESS_REDIS_HOST: redis7
|
|
COOKIELESS_REDIS_PORT: 6379
|
|
CLICKHOUSE_HOST: clickhouse
|
|
CLICKHOUSE_DATABASE: posthog
|
|
CLICKHOUSE_SECURE: "false"
|
|
CLICKHOUSE_VERIFY: "false"
|
|
OBJECT_STORAGE_ENABLED: "true"
|
|
OBJECT_STORAGE_ENDPOINT: http://objectstorage:19000
|
|
OBJECT_STORAGE_PUBLIC_ENDPOINT: ${POSTHOG_SITE_URL}
|
|
OBJECT_STORAGE_ACCESS_KEY_ID: object_storage_root_user
|
|
OBJECT_STORAGE_SECRET_ACCESS_KEY: object_storage_root_password
|
|
OTEL_EXPORTER_OTLP_ENDPOINT: ""
|
|
volumes:
|
|
- geoip-data:/share:ro
|
|
|
|
# Node plugin server: event ingestion (Kafka -> person processing -> ClickHouse)
|
|
ingestion-general:
|
|
image: posthog/posthog-node:${POSTHOG_NODE_VERSION}
|
|
restart: unless-stopped
|
|
logging: *default-logging
|
|
depends_on:
|
|
db:
|
|
condition: service_healthy
|
|
redis7:
|
|
condition: service_healthy
|
|
kafka:
|
|
condition: service_healthy
|
|
clickhouse:
|
|
condition: service_started
|
|
kafka-init:
|
|
condition: service_completed_successfully
|
|
init-assets:
|
|
condition: service_completed_successfully
|
|
environment:
|
|
PLUGIN_SERVER_MODE: ingestion-v2-combined
|
|
ENCRYPTION_SALT_KEYS: ${POSTHOG_ENCRYPTION_SALT_KEYS}
|
|
DATABASE_URL: postgres://posthog:posthog@db:5432/posthog
|
|
PERSONS_DATABASE_URL: postgres://posthog:posthog@db:5432/posthog
|
|
BEHAVIORAL_COHORTS_DATABASE_URL: postgres://posthog:posthog@db:5432/posthog
|
|
KAFKA_HOSTS: kafka:9092
|
|
REDIS_URL: redis://redis7:6379/
|
|
COOKIELESS_REDIS_HOST: redis7
|
|
COOKIELESS_REDIS_PORT: 6379
|
|
CDP_REDIS_HOST: redis7
|
|
LOGS_REDIS_HOST: redis7
|
|
LOGS_REDIS_TLS: "false"
|
|
TRACES_REDIS_HOST: redis7
|
|
TRACES_REDIS_TLS: "false"
|
|
CLICKHOUSE_HOST: clickhouse
|
|
CLICKHOUSE_DATABASE: posthog
|
|
CLICKHOUSE_SECURE: "false"
|
|
CLICKHOUSE_VERIFY: "false"
|
|
volumes:
|
|
- geoip-data:/share:ro
|
|
|
|
# Node plugin server: session replay blob ingestion (Kafka -> S3)
|
|
ingestion-sessionreplay:
|
|
image: posthog/posthog-node:${POSTHOG_NODE_VERSION}
|
|
restart: unless-stopped
|
|
logging: *default-logging
|
|
depends_on:
|
|
db:
|
|
condition: service_healthy
|
|
redis7:
|
|
condition: service_healthy
|
|
kafka:
|
|
condition: service_healthy
|
|
kafka-init:
|
|
condition: service_completed_successfully
|
|
objectstorage:
|
|
condition: service_started
|
|
environment:
|
|
PLUGIN_SERVER_MODE: recordings-blob-ingestion-v2
|
|
ENCRYPTION_SALT_KEYS: ${POSTHOG_ENCRYPTION_SALT_KEYS}
|
|
DATABASE_URL: postgres://posthog:posthog@db:5432/posthog
|
|
KAFKA_HOSTS: kafka:9092
|
|
REDIS_URL: redis://redis7:6379/
|
|
SESSION_RECORDING_V2_S3_ENDPOINT: http://objectstorage:19000
|
|
SESSION_RECORDING_V2_S3_ACCESS_KEY_ID: object_storage_root_user
|
|
SESSION_RECORDING_V2_S3_SECRET_ACCESS_KEY: object_storage_root_password
|
|
SESSION_RECORDING_V2_S3_TIMEOUT_MS: 120000
|
|
|
|
# Node plugin server: session replay playback API
|
|
recording-api:
|
|
image: posthog/posthog-node:${POSTHOG_NODE_VERSION}
|
|
restart: unless-stopped
|
|
logging: *default-logging
|
|
depends_on:
|
|
db:
|
|
condition: service_healthy
|
|
redis7:
|
|
condition: service_healthy
|
|
clickhouse:
|
|
condition: service_started
|
|
objectstorage:
|
|
condition: service_started
|
|
environment:
|
|
PLUGIN_SERVER_MODE: recording-api
|
|
ENCRYPTION_SALT_KEYS: ${POSTHOG_ENCRYPTION_SALT_KEYS}
|
|
DATABASE_URL: postgres://posthog:posthog@db:5432/posthog
|
|
REDIS_URL: redis://redis7:6379/
|
|
SESSION_RECORDING_API_REDIS_HOST: redis7
|
|
SESSION_RECORDING_API_REDIS_PORT: 6379
|
|
CLICKHOUSE_HOST: clickhouse
|
|
CLICKHOUSE_DATABASE: posthog
|
|
CLICKHOUSE_SECURE: "false"
|
|
CLICKHOUSE_VERIFY: "false"
|
|
SESSION_RECORDING_V2_S3_ENDPOINT: http://objectstorage:19000
|
|
SESSION_RECORDING_V2_S3_ACCESS_KEY_ID: object_storage_root_user
|
|
SESSION_RECORDING_V2_S3_SECRET_ACCESS_KEY: object_storage_root_password
|
|
|
|
# Rust event capture endpoint (/e, /batch, /capture, /i/v0)
|
|
capture:
|
|
image: ghcr.io/posthog/posthog/capture:master
|
|
restart: unless-stopped
|
|
logging: *default-logging
|
|
depends_on:
|
|
kafka:
|
|
condition: service_healthy
|
|
redis7:
|
|
condition: service_healthy
|
|
environment:
|
|
ADDRESS: 0.0.0.0:3000
|
|
KAFKA_TOPIC: events_plugin_ingestion
|
|
KAFKA_HOSTS: kafka:9092
|
|
REDIS_URL: redis://redis7:6379/
|
|
CAPTURE_MODE: events
|
|
RUST_LOG: info,rdkafka=warn
|
|
CAPTURE_V1_SINKS: msk
|
|
CAPTURE_V1_SINK_MSK_KAFKA_HOSTS: kafka:9092
|
|
CAPTURE_V1_SINK_MSK_KAFKA_TOPIC_MAIN: events_plugin_ingestion
|
|
CAPTURE_V1_SINK_MSK_KAFKA_TOPIC_HISTORICAL: events_plugin_ingestion_historical
|
|
CAPTURE_V1_SINK_MSK_KAFKA_TOPIC_OVERFLOW: events_plugin_ingestion_overflow
|
|
CAPTURE_V1_SINK_MSK_KAFKA_TOPIC_DLQ: events_plugin_ingestion_dlq
|
|
CAPTURE_V1_SINK_MSK_KAFKA_TOPIC_EXCEPTION: ingestion-errortracking-main
|
|
CAPTURE_V1_SINK_MSK_KAFKA_TOPIC_HEATMAP: heatmaps_ingestion
|
|
CAPTURE_V1_SINK_MSK_KAFKA_TOPIC_CLIENT_INGESTION_WARNING: ingestion-clientwarnings-main-1
|
|
|
|
# Rust capture endpoint for session recordings (/s)
|
|
replay-capture:
|
|
image: ghcr.io/posthog/posthog/capture:master
|
|
restart: unless-stopped
|
|
logging: *default-logging
|
|
depends_on:
|
|
kafka:
|
|
condition: service_healthy
|
|
redis7:
|
|
condition: service_healthy
|
|
environment:
|
|
ADDRESS: 0.0.0.0:3000
|
|
KAFKA_TOPIC: session_recording_snapshot_item_events
|
|
KAFKA_HOSTS: kafka:9092
|
|
REDIS_URL: redis://redis7:6379/
|
|
CAPTURE_MODE: recordings
|
|
|
|
# Rust feature flag evaluation service (/flags)
|
|
feature-flags:
|
|
image: ghcr.io/posthog/posthog/feature-flags:master
|
|
restart: unless-stopped
|
|
logging: *default-logging
|
|
depends_on:
|
|
db:
|
|
condition: service_healthy
|
|
redis7:
|
|
condition: service_healthy
|
|
init-assets:
|
|
condition: service_completed_successfully
|
|
environment:
|
|
WRITE_DATABASE_URL: postgres://posthog:posthog@db:5432/posthog
|
|
READ_DATABASE_URL: postgres://posthog:posthog@db:5432/posthog
|
|
PERSONS_WRITE_DATABASE_URL: postgres://posthog:posthog@db:5432/posthog
|
|
PERSONS_READ_DATABASE_URL: postgres://posthog:posthog@db:5432/posthog
|
|
MAXMIND_DB_PATH: /share/GeoLite2-City.mmdb
|
|
REDIS_URL: redis://redis7:6379/
|
|
ADDRESS: 0.0.0.0:3001
|
|
RUST_LOG: info
|
|
COOKIELESS_REDIS_HOST: redis7
|
|
COOKIELESS_REDIS_PORT: 6379
|
|
volumes:
|
|
- geoip-data:/share:ro
|
|
|
|
# Rust hypercache server (/array remote config + /surveys)
|
|
hypercache-server:
|
|
image: ghcr.io/posthog/posthog/hypercache-server:master
|
|
restart: unless-stopped
|
|
logging: *default-logging
|
|
depends_on:
|
|
redis7:
|
|
condition: service_healthy
|
|
environment:
|
|
REDIS_URL: redis://redis7:6379/
|
|
ADDRESS: 0.0.0.0:3002
|
|
RUST_LOG: info
|
|
|
|
# Live events stream (/livestream)
|
|
livestream:
|
|
image: ghcr.io/posthog/posthog/livestream:master
|
|
restart: unless-stopped
|
|
logging: *default-logging
|
|
depends_on:
|
|
kafka:
|
|
condition: service_healthy
|
|
environment:
|
|
LIVESTREAM_JWT_SECRET: ${POSTHOG_SECRET_KEY}
|
|
volumes:
|
|
- ../files/livestream/configs.yml:/configs/configs.yml:ro
|
|
|
|
objectstorage:
|
|
image: minio/minio:RELEASE.2025-04-22T22-12-26Z
|
|
restart: unless-stopped
|
|
logging: *default-logging
|
|
environment:
|
|
MINIO_ROOT_USER: object_storage_root_user
|
|
MINIO_ROOT_PASSWORD: object_storage_root_password
|
|
entrypoint: sh
|
|
command: -c 'mkdir -p /data/posthog && minio server --address ":19000" --console-address ":19001" /data'
|
|
volumes:
|
|
- objectstorage-data:/data
|
|
|
|
# Caddy routes the single public domain to the right internal service,
|
|
# exactly like the upstream hobby deployment (TLS is terminated by Traefik)
|
|
proxy:
|
|
image: caddy:2.10-alpine
|
|
restart: unless-stopped
|
|
logging: *default-logging
|
|
depends_on:
|
|
web:
|
|
condition: service_started
|
|
entrypoint: sh
|
|
command: -c 'printf "%s" "$$CADDYFILE" > /etc/caddy/Caddyfile && exec caddy run -c /etc/caddy/Caddyfile'
|
|
environment:
|
|
CADDYFILE: |
|
|
{
|
|
auto_https off
|
|
}
|
|
:80 {
|
|
@capture path /e /e/ /e/* /i/v0 /i/v0/ /i/v0/* /i/v1/analytics/events /i/v1/analytics/events/ /batch /batch/ /batch/* /capture /capture/ /capture/*
|
|
@replay-capture path /s /s/ /s/*
|
|
@flags path /flags /flags/ /flags/* /api/feature_flag/local_evaluation /api/feature_flag/local_evaluation/ /api/feature_flag/local_evaluation/*
|
|
@surveys path /surveys /surveys/ /api/surveys /api/surveys/
|
|
@remote-config path /array/*
|
|
@webhooks path /public/webhooks /public/webhooks/ /public/webhooks/* /public/m/ /public/m/*
|
|
@livestream path /livestream /livestream/ /livestream/*
|
|
@objectstorage path /posthog /posthog/ /posthog/*
|
|
|
|
handle @capture {
|
|
reverse_proxy capture:3000
|
|
}
|
|
handle @replay-capture {
|
|
reverse_proxy replay-capture:3000
|
|
}
|
|
handle @flags {
|
|
reverse_proxy feature-flags:3001
|
|
}
|
|
handle @surveys {
|
|
reverse_proxy hypercache-server:3002
|
|
}
|
|
handle @remote-config {
|
|
reverse_proxy hypercache-server:3002
|
|
}
|
|
handle @webhooks {
|
|
reverse_proxy plugins:6738
|
|
}
|
|
handle @livestream {
|
|
uri strip_prefix /livestream
|
|
reverse_proxy livestream:8080 {
|
|
flush_interval -1
|
|
}
|
|
}
|
|
handle @objectstorage {
|
|
reverse_proxy objectstorage:19000
|
|
}
|
|
handle {
|
|
reverse_proxy web:8000
|
|
}
|
|
}
|
|
|
|
volumes:
|
|
postgres-data:
|
|
redis-data:
|
|
zookeeper-data:
|
|
zookeeper-datalog:
|
|
redpanda-data:
|
|
clickhouse-data:
|
|
posthog-assets:
|
|
geoip-data:
|
|
objectstorage-data:
|