我的博客想看访问数据——多少人来了、从哪来、看了哪些页面,最好页面底部还能显示个总数。第三方统计要么数据在别人那,要么国内加载慢。最后我用 Umami 跑在自己的 NAS 上,数据落本地硬盘,后台面板开箱可用,也没花额外的钱。这篇是我的实操步骤。
这套东西能给你什么
装完之后你会得到两样:
- 后台分析面板:PV/UV、来源、国家、设备、实时在线,都有现成图表
- 前台数字:在自己网站底部显示「本站总浏览量 X 次」这种计数
数据全部存在你自己的设备上,不经第三方。Umami 不用 cookie,所以也不用给网站加隐私弹窗。
一个 Umami 实例能管多个网站,每个站分一个 ID,各贴一段 JS 就行。
做完之后,网站底部会显示这样一行实时计数(数字到秒在跳):
整体结构
访客浏览器
↓ 加载 Umami 统计脚本
统计域名(比如 stats.你的域名.com)
↓ Cloudflare Tunnel 反代
NAS:Umami 容器 + PostgreSQL(数据在硬盘上)
Cloudflare 在这里只当网络通道,不碰你的数据内容。
第 1 步:在 NAS 上跑起 Umami
我用 Docker Compose 一次起两个容器:Umami 本体 + PostgreSQL 数据库。
新建一个 docker-compose.yml,内容类似这样(按你的实际情况改端口和密码):
services:
umami:
image: ghcr.io/umami-software/umami:postgresql-latest
ports:
- "36439:3000" # 左边是宿主机(NAS)端口,右边是容器内端口
environment:
DATABASE_URL: postgresql://umami:你的密码@db:5432/umami
DATABASE_TYPE: postgresql
APP_SECRET: 换成随机字符串
depends_on:
db:
condition: service_healthy # 等数据库就绪再启动 Umami
db:
image: postgres:15-alpine
environment:
POSTGRES_DB: umami
POSTGRES_USER: umami
POSTGRES_PASSWORD: 你的密码
volumes:
- ./data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U umami"]
interval: 10s
timeout: 5s
retries: 5
healthcheck那段建议留着。不加的话,PostgreSQL 还没完全启动 Umami 就去连,容易启动失败或者连上又断——重启 NAS 后尤其容易遇到。
在 NAS 的 Docker 管理界面里粘贴这段(各家 NAS 都有“项目 / Compose”这种入口),启动。
端口别记混:上面把容器的
3000映射成了36439,所以内网访问要开http://NAS的IP:36439。直接按 3000 打开是打不开的,那是容器内部的端口。
启动后浏览器打开这个地址,用默认账号登录(Umami 默认 admin / umami),进去第一件事是改密码。
第 2 步:让它能从外网访问
家里或内网的 NAS 没有公网 IP,用 Cloudflare Tunnel 穿出来:
- 进 Cloudflare Zero Trust 后台,创建一个 Tunnel,会拿到一串 Token
- 在 NAS 上跑
cloudflared(Docker 或装二进制都行),把 Token 配上 - 给这个 Tunnel 加一条 Public Hostname,比如
stats.你的域名.com,回源指向http://localhost:36439(或容器名http://umami:3000)
配好之后,你从任何地方打开 stats.你的域名.com 就能进后台了,而且是 HTTPS,不用自己申请证书。
第 3 步:给网站加上统计脚本
在 Umami 后台添加你的网站,会生成一段 tracking 代码和一个 website ID。把这段脚本贴到网站的 <head> 里:
<script defer src="https://stats.你的域名.com/script.js" data-website-id="你的websiteID"></script>
静态博客一般贴在公共布局文件里(我的是 BaseLayout.astro),全站页面就都带上了。
脚本文件名有两种:新版本是
script.js,老一点的版本叫umami.js,功能一样。不确定就直接复制后台给你生成的那段代码,别自己拼。
等几分钟回后台看,有访客进来就能看到数据了。
第 4 步:在页面底部显示访问数
后台有了,前台也想显示个总数。Umami 支持“公开分享”——在后台给网站开一个分享链接,会得到一个 share ID,靠它就能调接口拿数字。
流程是两步:
① 用 share ID 换一个临时 token:
GET https://stats.你的域名.com/api/share/{shareId}
返回里有个 token 和 websiteId。
② 带这个 token 去查统计:
GET https://stats.你的域名.com/api/websites/{websiteId}/stats?startAt=0&endAt=当前时间戳
请求头带上:
x-umami-share-token: 刚才换到的 token
x-umami-share-context: share
返回的是访问量和访客数,前端渲染成「本站总浏览量 X 次」就行。
我博客上是个 Astro 组件做这件事:进页面时先显示上次缓存在 localStorage 的数字(不等接口),后台同时去拉最新值,拉到再更新。这样访客不会看到空白或者等半天才出数字。
分享 ID 本来就是只读的,拿它只能查统计,改不了数据也进不了后台,所以放在前端代码里没问题。
第 5 步:记得备份
数据都在 PostgreSQL 里,定期导出一下比较稳妥。我是每天跑一次 pg_dump 并保留 7 天:
pg_dump -U umami umami > backup_$(date +%F).sql
丢进定时任务里就行。NAS 一般都有“计划任务”功能,配个每天凌晨执行。
关于速度
这套架构下,访客的请求路径是:浏览器 → Cloudflare 边缘 → Tunnel → 你的 NAS。国内访问因为要绕一圈,加载统计脚本会比纯 CDN 慢一些,但对统计这种后台数据来说影响不大(它不阻塞页面显示)。
如果你特别在意国内打开速度,可以再租个国内轻量云做反代,或者用 DNS 分线路解析——不过那是后话了,先用起来再说。
写在最后
自己搭统计最有价值的地方不是省多少钱,而是数据在自己手上:想查什么自己写 SQL,想导出去随时能导,也不用担心哪天第三方服务关停就没了。
装好之后我每天会瞄一眼后台的实时在线,看到有人正在读自己写的东西,那种感觉还挺实在的。你要是也想给自己的站点加一套,可以照着这个流程走一遍。
评论