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

# Deployment

> Sign up for Cielara and deploy it into your own cloud account.

Cielara runs inside your own cloud account, so your data stays in infrastructure you own. Your 30-day trial starts as soon as you sign up, and the steps below take you from a new account to a running Cielara instance.

The deploy form is a five-step wizard: **Cloud**, **Target**, **Prepare**, **Infrastructure** and **Review**. This page follows it step by step. Names in bold are the labels you see in the form. The form itself shows only titles, fields and commands; the explanation behind each step lives here.

## Before You Start

You run two small Terraform configurations from your own machine: one that creates the identity Cielara deploys with, and one that creates the network Cielara deploys into. Both are required. You need:

| What | Why |
| - | - |
| Terraform 1.7 or later | Runs the prepare and network configurations. [Install Terraform](https://developer.hashicorp.com/terraform/install) |
| Your cloud's CLI, signed in as an IAM admin: a GCP project owner, an AWS IAM admin or an Azure subscription Owner | Terraform uses its credentials to create the identity Cielara deploys with and grant it roles. [gcloud](https://cloud.google.com/sdk/docs/install), [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html) or [Azure CLI](https://learn.microsoft.com/cli/azure/install-azure-cli) |
| A GCP project, AWS account or Azure subscription | Where Cielara runs |

`terraform version` and your CLI's version command (`gcloud version`, `aws --version`, `az version`) show whether you have them.

### Where the Files Go

The form names one folder per deployment, with a subfolder for each Terraform configuration. Each holds its own `main.tf` and Terraform state:

```text theme={null}
~/cielara/<deployment-name>/prepare/   the prepare configuration
~/cielara/<deployment-name>/network/   the network configuration
```

## Deployment Flow

**1. Sign Up for a Cielara Account**

Go to [console.cielara.ai/signup](https://console.cielara.ai/signup) and sign up. Enter your details and verify your email. Once your account is created you receive a 30-day trial license and access to the Cielara console.

If the console shows **Your license is being set up** after you sign in, your trial license is still being issued. This usually takes a few minutes.

**2. Open the Deploy Form**

Sign in to the Cielara console. A new account with no deployment opens the deploy form directly. You can also reach it from **Deployments** in the sidebar.

The footer names the one thing still blocking the current step, for example **Upload cielara-key.json to continue**, and **Continue** stays disabled until it is done. The steps along the top show where you are. Click a completed step to go back to it.

**3. Cloud**

Under **Which cloud are you deploying to?**, pick **Google Cloud**, **AWS** or **Azure**. Every later step is tailored to that cloud. The **Deployment guide** link beside the title opens this page. What you need for each cloud is listed under [Before You Start](#before-you-start).

**4. Target, Prepare and Infrastructure**

> [tab] GCP
>
> ### Target
>
> | Field | Description |
> | - | - |
> | **Project ID** | Your GCP project ID. Find it in the GCP console under **Project info**, or run `gcloud projects list`. |
> | **Deployment name** | A short lowercase name of up to 25 characters, for example `acme-inc`. Cielara names every resource it creates `cdl-<number>-<name>`, where the number is the deploy time. The name also names your folder, `~/cielara/<name>`. |
> | **Region** | The region Cielara runs in, for example `us-central1`. Choose the region closest to your team or where your data residency requirements apply. Cannot be changed after deployment. |
>
> ### Prepare Your GCP Project
>
> This step creates the service account Cielara deploys with. You need Terraform 1.7 or later and the `gcloud` CLI, signed in as a project owner.
>
> 1. **Sign in to your cloud.** Google expires these credentials on its own schedule, so repeat this before every apply.
>
>    ```bash macOS/Linux theme={null}
>    gcloud auth login && gcloud auth application-default login
>    ```
>
>    ```powershell Windows theme={null}
>    gcloud auth login; gcloud auth application-default login
>    ```
>
>    Then check that your project ID exists. The form fills in your **Project ID**.
>
>    ```bash theme={null}
>    gcloud projects describe <project-id>
>    ```
>
>    If it prints the project, the ID is right and your account can see it. An error such as `does not have permission to access projects instance` means the Project ID or the signed-in account is wrong. Fix it before you apply: Terraform fails the same way, only later.
> 2. **Make a folder for this deployment.**
>
>    ```bash macOS/Linux theme={null}
>    mkdir -p ~/cielara/<name>/prepare && cd ~/cielara/<name>/prepare
>    ```
>
>    ```powershell Windows theme={null}
>    New-Item -ItemType Directory -Force $HOME\cielara\<name>\prepare | Out-Null
>    cd $HOME\cielara\<name>\prepare
>    ```
> 3. **Download main.tf into the /prepare folder you created.** Click **Download main.tf**. The file is pre-filled with your project and region. Then move it into the folder:
>
>    ```bash macOS/Linux theme={null}
>    mv <download-folder>/main.tf ~/cielara/<name>/prepare/
>    ```
>
>    ```powershell Windows theme={null}
>    Move-Item <download-folder>\main.tf $HOME\cielara\<name>\prepare\
>    ```
> 4. **Apply.** The apply enables the required APIs, creates the service account with the minimum IAM roles, and writes `cielara-key.json`.
>
>    ```bash macOS/Linux theme={null}
>    cd ~/cielara/<name>/prepare && terraform init && terraform apply
>    ```
>
>    ```powershell Windows theme={null}
>    cd $HOME\cielara\<name>\prepare
>    terraform init
>    terraform apply
>    ```
>
>    By default Terraform keeps its state in this folder. This is not recommended: the state exists only on this machine, and it holds the service account's private key. Keep it in a GCS bucket you own instead. `main.tf` carries ready-made `backend` blocks: uncomment the one you want before `terraform init`. If you already applied with local state, run `terraform init -migrate-state` after uncommenting it.
> 5. **Upload the cielara-key.json.** It is in `~/cielara/<name>/prepare`. Drop it on **Drop cielara-key.json here**, or click **Browse**. Treat the file like a password and do not commit it to git.
>
> The key file also records where the Terraform state lives. Click **Enter manually** to see or change it:
>
> | Field | Description |
> | - | - |
> | **Terraform State Storage URL** | Where your prepare run keeps its state: `local`, or a bucket such as `gs://acme-inc-tfstate/cielara-prepare/gke`. Recorded with the deployment so a later update can find the state. |
>
> ### Infrastructure
>
> The network is required. **Continue** stays disabled, with **Upload cielara-network.json to continue** in the footer, until you upload the file from the steps below. Node pools, database and version have defaults you can leave alone.
>
> #### Network
>
> Cielara deploys into a network you own. The form gives you a pre-filled Terraform file for Cielara's [`cielara-network`](https://registry.terraform.io/modules/causal-dynamics-lab/cielara-network/google/latest) module. It creates a VPC, a regional subnet with pods and services ranges, private Google access, and Cloud NAT with a static egress IP.
>
> 1. **Make a folder for the network.** It sits next to the prepare folder, not inside it: the network is its own Terraform configuration with its own state.
>
>    ```bash macOS/Linux theme={null}
>    mkdir -p ~/cielara/<name>/network && cd ~/cielara/<name>/network
>    ```
>
>    ```powershell Windows theme={null}
>    New-Item -ItemType Directory -Force $HOME\cielara\<name>\network | Out-Null
>    cd $HOME\cielara\<name>\network
>    ```
> 2. **Download main.tf into the /network folder you created.** Click **Download main.tf**. The file is pre-filled with your project and region. Move it into the network folder:
>
>    ```bash macOS/Linux theme={null}
>    mv <download-folder>/main.tf ~/cielara/<name>/network/
>    ```
>
>    ```powershell Windows theme={null}
>    Move-Item <download-folder>\main.tf $HOME\cielara\<name>\network\
>    ```
>
>    If your browser saved it as `main (1).tf` because the prepare `main.tf` was still in the download folder, move that file instead.
> 3. **Apply it and write its output.**
>
>    ```bash macOS/Linux theme={null}
>    cd ~/cielara/<name>/network && terraform init && terraform apply && terraform output -raw handback > cielara-network.json
>    ```
>
>    ```powershell Windows theme={null}
>    cd $HOME\cielara\<name>\network
>    terraform init
>    terraform apply
>    terraform output -raw handback > cielara-network.json
>    ```
> 4. **Upload cielara-network.json.** It is in `~/cielara/<name>/network`. The form lists the values it read from the file, and **Review** shows them again.
>
> The upload is refused, with the reason, when the file:
>
> * is empty. The command ran before the apply finished, or the apply failed. Terraform printed why in your terminal
> * describes a network in a different project or region than the **Target** step
> * is missing a value, or has a value Cielara cannot use. Nothing from the file is kept
>
> **Already have a network made some other way?** Write the same JSON by hand and upload it:
>
> ```json theme={null}
> {
>   "project_id": "acme-inc-prod",
>   "region": "us-central1",
>   "vpc_self_link": "projects/acme-inc-prod/global/networks/acme-vpc",
>   "gke_subnet_self_link": "projects/acme-inc-prod/regions/us-central1/subnetworks/acme-subnet",
>   "pods_range_name": "pods",
>   "services_range_name": "services",
>   "nat_ip": "203.0.113.10"
> }
> ```
>
> The network must meet the same contract the module produces. Cielara checks it before the deploy starts:
>
> * A regional subnet in the deploy region and the deploy project. Shared VPC host and service projects are not supported
> * Two secondary ranges on that subnet, one for pods and one for services. The pods range needs a `/24` per node of free space
> * Private Google access enabled on the subnet
> * Working egress (Cloud NAT or equivalent) with a stable IP. `nat_ip` is required when the deployment uses Cielara's managed RabbitMQ, because the broker's firewall admits exactly that address
> * Address space that does not overlap `172.16.0.0/28` (the Kubernetes control plane range) or the Cloud SQL private services range, `10.96.0.0/16` by default
>
> A default VPC, such as the `default` network a new project gets, has no secondary ranges or Cloud NAT and does not meet this contract.
>
> #### Node Pools
>
> The defaults suit most deployments. The **Node pools** row shows the default pool's machine type and capacity, for example `n2-standard-8 · on-demand`. Click **Change** to pick another. Change a machine type only when the region lacks capacity for the default. Types that are too small for a pool are greyed out with the reason.
>
> | Field | Description |
> | - | - |
> | **Default pool** | Runs the core services. Below it, choose **On-demand** or **Spot**. Spot is up to 40% cheaper, but Google can reclaim spot nodes with 30 seconds notice. There is no on-demand fallback on GCP: if spot capacity runs out, pods wait until it returns. On-demand is recommended for production. |
> | **Agent pool** | Runs the analysis agents. Shown only when your deployment provisions a dedicated agent pool. A spot reclaim mid-run interrupts that agent run, and agent jobs are retried. |
>
> Recommended machine types by size of your codebase:
>
> | Scale | Source code repositories | Recommended machine type |
> | - | - | - |
> | Small to medium | Up to 300 | `n2-highmem-4` |
> | Large | 300+ | `n2-highmem-8` or `c3-highmem-8` |
>
> #### Database
>
> The **Database** row reads **Sized by Cielara**. Leave it to let Cielara size the managed Postgres instance, or pick a size from the list. Your cloud decides what is orderable in the region. You can change it after deployment from the deployment's Database tab.
>
> #### Version
>
> **Latest** deploys the latest release and is recommended. Choose **Pin** to pick a specific release from the history; pre-release versions are marked `pre`.

> [tab] AWS
>
> ### Target
>
> | Field | Description |
> | - | - |
> | **Deployment name** | A short lowercase name of up to 25 characters, for example `acme-inc`. Cielara names every resource it creates `cdl-<number>-<name>`, where the number is the deploy time. The name also names your folder, `~/cielara/<name>`. |
> | **Region** | The region Cielara runs in, for example `us-east-1`. Choose the region closest to your team or where your data residency requirements apply. Cannot be changed after deployment. |
>
> Your AWS account ID is not a form field. Cielara reads it from the role the prepare step creates.
>
> ### Prepare Your AWS Account
>
> This step creates the cross-account IAM role Cielara deploys with. No long-lived keys leave your account. You need Terraform 1.7 or later and the AWS CLI, signed in as an IAM admin with `AWS_REGION` set.
>
> The download is generated for your Cielara account, so take it from your own form rather than reusing a copy.
>
> 1. **Sign in to your cloud.**
>
>    ```bash theme={null}
>    aws sso login
>    ```
>
>    If you use static keys instead of SSO, run `aws configure`. Then check which account you are signed in to:
>
>    ```bash theme={null}
>    aws sts get-caller-identity
>    ```
>
>    It shows the account you are signed into. The apply prepares that account, so check it is the one Cielara should deploy into.
> 2. **Make a folder for this deployment.**
>
>    ```bash macOS/Linux theme={null}
>    mkdir -p ~/cielara/<name>/prepare && cd ~/cielara/<name>/prepare
>    ```
>
>    ```powershell Windows theme={null}
>    New-Item -ItemType Directory -Force $HOME\cielara\<name>\prepare | Out-Null
>    cd $HOME\cielara\<name>\prepare
>    ```
> 3. **Download main.tf into the /prepare folder you created.** Click **Download main.tf**. The file is pre-filled for your account and region. Then move it into the folder:
>
>    ```bash macOS/Linux theme={null}
>    mv <download-folder>/main.tf ~/cielara/<name>/prepare/
>    ```
>
>    ```powershell Windows theme={null}
>    Move-Item <download-folder>\main.tf $HOME\cielara\<name>\prepare\
>    ```
> 4. **Apply.** The apply creates the `cielara_eks_deployer` role, trusted only by Cielara's control plane and gated by your Cielara client ID, and writes `cielara-creds.json`.
>
>    ```bash macOS/Linux theme={null}
>    cd ~/cielara/<name>/prepare && terraform init && terraform apply
>    ```
>
>    ```powershell Windows theme={null}
>    cd $HOME\cielara\<name>\prepare
>    terraform init
>    terraform apply
>    ```
>
>    By default Terraform keeps its state in this folder. This is not recommended: the state exists only on this machine. Keep it in an S3 bucket you own instead. `main.tf` carries ready-made `backend` blocks: uncomment the one you want before `terraform init`. If you already applied with local state, run `terraform init -migrate-state` after uncommenting it.
> 5. **Upload the cielara-creds.json.** It is in `~/cielara/<name>/prepare`. Drop it on **Drop cielara-creds.json here**, or click **Browse**.
>
> The file fills the role and state location. Click **Enter manually** to see or change them:
>
> | Field | Description |
> | - | - |
> | **Role ARN** | The ARN of the deployer role, for example `arn:aws:iam::123456789012:role/cielara_eks_deployer`. The account ID in the ARN is the account Cielara deploys into. `terraform output -raw role_arn` prints it. |
> | **Terraform State Storage URL** | Where your prepare run keeps its state: `local`, or a bucket such as `s3://acme-inc-tfstate/cielara-prepare/eks/terraform.tfstate`. Recorded with the deployment so a later update can find the state. |
>
> ### Infrastructure
>
> The network is required. **Continue** stays disabled, with **Upload cielara-network.json to continue** in the footer, until you upload the file from the steps below. Node pools, database and version have defaults you can leave alone.
>
> #### Network
>
> Cielara deploys into a network you own. The form gives you a pre-filled Terraform file for Cielara's [`cielara-network`](https://registry.terraform.io/modules/causal-dynamics-lab/cielara-network/aws/latest) module. It creates a VPC with one private and one public subnet in each of two availability zones, and NAT.
>
> 1. **Make a folder for the network.** It sits next to the prepare folder, not inside it: the network is its own Terraform configuration with its own state.
>
>    ```bash macOS/Linux theme={null}
>    mkdir -p ~/cielara/<name>/network && cd ~/cielara/<name>/network
>    ```
>
>    ```powershell Windows theme={null}
>    New-Item -ItemType Directory -Force $HOME\cielara\<name>\network | Out-Null
>    cd $HOME\cielara\<name>\network
>    ```
> 2. **Download main.tf into the /network folder you created.** Click **Download main.tf**. The file is pre-filled with your region. Move it into the network folder:
>
>    ```bash macOS/Linux theme={null}
>    mv <download-folder>/main.tf ~/cielara/<name>/network/
>    ```
>
>    ```powershell Windows theme={null}
>    Move-Item <download-folder>\main.tf $HOME\cielara\<name>\network\
>    ```
>
>    If your browser saved it as `main (1).tf` because the prepare `main.tf` was still in the download folder, move that file instead.
> 3. **Apply it and write its output.**
>
>    ```bash macOS/Linux theme={null}
>    cd ~/cielara/<name>/network && terraform init && terraform apply && terraform output -raw handback > cielara-network.json
>    ```
>
>    ```powershell Windows theme={null}
>    cd $HOME\cielara\<name>\network
>    terraform init
>    terraform apply
>    terraform output -raw handback > cielara-network.json
>    ```
> 4. **Upload cielara-network.json.** It is in `~/cielara/<name>/network`. The form lists the values it read from the file, and **Review** shows them again.
>
> The upload is refused, with the reason, when the file:
>
> * is empty. The command ran before the apply finished, or the apply failed. Terraform printed why in your terminal
> * describes a network in a different region than the **Target** step
> * does not have exactly two private and two public subnets, one of each per availability zone
> * is missing a value, or has a value Cielara cannot use. Nothing from the file is kept
>
> **Already have a network made some other way?** Write the same JSON by hand and upload it:
>
> ```json theme={null}
> {
>   "region": "us-east-1",
>   "vpc_id": "vpc-0abc123def4567890",
>   "private_subnet_ids": ["subnet-0aaa1111bbbb2222c", "subnet-0ddd3333eeee4444f"],
>   "public_subnet_ids": ["subnet-0555666677778888a", "subnet-0999aaaabbbbccccd"]
> }
> ```
>
> The network must meet the same contract the module produces:
>
> * The VPC is in the selected region, with DNS hostnames and DNS support enabled
> * Two private subnets for the cluster nodes, in different availability zones, tagged `kubernetes.io/role/internal-elb=1`
> * Two public subnets for load balancers, in the same two availability zones, tagged `kubernetes.io/role/elb=1`
>
> #### Node Pools
>
> The defaults suit most deployments. The **Node pools** row shows the default pool's instance type and capacity. Click **Change** to pick another. Change an instance type only when the region lacks capacity for the default. Types that are too small for a pool are greyed out with the reason.
>
> | Field | Description |
> | - | - |
> | **Default pool** | Runs the core services. Below it, choose **On-demand** or **Spot**. The default is Spot, which is up to 40% cheaper. When EC2 has no spot capacity for the type you pick, an on-demand fallback pool grows to cover it, so a shortage causes no outage. The choice applies to the default and agent pools together. |
> | **Agent pool** | Runs the analysis agents. Memory-optimized and kept in a single availability zone because its volumes are zonal. |
>
> Recommended instance types by size of your codebase:
>
> | Scale | Source code repositories | Recommended instance type |
> | - | - | - |
> | Small to medium | Up to 300 | `r6i.xlarge` |
> | Large | 300+ | `r6i.2xlarge` or `r7i.2xlarge` |
>
> #### Database
>
> The **Database** row reads **Sized by Cielara**. Leave it to let Cielara size the managed Postgres instance, or pick a size from the list. Your cloud decides what is orderable in the region. You can change it after deployment from the deployment's Database tab.
>
> #### Version
>
> **Latest** deploys the latest release and is recommended. Choose **Pin** to pick a specific release from the history; pre-release versions are marked `pre`.

> [tab] Azure
>
> ### Target
>
> | Field | Description |
> | - | - |
> | **Subscription ID** | Your Azure subscription ID. Find it in the Azure portal under **Subscriptions**, or run `az account show --query id -o tsv`. |
> | **Deployment name** | A short lowercase name of up to 25 characters, for example `acme-inc`. Cielara names every resource it creates `cdl-<number>-<name>`, where the number is the deploy time. The name also names your folder, `~/cielara/<name>`. |
> | **Region** | The region Cielara runs in, for example `eastus2`. Choose the region closest to your team or where your data residency requirements apply. Cannot be changed after deployment. |
>
> ### Prepare Your Azure Subscription
>
> This step creates the service principal Cielara deploys with. You need Terraform 1.7 or later and the Azure CLI, signed in as a subscription Owner, or an identity that can create service principals and subscription-scoped role assignments.
>
> The download is generated for your Cielara account, so take it from your own form rather than reusing a copy.
>
> 1. **Sign in to your cloud.** Use `az login --use-device-code` instead if no browser is available.
>
>    ```bash theme={null}
>    az login
>    ```
>
>    Then check that your subscription ID exists. The form fills in your **Subscription ID**.
>
>    ```bash theme={null}
>    az account show --subscription <subscription-id>
>    ```
>
>    If it prints the subscription, the ID is right and your account can see it. An error means the Subscription ID or the signed-in account is wrong. Fix it before you apply.
> 2. **Make a folder for this deployment.**
>
>    ```bash macOS/Linux theme={null}
>    mkdir -p ~/cielara/<name>/prepare && cd ~/cielara/<name>/prepare
>    ```
>
>    ```powershell Windows theme={null}
>    New-Item -ItemType Directory -Force $HOME\cielara\<name>\prepare | Out-Null
>    cd $HOME\cielara\<name>\prepare
>    ```
> 3. **Download main.tf into the /prepare folder you created.** Click **Download main.tf**. The file is pre-filled with your subscription and region. Then move it into the folder:
>
>    ```bash macOS/Linux theme={null}
>    mv <download-folder>/main.tf ~/cielara/<name>/prepare/
>    ```
>
>    ```powershell Windows theme={null}
>    Move-Item <download-folder>\main.tf $HOME\cielara\<name>\prepare\
>    ```
> 4. **Apply.** The apply creates the `cielara_aks_deployer` service principal scoped to your subscription and writes `cielara-creds.json`.
>
>    ```bash macOS/Linux theme={null}
>    cd ~/cielara/<name>/prepare && terraform init && terraform apply
>    ```
>
>    ```powershell Windows theme={null}
>    cd $HOME\cielara\<name>\prepare
>    terraform init
>    terraform apply
>    ```
>
>    By default Terraform keeps its state in this folder. This is not recommended: the state exists only on this machine, and it holds the client secret. Keep it in an Azure Storage container you own instead. `main.tf` carries ready-made `backend` blocks: uncomment the one you want before `terraform init`. If you already applied with local state, run `terraform init -migrate-state` after uncommenting it.
> 5. **Upload the cielara-creds.json.** It is in `~/cielara/<name>/prepare`. Drop it on **Drop cielara-creds.json here**, or click **Browse**. The file holds the client secret, so treat it like a password and do not commit it to git.
>
> The file fills the service principal and state location. Click **Enter manually** to see or change them:
>
> | Field | Description |
> | - | - |
> | **Tenant ID** | Your Microsoft Entra ID tenant. Find it in the Azure portal under **Microsoft Entra ID > Overview**, or run `az account show --query tenantId -o tsv`. |
> | **Client ID** | The application (client) ID of the `cielara_aks_deployer` service principal. |
> | **Client secret** | The service principal's secret. Stored encrypted. |
> | **Terraform State Storage URL** | Where your prepare run keeps its state: `local`, or a container such as `https://acmeinctfstate.blob.core.windows.net/tfstate/cielara-prepare-aks.tfstate`. Recorded with the deployment so a later update can find the state. |
>
> ### Infrastructure
>
> The network is required. **Continue** stays disabled, with **Upload cielara-network.json to continue** in the footer, until you upload the file from the steps below. Node pools, database and version have defaults you can leave alone.
>
> #### Network
>
> Cielara deploys into a network you own. The form gives you a pre-filled Terraform file for Cielara's [`cielara-network`](https://registry.terraform.io/modules/causal-dynamics-lab/cielara-network/azurerm/latest) module. It creates a VNet with the subnets Cielara needs and a NAT gateway, inside a resource group you already have.
>
> 1. **Make a folder for the network.** It sits next to the prepare folder, not inside it: the network is its own Terraform configuration with its own state.
>
>    ```bash macOS/Linux theme={null}
>    mkdir -p ~/cielara/<name>/network && cd ~/cielara/<name>/network
>    ```
>
>    ```powershell Windows theme={null}
>    New-Item -ItemType Directory -Force $HOME\cielara\<name>\network | Out-Null
>    cd $HOME\cielara\<name>\network
>    ```
> 2. **Download main.tf into the /network folder you created.** First enter the **Existing resource group** the network is created in. It must already exist, in the region you chose: the module never creates one. Then click **Download main.tf** and move the file into the network folder:
>
>    ```bash macOS/Linux theme={null}
>    mv <download-folder>/main.tf ~/cielara/<name>/network/
>    ```
>
>    ```powershell Windows theme={null}
>    Move-Item <download-folder>\main.tf $HOME\cielara\<name>\network\
>    ```
>
>    If your browser saved it as `main (1).tf` because the prepare `main.tf` was still in the download folder, move that file instead.
> 3. **Apply it and write its output.**
>
>    ```bash macOS/Linux theme={null}
>    cd ~/cielara/<name>/network && terraform init && terraform apply && terraform output -raw handback > cielara-network.json
>    ```
>
>    ```powershell Windows theme={null}
>    cd $HOME\cielara\<name>\network
>    terraform init
>    terraform apply
>    terraform output -raw handback > cielara-network.json
>    ```
> 4. **Upload cielara-network.json.** It is in `~/cielara/<name>/network`. The form lists the values it read from the file, and **Review** shows them again.
>
> The upload is refused, with the reason, when the file:
>
> * is empty. The command ran before the apply finished, or the apply failed. Terraform printed why in your terminal
> * describes a network in a different region than the **Target** step
> * is missing a value, or has a value Cielara cannot use. Nothing from the file is kept
>
> **Already have a network made some other way?** Write the same JSON by hand and upload it:
>
> ```json theme={null}
> {
>   "resource_group_name": "acme-inc-network",
>   "location": "eastus2",
>   "vnet_name": "acme-vnet",
>   "system_subnet_name": "system",
>   "user_subnet_name": "user",
>   "appgw_subnet_name": "appgw",
>   "postgres_subnet_name": "postgres",
>   "nat_gateway_name": "acme-nat"
> }
> ```
>
> | Key | Description |
> | - | - |
> | `resource_group_name` | The resource group that holds the VNet, subnets and NAT gateway. Must be in the selected region. |
> | `vnet_name` | The existing virtual network. |
> | `system_subnet_name` | The subnet for the system node pool. |
> | `user_subnet_name` | The subnet for the user node pool. |
> | `appgw_subnet_name` | The subnet dedicated to the Application Gateway that fronts Cielara. |
> | `postgres_subnet_name` | The subnet delegated to Azure Database for PostgreSQL. |
> | `nat_gateway_name` | The NAT gateway attached to the node subnets. |
>
> #### Node Pools
>
> The defaults suit most deployments. The **Node pools** row shows the default pool's VM size. Click **Change** to pick another. Change a VM size only when the region or subscription lacks quota for the default. Sizes that are too small for a pool are greyed out with the reason. After deployment, changing a pool's size rotates its nodes. All Azure pools run on regular priority.
>
> | Field | Description |
> | - | - |
> | **Default pool** | Runs the core services. |
> | **On-demand pool** | An always-on mirror of the default pool that bounds cost. |
> | **Agent-memory pool** | Runs the analysis agents. Memory-optimized and scales from zero. |
>
> Recommended VM sizes by size of your codebase:
>
> | Scale | Source code repositories | Recommended VM size |
> | - | - | - |
> | Small to medium | Up to 300 | `Standard_E4s_v5` |
> | Large | 300+ | `Standard_E8s_v5` or `Standard_E16s_v5` |
>
> #### Database
>
> The **Database** row reads **Sized by Cielara**. Leave it to let Cielara size the managed Postgres instance, or pick a size from the list. Your cloud decides what is orderable in the region. You can change it after deployment from the deployment's Database tab.
>
> #### Version
>
> **Latest** deploys the latest release and is recommended. Choose **Pin** to pick a specific release from the history; pre-release versions are marked `pre`.

Leave node pools, database and version on their defaults and the button reads **Continue with defaults**.

**5. Review and Deploy**

**Review and deploy** lists everything before anything is created: the target, including the resource prefix every resource is named with; the credentials; the network values from `cielara-network.json`; and the node pools, database and version. **What gets created** lists the resources Cielara adds in your account. Click **Edit** on any group to go back to its step. The region and name cannot be changed after deployment.

Click **Deploy Cielara**. The footer shows how long a deployment usually takes. Cielara creates the infrastructure and installs itself. No manual steps are required.

**Deployment started** confirms the deployment, the cloud and the region. Click **View deployment** to follow its progress, or **Start another**.

If the deploy is refused with `client already has a deployment ... destroy it before creating another`, your account already has a Cielara deployment. Each account runs one at a time: destroy the existing deployment first, then deploy again.

**6. Verify**

When the status reaches **Deployment complete**, the **Deployments** page shows your Cielara URL. Open it, sign in with the invitation sent to your email, and continue with the [Quickstart](https://docs.cielara.ai/quickstart.md).

If the status reaches **Deployment failed**, expand the deployment to read the message. Common causes are a missing permission on the prepare role, a region without capacity for the chosen machine type, or a network that does not meet the contract above. Fix the cause and click **Retry**.

## Terraform Module Reference

The prepare `main.tf` you download pins a release of Cielara's prepare module for your cloud. The form links to the exact version it pinned under **Module docs**. The full module documentation is on the Terraform Registry:

| Cloud | Module |
| - | - |
| GCP | [cielara-prepare-gke](https://registry.terraform.io/modules/causal-dynamics-lab/cielara-prepare-gke/google/latest) |
| AWS | [cielara-prepare-eks](https://registry.terraform.io/modules/causal-dynamics-lab/cielara-prepare-eks/aws/latest) |
| Azure | [cielara-prepare-aks](https://registry.terraform.io/modules/causal-dynamics-lab/cielara-prepare-aks/azurerm/latest) |

The network `main.tf` pins the same release of Cielara's network module. It also re-exports the module's `handback` output, which is what `terraform output -raw handback` reads. A `main.tf` you write yourself needs the same block, or the command writes an empty file:

```hcl theme={null}
output "handback" {
  value = module.cielara_network.handback
}
```

| Cloud | Module |
| - | - |
| GCP | [cielara-network/google](https://registry.terraform.io/modules/causal-dynamics-lab/cielara-network/google/latest) |
| AWS | [cielara-network/aws](https://registry.terraform.io/modules/causal-dynamics-lab/cielara-network/aws/latest) |
| Azure | [cielara-network/azurerm](https://registry.terraform.io/modules/causal-dynamics-lab/cielara-network/azurerm/latest) |


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.