Files
hermes-mcp/DEPLOY.md
Garfield 02398258a5 feat: native OAuth login page, architecture docs, docs site update
- Add GET/POST /login to hermes for first-party cookie during OAuth popup
  (fixes browser CHIPS cookie partitioning that broke claude.ai connection)
- Add role column to all findCustomer* SQL queries in src/auth.ts
- Add claude.ai tab to docs/getting-started.html with OAuth flow steps
- Add ARCHITECTURE.md with system diagrams, data flow, and key invariants
- Rewrite README.md and DEPLOY.md to reflect actual MicroK8s deployment
- Deploy updated docs site (squaremcp-docs sha256 updated)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-14 13:48:01 -04:00

4.4 KiB

Hermes MCP — Deployment Runbook

Production deployment runs on a single-node MicroK8s cluster in the fetcherpay namespace. Three services are deployed: hermes-mcp (API), squaremcp-app (SaaS UI), squaremcp-docs (docs).


Prerequisites

  • MicroK8s with addons: dns, ingress, registry, cert-manager
  • Local image registry at localhost:32000
  • ClusterIssuer named letsencrypt-prod configured
  • MySQL 8 running as Docker container on host (127.0.0.1:3306)
  • Redis 7 running as Docker container on host (127.0.0.1:6379)

Deploying hermes-mcp

# 1. Build TypeScript
npm run build

# 2. Build and push Docker image
docker build -t localhost:32000/hermes-mcp:latest .
docker push localhost:32000/hermes-mcp:latest

# 3. Get the sha256 digest from push output, or:
docker inspect localhost:32000/hermes-mcp:latest \
  --format='{{index .RepoDigests 0}}'

# 4. Update hermes-k8s.yaml
# Change: image: localhost:32000/hermes-mcp@sha256:<old>
# To:     image: localhost:32000/hermes-mcp@sha256:<new>

# 5. Apply
microk8s kubectl apply -f hermes-k8s.yaml

# 6. Wait for rollout
microk8s kubectl rollout status deployment/hermes-mcp -n fetcherpay

Important: hermes-k8s.yaml is gitignored — it contains plaintext secrets. Never force-add it to git. Always use sha256 digest (never :latest) in the manifest.


Deploying squaremcp-app (dashboard UI)

docker build -f product/app/Dockerfile . -t localhost:32000/squaremcp-app:latest
docker push localhost:32000/squaremcp-app:latest

# Update sha256 in product/app/app-k8s.yaml, then:
microk8s kubectl apply -f product/app/app-k8s.yaml

Deploying squaremcp-docs

docker build -f docs/Dockerfile . -t localhost:32000/squaremcp-docs:latest
docker push localhost:32000/squaremcp-docs:latest

# Update sha256 in docs/docs-k8s.yaml, then:
microk8s kubectl apply -f docs/docs-k8s.yaml

Useful commands

# Check pod status
microk8s kubectl get pods -n fetcherpay

# Live logs
microk8s kubectl logs -n fetcherpay -l app=hermes-mcp -f --tail=100

# Health check
curl https://hermes.squaremcp.com/health

# Inject env var without rebuild (takes effect after rollout)
microk8s kubectl set env deployment/hermes-mcp -n fetcherpay KEY=value
microk8s kubectl rollout restart deployment/hermes-mcp -n fetcherpay

# Restart all pods
microk8s kubectl rollout restart deployment -n fetcherpay

# Check TLS certificates
microk8s kubectl get certificate -n fetcherpay

Environment variables (hermes-mcp)

Key variables in hermes-k8s.yaml:

Variable Purpose
PORT Server port (3456)
SERVER_URL Public base URL (https://hermes.squaremcp.com)
MCP_API_KEY Global superadmin API key
MYSQL_HOST/PORT/USER/PASSWORD MySQL connection
REDIS_URL Redis connection (redis://127.0.0.1:6379)
CREDENTIAL_ENCRYPTION_KEY AES-256-GCM key for stored platform credentials
OAUTH_CLIENT_ID/SECRET Pre-registered OAuth app credentials
OBSIDIAN_VAULT_PATH Mount path for Obsidian vault (/vaults)
YAHOO_EMAIL / YAHOO_APP_PASSWORD Default Yahoo IMAP account
GMAIL_EMAIL / GMAIL_APP_PASSWORD Default Gmail account
FETCHERPAY_* Fetcherpay email IMAP/SMTP

Do not rotate CREDENTIAL_ENCRYPTION_KEY without first re-encrypting all stored customer credentials in Redis.


Schema migrations

src/db.ts uses ensureColumn() — an idempotent helper that ALTER TABLE ... ADD COLUMN IF NOT EXISTS. Run migrations by deploying a new image; the startup hook runs automatically.

To run a migration manually:

mysql -h 127.0.0.1 -u root -pfetcherpay hermes_oauth

Domains and TLS

Domain K8s Ingress TLS secret
hermes.squaremcp.com hermes-ingress hermes-squaremcp-tls
app.squaremcp.com squaremcp-app-ingress squaremcp-app-tls
docs.squaremcp.com squaremcp-docs-ingress squaremcp-docs-tls

TLS certificates are auto-provisioned by cert-manager from Let's Encrypt. Check certificate status:

microk8s kubectl describe certificate -n fetcherpay

Rollback

To roll back to the previous image, update the sha256 digest in the manifest to the previous value and re-apply:

microk8s kubectl apply -f hermes-k8s.yaml
microk8s kubectl rollout status deployment/hermes-mcp -n fetcherpay