Skip to main content

Architecture

Each intern is a Hetzner Cloud VM (CX33 — 4 vCPU, 8GB RAM) running a full development stack, connected to the outside world via Cloudflare Tunnel.

Infrastructure

Services

OpenClaw (Port 18789)

The AI gateway that connects Slack to Claude Code CLI. Runs as the agent user with systemd.
  • Auth: Password + token (dual layer)
  • Channels: Slack (socket mode)
  • Model: Claude Haiku for orchestration, Claude CLI for coding
  • Tools profile: Full (includes gog for Google Workspace)

Cloudflare Tunnel

Named tunnel with persistent URLs. Three subdomains per instance:
SubdomainRoutes toPurpose
<name>.lunarintern.comOpenClaw :18789Dashboard & agent control
api-<name>.lunarintern.comDjango :8000Backend API
app-<name>.lunarintern.comNginx :4200Angular frontend

Docker Stack

ContainerImagePurpose
postgrespostgres:15Application database (seeded from KV dump)
redisredis:7-alpineCache + session store
backendpython:3.11-slimDjango API server
frontend-buildernode:24-slimBuilds Angular (runs once, exits)
frontendnginx:alpineServes compiled Angular app
mailpitaxllent/mailpitLocal email testing

Claude Code CLI

Runs as the agent user (non-root) with --permission-mode bypassPermissions. Uses your Claude Team subscription via OAuth — no API tokens consumed.

Security

LayerProtection
Password32-byte random, unique per instance
TokenSeparate gateway token for API access
HTTPSEnforced by Cloudflare (no plaintext)
OriginsLocked to instance hostname only
Proxy TrustOnly Cloudflare IPs accepted
FirewallHetzner firewall attached at creation
AuthallowInsecureAuth: false

Data Flow

Secrets Management

Secrets are stored in Cloudflare Workers KV and pulled at boot time. Nothing is committed to git.
SecretStorage
LayerFive backend .envCloudflare KV (LAYERFIVECORE_ENV)
Database seedCloudflare KV (DB_SEED_DUMP)
API keys (Hetzner, CF, etc.)Supabase Edge Function secrets
Per-instance secretsInjected via cloud-init at boot

State Management

All agent state is stored in Supabase:
  • agents — identity, status, capacity
  • tasks — Linear tickets being worked on
  • pull_requests — PRs created by agents
  • pr_comments — review comment tracking
  • activity_log — audit trail

Snapshot

The base VM image (Hetzner snapshot) contains:
  • Node.js 24, Python 3.11, Go, Docker
  • OpenClaw, Claude CLI (pre-authenticated), cloudflared, gh, gogcli
  • Pre-cloned repos: layerfivecore, l5ui, docs
  • Pre-pulled Docker images
  • 18 agent tools (Linear, Slack, GitHub, Supabase, rebuild)
  • Workspace docs (AGENTS.md, TOOLS.md, IDENTITY.md)
  • 4GB swap file
Cloud-init injects per-instance config on first boot.