使用 Docker Compose 在 VPS 上自托管 Plausible Analytics

5 分钟阅读·Matthieu·privacygdprdocker-composeanalyticsplausibleclickhouse|

使用 Docker Compose 在 VPS 上部署 Plausible 社区版。完整指南涵盖安装、跟踪脚本集成、自定义事件、备份和更新。

Plausible Analytics 提供无 cookie、不收集个人数据、无需同意横幅的网站分析。自托管社区版意味着访客数据永远不会离开你的服务器。本指南涵盖完整生命周期:使用 Docker Compose 部署 Plausible CE v3.2.0、集成跟踪脚本、设置自定义事件、备份和更新。

前提条件: 一台至少 4 GB 内存的 VPS,运行 Docker 和 Docker Compose VPS上的Docker生产环境:会出什么问题以及如何解决,一个指向服务器的域名,以及一个处理 TLS 的反向代理 Traefik vs Caddy vs Nginx:Docker反向代理对比

Plausible 社区版是什么?与云版本有何不同?

Plausible CE 是 Plausible Analytics 的免费、AGPL 许可、自托管版本。它以三个 Docker 容器运行:Plausible Web 应用(Elixir)、PostgreSQL(用户账户)和 ClickHouse(分析事件存储)。你可以获得与付费云版本相同的隐私优先仪表板。数据保留在你的服务器上。CE 每年发布两次长期支持版本。

两者的区别:

功能 云版本 社区版
核心分析仪表板
隐私优先(无 cookie)
自定义事件和目标
Stats API (v2)
邮件报告 是(需要 SMTP)
漏斗和收入目标
Sites API
Looker Studio 连接器
Google Search Console 集成 是(需要配置)
SSO / 团队管理
高级支持 仅社区
更新频率 每周 每年两次
基础设施管理 托管 自行管理

云版本采用订阅模式。访问 Plausible 定价页面查看当前费率。自托管只需支付 VPS 资源费用。

自托管 Plausible 的系统要求是什么?

ClickHouse 是最消耗资源的组件。空闲时至少需要 2 GB 内存,在对大数据集执行复杂查询时消耗更多。CPU 必须支持 SSE 4.2 指令(所有现代 x86_64 处理器都支持;ARM64 的 NEON 也可以)。请据此规划你的 VPS。

资源 最低要求 推荐
内存 2 GB 4 GB
CPU 1 vCPU (SSE 4.2) 2 vCPU
磁盘 10 GB 20 GB+
Docker 20.10+ 最新稳定版
Docker Compose v2.x 最新稳定版

磁盘增长取决于流量。ClickHouse 中每 100-200 万页面浏览量大约占用 1 GB。低流量情况下(每月不到 10 万页面浏览量),磁盘使用可以忽略不计。

如何使用 Docker Compose 安装 Plausible Analytics?

克隆官方社区版仓库的 v3.2.0 标签,配置环境变量,启动容器。整个过程大约五分钟。

克隆仓库:

git clone -b v3.2.0 --single-branch https://github.com/plausible/community-edition plausible-ce
cd plausible-ce

这会给你 compose.yml、ClickHouse 配置文件和一个 README。

如何配置环境变量?

plausible-ce 目录中创建 .env 文件。两个变量是必需的。其余是可选的,但有些强烈建议配置。

首先生成密钥:

openssl rand -base64 48

输出一个 64 字符的字符串。复制它用于 SECRET_KEY_BASE

为 TOTP 加密生成一个单独的密钥:

openssl rand -base64 32

现在创建 .env 文件:

cat > .env << 'EOF'
BASE_URL=https://plausible.example.com
SECRET_KEY_BASE=<your-64-char-secret>
TOTP_VAULT_KEY=<your-32-char-key>
DISABLE_REGISTRATION=invite_only

# SMTP for email reports and password resets
MAILER_EMAIL=plausible@example.com
SMTP_HOST_ADDR=mail.example.com
SMTP_HOST_PORT=587
SMTP_USER_NAME=plausible@example.com
SMTP_USER_PWD=<your-smtp-password>
SMTP_HOST_SSL_ENABLED=false
EOF

锁定文件权限,因为其中包含密钥:

chmod 600 .env
ls -la .env
-rw------- 1 root root 412 Mar 20 10:00 .env

