> ## Documentation Index
> Fetch the complete documentation index at: https://docs.lerian.studio/llms.txt
> Use this file to discover all available pages before exploring further.

# Midaz Terraform Foundation

> Provision the base infrastructure for Midaz on AWS, GCP, or Azure with ready-made Terraform examples — networking, databases, and Kubernetes.

Midaz Terraform Foundation is a repository of ready-made Terraform examples. Use them to create the base infrastructure that Midaz needs on AWS, GCP, or Azure. The examples follow each cloud provider's best practices.

This base infrastructure includes:

* Network (VPC, subnets)
* DNS
* Database
* Redis/Valkey
* Kubernetes cluster (EKS, GKE, or AKS)

<Danger>
  The templates provision a MongoDB-compatible database and a message broker only on some providers. AWS uses Amazon DocumentDB and Amazon MQ (RabbitMQ). Azure uses Cosmos DB with the MongoDB API. GCP has no managed equivalent, so you must provision MongoDB and RabbitMQ yourself on GCP.
</Danger>

## Why use it

***

Infrastructure provisioning should not be slow, inconsistent, or error-prone. `midaz-terraform-foundation` follows Lerian's best practices for security, observability, and scalability. The tables below compare it to a manual or ad-hoc setup.

### Speed and standardization

| **Criteria**              | **With Midaz Terraform**                                           | **Manual Setup / Ad-hoc Scripts**            |
| :------------------------ | :----------------------------------------------------------------- | :------------------------------------------- |
| **Setup speed**           | **Fast** – provisions everything in minutes with a single `apply`. | **Slow** – takes days to configure and test. |
| **Architecture standard** | **Standardized** – follows Lerian's best practices.                | **Unpredictable** – may be inconsistent.     |
| **Reusability**           | **High** – supports multiple environments with minimal changes.    | **Low** – hard to reuse across projects.     |

### Security and observability

| **Criteria**               | **With Midaz Terraform**                                        | **Manual Setup / Ad-hoc Scripts**                       |
| :------------------------- | :-------------------------------------------------------------- | :------------------------------------------------------ |
| **Security by default**    | **Yes** – secure by design (isolated VPCs, IAM, secrets, etc.). | **No** – depends on the team, increasing exposure risk. |
| **Built-in observability** | **Built-in** – integrates with Prometheus, Grafana, and more.   | **Manual** – requires separate setup, often skipped.    |
| **Production-ready?**      | **Yes** – high availability and autoscaling out of the box.     | **Uncertain** – needs extra effort to harden.           |

### Maintenance and support

| **Criteria**                  | **With Midaz Terraform**                               | **Manual Setup / Ad-hoc Scripts**             |
| :---------------------------- | :----------------------------------------------------- | :-------------------------------------------- |
| **Maintainability**           | **Easy** – modular and versioned for painless updates. | **Hard** – scripts break easily.              |
| **Lerian support**            | **Included** – verified and supported by Lerian.       | **None** – not guaranteed.                    |
| **Estimated deployment time** | **1 day** – including validation.                      | **1–2 weeks** – with higher operational risk. |

<Tip>
  Use this repository for a faster, tested setup.

  `midaz-terraform-foundation` follows Lerian's engineering standards. It helps you deploy faster and avoid common setup errors.
</Tip>

## What you’ll need

***

Before you start, make sure you have:

* [Terraform v1.0.0 or higher](https://developer.hashicorp.com/terraform/install)
* A cloud provider account (AWS, GCP, or Azure).
* A storage bucket for Terraform state files.
* The CLI tool for your cloud provider:
  * `aws` for AWS
  * `gcloud` for GCP
  * `az` for Azure

### CI/CD Integration

This repository provides Terraform examples to deploy foundation infrastructure. It **does not include a CI/CD pipeline**. Create one that fits your project's needs.

Do you already run a Terraform CI/CD pipeline? Follow these steps:

<Steps>
  <Step>
    **Skip the deployment script.** It is for local use only.
  </Step>

  <Step>
    Copy the relevant example configs into your private Infrastructure as Code repo.
  </Step>

  <Step>
    Integrate the Terraform configs into your pipeline as needed.
  </Step>

  <Step>
    Use your CI/CD platform’s built-in secret management to handle credentials securely.
  </Step>
</Steps>

## Project structure

***

Each cloud provider has its own structure in the repository. Every infrastructure component follows a modular, controlled layout. You can deploy only the components you need, or the entire foundation.

```bash theme={null}
.
├── examples/
    ├── aws/
    │   ├── vpc/
    │   ├── route53/
    │   ├── rds/
    │   ├── documentdb/
    │   ├── amazonmq/
    │   ├── valkey/
    │   └── eks/
    ├── gcp/
    │   ├── vpc/
    │   ├── cloud-dns/
    │   ├── cloud-sql/
    │   ├── valkey/
    │   └── gke/
    └── azure/
        ├── network/
        ├── dns/
        ├── database/
        ├── cosmosdb/
        ├── redis/
        └── aks/
```

### Deployment order matters

To avoid errors and connect everything correctly, deploy the components in this order:

1. VPC / Network
2. DNS
3. Database
4. Redis/Valkey
5. Kubernetes cluster

## Creating the state storage

***

Terraform requires a remote backend to manage its state. Before you use these templates, create a storage bucket for the Terraform state files.

### AWS

**Replace `REGION` and `UNIQUE_BUCKET_NAME` with your own values.**

<Steps>
  <Step title="Create an S3 bucket">
    ```
     aws s3api create-bucket \
        --bucket UNIQUE_BUCKET_NAME \
        --region REGION \
        --create-bucket-configuration LocationConstraint=REGION
    ```
  </Step>

  <Step title="Enable versioning">
    ```
    aws s3api put-bucket-versioning \
        --bucket UNIQUE_BUCKET_NAME \
        --versioning-configuration Status=Enabled
    ```
  </Step>

  <Step title="Enable encryption">
    ```
    aws s3api put-bucket-encryption \
        --bucket UNIQUE_BUCKET_NAME \
        --server-side-encryption-configuration \
        '{"Rules":[{"ApplyServerSideEncryptionByDefault":{"SSEAlgorithm":"AES256"}}]}'
    ```
  </Step>

  <Step title="Block public access">
    ```
    aws s3api put-public-access-block \
        --bucket UNIQUE_BUCKET_NAME \
        --public-access-block-configuration \    '{"BlockPublicAcls":true,"IgnorePublicAcls":true,"BlockPublicPolicy":true,"RestrictPublicBuckets":true}'
    ```
  </Step>
</Steps>

### Google Cloud Platform

<Steps>
  <Step title="Create a GCS bucket">
    ```
    gsutil mb -l us-central1 gs://your-terraform-state-bucket
    ```
  </Step>

  <Step title="Enable versioning">
    ```
    gsutil versioning set on gs://your-terraform-state-bucket
    ```
  </Step>
</Steps>

### Azure

<Steps>
  <Step title="Create a resource group">
    ```
    az group create --name terraform-state-rg --location eastus
    ```
  </Step>

  <Step title="Create a storage account">
    ```
    az storage account create --name tfstate$RANDOM --resource-group terraform-state-rg --sku Standard_LRS
    ```
  </Step>

  <Step title="Create a container">
    ```
    az storage container create --name terraform-state --account-name <storage-account-name>
    ```
  </Step>
</Steps>

## Configuration requirements

***

Before you deploy the infrastructure, create and configure the variables file for each cloud component:

<Steps>
  <Step title="Copy the example file">
    ```
    cd examples/<provider>/<component>
    cp midaz.tfvars-example midaz.tfvars
    ```
  </Step>

  <Step>
    Replace all placeholders in the `midaz.tfvars` file with your actual values. \\

    i. **This file holds the key configuration for your infrastructure setup.**
  </Step>
</Steps>

## Production credentials and deployment

***

In production environments, you must manage credentials with care. This guide shows how to handle credentials securely.

### Cloud provider authentication

When you run the deploy script locally, use the cloud provider's CLI authentication tools instead of raw credentials. This method is more secure. It manages credential rotation, MFA, and token refresh automatically.

**Why adopt this approach?**

* Tokens refresh automatically.
* MFA and SSO integration out of the box.
* It rotates and stores credentials securely.
* Full audit trail for authentication events.

#### AWS

Use AWS CLI to assume a role.

```
aws sso login --profile your-profile
```

or

```
aws sts assume-role --role-arn arn:aws:iam::ACCOUNT_ID:role/ROLE_NAME --role-session-name terraform
```

#### GCP

Use gcloud authentication.

```
gcloud auth application-default login
```

**For service accounts**, use the following code:

```
gcloud auth activate-service-account --key-file=path/to/service-account.json
```

#### Azure

Use Azure CLI.

```
az login
```

For service principals, use the following code:

```
az login --service-principal
```

### Credential management best practices

Stay safe and compliant by following your cloud provider’s official guidance:

* **AWS**: [Managing AWS access keys](https://docs.aws.amazon.com/general/latest/gr/aws-access-keys-best-practices.html).
* **GCP**: [Managing service account keys](https://cloud.google.com/iam/docs/best-practices-for-managing-service-account-keys).
* **Azure**: [Identity management best practices](https://learn.microsoft.com/en-us/azure/security/fundamentals/identity-management-best-practices).

#### Recommended practices

* Rotate credentials on a regular schedule.
* Use role-based access control (RBAC) wherever possible.
* Require MFA for user accounts.
* Prefer short-lived, temporary credentials.
* Monitor and audit credential use.
* **Never** commit credentials to version control.

## Using the deploy script

***

The `deploy.sh` script handles the setup sequence, highlights issues, and deploys each component in the correct order.

### What it does

* Allows you to pick your cloud provider (AWS, Azure, or GCP).
* Offers options to deploy or destroy the stack.
* Checks that all backend configuration placeholders have values.
* Runs Terraform commands in the right order for each component.
* Outputs clear, color-coded logs so you know what’s happening at every step.

### How to use it

<Steps>
  <Step>
    Make sure that all **prerequisites are complete** and that you **created your remote state bucket**.
  </Step>

  <Step>
    Fill in all the **placeholders** in the `backend.tf` files.
  </Step>

  <Step title="Make the script executable">
    ```
    chmod +x deploy.sh
    ```
  </Step>

  <Step title="Run the script">
    ```
    ./deploy.sh
    ```
  </Step>

  <Step>
    When prompted, select your cloud provider.
  </Step>

  <Step title="The script will automatically">
    i. Check the remaining placeholders. \\

    ii. Run `terraform init`, `plan`, and `apply` for each component. \\

    iii. Deploy in the correct order and stop if something fails.
  </Step>
</Steps>

### Error handling

We built the script to fail quickly and provide an explanation. If something goes wrong, it will:

* Stop immediately if it finds placeholders you forgot to fill in.
* Exit if any Terraform command fails.
* Show you exactly which component failed and at what step.

## Installing Midaz

***

After deploying the foundation infrastructure, you can install Midaz using Helm. For more information, refer to the [Deploying using Helm](/en/platform/helm/midaz/midaz-installation) page.

#### Prerequisites

* A running Kubernetes cluster (EKS, GKE, or AKS).
* `kubectl` configured to access the cluster.
* Helm v3.x installed.
* Access to the [Midaz Helm repo](https://github.com/LerianStudio/helm).

### Install steps

<Steps>
  <Step>
    Add the Midaz Helm repository:

    ```
    helm repo add midaz https://lerianstudio.github.io/helm
    helm repo update
    ```
  </Step>

  <Step>
    Create a values file (`values.yaml`) with your configuration:

    ```bash expandable theme={null}
    # Example values.yaml
    # Disable default dependencies
    valkey:
       enabled: false

    postgresql:
       enabled: false

    ## Configure external PostgreSQL
    onboarding:
      configmap:
        DB_HOST: "postgresql.midaz.internal."
        DB_USER: "midaz"
        DB_PORT: "5432"
        DB_REPLICA_HOST: "postgresql-replica.midaz.internal."
        DB_REPLICA_USER: "midaz"
        DB_REPLICA_PORT: "5432"
        REDIS_HOST: "valkey.midaz.internal"
        REDIS_PORT: "6379"
      secrets:
         DB_PASSWORD: "<your-db-password>"
         DB_REPLICA_PASSWORD: "<your-replica-db-password>"
         REDIS_PASSWORD: "<your-redis-password>"

    transaction:
      configmap:
        DB_HOST: "postgresql.midaz.internal."
        DB_USER: "midaz"
        DB_PORT: "5432"
        DB_REPLICA_HOST: "postgresql-replica.midaz.internal."
        DB_REPLICA_USER: "midaz"
        DB_REPLICA_PORT: "5432"
        REDIS_HOST: "valkey.midaz.internal"
        REDIS_PORT: "6379"
      secrets:
        DB_PASSWORD: "<your-db-password>"
        DB_REPLICA_PASSWORD: "<your-replica-db-password>"
        REDIS_PASSWORD: "<your-redis-password>"
    ```
  </Step>

  <Step>
    Install Midaz:

    ```
    helm install midaz midaz/midaz -f values.yaml
    ```
  </Step>
</Steps>

For detailed configuration options and advanced setup, please refer to the [Midaz Helm Repository](https://github.com/LerianStudio/helm).

## Security tips

***

The cloud brings opportunities and responsibilities. To keep your Midaz infrastructure secure, follow these recommendations:

* Always use **private Kubernetes clusters** to limit public exposure.
* Access the **Kubernetes API via VPN** instead of allowing public access.
* Set up and **enforce RBAC** (Role-Based Access Control) to manage user permissions effectively.
* Store all secrets in the cloud provider’s **secret management service**.
* Give service accounts only the **permissions they truly need**.

## Contributing

***

Before you make any changes, set up Git hooks. Git hooks make sure every commit follows our standards and passes the required checks.

<Steps>
  <Step title="Install the Git hooks">
    ```
    make hooks
    ```
  </Step>

  <Step title="Create a new feature branch">
    ```
    git checkout -b feature/your-feature
    ```
  </Step>

  <Step>
    Make your changes and commit using Conventional Commits.
  </Step>

  <Step>
    Open a pull request targeting the `develop` branch.
  </Step>

  <Step>
    After tests pass and a maintainer approves, your changes merge into `main`.
  </Step>
</Steps>

Check out our [Contributing Guide](https://github.com/LerianStudio/midaz-terraform-foundation/blob/main/CONTRIBUTING.md) to learn more about how we work together and what we expect from contributors.

## License

***

Midaz Terraform Foundation uses the [Apache License 2.0](https://github.com/LerianStudio/midaz-terraform-foundation/blob/main/LICENSE).

## Need help?

***

* Check the README inside each component folder.
* Search existing [issues](https://github.com/LerianStudio/midaz-terraform-foundation/issues).
* Open a new issue if needed.
