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

# Deploy InfraAudit on Kubernetes With Provided Manifests

> Deploy InfraAudit on Kubernetes using the provided manifests. Covers secrets, ConfigMaps, deployments, ingress, and horizontal scaling.

InfraAudit ships Kubernetes manifests under `deployments/kubernetes/` in the main repository. This guide walks through a production-grade deployment: creating secrets, applying all manifests in order, verifying the rollout, and configuring ingress.

## Prerequisites

Before you start, make sure you have:

* A Kubernetes 1.24 or later cluster
* `kubectl` configured to target the cluster
* A Supabase project — see [Prerequisites](/self-hosting/prerequisites)
* A PostgreSQL instance (managed service like RDS, CloudSQL, or Azure Database — or use the in-cluster Postgres manifest)
* Redis (optional — the API degrades gracefully if unavailable)

## Manifest directory structure

```
deployments/kubernetes/
├── namespace.yaml
├── configmap.yaml
├── secret.yaml.example
├── postgres-deployment.yaml   # optional: in-cluster Postgres
├── redis-deployment.yaml
├── api-deployment.yaml
├── api-service.yaml
├── frontend-deployment.yaml
├── frontend-service.yaml
└── ingress.yaml
```

<Steps>
  <Step title="Create the namespace">
    Apply the namespace manifest to create the `infraudit` namespace:

    ```bash theme={null}
    kubectl apply -f deployments/kubernetes/namespace.yaml
    ```
  </Step>

  <Step title="Create the Secret">
    Copy the example secret file and fill in your values:

    ```bash theme={null}
    cp deployments/kubernetes/secret.yaml.example deployments/kubernetes/secret.yaml
    ```

    Edit `secret.yaml`:

    ```yaml theme={null}
    apiVersion: v1
    kind: Secret
    metadata:
      name: infraudit-secrets
      namespace: infraudit
    type: Opaque
    stringData:
      SUPABASE_URL: "https://xxxxxxxxxxxxxx.supabase.co"
      SUPABASE_JWT_SECRET: "your-jwt-secret"
      SUPABASE_ANON_KEY: "eyJhbGciOi..."
      SUPABASE_SERVICE_ROLE_KEY: "eyJhbGciOi..."
      DB_PASSWORD: "your-postgres-password"
      ENCRYPTION_KEY: "your-32-byte-hex-key"
      GEMINI_API_KEY: ""
    ```

    Apply the secret:

    ```bash theme={null}
    kubectl apply -f deployments/kubernetes/secret.yaml
    ```

    <Warning>
      Do not commit `secret.yaml` to source control. For production, use a secrets manager — AWS Secrets Manager, HashiCorp Vault, or the [External Secrets Operator](https://external-secrets.io/) to sync secrets into Kubernetes automatically.
    </Warning>
  </Step>

  <Step title="Apply the ConfigMap">
    Edit `configmap.yaml` to set your `FRONTEND_URL`, `SERVER_PORT`, and `ENVIRONMENT`, then apply:

    ```bash theme={null}
    kubectl apply -f deployments/kubernetes/configmap.yaml
    ```
  </Step>

  <Step title="Deploy Postgres and Redis">
    If you're connecting to an external database, skip the Postgres manifest. Otherwise, deploy both:

    ```bash theme={null}
    kubectl apply -f deployments/kubernetes/postgres-deployment.yaml
    kubectl apply -f deployments/kubernetes/redis-deployment.yaml
    ```

    Wait for both pods to become ready before proceeding:

    ```bash theme={null}
    kubectl rollout status deployment/infraudit-postgres -n infraudit
    kubectl rollout status deployment/infraudit-redis -n infraudit
    ```
  </Step>

  <Step title="Deploy the API">
    Apply the API deployment and service:

    ```bash theme={null}
    kubectl apply -f deployments/kubernetes/api-deployment.yaml
    kubectl apply -f deployments/kubernetes/api-service.yaml
    ```

    Check the rollout:

    ```bash theme={null}
    kubectl rollout status deployment/infraudit-api -n infraudit
    ```

    Verify the health endpoint from inside the cluster:

    ```bash theme={null}
    kubectl run test --rm -it --image=curlimages/curl --restart=Never -n infraudit \
      -- curl http://infraudit-api:8080/healthz
    # {"status":"ok"}
    ```
  </Step>

  <Step title="Deploy the frontend">
    ```bash theme={null}
    kubectl apply -f deployments/kubernetes/frontend-deployment.yaml
    kubectl apply -f deployments/kubernetes/frontend-service.yaml
    ```
  </Step>

  <Step title="Configure ingress">
    Edit `ingress.yaml` to set your hostname and TLS secret, then apply:

    ```bash theme={null}
    kubectl apply -f deployments/kubernetes/ingress.yaml
    ```

    The default ingress configuration assumes an nginx ingress controller and cert-manager for TLS. Adjust the annotations if you use Traefik or another ingress controller.
  </Step>
</Steps>

## Default resource limits

The manifests include conservative resource limits. Adjust them based on the number of resources you're scanning and how frequently you run scans:

| Container  | CPU request | CPU limit | Memory request | Memory limit |
| ---------- | ----------- | --------- | -------------- | ------------ |
| `api`      | 100m        | 500m      | 256Mi          | 1Gi          |
| `frontend` | 50m         | 200m      | 64Mi           | 256Mi        |
| `postgres` | 200m        | 1000m     | 512Mi          | 2Gi          |
| `redis`    | 50m         | 100m      | 64Mi           | 256Mi        |

## Horizontal scaling

The API is stateless — sessions are in Supabase and shared cache state is in Redis. You can scale the API horizontally at any time:

```bash theme={null}
kubectl scale deployment infraudit-api --replicas=3 -n infraudit
```

The frontend is also stateless and can be scaled the same way. The Postgres deployment is not designed for horizontal scaling — use a managed database service if you need high availability.

## Next steps

<CardGroup cols={2}>
  <Card title="Configuration reference" icon="sliders" href="/self-hosting/configuration">
    Review all environment variables and tune your deployment.
  </Card>

  <Card title="Upgrades" icon="arrow-up" href="/self-hosting/upgrades">
    Learn how to update image tags and run migrations safely.
  </Card>
</CardGroup>