各变量的作用:

  • BASE_URL:Plausible 可访问的公共 URL。必须与反向代理配置匹配。
  • SECRET_KEY_BASE:加密会话并生成派生密钥。最少 64 字节。绝不要分享。
  • TOTP_VAULT_KEY:使用 AES256-GCM 加密双因素认证密钥。如果省略,将通过 PBKDF2 从 SECRET_KEY_BASE 派生,但显式设置更有利于密钥轮换。
  • DISABLE_REGISTRATION:设为 invite_only(默认)或在创建账户后设为 true。防止陌生人在你的实例上注册。
  • SMTP 变量:邮件报告、密码重置和邀请邮件所需。没有 SMTP,Plausible 仍可工作,但邮件功能将被禁用。

如何为 Plausible 配置带 TLS 的反向代理?

Plausible 默认监听 8000 端口。反向代理将 HTTPS 流量转发到该端口。如果你已经运行了 Caddy 或 Traefik Traefik vs Caddy vs Nginx:Docker反向代理对比,将 Plausible 添加为新的上游。

创建 compose.override.yml 将 Plausible 连接到反向代理网络:

services:
  plausible:
    networks:
      - proxy
      - default

networks:
  proxy:
    external: true

如果使用 Caddy,在 Caddyfile 中添加:

plausible.example.com {
    reverse_proxy plausible:8000
}

如果使用 Traefik,在 override 中添加标签:

services:
  plausible:
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.plausible.rule=Host(`plausible.example.com`)"
      - "traefik.http.routers.plausible.tls.certresolver=letsencrypt"
      - "traefik.http.services.plausible.loadbalancer.server.port=8000"
    networks:
      - proxy
      - default

networks:
  proxy:
    external: true

另外,Plausible 内置了 Let's Encrypt 支持。在 .env 文件中设置 HTTP_PORT=80HTTPS_PORT=443,然后在 override 中暴露这些端口:

services:
  plausible:
    ports:
      - 80:80
      - 443:443

这种方式更简单,但意味着 Plausible 自行管理 TLS,如果其他服务共享同一服务器可能会产生冲突。

启动容器

docker compose up -d

三个容器启动:plausible_db(PostgreSQL 16)、plausible_events_db(ClickHouse 24.12)和 plausible(Web 应用)。Plausible 容器在启动时自动运行数据库迁移。

检查三个容器是否健康:

docker compose ps
NAME                  IMAGE                                          STATUS
plausible             ghcr.io/plausible/community-edition:v3.2.0     Up 30s (healthy)
plausible_db          postgres:16-alpine                             Up 35s (healthy)
plausible_events_db   clickhouse/clickhouse-server:24.12-alpine      Up 35s (healthy)

三个都应显示 (healthy)。如果 ClickHouse 显示 (health: starting),再等一分钟。它通过 wget 对 HTTP 接口执行健康检查。

创建管理员账户

在浏览器中打开 https://plausible.example.com。你会看到注册表单。创建你的账户。设置 DISABLE_REGISTRATION=invite_only 后,新用户只能在你从仪表板明确邀请后才能注册。

注册后,如果你是唯一用户,可以完全锁定注册:

编辑 .env 并更改:

DISABLE_REGISTRATION=true

然后重启:

docker compose up -d

如何将 Plausible 跟踪脚本添加到你的网站?

登录后,点击"Add a website"并输入你的域名。Plausible 会生成一个跟踪代码片段。默认的 script 标签如下:

<script defer data-domain="yoursite.com" src="https://plausible.example.com/js/script.js"></script>

plausible.example.com 替换为你的 Plausible 实例的实际 URL。将此标签添加到每个需要跟踪的页面的 <head> 中。

如何将 Plausible 添加到静态 HTML 网站?

将 script 标签直接粘贴到 HTML 的 <head> 中:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>My Site</title>
    <script defer data-domain="yoursite.com" src="https://plausible.example.com/js/script.js"></script>
</head>
<body>
    <!-- content -->
</body>
</html>

对于静态网站生成器(Hugo、Jekyll、11ty),将 script 标签添加到基础模板或 head partial 中。

如何将 Plausible 添加到 WordPress 网站?

