PersonalWebApplication/docs/superpowers/plans/2026-06-18-deploy.md
cc d2ff88bc4d feat(start): 补齐竖屏背景图(portrait 全套 webp)并重新验证部署
- portrait/ 加入 No.1~5.webp + Night.webp(由 Pictures/portrait 源图
  用 sharp 转 webp,quality 82,体积 ~0.1~0.6MB)
- 前端 build 后两套图(landscape/portrait)均打包,已部署到
  8.130.143.54:8548 并验证(title=CCStart,health 200)
- 更新部署文档:重新验证日期、portrait 集说明、转换工具改用 sharp

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-23 20:14:08 +08:00

7.3 KiB
Raw Blame History

InternetProject Deployment Plan

For agentic workers: REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (- [ ]) syntax for tracking.

Goal: Deploy the React + Rust full-stack app to root@8.130.143.54, accessible at http://8.130.143.54:8548.

Architecture: Rust binary (RustServer) serves both the REST API and React static files from a single process. React is built locally, Rust is cross-compiled in WSL, both artifacts are uploaded via scp and started with nohup.

Tech Stack: React 19 + Vite 8 (frontend), Rust + Axum 0.8 (backend), Ubuntu 22.04 (server), WSL2 mirrored network (build env)

Global Constraints

  • Server: root@8.130.143.54, Ubuntu 22.04, x86_64
  • Deploy path: /opt/internet-project/ on server
  • Static files served from: /opt/internet-project/static/
  • Port: 8548 (via PORT=8548 env var at runtime)
  • WSL mirrored network + autoProxy=true — no manual proxy config needed
  • main.rs already updated to read PORT env var (default 8080)
  • Do NOT install any toolchain on the remote server

Task 1: Build React Frontend

Files:

  • Build: Client/Client/dist/

