CLI Reference
Complete reference for all xeroops commands. Commands follow a strict lifecycle order — run them in sequence the first time.
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
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
init
Generates:
- WireGuard server keypair (unique per deployment)
- WireGuard bootstrap client keypair
- SSH RSA-4096 keypair
- CloudFront RSA-2048 keypair for signed URLs
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
Creates in order, with full rollback on failure:
- VPC + public and private subnets
- Internet Gateway + route tables
- S3 VPC Endpoint (all nodes access S3 without internet)
- 9 security groups (lb, wireguard, app, postgres, redis, management, internal_communication, internal_ssh, ssh_from_lb)
- EC2 KeyPair (imports SSH public key)
- IAM Role + Instance Profile with S3, EC2, Route53, SES permissions
- 4 S3 buckets (uploads, pgdump, walg, logs)
- 7 ENIs with static private IPs
- 2 EBS data volumes for db1 and db2
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:
config/instance-config.env— non-secret instance configurationconfig/prod-credentials.env— generated secretsconfig/service-ports.json— role-to-service mapping
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
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
Launch sequence:
- Pre-flight: verify 3 required S3 config files exist
- Check no existing instances (must
cleanupfirst) - Confirm instance list with user
- Pre-allocate Elastic IPs
- Launch all instances in parallel using pre-created ENIs
- Wait for db instances, attach EBS volumes
- Associate EIPs to ENIs
- Update Route53 DNS — uses the app domain from local state if set; otherwise checks your S3 uploads bucket for one set later via
set-domainor the dashboard, so a domain never has to be re-entered on every redeploy - Patch
~/.xeroops/xeroops.confwith 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
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
certbot command needed.cleanup
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.
xeroops deploy in the morning to get back up in 60 seconds.status
Displays: license info, deployment config, infrastructure resource IDs, ENIs, EBS volumes, EIPs.
destroy
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
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.
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