feat(deploy): serve the App Lab onboarding zip at /download/ (prod + LAN)

Turnkey hosting for the distributable app: both web containers now mount
deploy/download/ read-only and nginx serves it at /download/<file>
(autoindex off, no-store). Drop dist/apess-onboard.zip into deploy/download/
and students fetch https://apess.redclaw.dev/download/apess-onboard.zip →
App Lab "Import an app" → Run. No image rebuild to update the artifact.

The zip carries a baked cloud token, so deploy/download/*.zip is gitignored
and the URL should be treated as a secret (workshop network / access-gated,
not a public link).

Co-Authored-By: Claude Opus 4.8 <[email protected]>
This commit is contained in:
Omar Sobh
2026-07-22 14:15:15 -07:00
co-authored by Claude Opus 4.8
parent d59bbc0ef3
commit c02898a02d
6 changed files with 60 additions and 0 deletions
+4
View File
@@ -32,3 +32,7 @@ deploy/workshop-llm/.env
*.njsproj *.njsproj
*.sln *.sln
*.sw? *.sw?
# Distributable artifacts (baked token) — never commit
deploy/download/*.zip
deploy/download/*.tar*
+4
View File
@@ -8,6 +8,10 @@ services:
image: apess-web:latest image: apess-web:latest
container_name: apess-web container_name: apess-web
restart: unless-stopped restart: unless-stopped
volumes:
# Serve /download/apess-onboard.zip (the App Lab onboarding app). Drop the
# zip into deploy/download/ — no image rebuild. The zip holds a baked token.
- ./download:/usr/share/nginx/download:ro
networks: networks:
- clawbooks-net - clawbooks-net
# Routing is defined in deploy/traefik/apess.yml (file provider) to avoid # Routing is defined in deploy/traefik/apess.yml (file provider) to avoid
+26
View File
@@ -0,0 +1,26 @@
# Download directory
Drop distributable artifacts here — they're served at `/download/<file>` by both
the prod (`deploy/docker-compose.yml`) and LAN (`deploy/lan/`) web containers via a
read-only volume mount. No image rebuild needed; the container picks up new files
immediately.
## The App Lab onboarding app
```sh
# 1. build the zip (bakes in the cloud token)
export ANTHROPIC_OAUTH_TOKEN=sk-ant-oat01-…
./deploy/uno-q/package-onboard-app.sh
# 2. place it here for download
cp deploy/uno-q/dist/apess-onboard.zip deploy/download/
# 3. students fetch it (then App Lab → "Import an app" → Run)
# https://apess.redclaw.dev/download/apess-onboard.zip
```
## ⚠️ Secret
`apess-onboard.zip` contains a **baked cloud token**. Never commit it (this dir's
`*.zip` is gitignored). Treat the download URL as a secret — serve it on the
workshop network, or behind the workshop's access, not as a public link.
+3
View File
@@ -27,6 +27,9 @@ services:
- '${WEB_PORT:-80}:80' # WEB_PORT=8080 if the box can't bind :80 - '${WEB_PORT:-80}:80' # WEB_PORT=8080 if the box can't bind :80
volumes: volumes:
- ./nginx.lan.conf:/etc/nginx/conf.d/default.conf:ro - ./nginx.lan.conf:/etc/nginx/conf.d/default.conf:ro
# Serve /download/apess-onboard.zip — drop the packaged app zip into
# deploy/download/ (shared with the prod deploy). Holds a baked token.
- ../download:/usr/share/nginx/download:ro
depends_on: depends_on:
- apess-api - apess-api
networks: [apess-lan] networks: [apess-lan]
+11
View File
@@ -52,6 +52,17 @@ server {
return 200 "ok\n"; return 200 "ok\n";
} }
# Downloadable artifacts (the App Lab onboarding zip) — mounted dir, so you drop
# the file in without rebuilding (compose: ../download:/usr/share/nginx/download).
# apess-onboard.zip carries a baked cloud token; it's on the isolated workshop
# LAN, but treat the path as a secret. autoindex off = not browsable.
location /download/ {
alias /usr/share/nginx/download/;
autoindex off;
add_header Cache-Control "no-store";
try_files $uri =404;
}
# SPA fallback (client-side routes: /workshop, /admin, /judge, …) # SPA fallback (client-side routes: /workshop, /admin, /judge, …)
location / { location / {
try_files $uri $uri/ /index.html; try_files $uri $uri/ /index.html;
+12
View File
@@ -23,6 +23,18 @@ server {
add_header Cache-Control "no-cache, no-store, must-revalidate"; add_header Cache-Control "no-cache, no-store, must-revalidate";
} }
# Downloadable artifacts (the App Lab onboarding zip). Served from a MOUNTED
# dir so you drop files in without rebuilding the image (see docker-compose:
# ./download:/usr/share/nginx/download:ro). NOTE: apess-onboard.zip carries a
# baked cloud token — treat the URL as a secret (share on the workshop network,
# not publicly). autoindex off so the directory can't be browsed.
location /download/ {
alias /usr/share/nginx/download/;
autoindex off;
add_header Cache-Control "no-store";
try_files $uri =404;
}
location = /healthz { location = /healthz {
access_log off; access_log off;
return 200 "ok\n"; return 200 "ok\n";