Documentation

Command Lifecycle

── First-time setup (run once) ──────────────────────
xeroops activate    Validate and store your license
xeroops init        Generate keys, copy AMIs to your region
xeroops create      Provision VPC, ENIs, S3, IAM, uploads config
xeroops verify      Confirm all resources exist in AWS

── Daily workflow ────────────────────────────────────
xeroops deploy      Launch EC2 instances from AMIs
xeroops set-domain  Point your domain's DNS at the load balancer
xeroops cleanup     Terminate EC2s (keep everything else)

── Utilities ─────────────────────────────────────────
xeroops status          Show current state (no AWS calls)
xeroops destroy         Delete infrastructure — S3 buckets preserved
xeroops deletes3buckets Delete S3 buckets + all local state (after destroy)

activate

xeroops activate Validate license and store it encrypted in ~/.xeroops/
-license-dir <path> Path to your license.json file. Required.

Verifies the RSA-PSS signature on your license, calls AWS STS to get your account ID, and confirms it matches the license's account_id. The validated license is stored encrypted at ~/.xeroops/license.enc.

xeroops activate -license-dir ./license.json
⚠️
Your license is cryptographically bound to one AWS account. Running in any other account will fail with an account mismatch error.

init

xeroops init Generate all cryptographic keys and prepare deployment config
(interactive) Prompts for AWS region and optionally a VPN domain for Route53 DNS.

Generates:

If your region differs from the AMI source region, both AMIs are copied automatically — this takes 5–10 minutes. Public keys are saved to deployment.json; private keys are AES-256-GCM encrypted in state.enc. Your WireGuard client config is written to ~/.xeroops/xeroops.conf.

create

xeroops create Provision all AWS infrastructure except EC2 instances, and upload config to S3
(no flags) Reads deployment config from state generated by init.

Creates in order, with full rollback on failure:

All secrets (PostgreSQL password, admin API secrets, CloudFront signing key) are generated automatically during init — there's no separate interactive prompt for them. create uploads the resulting config to your S3 uploads bucket, where every instance pulls it from on boot:

💡
Everything created by create is either free or near-free when idle. VPC, ENIs, security groups, and IAM cost nothing. EIPs cost ~$3.50/month each when unassociated. S3 costs pennies.

verify

xeroops verify Confirm all provisioned resources exist in AWS
(no flags) Makes read-only AWS API calls. Safe to run at any time.

Calls AWS APIs to verify every resource from create still exists. Prints a pass/fail table with resource IDs. Exits with a non-zero code if any check fails — useful in scripts.

deploy

xeroops deploy Launch EC2 instances and bring the cluster online
(no flags) Pre-flight check verifies S3 config exists before launching any EC2.

Launch sequence:

  1. Pre-flight: verify 3 required S3 config files exist
  2. Check no existing instances (must cleanup first)
  3. Confirm instance list with user
  4. Pre-allocate Elastic IPs
  5. Launch all instances in parallel using pre-created ENIs
  6. Wait for db instances, attach EBS volumes
  7. Associate EIPs to ENIs
  8. Update Route53 DNS — uses the app domain from local state if set; otherwise checks your S3 uploads bucket for one set later via set-domain or the dashboard, so a domain never has to be re-entered on every redeploy
  9. Patch ~/.xeroops/xeroops.conf with real WireGuard EIP

After launch, each instance boots from its AMI, pulls config from S3, and starts services automatically. The cluster is fully operational in ~60–90 seconds.

set-domain

xeroops set-domain <domain> Point your domain's DNS A record at the load balancer
<domain> Required. The domain you want serving your app, e.g. yourdomain.com.

Safe to run at any point in your workflow — before create, right after deploy, or any time later to change domains. If no Route53 hosted zone is on file for the domain yet, it finds or creates one and offers to auto-delegate nameservers if the domain is registered through Route53 in the same AWS account.

If instances are already running, it points the domain at the current openresty-lb Elastic IP immediately. If not, it just saves the domain — xeroops deploy picks it up and sets the A record itself once the EIP exists.

xeroops set-domain yourdomain.com
💡
This is what actually turns on TLS. Once DNS resolves, the dashboard's "Domain & Let's Encrypt" tab (or a fresh boot on trial/member tier) issues the certificate automatically — no manual certbot command needed.

cleanup

xeroops cleanup Terminate EC2 instances only — preserves all other resources
(no flags) Detaches EBS volumes before termination to preserve data.

Terminates EC2 instances, detaches EBS data volumes, disassociates and releases EIPs, cleans Route53 DNS. Preserves: VPC, ENIs, security groups, EBS volumes, S3 buckets, IAM — everything needed to redeploy instantly.

💡
Run this every evening. Your overnight cost drops to ~$7/month (S3 + EIPs). Run xeroops deploy in the morning to get back up in 60 seconds.

status

xeroops status Show current state from local files — no AWS API calls
(no flags) Reads ~/.xeroops/ only. Safe and instant.

Displays: license info, deployment config, infrastructure resource IDs, ENIs, EBS volumes, EIPs.

destroy

xeroops destroy Delete VPC, EC2 networking, and IAM resources. S3 buckets are preserved.
-confirm Required. Also prompts you to type "destroy" to confirm.
--dry-run Preview what would be deleted without deleting anything.
⚠️
This is permanent, but narrower than it sounds. Deletes EBS volumes, ENIs, security groups, IAM role, and the VPC. S3 buckets are deliberately preserved — your backups and uploaded files survive. Local state also survives (just emptied of infrastructure IDs), so xeroops status still shows your license and S3 bucket names afterward. Running instances must be cleaned up first.
# Preview first
xeroops destroy --dry-run

# Actually destroy
xeroops destroy -confirm
  Type "destroy" to confirm: destroy

deletes3buckets

xeroops deletes3buckets Permanently delete S3 buckets and all remaining local state. Irreversible.
-confirm Skip the interactive y/N confirmation prompt.

The actual "complete reset" step — run it only after destroy, once the VPC and all instances are gone (it checks and refuses otherwise). Deletes every S3 bucket in state, including all backups and uploaded files, then clears ~/.xeroops/ entirely. There is no infrastructure left to xeroops status after this — you'd start over from xeroops init.

⚠️
This is the step that actually destroys your backups. xeroops destroy alone leaves your S3 buckets — and every WAL-G/pg_dump backup in them — completely intact. Only run deletes3buckets once you're certain you'll never need this deployment's data again.
xeroops deletes3buckets -confirm