SSD Nodes Learn 🎉 VPS $5.50/月起
指南 Matt Connor作者: Matt Connor · 更新于 2026-08-16

自托管 Web 分析 VPS 怎么选?内存与日志对比

对比 Plausible、Umami、Matomo、GoatCounter 和 GoAccess:1 GB 或 2 GB 内存要求、数据库与磁盘增长、反向代理配置,以及广告拦截器会漏掉哪些访问。

VPS 上应该运行哪种自托管 Web 分析工具?

自托管 Web 分析工具分为两类。选错类别的代价通常高于选错具体产品。一类会在访问者的浏览器中运行一个小型脚本,并存储该脚本上报的数据。另一类会读取 Web 服务器已经写入的访问日志。数据库和所需内存等后续配置,都取决于这个选择。

小型服务器的简短结论如下。GoatCounter 和 Medama 只需 1 GB 内存即可运行,因为它们各自都是一个进程,并使用一个文件。Umami 需要一个 Postgres 容器,但提供了非技术人员也能读懂的仪表板。Plausible Community Edition 和 Rybbit 都运行 ClickHouse,因此应准备 2 GB 或更多内存。Matomo 功能完整,应根据流量为其配置相应规格的服务器。GoAccess 完全不会向页面添加内容,因为它读取的是已经存在的日志。

脚本标签或服务器日志:两者各自能看到什么

脚本标签会统计浏览器。页面加载后,脚本运行,并向您的采集器发送一个请求。链路中的任何环节发生故障,您都无法看到:用户禁用了 JavaScript、过滤列表阻止了请求、向采集器发送请求失败,或者爬虫根本不运行脚本。

日志解析器会统计请求。无论您是否安装其他组件,Web 服务器都会为每个请求写入一行日志,因此数据已经保存在磁盘上。它可以看到每个爬虫,也可以看到对不含脚本标签的文件发起的每次访问。它无法看到浏览器内部发生了什么,也无法看到由浏览器缓存或您服务器前方的 CDN(内容分发网络)提供的页面,因为该请求根本没有到达您的服务器。

这两个数字不会一致,但两者都没有错误。Matomo 同时支持这两种方式,并说明了与 JavaScript 跟踪器相比,日志导入会缺少哪些数据:屏幕分辨率和页面标题、事件、内容跟踪、热图、会话录制和表单分析。使用请求而不是浏览器进行统计,就必须舍弃这些数据。

机器人流量是造成差异的另一半原因。基于日志的统计会包含爬虫,除非您对其进行过滤;对于普通网站,爬虫占比通常足以改变结论。GoAccess 和 Matomo 的日志导入都会过滤已知机器人。但如果爬虫伪造 User-Agent,两者都无法将其过滤掉。因此,基于日志进行统计时,最好同时使用在服务器端阻止 AI 爬虫,并在阻止后而不是阻止前读取日志。

GoAccess:使用已有日志进行分析

请从项目自己的 Debian 和 Ubuntu 软件源安装 GoAccess,因为发行版软件包通常滞后于新版本。

wget -O - https://deb.goaccess.io/gnugpg.key | gpg --dearmor | sudo tee /usr/share/keyrings/goaccess.gpg >/dev/null
echo "deb [signed-by=/usr/share/keyrings/goaccess.gpg arch=$(dpkg --print-architecture)] https://deb.goaccess.io/ $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/goaccess.list
sudo apt-get update
sudo apt-get install goaccess

然后将日志作为输入,并生成静态报告。

goaccess /var/log/nginx/access.log -o ~/report.html --log-format=COMBINED

普通用户执行该命令会因 Permission denied 失败,因为在 Ubuntu 中,nginx 日志归 root 所有,所属组为 adm。使用 sudo usermod -aG adm $USER 将自己加入该组,然后注销并重新登录,因为组成员身份在登录时读取。运行 id,确认列表中出现 adm 后再重试。

对当前日志生成的报告只包含 logrotate 尚未移动的内容。昨天的请求位于 access.log.1 中,更早的日志已被压缩,因此周报还必须读取轮转后的文件。

zcat /var/log/nginx/access.log.*.gz | goaccess - --log-format=COMBINED -o ~/last-week.html

GoAccess 还提供实时模式 --real-time-html,通过 WebSocket 更新页面。该模式需要额外的端口和单独的代理规则。对于大多数网站,由 cron 每小时生成一次报告就足够了,需要保护的内容也更少。

