diff --git a/README.md b/README.md
index 45e1d6c..72239d5 100644
--- a/README.md
+++ b/README.md
@@ -66,14 +66,14 @@ Once you have chosen the infrastructure module you want to use, move to the modu
## Live Infrastructure
-The `live` directory houses our live infrastructure. This is where you'll find our Terraform variables, backend configuration, and Terraform root modules.
+The `live` directory houses our live infrastructure components. This is where you'll find our Terraform variables, backend configuration, and Terraform root modules.
-It is recommended to create a separate directory for each environment (e.g., `dev`, `staging`, `prod`) and region (e.g., `us-east-1`, `us-west-2`, `eu-west-1`). This allows you to easily manage and deploy your infrastructure.
+It is recommended to create a separate directory for each domain that you want to manage with Terraform. For example, you could have a `core-networking` directory for managing your VPC, subnets, and security groups, and a `common-infra` directory for managing your RDS instances, S3 buckets, and other shared resources.
-| Module | Description |
-| :------------------------------------------------------------------------------- | :---------------------------------------------------- |
-| [Prod App Infrastructure (us-west-2)](./live/prod/us-west-2/app/README.md) | Terraform root module for our prod infrastructure. |
-| [Staging App Infrastructure (us-west-2)](./live/staging/us-west-2/app/README.md) | Terraform root module for our staging infrastructure. |
+| Module | Description |
+| :-------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------------- |
+| [Common Infrastructure](./live/common-infra/README.md) | Terraform module for managing common infrastructure components such as VPC, subnets, security groups, and RDS instances. |
+| [Terraform Backend Configuration](./live/terraform-backend/README.md) | Terraform module for setting up the S3 backend. |
## Terraform Modules
diff --git a/live/prod/us-west-2/app/.terraform.lock.hcl b/live/common-infra/.terraform.lock.hcl
similarity index 100%
rename from live/prod/us-west-2/app/.terraform.lock.hcl
rename to live/common-infra/.terraform.lock.hcl
diff --git a/live/prod/us-west-2/app/README.md b/live/common-infra/README.md
similarity index 60%
rename from live/prod/us-west-2/app/README.md
rename to live/common-infra/README.md
index ac27a78..9c3f3df 100644
--- a/live/prod/us-west-2/app/README.md
+++ b/live/common-infra/README.md
@@ -1,75 +1,92 @@
-# Prod Infrastructure (us-west-2)
+# Common Infrastructure
-🏢 This directory contains the infrastructure as code for our cloud infrastructure. It provides a ready-to-use Terraform module with various features. Follow the steps below to get started.
+🏢 This directory contains the Terraform configuration for our core cloud infrastructure. It provides a ready-to-use Terraform module with essential services and security features.
## Features
-- ✨ Ready to use Root Terraform module!
-- 🗄️ Store Terraform state in an S3 bucket with a DynamoDB table for locking.
-- 🌐 VPC with public and private subnets (application and database subnets) in three availability zones.
-- 🔒 Security groups for bastion host and database.
-- 🔑 Bastion host to access private resources.
-- 🐘 RDS Postgres instance and other database resources.
-- 🔒 AWS Secrets Manager to store database credentials.
-- 🔧 SSM Parameter Store to store parameters such as VPC ID, Subnet IDs, etc.
+- ✨ Comprehensive Root Terraform module for quick deployment.
+- 🗄️ Configured to use an external S3 bucket for Terraform state management with a DynamoDB table for state locking.
+- 🌐 Highly available VPC setup with public and private subnets across multiple availability zones.
+- 🔒 Configured security groups for bastion hosts and databases.
+- 🔑 Bastion host setup for secure access to internal services.
+- 🐘 RDS Postgres setup for reliable database services.
+- 🔒 Utilization of AWS Secrets Manager for secure storage of database credentials.
+- 🔧 Use of SSM Parameter Store for managing network and service parameters.
## Prerequisites
-- [Terraform](https://www.terraform.io/downloads.html)
-- [TFswitch](https://tfswitch.warrensbox.com/)
+- [Terraform](https://www.terraform.io/downloads.html) for infrastructure provisioning.
+- [TFswitch](https://tfswitch.warrensbox.com/) to switch between Terraform versions easily.
## Setup
-1. Switch to the correct Terraform version
+1. **Set Terraform Version:**
-```sh
-tfswitch
-```
+ Ensure you are using the correct Terraform version:
-2. Initialize the Terraform working directory:
+ ```sh
+ tfswitch
+ ```
-```sh
-terraform init
-```
+2. **Check the Terraform Backend Configuration:**
-## Deploy
+ Verify that the backend configuration is set correctly in the `backend.tf` file.
-1. Plan the deployment:
+ ```hcl
+ terraform {
+ required_version = ">= 1.0.0"
-```sh
-terraform plan -out ./prod.tfplan
-```
+ backend "s3" {
+ region = "us-west-2"
+ bucket = "terraform-state"
+ key = "terraform.tfstate"
+ dynamodb_table = "terraform-state-lock"
+ profile = ""
+ role_arn = ""
+ encrypt = "true"
+ }
+ }
-2. Apply the deployment:
+ ```
-```sh
-terraform apply ./prod.tfplan
-```
+ Replace the placeholder values with the actual bucket name, key, region, and DynamoDB table name.
-### First Time Deployment?
+3. **Initialize Terraform:**
-If this is the first time you are deploying, a file called `s3-backend.tf` will be created. This file configures the backend for Terraform, using S3 to store the state of our infrastructure.
+ Initialize the working directory with the required providers and modules:
-Run the following command to copy the state to the S3 bucket:
+ ```sh
+ terraform init
+ ```
-```sh
-terraform init -force-copy
-```
+4. **Workspace Management:**
-Push the `s3-backend.tf` file to the repository:
+ Select or create a new workspace tailored to your deployment environment:
-```sh
-git add s3-backend.tf && git commit -m "Add s3-backend.tf file"
-git push
-```
+ ```sh
+ # Switch to the another workspace or create it if it doesn't exist
+ terraform workspace select -or-create prod
+ ```
-## Destroy
+## Deploy
-To destroy the infrastructure, run the following command:
+🚀 **Deployment Instructions:**
-```sh
-terraform destroy
-```
+1. **Plan Your Deployment:**
+
+ Review and verify the deployment plan:
+
+ ```sh
+ terraform plan -var-file ./configs/prod.tfvars -out=prod.tfplan
+ ```
+
+2. **Execute the Plan:**
+
+ Apply the planned configuration to provision the infrastructure:
+
+ ```sh
+ terraform apply "prod.tfplan"
+ ```
## Post Deployment Steps
@@ -193,6 +210,16 @@ You can now execute SQL commands to test the database setup. For example:
These steps will help you verify the successful setup of the database and ensure that the necessary connections and configurations are in place.
+## Destroy
+
+💣 **NOTE:** In this example, we are using the `prod` environment and the `us-west-2` region. Modify these values according to your environment and region.
+
+To destroy the infrastructure, run the following command:
+
+```sh
+terraform destroy -var-file ./configs/prod.tfvars
+```
+
## Module Documentation
The module documentation is generated with [terraform-docs](https://github.com/terraform-docs/terraform-docs) by running the following command from the module directory:
diff --git a/live/prod/us-west-2/app/backend.tf b/live/common-infra/backend.tf
similarity index 61%
rename from live/prod/us-west-2/app/backend.tf
rename to live/common-infra/backend.tf
index 0cff6d7..690d171 100644
--- a/live/prod/us-west-2/app/backend.tf
+++ b/live/common-infra/backend.tf
@@ -6,14 +6,16 @@ module "terraform_state_backend" {
source = "cloudposse/tfstate-backend/aws"
version = "1.1.1"
- name = module.label.name
- namespace = module.label.namespace
- environment = module.label.environment
- attributes = ["state"]
+ # Avoid creating anything within if we are not in the workspace "default" and "prod".
+ enabled = contains(["default", "prod"], terraform.workspace)
+
+ name = module.label.name
+ namespace = module.label.namespace
+ attributes = ["state"]
terraform_backend_config_file_path = "."
terraform_backend_config_file_name = "s3-backend.tf"
- terraform_state_file = "${module.label.id}.tfstate"
+ terraform_state_file = "${module.label.namespace}-${module.label.name}.tfstate"
bucket_enabled = true
dynamodb_enabled = true
diff --git a/live/prod/us-west-2/app/bastion.tf b/live/common-infra/bastion.tf
similarity index 50%
rename from live/prod/us-west-2/app/bastion.tf
rename to live/common-infra/bastion.tf
index 2b7ffea..452e18e 100644
--- a/live/prod/us-west-2/app/bastion.tf
+++ b/live/common-infra/bastion.tf
@@ -1,30 +1,30 @@
-locals {
- bastion = {
- enable = true
- }
+variable "enable_bastion" {
+ type = bool
+ description = "Enable bastion host"
+ default = false
}
module "bastion" {
- count = local.bastion.enable ? 1 : 0
+ count = var.enable_bastion ? 1 : 0
- source = "../../../../modules/bastion"
+ source = "../../modules/bastion"
name = "${module.label.id}-bastion"
vpc_id = module.vpc.vpc_id
subnets = module.vpc.public_subnets
associate_public_ip_address = true
- associate_elastic_ip_address = true
+ associate_elastic_ip_address = false
tags = module.label.tags
}
output "bastion_instance_id" {
- value = local.bastion.enable ? module.bastion[0].instance_id : null
+ value = var.enable_bastion ? module.bastion[0].instance_id : null
}
output "bastion_instance_profile" {
- value = local.bastion.enable ? module.bastion[0].instance_profile : null
+ value = var.enable_bastion ? module.bastion[0].instance_profile : null
}
output "ssm_parameter_bastion_ssh_key" {
description = "name of the ssm parameter for the bastion ssh key"
- value = local.bastion.enable ? module.bastion[0].ssm_parameter_ssh_key : null
+ value = var.enable_bastion ? module.bastion[0].ssm_parameter_ssh_key : null
}
diff --git a/live/common-infra/configs/prod.tfvars b/live/common-infra/configs/prod.tfvars
new file mode 100644
index 0000000..cc4017d
--- /dev/null
+++ b/live/common-infra/configs/prod.tfvars
@@ -0,0 +1,20 @@
+# General settings
+
+region = "us-west-2"
+name = "core"
+namespace = "nan"
+environment = "prod"
+tags = {
+ "Terraform" = "true"
+ "Environment" = "prod"
+}
+
+# AWS settings
+
+vpc_cidr_block = "10.0.0.0/16"
+enable_bastion = false
+
+# RDS Database settings
+
+example_db_name = "example"
+example_db_master_username = "root"
diff --git a/live/common-infra/configs/staging.tfvars b/live/common-infra/configs/staging.tfvars
new file mode 100644
index 0000000..cc4017d
--- /dev/null
+++ b/live/common-infra/configs/staging.tfvars
@@ -0,0 +1,20 @@
+# General settings
+
+region = "us-west-2"
+name = "core"
+namespace = "nan"
+environment = "prod"
+tags = {
+ "Terraform" = "true"
+ "Environment" = "prod"
+}
+
+# AWS settings
+
+vpc_cidr_block = "10.0.0.0/16"
+enable_bastion = false
+
+# RDS Database settings
+
+example_db_name = "example"
+example_db_master_username = "root"
diff --git a/live/common-infra/context.tf b/live/common-infra/context.tf
new file mode 100644
index 0000000..2be61f9
--- /dev/null
+++ b/live/common-infra/context.tf
@@ -0,0 +1,54 @@
+variable "name" {
+ description = "Name to use for servers, tags, etc"
+ type = string
+ default = "name"
+}
+
+variable "namespace" {
+ description = "Namespace, which could be your organization name or abbreviation, e.g. 'eg' or 'cp'"
+ type = string
+ default = "development"
+}
+
+variable "environment" {
+ description = "Environment, e.g. 'prod', 'staging', 'dev', 'pre-prod', 'UAT'"
+ type = string
+ default = "development"
+}
+
+variable "stage" {
+ description = "Stage, e.g. 'build', 'test', 'deploy', 'release'"
+ type = string
+ # not required, so no default
+ default = null
+}
+
+variable "tags" {
+ description = "Any extra tags to assign to objects"
+ type = map(any)
+ default = {}
+}
+
+data "aws_caller_identity" "aws" {}
+
+locals {
+ tf_tags = {
+ Terraform = true,
+ By = data.aws_caller_identity.aws.arn
+ }
+}
+
+// Keep labels, tags consistent
+module "label" {
+ source = "cloudposse/label/null"
+ version = "0.25.0"
+
+ name = var.name
+ environment = var.environment
+ namespace = var.namespace
+ stage = var.stage
+
+ delimiter = "-"
+ label_order = ["namespace", "environment", "stage", "name", "attributes"]
+ tags = merge(var.tags, local.tf_tags)
+}
diff --git a/live/prod/us-west-2/app/docs/MODULE.md b/live/common-infra/docs/MODULE.md
similarity index 66%
rename from live/prod/us-west-2/app/docs/MODULE.md
rename to live/common-infra/docs/MODULE.md
index a5e3ad2..94f63be 100644
--- a/live/prod/us-west-2/app/docs/MODULE.md
+++ b/live/common-infra/docs/MODULE.md
@@ -16,11 +16,11 @@
| Name | Source | Version |
|------|--------|---------|
-| [bastion](#module\_bastion) | ../../../../modules/bastion | n/a |
-| [exampledb](#module\_exampledb) | ../../../../modules/rds | n/a |
+| [bastion](#module\_bastion) | ../../modules/bastion | n/a |
+| [exampledb](#module\_exampledb) | ../../modules/rds | n/a |
| [label](#module\_label) | cloudposse/label/null | 0.25.0 |
| [terraform\_state\_backend](#module\_terraform\_state\_backend) | cloudposse/tfstate-backend/aws | 1.1.1 |
-| [vpc](#module\_vpc) | ../../../../modules/vpc | n/a |
+| [vpc](#module\_vpc) | ../../modules/vpc | n/a |
## Resources
@@ -30,7 +30,18 @@
## Inputs
-No inputs.
+| Name | Description | Type | Default | Required |
+|------|-------------|------|---------|:--------:|
+| [enable\_bastion](#input\_enable\_bastion) | Enable bastion host | `bool` | `false` | no |
+| [environment](#input\_environment) | Environment, e.g. 'prod', 'staging', 'dev', 'pre-prod', 'UAT' | `string` | `"development"` | no |
+| [example\_db\_master\_username](#input\_example\_db\_master\_username) | The username for the master DB user | `string` | `"root"` | no |
+| [example\_db\_name](#input\_example\_db\_name) | The name of the database to create | `string` | `"mydb"` | no |
+| [name](#input\_name) | Name to use for servers, tags, etc | `string` | `"name"` | no |
+| [namespace](#input\_namespace) | Namespace, which could be your organization name or abbreviation, e.g. 'eg' or 'cp' | `string` | `"development"` | no |
+| [region](#input\_region) | AWS region | `string` | `"us-west-2"` | no |
+| [stage](#input\_stage) | Stage, e.g. 'build', 'test', 'deploy', 'release' | `string` | `null` | no |
+| [tags](#input\_tags) | Any extra tags to assign to objects | `map(any)` | `{}` | no |
+| [vpc\_cidr\_block](#input\_vpc\_cidr\_block) | CIDR block for the VPC | `string` | `"10.0.0.0/16"` | no |
## Outputs
diff --git a/live/prod/us-west-2/app/example-rds-instance.tf b/live/common-infra/example-rds-instance.tf
similarity index 69%
rename from live/prod/us-west-2/app/example-rds-instance.tf
rename to live/common-infra/example-rds-instance.tf
index 46fdade..7b14a28 100644
--- a/live/prod/us-west-2/app/example-rds-instance.tf
+++ b/live/common-infra/example-rds-instance.tf
@@ -1,20 +1,25 @@
-locals {
- exampledb = {
- db_name = "mydb"
- db_master_username = "myuser"
- }
+variable "example_db_name" {
+ description = "The name of the database to create"
+ type = string
+ default = "mydb"
+}
+
+variable "example_db_master_username" {
+ description = "The username for the master DB user"
+ type = string
+ default = "root"
}
module "exampledb" {
- source = "../../../../modules/rds"
+ source = "../../modules/rds"
name = "${module.label.id}-exampledb"
vpc_id = module.vpc.vpc_id
db_subnet_group = module.vpc.database_subnet_group
- db_name = local.exampledb.db_name
- db_master_username = local.exampledb.db_master_username
+ db_name = var.example_db_name
+ db_master_username = var.example_db_master_username
db_port = 5432
allocated_storage = 20
diff --git a/live/prod/us-west-2/app/main.tf b/live/common-infra/main.tf
similarity index 78%
rename from live/prod/us-west-2/app/main.tf
rename to live/common-infra/main.tf
index fe5e8dc..143ee86 100644
--- a/live/prod/us-west-2/app/main.tf
+++ b/live/common-infra/main.tf
@@ -1,5 +1,5 @@
provider "aws" {
- region = "us-west-2"
+ region = var.region
default_tags {
tags = {
diff --git a/live/prod/us-west-2/app/outputs.tf b/live/common-infra/outputs.tf
similarity index 100%
rename from live/prod/us-west-2/app/outputs.tf
rename to live/common-infra/outputs.tf
diff --git a/live/common-infra/variables.tf b/live/common-infra/variables.tf
new file mode 100644
index 0000000..098424d
--- /dev/null
+++ b/live/common-infra/variables.tf
@@ -0,0 +1,5 @@
+variable "region" {
+ description = "AWS region"
+ type = string
+ default = "us-west-2"
+}
diff --git a/live/prod/us-west-2/app/versions.tf b/live/common-infra/versions.tf
similarity index 100%
rename from live/prod/us-west-2/app/versions.tf
rename to live/common-infra/versions.tf
diff --git a/live/prod/us-west-2/app/vpc.tf b/live/common-infra/vpc.tf
similarity index 84%
rename from live/prod/us-west-2/app/vpc.tf
rename to live/common-infra/vpc.tf
index 16a3f0b..ae45af9 100644
--- a/live/prod/us-west-2/app/vpc.tf
+++ b/live/common-infra/vpc.tf
@@ -1,7 +1,13 @@
+variable "vpc_cidr_block" {
+ description = "CIDR block for the VPC"
+ type = string
+ default = "10.0.0.0/16"
+}
+
module "vpc" {
- source = "../../../../modules/vpc"
+ source = "../../modules/vpc"
name = module.label.id
- vpc_cidr_block = "10.0.0.0/16"
+ vpc_cidr_block = var.vpc_cidr_block
tags = module.label.tags
enable_nat_gateway = true
single_nat_gateway = true
diff --git a/live/prod/us-west-2/app/context.tf b/live/prod/us-west-2/app/context.tf
deleted file mode 100644
index 29e3340..0000000
--- a/live/prod/us-west-2/app/context.tf
+++ /dev/null
@@ -1,34 +0,0 @@
-locals {
- context = {
- name = "app"
- namespace = "nan"
- environment = "prod"
- tags = {
- "Terraform" = "true"
- "Environment" = "prod"
- }
- }
-}
-
-data "aws_caller_identity" "aws" {}
-
-locals {
- tf_tags = {
- Terraform = true,
- By = data.aws_caller_identity.aws.arn
- }
-}
-
-// Keep labels, tags consistent
-module "label" {
- source = "cloudposse/label/null"
- version = "0.25.0"
-
- name = local.context.name
- environment = local.context.environment
- namespace = local.context.namespace
-
- delimiter = "-"
- label_order = ["namespace", "environment", "name", "attributes"]
- tags = merge(local.context.tags, local.tf_tags)
-}
diff --git a/live/staging/us-west-2/app/README.md b/live/staging/us-west-2/app/README.md
deleted file mode 100644
index bf0c60c..0000000
--- a/live/staging/us-west-2/app/README.md
+++ /dev/null
@@ -1,204 +0,0 @@
-# Staging Infrastructure (us-west-2)
-
-🏢 This directory contains the infrastructure as code for our cloud infrastructure. It provides a ready-to-use Terraform module with various features. Follow the steps below to get started.
-
-## Features
-
-- ✨ Ready to use Root Terraform module!
-- 🗄️ Store Terraform state in an S3 bucket with a DynamoDB table for locking.
-- 🌐 VPC with public and private subnets (application and database subnets) in three availability zones.
-- 🔒 Security groups for bastion host and database.
-- 🔑 Bastion host to access private resources.
-- 🐘 RDS Postgres instance and other database resources.
-- 🔒 AWS Secrets Manager to store database credentials.
-- 🔧 SSM Parameter Store to store parameters such as VPC ID, Subnet IDs, etc.
-
-## Prerequisites
-
-- [Terraform](https://www.terraform.io/downloads.html)
-- [TFswitch](https://tfswitch.warrensbox.com/)
-
-## Setup
-
-1. Switch to the correct Terraform version
-
-```sh
-tfswitch
-```
-
-2. Initialize the Terraform working directory:
-
-```sh
-terraform init
-```
-
-## Deploy
-
-1. Plan the deployment:
-
-```sh
-terraform plan -out ./staging.tfplan
-```
-
-2. Apply the deployment:
-
-```sh
-terraform apply ./staging.tfplan
-```
-
-### First Time Deployment?
-
-If this is the first time you are deploying, a file called `s3-backend.tf` will be created. This file configures the backend for Terraform, using S3 to store the state of our infrastructure.
-
-Run the following command to copy the state to the S3 bucket:
-
-```sh
-terraform init -force-copy
-```
-
-Push the `s3-backend.tf` file to the repository:
-
-```sh
-git add s3-backend.tf && git commit -m "Add s3-backend.tf file"
-git push
-```
-
-## Destroy
-
-To destroy the infrastructure, run the following command:
-
-```sh
-terraform destroy
-```
-
-## Post Deployment Steps
-
-After successfully deploying the infrastructure, follow these steps to test the deployment and ensure everything is working as expected:
-
-### Accessing the Parameter Store
-
-Retrieve stored values, such as the VPC ID, using the AWS Parameter Store:
-
-```bash
-# Retrieve the parameter value from the AWS Parameter Store
-vpc_id_parameter_name=$(terraform output -json | jq -r '.ssm_parameter_vpc_id.value')
-vpc_id=$(aws ssm get-parameter --name "$vpc_id_parameter_name" --query 'Parameter.Value' --output text)
-
-# Print the value
-echo "VPC ID: $vpc_id"
-```
-
-### Connecting to the Bastion Host
-
-To establish a secure connection with the bastion host, follow these steps:
-
-#### Obtain Required Information
-
-First, you need to gather some essential information:
-
-- Bastion SSH Parameter Name
-- Bastion Instance ID
-
-You can retrieve these values using Terraform:
-
-```bash
-bastion_ssh_parameter_name=$(terraform output -json | jq -r '.ssm_parameter_bastion_ssh_key.value')
-bastion_instance_id=$(terraform output -json | jq -r '.bastion_instance_id.value')
-```
-
-#### Generate .pem file with the ssh key
-
-```bash
-aws ssm get-parameter --name "$bastion_ssh_parameter_name" --with-decryption --query 'Parameter.Value' --output text > /tmp/ssh_key.pem
-chmod 400 /tmp/ssh_key.pem
-```
-
-#### Retrieve bastion's public IP
-
-```bash
-bastion_public_ip=$(aws ec2 describe-instances --instance-ids "$bastion_instance_id" --query 'Reservations[0].Instances[0].PublicIpAddress' --output text | tr '.' '-')
-
-# Print the value
-echo "Bastion IP: $bastion_public_ip"
-```
-
-#### Connect to Bastion Host
-
-```bash
-ssh -i "/tmp/ssh_key.pem" ubuntu@ec2-"$bastion_public_ip".us-west-2.compute.amazonaws.com
-```
-
-Ensure that you can access the database from the bastion host and verify that Docker is functioning correctly.
-
-#### Testing Docker and Internet Access
-
-To verify internet access and Docker functionality, execute the following commands:
-
-```bash
-# Test Internet Access
-ping -c 3 google.com
-
-# Test Docker
-docker run -it --rm hello-world
-```
-
-#### Connecting to the Database
-
-To connect to the database from the bastion host, retrieve the connection information from AWS Secrets Manager. Follow these steps:
-
-- Outside the bastion host:
-
-```bash
-# Retrieve the parameter value from the AWS Parameter Store
-SECRET_ID=$(terraform output -json | jq -r '.example_db_connection_secret_arn.value')
-```
-
-- Inside the bastion host:
-
-```bash
-# Retrieve the connection information from AWS Secrets Manager
-db_secret=$(aws secretsmanager get-secret-value --secret-id "$SECRET_ID" \
- --query 'SecretString' --output json)
-
-# Parse the connection information to obtain the username, password, host, port, and database name
-db_username=$(echo $db_secret | jq -r '.username')
-db_password=$(echo $db_secret | jq -r '.password')
-db_host=$(echo $db_secret | jq -r '.host')
-db_port=$(echo $db_secret | jq -r '.port')
-db_name=$(echo $db_secret | jq -r '.dbname')
-
-# Connect to the database using Psql with Docker
-docker run -it --rm postgres:14.0-alpine psql -h $db_host -p $db_port -U $db_username -d $db_name
-```
-
-You can now execute SQL commands to test the database setup. For example:
-
-- Retrieve the current date and time:
-
-```sql
-> SELECT NOW();
-```
-
-- Check the database version:
-
-```sql
-> SELECT version();
-```
-
-- List the tables in the database:
-
-```sql
-> SELECT table_name FROM information_schema.tables WHERE table_schema = 'public';
-```
-
-These steps will help you verify the successful setup of the database and ensure that the necessary connections and configurations are in place.
-
-## Module Documentation
-
-The module documentation is generated with [terraform-docs](https://github.com/terraform-docs/terraform-docs) by running the following command from the module directory:
-
-```sh
-terraform-docs md . > ./docs/MODULE.md
-```
-
-You can also view the latest version of the module documentation [here](./docs/MODULE.md).
diff --git a/live/staging/us-west-2/app/bastion.tf b/live/staging/us-west-2/app/bastion.tf
deleted file mode 100644
index 2b7ffea..0000000
--- a/live/staging/us-west-2/app/bastion.tf
+++ /dev/null
@@ -1,30 +0,0 @@
-locals {
- bastion = {
- enable = true
- }
-}
-
-module "bastion" {
- count = local.bastion.enable ? 1 : 0
-
- source = "../../../../modules/bastion"
- name = "${module.label.id}-bastion"
- vpc_id = module.vpc.vpc_id
- subnets = module.vpc.public_subnets
- associate_public_ip_address = true
- associate_elastic_ip_address = true
- tags = module.label.tags
-}
-
-output "bastion_instance_id" {
- value = local.bastion.enable ? module.bastion[0].instance_id : null
-}
-
-output "bastion_instance_profile" {
- value = local.bastion.enable ? module.bastion[0].instance_profile : null
-}
-
-output "ssm_parameter_bastion_ssh_key" {
- description = "name of the ssm parameter for the bastion ssh key"
- value = local.bastion.enable ? module.bastion[0].ssm_parameter_ssh_key : null
-}
diff --git a/live/staging/us-west-2/app/context.tf b/live/staging/us-west-2/app/context.tf
deleted file mode 100644
index 8090493..0000000
--- a/live/staging/us-west-2/app/context.tf
+++ /dev/null
@@ -1,34 +0,0 @@
-locals {
- context = {
- name = "app"
- namespace = "nan"
- environment = "staging"
- tags = {
- "Terraform" = "true"
- "Environment" = "staging"
- }
- }
-}
-
-data "aws_caller_identity" "aws" {}
-
-locals {
- tf_tags = {
- Terraform = true,
- By = data.aws_caller_identity.aws.arn
- }
-}
-
-// Keep labels, tags consistent
-module "label" {
- source = "cloudposse/label/null"
- version = "0.25.0"
-
- name = local.context.name
- environment = local.context.environment
- namespace = local.context.namespace
-
- delimiter = "-"
- label_order = ["namespace", "environment", "name", "attributes"]
- tags = merge(local.context.tags, local.tf_tags)
-}
diff --git a/live/staging/us-west-2/app/example-rds-instance.tf b/live/staging/us-west-2/app/example-rds-instance.tf
deleted file mode 100644
index 46fdade..0000000
--- a/live/staging/us-west-2/app/example-rds-instance.tf
+++ /dev/null
@@ -1,45 +0,0 @@
-locals {
- exampledb = {
- db_name = "mydb"
- db_master_username = "myuser"
- }
-}
-
-module "exampledb" {
- source = "../../../../modules/rds"
-
- name = "${module.label.id}-exampledb"
-
- vpc_id = module.vpc.vpc_id
- db_subnet_group = module.vpc.database_subnet_group
-
- db_name = local.exampledb.db_name
- db_master_username = local.exampledb.db_master_username
- db_port = 5432
-
- allocated_storage = 20
-
- manage_master_user_password = true
-
- tags = module.label.tags
-}
-
-output "example_db_instance_address" {
- description = "The address of the RDS instance"
- value = module.exampledb.db_instance_address
-}
-
-output "example_db_instance_port" {
- description = "The database port"
- value = module.exampledb.db_instance_port
-}
-
-output "example_db_instance_name" {
- description = "The database name"
- value = module.exampledb.db_instance_name
-}
-
-output "example_db_instance_master_user_secret_arn" {
- description = "The ARN of the secret containing the connection details for the RDS instance"
- value = module.exampledb.db_instance_master_user_secret_arn
-}
diff --git a/live/staging/us-west-2/app/vpc.tf b/live/staging/us-west-2/app/vpc.tf
deleted file mode 100644
index 1da0966..0000000
--- a/live/staging/us-west-2/app/vpc.tf
+++ /dev/null
@@ -1,38 +0,0 @@
-module "vpc" {
- source = "../../../../modules/vpc"
- name = module.label.id
- vpc_cidr_block = "10.1.0.0/16"
- tags = module.label.tags
- enable_nat_gateway = true
- single_nat_gateway = true
-}
-
-output "ssm_parameter_vpc_id" {
- description = "name of the ssm parameter for the vpc id"
- value = module.vpc.ssm_parameter_vpc_id
-}
-
-output "ssm_parameter_public_subnets" {
- description = "name of the ssm parameter for the public subnets"
- value = module.vpc.ssm_parameter_public_subnets
-}
-
-output "ssm_parameter_private_subnets" {
- description = "name of the ssm parameter for the private subnets"
- value = module.vpc.ssm_parameter_private_subnets
-}
-
-output "ssm_parameter_database_subnets" {
- description = "name of the ssm parameter for the database subnets"
- value = module.vpc.ssm_parameter_database_subnets
-}
-
-output "ssm_parameter_app_subnets" {
- description = "name of the ssm parameter for the app subnets"
- value = module.vpc.ssm_parameter_app_subnets
-}
-
-output "ssm_parameter_app_security_group" {
- description = "name of the ssm parameter for the app security group"
- value = module.vpc.ssm_parameter_app_security_group
-}
diff --git a/live/staging/us-west-2/app/.terraform.lock.hcl b/live/terraform-backend/.terraform.lock.hcl
similarity index 100%
rename from live/staging/us-west-2/app/.terraform.lock.hcl
rename to live/terraform-backend/.terraform.lock.hcl
diff --git a/live/terraform-backend/README.md b/live/terraform-backend/README.md
new file mode 100644
index 0000000..6d6cf9a
--- /dev/null
+++ b/live/terraform-backend/README.md
@@ -0,0 +1,77 @@
+# Terraform S3 Backend Configuration
+
+🔒 This directory contains the Terraform configuration for setting up and managing the S3 backend used for storing the state of our cloud infrastructure securely.
+
+## Features
+
+- ✨ Utilization of the [cloudposse/tfstate-backend/aws](https://github.com/cloudposse/terraform-aws-tfstate-backend) module for robust backend setup.
+- 🗄️ Secure storage of Terraform state in an S3 bucket.
+- 🔒 DynamoDB table for state locking to prevent concurrent state modifications.
+
+## Prerequisites
+
+- [Terraform](https://www.terraform.io/downloads.html) installed on your machine.
+- Proper AWS credentials configured that can access the necessary resources.
+- [TFswitch](https://tfswitch.warrensbox.com/) for managing Terraform versions.
+
+## Setup
+
+1. **Initialize Terraform:**
+
+ Initialize the Terraform working directory which will download the necessary providers and modules:
+
+ ```sh
+ terraform init
+ ```
+
+## Deploy
+
+1. **Plan the Deployment:**
+
+ Generate an execution plan for Terraform:
+
+ ```sh
+ terraform plan -var-file ./configs/common-infra.tfvars -out ./common-infra.tfplan
+ ```
+
+2. **Apply the Configuration:**
+
+ Apply the configuration to set up the S3 bucket and DynamoDB table:
+
+ ```sh
+ terraform apply "./common-infra.tfplan"
+ ```
+
+ 🚀 **NOTE:** Confirm the actions before proceeding to ensure that the correct resources are being created or modified.
+
+### First Time Deployment?
+
+If this is your first deployment, Terraform will prompt you to confirm the setup of the backend. This is a critical step as it involves creating resources that will handle your Terraform state.
+
+- **Initiate Backend Transfer:**
+
+ If migrating from a local state, use the following command to migrate the state to the S3 bucket safely:
+
+ ```sh
+ terraform init -force-copy
+ ```
+
+ Push the changes to your version control system:
+
+ ```sh
+ git add s3-backend.tf && git commit -m "Setup Terraform S3 backend"
+ git push
+ ```
+
+## Destroy
+
+To remove the backend infrastructure, you can run the following command. Be cautious as this will remove the S3 bucket and the DynamoDB table used for state locking:
+
+```sh
+terraform destroy
+```
+
+## Additional Notes
+
+- **Security Best Practices:** Ensure that the S3 bucket and DynamoDB table have strict access policies to protect your state files.
+- **Documentation:** Keep documentation up to date and ensure all team members are aware of the backend configurations and how to handle state files securely.
diff --git a/live/staging/us-west-2/app/backend.tf b/live/terraform-backend/backend.tf
similarity index 72%
rename from live/staging/us-west-2/app/backend.tf
rename to live/terraform-backend/backend.tf
index 0cff6d7..e1dbb34 100644
--- a/live/staging/us-west-2/app/backend.tf
+++ b/live/terraform-backend/backend.tf
@@ -6,14 +6,13 @@ module "terraform_state_backend" {
source = "cloudposse/tfstate-backend/aws"
version = "1.1.1"
- name = module.label.name
- namespace = module.label.namespace
- environment = module.label.environment
- attributes = ["state"]
+ name = var.name
+ namespace = var.namespace
+ attributes = ["state"]
terraform_backend_config_file_path = "."
terraform_backend_config_file_name = "s3-backend.tf"
- terraform_state_file = "${module.label.id}.tfstate"
+ terraform_state_file = "${var.namespace}-${var.name}.tfstate"
bucket_enabled = true
dynamodb_enabled = true
diff --git a/live/terraform-backend/configs/common-infra.tfvars b/live/terraform-backend/configs/common-infra.tfvars
new file mode 100644
index 0000000..7c44863
--- /dev/null
+++ b/live/terraform-backend/configs/common-infra.tfvars
@@ -0,0 +1,8 @@
+# General settings
+
+region = "us-west-2"
+name = "core"
+namespace = "nan"
+tags = {
+ "Terraform" = "true"
+}
diff --git a/live/terraform-backend/context.tf b/live/terraform-backend/context.tf
new file mode 100644
index 0000000..7fb1402
--- /dev/null
+++ b/live/terraform-backend/context.tf
@@ -0,0 +1,26 @@
+variable "name" {
+ description = "Name to use for servers, tags, etc"
+ type = string
+ default = "name"
+}
+
+variable "namespace" {
+ description = "Namespace, which could be your organization name or abbreviation, e.g. 'eg' or 'cp'"
+ type = string
+ default = "development"
+}
+
+variable "tags" {
+ description = "Any extra tags to assign to objects"
+ type = map(any)
+ default = {}
+}
+
+data "aws_caller_identity" "aws" {}
+
+locals {
+ tf_tags = {
+ Terraform = true,
+ By = data.aws_caller_identity.aws.arn
+ }
+}
diff --git a/live/staging/us-west-2/app/docs/MODULE.md b/live/terraform-backend/docs/MODULE.md
similarity index 66%
rename from live/staging/us-west-2/app/docs/MODULE.md
rename to live/terraform-backend/docs/MODULE.md
index a5e3ad2..94f63be 100644
--- a/live/staging/us-west-2/app/docs/MODULE.md
+++ b/live/terraform-backend/docs/MODULE.md
@@ -16,11 +16,11 @@
| Name | Source | Version |
|------|--------|---------|
-| [bastion](#module\_bastion) | ../../../../modules/bastion | n/a |
-| [exampledb](#module\_exampledb) | ../../../../modules/rds | n/a |
+| [bastion](#module\_bastion) | ../../modules/bastion | n/a |
+| [exampledb](#module\_exampledb) | ../../modules/rds | n/a |
| [label](#module\_label) | cloudposse/label/null | 0.25.0 |
| [terraform\_state\_backend](#module\_terraform\_state\_backend) | cloudposse/tfstate-backend/aws | 1.1.1 |
-| [vpc](#module\_vpc) | ../../../../modules/vpc | n/a |
+| [vpc](#module\_vpc) | ../../modules/vpc | n/a |
## Resources
@@ -30,7 +30,18 @@
## Inputs
-No inputs.
+| Name | Description | Type | Default | Required |
+|------|-------------|------|---------|:--------:|
+| [enable\_bastion](#input\_enable\_bastion) | Enable bastion host | `bool` | `false` | no |
+| [environment](#input\_environment) | Environment, e.g. 'prod', 'staging', 'dev', 'pre-prod', 'UAT' | `string` | `"development"` | no |
+| [example\_db\_master\_username](#input\_example\_db\_master\_username) | The username for the master DB user | `string` | `"root"` | no |
+| [example\_db\_name](#input\_example\_db\_name) | The name of the database to create | `string` | `"mydb"` | no |
+| [name](#input\_name) | Name to use for servers, tags, etc | `string` | `"name"` | no |
+| [namespace](#input\_namespace) | Namespace, which could be your organization name or abbreviation, e.g. 'eg' or 'cp' | `string` | `"development"` | no |
+| [region](#input\_region) | AWS region | `string` | `"us-west-2"` | no |
+| [stage](#input\_stage) | Stage, e.g. 'build', 'test', 'deploy', 'release' | `string` | `null` | no |
+| [tags](#input\_tags) | Any extra tags to assign to objects | `map(any)` | `{}` | no |
+| [vpc\_cidr\_block](#input\_vpc\_cidr\_block) | CIDR block for the VPC | `string` | `"10.0.0.0/16"` | no |
## Outputs
diff --git a/live/staging/us-west-2/app/main.tf b/live/terraform-backend/main.tf
similarity index 78%
rename from live/staging/us-west-2/app/main.tf
rename to live/terraform-backend/main.tf
index fe5e8dc..143ee86 100644
--- a/live/staging/us-west-2/app/main.tf
+++ b/live/terraform-backend/main.tf
@@ -1,5 +1,5 @@
provider "aws" {
- region = "us-west-2"
+ region = var.region
default_tags {
tags = {
diff --git a/live/staging/us-west-2/app/outputs.tf b/live/terraform-backend/outputs.tf
similarity index 100%
rename from live/staging/us-west-2/app/outputs.tf
rename to live/terraform-backend/outputs.tf
diff --git a/live/terraform-backend/variables.tf b/live/terraform-backend/variables.tf
new file mode 100644
index 0000000..098424d
--- /dev/null
+++ b/live/terraform-backend/variables.tf
@@ -0,0 +1,5 @@
+variable "region" {
+ description = "AWS region"
+ type = string
+ default = "us-west-2"
+}
diff --git a/live/staging/us-west-2/app/versions.tf b/live/terraform-backend/versions.tf
similarity index 100%
rename from live/staging/us-west-2/app/versions.tf
rename to live/terraform-backend/versions.tf