Skip to content

Checking access...

Infrastructure & Deployment

This document covers the production and staging infrastructure for Hello World DAO: the Hetzner VPS, Cloudflare DNS, Docker-based oracle-bridge deployment, and the FounderyOS Kubernetes cluster on AX42-U.


Hetzner VPS (oracle-bridge Staging)

The oracle-bridge off-chain service is deployed to a Hetzner server in Helsinki.

PropertyValue
ProviderHetzner Cloud
LocationHelsinki, Finland
IP65.21.149.226
SSHssh -i ~/.ssh/oracle-bridge-deploy deploy@65.21.149.226

Docker Containers

Oracle-bridge runs as Docker containers managed by Docker Compose:

ContainerPortPurpose
oracle-bridge-staging8787Staging environment
oracle-bridge-production8788Production environment
bash
# SSH to VPS
ssh -i ~/.ssh/oracle-bridge-deploy deploy@65.21.149.226

# View running containers
docker ps

# View staging logs (last 100 lines)
docker logs oracle-bridge-staging --tail 100 -f

# Restart staging container
docker compose -f ~/oracle-bridge/docker-compose.staging.yml restart

Docker Compose Directory

Compose files and .env files live in ~/oracle-bridge/ on the VPS. Never edit these manually in production — changes are managed by CI/CD.

Container Registry

Images are published to GitHub Container Registry:

ghcr.io/hello-world-co-op/oracle-bridge:staging   (latest staging build)
ghcr.io/hello-world-co-op/oracle-bridge:latest     (latest production build)
ghcr.io/hello-world-co-op/oracle-bridge:v0.x.x     (versioned release tags)

PEM and CA Certificates

Secrets stored on the VPS:

PathContentsPermissions
/etc/oracle-bridge/github-ci-identity.pemIC identity for canister calls640 root:docker
/etc/oracle-bridge/proton-bridge-ca.crtInternal CA cert640 root:docker

These are mounted read-only into containers via the compose file. To rotate: update the file on the VPS and restart the container.


CI/CD — Docker Build & Deploy

Oracle-bridge uses GitHub Actions for automated deployment. Manual dfx deploy or SSH deploys are not used.

Workflow Files

WorkflowFileTrigger
Staging deploydocker-build.ymlPush to main
Production deploydeploy-production.ymlGitHub Release event

Staging Deploy Flow

git push origin main


GHA: docker-build.yml
    ├── Build Docker image
    ├── Push to ghcr.io:staging
    └── SSH to VPS → docker compose pull + up -d

To check deploy status:

bash
# View latest staging deploy run
gh run list --workflow=docker-build.yml --repo Hello-World-Co-Op/oracle-bridge --limit 5

# View logs for a specific run
gh run view <run-id> --log

Production Release Flow

gh release create v0.x.x --title "..." --notes "..."


GHA: deploy-production.yml
    ├── Build Docker image
    ├── Push to ghcr.io:latest + ghcr.io:v0.x.x
    └── SSH to VPS → docker compose pull + up -d (production container)

Cloudflare DNS

DNS for helloworlddao.com migrated from GoDaddy to Cloudflare in February 2026.

PropertyValue
Nameserverslewis.ns.cloudflare.com, audrey.ns.cloudflare.com
Zone IDc568354061b31b7b1c96f9cd2f98c4a4
Credentials~/.config/cloudflare/credentials.env

DNS Sync Script

DNS records are managed declaratively via ops-infra/scripts/cloudflare-dns-sync.sh. This script defines all 61+ records and syncs them to Cloudflare.

bash
# Dry run — shows what would change
./ops-infra/scripts/cloudflare-dns-sync.sh --dry-run

# Apply changes
./ops-infra/scripts/cloudflare-dns-sync.sh

Important: IC boundary node records MUST be proxied: false (DNS-only, grey cloud). Cloudflare's auto-import sets proxied: true for all records — the sync script corrects this. Proxied IC records break canister routing.

DDNS Script

