Masterplan Optimiser
Root & controller

Operator Guide

HA Setup

Commission a provider-neutral two-node cluster. Complete every step with disposable data and certify the pair before using it for production.

Prerequisites

  • Two Ubuntu VPSs running the exact same clean Git commit.
  • Passwordless SSH from each deploy account to the other, with verified host keys.
  • One public hostname proxied through a dedicated Cloudflare Load Balancer.
  • One pool per VPS and an HTTPS monitor on /ha/ready.
  • A Cloudflare Workers account with Durable Objects and a narrowly scoped Load Balancing API token.
  • Cloudflare Origin CA certificate/key installed independently on each VPS.
  • One operator-held snapshot recovery identity with two protected off-VPS copies.

1. Create Cloudflare routing

Cloudflare

  1. Create a dedicated pool for VPS A containing only its origin address.
  2. Create a dedicated pool for VPS B containing only its origin address.
  3. Create an HTTPS monitor for /ha/ready that requires HTTP 200.
  4. Create a dedicated Load Balancer for the application hostname with both pools.
  5. Disable session affinity and custom load-balancing rules; the witness owns pool ordering.
  6. Record the zone, load balancer and two pool IDs. These identifiers are not secrets.

2. Deploy the witness

Workstation

cd infra/cloudflare-ha-witness
npm ci
npx wrangler secret put ADMIN_TOKEN
npx wrangler secret put CLOUDFLARE_API_TOKEN
npm run check
npm run deploy

ADMIN_TOKEN is a new high-entropy bootstrap secret kept on the trusted workstation. CLOUDFLARE_API_TOKEN may edit Load Balancing only for this zone. Record the Worker HTTPS URL; never store either token in Git or on an application VPS.

3. Configure both nodes

VPS SSH

First prove SSH works in each direction:

ssh -o BatchMode=yes PEER_SSH_ALIAS true

MP-OPT

On each VPS select High availability → Configure this symmetric cluster node. Use the same cluster ID and Worker URL, unique opposite node/peer IDs, and that node's peer SSH alias.

Each wizard shows its public HA age recipient and witness node token once. Store the two bootstrap values securely. After both nodes exist, select Change the peer age encryption recipient on each node and paste only the other node's public recipient.

4. Install origin TLS

Cloudflare

Issue Origin CA material valid for the exact application hostname. Keep private keys separate for each node where possible.

MP-OPT

On both nodes select High availability → Install and verify Cloudflare Origin CA TLS, then deploy/recreate the application stack and require local Caddy validation.

5. Bootstrap the cluster exactly once

Workstation

curl --fail-with-body -X POST "https://WORKER_URL/v1/clusters/CLUSTER_ID/bootstrap" \
  -H "Authorization: Bearer ADMIN_TOKEN" \
  -H "Content-Type: application/json" \
  --data '{"cluster_id":"CLUSTER_ID","node_a_id":"NODE_A","node_a_token":"NODE_A_TOKEN","node_a_pool_id":"NODE_A_POOL_ID","node_b_id":"NODE_B","node_b_token":"NODE_B_TOKEN","node_b_pool_id":"NODE_B_POOL_ID","initial_holder":"NODE_A","zone_id":"ZONE_ID","load_balancer_id":"LOAD_BALANCER_ID"}'

The endpoint is creation-only. The response must name the requested holder and generation 1. Wait until routing readiness becomes true.

6. Configure recovery and seed the peer

MP-OPT

  1. On the holder, configure the shared public snapshot recovery recipient.
  2. Require matching local/peer recipient SHA-256 values.
  3. Choose manual portable or automatic SSH recovery storage.
  4. Select Send a complete verified copy to the peer now.
  5. Require the sender and receiver to show the same bundle ID and SHA-256.

Only after this succeeds should you begin the formal certification. Automatic failover remains disabled.