Files
gitlab-instance-0a899031_cn…/NOMADCNA_PROJECT_DEPLOYMENT_REPORT.md
root b2fc70b403 s
2026-06-06 23:25:03 +08:00

1097 lines
37 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 游牧中国 NomadCNA 项目与服务器部署报告
生成时间2026-06-06 23:16 CST
服务器时区Asia/Shanghai / CST +0800
项目路径:`/home/ubuntu/gitlab-instance-0a899031_cnomadcna`
Git 分支:`test2`
最新提交:`00b1c8e`2026-06-06 23:05:17 +0800
报告范围:当前仓库代码、前端/后端/数据服务、服务器上实际运行的相关服务、反向代理、端口、构建状态、运维风险与后续建议。
敏感信息处理本报告只记录环境变量名、用途、路径、端口和域名不记录任何密码、Token、Access Key、Secret、数据库连接串原文。
## 1. 项目定位
NomadCNA / 游牧中国是一个面向数字游民的中文优先、英文可切换的一站式网站,当前定位可以概括为:
- 数字游民城市决策平台:展示中国城市的成本、网速、安全、气候、社区活跃度、标签和详情。
- 数字游民社区入口:提供报名、登录、会员、资料录入、同城活动、交友匹配、站内消息。
- 数字游民服务市场:提供共享办公、城市落地顾问、保障类服务、赏金任务、反馈和咨询线索。
- 数字游民内容与工具电子书、视频、报告、AI 助手、FIRE/汇率/签证/气候工具。
- 生产部署站点:当前主域为 `nomadro.cn` / `www.nomadro.cn`PocketBase 为 `pocketbase.nomadro.cn`FastAPI 为 `api.nomadro.cn`
当前项目已经不是纯前端展示站,已经具备“前端 + Next.js API + FastAPI + PocketBase + 支付 + 上传 + 消息 + 监控”的完整早期产品架构。
## 2. 访问地址与部署入口
### 2.1 对外域名
| 域名 | 当前用途 | 反向代理目标 | HTTPS 状态 |
| --- | --- | --- | --- |
| `https://nomadro.cn` | 游牧中国主站 | `127.0.0.1:4002` | 已配置证书 |
| `https://www.nomadro.cn` | 游牧中国主站 | `127.0.0.1:4002` | 已配置证书 |
| `http://api.nomadro.cn` | FastAPI 后端 API | `127.0.0.1:8000` | 当前只看到 HTTP 配置 |
| `https://pocketbase.nomadro.cn` | PocketBase REST API 与后台 | `127.0.0.1:8090` | 已配置证书 |
| `https://umami.nomadro.cn` | Umami 统计 | `127.0.0.1:9280` | 已配置证书 |
| `http://ntfy.nomadro.cn` | ntfy 推送服务 | `127.0.0.1:9180` | 当前只看到 HTTP 配置 |
| `http://netdata.nomadro.cn` | Netdata 监控面板 | `127.0.0.1:19999` | 当前只看到 HTTP 配置,已配置 Basic Auth |
### 2.2 本机端口
| 端口 | 监听地址 | 服务 | 说明 |
| --- | --- | --- | --- |
| `4002` | `*:4002` | NomadCNA Next.js | 生产前端systemd 管理 |
| `8000` | `127.0.0.1:8000` | NomadCNA FastAPI | 后端 APIsystemd 管理 |
| `8090` | `127.0.0.1:8090` | PocketBase | 本站主数据服务 |
| `9280` | `127.0.0.1:9280` | Umami | 统计分析服务 |
| `9180` | `127.0.0.1:9180` | ntfy Docker 容器 | 通知推送服务 |
| `19999` | `127.0.0.1:19999` | Netdata | 宿主机监控 |
| `80/443` | `0.0.0.0` | Nginx | 站点反向代理 |
| `3306` | `0.0.0.0` | MariaDB/MySQL | 宝塔/其他服务使用,非当前 NomadCNA 主数据 |
| `5432` | `127.0.0.1` | PostgreSQL 16 | Umami 使用 |
| `21` | `0.0.0.0` | pure-ftpd | FTP 服务 |
| `888` | `0.0.0.0` | 宝塔面板 Nginx | 管理面板 |
| `36711` | `0.0.0.0` | 宝塔面板 webserver | 管理面板相关 |
| `7000/8999` | `*` | frp-panel | 同机运行的穿透/面板服务 |
### 2.3 健康检查结果
已验证:
- `http://127.0.0.1:8000/api/health` 返回 `200`,服务名为 `NomadCNA FastAPI`
- `http://127.0.0.1:4002/zh` 返回 `200`Next.js 页面可访问。
- `http://127.0.0.1:8090/api/health` 返回 `200`PocketBase 可访问。
- `https://nomadro.cn` 返回 `307``/zh`,随后返回 `200`
- `https://www.nomadro.cn` 返回 `307``/zh`,随后返回 `200`
- `http://api.nomadro.cn/api/health` 返回 FastAPI 健康信息。
- `https://pocketbase.nomadro.cn/api/health` 返回 `200`
## 3. 技术栈
### 3.1 前端
- Next.js `16.1.6`
- React `19.2.3`
- React DOM `19.2.3`
- TypeScript `^5`
- Tailwind CSS `^4`
- ECharts `^6.0.0`
- PocketBase JS SDK `^0.26.8`
- MinIO SDK `^8.0.7`
- 包管理器:`pnpm 10.25.0`
- Node.js`v22.13.1`
### 3.2 后端
- FastAPI
- Uvicorn
- httpx
- python-multipart
- PyJWT
- passlib[bcrypt]
- Pydantic v2
- Python `3.12.3`
### 3.3 数据与存储
- PocketBase主业务数据库运行在 `/opt/pocketbase`
- PocketBase 数据目录:`/opt/pocketbase/pb_data`
- PocketBase 迁移目录:`/opt/pocketbase/pb_migrations`
- MinIO代码中已接入Docker compose 中也有 `nomadro-minio` 配置,但当前 `docker ps` 只看到 `nomadro-ntfy` 正在运行。
- 本地上传FastAPI 挂载 `backend/uploads`Next.js 上传接口使用 MinIO。
### 3.4 代理、运维与监控
- Nginx宝塔路径 `/www/server/nginx`,站点配置在 `/www/server/panel/vhost/nginx/`
- systemd管理 Next.js、FastAPI、PocketBase、Umami、Netdata 等服务。
- Docker当前运行 `nomadro-ntfy` 容器。
- Netdata宿主机实时监控。
- Umami站点访问统计。
- 宝塔面板相关服务Nginx、pure-ftpd、MariaDB、站点统计、面板防火墙。
## 4. 仓库结构
项目根目录主要文件:
| 路径 | 说明 |
| --- | --- |
| `app/` | Next.js App Router 应用主体 |
| `app/[locale]/` | 中英文路由页面,支持 `/zh``/en` |
| `app/api/` | Next.js API routes主要处理认证、支付、上传、会员状态 |
| `app/components/` | Navbar、Hero、城市卡片、弹窗、菜单、通知铃等组件 |
| `app/context/` | 主题和语言 Context |
| `app/data/` | 城市、博客、招聘等 fallback/mock 数据 |
| `app/lib/` | API 客户端、PocketBase、支付、MinIO、图表、Cookie 等工具 |
| `backend/` | FastAPI 本地 API 服务 |
| `config/` | 站点、导航、域名、服务、首页、页脚、筛选配置 |
| `i18n/` | 国际化路由和导航适配 |
| `messages/` | 中文和英文文案 |
| `public/` | 静态资源 |
| `next.config.ts` | Next.js 配置和 API rewrite |
| `proxy.ts` | locale 重定向代理 |
| `package.json` | 前端依赖和脚本 |
| `backend/requirements.txt` | Python 后端依赖 |
| `cnomadcna.sh` | 生产 Next.js systemd 启动脚本 |
| `PROJECT_ANALYSIS_REPORT.md` | 旧分析报告 |
| `NOMADCNA_PROJECT_DEPLOYMENT_REPORT.md` | 当前报告 |
项目体积:当前仓库目录约 `746M`,包含 `.next``node_modules``backend/.venv` 等运行产物。
## 5. 前端应用结构
### 5.1 国际化
- 支持语言:`zh``en`
- 默认语言:`zh`
- URL 策略:总是带 locale 前缀。
- `proxy.ts` 会将无 locale 的页面请求重定向到 `/zh`
- `/api``/_next`、静态文件和带扩展名路径不做 locale 重定向。
### 5.2 主要页面
当前 `app/[locale]` 下页面包括:
| 页面 | 用途 |
| --- | --- |
| `/` | 首页,城市列表、内容入口、统计、活动、路线、社区模块 |
| `/dashboard` | 下一站推荐,根据预算、网速、气候、标签推荐城市 |
| `/city/[slug]` | 城市详情动态页 |
| `/meetups` | 线下活动列表 |
| `/meetups/host` | 发起活动 |
| `/dating` | 智能匹配、交友、伙伴、室友、合伙人 |
| `/tools` | 汇率、税务估算、签证倒计时、FIRE、气候匹配 |
| `/ai` | AI 助手,基于城市数据库返回建议 |
| `/gigs` | 赏金任务发布和接单 |
| `/services` | 数字游民服务咨询入口 |
| `/pricing` | Free / Basic / Pro 定价展示 |
| `/join` | 社区报名、资料录入、上传、支付跳转 |
| `/join/paid` | 支付回跳与会员开通确认 |
| `/messages` | 站内消息中心 |
| `/settings/notifications` | 通知偏好设置 |
| `/report``/report/data` | 数字游民报告 |
| `/map` | 成员地图 |
| `/blog` | 博客 |
| `/ebooks/[slug]` | 电子书动态页 |
| `/videos/[slug]` | 视频动态页 |
| `/app` | App 下载/介绍页 |
| `/feedback` | 反馈 |
| `/discuss` | 讨论社区 |
| `/jobs``/careers` | 招聘/职业 |
| `/about``/contact``/press``/support``/help` | 基础内容页 |
| `/terms``/privacy``/cookies``/safety``/guidelines` | 法务和社区规则 |
### 5.3 首页数据策略
首页当前采用“线上 API 优先、fallback 静态数据兜底”的方式:
- `/api/cities`:城市列表。
- `/api/content/home`:首页内容卡片。
- `/api/stats/overview`:城市、游民、活动、成本、讨论等统计。
- `/api/profiles`:成员头像和正在旅行的人。
- `/api/meetups`:近期活动。
- `/api/discussions`:热门讨论。
- `/api/routes`:热门路线。
如果 API 请求失败,会回退到 `config/home.config.ts``app/data/cities.ts` 内的本地数据。这让站点在后端短暂不可用时仍能展示基本内容。
### 5.4 导航与站点配置
站点标题:`游牧中国 NomadCNA - 数字游民生活操作系统`
站点描述:数字游民的一站式生活操作系统,覆盖城市决策、税务签证、智能匹配、赏金任务。
主导航包括:
- 城市
- 下一站
- 聚会
- 社区
- 工具箱
- AI
- 赏金
- 会员
- 探索
## 6. API 层结构
当前 API 有两层,需要明确区分。
### 6.1 Next.js API routes
`app/api` 下当前存在:
| 路径 | 用途 |
| --- | --- |
| `/api/auth/me` | 读取登录态、刷新 PocketBase auth、返回 VIP 状态 |
| `/api/auth/logout` | 清除登录 Cookie |
| `/api/auth/sync-session` | 支付后同步 token 到 Cookie |
| `/api/auth/change-password` | 修改密码 |
| `/api/join` | 提交报名资料到 PocketBase 指定集合 |
| `/api/join/status` | 检查是否已经提交报名 |
| `/api/upload-media` | 通过 MinIO 上传图片/视频 |
| `/api/vip/check` | 检查 `site_vip` 会员记录 |
| `/api/pay` | 创建支付订单,调用 payjsapi / ZPay / XorPay |
| `/api/pay/status` | 查询支付状态 |
| `/api/meetup/check-user` | 检查用户是否存在和是否 VIP |
| `/api/meetup/ensure-user` | 确保用户存在 |
| `/api/meetup/complete-order` | 支付成功后确认订单并开通 VIP |
| `/api/meetup/need-password-change` | 检查是否需要改默认密码 |
| `/api/meetup/set-needs-password-change` | 设置需要改密码 |
| `/api/geo/china` | 拉取中国地图 GeoJSON |
### 6.2 FastAPI 后端
FastAPI 运行在 `127.0.0.1:8000`,服务名 `cnomadcna-api.service`。主要接口包括:
| 路径 | 用途 |
| --- | --- |
| `/api/health` | 健康检查 |
| `/api/auth/register` | 注册并设置 session |
| `/api/auth/login` | 登录并设置 session |
| `/api/auth/me` | 当前用户和会员状态 |
| `/api/auth/logout` | 清除 session |
| `/api/auth/change-password` | 修改密码 |
| `/api/meetup/check-user` | 检查用户和会员 |
| `/api/meetup/ensure-user` | 创建或登录用户 |
| `/api/meetup/complete-order` | 本地订单完成和 membership 写入 |
| `/api/vip/check` | 根据 `memberships` 检查 VIP |
| `/api/join` | 提交会员申请 |
| `/api/join/status` | 报名状态 |
| `/api/upload-media` | 本地上传到 `backend/uploads` |
| `/api/pay` | 本地开发支付 |
| `/api/pay/status` | 本地开发支付状态 |
| `/api/cities` | 城市列表 |
| `/api/cities/{slug}` | 城市详情 |
| `/api/content/home` | 首页内容 |
| `/api/content/{slug}` | 内容详情 |
| `/api/notifications` | 消息列表和筛选 |
| `/api/notifications/unread-count` | 未读数 |
| `/api/notifications/{id}/read` | 标记已读 |
| `/api/notifications/{id}/unread` | 标记未读 |
| `/api/notifications/{id}/archive` | 归档 |
| `/api/notifications/{id}/restore` | 恢复 |
| `/api/notifications/{id}/pin` | 置顶 |
| `/api/notifications/mark-all-read` | 全部已读 |
| `/api/notifications/preferences` | 读取/保存通知偏好 |
| `/api/recommendations/next-stop` | 下一站推荐 |
| `/api/routes` | 游牧路线 |
| `/api/services` | 服务列表 |
| `/api/services/leads` | 服务咨询线索 |
| `/api/downloads/{filename}` | 下载 PDF/Zip 等资源 |
| `/api/meetups` | 活动列表和创建 |
| `/api/discussions` | 讨论列表和创建 |
| `/api/gigs` | 赏金列表和发布 |
| `/api/gigs/{gig_id}/apply` | 接单 |
| `/api/profiles` | 成员资料 |
| `/api/matches/swipes` | 匹配滑动记录 |
| `/api/feedback` | 反馈 |
| `/api/stats/member-map` | 成员地图统计 |
| `/api/stats/overview` | 总览统计 |
| `/api/stats/city-ranking` | 城市排行 |
| `/api/geo/china` | 地图数据 |
| `/api/ai/assistant` | AI 助手模拟响应 |
### 6.3 Next.js rewrite
`next.config.ts` 把部分 `/api/*` 路径 rewrite 到 FastAPI
- health
- cities
- content
- notifications
- recommendations
- routes
- services
- downloads
- meetups
- discussions
- gigs
- profiles
- matches
- feedback
- stats
- ai
这意味着:
- 上面列出的业务数据 API 会由 FastAPI 处理。
- Next.js 自身的 `/api/auth/*``/api/pay/*``/api/join/*``/api/upload-media``/api/vip/check` 等仍由 Next.js API routes 处理。
- `app/lib/api-client.ts` 默认 `NEXT_PUBLIC_API_BASE_URL || http://127.0.0.1:8000`。生产环境必须保证 `NEXT_PUBLIC_API_BASE_URL` 指向公网可访问的 API 地址,例如 `http://api.nomadro.cn` 或未来的 `https://api.nomadro.cn`,否则浏览器会尝试请求访问者自己机器的 `127.0.0.1:8000`
## 7. PocketBase 数据模型
### 7.1 PocketBase 服务
PocketBase systemd 配置:
- 服务名:`pocketbase.service`
- 工作目录:`/opt/pocketbase`
- 启动命令:`/opt/pocketbase/pocketbase serve --http=127.0.0.1:8090 --dir=/opt/pocketbase/pb_data --origins=https://nomadro.cn,https://www.nomadro.cn,https://pocketbase.nomadro.cn`
- 数据目录:`/opt/pocketbase/pb_data`
- 迁移目录:`/opt/pocketbase/pb_migrations`
- 当前状态active/running
PocketBase 数据库文件:
- `/opt/pocketbase/pb_data/data.db`
- `/opt/pocketbase/pb_data/auxiliary.db`
- `/opt/pocketbase/pb_data/types.d.ts`
### 7.2 初始化脚本中的集合
`backend/init_db.py` 定义并初始化以下集合:
| 集合 | 用途 |
| --- | --- |
| `cities` | 城市主数据,包括 slug、名称、成本、网速、安全、气候、坐标、标签 |
| `city_details` | 城市详情 JSON包括指南、优缺点、评价、成本、天气、趋势等 |
| `profiles` | 成员资料和匹配展示 |
| `member_applications` | 社区报名资料 |
| `memberships` | FastAPI 使用的会员记录 |
| `orders` | FastAPI 本地订单 |
| `media_assets` | 上传媒体记录 |
| `meetups` | 线下活动 |
| `discussions` | 讨论帖 |
| `gigs` | 赏金任务 |
| `gig_applications` | 接单申请 |
| `services` | 服务市场条目 |
| `service_leads` | 服务咨询线索 |
| `routes` | 游牧路线 |
| `recommendation_logs` | 下一站推荐日志 |
| `notifications` | 站内通知 |
| `notification_receipts` | 通知已读/归档/置顶状态 |
| `notification_preferences` | 通知偏好 |
| `feedback` | 用户反馈 |
| `swipes` | 交友匹配滑动行为 |
| `content_items` | 电子书、视频、App、指南等内容卡片 |
### 7.3 种子数据
种子数据覆盖:
- 18 个中国数字游民城市,包括大理、成都、深圳、上海、杭州、厦门、北京、广州、重庆、昆明、三亚、丽江、西安、南京、长沙、青岛、苏州、珠海。
- 城市成本、网速、安全、气候、经纬度、标签和英文描述。
- 首页内容数字游民落地手册、访谈视频、NomadCNA App、数字游民指南。
- 活动、讨论、赏金、成员资料、服务、路线、通知。
- 典型服务:远程工作者医疗与旅行保障、共享办公通行证、城市落地顾问。
- 典型路线:云南慢生活线、湾区创业线、江南互联网线。
### 7.4 会员模型一致性风险
当前存在两套会员判断模型:
- FastAPI 的 `/api/vip/check``/api/auth/me` 使用 `memberships` 集合。
- Next.js 的 `/api/vip/check``/api/auth/me``/api/meetup/complete-order` 使用 `site_vip` 集合。
- `/opt/pocketbase/pb_migrations` 当前列出的迁移包含 `memberships`,未在本次扫描输出中看到 `site_vip` 迁移文件。
这会带来风险:
- 如果生产 PocketBase 中没有 `site_vip` 集合Next.js 会员检查会一直返回非 VIP。
- 如果支付完成只写 `site_vip`FastAPI 的会员检查不会识别。
- 如果某些页面走 Next.js API某些页面走 FastAPI API会员状态可能不一致。
建议统一为一套会员集合,或明确 `site_vip` 是跨站会员表、`memberships` 是旧表,并补充迁移、同步逻辑和文档。
## 8. 支付与报名链路
### 8.1 报名流程
主要页面:`/zh/join`
流程:
1. 用户填写昵称、性别、感情状态、职业、简介、微信、学历、毕业年份、手机号、图片/视频。
2. 页面先检查 `/api/auth/me`
3. 未登录则打开认证弹窗。
4. 已登录后调用 `/api/join` 写入报名资料。
5. 再调用 `/api/vip/check`
6. 如果不是 VIP则调用 `/api/pay` 跳转支付。
7. 支付成功回跳 `/join/paid`
8. `/join/paid` 根据 `order_id` 调用 `/api/meetup/complete-order`
9. 订单确认后同步登录态、触发 `auth:updated``vip:updated` 事件。
10. 新用户会显示默认密码提示,并允许修改密码。
### 8.2 支付配置
代码支持:
- `zpay`
- `xorpay`
- payjsapi 风格 API
- PC / H5 / 微信浏览器支付环境判断
- 微信内强制走 XorPay 的逻辑
- ZPay 二维码轮询和支付成功后自动确认
关键环境变量名:
- `PAYMENT_API_URL`
- `PAYMENT_PROVIDER`
- `PAYMENT_DEFAULT_AMOUNT`
- `PAYMENT_DEFAULT_TYPE`
- `PAYMENT_JOIN_AMOUNT`
- `PAYMENT_JOIN_TYPE`
- `ZPAY_SUBMIT_URL`
- `NEXT_PUBLIC_SITE_ID`
`config/domain.config.ts` 中有保护逻辑:生产环境如果 `PAYMENT_API_URL` 指向 localhost会使用 `https://api.${ROOT_DOMAIN}`
### 8.3 安全注意点
- 新用户默认密码当前是 `12345678`,且页面会展示和复制该密码。这适合 MVP但生产上存在弱口令风险。
- 建议改为一次性随机临时密码、一次性登录链接,或强制首次设置密码后才完成登录。
- 支付确认依赖订单 ID 格式解析,建议补充订单表记录、签名校验、回调审计和重复开通幂等测试。
## 9. 上传与对象存储
当前存在两套上传实现:
### 9.1 Next.js MinIO 上传
路径:`app/api/upload-media/route.ts`
- 接收 `multipart/form-data`
- 文件大小限制20MB。
- 生成对象 key`{uploadPrefix}/{timestamp}_{random}.{ext}`
- 调用 `app/lib/minio/client.ts``putObject`
- 返回公开 URL。
关键环境变量:
- `MINIO_ENDPOINT`
- `MINIO_PORT`
- `MINIO_USE_SSL`
- `MINIO_BUCKET`
- `MINIO_ACCESS_KEY`
- `MINIO_SECRET_KEY`
- `MINIO_REGION`
- `MINIO_PUBLIC_URL`
- `MINIO_UPLOAD_PREFIX`
### 9.2 FastAPI 本地上传
路径:`backend/main.py``/api/upload-media`
- 文件大小限制20MB。
- 写入 `settings.upload_dir`,默认 `backend/uploads`
- 通过 `/uploads/{name}` 静态路径提供访问。
- 同时写 `media_assets` 集合。
### 9.3 当前部署观察
- Docker compose 中定义了 `nomadro-minio`,端口计划为 `127.0.0.1:9100``127.0.0.1:9101`
- 但当前 `docker ps` 只看到 `nomadro-ntfy` 运行,未看到 MinIO 容器。
- `.env.local` 中存在 MinIO 配置项,但报告未记录敏感值。
建议尽快确认生产上传到底走 MinIO 还是 FastAPI 本地目录,并统一一条路径。
## 10. systemd 服务
### 10.1 NomadCNA Next.js
服务名:`cnomadcna.service`
状态enabled / active / running
工作目录:`/home/ubuntu/gitlab-instance-0a899031_cnomadcna`
启动脚本:`/home/ubuntu/gitlab-instance-0a899031_cnomadcna/cnomadcna.sh`
环境:
- `NODE_ENV=production`
- `HOSTNAME=0.0.0.0`
- `PORT=4002`
启动命令最终为:
```bash
pnpm start
```
`package.json``start` 为:
```bash
next start
```
当前运行:
- 主进程:`node /usr/local/bin/pnpm start`
- 子进程:`next-server (v16.1.6)`
- 监听:`*:4002`
- 最近启动2026-06-06 21:50 CST
### 10.2 NomadCNA FastAPI
服务名:`cnomadcna-api.service`
状态enabled / active / running
工作目录:`/home/ubuntu/gitlab-instance-0a899031_cnomadcna`
环境文件:`/home/ubuntu/gitlab-instance-0a899031_cnomadcna/backend/.env`
启动命令:
```bash
/home/ubuntu/gitlab-instance-0a899031_cnomadcna/backend/.venv/bin/uvicorn backend.main:app --host 127.0.0.1 --port 8000
```
当前运行:
- 主进程:`uvicorn`
- 监听:`127.0.0.1:8000`
- 最近启动2026-06-06 21:46 CST
### 10.3 PocketBase
服务名:`pocketbase.service`
状态enabled / active / running
工作目录:`/opt/pocketbase`
启动命令:
```bash
/opt/pocketbase/pocketbase serve --http=127.0.0.1:8090 --dir=/opt/pocketbase/pb_data --origins=https://nomadro.cn,https://www.nomadro.cn,https://pocketbase.nomadro.cn
```
监听:`127.0.0.1:8090`
### 10.4 Umami
服务名:`umami.service`
状态enabled / active / running
用户:`umami`
工作目录:`/opt/umami`
环境文件:`/opt/umami/.env.production`
启动命令:
```bash
/usr/local/bin/node /opt/umami/.next/standalone/server.js
```
监听:`127.0.0.1:9280`
注意:最近日志有 Next.js Server Action 找不到的错误,可能来自旧前端请求或版本切换后的残留请求。
### 10.5 Netdata
服务名:`netdata.service`
状态enabled / active / running
监听:`127.0.0.1:19999`
Nginx 反代:`netdata.nomadro.cn`,带 Basic Auth。
### 10.6 其他同机服务
| 服务 | 状态 | 说明 |
| --- | --- | --- |
| `nginx` | running | 宝塔 Nginx主反向代理 |
| `mysqld` | running | MariaDB/MySQL |
| `postgresql@16-main` | running | PostgreSQL 16Umami 使用 |
| `docker` / `containerd` | running | Docker 运行时 |
| `pure-ftpd` | running | FTP |
| `frpp.service` | running | frp-panel |
| `site_total.service` | running | 宝塔站点统计 |
| `BT-FirewallServices.service` | running | 宝塔防火墙服务 |
## 11. Nginx 反向代理
Nginx 配置路径:`/www/server/panel/vhost/nginx/`
### 11.1 主站
配置文件:`/www/server/panel/vhost/nginx/www.nomadro.cn.conf`
- upstream`nomadro_nextjs`
- upstream 地址:`127.0.0.1:4002`
- `80` 端口:重定向到 HTTPS。
- `443 ssl http2`:代理到 Next.js。
- 证书:`/etc/letsencrypt/live/nomadro.cn/fullchain.pem`
- 日志:
- `/www/wwwlogs/www.nomadro.cn.log`
- `/www/wwwlogs/www.nomadro.cn.error.log`
### 11.2 FastAPI
配置文件:`/www/server/panel/vhost/nginx/api.nomadro.cn.conf`
- upstream`nomadro_api`
- upstream 地址:`127.0.0.1:8000`
- 当前只看到 HTTP server 配置。
- 日志:
- `/www/wwwlogs/api.nomadro.cn.log`
- `/www/wwwlogs/api.nomadro.cn.error.log`
建议为 `api.nomadro.cn` 配置 HTTPS尤其是认证、支付、会员接口需要安全传输。
### 11.3 PocketBase
配置文件:`/www/server/panel/vhost/nginx/pocketbase.nomadro.cn.conf`
- upstream`nomadro_pocketbase`
- upstream 地址:`127.0.0.1:8090`
- `80` 重定向到 HTTPS。
- `443 ssl http2` 代理到 PocketBase。
- 证书:`/etc/letsencrypt/live/pocketbase.nomadro.cn/fullchain.pem`
### 11.4 Umami
配置文件:`/www/server/panel/vhost/nginx/umami.nomadro.cn.conf`
- upstream`nomadro_umami`
- upstream 地址:`127.0.0.1:9280`
- `80` 重定向到 HTTPS。
- `443 ssl http2` 代理到 Umami。
### 11.5 ntfy
配置文件:`/www/server/panel/vhost/nginx/ntfy.nomadro.cn.conf`
- upstream`nomadro_ntfy`
- upstream 地址:`127.0.0.1:9180`
- 当前只看到 HTTP server 配置。
- 建议后续补 HTTPS。
### 11.6 Netdata
配置文件:`/www/server/panel/vhost/nginx/netdata.nomadro.cn.conf`
- upstream`nomadro_netdata`
- upstream 地址:`127.0.0.1:19999`
- 使用 Basic Auth 文件:`/www/server/panel/vhost/nginx/netdata.nomadro.cn.htpasswd`
- 当前只看到 HTTP server 配置。
### 11.7 Nginx 配置校验
已执行 Nginx 配置测试:
```bash
nginx -t
```
结果syntax oktest successful。
## 12. TLS 证书
Certbot 当前证书:
| 证书名 | 域名 | 到期时间 |
| --- | --- | --- |
| `nomadro.cn` | `nomadro.cn`, `www.nomadro.cn` | 2026-09-04 12:34:54 UTC |
| `pocketbase.nomadro.cn` | `pocketbase.nomadro.cn` | 2026-09-04 12:49:52 UTC |
| `umami.nomadro.cn` | `umami.nomadro.cn` | 2026-09-04 13:58:40 UTC |
当前未看到 `api.nomadro.cn``ntfy.nomadro.cn``netdata.nomadro.cn` 的 Certbot 证书。
## 13. Docker 服务
当前 `docker ps` 只看到:
| 容器 | 镜像 | 状态 | 端口 |
| --- | --- | --- | --- |
| `nomadro-ntfy` | `binwiederhier/ntfy:latest` | running | `127.0.0.1:9180->80` |
`/opt/nomadro-services/docker-compose.yml` 中还定义了:
- `nomadro-minio`:对象存储,计划监听 `127.0.0.1:9100` / `127.0.0.1:9101`
- `nomadro-ntfy`:通知推送。
- `nomadro-uptime-kuma`:可用性监控,计划监听 `127.0.0.1:9301`
- `nomadro-netdata`:容器版 Netdata计划监听 `127.0.0.1:9199`
- `nomadro-mirotalk`:视频会议,计划监听 `127.0.0.1:9300`
实际运行和 compose 定义不完全一致。当前宿主机 systemd 版 Netdata 正在运行Docker 版 Netdata 未运行。MinIO、Uptime Kuma、MiroTalk 当前也未在 `docker ps` 中出现。
## 14. 服务器资源与安全边界
### 14.1 系统信息
- 主机名:`VM-0-16-ubuntu`
- 云厂商Tencent Cloud CVM
- 操作系统Ubuntu 24.04.4 LTS
- 内核Linux 6.8.0-101-generic
- 架构x86_64
- 运行时间:约 6 天 9 小时
### 14.2 资源状态
- 内存3.6Gi,总可用约 2.5Gi。
- Swap1.9Gi,已用约 512Mi。
- 根分区69G总用量 17G可用 50G使用率 25%。
- 当前负载较低。
### 14.3 防火墙
UFW 状态active
默认策略:
- incomingdeny
- outgoingallow
- routeddeny
当前开放端口包括:
- `80`
- `443`
- `22`
- `21`
- `20/tcp`
- `888/tcp`
- `8080`
- `36711/tcp`
- `39000:40000/tcp`
- 以及一个 `8` 规则
风险点:
- FTP 端口 `20/21` 和被动端口段 `39000:40000` 对公网开放。
- 宝塔面板端口 `888``36711` 对公网开放。
- `22` 对公网开放。
- `3306` MariaDB 当前监听 `0.0.0.0:3306`,即便 UFW 未列出 `3306` 开放,也建议数据库服务改为只监听本地或确保云防火墙关闭公网访问。
## 15. 环境变量与配置
### 15.1 根目录 `.env.local`
当前项目根目录存在 `.env.local`,生产构建会加载它。已确认其包含以下类别变量:
- 根域名:`ROOT_DOMAIN``NEXT_PUBLIC_ROOT_DOMAIN`
- PocketBase`NEXT_PUBLIC_POCKETBASE_URL``POCKETBASE_URL`
- 支付:`PAYMENT_API_URL``PAYMENT_PROVIDER``PAYMENT_DEFAULT_AMOUNT``PAYMENT_JOIN_AMOUNT`
- 站点:`NEXT_PUBLIC_SITE_ID``NEXT_PUBLIC_SITE_URL``NEXT_PUBLIC_API_BASE_URL`
- MinIO`MINIO_ENDPOINT``MINIO_PORT``MINIO_USE_SSL`
- PocketBase 管理员:`POCKETBASE_EMAIL``POCKETBASE_PASSWORD`
### 15.2 FastAPI `backend/.env`
当前 systemd 会读取 `backend/.env`,包含:
- `PB_URL`
- `PB_ADMIN_EMAIL`
- `PB_ADMIN_PASSWORD`
- `API_COOKIE_NAME`
- `FRONTEND_ORIGINS`
- `UPLOAD_DIR`
- `DEV_AUTO_PAY`
### 15.3 敏感文件 Git 风险
`git ls-files` 显示以下文件被 Git 跟踪:
- `.env.example`
- `.env.local`
- `.env.local.bak.20260606212903`
- `backend/.env.example`
其中 `.env.local``.env.local.bak.*` 不应被提交。`.env.example` 当前也包含真实样式的敏感配置,不应放真实账号或密码。
建议:
1. 立即将 `.env.local``.env.local.bak.*` 从 Git 索引移除。
2.`.gitignore` 中的 `# .env*` 改为实际忽略规则。
3. 重置已经暴露过的 PocketBase、支付、MinIO 等所有密钥。
4. `.env.example` 只保留占位符,例如 `POCKETBASE_PASSWORD=replace_me`
## 16. 构建与质量状态
### 16.1 `pnpm build`
已执行:
```bash
pnpm build
```
结果:通过。
构建输出:
- Next.js `16.1.6`
- 成功编译。
- TypeScript 检查通过。
- 静态页面生成85 个。
- 路由包含 `/zh``/en` 以及所有主要页面。
- API route 均被识别为动态服务端路由。
注意:本次构建刷新了 `.next` 产物时间戳,`.next/BUILD_ID` 时间为 2026-06-06 23:16 CST。
### 16.2 `pnpm lint`
已执行:
```bash
pnpm lint
```
结果:失败,`7 errors / 31 warnings`
主要错误:
- `app/[locale]/dashboard/page.tsx`React Hooks 新规则提示 effect 内同步 `setLoading(true)`
- `app/api/meetup/complete-order/route.ts``userId``payType` 应使用 `const`
- `app/components/CityModal.tsx`effect 内同步 `setMounted(true)`
- `app/components/SiteMenu.tsx`effect 内同步 `setUserEmail(...)`
- `app/components/ThemeToggle.tsx`effect 内同步 `setMounted(true)`
- `app/context/ThemeContext.tsx`effect 内同步设置 theme/mounted。
主要警告:
- 多处使用 `<img>`Next.js 建议使用 `next/image`
- 若干未使用变量。
- `MembersMap.tsx` 有 hook 依赖提示。
结论:
- 当前源码可以生产构建并运行。
- 但 lint 不通过CI 若以 lint 为发布门槛会失败。
- 建议先修复 7 个 lint error再逐步处理图片优化和未使用变量。
## 17. 当前运行日志观察
### 17.1 Next.js
最近重启后正常启动,监听 `4002`。日志有 Node.js deprecation warning
- `util._extend` 已废弃,建议依赖链后续升级或等待 Next/相关依赖修复。
### 17.2 FastAPI
最近启动正常。早些时候曾出现:
- `PocketBase 404: Missing collection context.`
随后 PocketBase 集合初始化后,`/api/cities``/api/profiles``/api/content/home` 已返回 `200`
当前还看到外部或代理访问 `/``/favicon.ico` 到 FastAPI 时返回 `404`,这是正常的,因为 FastAPI 只提供 `/api/*``/uploads/*`
### 17.3 PocketBase
启动正常REST API 和 Dashboard 均监听 `127.0.0.1:8090`
### 17.4 Umami
服务运行中,但日志出现 `Failed to find Server Action "000000..."`。可能是部署切换后旧请求、缓存或探测请求造成,需要后续观察。
### 17.5 宝塔 site_total
`site_total.service` 日志持续出现写 HyperLogLog 文件失败,路径类似:
- `/www/server/site_total/data/hll/2026-06-04/www.nomadro.cn.hll`
- `/www/server/site_total/data/hll/2026-06-04/ALL.hll`
这不直接影响 NomadCNA 主站,但会影响宝塔站点统计准确性。
## 18. 运维命令速查
### 18.1 项目前端
```bash
cd /home/ubuntu/gitlab-instance-0a899031_cnomadcna
pnpm install
pnpm build
pnpm start
```
开发模式:
```bash
pnpm dev
```
注意:`package.json` 中 dev 实际端口是 `3001`
```bash
next dev -p 3001 -H 0.0.0.0
```
### 18.2 后端
```bash
cd /home/ubuntu/gitlab-instance-0a899031_cnomadcna
source backend/.venv/bin/activate
pip install -r backend/requirements.txt
uvicorn backend.main:app --host 127.0.0.1 --port 8000
```
初始化 PocketBase 集合和种子:
```bash
cd /home/ubuntu/gitlab-instance-0a899031_cnomadcna
source backend/.venv/bin/activate
python -m backend.init_db
```
### 18.3 systemd
查看状态:
```bash
systemctl status cnomadcna.service --no-pager -l
systemctl status cnomadcna-api.service --no-pager -l
systemctl status pocketbase.service --no-pager -l
systemctl status umami.service --no-pager -l
```
重启服务:
```bash
systemctl restart cnomadcna.service
systemctl restart cnomadcna-api.service
systemctl restart pocketbase.service
```
查看日志:
```bash
journalctl -u cnomadcna.service -n 100 --no-pager
journalctl -u cnomadcna-api.service -n 100 --no-pager
journalctl -u pocketbase.service -n 100 --no-pager
journalctl -u umami.service -n 100 --no-pager
```
### 18.4 Nginx
测试配置:
```bash
nginx -t
```
重载配置:
```bash
systemctl reload nginx
```
主站日志:
```bash
tail -f /www/wwwlogs/www.nomadro.cn.log
tail -f /www/wwwlogs/www.nomadro.cn.error.log
```
API 日志:
```bash
tail -f /www/wwwlogs/api.nomadro.cn.log
tail -f /www/wwwlogs/api.nomadro.cn.error.log
```
### 18.5 健康检查
```bash
curl -fsS http://127.0.0.1:8000/api/health
curl -I http://127.0.0.1:4002/zh
curl -I http://127.0.0.1:8090/api/health
curl -fsS http://api.nomadro.cn/api/health
curl -I https://nomadro.cn
curl -I https://pocketbase.nomadro.cn/api/health
```
### 18.6 Docker 服务
```bash
docker ps
cd /opt/nomadro-services
docker compose ps
docker compose up -d
docker compose logs -f ntfy
```
## 19. 主要风险清单
### P0敏感环境文件被 Git 跟踪
`.env.local``.env.local.bak.20260606212903` 已被 Git 跟踪。`.env.example` 也包含真实样式敏感信息。
影响:密钥泄露风险。
建议:从 Git 索引移除、重置所有已暴露密钥、改 `.env.example` 为占位符、更新 `.gitignore`
### P0API 子域未配置 HTTPS
`api.nomadro.cn` 当前只看到 HTTP Nginx 配置。
影响:登录态、支付确认、用户资料提交等请求如果走公网 HTTP存在明文传输风险。
建议:为 `api.nomadro.cn` 申请证书并强制 HTTP 到 HTTPS。
### P0默认密码 `12345678`
新用户支付后使用固定默认密码。
影响:弱口令和撞库风险。
建议:改为随机临时密码、一次性链接、强制首次设置密码。
### P1会员集合不一致
Next.js 使用 `site_vip`FastAPI 使用 `memberships`
影响:支付后不同接口可能返回不同会员状态。
建议:统一会员表或明确同步策略。
### P1MinIO 运行状态和代码配置不一致
代码中 Next.js 上传走 MinIO但当前 Docker 只看到 `nomadro-ntfy`,未看到 MinIO 运行。
影响:生产上传可能失败。
建议:确认 MinIO 是否部署在其他机器/域名;如果是本机,启动并配置反代;如果不用 MinIO统一改为 FastAPI 本地上传或其他对象存储。
### P1Lint 不通过
`pnpm lint` 当前 7 个 error。
影响CI/CD、代码质量和后续维护。
建议:优先修复 lint error再处理 warning。
### P1数据库与管理端口暴露面较大
MariaDB 监听 `0.0.0.0:3306`FTP、宝塔面板、SSH 对公网开放。
影响:攻击面扩大。
建议:数据库只监听本地;管理端口限制 IPSSH 使用密钥、禁用密码或更换端口FTP 如非必要关闭。
### P2`NEXT_PUBLIC_API_BASE_URL` 必须稳定设置
`app/lib/api-client.ts` 默认值是 `http://127.0.0.1:8000`
影响:若生产构建没有设置 `NEXT_PUBLIC_API_BASE_URL`,浏览器会访问用户本机 localhost。
建议:生产环境固定设置为 API 公网域名,且优先升级到 HTTPS。
### P2站点统计服务有错误日志
宝塔 `site_total` 无法写 hll 文件。
影响:宝塔统计不准确。
建议:检查目录是否存在、权限是否正确,或关闭无用统计。
### P2同机服务较多
同机运行 NomadCNA、PocketBase、Umami、MariaDB、PostgreSQL、Docker、Netdata、FTP、宝塔、frp-panel。
影响:故障面复杂,资源争用和安全边界不清晰。
建议:为生产服务建立清晰分层,至少将数据库/监控/管理面板访问收紧。
## 20. 建议的下一步
### 20.1 立即处理
1. 清理 Git 中的 `.env.local``.env.local.bak.*`,重置所有相关密钥。
2.`api.nomadro.cn` 配置 HTTPS并让前端 `NEXT_PUBLIC_API_BASE_URL` 使用 HTTPS。
3. 统一 VIP 数据模型,确认 `site_vip` 是否存在并补充迁移。
4. 修复 `pnpm lint` 的 7 个 error。
5. 确认 MinIO 是否实际运行;若未运行,先修复上传链路。
### 20.2 一周内处理
1. 将默认密码机制改为随机临时密码或首次设置密码。
2.`ntfy.nomadro.cn``netdata.nomadro.cn` 补 HTTPS或仅内网/白名单访问。
3. 收紧 FTP、宝塔、SSH、MariaDB 的公网访问面。
4. 为 PocketBase 数据目录建立自动备份策略。
5. 添加 API smoke test包括 `/api/health``/api/cities``/api/auth/me``/api/vip/check``/api/upload-media`
### 20.3 产品增强
1. 城市数据接入真实来源,增加数据更新时间和数据来源说明。
2. AI 助手接入真实模型,并基于用户画像、预算、收藏、路线生成建议。
3. 站内消息接入 ntfy / 邮件 / 企业微信。
4. 活动报名、赏金接单、服务咨询增加后台运营视图。
5. 定价页与真实支付金额、会员权益完全一致。
6. 对首页和城市卡片图片迁移到 `next/image` 或明确 CDN 图片策略。
## 21. 当前结论
NomadCNA 当前已经完成了数字游民网站的关键骨架:
- 主站可通过 `nomadro.cn``www.nomadro.cn` 访问。
- Next.js 生产服务、FastAPI、PocketBase 均在 systemd 中运行。
- Nginx 已完成主站、PocketBase、Umami 的 HTTPS 反向代理。
- FastAPI 健康接口、主站页面、PocketBase 健康接口均验证可用。
- PocketBase 已有城市、内容、活动、讨论、赏金、成员、服务、路线、通知等完整业务集合。
- 前端页面覆盖城市发现、下一站推荐、活动、匹配、工具、AI、赏金、服务、会员、报名、支付成功页和消息中心。
- `pnpm build` 已通过,说明当前生产构建可用。
同时,当前最需要优先处理的是生产安全和一致性:
- 敏感环境文件不能继续被 Git 跟踪。
- API 域名需要 HTTPS。
- 会员数据模型需要统一。
- 固定默认密码需要替换。
- 上传服务需要确认实际可用。
- lint error 需要修复,以便后续稳定迭代。
整体判断当前项目已经具备上线早期数字游民平台的基础能力但在正式扩大用户规模前应先完成密钥治理、HTTPS、会员模型、上传链路和 lint 修复。