PostHog:自建产品分析平台,开源的 Mixpanel/Amplitude 替代品

PostHog 是功能最全面的开源产品分析套件,集事件追踪、漏斗分析、用户会话录制、功能开关(Feature Flags)、A/B 测试、热力图于一体,对标 Mixpanel、Amplitude、FullStory 等商业产品。对于中小型 SaaS 产品和独立开发者而言,这些工具的商业版订阅费用可高达每月数千美元。PostHog 的自托管版本完全免费,数据完全存储在自己的服务器上,无用户数量限制,还能规避浏览器广告拦截器导致的数据丢失问题。本文将使用 PostHog 官方提供的 Hobby 部署方案,配合 Caddy 完成完整的生产环境搭建。


服务器配置

PostHog 的技术栈较为复杂,完整部署包含 ClickHouse(列式数据库,负责事件存储与分析查询)、PostgreSQL(元数据存储)、Redis(缓存与队列)、Kafka(事件流处理)以及 Zookeeper(Kafka 依赖),这些组件合在一起资源消耗显著。官方建议 Hobby 部署至少使用 4 核 8GB 机型,尤其是 ClickHouse 在执行复杂聚合查询时 CPU 和内存消耗较大。

推荐使用雨云服务器 rainyun+com部署 PostHog,注册填优惠码 2026off 领 5 折优惠券,4 核 8GB 机型性价比优秀,非常适合运行此类复杂的多服务栈。

推荐配置:

项目 规格
CPU 4 核
内存 8 GB
磁盘 80 GB SSD(ClickHouse 数据增长较快)
操作系统 Ubuntu 22.04 LTS
带宽 10 Mbps 及以上

提示: 如果你的产品日事件量超过 100 万,建议将磁盘扩展到 200GB 以上,或配置 S3 兼容的对象存储用于 ClickHouse 的冷数据存储。

安装 Docker 和相关工具:

curl -fsSL https://get.docker.com | sh
apt install -y git curl jq

# 调整内核参数(ClickHouse 需要)
echo "vm.max_map_count=262144" >> /etc/sysctl.conf
sysctl -p

docker --version
docker compose version

Docker Compose 部署

PostHog 官方提供了专门为 Hobby(单机自托管)场景设计的一键部署脚本,内含完整的 docker-compose 配置。

克隆官方部署仓库

cd /opt
git clone https://github.com/PostHog/posthog-hobby.git posthog
cd /opt/posthog

查看并编辑配置

查看仓库结构:

ls -la
# 应包含:docker-compose.yml, .env.template, bin/deploy-hobby 等

复制环境变量模板:

cp .env.template .env

编辑 .env 文件,填写关键配置:

# 以下是 .env 中需要修改的核心配置

# 域名配置
DOMAIN=posthog.yourdomain.com

# Django 密钥(必须修改)
SECRET_KEY=$(openssl rand -base64 32)

# PostHog 版本(建议固定版本号而非 latest)
POSTHOG_VERSION=latest

# 禁用自动升级(生产环境建议手动控制版本)
DISABLE_SELF_UPDATES=false

# 邮件配置(可选,用于用户邀请、报警通知)
EMAIL_HOST=smtp.gmail.com
EMAIL_PORT=587
EMAIL_USE_TLS=true
EMAIL_HOST_USER=your-email@gmail.com
EMAIL_HOST_PASSWORD=your_gmail_app_password
DEFAULT_FROM_EMAIL=noreply@yourdomain.com

使用 sed 一键更新域名(替换占位符):

sed -i "s/your_domain_here/posthog.yourdomain.com/g" .env

完整 docker-compose.yml(说明版)

官方的 docker-compose.yml 包含所有组件,以下展示简化版本以说明架构:

version: "3.8"

