PostHog 自开发部署
· 约 12 分钟读完
目录
写在前面
自部署 PostHog 实际上非常有难度且繁琐,本质上是 PostHog 对于自部署的支持十分有限,官方也并不希望用户自行部署(不便于卖他的 Cloud 服务 😂)。
下面的流程主要是如何在本机(macOS 或 Unix 类机器)上启动一个可以二次开发的部署。
如果你希望将自部署的 PostHog 用于生产(或预生产)环境,推荐使用官方提供的 Ubuntu 一键部署脚本,可以迅速启动一个完整的单机 PostHog,具备自部署的完整功能。
如果希望得到更多 PostHog 中文社区的帮助,可以联系 me@jiake.li。
❗️ 本指南仅适用于 PostHog 本身的开发。如果你想部署 PostHog 用于产品分析需求,请参考官方的自托管文档。
PostHog 内部结构是什么样的?
在开始设置之前,先了解 PostHog 的组成部分。该应用由 4 个同时运行的组件组成:
- Celery worker(处理后台任务)
- Django 服务器
- Node.js 插件服务器(处理事件接收和应用/插件)
- 使用 Node.js 构建的 React 前端
这些组件依赖于以下外部服务:
- ClickHouse:存储大数据(事件、用户、分析查询)
- Kafka:事件接收队列
- MinIO:存储文件(会话录制、文件导出)
- PostgreSQL:存储普通数据(用户、项目、保存的洞察)
- Redis:缓存和服务间通信
- Zookeeper:协调 Kafka 和 ClickHouse 集群
启动 PostHog 开发实例时,推荐以下配置:
- 外部服务通过
docker compose在 Docker 中运行 - PostHog 本身在主机(你的系统)上运行
下面的指南就使用这种配置。
技术上也可以完全在 Docker 中运行 PostHog,但同步更改会变得更慢,而且为了开发,你仍然需要在主机上安装 PostHog 的依赖(如格式化或类型检查工具)。另一种方式是完全在主机上运行所有内容,但从头搭建 Kafka 或 ClickHouse 太复杂,实践中不可行。
本指南假设你运行的是 macOS 或当前的 Ubuntu Linux LTS(24.04)。其他 Linux 发行版请按需调整步骤(例如用 dnf 或 pacman 代替 apt)。
Windows 本身不支持,但可以运行 Linux 虚拟机,推荐最新的 Ubuntu LTS Desktop(不推荐 Ubuntu Server,因为调试前端需要能访问 localhost 的浏览器)。
选项一:使用 Codespaces 开发
这是更快的入门方式,适合快速试一试。想完整搭建请看选项二。
-
创建你的 codespace。

-
把机器类型改为 8 核(最小配置可能跑不动 PostHog)。

