Add gw-03 deploy artifacts (Docker + Traefik + nginx)
Stages the production deploy bundle next to the existing ClawBooks stack
on zeroclaw-gw-03. Reuses ClawBooks' Traefik v3.6 via shared
clawbooks-net Docker network, no separate proxy.
- deploy/Dockerfile.web: multi-stage Node 22 build -> nginx 1.27 alpine
- deploy/nginx.conf: SPA history fallback, asset caching, /healthz probe
- deploy/docker-compose.yml: apess-web service with Traefik labels for
apess.redclaw.dev on the websecure entrypoint
- deploy/traefik/apess.yml: TLS dynamic config pointing at the
*.redclaw.dev Cloudflare Origin Certificate (to be installed at
/etc/ssl/redclaw/apess.{pem,key} on gw-03)
- deploy/README.md: prereqs (CF DNS + Origin Cert), deploy commands,
verification, rollback
No infra changes applied yet -- this is the artifact bundle. Deploy
pending three out-of-repo prereqs: CF DNS records, CF Origin Cert
issuance, and rsync+up on gw-03.
This commit is contained in:
@@ -0,0 +1,13 @@
|
|||||||
|
FROM node:22-alpine AS build
|
||||||
|
WORKDIR /app
|
||||||
|
RUN corepack enable
|
||||||
|
COPY package.json pnpm-lock.yaml ./
|
||||||
|
RUN pnpm install --frozen-lockfile
|
||||||
|
COPY . .
|
||||||
|
RUN pnpm build
|
||||||
|
|
||||||
|
FROM nginx:1.27-alpine
|
||||||
|
COPY deploy/nginx.conf /etc/nginx/conf.d/default.conf
|
||||||
|
COPY --from=build /app/dist /usr/share/nginx/html
|
||||||
|
EXPOSE 80
|
||||||
|
HEALTHCHECK --interval=30s --timeout=3s CMD wget -qO- http://127.0.0.1/ > /dev/null || exit 1
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
# APESS 2026 — gw-03 deploy
|
||||||
|
|
||||||
|
Drops `apess-web` next to the existing ClawBooks stack on `zeroclaw-gw-03` (Architect). Reuses ClawBooks' Traefik v3.6 instance via the shared `clawbooks-net` Docker network.
|
||||||
|
|
||||||
|
## Prerequisites (one-time, on gw-03)
|
||||||
|
|
||||||
|
1. **Cloudflare DNS** — add `A` records (proxied):
|
||||||
|
- `apess.redclaw.dev` → `37.27.250.130`
|
||||||
|
- `api.apess.redclaw.dev` → `37.27.250.130` (backend, future)
|
||||||
|
2. **Cloudflare Origin Certificate** — issue from CF dashboard:
|
||||||
|
- Hostnames: `*.redclaw.dev`, `redclaw.dev` (covers all subdomains)
|
||||||
|
- Validity: 15 years
|
||||||
|
- Save:
|
||||||
|
- `/etc/ssl/redclaw/apess.pem` (root:root 644)
|
||||||
|
- `/etc/ssl/redclaw/apess.key` (root:root 600)
|
||||||
|
3. **Traefik dynamic config** — copy `traefik/apess.yml` into the live config dir:
|
||||||
|
```bash
|
||||||
|
sudo cp deploy/traefik/apess.yml /home/redclaw/projects/clawbooks/traefik/dynamic/
|
||||||
|
```
|
||||||
|
Traefik hot-reloads the dynamic dir; no restart needed.
|
||||||
|
|
||||||
|
## Deploy
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# On macbook
|
||||||
|
ssh [email protected] "mkdir -p ~/projects/apress"
|
||||||
|
rsync -avz --exclude node_modules --exclude dist --exclude .git \
|
||||||
|
~/projects/apress/ [email protected]:~/projects/apress/
|
||||||
|
|
||||||
|
# On gw-03
|
||||||
|
ssh [email protected]
|
||||||
|
cd ~/projects/apress
|
||||||
|
docker compose -f deploy/docker-compose.yml up -d --build
|
||||||
|
docker logs -f apess-web # verify nginx is up
|
||||||
|
```
|
||||||
|
|
||||||
|
## Verify
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -fsS https://apess.redclaw.dev/ | head -5
|
||||||
|
curl -fsS https://apess.redclaw.dev/healthz # → ok
|
||||||
|
```
|
||||||
|
|
||||||
|
## Rollback
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ssh [email protected] "cd ~/projects/apress && docker compose -f deploy/docker-compose.yml down"
|
||||||
|
# Remove DNS records if needed
|
||||||
|
```
|
||||||
|
|
||||||
|
## Why this lives on gw-03
|
||||||
|
|
||||||
|
- 104 GB free disk, 16 GB Intel RAM, idle CPU
|
||||||
|
- Traefik v3.6 already terminating TLS for `clawbooks.app` & `finclaw.net`
|
||||||
|
- Shared `clawbooks-net` Docker network — Traefik auto-discovers via labels
|
||||||
|
- Single-node simplicity for a 5.5-hour workshop event
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
name: apess
|
||||||
|
|
||||||
|
services:
|
||||||
|
apess-web:
|
||||||
|
build:
|
||||||
|
context: ..
|
||||||
|
dockerfile: deploy/Dockerfile.web
|
||||||
|
image: apess-web:latest
|
||||||
|
container_name: apess-web
|
||||||
|
restart: unless-stopped
|
||||||
|
networks:
|
||||||
|
- clawbooks-net
|
||||||
|
labels:
|
||||||
|
- traefik.enable=true
|
||||||
|
- traefik.docker.network=clawbooks-net
|
||||||
|
- traefik.http.routers.apess-web.rule=Host(`apess.redclaw.dev`)
|
||||||
|
- traefik.http.routers.apess-web.entrypoints=websecure
|
||||||
|
- traefik.http.routers.apess-web.tls=true
|
||||||
|
- traefik.http.routers.apess-web.service=apess-web
|
||||||
|
- traefik.http.services.apess-web.loadbalancer.server.port=80
|
||||||
|
|
||||||
|
networks:
|
||||||
|
clawbooks-net:
|
||||||
|
external: true
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
server_name _;
|
||||||
|
root /usr/share/nginx/html;
|
||||||
|
index index.html;
|
||||||
|
|
||||||
|
gzip on;
|
||||||
|
gzip_types text/plain text/css application/json application/javascript text/xml application/xml image/svg+xml;
|
||||||
|
gzip_vary on;
|
||||||
|
gzip_min_length 256;
|
||||||
|
|
||||||
|
location / {
|
||||||
|
try_files $uri $uri/ /index.html;
|
||||||
|
}
|
||||||
|
|
||||||
|
location /assets/ {
|
||||||
|
expires 1y;
|
||||||
|
add_header Cache-Control "public, immutable";
|
||||||
|
try_files $uri =404;
|
||||||
|
}
|
||||||
|
|
||||||
|
location = /index.html {
|
||||||
|
add_header Cache-Control "no-cache, no-store, must-revalidate";
|
||||||
|
}
|
||||||
|
|
||||||
|
location = /healthz {
|
||||||
|
access_log off;
|
||||||
|
return 200 "ok\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
tls:
|
||||||
|
certificates:
|
||||||
|
- certFile: /etc/ssl/redclaw/apess.pem
|
||||||
|
keyFile: /etc/ssl/redclaw/apess.key
|
||||||
|
stores:
|
||||||
|
- default
|
||||||
Reference in New Issue
Block a user