233 lines
5.9 KiB
Markdown
233 lines
5.9 KiB
Markdown
|
|
# 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`:
|
|||
|
|
```powershell
|
|||
|
|
npm install
|
|||
|
|
```
|
|||
|
|
Expected: `node_modules/` populated, no errors.
|
|||
|
|
|
|||
|
|
- [ ] **Step 2: Build the frontend**
|
|||
|
|
|
|||
|
|
```powershell
|
|||
|
|
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**
|
|||
|
|
|
|||
|
|
```powershell
|
|||
|
|
Get-ChildItem Client\dist
|
|||
|
|
```
|
|||
|
|
Expected: `index.html`, `assets/`, `favicon.svg`, `icons.svg` present.
|
|||
|
|
|
|||
|
|
- [ ] **Step 4: Commit the main.rs port change**
|
|||
|
|
|
|||
|
|
```powershell
|
|||
|
|
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:
|
|||
|
|
```bash
|
|||
|
|
cd /mnt/f/Code/InternetProject/Server
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
- [ ] **Step 2: Check Rust toolchain is installed**
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
rustc --version
|
|||
|
|
```
|
|||
|
|
If not installed:
|
|||
|
|
```bash
|
|||
|
|
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**
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
cargo build --release
|
|||
|
|
```
|
|||
|
|
First build takes 2–5 minutes (downloads + compiles dependencies). Expected final line:
|
|||
|
|
```
|
|||
|
|
Finished `release` profile [optimized] target(s) in Xs
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
- [ ] **Step 4: Verify binary exists and is Linux ELF**
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
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:
|
|||
|
|
```bash
|
|||
|
|
ssh root@8.130.143.54 "mkdir -p /opt/internet-project/static"
|
|||
|
|
```
|
|||
|
|
Expected: no output, exit 0.
|
|||
|
|
|
|||
|
|
- [ ] **Step 2: Upload the Rust binary**
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
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**
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
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**
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
ssh root@8.130.143.54 "chmod +x /opt/internet-project/RustServer"
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
- [ ] **Step 5: Verify remote layout**
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
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**
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
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**
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
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**
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
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**
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
curl http://8.130.143.54:8548/api/web/stats
|
|||
|
|
```
|
|||
|
|
Expected: JSON with system metrics (CPU, memory, etc.).
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Operations Reference
|
|||
|
|
|
|||
|
|
**Stop server:**
|
|||
|
|
```bash
|
|||
|
|
ssh root@8.130.143.54 "pkill RustServer"
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**View live logs:**
|
|||
|
|
```bash
|
|||
|
|
ssh root@8.130.143.54 "tail -f /opt/internet-project/server.log"
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**Redeploy after code changes:**
|
|||
|
|
Re-run Tasks 1–4. For frontend-only changes, skip Task 2.
|