SSD Nodes Learn Hosting plans →
指南 Matt Connor作者: Matt Connor

Dawarich、Traccar、OwnTracks与Home Assistant怎么选

比较Dawarich、Traccar、OwnTracks和Home Assistant的位置追踪功能:历史记录、实时地图、地理围栏与自动化,并说明为何不要将数据接收端点暴露在公网。

适合您场景的自托管位置跟踪应用

选择自托管位置跟踪方案,首先要明确一个问题:您是要为自己保留位置历史,还是要与其他人共同查看实时位置?Dawarich 适合前者。它是 Google Maps Timeline 的自托管替代方案,还可以导入您已有的位置历史。Traccar 适合后者。它最初面向 GPS 硬件和车队设计,并将手机视为另一台跟踪设备。OwnTracks 位于两者之下,既是手机应用,也提供消息格式。如果您运行 Home Assistant,它已经知道手机的位置,但默认会在十天后删除轨迹。

请根据您下个月想查看的内容进行选择:

  • 上个 3 月去过的所有地点和行程地图:Dawarich。
  • 多台设备的实时地图,以及地理围栏和事件规则:Traccar。
  • 让一部手机通过 HTTP 将位置发送到您已经运行的系统:OwnTracks。
  • 家庭和外出自动化,不需要位置历史:单独使用 Home Assistant。

如果使用 HTTP 上报,手机必须能够访问您控制的 HTTPS 端点,因此服务端配置会在下面单独介绍。如果您还在确定服务器上应运行哪些其他服务,今年值得自托管的更完整服务列表可以说明跟踪器在整体方案中的位置。

Traccar:GPS 硬件、车队与实时定位

Traccar 是一个追踪服务器。它支持专用 GPS 追踪器使用的协议,每个协议占用一个独立端口,在当前的协议列表中编号从 5001 到 5267。Traccar 的 Docker 指南中发布了 5000 到 5300 范围内的所有 TCP 和 UDP 端口。同一份指南警告称,每个发布的端口都会启动一个 docker-proxy 进程,这会消耗大量内存。因此,仅发布设备实际使用的端口,或者禁用 Docker 的用户空间代理(改用 iptables NAT),是更轻量的选择。此外,它还提供实时地图、地理围栏、事件规则和报告功能。Web 界面默认监听 8082 端口。

对于手机,可以使用 Android 和 iOS 平台的 Traccar Client 应用。它通过 OsmAnd 协议上报数据,该协议默认监听 5055 端口。应用的设置决定了电池续航和数据行数。Distance 要求在移动时每隔 N 米更新一次。Interval 在距离为 0 时提供基于时间的上报(仅适用于 Android),或者在精度设置为最高时生效。Angle 在精度设置为最高时,根据航向变化(以度为单位)触发更新。Stationary Heartbeat 涵盖了设备静止时的处理方式。Traccar 的官方文档指出,由于手机端会自行决策,因此无法保证上述设置的精确结果。

Traccar 自带一个嵌入式 H2 数据库,以便安装后无需配置即可运行,但该项目不建议在生产环境中使用 H2。其文档涵盖了 MySQL、MariaDB 和 PostgreSQL 作为替代方案,并建议在大规模部署时使用基于 PostgreSQL 构建的时序数据库 TimescaleDB。请在积累历史数据之前迁移数据库,因为如果后续想要保留这些历史记录,则必须将现有数据迁移到新数据库中。

Traccar 的局限性在于:它是一个用于实时监控的控制台。其报告功能侧重于车队报告、行程、停靠点和汇总,因此查看你过去一年的周末行程时,结果更像是一次查询输出,而非时间轴。

OwnTracks:手机应用、Recorder 和 Frontend

OwnTracks 是一种简洁的经典配置。应用每次判断设备已移动时,都会发布一小段 JSON 载荷。它可以通过 MQTT(消息队列遥测传输)或普通 HTTP 发布。在 HTTP 模式下,端点 URL 的格式为 http[s]://[user[:password]@]host[:port]/path,使用 HTTP Basic 进行身份验证。项目强烈推荐使用 https:// 方案。对于 OwnTracks Recorder,路径为 /pub。