GoatCounter:一个 Go 二进制文件和一个 SQLite 文件

GoatCounter 以静态编译的二进制文件发布,因此无需安装运行时。可以从发布页面获取构建版本并运行,也可以使用镜像。

docker run -p 8080:8080 -v goatcounter-data:/home/goatcounter/goatcounter-data arp242/goatcounter

以二进制文件运行时,goatcounter serve 监听 8080 端口,并在 ./goatcounter-data/db.sqlite3 创建 SQLite 数据库。当实例已经位于代理之后时,应从命令行创建第一个站点,而不是使用 Web 向导。

goatcounter db create site -vhost=stats.example.com -user.email=me@example.com

它可以通过 goatcounter serve -listen=:443 -tls=tls,rdr,acme 管理自己的证书,并使用 ACME(自动证书管理环境)。如果服务器上没有运行其他服务,这种方式很实用。如果 nginx 或 Caddy 已占用 443 端口,则让 GoatCounter 继续监听 8080 端口,并将请求代理到它。根据项目自己的统计,跟踪脚本大小约为 3.5K;对于不运行 JavaScript 的页面,还提供跟踪像素。如果繁忙站点上的 SQLite 成为限制,同一个二进制文件也可以通过 goatcounter serve -db 'postgresql+dbname=goatcounter' 使用 Postgres。备份只需复制文件,这正是这种工具形态的实际优势。

Medama:单个容器占用 256 MB

Medama 是这里介绍的最新单二进制选项。它从设计上不使用 Cookie,项目声称跟踪器小于 1 KB,并且在内存为 256 MB 的虚拟机上也能运行小型网站。这些是项目公开发布的声明,不是本指南实测的数据。

docker volume create medama-data
docker run -d -p 127.0.0.1:8080:8080 -v medama-data:/app/data ghcr.io/medama-io/medama:latest

官方命令将端口发布为 8080:8080。上面的 loopback 前缀是有意设置的,反向代理部分会解释原因。首次登录时,用户名是 admin,密码是 CHANGE_ME_ON_FIRST_LOGIN;密码名称本身就是操作提示。

有一种已记录的失败情况需要注意。登录只能通过 HTTPS 或在 localhost 上进行。因此,如果在证书配置完成前先设置反向代理,表单会拒绝正确的密码,且不会显示原因。请先完成 TLS(传输层安全)配置,再登录。

Umami:Postgres,以及用户熟悉的仪表板

git clone https://github.com/umami-software/umami.git
cd umami
docker compose up -d

该命令会在 3000 端口启动应用,并在旁边运行一个 PostgreSQL 容器。如果改为从源代码构建,文档要求 PostgreSQL v12.14 或更高版本,以及 Node.js 18.18 或更高版本。Umami 提供预构建镜像 docker.umami.is/umami-software/umami:postgresql-latest,但必须将 DATABASE_URL 设置为指向现有数据库。

首次登录时,用户名为 admin,密码为 umami。将 DNS 指向该服务器前,请先修改密码,因为 DNS 记录解析且代理开始响应后,该实例就会立即从互联网访问。有关 Compose 详细信息、环境文件和重启策略,请参阅VPS 上的 Docker Compose 堆栈,不要直接复制未经阅读的堆栈配置。

该服务由一个 Node 进程和 Postgres 组成。它比单个二进制程序占用更多资源,但比任何运行 ClickHouse 的方案轻量得多。

Plausible Community Edition:ClickHouse 决定内存下限

git clone -b v3.2.1 --single-branch https://github.com/plausible/community-edition plausible-ce
cd plausible-ce
touch .env
echo "BASE_URL=https://stats.example.com" >> .env
echo "SECRET_KEY_BASE=$(openssl rand -base64 48)" >> .env
docker compose up -d

截至 2026 年 8 月,当前版本为 v3.2.1。clone 命令会有意固定该版本。整个栈包含三部分:应用、用于存储账户和设置的 Postgres,以及用于存储事件数据的 ClickHouse。SECRET_KEY_BASE 必须至少是 64 字节的字符串,openssl 调用会生成符合要求的值。

Plausible 的要求是至少 2 GB RAM,避免 ClickHouse 和应用触发 out-of-memory killer;CPU 还必须支持 ClickHouse 所需的 SSE 4.2 或 NEON。购买前应检查第二项要求。这也是选择 ARM 还是 x86 VPS时需要考虑的实际差异之一。ClickHouse 还会使用它认为可用的全部内存,因此在共享服务器上,应按照在 Compose 中限制容器内存中的说明设置上限。

