- Write up a basic summary of the design here (global tfstate with many per-project tfstates using remote state)
- Create an unprivileged user that is only permitted to read the global bootstrap configuration for the purposes of importing state (?)
- To use Terraform at all, we need a set of credentials for performing administrative tasks. Create an IAM user named 'terraform-bootstrap' and attach a policy named AdministratorAccess (Permissions tab -> Attach Policy) with the following contents:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "*",
"Resource": "*"
}
]
}
- Install aws-cli and create a profile with the credentials of the terraform-bootstrap user:
# in ~/.aws/credentials
[terraform-bootstrap]
aws_access_key_id = <access key>
aws_secret_access_key = <secret key>
- Import the admin user for management via terraform:
AWS_DEFAULT_REGION=<default_region> AWS_PROFILE=terraform-bootstrap terraform import "aws_iam_user.terraform-bootstrap" "terraform-bootstrap"
- Run
terraform plan
to validate that the correct actions are planned, then runterraform apply
. You will be be prompted for the two variables: primary_region
- The primary AWS region to create the remote state bucket in.remote_state_bucket
- A unique name for the bucket to store terraform state in. S3 buckets are in one global namespace, so you'll see the following error if you have chosen a bucket name that already exists:
* aws_s3_bucket.terraform-remote-state: Error creating S3 bucket: BucketAlreadyExists: The requested bucket name is not available. The bucket namespace is shared by all users of the system. Please select a different name and try again. status code: 409, request id: F144F0642E53A6B7
- Enable remote state storage for the project. The command to do this is conveniently included in the terraform output in a variable called 'remote_state_config_command'. If you have jq installed, you can do the following:
bash -c $(terraform output -json | jq --raw-output ".remote_state_config_command.value")
- (Optional) Delete and replace the credentials used created manually in the first step. The bootstrap process creates a new set of access credentials, so we no longer
need the original ones. Run the following to get the new credentials and replace the existing
[terraform-bootstrap]
section in~/.aws/credentials
:
terraform output -json | jq --raw-output ".aws_credentials_entry.value"
- Create a directory for the new project and copy the
bootstrap_project/bootstrap_project.tf
andbootstrap_project/terraform.tfvars
there. - Edit the
terraform.tfvars
file to point to the correct remote state bucket and region and fill in a project name (this can be anything, but is useful for identifying resources in the AWS console). - Run
terraform plan
to validate that the correct actions are planned, then runterraform apply
. - Fill in awscli profile with credentials from output:
> terraform output -json | jq --raw-output ".aws_credentials_entry.value"
[terraform-<project>]
aws_access_key_id = <access key>
aws_secret_access_key = <secret key>
- Configure terraform remote state syncing to global terraform remote state bucket (configured above):
> CMD = $(terraform output -json | jq --raw-output ".remote_state_config_command.value")
> echo $CMD
terraform remote config -backend=s3 -backend-config="bucket=<remote state bucket>" -backend-config="key=<project>.tfstate" -backend-config="profile=terraform-<project>" -backend-config="region=us-east-1"
bash -c $CMD
- (Optional, but recommended) Delete the
terraform-bootstrap-project
provider and all references to it. Now that the project is bootstrapped with its own admin user, we don't need the bootstrap user or its credentials anymore.