Deployment

Belt deploys serverless applications to AWS using Terraform. The CLI wraps terraform init/plan/apply with conventions for environment management, Lambda packaging, and pre-deploy backups.

Quick Deploy

belt deploy <env>              # init → plan → apply (interactive)
belt deploy prod --auto        # skip confirmation prompt
belt deploy prod --skip-backup # skip pre-deploy backup
belt deploy --backup-only      # create recovery point without deploying

First-Time Setup

# 1. Create S3 bucket for Terraform state
belt setup state

# 2. Scaffold an environment
belt generate environment dev01

# 3. Generate DynamoDB table definitions from schema
belt setup tables dev01

# 4. Initialize and deploy
belt deploy dev01

Environment Structure

Each environment lives in infrastructure/<env>/:

infrastructure/
├── modules/
│   └── main/            # Shared Terraform module
├── dev01/
│   ├── main.tf          # Module reference + provider
│   ├── variables.tf     # Variable declarations
│   ├── terraform.tfvars # Environment-specific values
│   ├── backend.tf       # S3 state backend
│   └── outputs.tf       # Exported values
└── prod/
    └── ...

What Gets Deployed

The Conveyor Belt Terraform provider reads your Ruby DSL and creates:

  1. API Gateway — HTTP API with routes matching your DSL
  2. Lambda functions — packaged Ruby code (one per gateway/function block)
  3. IAM roles — least-privilege policies for DynamoDB table access
  4. CloudWatch logs — log groups for each Lambda
  5. DynamoDB tables — from your schema definition
  6. Custom domain — if configured (Route53 + ACM certificate)

Lambda Packaging

Belt packages the lambda/ directory plus vendored gems. For path: gems (local development), Belt materializes them into vendor/cache automatically.

The Lambda entry point is specified in config/lambda/<name>.yml:

handler: lambda/<name>.lambda_handler
runtime: ruby3.3
timeout: 30
memory: 256
environment:
  ENVIRONMENT: ${var.environment}

Route Manifests

Before deploying, generate the route manifest used at runtime:

belt routes --namespace api
# → writes lambda/lib/routes/api_routes.rb

This is typically done automatically by belt deploy.

Sidecar Lambda Zips

Conveyor Belt packages Ruby lambdas. Some apps also have standalone aws_lambda_function resources (Node image processors, Cognito triggers) whose Terraform uses filename + filebase64sha256 pointing at a zip on disk.

belt deploy, belt plan, and belt apply scan infrastructure/**/*.tf for those zip paths and build any that are missing (or whose source hash changed):

The zip lives next to the source (image-processor/image-processor.zip). This is the same pre-terraform step Stowzilla's scripts/deploy.sh does for the image processor. Existing zips with no hash file are left alone.

Docker must be running for Node packages.

Terraform Commands

Belt wraps Terraform with environment awareness:

belt init <env>       # terraform init with correct backend
belt plan <env>       # terraform plan
belt apply <env>      # terraform apply
belt destroy <env>    # terraform destroy (careful!)
belt output <env>     # terraform output

Or use belt deploy <env> which runs init → plan → apply in sequence.

Pre-Deploy Backups

Configure in infrastructure/<env>/belt.rb:

Belt.configure do |config|
  config.backups do
    dynamodb :all
    retention snapshots: 90
  end
end

Backups run automatically before each deploy (DynamoDB snapshots, Cognito exports, S3 syncs). See belt explain backups for full documentation.

Environment Variables

Set BELT_ENV to avoid typing the environment every time:

export BELT_ENV=dev01
belt deploy           # uses BELT_ENV
belt deploy prod      # explicit arg wins

Frontend Deployment

For apps with a frontend:

belt deploy frontend <env>                  # build + deploy all frontends
belt deploy frontend <env> --frontend ops   # deploy one named frontend
belt frontend env <env>                     # generate .env from Terraform outputs
belt frontend list                          # show configured frontends

The directory is frontend/ by default. Multiple SPAs are declared in config/frontends.yml — see belt explain frontend. Full belt deploy <env> deploys every configured frontend after terraform apply.

See Also

Raw markdown