Dokploy

PostHog

PostHog is an open-source product analytics platform with feature flags, session replay, surveys, A/B testing and a customer data pipeline, all in one tool.

PostHog logo

Configuration

# 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:
[variables]
main_domain = "${domain}"
secret_key = "${password:64}"
salt_keys = "${hash:32}"

[config]
[[config.domains]]
serviceName = "proxy"
port = 80
host = "${main_domain}"
path = "/"

[config.env]
# PostHog stopped publishing tagged releases; images are pinned to a tested
# master commit. POSTHOG_VERSION is both the posthog/posthog image tag and the
# git ref used to fetch the matching ClickHouse configuration.
POSTHOG_VERSION = "1e7b36ebe0da38a738fed250d175809a899ef422"
POSTHOG_NODE_VERSION = "sha-82ea668"
# Set to https://<your-domain> after enabling HTTPS on the domain
POSTHOG_SITE_URL = "http://${main_domain}"
# Set to "true" once the domain uses HTTPS (marks session/CSRF cookies Secure)
POSTHOG_SECURE_COOKIES = "false"
POSTHOG_SECRET_KEY = "${secret_key}"
POSTHOG_ENCRYPTION_SALT_KEYS = "${salt_keys}"

[[config.mounts]]
filePath = "/db-init/create-extra-dbs.sh"
content = """
#!/bin/bash
# Creates the auxiliary databases PostHog services can point at
# (mirrors docker/postgres-init-scripts in the PostHog repo)
set -e
set -u

for db in cyclotron posthog_persons behavioral_cohorts; do
    DB_EXISTS=$(psql -U "$POSTGRES_USER" -tAc "SELECT 1 FROM pg_database WHERE datname='$db'")
    if [ -z "$DB_EXISTS" ]; then
        echo "Creating database '$db'..."
        psql -U "$POSTGRES_USER" -c "CREATE DATABASE $db;"
        psql -U "$POSTGRES_USER" -c "GRANT ALL PRIVILEGES ON DATABASE $db TO $POSTGRES_USER;"
    fi
done
"""

[[config.mounts]]
filePath = "/livestream/configs.yml"
content = """
debug: false
kafka:
    brokers: 'kafka:9092'
    topic: 'events_plugin_ingestion'
    group_id: 'livestream'
    security_protocol: 'PLAINTEXT'
    session_recording_enabled: true
    session_recording_security_protocol: 'PLAINTEXT'
consumers:
    event:
        enabled: true
        brokers: 'kafka:9092'
        topic: 'events_plugin_ingestion'
        security_protocol: 'PLAINTEXT'
        group_id: 'livestream'
    session_recording:
        enabled: true
        brokers: 'kafka:9092'
        topic: 'session_recording_snapshot_item_events'
        security_protocol: 'PLAINTEXT'
        group_id: 'livestream-session-recordings'
    notification:
        enabled: false
mmdb:
    path: 'GeoLite2-City.mmdb'
"""

Base64

To import this template in Dokploy: create a Compose service → AdvancedBase64 import and paste the content below:

ewogICJjb21wb3NlIjogIiMgUG9zdEhvZyBzZWxmLWhvc3RlZCAoXCJob2JieVwiIGRlcGxveW1lbnQsIHRyaW1tZWQgZm9yIGEgc2luZ2xlIFZQUykuXG4jIEJhc2VkIG9uIGh0dHBzOi8vZ2l0aHViLmNvbS9Qb3N0SG9nL3Bvc3Rob2cvYmxvYi9tYXN0ZXIvZG9ja2VyLWNvbXBvc2UuaG9iYnkueW1sXG4jIE9taXR0ZWQgdnMgdXBzdHJlYW0gaG9iYnkgKGhlYXZ5L29wdGlvbmFsKTogVGVtcG9yYWwgKyBFbGFzdGljc2VhcmNoIChkYXRhXG4jIHdhcmVob3VzZSAvIGJhdGNoIGV4cG9ydHMpLCBicm93c2VybGVzcyAoaW1hZ2UgZXhwb3J0cyAvIGhlYXRtYXAgc2NyZWVuc2hvdHMpLFxuIyBwZXJzb25ob2csIGN5bWJhbCArIGVycm9yLXRyYWNraW5nL2xvZ3MvdHJhY2VzIGluZ2VzdGlvbiwgY2FwdHVyZS1haSBhbmRcbiMgY2FwdHVyZS1sb2dzLiBFdmVyeXRoaW5nIG5lZWRlZCBmb3IgcHJvZHVjdCBhbmFseXRpY3MsIGZlYXR1cmUgZmxhZ3MsXG4jIHN1cnZleXMsIHNlc3Npb24gcmVwbGF5IGFuZCB0aGUgQ0RQIHBpcGVsaW5lIGlzIGluY2x1ZGVkLlxuXG54LWxvZ2dpbmc6ICZkZWZhdWx0LWxvZ2dpbmdcbiAgZHJpdmVyOiBqc29uLWZpbGVcbiAgb3B0aW9uczpcbiAgICBtYXgtc2l6ZTogXCI1MG1cIlxuICAgIG1heC1maWxlOiBcIjNcIlxuXG54LWRqYW5nby1lbnY6ICZkamFuZ28tZW52XG4gICMgUG9zdGdyZXNcbiAgREFUQUJBU0VfVVJMOiBwb3N0Z3JlczovL3Bvc3Rob2c6cG9zdGhvZ0BkYjo1NDMyL3Bvc3Rob2dcbiAgUEdIT1NUOiBkYlxuICBQR1VTRVI6IHBvc3Rob2dcbiAgUEdQQVNTV09SRDogcG9zdGhvZ1xuICBQRVJTT05TX0RCX1dSSVRFUl9VUkw6IHBvc3RncmVzOi8vcG9zdGhvZzpwb3N0aG9nQGRiOjU0MzIvcG9zdGhvZ1xuICBQRVJTT05TX0RCX1JFQURFUl9VUkw6IHBvc3RncmVzOi8vcG9zdGhvZzpwb3N0aG9nQGRiOjU0MzIvcG9zdGhvZ1xuICAjIENsaWNrSG91c2UgKHVzZXJzIG1hdGNoIGRvY2tlci9jbGlja2hvdXNlL3VzZXJzLnhtbCBmcm9tIHRoZSBQb3N0SG9nIHJlcG8pXG4gIENMSUNLSE9VU0VfSE9TVDogY2xpY2tob3VzZVxuICBDTElDS0hPVVNFX0RBVEFCQVNFOiBwb3N0aG9nXG4gIENMSUNLSE9VU0VfU0VDVVJFOiBcImZhbHNlXCJcbiAgQ0xJQ0tIT1VTRV9WRVJJRlk6IFwiZmFsc2VcIlxuICBDTElDS0hPVVNFX0FQSV9VU0VSOiBhcGlcbiAgQ0xJQ0tIT1VTRV9BUElfUEFTU1dPUkQ6IGFwaXBhc3NcbiAgQ0xJQ0tIT1VTRV9BUFBfVVNFUjogYXBwXG4gIENMSUNLSE9VU0VfQVBQX1BBU1NXT1JEOiBhcHBwYXNzXG4gIENMSUNLSE9VU0VfTE9HU19DTFVTVEVSX0hPU1Q6IGNsaWNraG91c2VcbiAgQ0xJQ0tIT1VTRV9MT0dTX0NMVVNURVJfU0VDVVJFOiBcImZhbHNlXCJcbiAgIyBSZWRpcyAvIEthZmthXG4gIFJFRElTX1VSTDogcmVkaXM6Ly9yZWRpczc6NjM3OS9cbiAgS0FGS0FfSE9TVFM6IGthZmthOjkwOTJcbiAgRkxBR1NfUkVESVNfRU5BQkxFRDogXCJmYWxzZVwiXG4gICMgT2JqZWN0IHN0b3JhZ2UgKE1pbklPKVxuICBPQkpFQ1RfU1RPUkFHRV9FTkFCTEVEOiBcInRydWVcIlxuICBPQkpFQ1RfU1RPUkFHRV9FTkRQT0lOVDogaHR0cDovL29iamVjdHN0b3JhZ2U6MTkwMDBcbiAgT0JKRUNUX1NUT1JBR0VfUFVCTElDX0VORFBPSU5UOiAke1BPU1RIT0dfU0lURV9VUkx9XG4gIE9CSkVDVF9TVE9SQUdFX0FDQ0VTU19LRVlfSUQ6IG9iamVjdF9zdG9yYWdlX3Jvb3RfdXNlclxuICBPQkpFQ1RfU1RPUkFHRV9TRUNSRVRfQUNDRVNTX0tFWTogb2JqZWN0X3N0b3JhZ2Vfcm9vdF9wYXNzd29yZFxuICBPQkpFQ1RfU1RPUkFHRV9GT1JDRV9QQVRIX1NUWUxFOiBcInRydWVcIlxuICAjIFNlc3Npb24gcmVwbGF5IHN0b3JhZ2VcbiAgU0VTU0lPTl9SRUNPUkRJTkdfVjJfUzNfRU5EUE9JTlQ6IGh0dHA6Ly9vYmplY3RzdG9yYWdlOjE5MDAwXG4gIFNFU1NJT05fUkVDT1JESU5HX1YyX1MzX0FDQ0VTU19LRVlfSUQ6IG9iamVjdF9zdG9yYWdlX3Jvb3RfdXNlclxuICBTRVNTSU9OX1JFQ09SRElOR19WMl9TM19TRUNSRVRfQUNDRVNTX0tFWTogb2JqZWN0X3N0b3JhZ2Vfcm9vdF9wYXNzd29yZFxuICBSRUNPUkRJTkdfQVBJX1VSTDogaHR0cDovL3JlY29yZGluZy1hcGk6NjczOFxuICAjIEFwcFxuICBTSVRFX1VSTDogJHtQT1NUSE9HX1NJVEVfVVJMfVxuICBTRUNSRVRfS0VZOiAke1BPU1RIT0dfU0VDUkVUX0tFWX1cbiAgRU5DUllQVElPTl9TQUxUX0tFWVM6ICR7UE9TVEhPR19FTkNSWVBUSU9OX1NBTFRfS0VZU31cbiAgREVQTE9ZTUVOVDogaG9iYnlcbiAgSVNfQkVISU5EX1BST1hZOiBcInRydWVcIlxuICBESVNBQkxFX1NFQ1VSRV9TU0xfUkVESVJFQ1Q6IFwidHJ1ZVwiXG4gICMgXCJmYWxzZVwiIHNvIGxvZ2luIHdvcmtzIG92ZXIgcGxhaW4gSFRUUDsgc2V0IHRvIFwidHJ1ZVwiIG9uY2UgdGhlIGRvbWFpbiB1c2VzIEhUVFBTXG4gIFNFQ1VSRV9DT09LSUVTOiAke1BPU1RIT0dfU0VDVVJFX0NPT0tJRVN9XG4gIENEUF9BUElfVVJMOiBodHRwOi8vcGx1Z2luczo2NzM4XG4gIEZFQVRVUkVfRkxBR1NfU0VSVklDRV9VUkw6IGh0dHA6Ly9mZWF0dXJlLWZsYWdzOjMwMDFcbiAgTElWRVNUUkVBTV9IT1NUOiAke1BPU1RIT0dfU0lURV9VUkx9L2xpdmVzdHJlYW1cbiAgQVBJX1FVRVJJRVNfUEVSX1RFQU06ICd7XCIxXCI6IDEwMH0nXG4gIE9URUxfU0RLX0RJU0FCTEVEOiBcInRydWVcIlxuICBPVEVMX0VYUE9SVEVSX09UTFBfRU5EUE9JTlQ6IFwiXCJcblxuc2VydmljZXM6XG4gICMgT25lLXNob3Q6IGZldGNoZXMgdGhlIENsaWNrSG91c2UgY29uZmlndXJhdGlvbiwgS2Fma2EgdGFibGUgc2NoZW1hcyBhbmRcbiAgIyBmdW5uZWwgVURGcyBmcm9tIHRoZSBQb3N0SG9nIHJlcG8gKHBpbm5lZCB0byB0aGUgc2FtZSBjb21taXQgYXMgdGhlIGFwcFxuICAjIGltYWdlKSBwbHVzIHRoZSBHZW9MaXRlMiBHZW9JUCBkYXRhYmFzZS4gSWRlbXBvdGVudCBhY3Jvc3MgcmVkZXBsb3lzLlxuICBpbml0LWFzc2V0czpcbiAgICBpbWFnZTogYWxwaW5lOjMuMjFcbiAgICByZXN0YXJ0OiBvbi1mYWlsdXJlXG4gICAgbG9nZ2luZzogKmRlZmF1bHQtbG9nZ2luZ1xuICAgIGVudHJ5cG9pbnQ6IC9iaW4vc2hcbiAgICBjb21tYW5kOlxuICAgICAgLSAtY1xuICAgICAgLSB8XG4gICAgICAgIHNldCAtZVxuICAgICAgICBhcGsgYWRkIC0tbm8tY2FjaGUgZ2l0IGN1cmwgYnJvdGxpID4vZGV2L251bGxcbiAgICAgICAgaWYgWyAhIC1mIC9hc3NldHMvLm9rLSR7UE9TVEhPR19WRVJTSU9OfSBdOyB0aGVuXG4gICAgICAgICAgZWNobyBcIkZldGNoaW5nIFBvc3RIb2cgcmVwbyBhc3NldHMgQCAke1BPU1RIT0dfVkVSU0lPTn1cIlxuICAgICAgICAgIHJtIC1yZiAvdG1wL3BoICYmIG1rZGlyIC1wIC90bXAvcGggJiYgY2QgL3RtcC9waFxuICAgICAgICAgIGdpdCBpbml0IC1xIC5cbiAgICAgICAgICBnaXQgcmVtb3RlIGFkZCBvcmlnaW4gaHR0cHM6Ly9naXRodWIuY29tL1Bvc3RIb2cvcG9zdGhvZy5naXRcbiAgICAgICAgICBnaXQgc3BhcnNlLWNoZWNrb3V0IHNldCAtLW5vLWNvbmUgL2RvY2tlci9jbGlja2hvdXNlLyAvcG9zdGhvZy9pZGwvIC9wb3N0aG9nL3VzZXJfc2NyaXB0cy9cbiAgICAgICAgICBnaXQgLWMgcHJvdG9jb2wudmVyc2lvbj0yIGZldGNoIC1xIC0tZGVwdGggMSAtLWZpbHRlcj1ibG9iOm5vbmUgb3JpZ2luICR7UE9TVEhPR19WRVJTSU9OfVxuICAgICAgICAgIGdpdCBjaGVja291dCAtcSBGRVRDSF9IRUFEXG4gICAgICAgICAgcm0gLXJmIC9hc3NldHMvY2xpY2tob3VzZSAvYXNzZXRzL2lkbCAvYXNzZXRzL3VzZXJfc2NyaXB0cyAvYXNzZXRzLy5vay0qXG4gICAgICAgICAgY3AgLXIgZG9ja2VyL2NsaWNraG91c2UgL2Fzc2V0cy9jbGlja2hvdXNlXG4gICAgICAgICAgY3AgLXIgcG9zdGhvZy9pZGwgL2Fzc2V0cy9pZGxcbiAgICAgICAgICBjcCAtciBwb3N0aG9nL3VzZXJfc2NyaXB0cyAvYXNzZXRzL3VzZXJfc2NyaXB0c1xuICAgICAgICAgIHRvdWNoIC9hc3NldHMvLm9rLSR7UE9TVEhPR19WRVJTSU9OfVxuICAgICAgICAgIGVjaG8gXCJSZXBvIGFzc2V0cyByZWFkeVwiXG4gICAgICAgIGZpXG4gICAgICAgIGlmIFsgISAtcyAvc2hhcmUvR2VvTGl0ZTItQ2l0eS5tbWRiIF07IHRoZW5cbiAgICAgICAgICBlY2hvIFwiRG93bmxvYWRpbmcgR2VvTGl0ZTIgZGF0YWJhc2VcIlxuICAgICAgICAgIGN1cmwgLXNMIC0taHR0cDEuMSBodHRwczovL21tZGJjZG4ucG9zdGhvZy5uZXQvIHwgYnJvdGxpIC0tZGVjb21wcmVzcyAtLW91dHB1dD0vc2hhcmUvR2VvTGl0ZTItQ2l0eS5tbWRiXG4gICAgICAgICAgY2htb2QgNjQ0IC9zaGFyZS9HZW9MaXRlMi1DaXR5Lm1tZGJcbiAgICAgICAgZmlcbiAgICAgICAgZWNobyBcImluaXQtYXNzZXRzIGRvbmVcIlxuICAgIHZvbHVtZXM6XG4gICAgICAtIHBvc3Rob2ctYXNzZXRzOi9hc3NldHNcbiAgICAgIC0gZ2VvaXAtZGF0YTovc2hhcmVcblxuICBkYjpcbiAgICBpbWFnZTogcG9zdGdyZXM6MTUuMTItYWxwaW5lXG4gICAgcmVzdGFydDogdW5sZXNzLXN0b3BwZWRcbiAgICBsb2dnaW5nOiAqZGVmYXVsdC1sb2dnaW5nXG4gICAgZW52aXJvbm1lbnQ6XG4gICAgICBQT1NUR1JFU19VU0VSOiBwb3N0aG9nXG4gICAgICBQT1NUR1JFU19EQjogcG9zdGhvZ1xuICAgICAgUE9TVEdSRVNfUEFTU1dPUkQ6IHBvc3Rob2dcbiAgICBoZWFsdGhjaGVjazpcbiAgICAgIHRlc3Q6IFtcIkNNRC1TSEVMTFwiLCBcInBnX2lzcmVhZHkgLVUgcG9zdGhvZ1wiXVxuICAgICAgaW50ZXJ2YWw6IDVzXG4gICAgICB0aW1lb3V0OiAxMHNcbiAgICAgIHJldHJpZXM6IDMwXG4gICAgICBzdGFydF9wZXJpb2Q6IDEwc1xuICAgIHZvbHVtZXM6XG4gICAgICAtIHBvc3RncmVzLWRhdGE6L3Zhci9saWIvcG9zdGdyZXNxbC9kYXRhXG4gICAgICAtIC4uL2ZpbGVzL2RiLWluaXQ6L2RvY2tlci1lbnRyeXBvaW50LWluaXRkYi5kOnJvXG5cbiAgcmVkaXM3OlxuICAgIGltYWdlOiByZWRpczo3LjItYWxwaW5lXG4gICAgcmVzdGFydDogdW5sZXNzLXN0b3BwZWRcbiAgICBsb2dnaW5nOiAqZGVmYXVsdC1sb2dnaW5nXG4gICAgY29tbWFuZDogcmVkaXMtc2VydmVyIC0tbWF4bWVtb3J5LXBvbGljeSBhbGxrZXlzLWxydSAtLW1heG1lbW9yeSAyMDBtYlxuICAgIGhlYWx0aGNoZWNrOlxuICAgICAgdGVzdDogW1wiQ01EXCIsIFwicmVkaXMtY2xpXCIsIFwicGluZ1wiXVxuICAgICAgaW50ZXJ2YWw6IDVzXG4gICAgICB0aW1lb3V0OiAxMHNcbiAgICAgIHJldHJpZXM6IDEwXG4gICAgdm9sdW1lczpcbiAgICAgIC0gcmVkaXMtZGF0YTovZGF0YVxuXG4gICMgUmVxdWlyZWQgYnkgQ2xpY2tIb3VzZSBmb3IgZGlzdHJpYnV0ZWQgRERMIChkb2NrZXIvY2xpY2tob3VzZS9jb25maWcueG1sXG4gICMgcG9pbnRzIGF0IHpvb2tlZXBlcjoyMTgxKVxuICB6b29rZWVwZXI6XG4gICAgaW1hZ2U6IHpvb2tlZXBlcjozLjcuMFxuICAgIHJlc3RhcnQ6IHVubGVzcy1zdG9wcGVkXG4gICAgbG9nZ2luZzogKmRlZmF1bHQtbG9nZ2luZ1xuICAgIGVudmlyb25tZW50OlxuICAgICAgWk9PX0FVVE9QVVJHRV9QVVJHRUlOVEVSVkFMOiAxXG4gICAgICBaT09fQVVUT1BVUkdFX1NOQVBSRVRBSU5DT1VOVDogM1xuICAgIHZvbHVtZXM6XG4gICAgICAtIHpvb2tlZXBlci1kYXRhOi9kYXRhXG4gICAgICAtIHpvb2tlZXBlci1kYXRhbG9nOi9kYXRhbG9nXG5cbiAgIyBLYWZrYSBBUEkgcHJvdmlkZWQgYnkgUmVkcGFuZGEgKGFzIHVwc3RyZWFtKSwgdHVuZWQgZG93biBmb3Igc21hbGwgc2VydmVyc1xuICBrYWZrYTpcbiAgICBpbWFnZTogZG9ja2VyLmlvL3JlZHBhbmRhZGF0YS9yZWRwYW5kYTp2MjUuMS45XG4gICAgcmVzdGFydDogdW5sZXNzLXN0b3BwZWRcbiAgICBsb2dnaW5nOiAqZGVmYXVsdC1sb2dnaW5nXG4gICAgY29tbWFuZDpcbiAgICAgIC0gcmVkcGFuZGFcbiAgICAgIC0gc3RhcnRcbiAgICAgIC0gLS1rYWZrYS1hZGRyIGludGVybmFsOi8vMC4wLjAuMDo5MDkyXG4gICAgICAtIC0tYWR2ZXJ0aXNlLWthZmthLWFkZHIgaW50ZXJuYWw6Ly9rYWZrYTo5MDkyXG4gICAgICAtIC0tcnBjLWFkZHIga2Fma2E6MzMxNDVcbiAgICAgIC0gLS1hZHZlcnRpc2UtcnBjLWFkZHIga2Fma2E6MzMxNDVcbiAgICAgIC0gLS1tb2RlIGRldi1jb250YWluZXJcbiAgICAgIC0gLS1zbXAgMVxuICAgICAgLSAtLW1lbW9yeSAxR1xuICAgICAgLSAtLXJlc2VydmUtbWVtb3J5IDBNXG4gICAgICAtIC0tb3ZlcnByb3Zpc2lvbmVkXG4gICAgICAtIC0tc2V0IHJlZHBhbmRhLmVtcHR5X3NlZWRfc3RhcnRzX2NsdXN0ZXI9ZmFsc2VcbiAgICAgIC0gLS1zZWVkcyBrYWZrYTozMzE0NVxuICAgICAgLSAtLXNldCByZWRwYW5kYS5hdXRvX2NyZWF0ZV90b3BpY3NfZW5hYmxlZD10cnVlXG4gICAgdm9sdW1lczpcbiAgICAgIC0gcmVkcGFuZGEtZGF0YTovdmFyL2xpYi9yZWRwYW5kYS9kYXRhXG4gICAgaGVhbHRoY2hlY2s6XG4gICAgICB0ZXN0OiBbXCJDTUQtU0hFTExcIiwgXCJjdXJsIC1mIGh0dHA6Ly9sb2NhbGhvc3Q6OTY0NC92MS9zdGF0dXMvcmVhZHkgfHwgZXhpdCAxXCJdXG4gICAgICBpbnRlcnZhbDogNXNcbiAgICAgIHRpbWVvdXQ6IDEwc1xuICAgICAgcmV0cmllczogMzBcbiAgICAgIHN0YXJ0X3BlcmlvZDogMjBzXG5cbiAgIyBPbmUtc2hvdDogcHJlLWNyZWF0ZXMgdGhlIEthZmthIHRvcGljcyB0aGF0IGNvbnN1bWVycyBjaGVjayBhdCBzdGFydHVwXG4gIGthZmthLWluaXQ6XG4gICAgaW1hZ2U6IGRvY2tlci5pby9yZWRwYW5kYWRhdGEvcmVkcGFuZGE6djI1LjEuOVxuICAgIHJlc3RhcnQ6IG9uLWZhaWx1cmVcbiAgICBsb2dnaW5nOiAqZGVmYXVsdC1sb2dnaW5nXG4gICAgZW50cnlwb2ludDogL2Jpbi9zaFxuICAgIGRlcGVuZHNfb246XG4gICAgICBrYWZrYTpcbiAgICAgICAgY29uZGl0aW9uOiBzZXJ2aWNlX2hlYWx0aHlcbiAgICBjb21tYW5kOlxuICAgICAgLSAtY1xuICAgICAgLSB8XG4gICAgICAgIHNldCAtZVxuICAgICAgICBUT1BJQ1M9XCJjbGlja2hvdXNlX2V2ZW50c19qc29uIFxcXG4gICAgICAgICAgICBjbGlja2hvdXNlX2FpX2V2ZW50c19qc29uIFxcXG4gICAgICAgICAgICBjbGlja2hvdXNlX2hlYXRtYXBfZXZlbnRzIFxcXG4gICAgICAgICAgICBjbGlja2hvdXNlX2luZ2VzdGlvbl93YXJuaW5ncyBcXFxuICAgICAgICAgICAgZXZlbnRzX3BsdWdpbl9pbmdlc3Rpb24gXFxcbiAgICAgICAgICAgIGV2ZW50c19wbHVnaW5faW5nZXN0aW9uX2RscSBcXFxuICAgICAgICAgICAgZXZlbnRzX3BsdWdpbl9pbmdlc3Rpb25fb3ZlcmZsb3cgXFxcbiAgICAgICAgICAgIGV2ZW50c19wbHVnaW5faW5nZXN0aW9uX2FzeW5jIFxcXG4gICAgICAgICAgICBldmVudHNfcGx1Z2luX2luZ2VzdGlvbl9oaXN0b3JpY2FsIFxcXG4gICAgICAgICAgICBpbmdlc3Rpb24tY2xpZW50d2FybmluZ3MtbWFpbi0xIFxcXG4gICAgICAgICAgICBoZWF0bWFwc19pbmdlc3Rpb24gXFxcbiAgICAgICAgICAgIHNlc3Npb25fcmVjb3JkaW5nX3NuYXBzaG90X2l0ZW1fZXZlbnRzIFxcXG4gICAgICAgICAgICBzZXNzaW9uX3JlY29yZGluZ19zbmFwc2hvdF9pdGVtX292ZXJmbG93IFxcXG4gICAgICAgICAgICBjbGlja2hvdXNlX2dyb3VwcyBcXFxuICAgICAgICAgICAgY2xpY2tob3VzZV9wZXJzb24gXFxcbiAgICAgICAgICAgIGNsaWNraG91c2VfcGVyc29uX2Rpc3RpbmN0X2lkIFxcXG4gICAgICAgICAgICBjbGlja2hvdXNlX2FwcF9tZXRyaWNzMiBcXFxuICAgICAgICAgICAgbG9nX2VudHJpZXMgXFxcbiAgICAgICAgICAgIGNsaWNraG91c2VfdG9waG9nXCJcbiAgICAgICAgZm9yIHRvcGljIGluICQkVE9QSUNTOyBkb1xuICAgICAgICAgIHJwayB0b3BpYyBjcmVhdGUgXCIkJHRvcGljXCIgLS1icm9rZXJzIGthZmthOjkwOTIgLXAgMSAtciAxIDI+L2Rldi9udWxsIFxcXG4gICAgICAgICAgICB8fCBycGsgdG9waWMgbGlzdCAtLWJyb2tlcnMga2Fma2E6OTA5MiB8IGdyZXAgLXEgXCIkJHRvcGljXCJcbiAgICAgICAgZG9uZVxuICAgICAgICBlY2hvIFwiS2Fma2EgdG9waWNzIHJlYWR5XCJcblxuICBjbGlja2hvdXNlOlxuICAgIGltYWdlOiBjbGlja2hvdXNlL2NsaWNraG91c2Utc2VydmVyOjI2LjYuMS4xMTkzXG4gICAgcmVzdGFydDogdW5sZXNzLXN0b3BwZWRcbiAgICBsb2dnaW5nOiAqZGVmYXVsdC1sb2dnaW5nXG4gICAgZGVwZW5kc19vbjpcbiAgICAgIGluaXQtYXNzZXRzOlxuICAgICAgICBjb25kaXRpb246IHNlcnZpY2VfY29tcGxldGVkX3N1Y2Nlc3NmdWxseVxuICAgICAgem9va2VlcGVyOlxuICAgICAgICBjb25kaXRpb246IHNlcnZpY2Vfc3RhcnRlZFxuICAgICAga2Fma2E6XG4gICAgICAgIGNvbmRpdGlvbjogc2VydmljZV9zdGFydGVkXG4gICAgZW50cnlwb2ludDogL2Jpbi9iYXNoXG4gICAgY29tbWFuZDpcbiAgICAgIC0gLWNcbiAgICAgIC0gfFxuICAgICAgICBzZXQgLWVcbiAgICAgICAgY3AgL2Fzc2V0cy9jbGlja2hvdXNlL2NvbmZpZy54bWwgL2V0Yy9jbGlja2hvdXNlLXNlcnZlci9jb25maWcueG1sXG4gICAgICAgIGNwIC9hc3NldHMvY2xpY2tob3VzZS9jb25maWcuZC9kZWZhdWx0LnhtbCAvZXRjL2NsaWNraG91c2Utc2VydmVyL2NvbmZpZy5kL2RlZmF1bHQueG1sXG4gICAgICAgIGNwIC9hc3NldHMvY2xpY2tob3VzZS91c2Vycy54bWwgL2V0Yy9jbGlja2hvdXNlLXNlcnZlci91c2Vycy54bWxcbiAgICAgICAgY3AgL2Fzc2V0cy9jbGlja2hvdXNlL3VzZXJfZGVmaW5lZF9mdW5jdGlvbi54bWwgL2V0Yy9jbGlja2hvdXNlLXNlcnZlci91c2VyX2RlZmluZWRfZnVuY3Rpb24ueG1sXG4gICAgICAgIG1rZGlyIC1wIC92YXIvbGliL2NsaWNraG91c2UvZm9ybWF0X3NjaGVtYXMgL3Zhci9saWIvY2xpY2tob3VzZS91c2VyX3NjcmlwdHNcbiAgICAgICAgY3AgLXIgL2Fzc2V0cy9pZGwvLiAvdmFyL2xpYi9jbGlja2hvdXNlL2Zvcm1hdF9zY2hlbWFzL1xuICAgICAgICBjcCAtciAvYXNzZXRzL3VzZXJfc2NyaXB0cy8uIC92YXIvbGliL2NsaWNraG91c2UvdXNlcl9zY3JpcHRzL1xuICAgICAgICBjaG1vZCAtUiA3NTUgL3Zhci9saWIvY2xpY2tob3VzZS91c2VyX3NjcmlwdHNcbiAgICAgICAgY2hvd24gLVIgY2xpY2tob3VzZTpjbGlja2hvdXNlIC92YXIvbGliL2NsaWNraG91c2UvZm9ybWF0X3NjaGVtYXMgL3Zhci9saWIvY2xpY2tob3VzZS91c2VyX3NjcmlwdHMgfHwgdHJ1ZVxuICAgICAgICAjIE1hdGVyaWFsaXplIHN5c3RlbSBsb2cgdGFibGVzIChzeXN0ZW0uY3Jhc2hfbG9nIGlzIHJlcXVpcmVkIGJ5IHRoZVxuICAgICAgICAjIGN1c3RvbV9tZXRyaWNzIENsaWNrSG91c2UgbWlncmF0aW9uKSwgbWlycm9yaW5nIHVwc3RyZWFtIGluaXQtZGIuc2hcbiAgICAgICAgKFxuICAgICAgICAgIGk9MFxuICAgICAgICAgIHdoaWxlIFsgJCRpIC1sdCA5MCBdOyBkb1xuICAgICAgICAgICAgaWYgY2xpY2tob3VzZS1jbGllbnQgLS1xdWVyeSBcIlNFTEVDVCAxXCIgPi9kZXYvbnVsbCAyPiYxOyB0aGVuXG4gICAgICAgICAgICAgIGNsaWNraG91c2UtY2xpZW50IC0tcXVlcnkgXCJTWVNURU0gRkxVU0ggTE9HU1wiICYmIGVjaG8gXCJzeXN0ZW0gbG9ncyBmbHVzaGVkXCIgJiYgYnJlYWtcbiAgICAgICAgICAgIGZpXG4gICAgICAgICAgICBzbGVlcCAyXG4gICAgICAgICAgICBpPSQkKChpKzEpKVxuICAgICAgICAgIGRvbmVcbiAgICAgICAgKSAmXG4gICAgICAgIGV4ZWMgL2VudHJ5cG9pbnQuc2hcbiAgICBlbnZpcm9ubWVudDpcbiAgICAgIENMSUNLSE9VU0VfU0tJUF9VU0VSX1NFVFVQOiAxXG4gICAgICBLQUZLQV9IT1NUUzoga2Fma2E6OTA5MlxuICAgIHZvbHVtZXM6XG4gICAgICAtIHBvc3Rob2ctYXNzZXRzOi9hc3NldHM6cm9cbiAgICAgIC0gY2xpY2tob3VzZS1kYXRhOi92YXIvbGliL2NsaWNraG91c2VcbiAgICBoZWFsdGhjaGVjazpcbiAgICAgIHRlc3Q6IFtcIkNNRC1TSEVMTFwiLCBcIndnZXQgLS1uby12ZXJib3NlIC0tdHJpZXM9MSAtLXNwaWRlciBodHRwOi8vbG9jYWxob3N0OjgxMjMvcGluZyB8fCBleGl0IDFcIl1cbiAgICAgIGludGVydmFsOiA1c1xuICAgICAgdGltZW91dDogMTBzXG4gICAgICByZXRyaWVzOiAzMFxuICAgICAgc3RhcnRfcGVyaW9kOiAzMHNcblxuICAjIERqYW5nbyBhcHA6IHJ1bnMgbWlncmF0aW9ucywgdGhlbiBzZXJ2ZXMgdGhlIEFQSSArIFVJIG9uIDo4MDAwXG4gIHdlYjpcbiAgICBpbWFnZTogcG9zdGhvZy9wb3N0aG9nOiR7UE9TVEhPR19WRVJTSU9OfVxuICAgIHJlc3RhcnQ6IHVubGVzcy1zdG9wcGVkXG4gICAgbG9nZ2luZzogKmRlZmF1bHQtbG9nZ2luZ1xuICAgIGNvbW1hbmQ6IFtcInNoXCIsIFwiLWNcIiwgXCIuL2Jpbi9taWdyYXRlICYmIGV4ZWMgLi9iaW4vZG9ja2VyLXNlcnZlclwiXVxuICAgIGRlcGVuZHNfb246XG4gICAgICBkYjpcbiAgICAgICAgY29uZGl0aW9uOiBzZXJ2aWNlX2hlYWx0aHlcbiAgICAgIHJlZGlzNzpcbiAgICAgICAgY29uZGl0aW9uOiBzZXJ2aWNlX2hlYWx0aHlcbiAgICAgIGNsaWNraG91c2U6XG4gICAgICAgIGNvbmRpdGlvbjogc2VydmljZV9oZWFsdGh5XG4gICAgICBrYWZrYTpcbiAgICAgICAgY29uZGl0aW9uOiBzZXJ2aWNlX2hlYWx0aHlcbiAgICAgIGthZmthLWluaXQ6XG4gICAgICAgIGNvbmRpdGlvbjogc2VydmljZV9jb21wbGV0ZWRfc3VjY2Vzc2Z1bGx5XG4gICAgICBvYmplY3RzdG9yYWdlOlxuICAgICAgICBjb25kaXRpb246IHNlcnZpY2Vfc3RhcnRlZFxuICAgIGVudmlyb25tZW50OlxuICAgICAgPDw6ICpkamFuZ28tZW52XG4gICAgICBOR0lOWF9VTklUX0FQUF9QUk9DRVNTRVM6IDJcbiAgICBoZWFsdGhjaGVjazpcbiAgICAgIHRlc3Q6IFtcIkNNRC1TSEVMTFwiLCBcImN1cmwgLWZzIGh0dHA6Ly9sb2NhbGhvc3Q6ODAwMC9faGVhbHRoIHx8IGV4aXQgMVwiXVxuICAgICAgaW50ZXJ2YWw6IDMwc1xuICAgICAgdGltZW91dDogMTBzXG4gICAgICByZXRyaWVzOiAxNVxuICAgICAgc3RhcnRfcGVyaW9kOiA2MDBzXG5cbiAgIyBDZWxlcnkgd29ya2VyICsgc2NoZWR1bGVyXG4gIHdvcmtlcjpcbiAgICBpbWFnZTogcG9zdGhvZy9wb3N0aG9nOiR7UE9TVEhPR19WRVJTSU9OfVxuICAgIHJlc3RhcnQ6IHVubGVzcy1zdG9wcGVkXG4gICAgbG9nZ2luZzogKmRlZmF1bHQtbG9nZ2luZ1xuICAgIGNvbW1hbmQ6IC4vYmluL2RvY2tlci13b3JrZXItY2VsZXJ5IC0td2l0aC1zY2hlZHVsZXJcbiAgICBkZXBlbmRzX29uOlxuICAgICAgZGI6XG4gICAgICAgIGNvbmRpdGlvbjogc2VydmljZV9oZWFsdGh5XG4gICAgICByZWRpczc6XG4gICAgICAgIGNvbmRpdGlvbjogc2VydmljZV9oZWFsdGh5XG4gICAgICBjbGlja2hvdXNlOlxuICAgICAgICBjb25kaXRpb246IHNlcnZpY2VfaGVhbHRoeVxuICAgICAga2Fma2E6XG4gICAgICAgIGNvbmRpdGlvbjogc2VydmljZV9oZWFsdGh5XG4gICAgICB3ZWI6XG4gICAgICAgIGNvbmRpdGlvbjogc2VydmljZV9zdGFydGVkXG4gICAgZW52aXJvbm1lbnQ6XG4gICAgICA8PDogKmRqYW5nby1lbnZcbiAgICAgIFBPU1RIT0dfU0tJUF9NSUdSQVRJT05fQ0hFQ0tTOiBcIjFcIlxuICAgICAgV0VCX0NPTkNVUlJFTkNZOiAyXG5cbiAgIyBOb2RlIHBsdWdpbiBzZXJ2ZXI6IENEUCAoZGVzdGluYXRpb25zLCB3ZWJob29rcywgdHJhbnNmb3JtYXRpb25zKVxuICBwbHVnaW5zOlxuICAgIGltYWdlOiBwb3N0aG9nL3Bvc3Rob2ctbm9kZToke1BPU1RIT0dfTk9ERV9WRVJTSU9OfVxuICAgIHJlc3RhcnQ6IHVubGVzcy1zdG9wcGVkXG4gICAgbG9nZ2luZzogKmRlZmF1bHQtbG9nZ2luZ1xuICAgIGRlcGVuZHNfb246XG4gICAgICBkYjpcbiAgICAgICAgY29uZGl0aW9uOiBzZXJ2aWNlX2hlYWx0aHlcbiAgICAgIHJlZGlzNzpcbiAgICAgICAgY29uZGl0aW9uOiBzZXJ2aWNlX2hlYWx0aHlcbiAgICAgIGthZmthOlxuICAgICAgICBjb25kaXRpb246IHNlcnZpY2VfaGVhbHRoeVxuICAgICAgY2xpY2tob3VzZTpcbiAgICAgICAgY29uZGl0aW9uOiBzZXJ2aWNlX3N0YXJ0ZWRcbiAgICAgIGthZmthLWluaXQ6XG4gICAgICAgIGNvbmRpdGlvbjogc2VydmljZV9jb21wbGV0ZWRfc3VjY2Vzc2Z1bGx5XG4gICAgICBpbml0LWFzc2V0czpcbiAgICAgICAgY29uZGl0aW9uOiBzZXJ2aWNlX2NvbXBsZXRlZF9zdWNjZXNzZnVsbHlcbiAgICBlbnZpcm9ubWVudDpcbiAgICAgICMgUnVuIG9ubHkgdGhlIHBpcGVsaW5lcyB0aGlzIHRlbXBsYXRlIHNoaXBzIChDRFAgZGVzdGluYXRpb25zL3dvcmtmbG93cyxcbiAgICAgICMgcmVhbHRpbWUgY29ob3J0cywgZmVhdHVyZS1mbGFnIGV2YWx1YXRpb24pLiBUaGUgZGVmYXVsdCBtb2RlIHdvdWxkIGFsc29cbiAgICAgICMgc3RhcnQgdGhlIGxvZ3MvZXJyb3ItdHJhY2tpbmcgaW5nZXN0aW9uIGNvbnN1bWVycywgd2hpY2ggdGhpcyB0ZW1wbGF0ZVxuICAgICAgIyBpbnRlbnRpb25hbGx5IG9taXRzLlxuICAgICAgTk9ERUpTX0NBUEFCSUxJVFlfR1JPVVBTOiBjZHBfd29ya2Zsb3dzLHJlYWx0aW1lX2NvaG9ydHMsZmVhdHVyZV9mbGFnc1xuICAgICAgU0lURV9VUkw6ICR7UE9TVEhPR19TSVRFX1VSTH1cbiAgICAgIFNFQ1JFVF9LRVk6ICR7UE9TVEhPR19TRUNSRVRfS0VZfVxuICAgICAgRU5DUllQVElPTl9TQUxUX0tFWVM6ICR7UE9TVEhPR19FTkNSWVBUSU9OX1NBTFRfS0VZU31cbiAgICAgIERBVEFCQVNFX1VSTDogcG9zdGdyZXM6Ly9wb3N0aG9nOnBvc3Rob2dAZGI6NTQzMi9wb3N0aG9nXG4gICAgICBQRVJTT05TX0RBVEFCQVNFX1VSTDogcG9zdGdyZXM6Ly9wb3N0aG9nOnBvc3Rob2dAZGI6NTQzMi9wb3N0aG9nXG4gICAgICBCRUhBVklPUkFMX0NPSE9SVFNfREFUQUJBU0VfVVJMOiBwb3N0Z3JlczovL3Bvc3Rob2c6cG9zdGhvZ0BkYjo1NDMyL3Bvc3Rob2dcbiAgICAgIENZQ0xPVFJPTl9EQVRBQkFTRV9VUkw6IHBvc3RncmVzOi8vcG9zdGhvZzpwb3N0aG9nQGRiOjU0MzIvcG9zdGhvZ1xuICAgICAgS0FGS0FfSE9TVFM6IGthZmthOjkwOTJcbiAgICAgIFJFRElTX1VSTDogcmVkaXM6Ly9yZWRpczc6NjM3OS9cbiAgICAgIENEUF9SRURJU19IT1NUOiByZWRpczdcbiAgICAgIENEUF9SRURJU19QT1JUOiA2Mzc5XG4gICAgICAjIFRMUyBmb3IgdGhlc2UgZGVmYXVsdHMgdG8gXCJ0cnVlXCIgaW4gcHJvZHVjdGlvbiBpbWFnZXM7IHRoaXMgc3RhY2snc1xuICAgICAgIyBSZWRpcyBpcyBwbGFpbnRleHQgKGEgVExTIGhhbmRzaGFrZSBhZ2FpbnN0IGl0IGhhbmdzIHVudGlsIHRpbWVvdXQgYW5kXG4gICAgICAjIGNyYXNoLWxvb3BzIHRoZSBwcm9jZXNzIGlmIHRoZXNlIGNvbnN1bWVycyBldmVyIHJ1bikuXG4gICAgICBMT0dTX1JFRElTX0hPU1Q6IHJlZGlzN1xuICAgICAgTE9HU19SRURJU19UTFM6IFwiZmFsc2VcIlxuICAgICAgVFJBQ0VTX1JFRElTX0hPU1Q6IHJlZGlzN1xuICAgICAgVFJBQ0VTX1JFRElTX1RMUzogXCJmYWxzZVwiXG4gICAgICBDT09LSUVMRVNTX1JFRElTX0hPU1Q6IHJlZGlzN1xuICAgICAgQ09PS0lFTEVTU19SRURJU19QT1JUOiA2Mzc5XG4gICAgICBDTElDS0hPVVNFX0hPU1Q6IGNsaWNraG91c2VcbiAgICAgIENMSUNLSE9VU0VfREFUQUJBU0U6IHBvc3Rob2dcbiAgICAgIENMSUNLSE9VU0VfU0VDVVJFOiBcImZhbHNlXCJcbiAgICAgIENMSUNLSE9VU0VfVkVSSUZZOiBcImZhbHNlXCJcbiAgICAgIE9CSkVDVF9TVE9SQUdFX0VOQUJMRUQ6IFwidHJ1ZVwiXG4gICAgICBPQkpFQ1RfU1RPUkFHRV9FTkRQT0lOVDogaHR0cDovL29iamVjdHN0b3JhZ2U6MTkwMDBcbiAgICAgIE9CSkVDVF9TVE9SQUdFX1BVQkxJQ19FTkRQT0lOVDogJHtQT1NUSE9HX1NJVEVfVVJMfVxuICAgICAgT0JKRUNUX1NUT1JBR0VfQUNDRVNTX0tFWV9JRDogb2JqZWN0X3N0b3JhZ2Vfcm9vdF91c2VyXG4gICAgICBPQkpFQ1RfU1RPUkFHRV9TRUNSRVRfQUNDRVNTX0tFWTogb2JqZWN0X3N0b3JhZ2Vfcm9vdF9wYXNzd29yZFxuICAgICAgT1RFTF9FWFBPUlRFUl9PVExQX0VORFBPSU5UOiBcIlwiXG4gICAgdm9sdW1lczpcbiAgICAgIC0gZ2VvaXAtZGF0YTovc2hhcmU6cm9cblxuICAjIE5vZGUgcGx1Z2luIHNlcnZlcjogZXZlbnQgaW5nZXN0aW9uIChLYWZrYSAtPiBwZXJzb24gcHJvY2Vzc2luZyAtPiBDbGlja0hvdXNlKVxuICBpbmdlc3Rpb24tZ2VuZXJhbDpcbiAgICBpbWFnZTogcG9zdGhvZy9wb3N0aG9nLW5vZGU6JHtQT1NUSE9HX05PREVfVkVSU0lPTn1cbiAgICByZXN0YXJ0OiB1bmxlc3Mtc3RvcHBlZFxuICAgIGxvZ2dpbmc6ICpkZWZhdWx0LWxvZ2dpbmdcbiAgICBkZXBlbmRzX29uOlxuICAgICAgZGI6XG4gICAgICAgIGNvbmRpdGlvbjogc2VydmljZV9oZWFsdGh5XG4gICAgICByZWRpczc6XG4gICAgICAgIGNvbmRpdGlvbjogc2VydmljZV9oZWFsdGh5XG4gICAgICBrYWZrYTpcbiAgICAgICAgY29uZGl0aW9uOiBzZXJ2aWNlX2hlYWx0aHlcbiAgICAgIGNsaWNraG91c2U6XG4gICAgICAgIGNvbmRpdGlvbjogc2VydmljZV9zdGFydGVkXG4gICAgICBrYWZrYS1pbml0OlxuICAgICAgICBjb25kaXRpb246IHNlcnZpY2VfY29tcGxldGVkX3N1Y2Nlc3NmdWxseVxuICAgICAgaW5pdC1hc3NldHM6XG4gICAgICAgIGNvbmRpdGlvbjogc2VydmljZV9jb21wbGV0ZWRfc3VjY2Vzc2Z1bGx5XG4gICAgZW52aXJvbm1lbnQ6XG4gICAgICBQTFVHSU5fU0VSVkVSX01PREU6IGluZ2VzdGlvbi12Mi1jb21iaW5lZFxuICAgICAgRU5DUllQVElPTl9TQUxUX0tFWVM6ICR7UE9TVEhPR19FTkNSWVBUSU9OX1NBTFRfS0VZU31cbiAgICAgIERBVEFCQVNFX1VSTDogcG9zdGdyZXM6Ly9wb3N0aG9nOnBvc3Rob2dAZGI6NTQzMi9wb3N0aG9nXG4gICAgICBQRVJTT05TX0RBVEFCQVNFX1VSTDogcG9zdGdyZXM6Ly9wb3N0aG9nOnBvc3Rob2dAZGI6NTQzMi9wb3N0aG9nXG4gICAgICBCRUhBVklPUkFMX0NPSE9SVFNfREFUQUJBU0VfVVJMOiBwb3N0Z3JlczovL3Bvc3Rob2c6cG9zdGhvZ0BkYjo1NDMyL3Bvc3Rob2dcbiAgICAgIEtBRktBX0hPU1RTOiBrYWZrYTo5MDkyXG4gICAgICBSRURJU19VUkw6IHJlZGlzOi8vcmVkaXM3OjYzNzkvXG4gICAgICBDT09LSUVMRVNTX1JFRElTX0hPU1Q6IHJlZGlzN1xuICAgICAgQ09PS0lFTEVTU19SRURJU19QT1JUOiA2Mzc5XG4gICAgICBDRFBfUkVESVNfSE9TVDogcmVkaXM3XG4gICAgICBMT0dTX1JFRElTX0hPU1Q6IHJlZGlzN1xuICAgICAgTE9HU19SRURJU19UTFM6IFwiZmFsc2VcIlxuICAgICAgVFJBQ0VTX1JFRElTX0hPU1Q6IHJlZGlzN1xuICAgICAgVFJBQ0VTX1JFRElTX1RMUzogXCJmYWxzZVwiXG4gICAgICBDTElDS0hPVVNFX0hPU1Q6IGNsaWNraG91c2VcbiAgICAgIENMSUNLSE9VU0VfREFUQUJBU0U6IHBvc3Rob2dcbiAgICAgIENMSUNLSE9VU0VfU0VDVVJFOiBcImZhbHNlXCJcbiAgICAgIENMSUNLSE9VU0VfVkVSSUZZOiBcImZhbHNlXCJcbiAgICB2b2x1bWVzOlxuICAgICAgLSBnZW9pcC1kYXRhOi9zaGFyZTpyb1xuXG4gICMgTm9kZSBwbHVnaW4gc2VydmVyOiBzZXNzaW9uIHJlcGxheSBibG9iIGluZ2VzdGlvbiAoS2Fma2EgLT4gUzMpXG4gIGluZ2VzdGlvbi1zZXNzaW9ucmVwbGF5OlxuICAgIGltYWdlOiBwb3N0aG9nL3Bvc3Rob2ctbm9kZToke1BPU1RIT0dfTk9ERV9WRVJTSU9OfVxuICAgIHJlc3RhcnQ6IHVubGVzcy1zdG9wcGVkXG4gICAgbG9nZ2luZzogKmRlZmF1bHQtbG9nZ2luZ1xuICAgIGRlcGVuZHNfb246XG4gICAgICBkYjpcbiAgICAgICAgY29uZGl0aW9uOiBzZXJ2aWNlX2hlYWx0aHlcbiAgICAgIHJlZGlzNzpcbiAgICAgICAgY29uZGl0aW9uOiBzZXJ2aWNlX2hlYWx0aHlcbiAgICAgIGthZmthOlxuICAgICAgICBjb25kaXRpb246IHNlcnZpY2VfaGVhbHRoeVxuICAgICAga2Fma2EtaW5pdDpcbiAgICAgICAgY29uZGl0aW9uOiBzZXJ2aWNlX2NvbXBsZXRlZF9zdWNjZXNzZnVsbHlcbiAgICAgIG9iamVjdHN0b3JhZ2U6XG4gICAgICAgIGNvbmRpdGlvbjogc2VydmljZV9zdGFydGVkXG4gICAgZW52aXJvbm1lbnQ6XG4gICAgICBQTFVHSU5fU0VSVkVSX01PREU6IHJlY29yZGluZ3MtYmxvYi1pbmdlc3Rpb24tdjJcbiAgICAgIEVOQ1JZUFRJT05fU0FMVF9LRVlTOiAke1BPU1RIT0dfRU5DUllQVElPTl9TQUxUX0tFWVN9XG4gICAgICBEQVRBQkFTRV9VUkw6IHBvc3RncmVzOi8vcG9zdGhvZzpwb3N0aG9nQGRiOjU0MzIvcG9zdGhvZ1xuICAgICAgS0FGS0FfSE9TVFM6IGthZmthOjkwOTJcbiAgICAgIFJFRElTX1VSTDogcmVkaXM6Ly9yZWRpczc6NjM3OS9cbiAgICAgIFNFU1NJT05fUkVDT1JESU5HX1YyX1MzX0VORFBPSU5UOiBodHRwOi8vb2JqZWN0c3RvcmFnZToxOTAwMFxuICAgICAgU0VTU0lPTl9SRUNPUkRJTkdfVjJfUzNfQUNDRVNTX0tFWV9JRDogb2JqZWN0X3N0b3JhZ2Vfcm9vdF91c2VyXG4gICAgICBTRVNTSU9OX1JFQ09SRElOR19WMl9TM19TRUNSRVRfQUNDRVNTX0tFWTogb2JqZWN0X3N0b3JhZ2Vfcm9vdF9wYXNzd29yZFxuICAgICAgU0VTU0lPTl9SRUNPUkRJTkdfVjJfUzNfVElNRU9VVF9NUzogMTIwMDAwXG5cbiAgIyBOb2RlIHBsdWdpbiBzZXJ2ZXI6IHNlc3Npb24gcmVwbGF5IHBsYXliYWNrIEFQSVxuICByZWNvcmRpbmctYXBpOlxuICAgIGltYWdlOiBwb3N0aG9nL3Bvc3Rob2ctbm9kZToke1BPU1RIT0dfTk9ERV9WRVJTSU9OfVxuICAgIHJlc3RhcnQ6IHVubGVzcy1zdG9wcGVkXG4gICAgbG9nZ2luZzogKmRlZmF1bHQtbG9nZ2luZ1xuICAgIGRlcGVuZHNfb246XG4gICAgICBkYjpcbiAgICAgICAgY29uZGl0aW9uOiBzZXJ2aWNlX2hlYWx0aHlcbiAgICAgIHJlZGlzNzpcbiAgICAgICAgY29uZGl0aW9uOiBzZXJ2aWNlX2hlYWx0aHlcbiAgICAgIGNsaWNraG91c2U6XG4gICAgICAgIGNvbmRpdGlvbjogc2VydmljZV9zdGFydGVkXG4gICAgICBvYmplY3RzdG9yYWdlOlxuICAgICAgICBjb25kaXRpb246IHNlcnZpY2Vfc3RhcnRlZFxuICAgIGVudmlyb25tZW50OlxuICAgICAgUExVR0lOX1NFUlZFUl9NT0RFOiByZWNvcmRpbmctYXBpXG4gICAgICBFTkNSWVBUSU9OX1NBTFRfS0VZUzogJHtQT1NUSE9HX0VOQ1JZUFRJT05fU0FMVF9LRVlTfVxuICAgICAgREFUQUJBU0VfVVJMOiBwb3N0Z3JlczovL3Bvc3Rob2c6cG9zdGhvZ0BkYjo1NDMyL3Bvc3Rob2dcbiAgICAgIFJFRElTX1VSTDogcmVkaXM6Ly9yZWRpczc6NjM3OS9cbiAgICAgIFNFU1NJT05fUkVDT1JESU5HX0FQSV9SRURJU19IT1NUOiByZWRpczdcbiAgICAgIFNFU1NJT05fUkVDT1JESU5HX0FQSV9SRURJU19QT1JUOiA2Mzc5XG4gICAgICBDTElDS0hPVVNFX0hPU1Q6IGNsaWNraG91c2VcbiAgICAgIENMSUNLSE9VU0VfREFUQUJBU0U6IHBvc3Rob2dcbiAgICAgIENMSUNLSE9VU0VfU0VDVVJFOiBcImZhbHNlXCJcbiAgICAgIENMSUNLSE9VU0VfVkVSSUZZOiBcImZhbHNlXCJcbiAgICAgIFNFU1NJT05fUkVDT1JESU5HX1YyX1MzX0VORFBPSU5UOiBodHRwOi8vb2JqZWN0c3RvcmFnZToxOTAwMFxuICAgICAgU0VTU0lPTl9SRUNPUkRJTkdfVjJfUzNfQUNDRVNTX0tFWV9JRDogb2JqZWN0X3N0b3JhZ2Vfcm9vdF91c2VyXG4gICAgICBTRVNTSU9OX1JFQ09SRElOR19WMl9TM19TRUNSRVRfQUNDRVNTX0tFWTogb2JqZWN0X3N0b3JhZ2Vfcm9vdF9wYXNzd29yZFxuXG4gICMgUnVzdCBldmVudCBjYXB0dXJlIGVuZHBvaW50ICgvZSwgL2JhdGNoLCAvY2FwdHVyZSwgL2kvdjApXG4gIGNhcHR1cmU6XG4gICAgaW1hZ2U6IGdoY3IuaW8vcG9zdGhvZy9wb3N0aG9nL2NhcHR1cmU6bWFzdGVyXG4gICAgcmVzdGFydDogdW5sZXNzLXN0b3BwZWRcbiAgICBsb2dnaW5nOiAqZGVmYXVsdC1sb2dnaW5nXG4gICAgZGVwZW5kc19vbjpcbiAgICAgIGthZmthOlxuICAgICAgICBjb25kaXRpb246IHNlcnZpY2VfaGVhbHRoeVxuICAgICAgcmVkaXM3OlxuICAgICAgICBjb25kaXRpb246IHNlcnZpY2VfaGVhbHRoeVxuICAgIGVudmlyb25tZW50OlxuICAgICAgQUREUkVTUzogMC4wLjAuMDozMDAwXG4gICAgICBLQUZLQV9UT1BJQzogZXZlbnRzX3BsdWdpbl9pbmdlc3Rpb25cbiAgICAgIEtBRktBX0hPU1RTOiBrYWZrYTo5MDkyXG4gICAgICBSRURJU19VUkw6IHJlZGlzOi8vcmVkaXM3OjYzNzkvXG4gICAgICBDQVBUVVJFX01PREU6IGV2ZW50c1xuICAgICAgUlVTVF9MT0c6IGluZm8scmRrYWZrYT13YXJuXG4gICAgICBDQVBUVVJFX1YxX1NJTktTOiBtc2tcbiAgICAgIENBUFRVUkVfVjFfU0lOS19NU0tfS0FGS0FfSE9TVFM6IGthZmthOjkwOTJcbiAgICAgIENBUFRVUkVfVjFfU0lOS19NU0tfS0FGS0FfVE9QSUNfTUFJTjogZXZlbnRzX3BsdWdpbl9pbmdlc3Rpb25cbiAgICAgIENBUFRVUkVfVjFfU0lOS19NU0tfS0FGS0FfVE9QSUNfSElTVE9SSUNBTDogZXZlbnRzX3BsdWdpbl9pbmdlc3Rpb25faGlzdG9yaWNhbFxuICAgICAgQ0FQVFVSRV9WMV9TSU5LX01TS19LQUZLQV9UT1BJQ19PVkVSRkxPVzogZXZlbnRzX3BsdWdpbl9pbmdlc3Rpb25fb3ZlcmZsb3dcbiAgICAgIENBUFRVUkVfVjFfU0lOS19NU0tfS0FGS0FfVE9QSUNfRExROiBldmVudHNfcGx1Z2luX2luZ2VzdGlvbl9kbHFcbiAgICAgIENBUFRVUkVfVjFfU0lOS19NU0tfS0FGS0FfVE9QSUNfRVhDRVBUSU9OOiBpbmdlc3Rpb24tZXJyb3J0cmFja2luZy1tYWluXG4gICAgICBDQVBUVVJFX1YxX1NJTktfTVNLX0tBRktBX1RPUElDX0hFQVRNQVA6IGhlYXRtYXBzX2luZ2VzdGlvblxuICAgICAgQ0FQVFVSRV9WMV9TSU5LX01TS19LQUZLQV9UT1BJQ19DTElFTlRfSU5HRVNUSU9OX1dBUk5JTkc6IGluZ2VzdGlvbi1jbGllbnR3YXJuaW5ncy1tYWluLTFcblxuICAjIFJ1c3QgY2FwdHVyZSBlbmRwb2ludCBmb3Igc2Vzc2lvbiByZWNvcmRpbmdzICgvcylcbiAgcmVwbGF5LWNhcHR1cmU6XG4gICAgaW1hZ2U6IGdoY3IuaW8vcG9zdGhvZy9wb3N0aG9nL2NhcHR1cmU6bWFzdGVyXG4gICAgcmVzdGFydDogdW5sZXNzLXN0b3BwZWRcbiAgICBsb2dnaW5nOiAqZGVmYXVsdC1sb2dnaW5nXG4gICAgZGVwZW5kc19vbjpcbiAgICAgIGthZmthOlxuICAgICAgICBjb25kaXRpb246IHNlcnZpY2VfaGVhbHRoeVxuICAgICAgcmVkaXM3OlxuICAgICAgICBjb25kaXRpb246IHNlcnZpY2VfaGVhbHRoeVxuICAgIGVudmlyb25tZW50OlxuICAgICAgQUREUkVTUzogMC4wLjAuMDozMDAwXG4gICAgICBLQUZLQV9UT1BJQzogc2Vzc2lvbl9yZWNvcmRpbmdfc25hcHNob3RfaXRlbV9ldmVudHNcbiAgICAgIEtBRktBX0hPU1RTOiBrYWZrYTo5MDkyXG4gICAgICBSRURJU19VUkw6IHJlZGlzOi8vcmVkaXM3OjYzNzkvXG4gICAgICBDQVBUVVJFX01PREU6IHJlY29yZGluZ3NcblxuICAjIFJ1c3QgZmVhdHVyZSBmbGFnIGV2YWx1YXRpb24gc2VydmljZSAoL2ZsYWdzKVxuICBmZWF0dXJlLWZsYWdzOlxuICAgIGltYWdlOiBnaGNyLmlvL3Bvc3Rob2cvcG9zdGhvZy9mZWF0dXJlLWZsYWdzOm1hc3RlclxuICAgIHJlc3RhcnQ6IHVubGVzcy1zdG9wcGVkXG4gICAgbG9nZ2luZzogKmRlZmF1bHQtbG9nZ2luZ1xuICAgIGRlcGVuZHNfb246XG4gICAgICBkYjpcbiAgICAgICAgY29uZGl0aW9uOiBzZXJ2aWNlX2hlYWx0aHlcbiAgICAgIHJlZGlzNzpcbiAgICAgICAgY29uZGl0aW9uOiBzZXJ2aWNlX2hlYWx0aHlcbiAgICAgIGluaXQtYXNzZXRzOlxuICAgICAgICBjb25kaXRpb246IHNlcnZpY2VfY29tcGxldGVkX3N1Y2Nlc3NmdWxseVxuICAgIGVudmlyb25tZW50OlxuICAgICAgV1JJVEVfREFUQUJBU0VfVVJMOiBwb3N0Z3JlczovL3Bvc3Rob2c6cG9zdGhvZ0BkYjo1NDMyL3Bvc3Rob2dcbiAgICAgIFJFQURfREFUQUJBU0VfVVJMOiBwb3N0Z3JlczovL3Bvc3Rob2c6cG9zdGhvZ0BkYjo1NDMyL3Bvc3Rob2dcbiAgICAgIFBFUlNPTlNfV1JJVEVfREFUQUJBU0VfVVJMOiBwb3N0Z3JlczovL3Bvc3Rob2c6cG9zdGhvZ0BkYjo1NDMyL3Bvc3Rob2dcbiAgICAgIFBFUlNPTlNfUkVBRF9EQVRBQkFTRV9VUkw6IHBvc3RncmVzOi8vcG9zdGhvZzpwb3N0aG9nQGRiOjU0MzIvcG9zdGhvZ1xuICAgICAgTUFYTUlORF9EQl9QQVRIOiAvc2hhcmUvR2VvTGl0ZTItQ2l0eS5tbWRiXG4gICAgICBSRURJU19VUkw6IHJlZGlzOi8vcmVkaXM3OjYzNzkvXG4gICAgICBBRERSRVNTOiAwLjAuMC4wOjMwMDFcbiAgICAgIFJVU1RfTE9HOiBpbmZvXG4gICAgICBDT09LSUVMRVNTX1JFRElTX0hPU1Q6IHJlZGlzN1xuICAgICAgQ09PS0lFTEVTU19SRURJU19QT1JUOiA2Mzc5XG4gICAgdm9sdW1lczpcbiAgICAgIC0gZ2VvaXAtZGF0YTovc2hhcmU6cm9cblxuICAjIFJ1c3QgaHlwZXJjYWNoZSBzZXJ2ZXIgKC9hcnJheSByZW1vdGUgY29uZmlnICsgL3N1cnZleXMpXG4gIGh5cGVyY2FjaGUtc2VydmVyOlxuICAgIGltYWdlOiBnaGNyLmlvL3Bvc3Rob2cvcG9zdGhvZy9oeXBlcmNhY2hlLXNlcnZlcjptYXN0ZXJcbiAgICByZXN0YXJ0OiB1bmxlc3Mtc3RvcHBlZFxuICAgIGxvZ2dpbmc6ICpkZWZhdWx0LWxvZ2dpbmdcbiAgICBkZXBlbmRzX29uOlxuICAgICAgcmVkaXM3OlxuICAgICAgICBjb25kaXRpb246IHNlcnZpY2VfaGVhbHRoeVxuICAgIGVudmlyb25tZW50OlxuICAgICAgUkVESVNfVVJMOiByZWRpczovL3JlZGlzNzo2Mzc5L1xuICAgICAgQUREUkVTUzogMC4wLjAuMDozMDAyXG4gICAgICBSVVNUX0xPRzogaW5mb1xuXG4gICMgTGl2ZSBldmVudHMgc3RyZWFtICgvbGl2ZXN0cmVhbSlcbiAgbGl2ZXN0cmVhbTpcbiAgICBpbWFnZTogZ2hjci5pby9wb3N0aG9nL3Bvc3Rob2cvbGl2ZXN0cmVhbTptYXN0ZXJcbiAgICByZXN0YXJ0OiB1bmxlc3Mtc3RvcHBlZFxuICAgIGxvZ2dpbmc6ICpkZWZhdWx0LWxvZ2dpbmdcbiAgICBkZXBlbmRzX29uOlxuICAgICAga2Fma2E6XG4gICAgICAgIGNvbmRpdGlvbjogc2VydmljZV9oZWFsdGh5XG4gICAgZW52aXJvbm1lbnQ6XG4gICAgICBMSVZFU1RSRUFNX0pXVF9TRUNSRVQ6ICR7UE9TVEhPR19TRUNSRVRfS0VZfVxuICAgIHZvbHVtZXM6XG4gICAgICAtIC4uL2ZpbGVzL2xpdmVzdHJlYW0vY29uZmlncy55bWw6L2NvbmZpZ3MvY29uZmlncy55bWw6cm9cblxuICBvYmplY3RzdG9yYWdlOlxuICAgIGltYWdlOiBtaW5pby9taW5pbzpSRUxFQVNFLjIwMjUtMDQtMjJUMjItMTItMjZaXG4gICAgcmVzdGFydDogdW5sZXNzLXN0b3BwZWRcbiAgICBsb2dnaW5nOiAqZGVmYXVsdC1sb2dnaW5nXG4gICAgZW52aXJvbm1lbnQ6XG4gICAgICBNSU5JT19ST09UX1VTRVI6IG9iamVjdF9zdG9yYWdlX3Jvb3RfdXNlclxuICAgICAgTUlOSU9fUk9PVF9QQVNTV09SRDogb2JqZWN0X3N0b3JhZ2Vfcm9vdF9wYXNzd29yZFxuICAgIGVudHJ5cG9pbnQ6IHNoXG4gICAgY29tbWFuZDogLWMgJ21rZGlyIC1wIC9kYXRhL3Bvc3Rob2cgJiYgbWluaW8gc2VydmVyIC0tYWRkcmVzcyBcIjoxOTAwMFwiIC0tY29uc29sZS1hZGRyZXNzIFwiOjE5MDAxXCIgL2RhdGEnXG4gICAgdm9sdW1lczpcbiAgICAgIC0gb2JqZWN0c3RvcmFnZS1kYXRhOi9kYXRhXG5cbiAgIyBDYWRkeSByb3V0ZXMgdGhlIHNpbmdsZSBwdWJsaWMgZG9tYWluIHRvIHRoZSByaWdodCBpbnRlcm5hbCBzZXJ2aWNlLFxuICAjIGV4YWN0bHkgbGlrZSB0aGUgdXBzdHJlYW0gaG9iYnkgZGVwbG95bWVudCAoVExTIGlzIHRlcm1pbmF0ZWQgYnkgVHJhZWZpaylcbiAgcHJveHk6XG4gICAgaW1hZ2U6IGNhZGR5OjIuMTAtYWxwaW5lXG4gICAgcmVzdGFydDogdW5sZXNzLXN0b3BwZWRcbiAgICBsb2dnaW5nOiAqZGVmYXVsdC1sb2dnaW5nXG4gICAgZGVwZW5kc19vbjpcbiAgICAgIHdlYjpcbiAgICAgICAgY29uZGl0aW9uOiBzZXJ2aWNlX3N0YXJ0ZWRcbiAgICBlbnRyeXBvaW50OiBzaFxuICAgIGNvbW1hbmQ6IC1jICdwcmludGYgXCIlc1wiIFwiJCRDQUREWUZJTEVcIiA+IC9ldGMvY2FkZHkvQ2FkZHlmaWxlICYmIGV4ZWMgY2FkZHkgcnVuIC1jIC9ldGMvY2FkZHkvQ2FkZHlmaWxlJ1xuICAgIGVudmlyb25tZW50OlxuICAgICAgQ0FERFlGSUxFOiB8XG4gICAgICAgIHtcbiAgICAgICAgICAgIGF1dG9faHR0cHMgb2ZmXG4gICAgICAgIH1cbiAgICAgICAgOjgwIHtcbiAgICAgICAgICAgIEBjYXB0dXJlIHBhdGggL2UgL2UvIC9lLyogL2kvdjAgL2kvdjAvIC9pL3YwLyogL2kvdjEvYW5hbHl0aWNzL2V2ZW50cyAvaS92MS9hbmFseXRpY3MvZXZlbnRzLyAvYmF0Y2ggL2JhdGNoLyAvYmF0Y2gvKiAvY2FwdHVyZSAvY2FwdHVyZS8gL2NhcHR1cmUvKlxuICAgICAgICAgICAgQHJlcGxheS1jYXB0dXJlIHBhdGggL3MgL3MvIC9zLypcbiAgICAgICAgICAgIEBmbGFncyBwYXRoIC9mbGFncyAvZmxhZ3MvIC9mbGFncy8qIC9hcGkvZmVhdHVyZV9mbGFnL2xvY2FsX2V2YWx1YXRpb24gL2FwaS9mZWF0dXJlX2ZsYWcvbG9jYWxfZXZhbHVhdGlvbi8gL2FwaS9mZWF0dXJlX2ZsYWcvbG9jYWxfZXZhbHVhdGlvbi8qXG4gICAgICAgICAgICBAc3VydmV5cyBwYXRoIC9zdXJ2ZXlzIC9zdXJ2ZXlzLyAvYXBpL3N1cnZleXMgL2FwaS9zdXJ2ZXlzL1xuICAgICAgICAgICAgQHJlbW90ZS1jb25maWcgcGF0aCAvYXJyYXkvKlxuICAgICAgICAgICAgQHdlYmhvb2tzIHBhdGggL3B1YmxpYy93ZWJob29rcyAvcHVibGljL3dlYmhvb2tzLyAvcHVibGljL3dlYmhvb2tzLyogL3B1YmxpYy9tLyAvcHVibGljL20vKlxuICAgICAgICAgICAgQGxpdmVzdHJlYW0gcGF0aCAvbGl2ZXN0cmVhbSAvbGl2ZXN0cmVhbS8gL2xpdmVzdHJlYW0vKlxuICAgICAgICAgICAgQG9iamVjdHN0b3JhZ2UgcGF0aCAvcG9zdGhvZyAvcG9zdGhvZy8gL3Bvc3Rob2cvKlxuXG4gICAgICAgICAgICBoYW5kbGUgQGNhcHR1cmUge1xuICAgICAgICAgICAgICAgIHJldmVyc2VfcHJveHkgY2FwdHVyZTozMDAwXG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBoYW5kbGUgQHJlcGxheS1jYXB0dXJlIHtcbiAgICAgICAgICAgICAgICByZXZlcnNlX3Byb3h5IHJlcGxheS1jYXB0dXJlOjMwMDBcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGhhbmRsZSBAZmxhZ3Mge1xuICAgICAgICAgICAgICAgIHJldmVyc2VfcHJveHkgZmVhdHVyZS1mbGFnczozMDAxXG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBoYW5kbGUgQHN1cnZleXMge1xuICAgICAgICAgICAgICAgIHJldmVyc2VfcHJveHkgaHlwZXJjYWNoZS1zZXJ2ZXI6MzAwMlxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaGFuZGxlIEByZW1vdGUtY29uZmlnIHtcbiAgICAgICAgICAgICAgICByZXZlcnNlX3Byb3h5IGh5cGVyY2FjaGUtc2VydmVyOjMwMDJcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGhhbmRsZSBAd2ViaG9va3Mge1xuICAgICAgICAgICAgICAgIHJldmVyc2VfcHJveHkgcGx1Z2luczo2NzM4XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBoYW5kbGUgQGxpdmVzdHJlYW0ge1xuICAgICAgICAgICAgICAgIHVyaSBzdHJpcF9wcmVmaXggL2xpdmVzdHJlYW1cbiAgICAgICAgICAgICAgICByZXZlcnNlX3Byb3h5IGxpdmVzdHJlYW06ODA4MCB7XG4gICAgICAgICAgICAgICAgICAgIGZsdXNoX2ludGVydmFsIC0xXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaGFuZGxlIEBvYmplY3RzdG9yYWdlIHtcbiAgICAgICAgICAgICAgICByZXZlcnNlX3Byb3h5IG9iamVjdHN0b3JhZ2U6MTkwMDBcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGhhbmRsZSB7XG4gICAgICAgICAgICAgICAgcmV2ZXJzZV9wcm94eSB3ZWI6ODAwMFxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbnZvbHVtZXM6XG4gIHBvc3RncmVzLWRhdGE6XG4gIHJlZGlzLWRhdGE6XG4gIHpvb2tlZXBlci1kYXRhOlxuICB6b29rZWVwZXItZGF0YWxvZzpcbiAgcmVkcGFuZGEtZGF0YTpcbiAgY2xpY2tob3VzZS1kYXRhOlxuICBwb3N0aG9nLWFzc2V0czpcbiAgZ2VvaXAtZGF0YTpcbiAgb2JqZWN0c3RvcmFnZS1kYXRhOlxuIiwKICAiY29uZmlnIjogIlt2YXJpYWJsZXNdXG5tYWluX2RvbWFpbiA9IFwiJHtkb21haW59XCJcbnNlY3JldF9rZXkgPSBcIiR7cGFzc3dvcmQ6NjR9XCJcbnNhbHRfa2V5cyA9IFwiJHtoYXNoOjMyfVwiXG5cbltjb25maWddXG5bW2NvbmZpZy5kb21haW5zXV1cbnNlcnZpY2VOYW1lID0gXCJwcm94eVwiXG5wb3J0ID0gODBcbmhvc3QgPSBcIiR7bWFpbl9kb21haW59XCJcbnBhdGggPSBcIi9cIlxuXG5bY29uZmlnLmVudl1cbiMgUG9zdEhvZyBzdG9wcGVkIHB1Ymxpc2hpbmcgdGFnZ2VkIHJlbGVhc2VzOyBpbWFnZXMgYXJlIHBpbm5lZCB0byBhIHRlc3RlZFxuIyBtYXN0ZXIgY29tbWl0LiBQT1NUSE9HX1ZFUlNJT04gaXMgYm90aCB0aGUgcG9zdGhvZy9wb3N0aG9nIGltYWdlIHRhZyBhbmQgdGhlXG4jIGdpdCByZWYgdXNlZCB0byBmZXRjaCB0aGUgbWF0Y2hpbmcgQ2xpY2tIb3VzZSBjb25maWd1cmF0aW9uLlxuUE9TVEhPR19WRVJTSU9OID0gXCIxZTdiMzZlYmUwZGEzOGE3MzhmZWQyNTBkMTc1ODA5YTg5OWVmNDIyXCJcblBPU1RIT0dfTk9ERV9WRVJTSU9OID0gXCJzaGEtODJlYTY2OFwiXG4jIFNldCB0byBodHRwczovLzx5b3VyLWRvbWFpbj4gYWZ0ZXIgZW5hYmxpbmcgSFRUUFMgb24gdGhlIGRvbWFpblxuUE9TVEhPR19TSVRFX1VSTCA9IFwiaHR0cDovLyR7bWFpbl9kb21haW59XCJcbiMgU2V0IHRvIFwidHJ1ZVwiIG9uY2UgdGhlIGRvbWFpbiB1c2VzIEhUVFBTIChtYXJrcyBzZXNzaW9uL0NTUkYgY29va2llcyBTZWN1cmUpXG5QT1NUSE9HX1NFQ1VSRV9DT09LSUVTID0gXCJmYWxzZVwiXG5QT1NUSE9HX1NFQ1JFVF9LRVkgPSBcIiR7c2VjcmV0X2tleX1cIlxuUE9TVEhPR19FTkNSWVBUSU9OX1NBTFRfS0VZUyA9IFwiJHtzYWx0X2tleXN9XCJcblxuW1tjb25maWcubW91bnRzXV1cbmZpbGVQYXRoID0gXCIvZGItaW5pdC9jcmVhdGUtZXh0cmEtZGJzLnNoXCJcbmNvbnRlbnQgPSBcIlwiXCJcbiMhL2Jpbi9iYXNoXG4jIENyZWF0ZXMgdGhlIGF1eGlsaWFyeSBkYXRhYmFzZXMgUG9zdEhvZyBzZXJ2aWNlcyBjYW4gcG9pbnQgYXRcbiMgKG1pcnJvcnMgZG9ja2VyL3Bvc3RncmVzLWluaXQtc2NyaXB0cyBpbiB0aGUgUG9zdEhvZyByZXBvKVxuc2V0IC1lXG5zZXQgLXVcblxuZm9yIGRiIGluIGN5Y2xvdHJvbiBwb3N0aG9nX3BlcnNvbnMgYmVoYXZpb3JhbF9jb2hvcnRzOyBkb1xuICAgIERCX0VYSVNUUz0kKHBzcWwgLVUgXCIkUE9TVEdSRVNfVVNFUlwiIC10QWMgXCJTRUxFQ1QgMSBGUk9NIHBnX2RhdGFiYXNlIFdIRVJFIGRhdG5hbWU9JyRkYidcIilcbiAgICBpZiBbIC16IFwiJERCX0VYSVNUU1wiIF07IHRoZW5cbiAgICAgICAgZWNobyBcIkNyZWF0aW5nIGRhdGFiYXNlICckZGInLi4uXCJcbiAgICAgICAgcHNxbCAtVSBcIiRQT1NUR1JFU19VU0VSXCIgLWMgXCJDUkVBVEUgREFUQUJBU0UgJGRiO1wiXG4gICAgICAgIHBzcWwgLVUgXCIkUE9TVEdSRVNfVVNFUlwiIC1jIFwiR1JBTlQgQUxMIFBSSVZJTEVHRVMgT04gREFUQUJBU0UgJGRiIFRPICRQT1NUR1JFU19VU0VSO1wiXG4gICAgZmlcbmRvbmVcblwiXCJcIlxuXG5bW2NvbmZpZy5tb3VudHNdXVxuZmlsZVBhdGggPSBcIi9saXZlc3RyZWFtL2NvbmZpZ3MueW1sXCJcbmNvbnRlbnQgPSBcIlwiXCJcbmRlYnVnOiBmYWxzZVxua2Fma2E6XG4gICAgYnJva2VyczogJ2thZmthOjkwOTInXG4gICAgdG9waWM6ICdldmVudHNfcGx1Z2luX2luZ2VzdGlvbidcbiAgICBncm91cF9pZDogJ2xpdmVzdHJlYW0nXG4gICAgc2VjdXJpdHlfcHJvdG9jb2w6ICdQTEFJTlRFWFQnXG4gICAgc2Vzc2lvbl9yZWNvcmRpbmdfZW5hYmxlZDogdHJ1ZVxuICAgIHNlc3Npb25fcmVjb3JkaW5nX3NlY3VyaXR5X3Byb3RvY29sOiAnUExBSU5URVhUJ1xuY29uc3VtZXJzOlxuICAgIGV2ZW50OlxuICAgICAgICBlbmFibGVkOiB0cnVlXG4gICAgICAgIGJyb2tlcnM6ICdrYWZrYTo5MDkyJ1xuICAgICAgICB0b3BpYzogJ2V2ZW50c19wbHVnaW5faW5nZXN0aW9uJ1xuICAgICAgICBzZWN1cml0eV9wcm90b2NvbDogJ1BMQUlOVEVYVCdcbiAgICAgICAgZ3JvdXBfaWQ6ICdsaXZlc3RyZWFtJ1xuICAgIHNlc3Npb25fcmVjb3JkaW5nOlxuICAgICAgICBlbmFibGVkOiB0cnVlXG4gICAgICAgIGJyb2tlcnM6ICdrYWZrYTo5MDkyJ1xuICAgICAgICB0b3BpYzogJ3Nlc3Npb25fcmVjb3JkaW5nX3NuYXBzaG90X2l0ZW1fZXZlbnRzJ1xuICAgICAgICBzZWN1cml0eV9wcm90b2NvbDogJ1BMQUlOVEVYVCdcbiAgICAgICAgZ3JvdXBfaWQ6ICdsaXZlc3RyZWFtLXNlc3Npb24tcmVjb3JkaW5ncydcbiAgICBub3RpZmljYXRpb246XG4gICAgICAgIGVuYWJsZWQ6IGZhbHNlXG5tbWRiOlxuICAgIHBhdGg6ICdHZW9MaXRlMi1DaXR5Lm1tZGInXG5cIlwiXCJcbiIKfQ==

