# What is Keel?

Keel gives you a platform-style workflow on your own AWS account. Describe your app in `keel.yml`, then use one CLI to provision infrastructure, deploy code, and operate the app.

Keel has no vendor-hosted control plane or separate account to manage. The CLI runs locally; its optional control-plane Lambda runs in your AWS account. Your team keeps control of its identities, data, infrastructure, and bill, and the resources Keel creates continue running if you stop using it.

## What Keel provisions

From a single `keel.yml`, Keel creates and manages:

- **Compute:** ECS services on Fargate, Fargate Spot, or an EC2 capacity-provider fleet
- **Scheduled tasks:** EventBridge Scheduler running one-off ECS tasks
- **Static sites:** private S3 buckets served through CloudFront
- **Networking:** a VPC with public and private subnets, NAT, and security groups
- **Load balancing:** an Application Load Balancer with HTTPS
- **Builds:** CodeBuild pipelines using a Dockerfile or Cloud Native Buildpacks
- **Container images:** ECR repositories with lifecycle policies
- **Databases:** RDS for PostgreSQL, MySQL, and Aurora
- **Caches:** ElastiCache for Valkey and Redis
- **DNS and TLS:** Route 53 and ACM certificates
- **Security:** AWS WAF with managed rule sets
- **Identity:** optional Cognito pools for internal application users and Keel operators
- **Observability:** CloudWatch logs and metrics

Every managed resource is tagged with `ManagedBy=keel` plus the app and environment it belongs to, and each app+environment is recorded in a DynamoDB app registry so any team member can discover it with `keel apps`.

## Networking choices

Load balancing, task placement, and outbound networking are independent settings. There is no `mode` preset: an enum that implied all three became misleading once different services could choose different subnets.

```yaml
# Production-style defaults when omitted
load_balancer:
  enabled: true
networking:
  public_tasks: false
  nat_gateway: single

# A service may override only its own placement
services:
  image-worker:
    networking:
      public_tasks: true
```

The inexpensive footprint sets `load_balancer.enabled: false`, `networking.public_tasks: true`, and `networking.nat_gateway: none`. A public subnet does not open ingress; the service security group still decides what can reach it.

## How it works

Keel uses two paths depending on the operation:

- **Infrastructure commands** such as `keel up` and `keel infra plan/apply` generate OpenTofu configuration and run it with state in S3 and locking in DynamoDB.
- **Runtime commands** such as `keel deploy`, `keel logs`, `keel exec`, and `keel scale` use the AWS SDK directly.
- **The optional control plane** serves cached reads and brokers narrow operator capabilities. IAM sessions fall back to the direct path; operators deliberately do not hold a direct AWS credential.

See [Architecture](./architecture) and [The Keel Control Plane](./control-plane) for the full picture.

## Next steps

- [Getting Started](./getting-started) — install, set up auth, and ship your first deploy
- [Configuration](./configuration) — the anatomy of `keel.yml`
- [Deploying Rails](../deploying-rails) — a worked example with a web process, a worker, and migrations
