# 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