官方 Plausible Analytics WordPress 插件(v2.5.4,10,000+ 活跃安装)通过 WordPress 后台处理所有配置。

  1. 安装插件:插件 > 安装新插件 > 搜索"Plausible Analytics"
  2. 进入 设置 > Plausible Analytics
  3. 输入自托管实例的域名 URL(例如 https://plausible.example.com
  4. 输入要跟踪的域名
  5. 保存

插件自动注入跟踪脚本。它还支持 WooCommerce 转化跟踪和 Contact Form 7、WPForms、Ninja Forms 的自动表单提交跟踪。

如何将 Plausible 添加到 Next.js 应用?

使用 next-plausible 包(v3.12.5,每周 36,000 次下载)。

npm i next-plausible

对于 App Router(Next.js 13+),在根 layout 中添加 provider:

import PlausibleProvider from "next-plausible";

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html>
      <head>
        <PlausibleProvider
          domain="yoursite.com"
          customDomain="https://plausible.example.com"
          selfHosted
        />
      </head>
      <body>{children}</body>
    </html>
  );
}

要在组件中跟踪自定义事件,使用 usePlausible hook:

"use client";
import { usePlausible } from "next-plausible";

export default function SignupButton() {
  const plausible = usePlausible();
  return (
    <button onClick={() => plausible("Signup")}>
      Sign up
    </button>
  );
}

如何将 Plausible 添加到单页应用?

对于 React、Vue、Svelte 或任何 SPA,将 script 标签添加到 index.html。Plausible 通过 History API 自动跟踪路由变化。无需额外配置。

如果你的 SPA 使用基于 hash 的路由(/#/path),使用 hash 扩展:

<script defer data-domain="yoursite.com" src="https://plausible.example.com/js/script.hash.js"></script>

如何在 Plausible 中跟踪自定义事件和目标?

自定义事件可以跟踪页面浏览之外的操作:按钮点击、表单提交、文件下载、注册。Plausible 提供两种方法:无代码的 CSS 类方法和用于动态跟踪的 JavaScript API。

首先,启用支持自定义事件的增强脚本。替换默认脚本源:

<script defer data-domain="yoursite.com" src="https://plausible.example.com/js/script.tagged-events.js"></script>

CSS 类方法(无需 JavaScript)

plausible-event-name=EventName 格式向任何 HTML 元素添加 CSS 类:

<a href="/signup" class="plausible-event-name=Signup">Create Account</a>

<button class="plausible-event-name=Download+PDF">Download Report</button>

<form class="plausible-event-name=Contact+Form+Submit">
  <!-- form fields -->
</form>

事件名中的空格用 + 表示。某些 CMS(Webflow)会将 = 替换为 -。这种情况下使用双连字符 --plausible-event-name--Signup

JavaScript API 用于动态事件

对于需要条件逻辑或动态属性的事件,直接调用 plausible() 函数:

// Simple event
plausible("Signup");

// Event with custom properties
plausible("Download", {
  props: { format: "PDF", document: "annual-report" }
});

// Event with a callback (useful for redirects)
plausible("Outbound Link", {
  props: { url: "https://example.com" },
  callback: () => { window.location = "https://example.com"; }
});

在仪表板中创建目标

事件在创建匹配目标之前不会出现在仪表板中。进入 Site Settings > Goals > Add Goal。选择"Custom event"并输入准确的事件名称(例如 Signup)。名称区分大小写,必须与代码匹配。

如何使用 Plausible Stats API?

Plausible 包含 Stats API (v2),用于以编程方式访问分析数据。在自托管实例上,API 基础 URL 为 https://plausible.example.com/api/v2/query

创建 API 密钥:进入 Account Settings > API Keys > New API Key > Stats API

查询过去 7 天的访客数量:

curl --request POST \
  --header 'Authorization: Bearer YOUR-API-KEY' \
  --header 'Content-Type: application/json' \
  --url 'https://plausible.example.com/api/v2/query' \
  --data '{
    "site_id": "yoursite.com",
    "metrics": ["visitors", "pageviews", "bounce_rate"],
    "date_range": "7d"
  }'
{
  "results": [
    {
      "metrics": [1423, 3847, 42],
      "dimensions": []
    }
  ],
  "query": {
    "site_id": "yoursite.com",
    "metrics": ["visitors", "pageviews", "bounce_rate"],
    "date_range": ["2026-03-13", "2026-03-20"]
  }
}

按页面细分访客:

curl --request POST \
  --header 'Authorization: Bearer YOUR-API-KEY' \
  --header 'Content-Type: application/json' \
  --url 'https://www.example.com/api/v2/query' \
  --data '{
    "site_id": "yoursite.com",
    "metrics": ["visitors", "pageviews"],
    "date_range": "30d",
    "dimensions": ["event:page"],
    "pagination": {"limit": 5}
  }'

API 支持过滤、时间维度(time:daytime:month)和排序。速率限制为每小时 600 次请求。完整的 Stats API 参考文档包含所有可用指标和维度。

如何设置邮件报告?

邮件报告需要在 .env 文件中配置可用的 SMTP(上面的环境设置部分已介绍)。SMTP 配置完成后,任何用户都可以从 Plausible 仪表板启用每周或每月邮件报告。

进入 Site Settings > Email Reports。添加收件人地址。Plausible 按你选择的频率发送访客、热门页面和流量来源的摘要。

如果邮件未送达,检查 Plausible 容器日志:

docker compose logs plausible | grep -i mail

常见问题:SMTP 端口错误(STARTTLS 使用 587,隐式 TLS 使用 465 并设置 SMTP_HOST_SSL_ENABLED=true),或认证失败。

如何备份自托管的 Plausible 实例?

Plausible 将数据存储在两个数据库和一个卷中。丢失其中任何一个都意味着数据丢失。三个都要备份。

数据 存储 备份方法
用户账户、站点配置 PostgreSQL pg_dump
分析事件 ClickHouse 卷备份或 BACKUP 命令
证书、上传文件 plausible-data 卷复制

备份 PostgreSQL

docker compose exec plausible_db pg_dump -U postgres plausible_db | gzip > backup-postgres-$(date +%F).sql.gz

备份 ClickHouse

ClickHouse 24.12 原生支持 BACKUP 命令。在容器内执行:

docker compose exec plausible_events_db clickhouse-client \
  --query "BACKUP DATABASE plausible_events_db TO Disk('backups', 'plausible-$(date +%F).zip')"

如果 backups 磁盘未配置,使用卷级别备份:

docker compose stop plausible_events_db
docker run --rm \
  -v plausible-ce_event-data:/source:ro \
  -v $(pwd)/backups:/backup \
  alpine tar czf /backup/clickhouse-$(date +%F).tar.gz -C /source .
docker compose start plausible_events_db

这会短暂停止 ClickHouse。如需零停机备份,在 ClickHouse 中配置 backups 磁盘或使用 clickhouse-backup。

自动化备份

创建脚本 /opt/plausible-backup.sh

#!/bin/bash
set -euo pipefail
BACKUP_DIR=/opt/backups/plausible
mkdir -p "$BACKUP_DIR"
cd /opt/plausible-ce

# PostgreSQL
docker compose exec -T plausible_db pg_dump -U postgres plausible_db \
  | gzip > "$BACKUP_DIR/postgres-$(date +%F).sql.gz"

# ClickHouse volume
docker run --rm \
  -v plausible-ce_event-data:/source:ro \
  -v "$BACKUP_DIR":/backup \
  alpine tar czf "/backup/clickhouse-$(date +%F).tar.gz" -C /source .

# Plausible data volume
docker run --rm \
  -v plausible-ce_plausible-data:/source:ro \
  -v "$BACKUP_DIR":/backup \
  alpine tar czf "/backup/plausible-data-$(date +%F).tar.gz" -C /source .

# Rotate: keep 14 days
find "$BACKUP_DIR" -name "*.gz" -mtime +14 -delete

echo "Backup complete: $(ls -lh $BACKUP_DIR/*$(date +%F)*)"
chmod 700 /opt/plausible-backup.sh

使用 cron 安排每日执行:

crontab -e

添加:

0 3 * * * /opt/plausible-backup.sh >> /var/log/plausible-backup.log 2>&1

了解更多 Docker 卷备份策略,请参阅 在VPS上备份和恢复Docker卷

如何安全更新 Plausible 社区版?

Plausible CE 每年发布两次。在 compose.yml 中将版本固定到特定标签以获得可预测的升级。默认配置已固定到 v3.2.0

版本固定策略:

级别 标签示例 自动更新内容
补丁(最安全) v3.2.0 无。仅手动升级。
次要版本 v3.2 补丁版本(错误修复)
主要版本 v3 次要和补丁版本

