fix(deploy): use single-level apess-api.redclaw.dev for the API host
api.apess.redclaw.dev is a multi-level subdomain that Cloudflare Universal SSL and the *.redclaw.dev origin cert don't cover (edge TLS handshake fails). Switch the API host to apess-api.redclaw.dev, which the existing edge + origin certs cover with no paid Cloudflare features. Updates the client API base default, the Traefik router host, and deploy docs. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
0eea6efdec
commit
d58065d292
@@ -5,7 +5,7 @@ Production web app for the **15th Asia-Pacific-Euro Summer School on Smart Struc
|
|||||||
Guides 60+ PhD students across 15 teams from kit unboxing → ZeroClaw firmware deployment → Agent Design Document (ADD) submission in a single 5.5-hour session.
|
Guides 60+ PhD students across 15 teams from kit unboxing → ZeroClaw firmware deployment → Agent Design Document (ADD) submission in a single 5.5-hour session.
|
||||||
|
|
||||||
- **Live URL** (planned): https://apess.redclaw.dev
|
- **Live URL** (planned): https://apess.redclaw.dev
|
||||||
- **API** (planned): https://api.apess.redclaw.dev
|
- **API** (planned): https://apess-api.redclaw.dev
|
||||||
- **Host node**: `zeroclaw-gw-03` (Architect)
|
- **Host node**: `zeroclaw-gw-03` (Architect)
|
||||||
- **PRD**: `APESS-2026-Workshop-PRD-v1.0.docx` (separate, confidential)
|
- **PRD**: `APESS-2026-Workshop-PRD-v1.0.docx` (separate, confidential)
|
||||||
|
|
||||||
|
|||||||
+10
-9
@@ -3,15 +3,16 @@
|
|||||||
Drops `apess-web` (static SPA) and `apess-api` (collective backend) next to the existing ClawBooks stack on `zeroclaw-gw-03` (Architect). Reuses ClawBooks' Traefik v3.6 instance via the shared `clawbooks-net` Docker network.
|
Drops `apess-web` (static SPA) and `apess-api` (collective backend) next to the existing ClawBooks stack on `zeroclaw-gw-03` (Architect). Reuses ClawBooks' Traefik v3.6 instance via the shared `clawbooks-net` Docker network.
|
||||||
|
|
||||||
- `apess.redclaw.dev` → `apess-web` (nginx static)
|
- `apess.redclaw.dev` → `apess-web` (nginx static)
|
||||||
- `api.apess.redclaw.dev` → `apess-api` (Node/Express + SQLite + WebSocket) — powers `/admin` and `/judge`
|
- `apess-api.redclaw.dev` → `apess-api` (Node/Express + SQLite + WebSocket) — powers `/admin` and `/judge`
|
||||||
|
|
||||||
## Prerequisites (one-time, on gw-03)
|
## Prerequisites (one-time, on gw-03)
|
||||||
|
|
||||||
1. **Cloudflare DNS** — add `A` records (proxied):
|
1. **Cloudflare DNS** — add `A` records (proxied):
|
||||||
- `apess.redclaw.dev` → `37.27.250.130`
|
- `apess.redclaw.dev` → `37.27.250.130`
|
||||||
- `api.apess.redclaw.dev` → `37.27.250.130`
|
- `apess-api.redclaw.dev` → `37.27.250.130`
|
||||||
2. **Cloudflare Origin Certificate** — issue from CF dashboard:
|
2. **Cloudflare Origin Certificate** — already in place from the web deploy:
|
||||||
- Hostnames: `*.redclaw.dev`, `redclaw.dev` (covers all subdomains — `api.` included)
|
- Hostnames: `*.redclaw.dev`, `redclaw.dev` — covers single-level subdomains, so
|
||||||
|
`apess-api.redclaw.dev` is covered (a multi-level host like `api.apess.…` would NOT be).
|
||||||
- Validity: 15 years
|
- Validity: 15 years
|
||||||
- Save:
|
- Save:
|
||||||
- `/etc/ssl/redclaw/apess.pem` (root:root 644)
|
- `/etc/ssl/redclaw/apess.pem` (root:root 644)
|
||||||
@@ -52,17 +53,17 @@ docker logs -f apess-api # verify "[apess-api] listening on :3000"
|
|||||||
curl -fsS https://apess.redclaw.dev/healthz # → ok
|
curl -fsS https://apess.redclaw.dev/healthz # → ok
|
||||||
|
|
||||||
# Backend REST
|
# Backend REST
|
||||||
curl -fsS https://api.apess.redclaw.dev/healthz # → ok
|
curl -fsS https://apess-api.redclaw.dev/healthz # → ok
|
||||||
curl -fsS -o /dev/null -w '%{http_code}\n' \
|
curl -fsS -o /dev/null -w '%{http_code}\n' \
|
||||||
https://api.apess.redclaw.dev/teams # → 401 (no code)
|
https://apess-api.redclaw.dev/teams # → 401 (no code)
|
||||||
curl -fsS -X PUT https://api.apess.redclaw.dev/teams/smoke \
|
curl -fsS -X PUT https://apess-api.redclaw.dev/teams/smoke \
|
||||||
-H 'content-type: application/json' -d '{"name":"smoke","kit":"KIT-00"}' # → 204
|
-H 'content-type: application/json' -d '{"name":"smoke","kit":"KIT-00"}' # → 204
|
||||||
curl -fsS https://api.apess.redclaw.dev/teams \
|
curl -fsS https://apess-api.redclaw.dev/teams \
|
||||||
-H "X-Access-Code: $ADMIN_CODE" | head -c 200 # → JSON incl. the smoke team
|
-H "X-Access-Code: $ADMIN_CODE" | head -c 200 # → JSON incl. the smoke team
|
||||||
|
|
||||||
# Backend WebSocket (run days before the event, not on July 27)
|
# Backend WebSocket (run days before the event, not on July 27)
|
||||||
# from a browser console on https://apess.redclaw.dev:
|
# from a browser console on https://apess.redclaw.dev:
|
||||||
# new WebSocket(`wss://api.apess.redclaw.dev/ws?code=${ADMIN_CODE}`).onmessage = e => console.log(e.data)
|
# new WebSocket(`wss://apess-api.redclaw.dev/ws?code=${ADMIN_CODE}`).onmessage = e => console.log(e.data)
|
||||||
# → a {"type":"snapshot",...} frame on connect
|
# → a {"type":"snapshot",...} frame on connect
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
http:
|
http:
|
||||||
routers:
|
routers:
|
||||||
apess-api:
|
apess-api:
|
||||||
rule: "Host(`api.apess.redclaw.dev`)"
|
rule: "Host(`apess-api.redclaw.dev`)"
|
||||||
entryPoints:
|
entryPoints:
|
||||||
- websecure
|
- websecure
|
||||||
service: apess-api
|
service: apess-api
|
||||||
|
|||||||
+1
-1
@@ -9,7 +9,7 @@ import type {
|
|||||||
} from '@/types'
|
} from '@/types'
|
||||||
|
|
||||||
export const API_BASE =
|
export const API_BASE =
|
||||||
(import.meta.env.VITE_API_BASE as string | undefined) ?? 'https://api.apess.redclaw.dev'
|
(import.meta.env.VITE_API_BASE as string | undefined) ?? 'https://apess-api.redclaw.dev'
|
||||||
|
|
||||||
async function asJson<T>(res: Response, label: string): Promise<T> {
|
async function asJson<T>(res: Response, label: string): Promise<T> {
|
||||||
if (!res.ok) throw new Error(`${label} ${res.status}`)
|
if (!res.ok) throw new Error(`${label} ${res.status}`)
|
||||||
|
|||||||
Reference in New Issue
Block a user