Infrastructure and deployment pipeline for OpenClaw, using a single-writer ECS+EFS architecture with immutable images and durable state.
- ECR for container images (digest-pinned by default, tag selection supported)
- ECS on Fargate with
desired_count = 1and serialized deployments - EFS mounted via access point at
/state - Internal ALB reachable via optional Tailscale subnet router
- Secrets from Secrets Manager or SSM injected into task env
- Terraform remote state in S3 with native state locking
app/ # config-only app assets
infra/bootstrap/ # one-time backend bootstrap
infra/main/ # main stack composed from modules
.github/workflows/ # CI/CD
scripts/ # helpers
See the full step-by-step deployment guide here. Need to run the OpenClaw CLI in the deployed task? See ECS Exec instructions.
just tf-bootstrap initjust tf-bootstrap apply
Or with Terraform directly:
cd infra/bootstrapterraform initterraform apply
Capture the outputs (state bucket, KMS key) and add them to
infra/main/backend.tf or set via TF_VAR_* and backend config.
just tf-main initjust tf-main planjust tf-main apply
Or with Terraform directly:
cd infra/mainterraform initterraform planterraform apply
- PRs: Terraform lint/validate, security checks, and Docker lint/scan/tests
- Main: build/push image, tag release version, apply Terraform with digest, wait for ECS stable
- Schedule: nightly rebuild + deploy at 00:00 UTC
This repo builds the OpenClaw gateway image from upstream source. CI resolves the
latest OpenClaw release tag via the GitHub API, checks it out before the Docker
build, and passes the tag as OPENCLAW_VERSION to label the image. The pushed
image is tagged with both the repository commit SHA and the OpenClaw release tag.
Local build (manual):
- Fetch the latest release tag:
curl -fsSL https://api.github.com/repos/openclaw/openclaw/releases/latest | jq -r .tag_name
- Clone OpenClaw into
app/openclaw:git clone --depth 1 --branch "<tag>" https://github.com/openclaw/openclaw app/openclaw
- Build the image:
docker build --build-arg OPENCLAW_VERSION="<tag>" -t openclaw:local ./app
Runtime knobs:
OPENCLAW_GATEWAY_BIND(default:lan)OPENCLAW_GATEWAY_PORT(default:18789)OPENCLAW_GATEWAY_TOKEN(required for non-loopback binds; injected via Secrets Manager)- Persistent state is under
/state(config in/state/.openclaw/openclaw.json).
This repo is public. Do not commit account IDs or sensitive values. Provide
values via GitHub Actions secrets and TF_VAR_* environment variables.
