37 KiB
游牧中国 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 | 后端 API,systemd 管理 |
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
流程:
- 用户填写昵称、性别、感情状态、职业、简介、微信、学历、毕业年份、手机号、图片/视频。
- 页面先检查
/api/auth/me。 - 未登录则打开认证弹窗。
- 已登录后调用
/api/join写入报名资料。 - 再调用
/api/vip/check。 - 如果不是 VIP,则调用
/api/pay跳转支付。 - 支付成功回跳
/join/paid。 /join/paid根据order_id调用/api/meetup/complete-order。- 订单确认后同步登录态、触发
auth:updated和vip:updated事件。 - 新用户会显示默认密码提示,并允许修改密码。
8.2 支付配置
代码支持:
zpayxorpay- payjsapi 风格 API
- PC / H5 / 微信浏览器支付环境判断
- 微信内强制走 XorPay 的逻辑
- ZPay 二维码轮询和支付成功后自动确认
关键环境变量名:
PAYMENT_API_URLPAYMENT_PROVIDERPAYMENT_DEFAULT_AMOUNTPAYMENT_DEFAULT_TYPEPAYMENT_JOIN_AMOUNTPAYMENT_JOIN_TYPEZPAY_SUBMIT_URLNEXT_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_ENDPOINTMINIO_PORTMINIO_USE_SSLMINIO_BUCKETMINIO_ACCESS_KEYMINIO_SECRET_KEYMINIO_REGIONMINIO_PUBLIC_URLMINIO_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=productionHOSTNAME=0.0.0.0PORT=4002
启动命令最终为:
pnpm start
package.json 中 start 为:
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
启动命令:
/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
启动命令:
/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
启动命令:
/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 16,Umami 使用 |
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 配置测试:
nginx -t
结果:syntax ok,test 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。
- Swap:1.9Gi,已用约 512Mi。
- 根分区:69G,总用量 17G,可用 50G,使用率 25%。
- 当前负载较低。
14.3 防火墙
UFW 状态:active
默认策略:
- incoming:deny
- outgoing:allow
- routed:deny
当前开放端口包括:
80443222120/tcp888/tcp808036711/tcp39000:40000/tcp- 以及一个
8规则
风险点:
- FTP 端口
20/21和被动端口段39000:40000对公网开放。 - 宝塔面板端口
888、36711对公网开放。 22对公网开放。3306MariaDB 当前监听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_URLPB_ADMIN_EMAILPB_ADMIN_PASSWORDAPI_COOKIE_NAMEFRONTEND_ORIGINSUPLOAD_DIRDEV_AUTO_PAY
15.3 敏感文件 Git 风险
git ls-files 显示以下文件被 Git 跟踪:
.env.example.env.local.env.local.bak.20260606212903backend/.env.example
其中 .env.local 和 .env.local.bak.* 不应被提交。.env.example 当前也包含真实样式的敏感配置,不应放真实账号或密码。
建议:
- 立即将
.env.local和.env.local.bak.*从 Git 索引移除。 - 将
.gitignore中的# .env*改为实际忽略规则。 - 重置已经暴露过的 PocketBase、支付、MinIO 等所有密钥。
.env.example只保留占位符,例如POCKETBASE_PASSWORD=replace_me。
16. 构建与质量状态
16.1 pnpm build
已执行:
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
已执行:
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 项目前端
cd /home/ubuntu/gitlab-instance-0a899031_cnomadcna
pnpm install
pnpm build
pnpm start
开发模式:
pnpm dev
注意:package.json 中 dev 实际端口是 3001:
next dev -p 3001 -H 0.0.0.0
18.2 后端
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 集合和种子:
cd /home/ubuntu/gitlab-instance-0a899031_cnomadcna
source backend/.venv/bin/activate
python -m backend.init_db
18.3 systemd
查看状态:
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
重启服务:
systemctl restart cnomadcna.service
systemctl restart cnomadcna-api.service
systemctl restart pocketbase.service
查看日志:
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
测试配置:
nginx -t
重载配置:
systemctl reload nginx
主站日志:
tail -f /www/wwwlogs/www.nomadro.cn.log
tail -f /www/wwwlogs/www.nomadro.cn.error.log
API 日志:
tail -f /www/wwwlogs/api.nomadro.cn.log
tail -f /www/wwwlogs/api.nomadro.cn.error.log
18.5 健康检查
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 服务
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。
P0:API 子域未配置 HTTPS
api.nomadro.cn 当前只看到 HTTP Nginx 配置。
影响:登录态、支付确认、用户资料提交等请求如果走公网 HTTP,存在明文传输风险。
建议:为 api.nomadro.cn 申请证书并强制 HTTP 到 HTTPS。
P0:默认密码 12345678
新用户支付后使用固定默认密码。
影响:弱口令和撞库风险。
建议:改为随机临时密码、一次性链接、强制首次设置密码。
P1:会员集合不一致
Next.js 使用 site_vip,FastAPI 使用 memberships。
影响:支付后不同接口可能返回不同会员状态。
建议:统一会员表或明确同步策略。
P1:MinIO 运行状态和代码配置不一致
代码中 Next.js 上传走 MinIO,但当前 Docker 只看到 nomadro-ntfy,未看到 MinIO 运行。
影响:生产上传可能失败。
建议:确认 MinIO 是否部署在其他机器/域名;如果是本机,启动并配置反代;如果不用 MinIO,统一改为 FastAPI 本地上传或其他对象存储。
P1:Lint 不通过
pnpm lint 当前 7 个 error。
影响:CI/CD、代码质量和后续维护。
建议:优先修复 lint error,再处理 warning。
P1:数据库与管理端口暴露面较大
MariaDB 监听 0.0.0.0:3306,FTP、宝塔面板、SSH 对公网开放。
影响:攻击面扩大。
建议:数据库只监听本地;管理端口限制 IP;SSH 使用密钥、禁用密码或更换端口;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 立即处理
- 清理 Git 中的
.env.local、.env.local.bak.*,重置所有相关密钥。 - 为
api.nomadro.cn配置 HTTPS,并让前端NEXT_PUBLIC_API_BASE_URL使用 HTTPS。 - 统一 VIP 数据模型,确认
site_vip是否存在并补充迁移。 - 修复
pnpm lint的 7 个 error。 - 确认 MinIO 是否实际运行;若未运行,先修复上传链路。
20.2 一周内处理
- 将默认密码机制改为随机临时密码或首次设置密码。
- 为
ntfy.nomadro.cn、netdata.nomadro.cn补 HTTPS,或仅内网/白名单访问。 - 收紧 FTP、宝塔、SSH、MariaDB 的公网访问面。
- 为 PocketBase 数据目录建立自动备份策略。
- 添加 API smoke test,包括
/api/health、/api/cities、/api/auth/me、/api/vip/check、/api/upload-media。
20.3 产品增强
- 城市数据接入真实来源,增加数据更新时间和数据来源说明。
- AI 助手接入真实模型,并基于用户画像、预算、收藏、路线生成建议。
- 站内消息接入 ntfy / 邮件 / 企业微信。
- 活动报名、赏金接单、服务咨询增加后台运营视图。
- 定价页与真实支付金额、会员权益完全一致。
- 对首页和城市卡片图片迁移到
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 修复。