Files
gitlab-instance-0a899031_cn…/README.md
2026-06-07 23:57:52 -05:00

24 KiB
Raw Blame History

游牧中国 NomadCNA

NomadCNA 是面向数字游民的生活操作系统,用一个站点承载城市决策、会员加入、线上/线下活动、视频会议、Web 群聊、内容资源、任务赏金、支付和媒体存储等能力。

生产站点:

业务介绍

NomadCNA 的目标用户是正在中国或亚洲范围内长期旅居、远程工作、寻找社群和机会的数字游民。业务上分为以下几条主线:

模块 说明
城市探索 展示中国数字游民城市数据,包括生活成本、网络、温度、社群密度、安全、文化等指标。
下一站决策 根据预算、网络、气候、标签偏好生成城市推荐。
线上/线下活动 支持公开、登录成员、VIP、主持人等权限层级线上/混合活动进入 统一活动间MiroTalk 视频 + The Lounge 群聊分屏),账户昵称自动带入视频房。
Web 群聊 The Lounge + Ergo IRC每活动可配置 loungeChannel(如 #nomadcna-20260608),默认频道 #nomadcna,#online-events
访谈视频 /videos 博主访谈列表,/videos/[slug] 单条详情;首页「访谈视频」链到列表页。
社区匹配 /dating 滑动匹配:意图 Tab、城市筛选、互赞、每日额度、高级筛选、撤销滑动。
会员加入与支付 支持加入表单、支付订单、支付状态轮询、VIP/会员写入。
Digital 子站 /digital 是内容专题站,包含数字游民指南、课程、电子书、资源、工作机会、个人资料等。
媒体与内容 支持图片/视频上传、远程媒体代理缓存、内容投稿、博客、电子书、视频等内容页面。
社区与增长 包含讨论、交友匹配、任务赏金、反馈、通知、站内消息、服务线索。

技术栈

层级 技术
Web 前端 Next.js 16 App Router、React 19、TypeScript、Tailwind CSS 4
API Next.js Route Handlers、FastAPI、PocketBase SDK/HTTP
数据 PocketBase、静态数据、MinIO 对象存储
支付 ZPay / XorPay 适配层
视频会议 MiroTalk P2PNginx HTTPS 反代
Web 群聊 The Lounge 4.5.0 + Ergo IRC Server 2.18.0
部署 systemd、Nginx、Certbot、Docker
包管理 pnpm 10.25.0

生产服务器当前 Node.js 版本为 v22.13.1

源码解析

顶层结构

.
├── app/                         # Next.js App Router 主目录
│   ├── [locale]/                # 中文/英文路由,默认 zh
│   ├── api/                     # Next.js Route Handlers
│   ├── components/              # 主站通用组件
│   ├── context/                 # Locale、Theme 等上下文
│   ├── data/                    # 城市、地图、mock 数据
│   ├── digital/                 # Digital 子站组件、配置、数据和工具
│   └── lib/                     # API、支付、媒体、活动、PocketBase 等工具
├── backend/                     # FastAPI 后端
├── config/                      # 主站和 Digital 子站配置
│   └── remote-services.ts       # 线上服务地址、Windows 远程开发模式
├── scripts/                     # dev-tunnel.py、dev-windows.ps1
├── i18n/                        # 路由和国际化导航封装
├── messages/                    # zh/en 文案
├── public/                      # 静态资源
├── cnomadcna.sh                 # 生产 Next.js 启动脚本
├── next.config.ts               # Next.js 配置与 API rewrites
├── package.json                 # 前端依赖与脚本
└── tsconfig.json                # TypeScript 配置

Next.js 页面结构

主站所有面向用户的页面位于 app/[locale],路由强制带语言前缀:

  • /zh/en:首页与城市探索
  • /zh/dashboard:下一站决策仪表盘
  • /zh/meetups:线上/线下活动列表与详情弹窗
  • /zh/meetups/host:活动发布页
  • /zh/meetups/[id]/live统一活动间(内嵌 MiroTalk + The Lounge需权限
  • /zh/videos:博主访谈视频列表
  • /zh/videos/[slug]:单条访谈详情
  • /zh/dating:社区滑动匹配(意图、城市、互赞、额度)
  • /zh/join:成员加入(城市、寻找意图、资料)
  • /zh/discuss:讨论
  • /zh/gigs:任务赏金
  • /zh/tools:工具箱
  • /zh/report/zh/report/data:统计与年报
  • /zh/digitalDigital 子站入口

通用布局与组件:

  • app/layout.tsx:根布局
  • app/[locale]/layout.tsx:语言布局
  • app/components/Navbar.tsxFooter.tsxSidebar.tsx:主站导航与外壳
  • app/context/LocaleContext.tsx:运行时文案读取
  • app/context/ThemeContext.tsx:亮色/暗色主题

Digital 子站

Digital 子站代码集中在 app/digitalapp/[locale]/digital

  • app/[locale]/digital/page.tsx:专题首页
  • app/[locale]/digital/course:课程页
  • app/[locale]/digital/course/[moduleIndex]/[lessonIndex]:课程章节
  • app/[locale]/digital/ebook:电子书
  • app/[locale]/digital/jobs:远程工作
  • app/[locale]/digital/join:加入/申请
  • app/[locale]/digital/profile:用户资料

配置在 config/digital

  • site.config.ts:专题主题、功能开关、课程/电子书/加入等能力
  • services.config.tsPocketBase、支付、MinIO 配置读取
  • domain.config.ts:域名和服务地址推导
  • course.tslessons.ts:课程数据

API 分层

本项目有两层 API

  1. Next.js 内置 APIapp/api/*
  2. FastAPI 后端:backend/main.py

next.config.ts 将大多数 /api/* 转发到 FastAPI

source: "/api/:path((?!(?:digital|media)(?:$|/.*)).*)"
destination: "http://127.0.0.1:8000/api/:path*"

因此:

  • /api/digital/* 由 Next.js Route Handlers 处理
  • /api/media/* 由 Next.js Route Handlers 处理
  • 其他 /api/* 默认转发到 FastAPI

Next.js API

路径 作用
app/api/digital/auth/* Digital 子站登录、退出、当前用户、注册、跨站同步
app/api/digital/join Digital 加入/申请表单写入 PocketBase
app/api/digital/pay/* Digital 支付创建、确认、状态查询
app/api/digital/upload-media 媒体上传到 MinIO
app/api/digital/vip/check VIP 状态检查
app/api/media/proxy 远程媒体抓取、校验、缓存到 MinIO 后跳转公开 URL

FastAPI 后端

FastAPI 入口为 backend/main.py,配置读取在 backend/settings.py。核心能力:

API 作用
/api/health 健康检查
/api/auth/email/api/auth/google/api/auth/me 主站认证
/api/join/api/join/status 加入表单与状态
/api/upload-media 后端媒体上传
/api/pay/api/pay/status 支付创建与查询
/cnomadcna/*_notify 支付网关回调
/api/cities/api/cities/{slug} 城市数据
/api/content/* 首页内容、内容投稿、内容详情
/api/videos 访谈视频列表(type=video 的 content_items
/api/notifications/* 通知、回执、偏好
/api/recommendations/next-stop 下一站推荐
/api/meetups 活动列表与创建
/api/meetups/{id} 单个活动详情
/api/meetups/{id}/session 活动间会话:权限校验、视频/群聊 URL、社区昵称
/api/matches/* 匹配候选、滑动、互赞、额度、撤销、我的资料
/api/discussions 讨论列表与创建
/api/gigs 任务赏金列表、创建、申请
/api/profiles 资料列表
/api/feedback 用户反馈(支持 ?type=report 预填)
/api/stats/* 成员地图、概览、城市排行
/api/services/api/services/leads 增值服务与线索
/api/ai/assistant AI 助手占位接口

后端辅助模块:

  • backend/pb_client.pyPocketBase HTTP 客户端
  • backend/payment.pyZPay / XorPay 支付适配
  • backend/minio_storage.pyMinIO 上传
  • backend/meetup_live.py:活动间 URL 生成、权限判断MiroTalk / Lounge
  • backend/avatar_assets.py与前端同步的头像池seed 用)
  • backend/init_db.pyseed_data.pyenhanced_seed.py:初始化与种子数据
  • backend/settings.py:环境变量读取(含 MIROTALK_URLLOUNGE_URL

活动、视频与群聊(深度融合)

相关文件:

文件 作用
app/[locale]/meetups/page.tsx 活动列表、详情弹窗、「进入活动间」入口
app/[locale]/meetups/[id]/live/page.tsx 统一活动间页面
app/components/meetups/EventLiveRoom.tsx 分屏 UI视频 iframe + 群聊 iframe
app/[locale]/meetups/host/page.tsx 发起活动
app/lib/meetups.ts MiroTalk/Lounge URL、房间 slug、loungeChannel、权限工具
backend/meetup_live.py 后端同名逻辑,供 /api/meetups/{id}/session 使用

app/lib/meetups.ts 负责:

  • MiroTalk 默认地址:NEXT_PUBLIC_MIROTALK_URL(生产 https://mirotalk.nomadro.cn
  • MiroTalk 房间名规范化、buildMiroTalkJoinUrl(meetup, displayName)
  • Lounge 默认地址:NEXT_PUBLIC_LOUNGE_URL(生产 https://lounge.nomadro.cn
  • 活动专属 IRC 频道:loungeChannel 字段,或从 mirotalkRoom 推导
  • 群聊 deep linkbuildMeetupChatUrl(meetup)lounge.nomadro.cn/#/chan-#频道
  • 活动间路径:buildMeetupLivePath(id)/meetups/{id}/live

账户打通GET /api/meetups/{id}/session 读取 PocketBase 登录态,校验 public/members/vip/hosts,将社区昵称写入 MiroTalk name= 参数。

PocketBase meetups 集合字段(线上活动相关):

  • modeoffline / online / hybrid
  • accessLevelpublic / members / vip / hosts
  • meetingProvider:如 mirotalk
  • mirotalkRoom:视频房间 slug
  • loungeChannelIRC 频道,如 #nomadcna-20260608
  • featuresJSONgroup_videoscreen_share

访谈视频

  • 列表:app/[locale]/videos/page.tsx,数据来自 GET /api/videos
  • 详情:app/[locale]/videos/[slug]/page.tsx
  • 首页右侧「访谈视频」卡片链到 /videos(非单条 slug

社区匹配Dating

  • 页面:app/[locale]/dating/page.tsx
  • 组件:app/[locale]/dating/components/IntentTabsCityFilterSwipeStackLikesPanelMatchModalAdvancedFiltersSwipeQuota 等)
  • 工具:app/[locale]/dating/utils.tsconstants.tstypes.ts
  • 头像池:app/data/avatars.tsUnsplash 人像,与 backend/avatar_assets.py 同步)

匹配 API均需登录部分需 VIP

  • GET /api/matches/candidates — 候选列表(意图、城市、性别筛选)
  • POST /api/matches/swipes — 左滑/右滑/超级赞
  • POST /api/matches/swipes/undo — 撤销上一次滑动
  • GET /api/matches/likes/mutual/quota/profile/me

媒体代理

  • app/lib/media.ts:封面 URL 规范化Unsplash 直连、MinIO 相对路径补全)
  • app/api/media/proxy/route.ts远程媒体抓取MinIO 失败时直返图片

配置与国际化

文件 作用
config/site.config.ts 主站 SEO 与站点基础信息
config/nav.config.ts 顶部导航
config/footer.config.ts 页脚
config/services.config.ts 主站支付配置
config/runtime-env.ts 运行环境判断
config/remote-services.ts 线上域名、MinIO/PocketBase 解析、远程开发模式
config/digital/* Digital 子站主题、服务、课程、域名配置
messages/zh.jsonmessages/en.json 中英文文案
i18n/routing.ts 语言列表与默认语言
i18n/navigation.ts 语言路由 Link / Router 封装

本地开发

环境要求

  • Node.js 20+,生产当前使用 Node.js 22.13.1
  • pnpm 10+
  • Python 3.12+
  • PocketBase
  • 可选MinIO、ZPay/XorPay 测试配置

安装依赖

pnpm install

Windows 本地连线上服务

典型配置见 .env.example / .env.local

  1. PocketBase 用公网 https://pocketbase.nomadro.cn
  2. MinIO S3 API 用 SSH 隧道映射到本机 9100
python scripts/dev-tunnel.py
  1. 本地跑 Next.js + FastAPI
pnpm dev
# 另开终端
backend\.venv\Scripts\uvicorn backend.main:app --host 127.0.0.1 --port 8000 --reload

或一键脚本:

powershell -ExecutionPolicy Bypass -File scripts/dev-windows.ps1

服务地址推导见 config/remote-services.ts

初始化数据库

python -m backend.init_db

会创建/补全 PocketBase 集合字段,并 upsert 城市、活动、内容、资料等种子数据。

前端开发

pnpm dev

默认启动在:

http://localhost:3001

FastAPI 后端开发

python3 -m venv backend/.venv
source backend/.venv/bin/activate
pip install -r backend/requirements.txt
uvicorn backend.main:app --host 127.0.0.1 --port 8000 --reload

构建与启动

pnpm build
pnpm start

常用检查

pnpm lint
pnpm exec tsc --noEmit --pretty false
APP_ENV=production NEXT_PUBLIC_APP_ENV=production NODE_ENV=production pnpm build

环境变量

不要把真实密钥提交到 Git。.env.example 只放示例值,生产值放 .env.localbackend/.env 或 systemd Environment。

前端公开变量

变量 说明
APP_ENV development / production
NEXT_PUBLIC_APP_ENV 浏览器可见运行环境
NEXT_PUBLIC_SITE_URL 站点根地址
NEXT_PUBLIC_SITE_ID 站点 ID用于会员/VIP 隔离
NEXT_PUBLIC_API_BASE_URL API 基础地址,生产通常为 /api
FASTAPI_PROXY_TARGET Next.js rewrite 转发 FastAPI 的目标(本地 http://127.0.0.1:8000
NEXT_PUBLIC_POCKETBASE_URL 浏览器可访问 PocketBase 地址
NEXT_PUBLIC_MIROTALK_URL MiroTalk P2P 服务地址
NEXT_PUBLIC_LOUNGE_URL The Lounge Web 群聊地址
NEXT_PUBLIC_MINIO_PUBLIC_URL MinIO 文件公开地址

后端和服务端变量

变量 说明
POCKETBASE_URL 服务端访问 PocketBase 的内网地址
POCKETBASE_EMAIL PocketBase 管理员邮箱
POCKETBASE_PASSWORD PocketBase 管理员密码
PAYMENT_API_URL 支付 API 地址
PAYMENT_PROVIDER zpayxorpay
PAYMENT_DEFAULT_AMOUNT 默认支付金额
PAYMENT_JOIN_AMOUNT 加入场景金额
PAYMENT_JOIN_TYPE 加入场景订单类型
ZPAY_PIDZPAY_KEY ZPay 商户配置
XORPAY_AIDXORPAY_SECRET XorPay 商户配置
MINIO_ENDPOINT MinIO 内网端点
MINIO_PORT MinIO 端口
MINIO_USE_SSL 是否对 MinIO 内网连接启用 SSL
MINIO_BUCKET 存储桶
MINIO_ACCESS_KEY MinIO Access Key
MINIO_SECRET_KEY MinIO Secret Key
MINIO_REGION MinIO 区域
MINIO_UPLOAD_PREFIX 上传路径前缀
FRONTEND_ORIGINS FastAPI CORS 白名单
UPLOAD_DIR 后端本地上传目录
MIROTALK_URL / LOUNGE_URL 后端生成活动间 URL默认同公网域名
DEV_SSH_HOST / DEV_SSH_PASSWORD Windows SSH 隧道(仅本地,勿提交)

生产服务器支持

生产代码目录:

/home/ubuntu/gitlab-instance-0a899031_cnomadcna

域名与服务映射

域名 上游 说明
nomadro.cn / www.nomadro.cn 127.0.0.1:4002 Next.js 主站,cnomadcna.service
api.nomadro.cn 127.0.0.1:8000 FastAPI
pocketbase.nomadro.cn 127.0.0.1:8090 PocketBase
minio.nomadro.cn 127.0.0.1:9100 / 9101 MinIO API / Console
mirotalk.nomadro.cn 127.0.0.1:9300 MiroTalk P2P
lounge.nomadro.cn 127.0.0.1:9000 The Lounge Web IRC
ergo.nomadro.cn HTTPS redirect 跳转到 lounge.nomadro.cnIRC 后端只内网监听
ntfy.nomadro.cn 127.0.0.1:9180 ntfy 通知服务

systemd 服务

服务 作用 当前策略
cnomadcna.service Next.js 生产服务 enabled监听 0.0.0.0:4002
mirotalk-p2p.service MiroTalk P2P enabled监听 127.0.0.1:9300
ergo.service Ergo IRC Server enabled监听 127.0.0.1:6667[::1]:6667
thelounge.service The Lounge Web IRC enabled监听 127.0.0.1:9000

常用命令:

systemctl status cnomadcna.service
systemctl status mirotalk-p2p.service
systemctl status ergo.service
systemctl status thelounge.service

journalctl -u cnomadcna.service -n 100 --no-pager
journalctl -u mirotalk-p2p.service -n 100 --no-pager
journalctl -u ergo.service -n 100 --no-pager
journalctl -u thelounge.service -n 100 --no-pager

Docker 服务

当前生产容器:

容器 镜像 端口
nomadro-minio minio/minio:latest 127.0.0.1:9100->9000127.0.0.1:9101->9001
nomadro-ntfy binwiederhier/ntfy:latest 127.0.0.1:9180->80

检查:

docker ps
docker logs nomadro-minio --tail 100
docker logs nomadro-ntfy --tail 100

Nginx

Nginx vhost 目录:

/www/server/panel/vhost/nginx

关键配置:

  • www.nomadro.cn.conf:主站
  • api.nomadro.cn.confFastAPI
  • mirotalk.nomadro.cn.confMiroTalk
  • lounge.nomadro.cn.confThe Lounge + Ergo redirect
  • minio.nomadro.cn.confMinIO
  • pocketbase.nomadro.cn.confPocketBase

常用命令:

nginx -t
nginx -s reload

HTTPS 证书

证书由 Certbot 管理。lounge.nomadro.cn 证书包含两个域名:

lounge.nomadro.cn
ergo.nomadro.cn

当前证书路径:

/etc/letsencrypt/live/lounge.nomadro.cn/fullchain.pem
/etc/letsencrypt/live/lounge.nomadro.cn/privkey.pem

检查:

certbot certificates

MiroTalk P2P

安装目录:

/opt/nomadro-services/mirotalk

运行方式:

  • systemdmirotalk-p2p.service
  • 内网端口:127.0.0.1:9300
  • 公网入口:https://mirotalk.nomadro.cn
  • 活动页自动生成链接:https://mirotalk.nomadro.cn/join?room=...&name=...

健康检查:

curl -I https://mirotalk.nomadro.cn/join?room=nomadcna-healthcheck

Ergo IRC Server

安装目录:

/opt/ergo

配置:

/etc/ergo/ircd.yaml
/etc/ergo/ergo.motd
/var/lib/ergo/ircd.db

当前策略:

  • 网络名:NomadCNA
  • 服务名:ergo.nomadro.cn
  • 只监听本机 127.0.0.1:6667[::1]:6667
  • 不开放公网 IRC TLS 6697
  • ergo.nomadro.cn 的 HTTPS 请求跳转到 The Lounge

本机 IRC 握手检查:

{ printf 'NICK health\r\nUSER health 0 * :NomadCNA Health\r\nJOIN #nomadcna\r\nQUIT :healthcheck\r\n'; sleep 1; } \
  | timeout 5s nc 127.0.0.1 6667

The Lounge Web 群聊

安装目录:

/opt/nomadro-services/thelounge

配置:

/var/lib/thelounge/config.js

当前策略:

  • public mode
  • 只监听 127.0.0.1:9000
  • Nginx 通过 https://lounge.nomadro.cn 反代
  • 默认网络锁定到本机 Ergo127.0.0.1:6667
  • 默认加入频道:#nomadcna,#online-events(可按活动追加,如 #nomadcna-20260608
  • 文件上传关闭
  • The Lounge 自身消息持久化关闭Ergo 保留内存历史

健康检查:

curl -I https://lounge.nomadro.cn/
curl 'https://lounge.nomadro.cn/socket.io/?EIO=4&transport=polling&t=health'

上线流程

前端上线

cd /home/ubuntu/gitlab-instance-0a899031_cnomadcna
APP_ENV=production NEXT_PUBLIC_APP_ENV=production NODE_ENV=production pnpm build
systemctl restart cnomadcna.service
systemctl status cnomadcna.service --no-pager

后端上线

FastAPI 当前运行在 127.0.0.1:8000。更新后需重启对应 uvicorn 进程或其 systemd 服务。如果后续为 FastAPI 增加 systemd 单元,建议命名为:

cnomadcna-api.service

Nginx 配置变更

nginx -t
nginx -s reload

服务健康检查

curl -I https://nomadro.cn/zh/meetups
curl -I https://api.nomadro.cn/api/health
curl -I https://mirotalk.nomadro.cn/join?room=nomadcna-healthcheck
curl -I https://lounge.nomadro.cn/
curl -I https://ergo.nomadro.cn/

数据与备份

建议纳入备份的内容:

路径/服务 说明
.env.localbackend/.env 生产环境变量和密钥
PocketBase 数据目录 用户、会员、订单、内容、活动等业务数据
MinIO 数据卷 上传媒体、远程媒体缓存
/var/lib/ergo Ergo IRC 数据库
/var/lib/thelounge The Lounge 配置、VAPID key、包配置
/opt/nomadro-services/mirotalk MiroTalk 源码部署目录
/www/server/panel/vhost/nginx/*.conf Nginx vhost 配置
/etc/systemd/system/*.service systemd 单元

安全注意事项

  • README 不应包含真实密钥、管理员密码、支付密钥或 MinIO Secret。
  • .env.localbackend/.env 不应提交到 Git。
  • The Lounge 当前为 public mode适合活动公开群聊如需长期身份和历史可切换 private mode 并创建用户账号。
  • Ergo 原生 IRC 公网端口当前不开放,这是有意设计;需要原生 IRC 客户端时再开放 6697 并配置 TLS。
  • 内部服务优先绑定 127.0.0.1,统一通过 Nginx HTTPS 暴露。
  • 修改 Nginx 前必须先 nginx -t
  • 更新证书后确认 SAN 包含对应域名。

开发约定

  • 新页面优先放入 app/[locale],并补充 messages/zh.jsonmessages/en.json
  • 需要语言感知链接时使用 i18n/navigation.ts 导出的 Link
  • 调用后端 API 使用 app/lib/api-client.ts
  • 主站通用配置放 config/*Digital 子站配置放 config/digital/*
  • 媒体上传和远程媒体代理优先走 MinIO。
  • 支付相关逻辑优先复用 app/lib/paymentbackend/payment.pyconfig/*/services.config.ts
  • 线上活动相关逻辑优先复用 app/lib/meetups.ts

常见问题

为什么 ergo.nomadro.cn 不直接打开 IRC

ergo.nomadro.cn 是 IRC 服务名,但原生 IRC 端口没有对公网开放。用户从浏览器进入 lounge.nomadro.cnThe Lounge 在服务器本机连接 Ergo。这样能减少公网攻击面同时满足 Web 群聊需求。

为什么 /api/digital/* 没有转发到 FastAPI

next.config.ts 明确排除了 digitalmedia 两类 API它们由 Next.js Route Handlers 直接处理。其他 /api/* 才会转发到 FastAPI。

活动视频房如何生成?

app/lib/meetups.ts 会根据活动 mirotalkRoom、或城市/日期/时间/ID 生成 room slug。登录用户通过 /api/meetups/{id}/session 获取带 name= 的入会 URL。

如何进入统一活动间?

活动详情弹窗点 「进入活动间」/meetups/{id}/live。页面内分屏嵌入 MiroTalk 与 The Lounge也可新窗口单独打开。

群聊频道如何进入?

  • 全局:https://lounge.nomadro.cn(默认 #nomadcna#online-events
  • 单活动:buildMeetupChatUrl(meetup)lounge.nomadro.cn/#/chan-#频道
  • PocketBase 活动记录可设 loungeChannel 字段

维护命令速查

# 构建并重启主站
APP_ENV=production NEXT_PUBLIC_APP_ENV=production NODE_ENV=production pnpm build
systemctl restart cnomadcna.service

# 查看服务
systemctl status cnomadcna.service --no-pager
systemctl status mirotalk-p2p.service --no-pager
systemctl status ergo.service --no-pager
systemctl status thelounge.service --no-pager

# 查看日志
journalctl -u cnomadcna.service -n 100 --no-pager
journalctl -u mirotalk-p2p.service -n 100 --no-pager
journalctl -u ergo.service -n 100 --no-pager
journalctl -u thelounge.service -n 100 --no-pager

# Nginx
nginx -t
nginx -s reload

# 端口
ss -ltnp | rg ':4002|:8000|:8090|:9000|:9300|:9100|:9101|:6667|:6697'

# Docker
docker ps

# HTTPS
certbot certificates