Instructions

PostHog

Self-hosted PostHog based on the official "hobby" deployment, trimmed to run on a single server.

Requirements

  • RAM: at least 8 GB free is strongly recommended (the stack runs Django, a Celery worker, two Node plugin-server processes, ClickHouse, Redpanda/Kafka, Postgres, Redis, MinIO and several small Rust services).
  • ~15 GB of free disk for the images and data volumes.

First boot

The first deployment takes 5-10 minutes: an init container fetches the ClickHouse configuration and the GeoIP database, and the web service runs all Postgres and ClickHouse migrations before it starts serving. Watch the web service logs; once you see the Unit server start, open the domain and create the first account.

After enabling HTTPS

If you serve PostHog over HTTPS (recommended for production), update these environment variables and redeploy:

  • POSTHOG_SITE_URL to https://<your-domain> (otherwise logins/CSRF and SDK snippets point at the wrong scheme)
  • POSTHOG_SECURE_COOKIES to true (marks session/CSRF cookies as Secure; the default false is what allows logging in over the initial plain-HTTP domain)

What is not included

Compared to the full upstream hobby stack, this template omits Temporal + Elasticsearch (data warehouse / batch exports), browserless (dashboard image exports and heatmap screenshots), and the error-tracking/logs/traces ingestion pipelines. Product analytics, feature flags, experiments, surveys, session replay, live events and the CDP destinations pipeline all work.

Versioning

PostHog no longer publishes tagged releases; images are pinned to a tested master commit via the POSTHOG_VERSION and POSTHOG_NODE_VERSION environment variables. To upgrade, set POSTHOG_VERSION to a newer commit sha of posthog/posthog (Docker Hub tag) and redeploy.

Tags

analytics, product-analytics, feature-flags, session-replay, ab-testing


Version: master-2026-07-14

On this page