Reference
CLI reference
Project & config
cumulus init # scaffold cumulus.toml interactively
cumulus validate # parse and validate cumulus.toml
cumulus apps # list declared apps
cumulus login # sign in via the browser (GitHub OAuth)
cumulus link # register project from cumulus.toml
cumulus aws connect # connect your AWS account
Servers (EC2)
cumulus server create [name] # provision an EC2 server
cumulus server list # list managed servers
cumulus server shell <name> # open an SSM session (operator)
cumulus server delete <name> # terminate a server
Deploy & operate
cumulus app deploy <app> [--sha <sha>] # deploy (defaults to HEAD)
cumulus app status <app> # latest deploy + phase per env
cumulus app restart <app> # restart service in place
cumulus app logs <app> # tail live logs
cumulus app releases <app> # list retained releases
cumulus app promote <app> --from <env> --to <env> # promote a known-good sha
cumulus app run <app> <task> # run a declared task on the server
cumulus app env-set <app> KEY=VALUE [--secret] # set an env var
cumulus app env-pull <app> # print KEY=VALUE lines
Projects & apps
The same app operations, addressed by project/app name or UUID rather than a linked app (handy in CI, or before cumulus link):
cumulus project list # list your projects
cumulus project create --name ... --region ... --repo ... --branch ... # register a project
cumulus app create <project> --name ... --runtime ... --target ... # add an app to a project
cumulus app deploy <project/app> --sha <sha> # deploy a specific commit
cumulus app deployments <project/app> # list past deployments
cumulus app status <project/app> # latest deploy + phase per env
cumulus app logs <project/app> # tail live logs
cumulus app releases <project/app> # list retained releases
cumulus app promote <project/app> --from <env> --to <env> # promote a known-good sha
cumulus app env-set <project/app> KEY=VALUE [--secret] # set an env var
cumulus app env-pull <project/app> # print KEY=VALUE lines
cumulus app run <project/app> <task> # run a declared task
cumulus app restart <project/app> # restart the service in place
Team
Organizations own every resource. Invite teammates with a role (Owner, Admin, Member, Billing, Viewer).
cumulus org invite-member <org-id> --email ... --role ... # invite a member by email
cumulus org members <org-id> # list members and roles
cumulus org accept <org-id> # accept a pending invite
cumulus.toml reference
[project]
name = "my-saas" # project name
region = "us-east-1" # AWS region
[[app]]
name = "api" # app name (unique in project)
runtime = "rust" # rust | python | static
target = "ec2" # ec2 | lambda | s3
source = "." # optional, defaults to the repo root (set a subdir for a monorepo)
binary = "api" # Rust: the [[bin]] name in Cargo.toml
server = "prod-1" # EC2: server name from `cumulus server create`
features = ["aws", "postgres"] # Rust: Cargo features to enable
# [app.health_check] # optional: gates deploys on a live readiness probe
# path = "/health" # if omitted, Cumulus waits a fixed interval before cutover
# port = 8080
# timeout_s = 10
[app.python] # python/ec2 only
version = "3.12"
entry = "main:app" # module:variable
server = "uvicorn" # uvicorn | gunicorn | none
workers = 2
[app.lambda] # rust/lambda or python/lambda
handler = "main.handler" # Python: module.function; Rust: "bootstrap"
python_version = "3.12" # python/lambda only
memory_mb = 256 # default 512
timeout_s = 29 # default 30
architecture = "arm64" # arm64 (default) | x86_64
[app.lambda.url] # optional Function URL
enabled = true
auth = "none" # none | iam
[app.s3] # static/s3 only
bucket = "my-site-bucket"
kms_key_arn = "arn:aws:kms:..."
[app.build] # static/s3 only
command = "npm run build"
output_dir = "out"
node_version = "20"
[app.cdn] # static/s3: CloudFront + ACM
enabled = true
custom_domain = "app.example.com"
hosted_zone_id = "Z1ABC123" # optional; auto-discovered
[app.tls] # EC2: ALB + ACM
enabled = true
domain = "api.example.com"
subnets = ["subnet-az-a", "subnet-az-b"]
hosted_zone_id = "Z1ABC123"
[app.storage] # EC2 or Lambda: S3 buckets for user uploads, one per entry
uploads = { cors_origins = ["https://app.example.com"] } # reads STORAGE_UPLOADS_BUCKET / _REGION
exports = { glacier_days = 30 } # default 90; 0 disables the Glacier rule
[app.env] # environment variables
LOG_LEVEL = "info" # inline value
DATABASE_URL = { secret = "/cumulus/api/DATABASE_URL" } # SSM SecureString
[app.tasks] # on-demand tasks (run with `cumulus app run`)
migrate = "python manage.py migrate --noinput"
shell = "python manage.py shell"
release = ["migrate"] # tasks run before cutover on each deploy
[app.environments.staging] # per-environment overrides
server = "staging-1"
Environment variables
| Variable | Purpose |
|---|---|
AWS_PROFILE |
AWS credential profile |
AWS_REGION |
AWS region (overrides cumulus.toml) |
CUMULUS_SSM_PREFIX |
SSM path prefix (default: cumulus) |
CUMULUS_LAMBDA_ROLE_ARN |
Lambda execution role ARN (auto-created if absent) |
CUMULUS_HOME |
Override config directory (default: ~/.cumulus) |