AWS
EC2 in a VPC clawops creates, with S3 for state.
export AWS_PROFILE=my-profile
clawops init --provider aws --region us-east-1
clawops doctor --provider aws
clawops plan --stack prod --ssh-cidr auto --out plan.json
clawops apply plan.jsonCredentials
The standard chain, unchanged: AWS_PROFILE, SSO, AWS_ACCESS_KEY_ID/AWS_SECRET_ACCESS_KEY,
or an instance role. clawops stores none of them. ~/.clawops/config.json records which profile
to read, never the credential.
Account setup it checks
clawops doctor --provider aws asks the account before anything is spent:
| Check | Why |
|---|---|
| Credentials resolve to an account | names the account id a deploy will land in |
| State bucket exists | Pulumi needs its backend before it can run |
| Instance type offered in the region | not every type is in every region, and the failure lands after the VPC, subnet, security group and address exist |
The bucket is created only when it is genuinely absent. A 404 means missing, and clawops
offers to create it with versioning on and public access blocked. A 403 means the name belongs
to another account. S3 names are global, or your credentials cannot read it, and clawops offers
no fix there because creating it would fail either way.
Permissions
| Service | Actions |
|---|---|
| EC2 | ec2:*Vpc*, ec2:*Subnet*, ec2:*SecurityGroup*, ec2:*KeyPair*, ec2:*Instance*, ec2:*InternetGateway*, ec2:*RouteTable*, ec2:*Address* |
| IAM | CreateRole, AttachRolePolicy, CreateInstanceProfile, AddRoleToInstanceProfile and their delete counterparts, the instance profile for SSM |
| S3 | GetObject, PutObject, DeleteObject, ListBucket on the state bucket |
Two additional permissions, used only by these checks:
ec2:DescribeInstanceTypeOfferings. Letsdoctorconfirm your size exists in the region. Without it the check reports as a warning naming the error, rather than passing or failing.bedrock:ListInferenceProfiles, only with Bedrock. It refuses bare foundation-model ids for on-demand inference, so clawops resolves each model to a regional inference profile at plan time and records it in the plan. Without the permission it warns and leaves the bare id, which Bedrock rejects. This is separate from the instance role, which needs onlybedrock:InvokeModelat runtime.
State
s3://clawops-state-<accountId>-<region>/clawops, derived by clawops init from the account and
region. Server-side encryption follows your bucket policy.
The region is in the name because an S3 bucket is a regional resource and Pulumi reads state on
every operation. A bucket on another continent slows every plan and apply for no visible
reason. S3 bills for storage and requests, never for the bucket itself.
Firewall
| Mode | Behaviour |
|---|---|
restricted (default) | deny-all; only the CIDRs you name reach SSH |
auto | detects your public IP at plan time and opens SSH to <ip>/32 |
open | 0.0.0.0/0, with a warning. Sandbox only |
No gateway rule exists under loopback publishing, which is the default. The gateway binds
127.0.0.1, so a rule for its port would grant no access and misread as exposure. Gateway rules
appear only with --publish-gateway all, for the CIDRs you name.
Egress is unrestricted by default. See Security for what the host reaches.
Sizes
| Alias | Type | vCPU | Memory | ~cost |
|---|---|---|---|---|
micro | t3.micro | 2 | 1 GB | ~$8/mo |
small | t3.small | 2 | 2 GB | ~$17/mo |
medium | t3.medium | 2 | 4 GB | ~$33/mo |
large | t3.large | 2 | 8 GB | |
gpu | g4dn.xlarge | 4 | 16 GB + T4 | ~$395/mo |
Or pass a type AWS names itself. Add ~$3.60/mo for the Elastic IP while the instance is stopped, and under $1/mo for state. Indicative, not a quote.
SSH user
clawops connects as ubuntu on AWS, which is not in the docker group, so day-two commands
escalate with sudo. GCP and Azure connect as clawops, which is in the group.
Full AWS guide, including resources created and the stack diagram →