docs(architecture): move dashboards to Vercel

This commit is contained in:
root 2026-03-30 00:05:50 +00:00
parent c0cf80d96b
commit 5cff282961
2 changed files with 63 additions and 112 deletions

View File

@ -1,4 +1,4 @@
# Track A: Azure VM — Gateway, Dashboards & Security
# Track A: Azure VM — Gateway, Gitea & Security
> **Agent:** Codex on Azure VM (`/opt/bytelyst/`)
> **Prompts:** 4 (run in dependency order below)
@ -17,34 +17,35 @@
| --- | ------------------------ | :------------: | :--------: | :------: |
| A1 | Caddy Gateway Setup | 🟨 In progress | — | ⬜ |
| A2 | Gitea HTTPS Exposure | ⬜ Not started | — | ⬜ |
| A3 | Dashboard Containers Fix | ⬜ Not started | — | ⬜ |
| A3 | Dashboard Frontend Split | ⬜ Not started | — | ⬜ |
| A4 | NSG Lockdown | ⬜ Not started | — | ⬜ |
**Execution order:**
```
A1: Caddy Gateway ──→ A2: Gitea HTTPS ──→ A4: NSG Lockdown
└──→ A3: Dashboard Fix (parallel with A2)
└──→ A3: Dashboard Frontends on Vercel
```
---
## DNS Prerequisites (manual — do before starting)
These DNS records must exist before Caddy can obtain Let's Encrypt certificates:
These VM-hosted DNS records must exist before Caddy can obtain Let's Encrypt certificates:
| Record | Type | Value | Purpose |
| ---------------------- | ---- | ---------------------- | ------------------- |
| `api.bytelyst.com` | A | `<Azure VM public IP>` | Backend API gateway |
| `gitea.bytelyst.com` | A | `<Azure VM public IP>` | Gitea npm registry |
| `admin.bytelyst.com` | A | `<Azure VM public IP>` | Admin dashboard |
| `tracker.bytelyst.com` | A | `<Azure VM public IP>` | Tracker dashboard |
| `admin.bytelyst.com` | CNAME or A | `<Vercel deployment>` | Admin frontend |
| `tracker.bytelyst.com` | CNAME or A | `<Vercel deployment>` | Tracker frontend |
**Verify DNS before starting A1:**
```bash
dig +short api.bytelyst.com # must return VM IP
dig +short gitea.bytelyst.com # must return VM IP
# admin/tracker should resolve to Vercel, not the VM
```
---
@ -52,7 +53,7 @@ dig +short gitea.bytelyst.com # must return VM IP
## A1: Caddy Gateway — Replace Traefik with Caddy
> **Depends on:** DNS records for `api.bytelyst.com`
> **Blocks:** A2, A3, A4
> **Blocks:** A2, A4
### Preconditions
@ -221,92 +222,70 @@ AFTER COMPLETING: Notify the operator that Track B → B4 (.npmrc migration) is
---
## A3: Fix admin-web and tracker-web Containers
## A3: Move admin-web and tracker-web to Vercel
> **Depends on:** A1 ✅ (Caddy running for subdomain routing)
> **Blocks:** Nothing (independent of Track B)
> **Depends on:** A1 ✅ for `api.bytelyst.com`
> **Blocks:** Nothing on the VM track
> **Can run in parallel with:** A2
### Preconditions
- [ ] A1 is complete — Caddy is running
- [ ] `admin.bytelyst.com` and `tracker.bytelyst.com` DNS A records resolve to VM IP
- [ ] Source code for dashboards is available on the VM
- [ ] `api.bytelyst.com` is live on the VM with HTTPS
- [ ] `admin-web` and `tracker-web` source code is available in the repo
- [ ] Vercel project(s) exist or can be created for the dashboards
### Prompt
```
You are working on the ByteLyst single-Azure-VM Docker deployment at /opt/bytelyst/.
You are working on the ByteLyst deployment split where the Azure VM hosts only self-hosted infrastructure and backend APIs, while public frontend apps deploy on Vercel.
TASK: Resolve the remaining admin-web and tracker-web containers so they are running and healthy, then expose them via Caddy.
TASK: Move admin-web and tracker-web out of the VM hosting path and make them Vercel-hosted frontends that talk to the VM backend through https://api.bytelyst.com.
CONTEXT:
- Per DEPLOYMENT_STATUS_2026-03-29.md, all 13 backend services are healthy
- admin-web and tracker-web are the two remaining UNRESOLVED containers
- Both are Next.js 16 apps from learning_ai_common_plat under dashboards/
- Both use workspace:* dependencies resolved by pnpm
- Both use the --webpack build flag
- admin-web port: 3001, tracker-web port: 3003
- Docker build context: dashboards/admin-web/ and dashboards/tracker-web/
- The VM should host only self-hosted and backend services
- admin-web and tracker-web are Next.js frontends from learning_ai_common_plat under dashboards/
- Their public domains should be:
- https://admin.bytelyst.com
- https://tracker.bytelyst.com
- Those domains should point to Vercel, not the VM
- Browser/API configuration should use the VM backend entrypoint at https://api.bytelyst.com
TASK LIST:
- [ ] 1. Check current container status:
docker compose ps admin-web tracker-web
docker compose logs admin-web --tail 100
docker compose logs tracker-web --tail 100
- [ ] 2. Diagnose the build/runtime failure (likely causes):
- @bytelyst/* package resolution — may need .docker-deps/ tarballs
- Standalone entrypoint not found
- Missing env vars (COSMOS_ENDPOINT, COSMOS_KEY, JWT_SECRET)
- [ ] 3. Fix the identified issues
- [ ] 4. Rebuild and restart:
docker compose up -d --build admin-web tracker-web
- [ ] 5. Add Caddy routes for the dashboards to the Caddyfile:
admin.bytelyst.com {
reverse_proxy admin-web:3001
}
tracker.bytelyst.com {
reverse_proxy tracker-web:3003
}
- [ ] 6. Reload Caddy: docker exec caddy caddy reload --config /etc/caddy/Caddyfile
- [ ] 7. Update DEPLOYMENT_STATUS_2026-03-29.md to reflect the fix
- [ ] 1. Audit both dashboards for browser-visible backend URLs and replace VM-local assumptions with the public API hostname
- [ ] 2. Document the required Vercel env vars for both apps
- [ ] 3. Ensure `admin.bytelyst.com` and `tracker.bytelyst.com` DNS point to Vercel, not the VM
- [ ] 4. Remove dashboard host-routing assumptions from the VM/Caddy plan
- [ ] 5. Update deployment docs to record the frontend/backend split
VERIFICATION (run all — every check must pass):
# Containers healthy
docker compose ps admin-web tracker-web
# Expected: both show "Up" and "healthy" (or at least "Up")
# DNS should no longer point at the VM
dig +short admin.bytelyst.com
dig +short tracker.bytelyst.com
# Expected: Vercel-managed resolution, not the VM public IP
# Local port access
curl -sf http://127.0.0.1:3001 | head -5
curl -sf http://127.0.0.1:3003 | head -5
# Expected: HTML response from each
# HTTPS via Caddy
# Frontends load on Vercel
curl -sI https://admin.bytelyst.com | head -3
# Expected: HTTP/2 200 (or 302)
curl -sI https://tracker.bytelyst.com | head -3
# Expected: HTTP/2 200 (or 302)
# Expected: HTTP 200 or 302 from Vercel-hosted apps
# All containers now healthy
docker compose ps | grep -E "(unhealthy|Exit)" | wc -l
# Expected: 0
# VM backend stays the single API entrypoint
curl -sf https://api.bytelyst.com/platform/health | jq -r '.status'
# Expected: ok
SUCCESS CRITERIA:
- Both admin-web and tracker-web containers are running
- Both respond on their ports (3001, 3003)
- Both accessible via HTTPS at admin.bytelyst.com and tracker.bytelyst.com
- DEPLOYMENT_STATUS doc updated with fix details
- Zero unhealthy containers in the full stack
- admin.bytelyst.com is served by Vercel
- tracker.bytelyst.com is served by Vercel
- Both frontends use https://api.bytelyst.com for backend access
- The VM no longer needs dashboard routing or public dashboard ports
COMMIT: fix(deployment): resolve admin-web and tracker-web containers
COMMIT: docs(architecture): move dashboards to Vercel and keep VM backend-only
```
---
## A4: NSG Lockdown — Reduce Public Port Exposure
> **Depends on:** A1 + A2 + A3 all complete (all traffic routed through Caddy)
> **Depends on:** A1 + A2 complete
> **Blocks:** Nothing
> **Run this LAST in Track A**
@ -314,7 +293,6 @@ COMMIT: fix(deployment): resolve admin-web and tracker-web containers
- [ ] A1 complete — all backends accessible via `api.bytelyst.com`
- [ ] A2 complete — Gitea accessible via `gitea.bytelyst.com`
- [ ] A3 complete — dashboards accessible via `admin.bytelyst.com` and `tracker.bytelyst.com`
- [ ] All services verified working through Caddy (no direct port access needed)
### Prompt
@ -324,8 +302,8 @@ TASK: Reduce the Azure NSG (Network Security Group) rules so only ports 80, 443,
CONTEXT:
- The Azure VM currently exposes many service ports publicly (3000-3300, 4003-4019, 8025, 8080, 10000, 11434)
- Caddy now handles ALL public HTTPS traffic on ports 80/443
- All services (backends, Gitea, dashboards, monitoring) are accessed through Caddy subdomains
- Caddy now handles the VM-hosted public HTTPS traffic on ports 80/443
- Only backend and self-hosted services should remain on the VM
- Only SSH (22) and HTTP/HTTPS (80/443) should remain publicly open
- This follows the recommendation in SECURE_API_EXPOSURE.md
@ -355,9 +333,6 @@ VERIFICATION (run all — every check must pass):
curl -sf https://gitea.bytelyst.com/api/v1/version | jq '.version'
# Expected: version string
curl -sI https://admin.bytelyst.com | head -1
# Expected: HTTP/2 200 (or 302)
# Direct port access blocked
for port in 3001 3003 3300 4003 4005 8025 8080 10000; do
curl -sf --max-time 3 http://<VM_PUBLIC_IP>:$port && echo "FAIL: $port open" || echo "PASS: $port closed"
@ -413,7 +388,7 @@ done
echo "--- Gitea npm registry ---"
curl -sf https://gitea.bytelyst.com/api/packages/ByteLyst/npm/@bytelyst%2ferrors | jq '.name'
echo "--- Dashboards ---"
echo "--- Dashboards (Vercel-hosted) ---"
curl -sI https://admin.bytelyst.com | head -1
curl -sI https://tracker.bytelyst.com | head -1

