# Terraform Module

The Terraform module option provides maximum simplicity. It provisions all the required infrastructure and permissions in your cloud provider of choice before deploying the DBNL platform Helm chart, removing the need to provision any infrastructure or permission separately.

Terraform modules are available for AWS, GCP and Azure. For access to the Terraform module for your cloud provider of choice see <https://registry.terraform.io/namespaces/dbnlai>.

## Prerequisites

The following prerequisite steps are required before starting the Terraform module installation.

### Configuration

To configure the Terraform module, you will need:

* A domain name to host the DBNL platform (e.g. dbnl.example.com).
* An RSA key pair to sign the personal access tokens as part of [Authentication](https://docs.dbnl.com/v0.29.x/platform/authentication).

An RSA key pair can be generated with:

```bash
openssl genrsa -out dbnl_dev_token_key.pem 2048
```

### Requirements

On the environment from which you are planning to install the module, you will need to:

* Install [kubectl](https://kubernetes.io/docs/tasks/tools/)
* Install [helm](https://helm.sh/docs/intro/install/)
* Install [terraform](https://developer.hashicorp.com/terraform/tutorials/aws-get-started/install-cli)

### Infrastructure

At a minimum, the user performing the installation needs to be able to provision the following infrastructure:

{% tabs %}
{% tab title="AWS" %}

* [Amazon Elastic Kubernetes Service](https://aws.amazon.com/eks/) (EKS)
* [Amazon Elastic Load Balancing](https://aws.amazon.com/elasticloadbalancing/) (ALB)
* [Amazon ElastiCache](https://aws.amazon.com/elasticache/)
* [Amazon RDS for PostgreSQL](https://aws.amazon.com/rds/postgresql/)
* [Amazon S3](https://aws.amazon.com/pm/serv-s3/)
* [Amazon Virtual Private Cloud](https://aws.amazon.com/vpc/) (VPC)
* [AWS Certificate Manager](https://aws.amazon.com/certificate-manager/) (ACM)
* [AWS Identity & Access Management](https://aws.amazon.com/iam/) (IAM)
  {% endtab %}

{% tab title="GCP" %}

* [GCP Identity and Access Management](https://cloud.google.com/security/products/iam) (IAM)
* [Google Cloud Storage](https://cloud.google.com/storage?hl=en) (GCS)
* [GCP Virtual Private Cloud](https://cloud.google.com/vpc?hl=en) (VPC)
* [GCP Cloud SQL for PostgreSQL](https://cloud.google.com/sql/docs/postgres)
* [GCP Memorystore for Redis](https://cloud.google.com/memorystore/docs/redis?hl=en)
* [Google Kubernetes Engine](https://cloud.google.com/kubernetes-engine?hl=en) (GKE)
* [Google-managed SSL Certificates](https://cloud.google.com/load-balancing/docs/ssl-certificates/google-managed-certs)

Specific APIs that need to be enabled for your Google Project:

* [GCP Compute Engine](https://cloud.google.com/compute/docs/reference/rest/v1)
* [GCP Service Networking](https://cloud.google.com/service-infrastructure/docs/service-networking/reference/rest?hl=en)
* [GCP Service Usage](https://cloud.google.com/service-usage/docs/overview?hl=en)
* [Google Cloud Resource Manager](https://cloud.google.com/resource-manager/docs)
  {% endtab %}

{% tab title="Azure" %}

* [Application Gateway](https://azure.microsoft.com/en-us/products/application-gateway)
* [Azure Blob Storage](https://azure.microsoft.com/en-us/products/storage/blobs)
* [Azure Cache for Redis](https://azure.microsoft.com/en-us/products/cache)
* [Azure Database for PostgreSQL](https://azure.microsoft.com/en-us/products/postgresql)
* [Azure Kubernetes Service](https://azure.microsoft.com/en-us/products/kubernetes-service) (AKS)
* [Azure Virtual Network](https://azure.microsoft.com/en-us/products/virtual-network)
* [Microsoft Entra](https://www.microsoft.com/en-ca/security/business/microsoft-entra)
  {% endtab %}
  {% endtabs %}

## Installation

The Terraform module can be installed using [terraform apply](https://developer.hashicorp.com/terraform/cli/commands/apply).

{% hint style="info" %}
We recommend using a [remote backend](https://developer.hashicorp.com/terraform/language/backend) to manage the Terraform state.
{% endhint %}

### Steps

The steps to install the Terraform module using the Terraform CLI are as follows:

{% tabs %}
{% tab title="AWS" %}

1. Create a DBNL folder and change to it.

```bash
mkdir dbnl
cd dbnl
```

2. Create a `variables.tf` file.

```hcl
variable "oidc_audience" {
  type        = string
  description = "OIDC audience."
}

variable "oidc_client_id" {
  type        = string
  description = "OIDC client id."
}

variable "oidc_issuer" {
  type        = string
  description = "OIDC issuer."
}

variable "oidc_scopes" {
  type        = string
  description = "OIDC scopes."
  default     = "openid profile email"
}

variable "domain" {
  description = "Domain to deploy to."
  type        = string
}

variable "dev_token_private_key_pem" {
  type        = string
  description = "Dev token private key PEM."
  sensitive   = true
}
```

3. Create a `main.tf` file.

```hcl
provider "aws" {
  # Configure AWS provider with target AWS account.
}

provider "kubernetes" {
  host                   = module.dbnl.cluster_endpoint
  cluster_ca_certificate = base64decode(module.dbnl.cluster_ca_cert)
  exec {
    api_version = "client.authentication.k8s.io/v1beta1"
    args        = ["eks", "get-token", "--cluster-name", module.dbnl.cluster_name]
    command     = "aws"
  }
}

provider "helm" {
  kubernetes {
    host                   = module.dbnl.cluster_endpoint
    cluster_ca_certificate = base64decode(module.dbnl.cluster_ca_cert)
    exec {
      api_version = "client.authentication.k8s.io/v1beta1"
      args        = ["eks", "get-token", "--cluster-name", module.dbnl.cluster_name]
      command     = "aws"
    }
  }
}

module "dbnl" {
  source = "dbnlAI/dbnl/aws"

  instance_size = "medium"
  
  oidc_audience  = var.oidc_audience
  oidc_client_id = var.oidc_client_id
  oidc_issuer    = var.oidc_issuer
  oidc_scopes    = var.oidc_scopes

  domain = var.domain
  
  dev_token_private_key = var.dev_token_private_key_pem
}
```

4. Create a `dbnl.tfvars` file.

```hcl
# For more details on OIDC options, see OIDC Authentication section.
oidc_audience  = "oidc.example.com"
oidc_client_id = "xxxxxxxx"
oidc_issuer    = "yyyyyyyy"
oidc_scopes    = "openid email profile"

domain = "dbnl.example.com"
```

5. Initialize the Terraform module.

```bash
terraform init
```

6. Apply the Terraform module.

```bash
terraform apply \
    -var-file="dbnl.tfvars" \
    -var="dev_token_private_key=${DBNL_DEV_TOKEN_PRIVATE_KEY}"
```

{% endtab %}

{% tab title="GCP" %}

1. Create a DBNL folder and change to it.

```bash
mkdir dbnl
cd dbnl
```

2. Create a `variables.tf` file.

```hcl
variable "oidc_audience" {
  type        = string
  description = "OIDC audience."
}

variable "oidc_client_id" {
  type        = string
  description = "OIDC client id."
}

variable "oidc_issuer" {
  type        = string
  description = "OIDC issuer."
}

variable "oidc_scopes" {
  type        = string
  description = "OIDC scopes."
  default     = "openid profile email"
}

variable "domain" {
  description = "Domain to deploy to."
  type        = string
}

variable "dev_token_private_key" {
  type        = string
  description = "Dev token private key PEM."
  sensitive   = true
}
```

3. Create a `main.tf` file.

```hcl
provider "google" {
  # Configure google provider with target Google project and region.
}

provider "kubernetes" {
  host                   = module.dbnl.cluster_endpoint
  cluster_ca_certificate = base64decode(module.dbnl.cluster_ca_cert)
  exec {
    api_version = "client.authentication.k8s.io/v1beta1"
    args        = []
    command     = "gke-gcloud-auth-plugin"
  }
}

provider "helm" {
  kubernetes {
    host                   = module.dbnl.cluster_endpoint
    cluster_ca_certificate = base64decode(module.dbnl.cluster_ca_cert)
    exec {
      api_version = "client.authentication.k8s.io/v1beta1"
      args        = []
      command     = "gke-gcloud-auth-plugin"
    }
  }
}

module "dbnl" {
  source = "dbnlAI/dbnl/gcp"

  instance_size = "medium"

  oidc_audience  = var.oidc_audience
  oidc_client_id = var.oidc_client_id
  oidc_issuer    = var.oidc_issuer
  oidc_scopes    = var.oidc_scopes

  domain = var.domain

  dev_token_private_key = var.dev_token_private_key
}
```

4. Create a `dbnl.tfvars` file.

```hcl
# For more details on OIDC options, see OIDC Authentication section.
oidc_audience  = "oidc.example.com"
oidc_client_id = "xxxxxxxx"
oidc_issuer    = "yyyyyyyy"
oidc_scopes    = "openid email profile"

domain = "dbnl.example.com"
```

5. Initialize the Terraform module.

```bash
terraform init
```

6. Apply the Terraform module.

```bash
terraform apply \
    -var-file="dbnl.tfvars" \
    -var="dev_token_private_key=${DBNL_DEV_TOKEN_PRIVATE_KEY}"
```

{% endtab %}

{% tab title="Azure" %}

1. Create a DBNL folder and change to it.

```bash
mkdir dbnl
cd dbnl
```

2. Create a `variables.tf` file.

```hcl
variable "oidc_audience" {
  type        = string
  description = "OIDC audience."
}

variable "oidc_client_id" {
  type        = string
  description = "OIDC client id."
}

variable "oidc_issuer" {
  type        = string
  description = "OIDC issuer."
}

variable "oidc_scopes" {
  type        = string
  description = "OIDC scopes."
  default     = "openid profile email"
}

variable "domain" {
  description = "Domain to deploy to."
  type        = string
}

variable "dev_token_private_key_pem" {
  type        = string
  description = "Dev token private key PEM."
  sensitive   = true
}
```

3. Create a `main.tf` file.

```hcl
provider "azurerm" {
  features {}
}

provider "kubernetes" {
  host                   = module.dbnl.cluster_host
  cluster_ca_certificate = base64decode(module.dbnl.cluster_ca_certificate)
  client_key             = base64decode(module.dbnl.cluster_client_key)
  client_certificate     = base64decode(module.dbnl.cluster_client_certificate)
}

provider "helm" {
  kubernetes {
    host                   = module.dbnl.cluster_host
    cluster_ca_certificate = base64decode(module.dbnl.cluster_ca_certificate)
    client_key             = base64decode(module.dbnl.cluster_client_key)
    client_certificate     = base64decode(module.dbnl.cluster_client_certificate)
  }
}

module "dbnl" {
  source = "dbnlAI/dbnl/azurerm"

  instance_size = "medium"  
  
  oidc_audience  = var.oidc_audience
  oidc_client_id = var.oidc_client_id
  oidc_issuer    = var.oidc_issuer
  oidc_scopes    = var.oidc_scopes

  domain = var.domain
  
  dev_token_private_key = var.dev_token_private_key_pem
}
```

4. Create a `dbnl.tfvars` file.

```hcl
# For more details on OIDC options, see OIDC Authentication section.
oidc_audience  = "oidc.example.com"
oidc_client_id = "xxxxxxxx"
oidc_issuer    = "yyyyyyyy"
oidc_scopes    = "openid email profile"

domain = "dbnl.example.com"
```

5. Initialize the Terraform module.

```bash
terraform init
```

6. Apply the Terraform module.

```bash
terraform apply \
    -var-file="dbnl.tfvars" \
    -var="dev_token_private_key=${DBNL_DEV_TOKEN_PRIVATE_KEY}"
```

{% endtab %}
{% endtabs %}

### Options

For more details on all the installation options, see the Terraform module README file and examples folder.
