chore: sync accumulated infra changes and docs
Removals: openwebui and netclaw compose + Traefik routes (both decommissioned). Updates: litellm, n8n, vaultwarden, ai-agents, media, traefik routes, CLAUDE.md (nodes/ports/known-issues), agent definitions. Additions: Rongorongo tree, LinkedStorm plan, rename-bart spec, vllm brief, tls-options and security-headers Traefik config. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,322 @@
|
||||
# RONGORONGO_DEPLOY.md
|
||||
# Rongorongo Decipherment Engine — Claude Code Deployment Guide
|
||||
# Target: hobbs.farm Docker Swarm infrastructure
|
||||
# Subdomain: rongorongo.hobbs.farm
|
||||
|
||||
---
|
||||
|
||||
## CONTEXT
|
||||
|
||||
This document instructs Claude Code to build, push, and deploy the Rongorongo
|
||||
Decipherment Engine as a containerized static web app to the hobbs.farm Swarm.
|
||||
|
||||
The app is a single-file HTML/JS application served by nginx. It calls the
|
||||
Anthropic API directly from the browser. No backend, no database. All session
|
||||
state is stored in browser localStorage.
|
||||
|
||||
Infrastructure assumptions (from existing hobbs.farm stack):
|
||||
- Docker Swarm: nodes hf-pdocker-01, hf-pdocker-02, bart
|
||||
- Traefik reverse proxy with wildcard *.hobbs.farm TLS via Cloudflare DNS
|
||||
- External overlay network: traefik-public
|
||||
- Registry: registry.hobbs.farm (if local) OR use Docker Hub as fallback
|
||||
- Portainer CE available for stack management
|
||||
- DNS: AdGuard Home with hairpin NAT for *.hobbs.farm
|
||||
|
||||
---
|
||||
|
||||
## REPOSITORY STRUCTURE
|
||||
|
||||
After cloning or creating the project, verify this structure exists:
|
||||
|
||||
```
|
||||
rongorongo/
|
||||
├── Dockerfile
|
||||
├── nginx.conf
|
||||
├── stack.yml
|
||||
├── frontend/
|
||||
│ └── index.html
|
||||
└── RONGORONGO_DEPLOY.md (this file)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## STEP 1 — VERIFY PREREQUISITES
|
||||
|
||||
Run these checks before proceeding. Stop and report any failures.
|
||||
|
||||
```bash
|
||||
# Confirm Docker and Swarm context
|
||||
docker info | grep -E "Swarm:|Manager:|Nodes:"
|
||||
|
||||
# Confirm traefik-public network exists
|
||||
docker network ls | grep traefik-public
|
||||
|
||||
# Confirm Traefik is running
|
||||
docker service ls | grep traefik
|
||||
|
||||
# Test registry connectivity (if using local registry)
|
||||
curl -s https://registry.hobbs.farm/v2/_catalog || echo "Registry unreachable — will use build-and-load method"
|
||||
|
||||
# Confirm you are on a Swarm manager node
|
||||
docker node ls
|
||||
```
|
||||
|
||||
If registry.hobbs.farm is unreachable, use the ALTERNATIVE DEPLOYMENT method
|
||||
at the bottom of this document.
|
||||
|
||||
---
|
||||
|
||||
## STEP 2 — BUILD THE IMAGE
|
||||
|
||||
```bash
|
||||
cd rongorongo/
|
||||
|
||||
# Build image
|
||||
docker build -t registry.hobbs.farm/rongorongo:latest .
|
||||
|
||||
# Verify image was created
|
||||
docker images | grep rongorongo
|
||||
```
|
||||
|
||||
Expected output: image tagged `registry.hobbs.farm/rongorongo:latest`, size
|
||||
should be ~25–40MB (nginx:alpine base + small HTML file).
|
||||
|
||||
---
|
||||
|
||||
## STEP 3 — PUSH TO REGISTRY
|
||||
|
||||
```bash
|
||||
# If registry requires auth:
|
||||
docker login registry.hobbs.farm
|
||||
|
||||
# Push
|
||||
docker push registry.hobbs.farm/rongorongo:latest
|
||||
```
|
||||
|
||||
If the push fails due to registry issues, fall through to ALTERNATIVE DEPLOYMENT.
|
||||
|
||||
---
|
||||
|
||||
## STEP 4 — DEPLOY STACK
|
||||
|
||||
```bash
|
||||
# Deploy or update the stack
|
||||
docker stack deploy -c stack.yml rongorongo --with-registry-auth
|
||||
|
||||
# Watch rollout
|
||||
docker service ps rongorongo_rongorongo --no-trunc
|
||||
```
|
||||
|
||||
Wait for the service to show `Running` status. This typically takes 15–30 seconds.
|
||||
|
||||
```bash
|
||||
# Confirm healthy
|
||||
docker service ls | grep rongorongo
|
||||
curl -s http://localhost/health # or via container exec
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## STEP 5 — DNS VERIFICATION
|
||||
|
||||
The stack.yml assumes `rongorongo.hobbs.farm` resolves to the Traefik entrypoint.
|
||||
|
||||
```bash
|
||||
# Check AdGuard Home has the record (or wildcard covers it)
|
||||
nslookup rongorongo.hobbs.farm
|
||||
|
||||
# Test internal access
|
||||
curl -sk https://rongorongo.hobbs.farm/health
|
||||
```
|
||||
|
||||
If using AdGuard Home for internal DNS and the wildcard *.hobbs.farm is already
|
||||
configured for hairpin NAT, no additional DNS entry is needed.
|
||||
|
||||
---
|
||||
|
||||
## STEP 6 — SMOKE TEST
|
||||
|
||||
Open https://rongorongo.hobbs.farm in a browser and verify:
|
||||
1. App loads with "Rongorongo · Decipherment Engine" title
|
||||
2. Sidebar navigation works (Image Corpus, Glyph Catalog, etc.)
|
||||
3. Enter an Anthropic API key in the sidebar footer input
|
||||
4. Upload a test image to the corpus
|
||||
5. Navigate to Pattern Analyzer and run an analysis
|
||||
6. Confirm AI response appears in the result box
|
||||
|
||||
---
|
||||
|
||||
## UPDATING THE APP
|
||||
|
||||
When index.html is modified:
|
||||
|
||||
```bash
|
||||
cd rongorongo/
|
||||
|
||||
# Rebuild
|
||||
docker build -t registry.hobbs.farm/rongorongo:latest .
|
||||
|
||||
# Push
|
||||
docker push registry.hobbs.farm/rongorongo:latest
|
||||
|
||||
# Force service update (pull new image)
|
||||
docker service update --image registry.hobbs.farm/rongorongo:latest --force rongorongo_rongorongo
|
||||
|
||||
# Watch update
|
||||
docker service ps rongorongo_rongorongo
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ROLLBACK
|
||||
|
||||
If something breaks after an update:
|
||||
|
||||
```bash
|
||||
docker service rollback rongorongo_rongorongo
|
||||
docker service ps rongorongo_rongorongo
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## TEARDOWN
|
||||
|
||||
To remove the service without destroying data (there is no persistent volume):
|
||||
|
||||
```bash
|
||||
docker stack rm rongorongo
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ALTERNATIVE DEPLOYMENT (no registry)
|
||||
|
||||
Use this if registry.hobbs.farm is unavailable. This method builds the image
|
||||
directly on the Swarm manager and uses `docker service create` instead of
|
||||
`stack deploy`.
|
||||
|
||||
```bash
|
||||
# On the Swarm manager node:
|
||||
cd rongorongo/
|
||||
|
||||
# Build locally
|
||||
docker build -t rongorongo:latest .
|
||||
|
||||
# Create service manually (adjust Traefik labels as needed)
|
||||
docker service create \
|
||||
--name rongorongo_rongorongo \
|
||||
--network traefik-public \
|
||||
--label "traefik.enable=true" \
|
||||
--label "traefik.docker.network=traefik-public" \
|
||||
--label "traefik.http.routers.rongorongo.rule=Host(\`rongorongo.hobbs.farm\`)" \
|
||||
--label "traefik.http.routers.rongorongo.entrypoints=websecure" \
|
||||
--label "traefik.http.routers.rongorongo.tls=true" \
|
||||
--label "traefik.http.routers.rongorongo.tls.certresolver=cloudflare" \
|
||||
--label "traefik.http.services.rongorongo.loadbalancer.server.port=80" \
|
||||
--replicas 1 \
|
||||
--restart-condition on-failure \
|
||||
rongorongo:latest
|
||||
|
||||
# Monitor
|
||||
docker service ps rongorongo_rongorongo
|
||||
```
|
||||
|
||||
NOTE: With this method, to update you must rebuild locally and run:
|
||||
```bash
|
||||
docker service update --image rongorongo:latest --force rongorongo_rongorongo
|
||||
```
|
||||
|
||||
This only works if your current node is the one running the replica. If you
|
||||
have a multi-node swarm, you should set up the registry to avoid placement issues.
|
||||
|
||||
---
|
||||
|
||||
## PORTAINER DEPLOYMENT (optional GUI method)
|
||||
|
||||
If you prefer Portainer CE:
|
||||
|
||||
1. Navigate to https://portainer.hobbs.farm (or your Portainer URL)
|
||||
2. Select the Swarm endpoint
|
||||
3. Go to Stacks → Add Stack
|
||||
4. Name: `rongorongo`
|
||||
5. Paste the contents of stack.yml into the web editor
|
||||
6. Set `registry.hobbs.farm/rongorongo:latest` as the image
|
||||
(you still need to build and push first)
|
||||
7. Click Deploy the stack
|
||||
|
||||
---
|
||||
|
||||
## ENVIRONMENT NOTES
|
||||
|
||||
The app does NOT use environment variables or Docker secrets. The Anthropic API
|
||||
key is entered by the user at runtime and stored in their browser's localStorage.
|
||||
This is intentional — the app is designed to be used by a single user (Jeremy)
|
||||
and no server-side key storage is needed or appropriate.
|
||||
|
||||
If you want to pre-populate the API key for convenience (only if the deployment
|
||||
is strictly private/internal), you can inject it at build time by modifying
|
||||
frontend/index.html before building:
|
||||
|
||||
Find this line:
|
||||
```javascript
|
||||
function getApiKey() {
|
||||
return document.getElementById('apiKeyInput').value.trim()
|
||||
```
|
||||
|
||||
And prepend a hardcoded fallback (NOT recommended for any externally accessible URL).
|
||||
|
||||
---
|
||||
|
||||
## TRAEFIK ENTRYPOINT NAMES
|
||||
|
||||
The stack.yml assumes:
|
||||
- HTTP entrypoint name: `web`
|
||||
- HTTPS entrypoint name: `websecure`
|
||||
- Cert resolver name: `cloudflare`
|
||||
|
||||
These match the standard hobbs.farm Traefik configuration. If your Traefik uses
|
||||
different names, edit the labels in stack.yml before deploying.
|
||||
|
||||
---
|
||||
|
||||
## TROUBLESHOOTING
|
||||
|
||||
**Service won't start:**
|
||||
```bash
|
||||
docker service ps rongorongo_rongorongo --no-trunc
|
||||
docker inspect $(docker ps -q --filter name=rongorongo) 2>/dev/null | grep -A5 '"State"'
|
||||
```
|
||||
|
||||
**Traefik not routing:**
|
||||
```bash
|
||||
# Check Traefik logs for rongorongo
|
||||
docker service logs traefik_traefik 2>&1 | grep -i rongorongo | tail -20
|
||||
# Confirm labels are applied
|
||||
docker service inspect rongorongo_rongorongo | grep -A2 Labels
|
||||
```
|
||||
|
||||
**TLS cert not issuing:**
|
||||
```bash
|
||||
# Wildcard cert should already cover rongorongo.hobbs.farm
|
||||
# If not, check Cloudflare DNS API token has Zone:Read and DNS:Edit
|
||||
docker service logs traefik_traefik 2>&1 | grep -i "acme\|certificate\|cloudflare" | tail -20
|
||||
```
|
||||
|
||||
**API calls blocked (CORS/CSP):**
|
||||
The nginx.conf includes a Content-Security-Policy header that allows
|
||||
`connect-src https://api.anthropic.com`. If you see CORS errors in the browser
|
||||
console, verify the CSP header is present:
|
||||
```bash
|
||||
curl -I https://rongorongo.hobbs.farm/ | grep -i content-security
|
||||
```
|
||||
|
||||
**App loads but AI calls fail:**
|
||||
- Check API key is entered correctly in the sidebar
|
||||
- Anthropic API key must start with `sk-ant-`
|
||||
- Confirm outbound HTTPS to api.anthropic.com is not blocked by firewall rules
|
||||
- The app sends `anthropic-dangerous-direct-browser-access: true` header which
|
||||
is required for direct browser API access
|
||||
|
||||
---
|
||||
|
||||
## END OF DEPLOYMENT GUIDE
|
||||
Reference in New Issue
Block a user