services:
  # ─── 数据层 ───────────────────────────────────────────
  db:
    image: postgres:15-alpine
    container_name: posthog-postgres
    restart: unless-stopped
    environment:
      POSTGRES_USER: posthog
      POSTGRES_PASSWORD: posthog
      POSTGRES_DB: posthog
    volumes:
      - postgres_data:/var/lib/postgresql/data
    networks:
      - posthog-net

  redis:
    image: redis:7-alpine
    container_name: posthog-redis
    restart: unless-stopped
    command: redis-server --maxmemory 512mb --maxmemory-policy allkeys-lru
    volumes:
      - redis_data:/data
    networks:
      - posthog-net

  zookeeper:
    image: zookeeper:3.7
    container_name: posthog-zookeeper
    restart: unless-stopped
    volumes:
      - zookeeper_data:/data
      - zookeeper_datalog:/datalog
    networks:
      - posthog-net

  kafka:
    image: bitnami/kafka:2.8.1-debian-10-r99
    container_name: posthog-kafka
    restart: unless-stopped
    depends_on:
      - zookeeper
    environment:
      KAFKA_BROKER_ID: "1001"
      KAFKA_CFG_ZOOKEEPER_CONNECT: zookeeper:2181
      KAFKA_CFG_ADVERTISED_LISTENERS: PLAINTEXT://kafka:9092
      ALLOW_PLAINTEXT_LISTENER: "true"
    volumes:
      - kafka_data:/bitnami/kafka
    networks:
      - posthog-net

  clickhouse:
    image: clickhouse/clickhouse-server:23.11.2.11
    container_name: posthog-clickhouse
    restart: unless-stopped
    ulimits:
      nofile:
        soft: 262144
        hard: 262144
    volumes:
      - clickhouse_data:/var/lib/clickhouse
      - ./posthog/idl:/idl
      - ./docker/clickhouse/docker-entrypoint-initdb.d:/docker-entrypoint-initdb.d
      - ./docker/clickhouse/config.xml:/etc/clickhouse-server/config.xml
      - ./docker/clickhouse/users.xml:/etc/clickhouse-server/users.xml
    networks:
      - posthog-net

  # ─── 应用层 ───────────────────────────────────────────
  web:
    image: posthog/posthog:${POSTHOG_VERSION:-latest}
    container_name: posthog-web
    restart: unless-stopped
    command: ./bin/docker-server
    ports:
      - "127.0.0.1:8000:8000"
    env_file:
      - .env
    environment:
      DATABASE_URL: postgres://posthog:posthog@db:5432/posthog
      REDIS_URL: redis://redis:6379/
      CLICKHOUSE_HOST: clickhouse
      KAFKA_HOSTS: kafka:9092
    depends_on:
      - db
      - redis
      - clickhouse
      - kafka
    networks:
      - posthog-net

  worker:
    image: posthog/posthog:${POSTHOG_VERSION:-latest}
    container_name: posthog-worker
    restart: unless-stopped
    command: ./bin/docker-worker-celery --without-gossip --without-mingle --without-heartbeat
    env_file:
      - .env
    environment:
      DATABASE_URL: postgres://posthog:posthog@db:5432/posthog
      REDIS_URL: redis://redis:6379/
      CLICKHOUSE_HOST: clickhouse
      KAFKA_HOSTS: kafka:9092
    depends_on:
      - db
      - redis
      - clickhouse
    networks:
      - posthog-net

  plugins:
    image: posthog/posthog:${POSTHOG_VERSION:-latest}
    container_name: posthog-plugins
    restart: unless-stopped
    command: ./bin/plugin-server --no-restart-loop
    env_file:
      - .env
    environment:
      DATABASE_URL: postgres://posthog:posthog@db:5432/posthog
      REDIS_URL: redis://redis:6379/
      KAFKA_HOSTS: kafka:9092
    depends_on:
      - db
      - redis
      - kafka
    networks:
      - posthog-net

volumes:
  postgres_data:
  redis_data:
  zookeeper_data:
  zookeeper_datalog:
  kafka_data:
  clickhouse_data:

networks:
  posthog-net:
    driver: bridge

使用官方一键部署脚本

官方提供的 deploy-hobby 脚本会自动处理配置和启动顺序:

cd /opt/posthog
chmod +x bin/deploy-hobby
./bin/deploy-hobby

脚本会自动:

  1. 检查系统依赖
  2. 生成必要的密钥
  3. 启动所有容器
  4. 执行数据库迁移
  5. 创建初始超级用户

整个过程大约需要 5~10 分钟(ClickHouse 和 Kafka 冷启动较慢)。

检查所有服务状态:

docker compose ps
# 确认所有 service 均为 running 状态

配置 Caddy 反代

安装 Caddy:

apt install -y debian-keyring debian-archive-keyring apt-transport-https curl
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | tee /etc/apt/sources.list.d/caddy-stable.list
apt update && apt install caddy -y

编辑 /etc/caddy/Caddyfile

posthog.yourdomain.com {
    reverse_proxy localhost:8000

    # PostHog 的事件采集 API 接受大量并发请求
    # 确保不限制连接数
    header {
        Strict-Transport-Security "max-age=31536000; includeSubDomains"
        X-Content-Type-Options nosniff
        Referrer-Policy strict-origin-when-cross-origin
        -Server
    }

    # 允许跨域(SDK 从不同域名发送事件)
    @options method OPTIONS
    handle @options {
        header Access-Control-Allow-Origin "*"
        header Access-Control-Allow-Methods "GET, POST, OPTIONS"
        header Access-Control-Allow-Headers "Content-Type"
        respond "" 204
    }

    log {
        output file /var/log/caddy/posthog-access.log
        format json
    }
}

重载 Caddy:

mkdir -p /var/log/caddy
systemctl reload caddy

初始设置

创建账户并配置组织

访问 https://posthog.yourdomain.com,系统引导你完成初始设置:

  1. 创建管理员账户(邮箱 + 密码)
  2. 填写组织名称
  3. 填写产品/项目名称(每个项目有独立的 API Key)
  4. 系统给出 JavaScript 埋点代码片段

获取项目 API Key

进入 Settings → Project → Project API Key,复制 phc_ 开头的公开 Key,用于 SDK 集成。


使用方法

JavaScript SDK 集成

在你的网站 <head> 中添加以下代码:

<script>
  !function(t,e){var o,n,p,r;e.__SV||(window.posthog=e,e._i=[],e.init=function(i,s,a){function g(t,e){var o=e.split(".");2==o.length&&(t=t[o[0]],e=o[1]),t[e]=function(){t.push([e].concat(Array.prototype.slice.call(arguments,0)))}}(p=t.createElement("script")).type="text/javascript",p.async=!0,p.src=s.api_host+"/static/array.js",(r=t.getElementsByTagName("script")[0]).parentNode.insertBefore(p,r);var u=e;for(void 0!==a?u=e[a]=[]:a="posthog",u.people=u.people||[],u.toString=function(t){var e="posthog";return"posthog"!==a&&(e+="."+a),t||(e+=" (stub)"),e},u.people.toString=function(){return u.toString(1)+".people (stub)"},o="capture identify alias people.set people.set_once set_config register register_once unregister opt_out_capturing has_opted_out_capturing opt_in_capturing reset isFeatureEnabled onFeatureFlags getFeatureFlag getFeatureFlagPayload reloadFeatureFlags group updateEarlyAccessFeatureEnrollment getEarlyAccessFeatures getActiveMatchingSurveys getSurveys".split(" "),n=0;n<o.length;n++)g(u,o[n]);e._i.push([i,s,a])},e.__SV=1)}(document,window.posthog||[]);
  
  posthog.init('phc_YOUR_PROJECT_API_KEY', {
    api_host: 'https://posthog.yourdomain.com',
    // 自动采集页面浏览事件
    capture_pageview: true,
    // 开启会话录制
    session_recording: {
      maskAllInputs: true  // 自动遮蔽输入框内容保护隐私
    }
  });
</script>

事件追踪(Custom Events)

// 追踪自定义事件
posthog.capture('button_clicked', {
  button_name: '立即购买',
  page: 'product_detail',
  price: 99.9,
  product_id: 'SKU-12345'
});

// 用户登录后识别用户
posthog.identify('user_123', {
  email: 'user@example.com',
  name: '张三',
  plan: 'pro',
  signup_date: '2026-01-15'
});

// 重置(用户登出时调用)
posthog.reset();

Python SDK 集成

pip install posthog
import posthog

posthog.project_api_key = 'phc_YOUR_PROJECT_API_KEY'
posthog.host = 'https://posthog.yourdomain.com'

# 追踪服务端事件
posthog.capture(
    distinct_id='user_123',
    event='order_completed',
    properties={
        'order_id': 'ORD-2026-001',
        'amount': 299.0,
        'currency': 'CNY',
        'items': ['商品A', '商品B']
    }
)

