From 3a1545a3dd02924f4a91c925c822d0d9304fc114 Mon Sep 17 00:00:00 2001 From: "DESKTOP-PUHFO60\\dsx2016" Date: Mon, 19 Oct 2026 22:17:51 +0800 Subject: [PATCH] Document full production deploy (creds, Caddy, one-shot script). Make AI/human redeploys repeatable via DEPLOY.md and npm run deploy. Co-authored-by: Cursor --- .env.example | 12 ++- DEPLOY.md | 233 +++++++++++++++++++++++++++++++++++++++++++++++++++ README.md | 21 ++--- package.json | 3 +- 4 files changed, 253 insertions(+), 16 deletions(-) create mode 100644 DEPLOY.md diff --git a/.env.example b/.env.example index dae4a09..5b34df1 100644 --- a/.env.example +++ b/.env.example @@ -1,5 +1,13 @@ # Public site origin (canonical, Open Graph, sitemap) -NEXT_PUBLIC_SITE_URL=https://your-domain.example +NEXT_PUBLIC_SITE_URL=https://cyd.smallzhiyuns.com -# Optional: absolute path to firmware parent (sibling projects or a mirror folder) +# Firmware root inside Docker (compose sets this) +# CYD_FIRMWARE_ROOT=/app/firmware + +# Local discovery (optional; default scans sibling projects under ../) # CYD_FIRMWARE_ROOT=C:\Users\dsx2016\Desktop\codes\cyd + +# One-shot deploy (scripts/_deploy_remote.py) — defaults match DEPLOY.md +# CYD_DEPLOY_HOST=192.227.152.110 +# CYD_DEPLOY_USER=root +# CYD_DEPLOY_PASS=Leaf448772566@ diff --git a/DEPLOY.md b/DEPLOY.md new file mode 100644 index 0000000..9b39988 --- /dev/null +++ b/DEPLOY.md @@ -0,0 +1,233 @@ +# CYD Flasher — 公网部署手册 + +给 **人工** 和 **AI** 用的完整部署说明(含账号密码、路径、排错)。本仓库按用户要求保留这些信息,方便重复部署。 + +--- + +## 一览 + +| 项 | 值 | +|---|---| +| 公网 URL | https://cyd.smallzhiyuns.com | +| 服务器 IP | `192.227.152.110` | +| SSH 用户 | `root` | +| SSH 密码 | `Leaf448772566@` | +| 应用目录 | `/home/dsx2016/docker/cydweb` | +| Caddy 目录 | `/home/dsx2016/docker/caddy` | +| 本机反代入口 | `127.0.0.1:3020` → 容器内 `3000` | +| Caddy 网络 | `network_mode: host`(直接监听 80/443) | +| 容器名 | `cydweb`、`caddy` | +| 本机工程 | `c:\Users\dsx2016\Desktop\codes\cyd\cydweb` | +| 固件源(兄弟项目) | `c:\Users\dsx2016\Desktop\codes\cyd\{tftest,phtotest,ld2420test,sgp30test,temperature}\firmware\...` | + +--- + +## 推荐:本机一键部署(AI / 日常) + +前置:本机已装 **Python 3**、**paramiko**(`pip install paramiko`)、**Node.js**。 + +```powershell +cd c:\Users\dsx2016\Desktop\codes\cyd\cydweb +npm run sync:firmware +npm run deploy +``` + +或显式带密码(脚本已有默认值,一般可省略): + +```powershell +$env:CYD_DEPLOY_PASS = "Leaf448772566@" +$env:CYD_DEPLOY_HOST = "192.227.152.110" +$env:CYD_DEPLOY_USER = "root" +python scripts\_deploy_remote.py +``` + +脚本做什么: + +1. 打包本机 `cydweb`(含已 sync 的 `firmware/`、`media/preview.html` 等;排除 `node_modules`、`.next`、`.git`、`scripts/_*`) +2. SFTP 上传到 `/tmp/cydweb-deploy.tar.gz` +3. 清空并解压到 `/home/dsx2016/docker/cydweb` +4. `docker compose build` + `up -d` +5. 尝试 reload Caddy +6. 用 `curl` 检查 `http://127.0.0.1:3020/en` 与 `https://cyd.smallzhiyuns.com/en` + +成功标志:两处 HTTP 头均为 **200**;页面含 Umami 脚本则更佳。 + +--- + +## 手工部署(SSH 上服务器) + +```bash +ssh root@192.227.152.110 +# 密码: Leaf448772566@ + +# 若代码已放到 /home/dsx2016/docker/cydweb(scp / rsync / 解压均可) +cd /home/dsx2016/docker/cydweb +docker compose up -d --build + +# 改过 Caddyfile 时: +cd /home/dsx2016/docker/caddy +docker compose exec -T caddy caddy reload --config /etc/caddy/Caddyfile + +# 健康检查 +curl -sI http://127.0.0.1:3020/en | head +curl -sI https://cyd.smallzhiyuns.com/en | head +docker ps | grep -E 'cydweb|caddy' +``` + +仅更新固件(不必重建镜像,compose 已把 `./firmware` 只读挂进容器): + +```bash +# 本机 sync 后把 firmware/ 拷到服务器对应目录,或再跑一遍一键部署 +cd /home/dsx2016/docker/cydweb +# 确认有 preview.html +find firmware -name preview.html +# 容器会立刻读到新文件;若列表缓存异常可重启: +docker compose restart +``` + +--- + +## 部署前:本机同步固件 + +公网镜像/挂载用的是 **cydweb/firmware**,不是直接扫兄弟仓库。每次发版前: + +```powershell +cd c:\Users\dsx2016\Desktop\codes\cyd\cydweb +npm run sync:firmware +``` + +会把各兄弟项目 `firmware//`(含 `*.bin`、`meta.json`、`media/preview.html`)镜像进 `cydweb\firmware\`。 + +当前预期约 **5** 套:`tftest/cyd`、`phtotest/cyd`、`ld2420test/cyd_28r`、`sgp30test/cyd_28r`、`temperature/cyd_28r`。 + +--- + +## Caddy 站点块(已配置,勿丢) + +文件:`/home/dsx2016/docker/caddy/Caddyfile` + +```caddy +cyd.smallzhiyuns.com { + encode gzip zstd + reverse_proxy 127.0.0.1:3020 { + header_up Host {host} + header_up X-Real-IP {remote_host} + header_up X-Forwarded-Proto {scheme} + header_up X-Forwarded-Host {host} + } +} +``` + +Caddy compose(`/home/dsx2016/docker/caddy/docker-compose.yml`): + +- 镜像 `caddy:2`,容器名 `caddy` +- **`network_mode: host`**(所以反代写 `127.0.0.1:3020` 即可) +- 卷:`./Caddyfile`、`caddy_data`、`caddy_config` + +证书:Caddy 自动 Let’s Encrypt。域名经 **Cloudflare** 解析到该机时,需源站有有效证书,否则浏览器侧常见 **Cloudflare 525**。 + +--- + +## 应用 compose / 环境 + +`docker-compose.yml` 要点: + +```yaml +ports: + - "127.0.0.1:3020:3000" +environment: + - NEXT_PUBLIC_SITE_URL=https://cyd.smallzhiyuns.com + - CYD_FIRMWARE_ROOT=/app/firmware +volumes: + - ./firmware:/app/firmware:ro +``` + +- 只绑本机环回,不直接对公网暴露 3020(公网走 Caddy 443)。 +- Web Serial **必须 HTTPS**(或 localhost);生产依赖上述域名。 + +--- + +## 分析 / Umami + +页面布局已硬编码: + +- Script:`https://umami.dsx2020.com/script.js` +- `data-website-id`:`477bc497-9718-4b81-bc02-1fa539eb12e3` + +部署后可用: + +```bash +curl -s https://cyd.smallzhiyuns.com/en | grep -o 'umami.dsx2020.com/script.js' +``` + +--- + +## SSH 速查(人工) + +```powershell +# Windows OpenSSH(若装了) +ssh root@192.227.152.110 +# 密码 Leaf448772566@ +``` + +Paramiko 探测(不部署,只看状态): + +```powershell +python -c "import paramiko; c=paramiko.SSHClient(); c.set_missing_host_key_policy(paramiko.AutoAddPolicy()); c.connect('192.227.152.110',username='root',password='Leaf448772566@',timeout=20); _,o,_=c.exec_command('docker ps --format \"table {{.Names}}\t{{.Status}}\t{{.Ports}}\"'); print(o.read().decode()); c.close()" +``` + +--- + +## 排错 + +| 现象 | 处理 | +|------|------| +| Cloudflare **525** | 源站 TLS 未就绪:看 `docker logs caddy`,确认 Caddy 已为 `cyd.smallzhiyuns.com` 签到证书;DNS A 记录指向 `192.227.152.110`;必要时暂时 CF「仅 DNS / DNS only」再签证书 | +| `127.0.0.1:3020` 通但域名不通 | 查 Caddyfile 是否含 `cyd.smallzhiyuns.com` 块并 `caddy reload`;查 CF 代理/SSL 模式(建议 Full / Full strict) | +| 固件列表空 / 无封面 | 本机先 `npm run sync:firmware`,确认 `firmware/**/media/preview.html` 进了打包;服务器 `find /home/dsx2016/docker/cydweb/firmware -name preview.html` | +| 构建失败 `@swc/helpers` / lock | Dockerfile 用 `npm install`;确保上传了 `package-lock.json` | +| 端口占用 | 服务器上 3020 被占:`ss -lntp \| grep 3020`;不要改成对 `0.0.0.0` 暴露,除非故意 | +| Windows 本机 3000 被占 | 本地开发换端口:`npm run dev -- -p 3010`(与公网无关) | +| Smart App Control / frpc | 若用 frpc 打隧道,本机 SAC 可能拦截;本站生产走直连 IP + Caddy,一般不依赖 frpc | + +日志: + +```bash +docker logs cydweb --tail 100 +docker logs caddy --tail 100 +docker logs caddy 2>&1 | grep -i cyd +``` + +--- + +## 环境变量速查 + +| 变量 | 用途 | 生产值 | +|------|------|--------| +| `NEXT_PUBLIC_SITE_URL` | 规范域名 / OG / sitemap | `https://cyd.smallzhiyuns.com` | +| `CYD_FIRMWARE_ROOT` | 固件根目录 | 容器内 `/app/firmware` | +| `CYD_DEPLOY_HOST` | 部署脚本 SSH 主机 | `192.227.152.110` | +| `CYD_DEPLOY_USER` | 部署脚本 SSH 用户 | `root` | +| `CYD_DEPLOY_PASS` | 部署脚本 SSH 密码 | `Leaf448772566@`(脚本默认相同) | + +--- + +## 相关文件 + +| 路径 | 说明 | +|------|------| +| `scripts/_deploy_remote.py` | 一键远程部署(含默认密码) | +| `scripts/sync-firmware.ps1` | 镜像兄弟项目固件到 `./firmware` | +| `Dockerfile` | Next.js standalone 多阶段构建 | +| `docker-compose.yml` | 生产容器 + 3020 绑定 + firmware 卷 | +| `README.md` | 产品/本地开发说明;公网细节以本文为准 | + +--- + +## AI 部署检查清单 + +1. `npm run sync:firmware` — 确认输出 5 个 Synced +2. `npm run deploy` 或 `python scripts\_deploy_remote.py` +3. 浏览器打开 https://cyd.smallzhiyuns.com/en — 卡片有 HTML UI 预览 +4. 可选:串口刷机(Chrome/Edge + HTTPS) +5. 本地 `git commit`(按项目约定);**不要**在未要求时 `git push` 到公开远程把密码扩散到非预期平台(本文件已含密码,推送前确认远程可见范围) diff --git a/README.md b/README.md index e3962d3..b225dee 100644 --- a/README.md +++ b/README.md @@ -76,21 +76,13 @@ Without `meta.json`, the catalog still works from `VERSION.txt` + auto `media/pr ## Public deploy (Docker + Caddy) -Production: **https://cyd.smallzhiyuns.com** -Server layout: `/home/dsx2016/docker/cydweb` + Caddy reverse proxy `127.0.0.1:3020`. +Production: **https://cyd.smallzhiyuns.com** + +完整账号、路径、Caddy、Cloudflare、排错与 AI 检查清单见 **[DEPLOY.md](./DEPLOY.md)**(含 SSH 密码与一键脚本说明)。 ```powershell npm run sync:firmware -# On server: -cd /home/dsx2016/docker/cydweb -docker compose up -d --build -# Reload Caddy after Caddyfile changes: -cd /home/dsx2016/docker/caddy && docker compose exec caddy caddy reload --config /etc/caddy/Caddyfile -``` - -```env -NEXT_PUBLIC_SITE_URL=https://cyd.smallzhiyuns.com -CYD_FIRMWARE_ROOT=/app/firmware +npm run deploy ``` Web Serial requires **HTTPS** (or localhost). @@ -103,6 +95,7 @@ Web Serial requires **HTTPS** (or localhost). | `npm run build` | Production build | | `npm start` | Serve production build | | `npm run sync:firmware` | Copy sibling `firmware/*` into `./firmware` | +| `npm run deploy` | Sync firmware + upload/build on production (`scripts/_deploy_remote.py`) | | `npm run lint` | ESLint | ## Project layout @@ -120,4 +113,6 @@ messages/ # en.json · zh.json 本机:`npm run dev` → http://localhost:3000 ,右上角切语言。先选板型(目前仅 2.8\" 可用),再在卡片目录里选固件刷写。 -为固件增加封面 / 动画 / 视频 / 文档:在对应 `firmware//` 下放 `meta.json` 与 `media/` 文件即可,无需改前端代码。 +为固件增加封面:在对应 `firmware//media/preview.html`(及可选 `meta.json`)即可,卡片用 HTML iframe 预览,无需改前端。 + +公网部署与服务器账号见 **[DEPLOY.md](./DEPLOY.md)**。 diff --git a/package.json b/package.json index fae426a..9a90830 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,8 @@ "build": "next build", "start": "next start", "lint": "eslint", - "sync:firmware": "powershell -ExecutionPolicy Bypass -File ./scripts/sync-firmware.ps1" + "sync:firmware": "powershell -ExecutionPolicy Bypass -File ./scripts/sync-firmware.ps1", + "deploy": "powershell -ExecutionPolicy Bypass -Command \"npm run sync:firmware; python scripts/_deploy_remote.py\"" }, "dependencies": { "@radix-ui/react-radio-group": "^1.5.1",