监测模式比任何服务器设置都重要。Quiet 仅在您发出请求时发布。Manual 会启用区域监测,并以低功耗方式请求位置。Significant 是常规的自动模式。在 iOS 上,Move 会在设备移动 locatorDisplacement 米或经过 locatorInterval 秒后立即发布,以先满足的条件为准;默认值分别为 100 米和 300 秒。在 Android 上,Move 默认每 10 秒请求一次定位。OwnTracks 文档说明,Move 模式的耗电量相当于导航应用,并建议在出行期间或充电时使用,而不要作为日常设置。

OwnTracks Recorder 会存储收到的数据并提供一个小型地图。独立的 OwnTracks Frontend 则在其上提供更完整的 Web 界面,包括热力图、日期范围筛选,以及以点或线绘制的历史轨迹。很多人从未安装 Recorder,因为无论应用指向 Recorder、Dawarich 还是 Home Assistant,载荷都完全相同。这正是从这里开始的原因:该应用是一个稳定、简单的生产端,之后可以随时更换消费端。

Dawarich:自托管的 Google Maps Timeline

Dawarich 使用 AGPL-3.0 许可,并通过 Docker Compose 文件运行。当前的默认安装包含 3 个容器:运行 Rails 应用及其内部 Sidekiq 后台任务的容器、PostgreSQL 容器和 Redis 容器。应用提供 3000 端口。可导入的数据源包括 Google Maps Timeline、OwnTracks、Strava、Immich、GPX 和 GeoJSON 文件,以及照片中的 EXIF 数据。正是这组导入来源让它成为时间线,而不是实时地图,因为它可以导入早于服务器部署时间的历史数据。

数据接收使用携带账户页面中 API key 的 HTTP 端点。OwnTracks 向 /api/v1/owntracks/points?api_key=... 发送数据,Overland 向 /api/v1/overland/batches?api_key=... 发送数据。GPSLogger 复用 OwnTracks 端点。

请注意该 key 的传输位置。它位于查询字符串中,而 nginx 的默认日志格式会写入完整请求行,因此每个位置点的 key 都会以明文写入 /var/log/nginx/access.log。应将该日志视为机密。如果将日志发送到任何集中式系统,请轮换该 key;不要将可用的 URL 粘贴到支持工单或讨论串中。

对于 compose 文件本身、卷和重启策略,请参阅在 VPS 上运行 compose 的容器机制。本页内容到决策为止。

Home Assistant:擅长判断是否在家,但不适合保存历史记录

如果您已经运行 Home Assistant,就已经具备设备跟踪功能。配套应用会报告位置,OwnTracks 集成会提供 webhook URL 和加密密钥,供您粘贴到应用中。配置 MQTT 后,该集成会监听 MQTT 消息,而不是 HTTP。

限制在于数据保留时间。Home Assistant 的 recorder 默认设置为 purge_keep_days: 10,自动清理任务每天本地时间 04:12 运行,以防数据库无限增长。这个默认值适合家庭自动化数据库,但不适合位置归档。Home Assistant 可以回答“现在有人在家吗”,但要回答“我在 3 月 14 日去过哪里”,就必须在历史记录被删除前保留它:提高 purge_keep_days,禁用 auto_purge,或将同一数据流发送到能够长期保留数据的系统。保留更多历史记录会增大 recorder 数据库;如果禁用 auto_purge,文档建议自行定期执行 recorder.purge 调用。

连续跟踪还是临时共享?

连续跟踪意味着应用全天发布位置,无论您是否在移动;它建立的历史记录就是主要用途。临时共享意味着人们在行程期间相互查看位置,而历史记录只是没人要求的副作用。同一款软件可以通过不同设置满足这两种用途。

对于连续跟踪,优先使用基于位移的上报,而不是较短的定时器;将数据库存储在实际会进行备份的存储设备上;并在第一天确定数据保留期限,不要等到磁盘已满时才决定。对于临时共享,只在需要时提高上报频率,之后将手机恢复为低功耗模式。OwnTracks 将此作为应用内的控制项,Traccar Client 则通过距离和时间间隔字段提供相同功能。

