在 Mac Mini 上 Self-Host Aptabase 的踩坑记录
最近在为自己开发的 App 寻找数据统计工具。市面上的选择不少,但大部分要么太重,要么在隐私方面让人不太放心。调研了一圈之后,Aptabase 吸引了我的注意 —— 它主打隐私优先,不使用任何用户唯一标识符,完全符合 GDPR、CCPA 等法规要求,而且自带的 Dashboard 简洁直观,提供了超过 10 种 SDK,基本覆盖了主流的开发框架。更重要的是,它支持 Self-Host,数据完全掌握在自己手里。
官方提供了 Self-Hosting 仓库,看起来很简单 ——clone 下来、改改配置、docker compose up -d 就完事了。但实际部署过程中还是踩了不少坑,Issue 里也有很多人遇到了类似的问题。这里把我的经历整理出来,希望能帮到后来人。
坑一:默认不发邮件,激活链接藏在日志里
Aptabase 默认没有配置 SMTP,注册账号后不会收到任何邮件。但它会把激活链接打印在容器日志里,所以注册完之后需要手动查看日志来获取激活链接:
1 | docker logs -f aptabase_app |
在日志中找到类似下面的链接,复制到浏览器打开即可激活账号:
1 | https://your-domain/api/_auth/continue?token=eyJhbGciOiJIUzI1NiIs... |
当然这只是临时方案,后面我们会配置 SMTP 来让邮件正常发送。
坑二:必须配置 HTTPS,否则激活链接会循环跳转
拿到激活链接后点击,却发现页面一直循环跳转回登录页,始终无法完成激活。排查后发现,Aptabase 要求 BASE_URL 必须是 HTTPS,否则认证流程中的 Cookie 和重定向会出问题。
我的服务跑在家里的 Mac Mini 上,没有公网 IP,也不想折腾证书。最终的方案是使用 Cloudflare Tunnel + 自定义域名来解决。
配置 Cloudflare Tunnel
- 登录 Cloudflare Dashboard,进入 Zero Trust → Networks → Tunnels
- 点击 Create a tunnel,选择 Cloudflared 类型,给 Tunnel 起一个名字(比如
mac-mini) - 按照页面提示,在 Mac Mini 上安装并运行
cloudflared。macOS 上可以用 Homebrew:
1 | brew install cloudflared |
然后按照页面给出的命令连接 Tunnel(会包含一个 Token):
1 | cloudflared service install <your-token> |
- 在 Tunnel 的 Public Hostname 页面添加一条记录:
- Subdomain:
stats(或你喜欢的名字) - Domain:选择你在 Cloudflare 上托管的域名,比如
pastepaw.com - Service:
http://localhost:3200(这里的端口对应 docker-compose 中 Nginx 映射的端口)
- Subdomain:
配置完成后,Cloudflare 会自动管理 HTTPS 证书,外部访问 https://stats.pastepaw.com 的流量会通过 Tunnel 安全地转发到你的 Mac Mini。
坑三:获取不到用户真实 IP
部署完成后发现 Dashboard 里所有用户的 IP 地址都一样 —— 显示的都是 Cloudflare 的 IP,而不是用户的真实 IP。
这是 Cloudflare Tunnel 的经典问题。流量经过 Cloudflare 代理后,到达你的服务时,来源 IP 变成了 Cloudflare 的服务器 IP。真正的用户 IP 被放在了 CF-Connecting-IP 这个 HTTP Header 里,但 Aptabase(基于 ASP.NET Core)默认不会读取这个 Header。
解决方案是在 Aptabase 前面加一层 Nginx,把 CF-Connecting-IP 转换为标准的 X-Forwarded-For,然后让 Cloudflare Tunnel 指向 Nginx 而非直接指向 Aptabase。
Nginx 配置文件 nginx.conf 如下:
1 | events { |
这样 Aptabase 就能正确识别到用户的真实 IP 了。
坑四:配置 SMTP 邮件发送
日志里翻激活链接终归不是长久之计。Aptabase 支持通过环境变量配置 SMTP,我这里选择了 Resend 作为邮件服务 —— 注册免费,每月有 3,000 封邮件的额度,对个人项目完全够用。
在 Resend 中绑定域名
- 注册 Resend 账号
- 进入 Domains 页面,点击 Add Domain
- 输入你想用于发送邮件的域名(比如
mail.pastepaw.com,也可以和 Aptabase 的域名不同,没有关系) - Resend 会给你几条 DNS 记录需要添加,通常包括:
- 一条 MX 记录
- 一条 SPF(TXT)记录
- 几条 DKIM(TXT)记录
- 到你的 DNS 管理面板(比如 Cloudflare)中添加这些记录
- 回到 Resend,点击 Verify,等待验证通过(通常几分钟内完成)
生成 API Key
- 在 Resend 左侧菜单进入 API Keys 页面
- 点击 Create API Key
- 给 Key 起个名字(比如
aptabase),权限选择 Sending access,域名限制可以选择刚才绑定的域名 - 复制生成的 Key(以
re_开头),这就是你的 SMTP 密码
配置环境变量
在 docker-compose.yml 的 Aptabase 服务中添加以下环境变量:
1 | SMTP_HOST: smtp.resend.com |
注意:这里端口要用 587(STARTTLS),而不是 465(Implicit TLS)。实测使用 465 端口在 Docker 环境下无法正常发送邮件,换成 587 后立刻恢复正常。这也是一个容易踩的坑。
完整的 Docker Compose 配置
以下是最终可用的完整 docker-compose.yml:
1 | services: |
需要创建一个 .env 文件来存放数据库密码:
1 | echo "PASSWORD=你的数据库强密码" > .env |
提醒:
AUTH_SECRET务必替换为自己生成的随机字符串,可以在 RandomKeygen 上生成一个。不要使用官方文档里的示例值。
启动服务
1 | docker compose up -d |
等待所有容器启动完成后,访问 https://stats.pastepaw.com,注册账号,这次你应该能正常收到激活邮件了。
整体架构图
所有组件部署完成后,整体架构如下:
各组件职责:
- Cloudflare:提供 HTTPS 证书管理和 CDN 加速,通过 Tunnel 将外部流量安全地转发到家里的 Mac Mini
- Nginx:反向代理,核心作用是将 Cloudflare 注入的
CF-Connecting-IPHeader 转换为X-Forwarded-For,让 Aptabase 能识别用户真实 IP - Aptabase:核心应用服务,处理 SDK 上报的事件、管理用户账号、提供 Dashboard
- PostgreSQL:存储用户账号、应用配置、API Key 等关系型数据
- ClickHouse:高性能 OLAP 引擎,存储所有上报的事件数据,支撑 Dashboard 的实时分析查询
- Resend:外部 SMTP 邮件服务,用于发送账号激活邮件等
事件数据流转
当 App 中的 SDK 上报一个事件时,数据会经过以下路径:
简单来说:SDK 发出的每一个事件,经过 Cloudflare 解密和 IP 标记、Nginx 的 Header 转换、Aptabase 的校验和地理解析后,最终以结构化的形式写入 ClickHouse。而你在 Dashboard 上看到的所有图表和指标,都是从 ClickHouse 中实时查询出来的。
总结
Aptabase 本身是一个非常优秀的轻量级统计工具,但 Self-Host 的文档相对简略,部署过程中有不少需要自己摸索的地方。总结一下关键的几个坑:
- 默认不发邮件 —— 激活链接在容器日志里,需要
docker logs -f查看 - 必须 HTTPS—— 否则认证流程会循环跳转,推荐使用 Cloudflare Tunnel 解决
- 真实 IP 获取 ——Cloudflare Tunnel 代理后需要加一层 Nginx 做 Header 转换
- SMTP 端口 —— 用 587(STARTTLS)而不是 465,后者在 Docker 环境下可能不工作
- 安全配置 —— 记得替换默认的
AUTH_SECRET,妥善保管 API Key 和数据库密码
希望这篇文章能帮到同样想 Self-Host Aptabase 的朋友,少走一些弯路。