> For the complete documentation index, see [llms.txt](https://docs.konvu.com/konvu/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.konvu.com/konvu/get-started/connect-your-environment/source-code/self-hosted-analysis/setting-up-infrastructure.md).

# Setting Up Infrastructure

Provision AWS EKS infrastructure using Terraform/OpenTofu. Skip this if you have an existing Kubernetes cluster.

{% hint style="info" %}
**AWS-Specific**: This guide provisions a complete AWS EKS cluster with Terraform. If you already have a Kubernetes cluster (AWS, GCP, Azure, on-premises, etc.), skip to [Installing the Broker and Controller](/konvu/get-started/connect-your-environment/source-code/self-hosted-analysis/installing-the-broker-and-controller.md).
{% endhint %}

## **Step 1: Store Your Credentials**

Create secrets in AWS Secrets Manager. These will be automatically synchronized to your Kubernetes cluster:

```bash
export AWS_REGION=<YOUR_AWS_REGION>  # e.g., us-east-1, us-west-2, eu-west-1

# Konvu company token (provided by Konvu)
aws secretsmanager create-secret \
  --name production-konvu-company-token \
  --secret-string "your-company-token" \
  --region $AWS_REGION

# GitHub App credentials (JSON format with your GitHub App details)
aws secretsmanager create-secret \
  --name production-konvu-github-app \
  --secret-string '{
    "appId": "123456",
    "installationId": "12345678",
    "privateKey": "-----BEGIN RSA PRIVATE KEY-----\nYour private key here\n-----END RSA PRIVATE KEY-----"
  }' \
  --region $AWS_REGION

# Your OpenAI API key (from your OpenAI account)
aws secretsmanager create-secret \
  --name production-konvu-openai-key \
  --secret-string "sk-your_openai_key" \
  --region $AWS_REGION
```

**Note**: The GitHub App credentials must be in JSON format with all three fields: `appId`, `installationId`, and `privateKey`.

## **Step 2: Initialize Your Terraform Workspace**

Create a directory for your Konvu infrastructure:

```bash
mkdir konvu-infrastructure && cd konvu-infrastructure
```

Create a `backend.tf` file to store Terraform state remotely:

```hcl
terraform {
  backend "s3" {
    bucket         = "your-company-terraform-state"
    key            = "konvu/terraform.tfstate"
    region         = "<YOUR_AWS_REGION>"
    dynamodb_table = "terraform-locks"
    encrypt        = true
  }
}
```

**First time setup?** Create the S3 bucket and DynamoDB table:

```bash
aws s3api create-bucket \
  --bucket your-company-terraform-state \
  --region <YOUR_AWS_REGION> \
  --create-bucket-configuration LocationConstraint=<YOUR_AWS_REGION>

aws s3api put-bucket-versioning \
  --bucket your-company-terraform-state \
  --versioning-configuration Status=Enabled

aws dynamodb create-table \
  --table-name terraform-locks \
  --attribute-definitions AttributeName=LockID,AttributeType=S \
  --key-schema AttributeName=LockID,KeyType=HASH \
  --billing-mode PAY_PER_REQUEST \
  --region <YOUR_AWS_REGION>
```

## **Step 3: Configure Your Infrastructure**

Create a `main.tf` file with your infrastructure definition using the public Konvu Terraform module from GitHub.

```hcl
terraform {
  required_version = "~> 1.9"

  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.80"
    }
    kubernetes = {
      source  = "hashicorp/kubernetes"
      version = "~> 2.35"
    }
    helm = {
      source  = "hashicorp/helm"
      version = "~> 2.17"
    }
  }
}

provider "aws" {
  region = var.aws_region
}

provider "aws" {
  alias  = "us-east-1"
  region = "us-east-1"
}

provider "kubernetes" {
  host                   = try(module.konvu_infrastructure.cluster_endpoint, "")
  cluster_ca_certificate = try(base64decode(module.konvu_infrastructure.cluster_certificate_authority_data), "")
  token                  = try(data.aws_eks_cluster_auth.cluster.token, "")
}

provider "helm" {
  kubernetes {
    host                   = try(module.konvu_infrastructure.cluster_endpoint, "")
    cluster_ca_certificate = try(base64decode(module.konvu_infrastructure.cluster_certificate_authority_data), "")
    token                  = try(data.aws_eks_cluster_auth.cluster.token, "")
  }
}

data "aws_eks_cluster_auth" "cluster" {
  name = var.cluster_name
}

module "konvu_infrastructure" {
  source = "git::https://github.com/KonvuTeam/terraform-aws-konvu-onprem.git?ref=v2.0.6"

  providers = {
    aws           = aws
    aws.us-east-1 = aws.us-east-1
    kubernetes    = kubernetes
    helm          = helm
  }

  aws_region   = var.aws_region
  cluster_name = var.cluster_name

  cluster_admin_role_arns = var.cluster_admin_role_arns

  deploy_kubernetes_resources = var.deploy_kubernetes_resources
  deploy_kubernetes_manifests = var.deploy_kubernetes_manifests

  vpc_cidr           = var.vpc_cidr
  availability_zones = var.availability_zones

  company_token_secret_name            = var.company_token_secret_name
  github_app_credentials_secret_name   = var.github_app_credentials_secret_name
  openai_key_secret_name              = var.openai_key_secret_name

  system_node_instance_type = var.system_node_instance_type
  system_node_count         = var.system_node_count

  tags                  = var.tags
}
```

Create supporting files: `variables.tf`, `outputs.tf`, and `terraform.tfvars`. See the [complete example](https://docs.konvu.com/konvu/reference/terraform) for full file contents.

Your `terraform.tfvars` should look similar to this:

```hcl
aws_region   = "<YOUR_AWS_REGION>"  # e.g., us-east-1, us-west-2, eu-west-1
cluster_name = "konvu-production"

cluster_admin_role_arns = [
  "arn:aws:iam::YOUR_ACCOUNT_ID:role/YourAdminRole",
]

deploy_kubernetes_resources = false
deploy_kubernetes_manifests = false

company_token_secret_name            = "production-konvu-company-token"
github_app_credentials_secret_name   = "production-konvu-github-app"
openai_key_secret_name              = "production-konvu-openai-key"

system_node_instance_type = "t3.small"   # Initial nodes for system components
system_node_count         = 2            # Karpenter will manage additional workload nodes

tags = {
  Environment = "production"
  ManagedBy   = "terraform"
  Purpose     = "konvu-analysis"
}
```

## **Step 4: Initialize Your Workspace**

Initialize Terraform to download the module and providers:

```bash
terraform init
```

## **Step 5: Deploy in Stages**

The infrastructure deploys in three stages to ensure dependencies resolve correctly.

### **Stage 1: Core Infrastructure (\~15 minutes)**

This stage creates your VPC, EKS cluster (Kubernetes v1.34), IAM roles, and initial node group.

```bash
terraform plan -out=stage1.tfplan
terraform apply stage1.tfplan
```

Verify the cluster is ready:

```bash
aws eks describe-cluster \
  --name konvu-production \
  --region $AWS_REGION \
  --query 'cluster.status'
# Expected: "ACTIVE"

aws eks update-kubeconfig --name konvu-production --region $AWS_REGION
kubectl get nodes
# Should show 2+ nodes in Ready state
```

### **Stage 2: Kubernetes Operators (\~2 minutes)**

This stage deploys Karpenter (v1.6.6) for intelligent node autoscaling and External Secrets Operator (v0.20.4) for secrets management.

Update `terraform.tfvars`:

```hcl
deploy_kubernetes_resources = true  # Changed
deploy_kubernetes_manifests = false
```

Apply the changes:

```bash
terraform plan -out=stage2.tfplan
terraform apply stage2.tfplan
```

Verify operators are running:

```bash
kubectl get pods -n kube-system -l app.kubernetes.io/name=karpenter
# Should show 2 pods Running

kubectl get pods -n konvu-controller -l app.kubernetes.io/name=external-secrets
# Should show 3 pods Running

helm list -A
# Should show: karpenter, external-secrets
```

**Troubleshooting**: If you encounter an `aws-auth` ConfigMap conflict, import it first:

```bash
terraform import 'module.konvu_infrastructure.kubernetes_config_map_v1.aws_auth[0]' kube-system/aws-auth
terraform apply stage2.tfplan
```

### **Stage 3: Operator Configuration (\~1 minute)**

This stage configures the operators with Konvu-specific resources: SecretStore connections, ExternalSecret definitions, and Karpenter provisioning policies.

Update `terraform.tfvars`:

```hcl
deploy_kubernetes_resources = true
deploy_kubernetes_manifests = true  # Changed
```

Apply:

```bash
terraform plan -out=stage3.tfplan
terraform apply stage3.tfplan
```

Verify secrets are synced from AWS Secrets Manager:

```bash
# Check controller secrets
kubectl get externalsecrets -n konvu-controller
# All should show STATUS: SecretSynced

kubectl get secrets -n konvu-controller
# Should show: konvu-company-token, konvu-ai-credentials

# Check broker secrets
kubectl get externalsecrets -n konvu-broker
# All should show STATUS: SecretSynced

kubectl get secrets -n konvu-broker
# Should show: konvu-company-token, konvu-git-credentials
```

Your infrastructure is now ready. Continue to Installing the Applications.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.konvu.com/konvu/get-started/connect-your-environment/source-code/self-hosted-analysis/setting-up-infrastructure.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
