This module provides a basic Fleet deployment on AWS with Terraform. It is the root module for the repo and creates the VPC, database, cache, ECS cluster, ALB, and Fleet service stack. If you want to bring part of that infrastructure yourself, use one of the nested submodules instead.
To quickly list available released module tags:
git tag | grep '^tf'
Module layout:
- Root module
byo-vpcbyo-vpc/byo-dbbyo-vpc/byo-db/byo-ecs
Aurora Blue-Green Restore Cutovers
The root module accepts the legacy rds_config object or the new rds_configs map. active_rds_config_name defaults to "current" and selects the cluster passed through the unchanged byo-db and byo-ecs interfaces.
See Aurora Blue-Green Restore Cutovers in the byo-vpc documentation for the complete migration, restore, cutover, rollback, and cleanup workflow.
AWS GovCloud Compatibility
The root module, byo-vpc, its nested AWS modules, and non-CloudFront addons are intended to remain partition-aware so they can be used in AWS GovCloud (US) where the underlying AWS service is available.
addons/cloudfront-software-installers is intentionally out of scope for AWS GovCloud compatibility because CloudFront is not available inside the AWS GovCloud (US) partition. Any deployment that combines CloudFront with GovCloud resources is a cross-partition architecture and should be reviewed separately.
KMS Coverage
This root module now exposes optional customer-managed KMS key (CMK) support for every KMS-capable surface that this stack manages directly or passes through to child modules.
At the root module level this includes:
- VPC flow log CloudWatch log groups
- Aurora storage encryption
- Aurora database password secret in Secrets Manager
- Aurora observability encryption for Performance Insights / CloudWatch Database Insights
- Aurora exported CloudWatch log groups
- ElastiCache at-rest encryption
- ElastiCache CloudWatch log groups for
cloudwatch-logsdelivery targets - ECS cluster exec log groups, Fleet app log groups, Fleet private-key secret, and other nested Fleet/ECS KMS features through child-module passthroughs
Behavior rules are consistent across features:
cmk_enabled = truemeans "use a customer-managed KMS key here."- Set
cmk_enabled = falseor omit it to keep using the service-managed key. - For KMS options that existed in published releases before this change, legacy
enabledis deprecated but still accepted. Terraform plan/apply warns when it is used, andcmk_enabledtakes precedence if both are set. - If CMK use is enabled and no key ARN is provided, the module creates a CMK and alias.
- If a key ARN is provided, the module uses that key and does not create one.
- For provided keys, required IAM is managed where this repo owns an IAM principal, but external key policies must already allow the relevant AWS service to use the key.
Aurora Database Insights
AWS has announced that the Performance Insights console reaches end of life on June 30, 2026. Aurora observability is moving toward CloudWatch Database Insights.
This module exposes Aurora observability through rds_config.observability:
database_insights_mode = nullmeans Terraform does not force Standard vs Advanced mode.database_insights_mode = "standard"explicitly keeps the cluster in Standard Database Insights mode.database_insights_mode = "advanced"enables Advanced Database Insights and therefore requires:performance_insights_enabled = truemonitoring_interval > 0retention_period >= 465
The observability CMK applies through Aurora's underlying Performance Insights encryption plane, which Database Insights builds on.
Aurora Backtrack
This module also exposes Aurora MySQL backtracking through rds_config.backtrack_window.
- Set it to a value between
0and259200seconds. - Set
0to disable backtracking explicitly. - Leave it
nullto keep the default upstream behavior.
S3 Bucket Policy: Deny Non-HTTPS
All S3 buckets created by this module automatically have a bucket policy that denies any requests made over plain HTTP. No configuration is required.
When cloudfront_distribution_arn is set in software_installers, the bucket policy automatically includes an allow statement for CloudFront to read objects. This means the cloudfront-software-installers addon no longer manages a bucket policy — it is fully handled here.
VPC Flow Log Retention
The root module now exposes flow_log_cloudwatch_log_group_retention_in_days on the vpc variable to set CloudWatch log retention for VPC flow logs. It defaults to null (infinite retention).
vpc = {
enable_flow_log = true
create_flow_log_cloudwatch_log_group = true
flow_log_cloudwatch_log_group_retention_in_days = 365
}
Migration Notes
- Existing environments remain unchanged unless you opt into new KMS or Database Insights settings.
- For provided CMKs, ensure the key policy already allows the relevant AWS service.
- Enabling KMS on existing CloudWatch log groups may require old log streams to be purged so all retained data is under the new key.
Use the repository-root helper script for CloudWatch Logs KMS cleanup:
# Dry run
DELETE_OLD_STREAMS=false ./scripts/cloudwatch_logs_kms_migration.sh <log-group-name> <region>
# Delete old streams
./scripts/cloudwatch_logs_kms_migration.sh <log-group-name> <region>
Example
module "fleet" {
source = "github.com/fleetdm/fleet-terraform?depth=1&ref=tf-mod-root-v1.30.0"
certificate_arn = module.acm.acm_certificate_arn
vpc = {
enable_flow_log = true
create_flow_log_cloudwatch_log_group = true
flow_log_cloudwatch_log_group_kms = {
cmk_enabled = true
}
}
rds_config = {
storage_kms = {
cmk_enabled = true
}
password_secret_kms = {
cmk_enabled = true
}
observability = {
database_insights_mode = "standard"
kms = {
cmk_enabled = true
}
}
}
redis_config = {
at_rest_kms = {
cmk_enabled = true
}
}
}
Migrating from existing Dogfood code
The below code describes how to migrate from existing Dogfood code.
moved {
from = module.vpc
to = module.main.module.vpc
}
moved {
from = module.aurora_mysql
to = module.main.module.byo-vpc.module.rds["current"]
}
moved {
from = aws_elasticache_replication_group.default
to = module.main.module.byo-vpc.module.redis.aws_elasticache_replication_group.default
}
This focuses on the resources that are "heavy" or store data. The ALB cannot be moved the same way because Dogfood uses aws_alb while the module uses aws_lb.
Cache Engine: Redis vs Valkey
This module supports both Redis and Valkey as the ElastiCache engine.
Provider Requirements
When using this module, ensure your AWS provider version is >= 5.73.0.
Using Valkey
redis_config = {
engine = "valkey"
engine_version = "7.2"
family = "valkey7"
instance_type = "cache.m5.large"
cluster_size = 3
}
Using Redis
redis_config = {
engine = "redis"
engine_version = "7.1"
family = "redis7"
instance_type = "cache.m5.large"
cluster_size = 3
}
How to improve this module
If this module does not fit your needs, open a ticket or contact Fleet. Variable changes should stay nullable when no sensible default exists and should be reflected all the way up the stack.
How to update this readme
Edit .header.md, run terraform init, then run terraform-docs markdown . > README.md.
Requirements
| Name | Version |
|---|---|
| terraform | >= 1.12.0 |
| aws | >= 6.37.0 |
Providers
| Name | Version |
|---|---|
| aws | >= 6.37.0 |
Modules
| Name | Source | Version |
|---|---|---|
| byo-vpc | ./byo-vpc | n/a |
| vpc | terraform-aws-modules/vpc/aws | 5.1.2 |
Resources
| Name | Type |
|---|---|
| aws_kms_alias.vpc_flow_log_cloudwatch_log_group | resource |
| aws_kms_key.vpc_flow_log_cloudwatch_log_group | resource |
| aws_caller_identity.current | data source |
| aws_iam_policy_document.vpc_flow_log_cloudwatch_log_group_kms | data source |
| aws_partition.current | data source |
| aws_region.current | data source |
Inputs
| Name | Description | Type | Default | Required |
|---|---|---|---|---|
| active_rds_config_name | Name of the rds_configs entry used by Fleet. Defaults to the synthetic current entry when using legacy rds_config. | string |
"current" |
no |
| alb_config | n/a | object({ |
{} |
no |
| certificate_arn | n/a | string |
n/a | yes |
| ecs_cluster | The config for the terraform-aws-modules/ecs/aws module. For published KMS blocks, legacy enabled is deprecated and still accepted; prefer cmk_enabled. |
object({ |
{ |
no |
| fleet_config | The configuration object for Fleet itself. Fields that default to null will have their respective resources created if not specified. For published KMS blocks, legacy enabled is deprecated and still accepted; prefer cmk_enabled. |
object({ |
{ |
no |
| kms_base_policy | Optional base KMS key-policy statements to apply to module-created CMKs before module-required service access statements are merged in. If null, the module defaults to the historical root kms:* statement. |
list(object({ |
null |
no |
| migration_config | The configuration object for Fleet's migration task. | object({ |
{ |
no |
| rds_config | The config for the terraform-aws-modules/rds-aurora/aws module. Deprecated: use rds_configs instead. | object({ |
{ |
no |
| rds_configs | Map of named Aurora cluster configurations for blue-green cutovers. When set, rds_config is ignored. | map(object({ |
null |
no |
| redis_config | n/a | object({ |
{ |
no |
| vpc | n/a | object({ |
{ |
no |
Outputs
| Name | Description |
|---|---|
| byo-vpc | n/a |
| vpc | n/a |