Sector7 (Graydon's network) uses a DDNS cron job to keep DNS current with the dynamic WAN IP:

bash
# Script location
ops-infra/scripts/cloudflare-ddns-helloworlddao.sh

# Current Sector7 WAN IP (as of 2026-02-28)
71.73.242.88

Key DNS Records

SubdomainTypeTargetNotes
wwwCNAMEIC boundary nodeMarketing suite canister
portalCNAMEIC boundary nodeDAO suite canister
adminCNAMEIC boundary nodeDAO admin suite canister
oracleA65.21.149.226Oracle bridge (staging on 8787)
staging-oracleA65.21.149.226Explicit staging endpoint
think-tankCNAMEIC boundary nodeThink Tank suite
ottercampCNAMEIC boundary nodeOtter Camp suite
governanceCNAMEIC boundary nodeGovernance suite

Unmanaged Records

These records exist in Cloudflare but are NOT managed by the sync script:

RecordReason
_domainconnectGoDaddy artifact — safe to leave
_gh-hello-world-coop-dao-eGitHub org verification — do not delete

IC Custom Domain API

To transfer a custom domain between IC canisters (e.g., promote staging canister to production):

bash
# Trigger domain transfer
curl -X PATCH https://icp0.io/custom-domains/v1/helloworlddao.com \
  -H "Content-Type: application/json" \
  -d '{"canister_id": "<new-canister-id>"}'

You must also remove the domain from the old canister's .well-known/ic-domains file before or after the API call. See IC Custom Domain Runbook for the full procedure.


Sector7 Kubernetes Cluster (FounderyOS)

FounderyOS (the off-chain SaaS platform) runs on a Kubernetes cluster hosted on Graydon's Sector7 network.

Cluster Nodes

NodeIPRoleRAMGPUNotes
Aurora192.168.2.159control-plane, gpu-compute64 GBGTX 1070Primary Ollama, k8s control
Theo192.168.2.160worker, compute16 GBGTX 1060Dedicated Ollama (Coby)
Library192.168.2.231worker, storage32 GBPostgreSQL PVCs
Knower192.168.2.93workstationTainted NoSchedule

kubectl Access

bash
# kubectl binary
~/.local/bin/kubectl

# Kubeconfig
~/.kube/config

# Context and cluster
context: sector7-coby
cluster: sector7 https://192.168.2.159:6443
bash
# Check cluster status
kubectl cluster-info --context sector7-coby

# List pods in hello-world namespace
kubectl get pods -n hello-world

# View pod logs
kubectl logs -n hello-world <pod-name> --tail 100 -f

Namespaces

NamespacePurposeQuota
hello-worldFounderyOS API, workers, OllamaResourceQuota applied
the-flourishAffiliate projectView-only for Coby

Coby's RBAC: edit on hello-world, view on the-flourish. No longer cluster-admin (post-S206).

FounderyOS Services

ServiceInternal AddressExternalNotes
APIfounderyos-api-svc.hello-worldfounderyos.devNode.js + Fastify
PostgreSQLpostgres-svc.hello-world:5432Neon-compatible
Ollama (Theo)ollama-theo-svc.hello-world:11434192.168.2.159:31434 (NodePort)Coby's dedicated
Ollama (Aurora)192.168.2.159:31434Graydon's primary
GlitchTipglitchtip.founderyos.devError tracking

Tailscale VPN

Cluster access (from outside Sector7 LAN) requires Tailscale:

bash
# Tailnet
hello-world-co-op.org.github

# Coby's identity
RationalSolutions@hello-world-co-op.org.github
bash
# Check Tailscale peers
tailscale status

# Ping Aurora control plane
ping 192.168.2.159

Database Migrations (FounderyOS)

FounderyOS uses Prisma for database schema management:

bash
# Apply pending migrations (from founderyos-api repo)
npx prisma migrate deploy

# Generate Prisma client after schema changes
npx prisma generate

Migrations run automatically on deploy via the founderyos-api pod's startup script. For manual migration during incidents:

bash
# Exec into API pod
kubectl exec -it -n hello-world <founderyos-api-pod> -- sh

# Run migration inside pod
npx prisma migrate deploy

Cycle Monitoring

The IC canister fleet (30+ canisters, ~30 TC total) is monitored via:

  • Local script: ops-infra/scripts/check-cycles.sh
  • GHA cron: ops-infra/.github/workflows/monitor-metrics.yml (runs every 6 hours)
  • Minimum balance: 100B cycles per canister

Canisters with high burn rates (user-service ~378M cycles/day, membership) require monthly top-ups. Top-up command:

bash
# Convert ICP to cycles and top up a canister
dfx ledger top-up <canister-id> --amount <icp> --network ic

Resource Stability Rules

These rules apply to all cluster workloads (learned from EPIC-033 OOM crash resolution):

  1. k3s reserves 2 GiB memory on all nodes (systemReserved)
  2. kubelet eviction triggers at < 500 Mi available
  3. All pods must have resources.limits and resources.requests set
  4. LimitRange and ResourceQuota are enforced per namespace
  5. Vitest test workers: maxThreads: 4 to prevent OOM during CI

Violating these rules causes node OOM and pod eviction cascades. Review ops-infra/k8s/ for current LimitRange and ResourceQuota manifests.

Hello World Co-Op DAO