PostHog 自托管实战:从一键脚本到三副本集群的完整路径
【免费下载链接】posthog:hedgehog: PostHog is the leading platform for building self-driving products. Our developer tools – AI observability, analytics, session replay, flags, experiments, error tracking, logs, and more – capture all the context agents need to diagnose problems, uncover opportunities, and ship fixes. Steer it all from Slack, web, desktop, or the MCP.项目地址: https://gitcode.com/GitHub_Trending/po/posthog
这篇文章写给正在评估 PostHog 部署的开发者与运维:从理清单机要跑哪些组件、用 Docker Compose 跑通第一个实例,到升级为生产集群,最后收拢在监控、备份与排坑清单上。
先看清组件全家福:PostHog 背后到底在跑什么
第一次在一台装完 PostHog 的机器上执行docker compose ps,你大概率会被二十多个容器砸一脸——到底哪个才是"PostHog 本 Hog"?先把心智模型搭起来:网页和 API 只是冰山一角,真正干活的是一条摄取链路(Rust 采集边缘 → Kafka → Node.js 消费者 → ClickHouse),外加元数据 Postgres、Redis、S3 兼容对象存储这一圈支撑件。
| 组件 | 技术栈 | 职责 | 关键端口 |
|---|---|---|---|
| Web / Worker | Python(Django + Celery) | API、前端、定时任务 | 8000 |
| 事件摄取边缘 | Rust(capture 系列) | 接 /e /s /i 上报,转发进 Kafka | 3000、4318 |
| Flags 边缘 | Rust | /flags 求值与热缓存 | 3001 |
| 摄取 Worker | Node.js | 消费 Kafka,落 ClickHouse / PG | 6738 |
| 元数据 DB | PostgreSQL 15 | 项目、用户、flags 定义 | 5432 |
| 分析 DB | ClickHouse 26.6 | 事件宽表、会话录制数据 | 8123 / 9000 |
| 消息总线 + 缓存 | Redpanda(Kafka 协议)/ Redis | 摄取缓冲 + 热缓存 | 9092 / 6379 |
会话录制这类大对象不塞进数据库,而是丢给 S3 兼容的对象存储(Compose 栈里默认 MinIO / SeaweedFS,19000 起服务)。仓库里的 docker-compose.hobby.yml 就是这份全家福的完整清单,装完之后对一遍服务名会很踏实。
30 分钟跑通第一个实例 🐳:Docker Compose 自托管之路径
当你把安装脚本跑完、打开域名却看到浏览器转了 5 分钟圈——别慌,这是正常的:脚本会拉镜像、预建 Kafka topic、跑全量迁移、等 Caddy 签好 TLS 证书,官方自己都说要等 5~10 分钟。它最后拿curl轮询/_health直到返回 200 才宣告结束,所以"转圈"本身说明链路在正常推进。
整个安装逻辑都在 bin/deploy-hobby 里:确认内存 ≥ 8GB、拉取代码、生成三把密钥、写.env、装 Docker、起栈。非交互执行时传"版本 tag + 域名"两个参数即可:
# 交互执行会逐项询问;脚本化执行直接传参 # 参数顺序:应用 tag(如 latest) 域名(必须 A 记录) sudo bash deploy-hobby latest analytics.example.com真正需要你理解、而不是手抄的,是.env里这几个必填项:
POSTHOG_SECRET=xxxx # Django 会话与签名密钥 ENCRYPTION_SALT_KEYS=xxxx # 字段加密盐,事后换掉=旧数据无法解密 BROWSERLESS_SECRET=xxxx # 截图渲染容器的独立凭证 DOMAIN=analytics.example.com # Caddy 自动签发 TLS 用的域名 POSTHOG_APP_TAG=latest # 镜像版本 tag可选项:
ANTHROPIC_API_KEY/OPENAI_API_KEY只在你想用内置 AI 功能时才填,留空不影响核心链路。
持久化与自检:数据不丢、活着可查
持久化只需要盯三个卷,其余随栈自动挂上:
volumes: - postgres-data:/var/lib/postgresql/data # 5432 元数据 - clickhouse-data:/var/lib/clickhouse # 9000 分析宽表 - objectstorage:/data # S3 兼容存储自检方面不用自己写:PG 用pg_isready、ClickHouse 探8123/ping、Flags 边缘探/_readiness,日志默认走json-file驱动做 50MB×3 轮转,防止日志反向吃光磁盘。
第一次 200 之后,登录域名你会看到这样的控制台——能进到这里,说明网关、Django、迁移、对象存储这一串都通了:
上生产 🚀:把单机升级成多节点集群
先说个背景:官方对自托管 K8s 的 Helm 支持已经停更(Compose 文件头部有明确注释),所以上生产基本等于"自己把单机架构搬上集群"。别慌,按四步走就行。
把网关和后端服务隔离到不同网段
单机里 Caddy 一个容器既做 TLS 又做路径分发(/e 给摄取边缘、/flags 给 Flags 边缘、其余转 Django)。生产环境换成专用 Ingress 或 LB 承担 TLS 与路由,内部服务一律不发布端口到公网,跨组件访问走集群内部 DNS。
无状态服务直接加副本
Django 的会话在 Redis 里、Celery worker 是纯队列消费者,所以 web 和 worker 都是无状态的,横向扩副本没有副作用:
spec: replicas: 3 template: spec: containers: - name: web image: posthog/posthog:<tag> ports: - containerPort: 8000 readinessProbe: httpGet: { path: /_health, port: 8000 } resources: requests: { memory: 2Gi, cpu: 1 } limits: { memory: 4Gi, cpu: 2 }Namespace、Service、ConfigMap、Secret 这些对象按常规流程建即可,不再逐个贴。
ClickHouse 集群怎么起三副本
为什么 ClickHouse 必须用 StatefulSet 而不是 Deployment:它的 part merge 依赖本地盘的顺序写,Pod 漂移到新节点会触发整段数据重灌和 re-merge,查询延迟会瞬间炸掉。绑定稳定 PVC 的 StatefulSet 才能保住这个前提:
spec: replicas: 3 serviceName: clickhouse template: spec: containers: - name: clickhouse image: clickhouse/clickhouse-server:26.6 ports: - containerPort: 8123 - containerPort: 9000 volumeClaimTemplates: - metadata: { name: ch-data } spec: accessModes: [ ReadWriteOnce ] resources: { requests: { storage: 500Gi } }Postgres 侧类似:单副本 StatefulSet 或托管 RDS 都行,查询压力大时挂一个只读副本分担报表查询。
把密钥从镜像里挪出去
DATABASE_URL、REDIS_URL、ClickHouse 账号密码全部进 Secret 对象;SITE_URL、ALLOWED_HOSTS这类非敏感值放 ConfigMap。这里有个不太直观的坑:POSTHOG_SECRET和ENCRYPTION_SALT_KEYS一旦生成就不该再换——安装脚本重跑时特意保留旧.env就是这个原因,K8s 化时同样要保证这两个值跨升级不变。
保活手册 🩺:四类生产场景怎么处理
- 用户报"页面打不开"时:先
curl网关背后的/_health,再用docker compose logs web(K8s 里对应 Pod 日志)看是不是卡在迁移——首启和每次升级后的迁移任务是启动慢的头号原因。 - 事件延迟上涨时:链路是采集边缘 → Kafka → 消费者 → ClickHouse,查 Kafka 消费 lag 和 ClickHouse 的 part 合并进度,瓶颈九成在最后一跳的落盘。
- ClickHouse 单节点磁盘快写满时:提前设 80% 告警,动作是配 TTL 让老分区自动过期 + 扩卷,而不是手动删数据破坏表结构。
- 监控失明时:web 容器内置 OTEL 环境变量(
OTEL_EXPORTER_OTLP_ENDPOINT等),hobby 栈默认是关掉的;生产把它指向自家 collector,Rust 服务再暴露 Prometheus 端口挂上 ServiceMonitor,指标就补齐了。 - 要恢复备份时:日常节奏是每日
pg_dump元数据库 + 对象存储桶同步 + ClickHouse 数据目录快照;恢复顺序反着来——先 PG、再对象存储、最后 CH,别搞反依赖。 - 流量翻倍时:先横向扩无状态侧(web / worker / 摄取 worker),它们扩到顶了再动 ClickHouse,动的是副本数而不是单机规格。
常见踩坑与自检清单
- DOMAIN 填了 IP:Caddy 自动签发 TLS 会直接失败,域名必须是 A 记录指向的 FQDN。
- 事后重跑了密钥生成:
ENCRYPTION_SALT_KEYS一变,历史加密字段全部解不开;复用旧.env是脚本的刻意行为,不是 bug。 - 内存卡在 4GB:安装脚本开头就喊 8GB 红线,低于它最先被 OOM 杀掉的通常是 ClickHouse。
- 健康检查 200 但页面报错:检查
share/GeoLite2-City.mmdb是否下载成功,缺了它地域解析会失败。 - 跳过迁移直接换镜像:升级必须走官方升级脚本,它保证先跑
bin/migrate再起进程,手搓docker compose up跳过这步会在老 schema 上崩。 - 把 19000/19001 对象存储端口发布到公网:S3 端点和控制台都应只对内网开放。
- 日志驱动改成了无轮转模式:默认
json-file50MB×3 是防日志吃盘的最后防线,改之前先想清楚。
跑完这份清单,你的第一个实例应该已经稳到可以交给团队试用了。参数细节对照官方 self-hosting 文档核对,版本升级和疑难杂症去社区论坛提问通常更快。
【免费下载链接】posthog:hedgehog: PostHog is the leading platform for building self-driving products. Our developer tools – AI observability, analytics, session replay, flags, experiments, error tracking, logs, and more – capture all the context agents need to diagnose problems, uncover opportunities, and ship fixes. Steer it all from Slack, web, desktop, or the MCP.项目地址: https://gitcode.com/GitHub_Trending/po/posthog
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考