Interfaces:

  • Produces: Client/dist/index.html + Client/dist/assets/* (consumed by Task 3)

  • Step 1: Install dependencies (if not already installed)

Run in PowerShell from F:\Code\InternetProject\Client:

npm install

Expected: node_modules/ populated, no errors.

  • Step 2: Build the frontend
npm run build

Expected output ends with something like:

dist/index.html                 x.xx kB
dist/assets/index-[hash].js   xxx.xx kB
✓ built in x.xxs
  • Step 3: Verify dist output
Get-ChildItem Client\dist

Expected: index.html, assets/, favicon.svg, icons.svg present.

  • Step 4: Commit the main.rs port change
git add Server/src/main.rs
git commit -m "feat: read PORT from env var, default 8080"

Task 2: Build Rust Binary in WSL

Files:

  • Build: Server/Server/target/release/RustServer

Interfaces:

  • Produces: /mnt/f/Code/InternetProject/Server/target/release/RustServer — Linux x86_64 ELF binary (consumed by Task 3)

  • Step 1: Open WSL and navigate to project

In a WSL terminal:

cd /mnt/f/Code/InternetProject/Server
  • Step 2: Check Rust toolchain is installed
rustc --version

If not installed:

curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
source "$HOME/.cargo/env"

Expected: rustc 1.xx.x (...) printed.

  • Step 3: Build release binary
cargo build --release

First build takes 25 minutes (downloads + compiles dependencies). Expected final line:

Finished `release` profile [optimized] target(s) in Xs
  • Step 4: Verify binary exists and is Linux ELF
file target/release/RustServer

Expected:

target/release/RustServer: ELF 64-bit LSB pie executable, x86-64, ...

Task 3: Upload Artifacts to Server

Files:

  • Remote create: /opt/internet-project/ (directory)
  • Remote create: /opt/internet-project/RustServer (binary)
  • Remote create: /opt/internet-project/static/ (frontend files)

Interfaces:

  • Consumes: Server/target/release/RustServer (from Task 2), Client/dist/* (from Task 1)

  • Produces: server-side deploy directory ready to run (consumed by Task 4)

  • Step 1: Create deploy directory on server

Run in WSL:

ssh root@8.130.143.54 "mkdir -p /opt/internet-project/static"

Expected: no output, exit 0.

  • Step 2: Upload the Rust binary
scp /mnt/f/Code/InternetProject/Server/target/release/RustServer \
    root@8.130.143.54:/opt/internet-project/RustServer

Expected: progress bar, then returns to prompt.

  • Step 3: Upload frontend static files
scp -r /mnt/f/Code/InternetProject/Client/dist/* \
    root@8.130.143.54:/opt/internet-project/static/

Expected: multiple files transferred (index.html, assets/, etc.).

  • Step 4: Make binary executable
ssh root@8.130.143.54 "chmod +x /opt/internet-project/RustServer"
  • Step 5: Verify remote layout
ssh root@8.130.143.54 "ls -lh /opt/internet-project/ && ls /opt/internet-project/static/"

Expected:

total XX
-rwxr-xr-x 1 root root XXM ... RustServer
drwxr-xr-x 2 root root ...  static/

assets  favicon.svg  icons.svg  index.html

Task 4: Start the Server and Verify

Files:

  • Remote: /opt/internet-project/server.log (created on start)

Interfaces:

  • Consumes: deploy directory from Task 3

  • Produces: running service at http://8.130.143.54:8548

  • Step 1: Start server with nohup

ssh root@8.130.143.54 "cd /opt/internet-project && nohup PORT=8548 ./RustServer > server.log 2>&1 &"

Expected: no output (background process started).

  • Step 2: Check server started successfully
ssh root@8.130.143.54 "sleep 1 && cat /opt/internet-project/server.log"

Expected:

backend listening on http://0.0.0.0:8548
  • Step 3: Verify API endpoint responds
curl http://8.130.143.54:8548/api/client/health

Expected: HTTP 200 with a JSON response (or empty 200).

  • Step 4: Verify frontend loads

Open http://8.130.143.54:8548 in a browser. Expected: React app renders correctly (login page / blog page visible).

  • Step 5: Verify API stats endpoint
curl http://8.130.143.54:8548/api/web/stats

Expected: JSON with system metrics (CPU, memory, etc.).


Operations Reference

Stop server:

ssh root@8.130.143.54 "pkill RustServer"

View live logs:

ssh root@8.130.143.54 "tail -f /opt/internet-project/server.log"

Redeploy after code changes: Re-run Tasks 14. For frontend-only changes, skip Task 2.

Frontend-only redeploy (re-verified 2026-06-23): The active WSL checkout is at /home/cc/InternetProject (not the /mnt/f/... path in the original tasks above). Since the Rust process serves static/ from disk, a frontend-only change needs no server restart — just rebuild and replace the static files:

cd /home/cc/InternetProject/Client
npm run build
# clear stale hashed assets so old bundles don't accumulate
ssh root@8.130.143.54 "rm -rf /opt/internet-project/static/assets && mkdir -p /opt/internet-project/static"
scp -r dist/* root@8.130.143.54:/opt/internet-project/static/
# verify live
curl -s http://8.130.143.54:8548/ | grep -o '<title>[^<]*</title>'
curl -s -o /dev/null -w '%{http_code}\n' http://8.130.143.54:8548/api/client/health

Restart the Rust binary (backend changes): A helper exists on the server: /opt/internet-project/restart_rust.sh. The previous binary is kept as RustServer.bak for rollback.

Startpage backgrounds: large PNG/JPG source images are pre-compressed to WebP (quality ~82) before building — keeps each background under ~600 KB for the 3 Mbps server link. Two sets live under Client/src/assets/startpage/: landscape/ and portrait/ (same filenames No.1~5.webp + Night.webp). As of 2026-06-23 both sets are fully populated; sharp is the converter (no system cwebp/ImageMagick in this WSL — install it on the fly if needed).