Appearance
AWS Resources & Runtime Access
Applications use short-lived ECS task-role credentials — never IAM users or long-lived access keys. Declare resources once and bind only the services that need them.
yaml
resources:
uploads:
type: s3
create:
versioning: true
retain: true
events:
type: sns
existing:
arn: arn:aws:sns:us-east-1:123456789012:application-events
reporting:
type: rds
existing:
identifier: reporting-prod
endpoint: reporting.internal
port: 5432
security_group_id: sg-0123456789
secret_arn: arn:aws:secretsmanager:us-east-1:123456789012:secret:reporting
kms_key_arn: arn:aws:kms:us-east-1:123456789012:key/00000000-0000-0000-0000-000000000000
services:
web:
type: web
port: 8080
health_check: /health
bindings:
- resource: uploads
access: [list, read, write]
prefix: user-content
- resource: events
access: [publish]
- resource: reporting
access: [connect]Keel generates a separate IAM task role and security group for every service. S3, SNS, and SQS bindings become resource-scoped IAM statements. RDS and cache bindings become ingress rules owned by Keel on the linked security group. Resource identifiers are injected as environment variables such as UPLOADS_BUCKET_NAME and EVENTS_TOPIC_ARN; linked secrets use ECS secret injection.
Supported capabilities
| Type | Ownership | Capabilities |
|---|---|---|
| S3 | managed or existing | list, read, write, delete |
| SNS | managed or existing | publish |
| SQS | managed or existing | send, consume |
| RDS / cache | existing | connect |
| IAM role | existing | assume |
An IAM-role binding grants sts:AssumeRole to the service. The target role's trust policy must separately trust the generated <app>-<service>-ecs-task role, particularly for cross-account access.
For an AWS service without a curated resource type, use an advanced custom IAM statement on the service and keep actions/resources narrowly scoped:
yaml
services:
worker:
permissions:
- actions: [ses:SendEmail]
resources: [arn:aws:ses:us-east-1:123456789012:identity/example.com]For an existing resource or secret encrypted by a customer-managed KMS key, set kms_key_arn. Keel adds the required data-key/decrypt actions to the task or execution role. A cross-account resource policy, role trust policy, or KMS key policy must still authorize the generated service task role on the owning side.
Private subnets automatically receive a free S3 gateway endpoint when an S3 resource is configured. Set vpc.private_aws_endpoints: true to provision interface endpoints for configured SNS, SQS, and STS access.
What retain means
retain (default true) marks a Keel-managed resource as data you keep when the app goes away. It behaves differently for the two kinds of resource, because AWS constrains them differently:
S3, SNS, SQS —
keel destroyreleases the resource from Keel's state and leaves it running in AWS. Keel no longer manages it, and AWS keeps billing you for it until you delete it yourself. The teardown prints the exactawsCLI command for each one. On the normal apply pathretainalso emitslifecycle { prevent_destroy = true }, which protects the resource from being replaced by an ordinarykeel infra apply.The database —
retaincannot leave an RDS instance running, because the database sits inside the VPC and holds a security group the teardown removes; AWS could not delete the VPC around it. What survives is a final snapshot.database.retainturns ondeletion_protectionand guarantees that snapshot, and the teardown prints therestore-db-*command for it.
keel destroy names everything it will delete and everything it will keep, then asks you to type the app name. Two flags change what survives:
--delete-retaineddestroysretain: trueresources along with the stack.--no-final-snapshotdeletes the database without a snapshot.
Deployment history deliberately survives a destroy (the record that something was deployed outlives the environment); remove it with --prune-history or keel history prune later. See Interruptions & Rescue for what else outlives an environment and why.
After redeploying an app whose resources were retained
The new keel up will collide with the surviving names — delete them, rename the resource in keel.yml, or import them first.
Resource commands
bash
# Create and bind a managed resource
keel resources add s3 uploads --versioning --bind web:list,read,write
# Link an existing resource without transferring ownership to Keel
keel resources link arn:aws:sns:us-east-1:123456789012:application-events \
--as events --bind web:publish
# Change access later
keel resources bind uploads worker --access read
keel resources unbind uploads worker
# Inspect the complete app inventory and effective rules
keel resources
keel resources show uploads
keel resources show @load-balancer
keel resources --service web
keel resources --json
# Inspect access from a service's point of view
keel access show web
keel access explain web uploadsBuilt-in resources use @ names in the inventory, including @vpc, @cluster, @registry, @load-balancer, @logs, and optional add-ons such as @database, @cache, @domain, and @waf.