BASE_URL 必须与公网 URL 完全一致。如果不一致,您登录后,应用会将请求重定向到错误的主机,并将会话 cookie 写入浏览器当前所在域名之外的域名,因此页面会返回登录表单,且不会显示错误消息。

随附的 compose 文件不会发布端口,因为预期由前置代理处理请求。请添加一个 override,仅在 loopback 上发布默认应用端口。

cat > compose.override.yml << EOF
services:
    plausible:
        ports:
            - 127.0.0.1:8000:8000
EOF

Matomo:完整产品及其所需的服务器

Matomo 运行在 PHP 和 MySQL 或 MariaDB 之上,因此它属于经典 Web 堆栈,而不是容器堆栈。它也是本文唯一一个按流量规模发布硬件建议的工具。

ChartMatomo sizing guidance by monthly pageviews
The data behind this chart
[
  {
    "label": "100K/month",
    "cpu_cores": 2,
    "ram_gb": 2,
    "disk_gb": 50
  },
  {
    "label": "1M/month",
    "cpu_cores": 4,
    "ram_gb": 8,
    "disk_gb": 250
  },
  {
    "label": "10M/month",
    "cpu_cores": 8,
    "ram_gb": 16,
    "disk_gb": 400
  }
]

这些是 Matomo 截至 2026 年 8 月发布的最低配置要求,不是本指南的实测结果。每月页面浏览量不超过 100,000 时,它要求 2 个 CPU 核心、2 GB RAM 和 50 GB SSD,并且一台服务器同时运行应用和数据库。在 1M/month 时,需要 8 GB RAM 和 250 GB 磁盘空间。在 10M/month 时,Matomo 建议使用两台服务器;最后一行显示的是数据库服务器配置:16 GB RAM 和 400 GB 磁盘空间。请将这些磁盘空间数值与单二进制文件方案放在一起比较,因为后者的完整数据集都存储在一个 SQLite 文件中。

归档机制往往最容易引发意外。默认情况下,Matomo 会在有人打开 dashboard 时生成报告。因此,随着数据量增长,dashboard 会变慢,最终可能超时。文档给出的解决方法是,在常规设置中关闭由浏览器触发的归档,然后改用 cron 运行 archiver;运行用户应为 Matomo 文件的所有者,工作目录应为 Matomo 目录。

php console core:archive --url=https://analytics.example.com

Matomo 还会在已处理的报告表旁保留原始日志表,并且可以按计划删除旧的原始数据和旧报告。安装时就应启用此功能,不要等到磁盘已满后再处理。Matomo 还可以导入服务器访问日志,因此它是本文唯一一个同时覆盖这两类数据的产品。

Rybbit 和较新的技术栈

git clone https://github.com/rybbit-io/rybbit.git
cd rybbit
chmod +x *.sh
./setup.sh your.domain.name

Rybbit 是近期出现的项目,提供现代化的仪表板。安装脚本会写入环境文件,并使用 Docker Compose 启动整个技术栈。它运行 ClickHouse,并自带 Caddy 作为 Web 服务器。Caddy 会占用 443 端口,并为您传入的域名申请证书。如果服务器上的 nginx 已占用 443 端口,脚本将无法绑定该端口。此时应使用项目提供的手动 Compose 部署方式,并将其置于现有代理之后。文档要求至少 2 GB RAM;项目已在 Ubuntu 24 LTS 上测试。由于 ClickHouse 的要求,ARM 架构需要使用 ARMv8.2-A 或更高版本。

对于任何新项目,都需要注意一个实际问题:功能更新很快,破坏性变更也可能随之出现。请固定版本标签,在拉取更新前阅读发布说明,并先备份数据库。

自行测量保留期和磁盘增长:在自己的服务器上获取数据

磁盘增长取决于工具为每个事件存储的内容。GoatCounter 将访问聚合为计数器,因此其文件大小更多取决于不同页面和天数,而不是原始访问量。Umami 和 Matomo 会为每个事件存储一行,Matomo 还会在原始数据之上存储经过处理的报表表。ClickHouse 按列存储事件,并进行高强度压缩,因此 Plausible 能够应对可能使行式存储承受压力的访问量。

本指南不提供每百万次页面浏览对应的 MB 数,因为没有在您的流量上进行测量。请自行读取数据。根据您自己的 Compose 文件调整服务名和用户名。