如果您需要的是单次行程的两小时共享链接,请在确定方案前查看所选服务器的发行说明。Traccar 提供临时设备共享链接,Dawarich 提供实时位置共享链接,并支持设置可选密码、到期日期和立即撤销。

是否确实需要 MQTT broker?

先不要使用 broker。HTTP 模式只需要 URL、密码和 TLS(传输层安全),上文列出的每台服务器都支持这种模式。当多个对象需要在同一时刻使用同一数据流时,broker 才有必要。例如,Home Assistant 根据某个区域做出响应,同时记录器写入历史记录;或者让家庭成员彼此可见。

MQTT 是一种发布-订阅协议,Mosquitto 是常用的 broker。它的默认监听器使用 1883 端口传输明文;请配置使用 8883 端口的 TLS 监听器,并且只对外暴露该监听器。访问控制按主题执行,因此可以允许某个账户发布到 owntracks/alice/phone,但不允许读取其他任何主题。这才是家庭环境使用 MQTT 的主要理由:broker 在应用层以下强制执行谁可以看到谁,因此应用程序缺陷无法扩大可见范围。

代价是增加一个服务,同时需要管理它自己的证书、用户列表和故障模式。broker 停止接受连接时,表现得就像手机没有信号一样,而这两种情况都不会告诉你具体原因。

一部手机会产生多少行位置数据?

以下数字为算术推算结果,而非实际测量值。这些数字假设报告间隔固定,每份报告产生一行数据,且不考虑其他变量。

图表Position rows per phone at a fixed reporting interval (arithmetic)
此图表背后的数据
[
  {
    "label": "Every 30 seconds",
    "points_30d": "86,400",
    "points_365d": "1,051,200"
  },
  {
    "label": "Every 60 seconds",
    "points_30d": "43,200",
    "points_365d": "525,600"
  },
  {
    "label": "Every 5 minutes",
    "points_30d": "8,640",
    "points_365d": "105,120"
  },
  {
    "label": "Every 15 minutes",
    "points_30d": "2,880",
    "points_365d": "35,040"
  }
]

如果手机每分钟上报一次,每月会产生 43,200 行数据,每年产生 525,600 行数据。若将间隔延长至十五分钟,则每年产生 35,040 行数据。实际应用的情况更为复杂,因为它们不仅基于时间上报,还会根据位移触发上报,且在手机静止时会停止报告。因此,请将这些行数视为固定间隔下的示例,而非预测值。

对于 PostgreSQL 而言,每年五十万行数据量很小。最先遇到的瓶颈是渲染:如果要求地图以全分辨率渲染一年的轨迹点,浏览器在数据库察觉到压力之前就会卡死。这就是为什么此类应用会将历史记录聚合为“行程”和“地点”的原因。请在自己的服务器上测量实际数据量,不要盲目相信博客文章中的数字:

SELECT pg_size_pretty(pg_total_relation_size('tc_positions'));

以上是 Traccar 在 PostgreSQL 中的 positions 表。在您选择的服务器上正常使用一个月后,运行相应的查询语句,然后乘以 12 即可。Home Assistant 默认会自动删除旧的历史记录。请在表规模尚小时制定保留策略,并确保备份涵盖整个数据库,而不仅仅是配置文件,因为位置历史记录无法通过其他任何方式恢复。

电池消耗由手机决定,而不是服务器决定

自托管不会改变这一点。操作系统决定何时唤醒 GPS、后台应用可以运行多久,以及应用能否持续运行到第二天。Android 会积极挂起后台任务,iOS 则会提供明显的位置变化,而不是连续的位置数据。服务器无法影响这些行为,因此,在应用中设置更短的上报间隔只是提出请求,手机会自行决定如何处理。

您能控制的是手机上的设置:授予应用“始终允许”的后台位置权限,将跟踪应用排除在电池优化之外,并根据当天的使用情况选择合适的上报模式。整周启用移动模式,手机通常会在下午 4 点前耗尽电量。

服务器端的表现是突然写入一批带有旧时间戳的记录。OwnTracks 以及启用了离线缓存设置的 Traccar Client,会在离线时暂存位置点,并在网络恢复后批量发送,因此写入时间和定位时间是不同的值。当地图在城市中画出一条直线时,这表示定位点之间存在缺失,而不是那里有一条道路。