# 批量导入历史事件
posthog.capture(
    distinct_id='user_456',
    event='signup',
    timestamp='2026-01-01T08:00:00Z'
)

Node.js SDK 集成

npm install posthog-node
const { PostHog } = require('posthog-node');

const client = new PostHog('phc_YOUR_PROJECT_API_KEY', {
  host: 'https://posthog.yourdomain.com'
});

// 追踪事件
client.capture({
  distinctId: 'user_123',
  event: 'api_called',
  properties: {
    endpoint: '/api/products',
    method: 'GET',
    response_time_ms: 42
  }
});

// 关闭连接(Node.js 应用退出时)
await client.shutdown();

功能开关(Feature Flags)

Feature Flags 允许你在不部署代码的情况下开启/关闭功能,或进行 A/B 测试。

在 PostHog 控制台创建 Feature Flag:

  1. 进入 Feature FlagsNew feature flag
  2. Key:new-checkout-ui
  3. 发布条件:向 20% 用户开启

在前端代码中使用:

// 检查功能开关(异步)
posthog.onFeatureFlags(function() {
  if (posthog.isFeatureEnabled('new-checkout-ui')) {
    // 显示新版结账界面
    showNewCheckoutUI();
  } else {
    showOldCheckoutUI();
  }
});

// 获取功能开关的 payload 值
const flagPayload = posthog.getFeatureFlagPayload('new-checkout-ui');
console.log(flagPayload); // 可以携带 JSON 配置数据

在服务端(Python)使用:

# 服务端功能开关判断(基于用户 ID,结果一致性更好)
is_enabled = posthog.is_feature_enabled(
    'new-checkout-ui',
    'user_123',
    person_properties={'plan': 'pro'}
)

if is_enabled:
    return render_new_checkout()
else:
    return render_old_checkout()

会话录制

会话录制默认需要在初始化时开启(见上方 JS 代码)。录制数据存储在 ClickHouse 中,在控制台 Session Recordings 页面可以回放用户操作,分析用户行为路径和操作卡点。

漏斗分析示例

在控制台 Funnels 中创建转化漏斗:

  1. 步骤 1:page_viewed(页面:/products
  2. 步骤 2:button_clickedbutton_name = "加入购物车"
  3. 步骤 3:order_completed

PostHog 自动计算每步的转化率,找出流失最严重的环节。

数据备份

# 备份 PostgreSQL(元数据)
docker exec posthog-postgres pg_dump -U posthog posthog | gzip > posthog_meta_$(date +%Y%m%d).sql.gz

# 备份 ClickHouse(事件数据)——使用 clickhouse-backup 工具
docker exec posthog-clickhouse clickhouse-client --query \
  "SELECT * FROM posthog.events WHERE toDate(timestamp) = today() FORMAT Native" > events_today.native

# 监控磁盘使用
docker exec posthog-clickhouse clickhouse-client --query \
  "SELECT formatReadableSize(sum(bytes_on_disk)) as size FROM system.parts WHERE active"

常见问题

ClickHouse 启动慢: 正常现象,ClickHouse 冷启动需要 1~3 分钟,耐心等待所有服务 healthy。

内存不足(OOM): 检查是否已设置 vm.max_map_count=262144,并确保服务器有至少 8GB 内存。可用 docker stats 实时监控各容器内存占用。

事件未出现在面板: PostHog 的事件处理链路较长(HTTP → Kafka → Worker → ClickHouse),从事件发送到面板可见有 10~30 秒延迟,属正常现象。

磁盘空间增长快: ClickHouse 的事件数据压缩率高,但长期运行仍会占用大量空间。建议设置 ClickHouse 的 TTL(数据保留期限):进入 Settings → Project → Data retention 配置事件保留天数。


PostHog 是目前开源产品分析领域最全面的解决方案,将过去需要多个付费工具才能实现的功能集于一身。虽然部署比其他轻量应用复杂,但一旦运行起来,它能为你的产品决策提供深刻的数据洞察。如果你需要一台性能稳定、价格实惠的服务器来运行 PostHog,推荐雨云服务器 rainyun+com的 4 核 8GB 机型,注册填优惠码 2026off 即可领取 5 折优惠券,让 PostHog 的自托管成本降到最低。

Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