建议:固定到补丁级别,阅读发布说明后手动更新。

升级步骤

  1. 阅读发布说明了解破坏性变更

  2. 备份数据库(运行上面的备份脚本)

  3. 拉取新版本:

cd /opt/plausible-ce
git fetch --tags
git checkout v3.3.0  # replace with the target version
  1. 启动更新后的容器:
docker compose up -d

Plausible 在启动时自动运行数据库迁移。首次启动时关注日志:

docker compose logs -f plausible

在输出中寻找 [info] Migrations up to XXXXXXXX applied successfully。如果看到迁移错误,不要丢弃旧数据。查看升级 wiki 页面获取版本特定说明。

  1. 清理旧镜像:
docker image prune -f

安全补丁不会回移植到旧版本。在 GitHub 上订阅发布通知:进入仓库,点击 Watch > Custom > Releases

是的。Plausible 不设置 cookie。不收集或存储个人数据。唯一访客通过访客 IP 地址与 User-Agent 字符串的哈希值计数。该哈希每 24 小时轮换一次,且从不以原始形式存储。原始 IP 地址在哈希后即被丢弃。

这意味着:

  • 无需 GDPR、CCPA 或 PECR 下的 cookie 同意横幅
  • 无个人数据处理,因此 GDPR 第六条的合法性基础要求不适用
  • 自托管意味着数据永远不会离开你的服务器,也不会传输给第三方处理者
  • 你是唯一的数据控制者,无需为分析签订数据处理协议

如果你的 VPS 托管在欧盟(Virtua Cloud 服务器位于欧洲数据中心),你的分析数据留在欧盟境内。无 Schrems II 传输问题。

这就是许多独立开发者和注重隐私的开发者放弃 Google Analytics 的原因。没有同意横幅,没有访客摩擦,没有数据处理协议需要管理。

监控 ClickHouse 资源使用

ClickHouse 是最消耗资源的组件。低流量空闲时使用约 500 MB 内存。查询大数据集时可能飙升到 2-3 GB。如果你的 VPS 总共只有 2 GB 内存,繁忙时可能出现 OOM kill。

监控内存使用:

docker stats plausible_events_db --no-stream
CONTAINER ID   NAME                  CPU %   MEM USAGE / LIMIT   MEM %
a1b2c3d4e5f6   plausible_events_db   0.50%   487MiB / 3.84GiB    12.38%

Plausible CE 附带的 ClickHouse 配置已包含低资源覆盖(通过 low-resources.xmldefault-profile-low-resources-overrides.xml)。这些限制了合并和查询的内存使用。

如果需要进一步调优,创建 clickhouse/custom.xml 覆盖文件并在 compose.override.yml 中挂载。关于 Docker Compose 中的资源限制,请参阅 Docker Compose资源限制、健康检查与重启策略

检查 ClickHouse 日志中的警告:

docker compose logs plausible_events_db | grep -i "memory\|oom"

出了问题?

容器无法启动: 检查 docker compose logs <service>。常见原因:端口冲突、缺少 .env 变量、ClickHouse 在旧 CPU 上未通过 SSE 4.2 检查。

登录页面出现"Bad Request": 你的 BASE_URL 与访问的 URL 不匹配。Plausible 检查 origin 头与 BASE_URL 是否一致以防止跨站请求伪造。

跟踪脚本未记录访问: 打开浏览器开发者工具,在网络标签中检查发往 /api/event 的请求。202 响应表示事件已被接受。如果看到 CORS 错误,说明反向代理剥离了请求头。确保代理传递 Host 头。

邮件报告未发送: 验证 SMTP 凭据。用 docker compose logs plausible | grep -i smtp 检查日志。用 swaksopenssl s_client 独立测试 SMTP 服务器。

ClickHouse 被 OOM killer 终止: VPS 内存不足。升级到至少 4 GB,或在 ClickHouse 配置覆盖中降低 max_memory_usage

安装后仪表板显示零访客: 跟踪脚本可能被广告拦截器阻止。考虑通过主域名代理脚本。Plausible 文档将此称为 proxy setup。

要监控 Plausible 实例的可用性,请参阅 使用Docker Compose在VPS上自建Uptime Kuma和Beszel