服务端:TLS 与认证接入路径

手机需要一个可解析的主机名以及一个它信任的证书。自签名证书是导致全新安装无法接收任何数据最常见的原因:应用在 TLS 握手阶段失败并直接放弃,而服务器日志保持空白,因为请求从未完成。空白日志看起来像是手机端的问题,但事实并非如此。

有两种简洁的方案。第一种是在 nginx 中使用真实证书终止 TLS,即 在 nginx 前端使用 Let's Encrypt 证书,并开放 80 和 443 端口。80 端口必须保持可访问,因为 certbot 的 nginx 插件通过 HTTP-01 挑战验证域名,而 Let's Encrypt 仅在 80 端口执行此操作,因此应将其重定向至 HTTPS 而非关闭。只有切换到 DNS-01 或 TLS-ALPN-01 挑战,才允许仅运行 443 端口。或者,使用 Cloudflare Tunnel 使公网 IP 上无任何监听,从而不暴露任何入站端口,这适用于 Dawarich 和 OwnTracks,因为它们的接入方式是普通 HTTP。

隧道方案有一个限制。Traccar 的 OsmAnd 协议基于 HTTP,因此手机客户端可以顺利通过反向代理或隧道。专用 GPS 硬件使用的二进制协议是基于特定端口的原始 TCP 或 UDP,这些协议需要真正开放的端口,且必须在 VPS 防火墙以及服务商独立的网络防火墙(大多数主机商的独立控制面板)上同时开启。

一旦服务端响应,请使用一个请求来验证路径,而不是直接从应用端猜测:

curl -si -u alice:secret -H 'Content-Type: application/json' \
  -d '{"_type":"location","lat":51.5,"lon":-0.12,"tst":1788480000}' \
  https://track.example.com/pub | head -1

正常工作的端点会返回 2xx 状态码。401 表示服务器拒绝了凭据或未收到凭据,但传输层是正常的。如果在出现任何状态行之前发生 curl 错误,则需要检查其错误信息:DNS 问题、连接被拒绝、超时和 TLS 失败是不同的问题,因此请在操作应用之前先修复报告的问题。

开放的摄入端点会导致位置泄露

没有身份验证的摄入 URL 会将你的位置信息暴露给任何发现它的人,而且确实有人会发现它。

  • 任何持有该 URL 的人都可以向你的历史记录中写入坐标点。虚假坐标点很难察觉,且清理起来非常繁琐。
  • URL 并非机密。它存在于手机的应用设置中、反向代理的访问日志中、如果你曾在浏览器标签页中测试过它,它也会出现在浏览器历史记录中,以及你在寻求帮助时附带的任何截图中。
  • 未受保护的读取 API(例如 OwnTracks Recorder 的 /api/0/last)会将你的最新位置提供给任何查询它的人。
  • 无论你做什么,主机名都是公开的。新签发的证书会在几分钟内出现在证书透明度日志中,因此即使你从未发布过该地址,它依然是可以被发现的。

对于 OwnTracks,请使用基于 TLS 的 HTTP Basic 认证;对于 Dawarich,请使用 API 密钥;对于 Traccar,请使用带有唯一设备标识符的账户模型。将管理界面置于与摄入路径相同的身份验证保护之下,因为在管理界面中可以读取完整的轨迹。一周后,检查一下都有谁在尝试访问:

sudo awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -20

列表中应以你手机的移动 IP 地址为主。任何其他高频访问的 IP 都值得关注,在 Nginx 中对位置摄入进行限速是没有成本的。

追踪器也可能静默失效。容器停止运行,手机持续缓存数据,直到几周后你发现行程缺失时才会察觉。请设置容器健康检查或 systemd OnFailure=,将其指向 你自己的 ntfy 服务器,这样即使在负责上报的手机上,你也能收到静默失效的通知。

谁还能看到这条轨迹,以及如何强制执行