du -h goatcounter-data/db.sqlite3
docker compose exec db psql -U umami -d umami -c "SELECT pg_size_pretty(pg_database_size('umami'));"
docker compose exec plausible_events_db clickhouse-client -q "SELECT formatReadableSize(sum(bytes_on_disk)) FROM system.parts WHERE active"

记录该数值,等待一周后再次记录,然后用两次记录的差值除以仪表板报告的该周页面浏览量。这个数值反映了您的网站和机器人过滤规则,因此比任何公开发布的平均值都更有参考价值。然后在数值仍然较小时设置保留上限。磁盘空间耗尽会使 VPS 上的所有服务停止运行,而不仅是分析服务;这也是应将数据库卷放在 df -h 会发出警告的位置的最有力理由。对于已经存放大型数据的服务器,这项风险更值得关注,因为自托管照片服务器会在任何分析数据库接近磁盘上限之前耗尽磁盘空间。

反向代理在子域名后面的工作方式

将采集器放在被测站点的子域名下,例如 stats.example.com。这样,采集器请求会被视为第一方请求,不会受到浏览器拦截第三方请求的规则影响。

发布容器端口时,将应用绑定到 loopback。Docker 会在 ufw 之前写入自己的防火墙规则,因此,即使 ufw status 显示该端口被拒绝,发布为 -p 3000:3000 的容器仍可从互联网访问。使用 curl http://SERVER_IP:3000 从另一台机器进行测试时,会得到仪表板。发布为 -p 127.0.0.1:3000:3000 后,同样的测试会返回 Connection refused,只有代理可以访问该端口。

