This module launches an Aurora Serverless v2 database cluster. Aurora serverless clusters measure capacity in ACUs (Aurora Capacity Units); each unit is approximately 2 GB of memory with corresponding CPU and networking.
Add this module to your main.tf (or appropriate) file and configure the inputs
to match your desired configuration. For example:
module "database" {
source = "github.com/codeforamerica/tofu-modules-aws-serverless-database?ref=1.7.0"
project = "my-project"
environment = "dev"
service = "web"
logging_key_arn = module.logging.kms_key_arn
secrets_key_arn = module.secrets.kms_key_arn
vpc_id = module.vpc.vpc_id
subnets = module.vpc.private_subnets
ingress_cidrs = module.vpc.private_subnets_cidr_blocks
min_capacity = 2
max_capacity = 32
}Make sure you re-run tofu init after adding the module to your configuration.
tofu init
tofu planTo update the source for this module, pass -upgrade to tofu init:
tofu init -upgradeWhen creating the database cluster, a role will be created for database monitoring. A random string will be appended to the role name to ensure it is unique and allow replacement without a conflict. However, this means the rest of the role name must be 38 characters or fewer.
The role name is constructed as follows (before the suffix is added):
role_name = "${project}-${environment}-[${service}-]-db-mon"If this combined string is longer than 38 characters, the module will fail to
create the database cluster. You can help to reduce the length of the role by
specifying short names for your project and (optionally) service using the
project_short and service_short input variables, respectively.
| Name | Description | Type | Default | Required |
|---|---|---|---|---|
| logging_key_arn | ARN of the KMS key for logging. | string |
n/a | yes |
| ingress_cidrs | List of CIDR blocks to allow ingress. This is typically your private subnets. | list(string) |
n/a | yes |
| project | Name of the project. | string |
n/a | yes |
| secrets_key_arn | ARN of the KMS key for secrets. This will be used to encrypt database credentials. | string |
n/a | yes |
| subnets | List of subnet ids the database instances may be placed in. | list(string) |
n/a | yes |
| vpc_id | Id of the VPC to launch the database cluster into. | string |
n/a | yes |
| apply_immediately | Whether to apply changes immediately rather than during the next maintenance window. WARNING: This may result in a restart of the cluster! | bool |
false |
no |
| automatic_backup_retention_period | Number of days to retain automatic backups, between 1 and 35. | number |
31 |
no |
| backup_namespace | Namespace for backups, prefixed to vault names to produce globally unique names. | string |
cfa |
no |
| backup_replica_region | Region to use for cross-region backup replication. If not specified, no replica will be created. If specified, the module will create a backup vault in the specified region and configure the backup schedules to replicate to the replica vault. | string |
null |
no |
| backup_retention_period | Deprecated: Use automatic_backup_retention_period instead. |
number |
null |
no |
| backup_schedules | Backup schedules to create for the database cluster. | list(object) |
list(object) |
no |
| cluster_parameters | Parameters to be set on the database cluster. | list(object) |
[] |
no |
| configure_aws_backup | Whether to configure AWS Backup with the defined backup schedules. | bool |
false |
no |
| db_users | Map of database users to create on the cluster. The map key becomes the database username. Requires enable_data_api = true and the AWS CLI must be installed on the OpenTofu runner. |
map(object) |
{} |
no |
| enable_data_api | Whether to enable the Data API for the database cluster. | bool |
false |
no |
| engine | Database engine to use for the cluster. Valid values are "mysql" and "postgresql". |
string |
"postgresql" |
no |
| engine_version | Version of the database engine to use. If left empty, the latest version will be used. Changing this value will result in downtime. | string |
null |
no |
| environment | Environment for the project. | string |
"dev" |
no |
| force_delete | Force deletion of resources. If changing to true, be sure to apply before destroying. | bool |
false |
no |
| iam_authentication | Whether to enable IAM authentication for the database cluster. | bool |
true |
no |
| [iam_db_users] | Map of IAM database users to create on the cluster. The map key becomes the database username. Requires iam_authentication = true and the AWS CLI must be installed on the OpenTofu runner. |
map(object) |
{} |
no |
| instances | Number of instances to create in the database cluster. | number |
2 |
no |
| key_recovery_period | Recovery period for deleted KMS keys in days. Must be between 7 and 30. |
number |
30 |
no |
| min_capacity | Minimum capacity for the serverless cluster in ACUs. | number |
2 |
no |
| max_capacity | Maximum capacity for the serverless cluster in ACUs. | number |
10 |
no |
| password_rotation_frequency | Number of days between automatic password rotations for the root user Set to 0 to disable automatic rotation. |
number |
30 |
no |
| project_short | Short name for the project. Used in resource names with character limits. Defaults to project. | string |
"" |
no |
| service | Optional service that these resources are supporting. Example: "api", "web", "worker". Used in resource names to differentiate from other services. |
string |
"" |
no |
| service_short | Short name for the service. Used in resource names with character limits. Defaults to the same value as service. |
string |
"" |
no |
| security_group_rules | Security group rules to control cluster ingress and egress. | map(object) |
{} |
no |
| skip_final_snapshot | Whether to skip the final snapshot when destroying the database cluster. | bool |
false |
no |
| snapshot_identifier | Optional name or ARN of the snapshot to restore the cluster from. Only applicable on create. | bool |
false |
no |
| tags | Optional tags to be applied to all resources. | map(string) |
{} |
no |
You can enable backups using AWS Backup by setting
configure_aws_backup to true. When enabled, the module will create a backup
vault in the current region.
module "database" {
source = "github.com/codeforamerica/tofu-modules-aws-serverless-database?ref=1.7.0"
project = "my-project"
environment = "dev"
service = "web"
logging_key_arn = module.logging.kms_key_arn
secrets_key_arn = module.secrets.kms_key_arn
vpc_id = module.vpc.vpc_id
subnets = module.vpc.private_subnets
ingress_cidrs = module.vpc.private_subnets_cidr_blocks
configure_aws_backup = true
}This will configure AWS Backup to use the following default schedule:
Note
Cron schedules are evaluated as UTC. With the defaults below, backups are scheduled for 9am UTC/4am EST/1am PST.
- name: daily
schedule: cron(0 9 ? * * *)
start_window: 320
completion_window: 1440
retention: 31
- name: monthly
schedule: cron(0 9 1 * ? *)
start_window: 320
completion_window: 1440
retention: 395
- name: yearly
schedule: cron(0 9 1 1 ? *)
start_window: 320
completion_window: 1440
retention: 1095You can override the default schedule by setting backup_schedules:
backup_schedules = [{
name = "daily"
schedule = "cron(0 4 ? * * *)"
start_window = 320
completion_window = 1440
retention = 8
}, {
name = "weekly"
schedule = "cron(0 4 * * * 0)"
start_window = 320
completion_window = 1440
retention = 53
}]Additionally, you can configure replication of backups to another region by
setting backup_replica_region. If left empty, no replicas will be created.
backup_replica_region = "us-west-2"| Name | Description | Type | Default | Required |
|---|---|---|---|---|
| name | Name of schedule. | string |
n/a | yes |
| schedule | The cron schedule on which to create the backup, evaluated as UTC. | string |
n/a | yes |
| retention | Number of days to retain the backup before it is deleted. | number |
n/a | yes |
| completion_window | Number of minutes after a backup has successfully started in which it must complete before being cancelled. | number |
1440 |
no |
| start_window | Number of minutes after the scheduled time in which the backup must be successfully started before being cancelled. | number |
320 |
no |
You can override the default cluster parameters by passing a list of parameters and their values. Some parameters can be applied immediately, while others will require a restart of the cluster. See the documentation for the appropriate database engine to determine which parameters can be applied immediately.
Note
If a parameter requires a restart, you must set the apply_method to
"pending-reboot".
cluster_parameters = [
{
name = "log_statement"
value = "all"
},
{
name = "shared_preload_libraries"
value = "pg_stat_statements,pglogical"
apply_method = "pending-reboot"
}
]| Name | Description | Type | Default | Required |
|---|---|---|---|---|
| name | Name of the parameter to set. | string |
n/a | yes |
| value | Value to set the parameter to. | string |
n/a | yes |
| apply_method | How to apply the parameter. Can be immediate or pending-reboot. |
string |
"immediate" |
no |
Warning
Creation of standard database users is limited to read-only users. We highly
recommend using [iam_db_users][iam_db_users] instead for enhanced security.
If you must rely on a user with a password, ensure that password is kept
secure and rotated regularly.
The same dependency on the RDS Data API exists for db_users as
iam_db_users
Although discouraged, it is occasionally necessary to create a read-only database user with a password. This option gives you the ability to create read-only database users with access to specific databases.
Provide a map of users, the keys of which will become the username. For example:
Caution
Database usernames should be treated as sensitive values and should not be committed directly to your repository.
Usernames are presented as strings here for demonstration purposes only.
enable_data_api = true
db_users = {
"myreadonlyuser" = {
databases = ["my_stats"]
}
}This will create a new database user with SELECT access to the specified
database(s). The user will be assigned a randomly generated password, and their
credentials will be stored in AWS Secrets Manager. The ARN of the secret for
each user is available in the db_user_secret_arns output.
| Name | Description | Type | Default | Required |
|---|---|---|---|---|
| databases | List of databases to grant the user access to. | list(string) |
n/a | yes |
| privileges | Privileges to grant on the databases for the user. The only valid value is "readonly". |
string |
"readonly" |
no |
You can optionally create database users to be used for IAM based authentication. This allows your application(s) to connect to the database without managing a static password that needs to be rotated regularly.
Note
To avoid needing to connect directly to the database, these users are managed
using RDS Data API. As a result, enable_data_api must be set to
true for this to succeed, and the OpenTofu runner must have the AWS CLI
installed.
Provide a map of users, the keys of which will become the username. For example:
Caution
Database usernames should be treated as sensitive values and should not be committed directly to your repository.
Usernames are presented as strings here for demonstration purposes only.
enable_data_api = true
iam_db_users = {
"myapp" = {
privileges = "all"
},
"myapp_ro" = {
databases = ["myapp", "myapp_queue"]
privileges = "readonly"
}
}To grant your resources the privileges to connect to the database as the user,
an IAM policy is created for each user, and mapped to the username in the
iam_db_user_policy_arns output. You can attach this policy to one or more IAM
roles which are attached to your resources.
Tip
You can also pass the policy ARN to another module that's responsible for configuring your roles, such as our aws_fargate_service module.
| Name | Description | Type | Default | Required |
|---|---|---|---|---|
| databases | List of databases to grant the user access to. Leave empty to grant access to all databases. | list(string) |
[] |
no |
| privileges | Privileges to grant on the databases for the user. Valid values are "all" and "readonly". |
string |
"all" |
no |
Security group rules control network access to the cluster. By default, the
cluster will not be available on the network can only be accessed via the
Data API. You can use security_group_rules to define rules to
ingress and/or egress traffic.
Tip
If you just want to allow access to the database from one or more CIDR blocks,
you can use the ingress_cidrs input variable for convenience.
security_group_rules = {
vpc_peer = {
description = "Allow access from VPC peer"
type = "ingress"
protocol = "tcp"
from_port = 5432
to_port = 5432
cidr_blocks = ["10.123.0.0/16"]
}
replication = {
description = "Allow egress for replication"
type = "egress"
cidr_blocks = ["10.123.0.0/16"]
}
}Caution
Be careful when using egress rules. In most cases, this will not be
necessary and can present a security risk. If you do need to use egress
rules, be sure to restrict the narrowest set of destinations that are
necessary.
Leaving your egress rules too broad can allow your data to be exfiltrated by a bad actor.
| Name | Description | Type | Default | Required |
|---|---|---|---|---|
| description | Description of the rule. | string |
"Managed by OpenTofu" |
no |
| type | Type of rule. Can be ingress or egress. |
string |
"ingress" |
no |
| protocol | Protocol to use. Valid values: icmp, icmpv6, tcp, udp, or all. |
string |
"tcp" |
no |
| from_port | Starting port for the rule. Defaults to the port for the database engine. | number |
5432 or 3306 |
no |
| to_port | Ending port for the rule. Defaults to the port for the database engine. | number |
5432 or 3306 |
no |
| cidr_blocks | List of CIDR blocks to allow access. | list(string) |
[] |
no |
| ipv6_cidr_blocks | List of IPv6 CIDR blocks to allow access. | list(string) |
[] |
no |
| prefix_list_ids | List of prefix list IDs to allow access. | list(string) |
[] |
no |
| source_security_group_id | ID of another security group to allow access. | string |
null |
no |
| Name | Description | Type |
|---|---|---|
| backup_key_arn | ARN of the primary KMS key for backups, if created. | string |
| backup_vault_arn | ARN of the backup vault, if created. | string |
| backup_vault_replica_arn | ARN of the backup vault replica, if created. | string |
| cluster_endpoint | DNS endpoint to connect to the database cluster. | string |
| cluster_id | ID of the RDS database cluster. | string |
| cluster_resource_id | Resource ID of the RDS database cluster. | string |
| db_user_secret_arns | Map of database username to the ARN of the Secrets Manager secret containing their credentials. | map(string) |
| iam_db_user_policy_arns | Map of IAM database username to the ARN of the IAM policy granting rds-db:connect access for that user. |
map(string) |
| secret_arn | ARN of the secret holding database credentials. | string |