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
|
||||
@@ -0,0 +1,18 @@
|
||||
FROM nginx:1.25-alpine
|
||||
|
||||
# Remove default nginx static content
|
||||
RUN rm -rf /usr/share/nginx/html/*
|
||||
|
||||
# Copy app
|
||||
COPY frontend/index.html /usr/share/nginx/html/index.html
|
||||
|
||||
# Copy nginx config
|
||||
COPY nginx.conf /etc/nginx/conf.d/default.conf
|
||||
|
||||
# Healthcheck
|
||||
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
|
||||
CMD wget -qO- http://localhost/health || exit 1
|
||||
|
||||
EXPOSE 80
|
||||
|
||||
CMD ["nginx", "-g", "daemon off;"]
|
||||
@@ -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
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,41 @@
|
||||
server {
|
||||
listen 80;
|
||||
server_name _;
|
||||
|
||||
root /usr/share/nginx/html;
|
||||
index index.html;
|
||||
|
||||
# Security headers
|
||||
add_header X-Frame-Options "SAMEORIGIN" always;
|
||||
add_header X-Content-Type-Options "nosniff" always;
|
||||
add_header X-XSS-Protection "1; mode=block" always;
|
||||
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
|
||||
|
||||
# CSP — allows Anthropic API calls and Google Fonts
|
||||
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; font-src 'self' https://fonts.gstatic.com; img-src 'self' data: blob:; connect-src 'self' https://api.anthropic.com; worker-src blob:;" always;
|
||||
|
||||
# Gzip
|
||||
gzip on;
|
||||
gzip_types text/html text/css application/javascript;
|
||||
gzip_min_length 1024;
|
||||
|
||||
# Health endpoint
|
||||
location /health {
|
||||
access_log off;
|
||||
return 200 "ok\n";
|
||||
add_header Content-Type text/plain;
|
||||
}
|
||||
|
||||
# SPA fallback
|
||||
location / {
|
||||
try_files $uri $uri/ /index.html;
|
||||
expires -1;
|
||||
add_header Cache-Control "no-store, no-cache, must-revalidate";
|
||||
}
|
||||
|
||||
# Cache static assets aggressively if you add any
|
||||
location ~* \.(js|css|png|jpg|jpeg|gif|ico|woff2)$ {
|
||||
expires 1y;
|
||||
add_header Cache-Control "public, immutable";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
version: "3.8"
|
||||
|
||||
services:
|
||||
rongorongo:
|
||||
image: registry.hobbs.farm/rongorongo:latest
|
||||
networks:
|
||||
- traefik-public
|
||||
deploy:
|
||||
replicas: 1
|
||||
restart_policy:
|
||||
condition: on-failure
|
||||
delay: 10s
|
||||
max_attempts: 3
|
||||
update_config:
|
||||
parallelism: 1
|
||||
delay: 10s
|
||||
failure_action: rollback
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.docker.network=traefik-public"
|
||||
|
||||
# HTTP → HTTPS redirect
|
||||
- "traefik.http.routers.rongorongo-http.rule=Host(`rongorongo.hobbs.farm`)"
|
||||
- "traefik.http.routers.rongorongo-http.entrypoints=web"
|
||||
- "traefik.http.routers.rongorongo-http.middlewares=redirect-to-https"
|
||||
|
||||
# HTTPS router
|
||||
- "traefik.http.routers.rongorongo.rule=Host(`rongorongo.hobbs.farm`)"
|
||||
- "traefik.http.routers.rongorongo.entrypoints=websecure"
|
||||
- "traefik.http.routers.rongorongo.tls=true"
|
||||
- "traefik.http.routers.rongorongo.tls.certresolver=cloudflare"
|
||||
|
||||
# Service
|
||||
- "traefik.http.services.rongorongo.loadbalancer.server.port=80"
|
||||
|
||||
# Middlewares
|
||||
- "traefik.http.routers.rongorongo.middlewares=rongorongo-headers"
|
||||
- "traefik.http.middlewares.rongorongo-headers.headers.customResponseHeaders.X-Robots-Tag=noindex,nofollow"
|
||||
healthcheck:
|
||||
test: ["CMD", "wget", "-qO-", "http://localhost/health"]
|
||||
interval: 30s
|
||||
timeout: 5s
|
||||
retries: 3
|
||||
start_period: 10s
|
||||
|
||||
networks:
|
||||
traefik-public:
|
||||
external: true
|
||||
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user