View File

@ -2,6 +2,12 @@
This handoff captures the current state of Track A on the Azure VM at `/opt/bytelyst/`.
Architecture decision after this handoff:
- The VM should host only self-hosted infrastructure and backend APIs
- `api.bytelyst.com` and `gitea.bytelyst.com` should point to the VM
- `admin.bytelyst.com` and `tracker.bytelyst.com` should be Vercel-hosted frontends, not VM-hosted services
## What Was Completed
- Fixed a blocking parse error in [`docker-compose.ecosystem.yml`](/opt/bytelyst/learning_ai_common_plat/docker-compose.ecosystem.yml) by removing a duplicate `efforise-web` service definition.
@ -24,14 +30,14 @@ This handoff captures the current state of Track A on the Azure VM at `/opt/byte
### 1. DNS is not ready
From the VM, these records did not resolve:
From the VM, these records did not resolve at the time of the original session:
- `api.bytelyst.com`
- `gitea.bytelyst.com`
- `admin.bytelyst.com`
- `tracker.bytelyst.com`
Without these, Caddy cannot obtain Let's Encrypt certificates and A1/A2/A3 HTTPS verification cannot pass.
For the revised architecture, only `api.bytelyst.com` and `gitea.bytelyst.com` must resolve to the VM for Track A. `admin.bytelyst.com` and `tracker.bytelyst.com` should resolve to Vercel instead.
### 2. Azure CLI is missing
@ -57,23 +63,20 @@ This blocks reliable rebuilds for A3 and potentially other services.
## Required Preconditions Before Resuming
1. Create DNS A records for:
1. Create or confirm VM DNS records for:
- `api.bytelyst.com`
- `gitea.bytelyst.com`
- `admin.bytelyst.com`
- `tracker.bytelyst.com`
2. Confirm they resolve to the VM public IP from the VM:
```bash
dig +short api.bytelyst.com
dig +short gitea.bytelyst.com
dig +short admin.bytelyst.com
dig +short tracker.bytelyst.com
curl -sf https://api.ipify.org && echo
```
3. Install Azure CLI and log in with permissions to manage the VM NSG.
4. Export a Linux-safe Gitea host before rebuilds, for example:
3. Point `admin.bytelyst.com` and `tracker.bytelyst.com` at Vercel, not the VM.
4. Install Azure CLI and log in with permissions to manage the VM NSG.
5. Export a Linux-safe Gitea host before rebuilds, for example:
```bash
export GITEA_NPM_HOST=172.17.0.1
@ -145,37 +148,10 @@ gitea-npm-registry
### A3
1. Keep `GITEA_NPM_HOST` exported to the Docker-reachable host IP before rebuilding.
2. Rebuild only the dashboard services first:
```bash
export GITEA_NPM_HOST=172.17.0.1
docker compose -f docker-compose.ecosystem.yml --env-file .env.ecosystem up -d --build admin-web tracker-web
docker compose -f docker-compose.ecosystem.yml --env-file .env.ecosystem logs admin-web --tail 100
docker compose -f docker-compose.ecosystem.yml --env-file .env.ecosystem logs tracker-web --tail 100
```
3. Add dashboard host blocks to `/opt/bytelyst/Caddyfile`:
```caddy
admin.bytelyst.com {
reverse_proxy admin-web:3001
}
tracker.bytelyst.com {
reverse_proxy tracker-web:3003
}
```
4. Reload Caddy and verify:
```bash
curl -sf http://127.0.0.1:3001 | head -5
curl -sf http://127.0.0.1:3003 | head -5
curl -sI https://admin.bytelyst.com | head -3
curl -sI https://tracker.bytelyst.com | head -3
docker compose -f docker-compose.ecosystem.yml --env-file .env.ecosystem ps | grep -E "(unhealthy|Exit)" | wc -l
```
1. Do not treat `admin-web` and `tracker-web` as VM-hosted production surfaces.
2. Deploy them to Vercel and configure them to use `https://api.bytelyst.com`.
3. Point `admin.bytelyst.com` and `tracker.bytelyst.com` to Vercel.
4. Do not add dashboard routes to `/opt/bytelyst/Caddyfile`.
### A4
@ -194,5 +170,5 @@ Suggested commits:
- `feat(gateway): replace Traefik with Caddy for HTTPS path routing`
- `feat(gateway): expose Gitea npm registry via HTTPS at gitea.bytelyst.com`
- `fix(deployment): resolve admin-web and tracker-web containers`
- `docs(architecture): move dashboards to Vercel and keep VM backend-only`
- `chore(security): lock down Azure NSG to 22/80/443 only`