server {
    listen 443 ssl;
    server_name stats.example.com;

    location / {
        proxy_pass http://127.0.0.1:3000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

这里不能省略转发标头。如果没有 X-Forwarded-For,每次访问都会显示为来自 127.0.0.1,因此国家/地区报告为空,独立访客数会趋近于 1。每个项目决定信任哪个标头,以及在哪个设置下信任该标头,因此应查看项目的代理文档,不要自行假定。Caddy 会自动设置这些标头;使用 Caddyfile 完成相同配置只需两行。

stats.example.com {
    reverse_proxy 127.0.0.1:3000
}

如果尚未选择代理,请参阅nginx、Caddy 和 Traefik 的比较,其中介绍了哪种代理适合运行少量子域名的单台服务器。

自托管会改变数据由谁持有,但不会改变法律对这些数据的规定。请区分以下两条规则。ePrivacy 的同意规则针对在访客设备上存储或读取任何内容。因此,不设置 Cookie 且不写入本地存储的工具,不属于这一项具体要求的适用范围。GDPR 针对个人数据处理,而 IP 地址属于个人数据。因此,您仍需要确定合法依据、设置保留期限,并在有人询问时说明您持有哪些与其相关的数据。

Plausible、Umami、GoatCounter 和 Medama 默认不设置 Cookie。但各项目推导的其他数据并不相同,且可能随版本变化。因此,请查阅项目自己的隐私文档,不要只参考摘要。Matomo 提供 IP 匿名化功能,以及需要在管理界面中启用的退出跟踪端点。

不同国家的监管机构可能得出不同结论。例如,法国 CNIL 发布了在特定条件下可免于获取同意的受众测量规定。本节仅作事实摘要,不构成法律建议。对于面向真实用户的实际网站,请咨询您所在司法辖区的律师。

还有一点经常被忽略:访问日志同样属于个人数据。GoAccess 不会向页面添加脚本,但仍会处理 IP 地址。因此,基于日志的分析并不会自动排除在相关规则之外。

广告拦截器,以及为什么数据会下降

过滤列表会匹配主机名和 URL 模式。托管式分析产品很容易被匹配,因为所有用户都从同一个广为人知的主机名加载它。将采集器迁移到您自己的子域名后,请求中就不再包含该主机名;从您选择的路径提供脚本后,也不再包含那个广为人知的文件名。这两项改动都会改变过滤列表需要匹配的内容。

本文不声称某个拦截率,因为没有进行相关测量。会拦截某种配置的访问者比例取决于您的受众;开发者受众的拦截比例通常远高于普通受众。请改为测量您自己的差距。在同一周内,使用 GoAccess 统计访问日志中 HTML 页面的请求数,再将其与基于脚本的工具报告的页面浏览量进行比较。两者的差值就是您网站上被拦截的访问,以及由缓存提供的页面。

从托管式产品切换的当天,预计总数会发生变化;其中一部分变化与拦截无关。不同产品对页面浏览量的定义不同。例如,它们对单页应用内部的路由变化是否算作一次页面浏览,以及会话何时结束,可能有不同处理方式。在认定流量下降之前,请先比较连续数周的趋势。

不同网站适合使用什么工具

  • 每月页面浏览量大约不超过 50,000 的个人网站或博客:使用 GoatCounter 或 Medama,部署在 1 GB VPS 上,并将备份作为文件副本保存。
  • 无法添加脚本的网站,或用户大量拦截脚本的网站:按计划对现有日志运行 GoAccess。
  • 需要由其他人查看仪表板的小型企业网站:使用 Umami,并部署其 Postgres 容器。
  • 需要目标和漏斗分析,且服务器内存为 2 GB 或以上的网站:使用 Plausible Community Edition;如果希望使用更新式的仪表板,并能接受项目成熟度较低,也可以使用 Rybbit。
  • 拥有多个网站、多个用户账户,或要求按照自己的保留策略保存原始数据:根据上文发布的指导为 Matomo 配置资源。

从能够回答实际问题的最小工具开始。之后从 GoatCounter 迁移到 Plausible,只需处理一个子域名和部分历史数据。从 Matomo 迁移到其他工具,则需要执行一项你不会愿意面对的迁移。如果你还在决定同一台服务器上适合部署哪些其他服务,请参阅更全面的自托管服务汇总,其中介绍了哪些服务适合与它部署在一起;如果你真正需要的是应用的请求级追踪,而不是访客数量统计,则应使用自托管可观测性服务来完成这项工作。

FAQ

不可以,而且这是两个不同的问题。ePrivacy 下的同意规则适用于在访问者设备上存储或读取数据,因此不设置 Cookie 且不写入本地存储的工具,不受该项具体要求约束。GDPR 是另一项规则,适用于个人数据处理。IP 地址属于个人数据,因此即使不使用 Cookie,您仍需要有合法处理依据,并设置数据保留期限。自托管会将数据存储在您的服务器上,您也因此成为负责处理这些数据的一方。请查看您所在地区监管机构的指南,并针对具体情况咨询律师。

VPS 上的自托管分析需要多少 RAM?

决定资源需求的是数据存储层,而不是仪表板。GoatCounter 和 Medama 以单个进程运行,并使用单个文件。Medama 的文档称,小型网站可运行在配备 256 MB 内存的机器上。Umami 会在 Node 应用旁运行一个 Postgres 容器。Plausible Community Edition 和 Rybbit 都运行 ClickHouse,两个项目都声明至少需要 2 GB 内存。Matomo 自己的指南建议,从 2 个 CPU 核心和 2 GB RAM 起步,支持每月最多 100,000 次页面浏览。

为什么我的自托管数据低于被替换的分析工具?

原因有两个,而且都确实存在。过滤列表会阻止部分采集请求,因此所有依赖脚本的工具都会漏掉这些访问。不同产品的计数方式也不同,因为页面浏览的定义以及会话结束的时机并不一致。将访问日志中一周的 HTML 页面请求,与同一周基于脚本统计的页面浏览进行比较。两者之间的差值就是被阻止的访问和缓存页面造成的差异,数据来自您自己的网站,而不是借用他人公布的比例。

我可以在 ARM VPS 上运行 Plausible 或 Rybbit 吗?

两者都运行 ClickHouse,而 ClickHouse 在 x86 上需要 SSE 4.2,在 ARM 上需要 NEON。Plausible 的要求明确说明了这一点,Rybbit 的文档则说明 ARM 系统需要 ARMv8.2-A 或更高版本。当前的 ARM 服务器核心满足这一要求,较旧的核心则不满足。失败时,ClickHouse 会因指令集错误而拒绝启动,而不是在应用日志中显示其他错误。在小型 ARM 服务器上,单文件工具可以避开这一问题,因为它们都不运行 ClickHouse。

我是否应该解析服务器日志,而不是使用跟踪脚本?

如果无法添加脚本、访问者大量拦截脚本,或希望统计包含爬虫在内的访问量,请使用日志解析。GoAccess 读取服务器已经写入的日志,因此不会增加页面体积,也不需要数据库。代价是无法统计浏览器内部发生的行为,也无法统计由 CDN 或浏览器缓存直接提供的页面,因为这些请求没有到达您的服务器。许多网站会同时使用两者,并将其视为两种不同的度量方式。