mauriceboe/TREK

GitHub: mauriceboe/TREK

一款功能丰富的自托管实时协作旅行规划平台,集成地图、预算、打包清单、预订管理和 AI 辅助等一站式旅行规划能力。

Stars: 6117 | Forks: 587

TREK
Your trips. Your plan. Your server. 一个自托管的实时协作旅行规划器 —— 内置地图、预算、打包清单、旅行日记和 AI 功能。
演示   Docker   Discord   路线图
Ko-fi   BMAC
许可证 最新发布 Docker 拉取量 Star 数
TREK — 60-second tour

Dashboard Trip planner with 3D map Journey journal Costs · expense splitting Atlas · visited countries Vacay planner Trip planner · day plan and route Admin panel
## 你将获得什么 TREK feature tiles
查看所有功能
#### 🧭 行程规划 - **拖拽式规划器** — 将地点整理为每日行程,支持重新排序和跨天移动 - **交互式地图** — Leaflet 或 Mapbox GL,支持 3D 建筑、地形、照片标记、聚类和路线可视化 - **地点搜索** — Google Places(照片、评分、营业时间)或 OpenStreetMap(免费,无需 API key) - **地点导入** — 共享的 Google Maps / Naver Maps 列表,以及 GPX 和 KML/KMZ/GeoJSON 地图文件 - **每日笔记** — 带时间戳和图标标签的笔记,支持拖拽重新排序 - **路线优化** — 自动对地点进行排序并导出到 Google Maps - **天气预报** — 通过 Open-Meteo 获取 16 天预报(无需 key)+ 历史气候后备方案 - **类别筛选** — 在地图上仅显示匹配的图钉 #### 🧳 旅行管理 - **预订** — 航班、住宿、餐厅,包含状态、确认号、文件;支持从预订确认邮件和 PDF 导入([KDE Itinerary](https://invent.kde.org/pim/kitinerary)) - **费用** — 跟踪并分摊旅行费用(Splitwise 风格):提供按人/按天的明细、结算和多币种支持 - **打包清单** — 分类、模板、用户分配、进度追踪 - **行李追踪** — 可选的重量追踪,采用 iOS 风格的重量分布展示 - **文档管理器** — 将文档、票据、PDF 附加到行程/地点/预订(每个 ≤ 50 MB) - **PDF 导出** — 将完整行程计划导出为带有封面、图片和笔记的 PDF
#### 👥 协作 - **实时同步** — WebSocket。所有已连接用户的更改都会立即显示 - **多用户行程** — 邀请成员并设置基于角色的访问权限 - **邀请链接** — 一次性或可重复使用的链接,支持设置过期时间 - **SSO (OIDC)** — 支持 Google、Apple、Authentik、Keycloak 或任何 OIDC 提供商 - **2FA** — TOTP + 备份代码 - **Passkeys** — 无密码 WebAuthn 登录(指纹/面部/PIN/安全密钥),管理员可切换开关 - **协作套件** — 群聊、共享笔记、投票、每日签到 #### 📱 移动端与 PWA - **可安装** — 适用于 iOS 和 Android,直接从浏览器安装,无需 App Store - **离线支持** — Service Worker 通过 Workbox 缓存瓦片、API 和上传内容 - **原生体验** — 全屏独立窗口、主题化状态栏、启动画面 - **触摸优化** — 针对移动设备的特定布局,处理安全区域
#### 🧩 附加组件(管理员可切换) - **清单** — 包含模板的打包清单和待办事项、成员分配、可选的行李追踪 - **费用** — 带有分摊和结算(谁欠谁)功能的费用追踪器,支持多币种 - **文档** — 在行程、地点和预订上附加文件 - **协作** — 聊天、笔记、投票、每日出勤情况 - **Vacay** — 个人假期规划器,包含日历、100+ 个国家的节假日、结转追踪 - **Atlas** — 已访问国家的世界地图、愿望清单、旅行统计数据、连续记录追踪、液态玻璃 UI - **Journey** — 杂志风格的旅行日记,包含条目、照片(Immich/Synology)、地图、心情 - **AirTrail** — 连接自托管的 AirTrail 实例,将航班导入并同步到预订中 - **MCP** — 通过 OAuth 2.1 将 TREK 暴露给 AI 助手 #### 🤖 AI / MCP - **内置 MCP server** — OAuth 2.1 身份验证。150+ 工具,30 个资源 - **细粒度作用域** — 跨 13 个权限组的 27 个 OAuth 作用域 - **全面自动化** — AI 可以创建行程、规划日程、生成打包清单、管理预算、标记已访问的国家 - **预置提示词** — `trip-summary`、`packing-list`、`budget-overview` - **组件感知** — 当 Atlas、Collab、Vacay 组件开启时会将它们暴露出来
#### ⚙️ 管理与定制 - **仪表盘视图** — 卡片网格或紧凑列表 · **暗黑模式** — 包含匹配状态栏的完整主题 - **20 种语言** — EN, DE, ES, FR, IT, NL, HU, RU, ZH, ZH-TW, PL, CS, AR (RTL), BR, ID, TR, JA, KO, UK, GR - **管理面板** — 用户、邀请、打包模板、分类、附加组件、API key、备份、GitHub 历史 - **通知** — 跨电子邮件 (SMTP)、webhook、ntfy 和应用内通知中心的用户个性化偏好设置 - **自动备份** — 计划执行并支持配置保留策略 · **单位** — °C/°F、12小时/24小时制、地图瓦片来源、默认坐标

