publish

star 0

将 landing/ 官方销售网站构建产物发布到 ai-board.reai.com(部署机 cn.reai.com,nginx + Let's Encrypt 自动 SSL)。首次发布自动完成 ACME 签证与 nginx 配置,后续发布只同步静态文件。Trigger when user types /publish 或提到 发布、部署到服务器、发布网页、更新线上、deploy。

ReAI-com By ReAI-com schedule Updated 6/2/2026

name: publish description: "将 landing/ 官方销售网站构建产物发布到 ai-board.reai.com(部署机 cn.reai.com,nginx + Let's Encrypt 自动 SSL)。首次发布自动完成 ACME 签证与 nginx 配置,后续发布只同步静态文件。Trigger when user types /publish 或提到 发布、部署到服务器、发布网页、更新线上、deploy。"

Publish — ai-board.reai.com 官网发布

landing/ 官方销售网站(Vue 3 + Supabase)的 Vite 构建产物(landing/dist/)发布到 ai-board.reai.com,部署机 cn.reai.com,nginx 直出 + Let's Encrypt 自动签证 / 续期。

发布对象是 landing/,不是 web/web/ 是 K203 桌面应用(Tauri)的操作界面,依赖本地 IPC,浏览器跑不了——不是网站。landing/ 才是面向公网的官网。详见仓库内两目录定位说明。

部署环境

项目
服务器 cn.reai.com (SSH: root@cn.reai.com)
服务器公网 IP 47.106.107.172(ai-board.reai.com 已正确指向它)
OS Ubuntu 22.04, nginx 1.18.0, certbot 5.2.2
域名 ai-board.reai.com
静态根目录 /var/www/ai-board.reai.com/(远端,nginx root
nginx 配置 /etc/nginx/sites-available/ai-board.reai.com.conf(symlink 到 sites-enabled)
ACME webroot /var/www/certbot(全服务器共用)
证书路径 /etc/letsencrypt/live/ai-board.reai.com/
SSL 续期 certbot 系统 timer 自动续期,无需人工
本地构建 cd landing && bun run build → 产物 landing/dist/

注意:远端静态目录不是 git 仓库,文件通过 rsync 同步。nginx 配置模板在本 skill 的 references/,scp 到远端安装。

构建前置:环境变量(landing 是动态站,硬依赖)

landing/ 前端直连 Supabase,构建时把以下 VITE_ 变量编译进产物。发布生产前必须确认 landing/.env.local 是生产配置(尤其 Supabase URL 不能是本地/dev 地址,否则线上预订/订单/admin 全部连不上):

变量 作用
VITE_SUPABASE_URL Supabase 项目地址(生产)
VITE_SUPABASE_ANON_KEY Supabase 匿名公钥
VITE_DOWNLOAD_MACOS / VITE_DOWNLOAD_WINDOWS 客户端下载链接
VITE_PAYMENT_URL 支付链接
VITE_SALE_OPEN 销售开关(控制是否开放下单)
# 发布前自检:确认不是本地地址
grep VITE_SUPABASE_URL landing/.env.local

架构

浏览器 → DNS(ai-board.reai.com → 47.106.107.172 = cn.reai.com)
        → nginx :443 (Let's Encrypt SSL)
        → root /var/www/ai-board.reai.com  (静态直出,SPA history fallback → index.html)
        → 前端 JS 直连 Supabase(数据收集 / 订单 / admin)

智能判断:首发 vs 常规发布

触发 /publish 时,先探测远端是否已 bootstrap(证书 + 正式 nginx 配置是否就位):

ssh root@cn.reai.com '
  HAS_CERT=$(test -f /etc/letsencrypt/live/ai-board.reai.com/fullchain.pem && echo y || echo n)
  HAS_CONF=$(test -L /etc/nginx/sites-enabled/ai-board.reai.com.conf && echo y || echo n)
  echo "cert=$HAS_CERT conf=$HAS_CONF"
'
  • cert=y conf=y → 已 bootstrap,走 常规发布(只同步静态文件)
  • 其他 → 未 bootstrap,走 首次发布(含 DNS 检查 + ACME 签证 + nginx 安装)

前置检查(每次都跑,不可跳过)

# 1. 本地代码状态(提醒,不强制)
git status --short

# 2. 服务器可达
ssh -o ConnectTimeout=10 root@cn.reai.com "echo OK"

# 3. DNS 校验 —— ai-board.reai.com 必须解析到 47.106.107.172
#    本机可能是代理 fake-ip 模式(dig 出 198.18.x.x 不可信),
#    一律以「服务器视角 + 公共 DNS」为准。
DNS_IP=$(ssh root@cn.reai.com "dig +short ai-board.reai.com A | head -1")
echo "ai-board.reai.com 解析 = $DNS_IP(期望 47.106.107.172)"
if [ "$DNS_IP" != "47.106.107.172" ]; then
  echo "❌ DNS 未指向部署机,certbot webroot 签证会失败。请先修正 A 记录。"
  exit 1
fi

# 4. 构建环境变量自检(确认 Supabase 是生产地址)
grep VITE_SUPABASE_URL landing/.env.local

本地构建

cd landing && bun run build && cd ..
ls landing/dist/index.html   # 确认产物存在

首次发布(Bootstrap,一次性)

前提:前置检查全部通过(DNS 指向 47.106.107.172、.env.local 为生产配置)。

# Step 1: 远端建静态根目录 + webroot,先同步一份文件
ssh root@cn.reai.com "mkdir -p /var/www/ai-board.reai.com /var/www/certbot"
rsync -avz --delete landing/dist/ root@cn.reai.com:/var/www/ai-board.reai.com/

# Step 2: 安装 http-only 配置(仅 80 + ACME challenge),enable 并 reload
scp .claude/skills/publish/references/nginx-ai-board.http-only.conf \
  root@cn.reai.com:/etc/nginx/sites-available/ai-board.reai.com.conf
ssh root@cn.reai.com "
  ln -sf /etc/nginx/sites-available/ai-board.reai.com.conf \
         /etc/nginx/sites-enabled/ai-board.reai.com.conf
  nginx -t && nginx -s reload
"

# Step 3: certbot webroot 签证(自动注册到续期 timer)
ssh root@cn.reai.com "
  certbot certonly --webroot -w /var/www/certbot \
    -d ai-board.reai.com \
    --non-interactive --agree-tos -m admin@reai.com \
    --key-type ecdsa
"

# Step 4: 换上正式配置(80→443 + 443 静态直出),reload
scp .claude/skills/publish/references/nginx-ai-board.conf \
  root@cn.reai.com:/etc/nginx/sites-available/ai-board.reai.com.conf
ssh root@cn.reai.com "nginx -t && nginx -s reload"

-m admin@reai.com:Let's Encrypt 到期提醒邮箱,按需替换。 签证成功后自动注册续期 timer,SSL 续期全自动


常规发布(已 bootstrap)

最常见路径——只同步静态文件,不碰 nginx / 证书:

cd landing && bun run build && cd ..
rsync -avz --delete landing/dist/ root@cn.reai.com:/var/www/ai-board.reai.com/

--delete 保证远端与本地 dist/ 完全一致(清掉旧 hash 资源)。静态站无需 reload nginx。


验证

# (a) HTTPS 可达
curl -sf -o /dev/null -w "HTTPS %{http_code}\n" https://ai-board.reai.com/

# (b) 证书域名 / 有效期
ssh root@cn.reai.com "certbot certificates -d ai-board.reai.com 2>/dev/null | grep -E 'Domains|Expiry'"

# (c) HTTP 自动跳转 HTTPS(应为 301)
curl -s -o /dev/null -w "HTTP→ %{http_code} → %{redirect_url}\n" http://ai-board.reai.com/

# (d) SPA 深链回退(多语言路由应回 index.html 而非 404)
curl -sf -o /dev/null -w "深链 /zh/pricing → %{http_code}\n" https://ai-board.reai.com/zh/pricing

回滚

# 静态内容回滚:发布前可先备份当前版本
#   ssh root@cn.reai.com "cp -a /var/www/ai-board.reai.com /var/www/ai-board.reai.com.bak"
# 回退:
ssh root@cn.reai.com "rm -rf /var/www/ai-board.reai.com && mv /var/www/ai-board.reai.com.bak /var/www/ai-board.reai.com"

# nginx 配置回滚:删 enable symlink + reload(站点下线,不影响其他站)
ssh root@cn.reai.com "rm -f /etc/nginx/sites-enabled/ai-board.reai.com.conf && nginx -t && nginx -s reload"

安全注意

  • 所有 rsync/scp/certbot 走 SSH,不暴露文件到公网。
  • 静态文件同步用 --delete 保证与本地一致,避免残留旧资源。
  • nginx reload 前必 nginx -t 验证配置。
  • 这台机器同时托管大量其他 *.cn.reai.com 站点:只操作 ai-board.reai.com 自己的 conf 和 /var/www/ai-board.reai.com 目录,绝不动其他站点的配置 / 目录 / 证书。
  • 构建前确认 .env.local 为生产 Supabase 配置,避免线上连错数据库。
Install via CLI
npx skills add https://github.com/ReAI-com/ai-vibe-board --skill publish
Repository Details
star Stars 0
call_split Forks 0
navigation Branch main
article Path SKILL.md
More from Creator