Traccar 通过用户和设备权限控制访问:账号只能看到管理员授予它的设备,API 使用会话或令牌。OwnTracks over MQTT 在 broker 中通过主题 ACL 强制执行访问控制。这是这些方案中最强的一种,因为无法订阅某个主题的账号,无论应用执行什么操作,都无法读取该主题。OwnTracks over HTTP 没有等效的控制层,因此端点后面的组件就是完整的访问控制机制。Dawarich 还支持家庭实时位置共享,每位成员都可以控制自己的共享设置。

家庭追踪既涉及同意,也涉及技术。所有发布手机位置的人都应知道手机正在发布位置,以及如何停止发布。个人无法关闭的追踪功能不能算家庭功能。

自托管无法解决的问题

  • 手机操作系统决定何时唤醒 GPS,因此电池耗电和轨迹中的缺口主要由手机造成,而不是服务器。
  • Google 已更改 Timeline 数据的导出方式。计划迁移前,请先阅读 Dawarich 当前的导入文档,因为 Google 今天提供的文件,已经不是人们两年前导入的文件。
  • 每次请求都会携带您的移动 IP 地址到达端点,中间经过的每个网络也都能看到该地址。自托管只会改变由谁保存这条记录,不会消除这条记录。
  • 位置历史无法替代。请备份数据库,并至少恢复一次以确认备份有效;同时对备份副本加密,因为它是服务器上最敏感的文件。

FAQ

哪款自托管应用可以替代 Google Maps Timeline?

Dawarich。它是 Google Timeline 的自托管替代方案,可导入 Google Maps Timeline 导出数据,以及 OwnTracks、Strava、Immich、GPX 和 GeoJSON 数据、照片 EXIF 信息,并将历史记录呈现为地点和行程,而不是实时地图。Traccar 也可以存储相同的定位点,但其界面是车队控制台,报告也是车队报告。规划迁移前,请查看 Dawarich 的导入文档,确认它要求的导出格式,因为 Google 的导出格式发生过变化。

不使用 MQTT broker 可以使用 OwnTracks 吗?

可以。将应用设置为 HTTP 模式,并为其提供格式为 http[s]://[user[:password]@]host[:port]/path 的 URL;对于 OwnTracks Recorder,该 URL 为 /pub。它会发送相同的 JSON 负载,并使用 HTTP Basic 进行身份验证;OwnTracks 强烈建议使用 https:// 方案。等到两个服务需要同时使用同一数据流,或需要按主题控制访问权限时,再添加 broker,让 broker 决定哪些用户可以查看哪些数据。

一年的位置历史记录需要多少存储空间?

应按行数规划,而不是按 GB 规划。每部手机每分钟上报一次,一年会产生 525,600 行;每十五分钟上报一次,则会产生 35,040 行。对于 PostgreSQL 来说,两者都不大。实际限制在于浏览器在一张地图上绘制一年中的所有定位点,因此这些应用会进行聚合。运行一个月后,使用 pg_total_relation_size 测量自己的表大小,再乘以十二。

为什么我的位置历史记录存在缺口?

手机操作系统决定何时唤醒 GPS,以及何时停止后台应用,因此大多数缺口都源于此。授予应用始终允许的后台位置权限,将其排除在电池优化之外,并检查上报模式。在 iOS 上使用 OwnTracks 时,Move 模式每移动 locatorDisplacement 米或经过 locatorInterval 秒发布一次,默认值分别为 100 米和 300 秒;在 Android 上,应用默认每 10 秒请求一次定位。无论哪种情况,其耗电量都相当于导航应用。如果定位记录延迟后成批到达,并携带较早的时间戳,说明离线缓冲区正在刷新。也就是说,定位已经完成,只是上传被延迟了。

仅使用秘密 URL 足以保护位置接收端点吗?

不够。未进行身份验证的接收端点允许任何获知 URL 的人向你的历史记录写入虚假定位点,而 URL 并不是秘密:它会出现在应用设置、反向代理访问日志、浏览器历史记录以及你分享的任何截图中。仅凭主机名也可以发现该端点,因为新证书签发后不久就会出现在证书透明度日志中。应通过 TLS 使用 HTTP Basic 或 API key,限制接收路径的请求速率,并让管理界面使用相同的身份验证保护。

这篇文章对您有帮助吗?

#自托管#privacy#traccar#owntracks#dawarich#gps