-
用列表中的 "Open in" 选项之一打开 codespace。
-
在 codespace 中打开终端,运行
docker compose -f docker-compose.dev.yml up。 -
在另一个终端中运行
pnpm i(后续命令都在这个终端里执行)。 -
运行
pip install -r requirements.txt -r requirements-dev.txt。 -
运行
./bin/migrate,然后运行./bin/start。 -
在浏览器中打开 http://localhost:8010/。
-
想要一些测试数据,运行
DEBUG=1 ./manage.py generate_demo_data。
选项二:本地开发
先决条件
macOS
- 安装 Xcode Command Line Tools:
xcode-select --install。 - 按照官方说明安装 Homebrew。安装后务必按终端提示把 Homebrew 加入
$PATH,否则命令行找不到用 brew 安装的包。 - 用
brew install orbstack安装 OrbStack,它是性能更好的 Docker Desktop 替代品。在 OrbStack 设置里把内存上限设为至少 4 GB(能给 8 GB 更好),CPU 上限设为至少 4 核(即 400%)。 - 继续下面的「克隆仓库」。
Ubuntu
-
按照官方说明安装 Docker。
-
安装
build-essential:sudo apt install -y build-essential -
继续下面的「克隆仓库」。
克隆仓库
克隆 PostHog 仓库。后续命令都假设你在 posthog/ 目录中。
git clone https://github.com/PostHog/posthog && cd posthog/即时设置(Flox)
你可以用 Flox 一步设置好开发环境。Flox 是一个开发环境管理器,负责管理开发 PostHog 所需的整个依赖关系图,这些依赖都声明在仓库的 .flox/manifest.toml 中。
-
安装 Flox(以及预提交检查要用的
ruff和rustup,它们在 Flox 环境之外):brew install flox ruff rustup && rustup-init && rustup default stable -
在仓库根目录激活环境(首次激活时会询问是否用
direnv自动激活):flox activate
这样就得到了一个功能齐全的环境,可执行文件和链接库都在 .flox/ 下,终端里会打印迁移和启动应用的说明。仓库内容的介绍可以看官方的项目结构文档。要提交更改,基于 master 新建分支开始开发即可。
手动设置
如果不想用 Flox,也可以手动设置环境。
1. 启动外部服务
这一步启动 PostHog 所需的全部外部服务。
首先把 127.0.0.1 kafka clickhouse 加到 /etc/hosts,否则 ClickHouse 和 Kafka 无法互相通信:
echo '127.0.0.1 kafka clickhouse' | sudo tee -a /etc/hosts如果你用的是较新版本(4.1 及以上)的 Podman 而不是 Docker,主机的
/etc/hosts默认会作为容器的基础 hosts 文件,这可能导致 ClickHouse 容器里的主机名解析失败。可以在containers.conf中设置base_hosts_file="none"解决。
然后启动 Docker Compose:
docker compose -f docker-compose.dev.yml up几个常见问题:
-
看到
Error while fetching server API version: 500 Server Error for http+docker://localhost/version,多半是 Docker Engine 没有运行。 -
任何地方出现
Exit Code 137,说明容器内存不足,需要在 OrbStack 设置里分配更多内存。 -
在 Linux 上可能需要
sudo,参见 Docker 文档中以非 root 用户管理 Docker 的部分,或者考虑用支持无根容器的 Podman。 -
看到
Ports are not available: exposing port TCP 0.0.0.0:5432 ... address already in use,说明本机已经有 Postgres 在运行。可以用lsof -i :5432看是哪个进程,Linux 上可以这样停掉它:sudo service postgresql stop
接着用 docker ps 和 docker logs(或 OrbStack 面板)确认这些服务都在运行,日志大致如下:
# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
5a38d4e55447 temporalio/ui:2.10.3 "./start-ui-server.sh" 51 seconds ago Up 44 seconds 0.0.0.0:8081->8080/tcp posthog-temporal-ui-1
89b969801426 temporalio/admin-tools:1.20.0 "tail -f /dev/null" 51 seconds ago Up 44 seconds posthog-temporal-admin-tools-1
81fd1b6d7b1b clickhouse/clickhouse-server:23.6.1.1524 "/entrypoint.sh" 51 seconds ago Up 50 seconds 0.0.0.0:8123->8123/tcp, 0.0.0.0:9000->9000/tcp, 0.0.0.0:9009->9009/tcp, 0.0.0.0:9440->9440/tcp posthog-clickhouse-1
f876f8bff35f bitnami/kafka:2.8.1-debian-10-r99 "/opt/bitnami/script…" 51 seconds ago Up 50 seconds 0.0.0.0:9092->9092/tcp posthog-kafka-1
d22559261575 temporalio/auto-setup:1.20.0 "/etc/temporal/entry…" 51 seconds ago Up 45 seconds 6933-6935/tcp, 6939/tcp, 7234-7235/tcp, 7239/tcp, 0.0.0.0:7233->7233/tcp posthog-temporal-1
5313fc278a70 postgres:12-alpine "docker-entrypoint.s…" 51 seconds ago Up 50 seconds (healthy) 0.0.0.0:5432->5432/tcp posthog-db-1
c04358d8309f zookeeper:3.7.0 "/docker-entrypoint.…" 51 seconds ago Up 50 seconds 2181/tcp, 2888/tcp, 3888/tcp, 8080/tcp posthog-zookeeper-1
09add699866e maildev/maildev:2.0.5 "bin/maildev" 51 seconds ago Up 50 seconds (healthy) 0.0.0.0:1025->1025/tcp, 0.0.0.0:1080->1080/tcp posthog-maildev-1
61a44c094753 elasticsearch:7.16.2 "/bin/tini -- /usr/l…" 51 seconds ago Up 50 seconds 9200/tcp, 9300/tcp posthog-elasticsearch-1
a478cadf6911 minio/minio:RELEASE.2022-06-25T15-50-16Z "sh -c 'mkdir -p /da…" 51 seconds ago Up 50 seconds 9000/tcp, 0.0.0.0:19000-19001->19000-19001/tcp posthog-object_storage-1
91f838afe40e redis:6.2.7-alpine "docker-entrypoint.s…" 51 seconds ago Up 50 seconds 0.0.0.0:6379->6379/tcp posthog-redis-1
# docker logs posthog-db-1 -n 1
2021-12-06 13:47:08.325 UTC [1] LOG: database system is ready to accept connections
# docker logs posthog-redis-1 -n 1
1:M 06 Dec 2021 13:47:08.435 * Ready to accept connections
# docker logs posthog-clickhouse-1 -n 1
Saved preprocessed configuration to '/var/lib/clickhouse/preprocessed_configs/users.xml'.
# ClickHouse 的日志写在 /var/log/clickhouse-server/ 下,而不是 stdout/stderr,出问题时可以 cat 这些文件:
# docker exec posthog-clickhouse-1 cat /var/log/clickhouse-server/clickhouse-server.log
# docker exec posthog-clickhouse-1 cat /var/log/clickhouse-server/clickhouse-server.err.log
# docker logs posthog-kafka-1
[2021-12-06 13:47:23,814] INFO [KafkaServer id=1001] started (kafka.server.KafkaServer)
# docker logs posthog-zookeeper-1
# ClickHouse 和 Kafka 都连着 Zookeeper,所以这里会有很多日志,这是正常的。Kafka 目前是唯一的 x86 容器,在 ARM 上可能会随机崩溃,遇到时重启它即可。
2. 安装本地 Postgres 工具
即使 Postgres 跑在 Docker 里,本机也需要装 Postgres(11 及以上)的 CLI 工具和开发库,pip 安装 psycopg2 时要用到。
-
macOS:
brew install postgresql这会同时安装服务器和工具,装完不要启动服务器。
-
Debian 系 Linux:
sudo apt install -y postgresql-client postgresql-contrib libpq-dev这里只装客户端和驱动,不装服务器。如果已经装了服务器,需要停掉它,因为它和 Postgres 容器抢同一个端口:
sudo systemctl disable postgresql.service。
3. 准备 Django 服务器
-
安装 SAML 需要的依赖(详情见 xmlsec 仓库):
- macOS:
brew install libxml2 libxmlsec1 pkg-config。如果xmlsec装不上,试试把 macOS 升级到最新版本。 - Debian 系 Linux:
sudo apt install -y libxml2 libxmlsec1-dev libffi-dev pkg-config
- macOS:
-
安装 Python 3.11。
-
macOS:
brew install python@3.11 -
Debian 系 Linux:
sudo add-apt-repository ppa:deadsnakes/ppa -y sudo apt update sudo apt install python3.11 python3.11-venv python3.11-dev -y
在 venv 外部始终用
python3而不是python,后者在某些系统上可能指向 Python 2。装了多个 Python 3 版本时用python3.11。也可以用 pyenv 管理多个版本。 -
-
安装 uv。它是一个很快的 Python 虚拟环境和依赖管理工具,在任何
pip命令前加上uv就能提速。 -
创建并激活虚拟环境:
uv venv env --python 3.11 # bash/zsh 等 source env/bin/activate # fish source env/bin/activate.fish -
升级 pip:
uv pip install -U pip -
安装依赖。如果你用的是 Apple Silicon Mac,第一次安装时需要指定 OpenSSL 头文件(
grpcio和psycopg2要用):brew install openssl CFLAGS="-I /opt/homebrew/opt/openssl/include $(python3.11-config --includes)" LDFLAGS="-L /opt/homebrew/opt/openssl/lib" GRPC_PYTHON_BUILD_SYSTEM_OPENSSL=1 GRPC_PYTHON_BUILD_SYSTEM_ZLIB=1 uv pip install -r requirements.txt之后(或在其他机器上)直接运行:
uv pip install -r requirements.txt -r requirements-dev.txt
4. 准备数据库
后端准备好了,Postgres 和 ClickHouse 也在运行,但数据库还是空的,需要运行迁移来建表:
cargo install sqlx-cli # 如果还没有安装
DEBUG=1 ./bin/migrate5. 启动 PostHog
同时启动 PostHog 的所有组件(后端、worker、插件服务器和前端):
./bin/start这个命令用 mprocs 在一个终端窗口里运行所有开发进程。
打开 http://localhost:8010 查看应用。
第一次运行时可能会报 "layout.html is not defined",等前端编译完再刷新即可。
想要测试数据,运行 DEBUG=1 ./manage.py generate_demo_data,加 --help 可以查看可用参数。
如果你只是想启动一个 PostHog 实例,下面的内容可以不用看了 😂
测试
要合并 PostHog 的 PR,所有测试都必须通过,最好还要补充新的测试,所以能方便地跑测试很重要。
前端
运行前端单元测试:
pnpm test:unit只跑某个路径下的文件:
pnpm jest --testPathPattern=frontend/src/lib/components/IntervalFilter/intervalFilterLogic.test.ts更新所有视觉回归测试快照前,先确保 Storybook 在运行(另开一个终端执行 pnpm storybook),可能还需要 pnpm exec playwright install。然后运行:
pnpm test:visual只更新某个路径下的 stories 快照:
pnpm test:visual:update frontend/src/lib/Example.stories.tsx后端
运行后端测试:
pytest只跑某个文件:
pytest posthog/test/test_example.py只跑匹配函数名的用例:
pytest posthog/test/test_example.py -k test_something想看调试日志(例如 ClickHouse 查询),加上 --log-cli-level=DEBUG。
额外:使用特性标志
本地开发时设置 DEBUG=1(会启用 SELF_CAPTURE),本地实例的分析数据都来自实例本身,更准确地说是当前选中的项目。你的操作会立即反映在当前项目里,这对测试功能很有用。例如,开发实例启用了哪些特性标志,取决于你当前打开的项目。
所以,开发依赖特性标志 foo-bar 的功能时,在本地实例里新建这个 key 的特性标志并发布即可。
想一次性拥有 PostHog 里现有的所有特性标志,运行 DEBUG=1 python3 manage.py sync_feature_flags,它们会被添加到实例中的每个项目,默认全量开启。以 _EXPERIMENT 结尾的标志会自动设置成带 control 和 test 两个变体的多变量标志。
后端侧的标志只在本地评估,需要设置 POSTHOG_PERSONAL_API_KEY 环境变量,可以在用户设置里生成。
额外:使用 VS Code 调试
PostHog 仓库自带 VS Code 调试配置。在 VS Code 的「运行和调试」里选择想调试的服务运行即可,之后就可以打断点、单步执行。前端和后端测试也有对应的调试配置。
可以用主配置 "PostHog" 调试所有服务。如果你用
./bin/start跑了大部分服务、只想调试后端,记得先在启动脚本里临时注释掉该服务。
额外:在 PyCharm 中调试后端
借助 PyCharm 内置的 Django 支持,后端调试很容易配置,尤其适合跟踪一个请求从客户端一路到服务器的处理过程。
设置 PyCharm
- 打开仓库文件夹。
- 设置 Python 解释器(Settings > Project: posthog > Python Interpreter > Add Interpreter):选择 "Existing",路径设为
path_to_repo/posthog/env/bin/python。 - 设置 Django 支持(Settings > Languages & Frameworks > Django):
- Django project root:
path_to_repo - Settings:
posthog/settings/__init__.py
- Django project root:
启动调试环境
- 不用手动运行
docker compose,直接打开docker-compose.dev.yml,点击services旁边的双播放图标。 - 在运行配置中选择:
- "PostHog",点击调试
- "Celery",点击调试(可选)
- "Frontend",点击运行
- "Plugin server",点击运行
额外:访问 Postgres
开发时可能需要直接连数据库查询或修改数据。用 pgAdmin 之类的工具,连接信息如下:host localhost,port 5432,database posthog,username posthog,password posthog。
额外:访问 Django Admin
如果打不开 http://localhost:8000/admin/,可能是你的本地用户不是 staff。连上数据库,找到你在 posthog_user 表里的记录,把 is_staff 设为 true 即可。