## 30 秒快速开始 ``` ENCRYPTION_KEY=$(openssl rand -hex 32) docker run -d -p 3000:3000 \ -e ENCRYPTION_KEY=$ENCRYPTION_KEY \ -v ./data:/app/data -v ./uploads:/app/uploads mauriceboe/trek ``` 打开 `http://localhost:3000`。首次启动时,TREK 会初始化一个管理员账户 —— 如果你设置了 `ADMIN_EMAIL` / `ADMIN_PASSWORD` 就会使用它们,否则凭据将打印到容器日志中(`docker logs trek`)。
  ·  Docker Compose  ·  Helm / Kubernetes  ·  安装为 PWA  ·  反向代理  ·  

## 技术栈
![Node.js](https://img.shields.io/badge/Node.js_22-339933?style=flat-square&logo=node.js&logoColor=white) ![NestJS](https://img.shields.io/badge/NestJS_11-E0234E?style=flat-square&logo=nestjs&logoColor=white) ![SQLite](https://img.shields.io/badge/SQLite-003B57?style=flat-square&logo=sqlite&logoColor=white) ![React](https://img.shields.io/badge/React_19-61DAFB?style=flat-square&logo=react&logoColor=black) ![Vite](https://img.shields.io/badge/Vite-646CFF?style=flat-square&logo=vite&logoColor=white) ![TypeScript](https://img.shields.io/badge/TypeScript-3178C6?style=flat-square&logo=typescript&logoColor=white) ![Tailwind](https://img.shields.io/badge/Tailwind-06B6D4?style=flat-square&logo=tailwindcss&logoColor=white) ![Leaflet](https://img.shields.io/badge/Leaflet-199900?style=flat-square&logo=leaflet&logoColor=white) ![Docker](https://img.shields.io/badge/Docker-2496ED?style=flat-square&logo=docker&logoColor=white)
通过 WebSocket (`ws`) 进行实时同步。后端基于 NestJS 11。状态管理使用 Zustand。身份验证通过 JWT + OAuth 2.1 + OIDC + Passkeys (WebAuthn) + TOTP MFA 实现。天气数据通过 Open-Meteo 获取(无需 key)。地图使用 Leaflet 和 Mapbox GL。

Docker Compose (生产环境)

带有安全默认设置的完整 compose 示例 ``` services: app: image: mauriceboe/trek:latest container_name: trek read_only: true security_opt: - no-new-privileges:true cap_drop: - ALL cap_add: - CHOWN - SETUID - SETGID tmpfs: - /tmp:noexec,nosuid,size=64m ports: - "3000:3000" environment: - NODE_ENV=production - PORT=3000 - ENCRYPTION_KEY=${ENCRYPTION_KEY:-} # generate with: openssl rand -hex 32 - TZ=${TZ:-UTC} - LOG_LEVEL=${LOG_LEVEL:-info} - ALLOWED_ORIGINS=${ALLOWED_ORIGINS:-} - APP_URL=${APP_URL:-} # required for OIDC + email links # - FORCE_HTTPS=true # behind a TLS-terminating proxy # - TRUST_PROXY=1 # - OIDC_ISSUER=https://auth.example.com # - OIDC_CLIENT_ID=trek # - OIDC_CLIENT_SECRET=supersecret # - OIDC_DISPLAY_NAME=SSO # - OIDC_ADMIN_CLAIM=groups # - OIDC_ADMIN_VALUE=app-trek-admins volumes: - ./data:/app/data - ./uploads:/app/uploads restart: unless-stopped healthcheck: test: ["CMD", "wget", "-qO-", "http://localhost:3000/api/health"] interval: 30s timeout: 10s retries: 3 start_period: 15s ``` 然后: ``` docker compose up -d ``` **HTTPS 说明:** `FORCE_HTTPS=true` 是可选的 —— 它会添加 301 重定向、HSTS、CSP upgrade-insecure-requests,并强制使用 `secure` cookie 标志。请仅在 TLS 终结反向代理后方使用它。`TRUST_PROXY=1` 用于告知服务器前方的代理数量,以便真实的客户端 IP 和 `X-Forwarded-Proto` 正常工作。

Helm (Kubernetes)

``` helm repo add trek https://mauriceboe.github.io/TREK helm repo update helm install trek trek/trek ``` 相关配置值请参见 [`charts/README.md`](https://github.com/mauriceboe/TREK/blob/main/charts/README.md)。

安装为应用 (PWA)

TREK 可作为 Progressive Web App 运行 —— 无需 App Store。 1. 在浏览器中打开 TREK(需要 HTTPS) 2. **iOS**:分享 ▸ *添加到主屏幕* 3. **Android**:菜单 ▸ *安装应用*(或 *添加到主屏幕*) 之后 TREK 将以其专属图标全屏启动,就像原生应用一样。
## 更新 **Docker Compose:** ``` docker compose pull && docker compose up -d ``` **Docker run** — 复用原有的卷路径: ``` docker pull mauriceboe/trek docker rm -f trek docker run -d --name trek -p 3000:3000 -v ./data:/app/data -v ./uploads:/app/uploads --restart unless-stopped mauriceboe/trek ``` 你的数据保留在挂载的 `data` 和 `uploads` 卷中 —— 更新绝对不会触及它们。

轮换加密密钥

如果你需要轮换 `ENCRYPTION_KEY`(例如,从通过 `JWT_SECRET`派生加密密钥的版本升级时): ``` docker exec -it trek node --import tsx scripts/migrate-encryption.ts ``` 脚本在进行更改前会创建一个带有时间戳的数据库备份,并提示输入旧密钥和新密钥(输入内容不会回显)。

反向代理

在生产环境中,请将 TREK 置于 TLS 终结反向代理之后。TREK 使用 WebSocket 进行实时同步,因此代理**必须**支持在 `/ws` 上进行 WebSocket 升级。
Nginx ``` server { listen 80; server_name trek.yourdomain.com; return 301 https://$host$request_uri; } server { listen 443 ssl http2; server_name trek.yourdomain.com; ssl_certificate /etc/ssl/fullchain.pem; ssl_certificate_key /etc/ssl/privkey.pem; # 500 MB covers backup-restore uploads (capped at 500 MB server-side). client_max_body_size 500m; location / { proxy_pass http://localhost:3000; proxy_http_version 1.1; 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; } location /ws { proxy_pass http://localhost:3000; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_set_header Host $host; proxy_read_timeout 86400; } } ```
Caddy ``` trek.yourdomain.com { reverse_proxy localhost:3000 } ``` Caddy 会自动处理 TLS 和 WebSocket。

## 环境变量
完整参考
| 变量 | 描述 | 默认值 | |----------|-------------|---------| | **核心** | | | | `PORT` | Server 端口 | `3000` | | `NODE_ENV` | 环境(`production` / `development`) | `production` | | `ENCRYPTION_KEY` | 用于存储的机密(API key、MFA、SMTP、OIDC)的静态加密密钥。建议:使用 `openssl rand -hex 32` 生成。如果未设置,将回退至 `data/.jwt_secret`(现有安装)或自动生成密钥(全新安装)。 | 自动 | | `TZ` | 用于日志、提醒和 cron 任务的时区(例如 `Europe/Berlin`) | `UTC` | | `LOG_LEVEL` | `info` = 简洁的用户操作,`debug` = 详细的调试信息 | `info` | | `DEFAULT_LANGUAGE` | 未保存偏好的用户在登录页看到的默认语言。会优先自动检测浏览器/操作系统语言;此项为回退值。支持:`de`, `en`, `es`, `fr`, `hu`, `nl`, `br`, `cs`, `pl`, `ru`, `zh`, `zh-TW`, `it`, `ar`, `id`, `tr`, `ja`, `ko`, `uk`, `gr` | `en` | | `ALLOWED_ORIGINS` | 用于 CORS 和电子邮件链接的逗号分隔来源 | same-origin | | `FORCE_HTTPS` | 可选。设为 `true` 时:将 HTTP 301 重定向至 HTTPS、发送 HSTS、添加 CSP `upgrade-insecure-requests`、强制 session cookie 加上 `secure` 标记。适用于处于 TLS 终结反向代理后方的情况。需要配合 `TRUST_PROXY` 使用。 | `false` | | `HSTS_INCLUDE_SUBDOMAINS` | 设为 `true` 时:将 `includeSubDomains` 指令添加到 HSTS 标头,将 HTTPS 强制扩展到所有子域。仅在 HSTS 处于激活状态时生效(`FORCE_HTTPS=true` 或 `NODE_ENV=production`)。如果在同级子域上通过纯 HTTP 运行其他服务,请保持为 `false`。 | `false` | | `COOKIE_SECURE` | 控制 `trek_session` cookie 上的 `secure` 标志。自动派生:当 `NODE_ENV=production` 或 `FORCE_HTTPS=true` 时开启。逃生通道:设为 `false` 以允许通过纯 HTTP 传递 session cookie。生产环境中不推荐使用。 | 自动 | | `SESSION_DURATION` | **未勾选“记住我”**(默认情况)时登录 session 的有效时长:设置 `trek_session` JWT 的 `exp`,并发布一个浏览器 session cookie(浏览器关闭时清除)。接受 `ms` 格式字符串:`1h`, `12h`, `7d`, `30d`, `90d`。无效值会在启动时发出警告并回退到默认值。 | `24h` | | `SESSION_DURATION_REMEMBER` | 登录时**勾选“记住我”**的 session 有效时长:一个生命周期更长的 JWT 以及一个能在浏览器重启后存活的持久化 `trek_session` cookie。格式和启动时的回退行为与 `SESSION_DURATION` 相同。 | `30d` | | `TRUST_PROXY` | 受信任的反向代理数量。告知服务器从 `X-Forwarded-For` 读取客户端 IP,从 `X-Forwarded-Proto` 读取协议。在生产环境中默认为 `1`;除非手动设置,否则在开发环境中关闭。 | `1` | | `ALLOW_INTERNAL_NETWORK` | 允许向私有 / RFC-1918 IP 发送出站请求(例如局域网上的 Immich)。回环地址和链路本地地址仍然被阻止。 | `false` | | `APP_URL` | 此实例的公开 base URL(例如 `https://trek.example.com`)。启用 OIDC 时必填;用作邮件通知链接的 base。 | — | | **OIDC / SSO** | | | | `OIDC_ISSUER` | OpenID Connect 提供商 URL | — | | `OIDC_CLIENT_ID` | OIDC client ID | — | | `OIDC_CLIENT_SECRET` | OIDC client secret | — | | `OIDC_DISPLAY_NAME` | SSO 登录按钮上显示的标签 | `SSO` | | `OIDC_ONLY` | 强制仅使用 SSO 模式:禁用密码登录和注册,无视“管理 > 设置”。首次 SSO 登录的用户将成为管理员。 | `false` | | `OIDC_ADMIN_CLAIM` | 用于识别管理员用户的 OIDC claim | — | | `OIDC_ADMIN_VALUE` | 授予管理员角色的 OIDC claim 值 | — | | `OIDC_SCOPE` | 空格分隔的 OIDC 作用域。**完全替换**默认值 —— 必须始终包含 `openid email profile`。 | `openid email profile` | | `OIDC_DISCOVERY_URL` | 覆盖自动构建的 OIDC 发现端点(例如 Authentik:`.../application/o/trek/.well-known/openid-configuration`) | — | | **初始设置** | | | | `ADMIN_EMAIL` | 首次启动时首个管理员的电子邮件。必须与 `ADMIN_PASSWORD` 一起设置。如果省略其中任何一个,将会在服务器日志中打印一个随机密码。一旦存在用户后即失效。 | `admin@trek.local` | | `ADMIN_PASSWORD` | 首次启动时首个管理员的密码。与 `ADMIN_EMAIL` 配对使用。 | 随机 | | **其他** | | | | `DEMO_MODE` | 启用演示模式(每小时重置数据) | `false` | | `MCP_RATE_LIMIT` | 每个用户每分钟的最大 MCP API 请求数 | `300` | | `MCP_MAX_SESSION_PER_USER` | 每个用户的最大并发 MCP 会话数 | `20` |

## 数据与备份 - **数据库** — SQLite,存储在 `./data/travel.db` - **上传文件** — 存储在 `./uploads/` - **日志** — `./data/logs/trek.log`(自动轮换) - **备份** — 可通过管理面板创建和恢复 - **自动备份** — 可在管理面板配置计划与保留策略
## 数据来源 Atlas 地图中的国家级和次国家级(省/县)边界来源于 [**geoBoundaries**](https://www.geoboundaries.org/) (Runfola et al., 2020),基于 [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/) 许愿。完整的第三方版权说明请参见 [NOTICE.md](NOTICE.md)。 ## 许可证 TREK 采用 [AGPL v3](LICENSE) 许可协议。可自由自托管用于个人或公司内部使用。如果你对 TREK 进行了修改并作为网络服务提供给第三方,你的修改必须以相同的许可协议开源。
标签:Docker, MITM代理, PWA, 人工智能, 协同办公, 地图集成, 安全防御评估, 旅游规划, 用户模式Hook绕过, 自动化攻击, 自托管, 请求拦截