# Workdir Provisioning

`provision.workdir` creates an isolated working directory for each component instance under `.workdir/<componentType>/<stack>-<componentName>-<hash>/`. The component source is staged into this directory and all toolchain commands execute there, enabling concurrent execution and just-in-time source provisioning without `.terraform/`, lockfile, or generated-varfile collisions.

> ⚠️ Experimental

## Schema

- **`provision.workdir.enabled`**

  Create an isolated working directory for each component instance.
  - **Type:** `boolean`
  - **Default:** `false`
  - **Applies to:** Terraform components, plus Helmfile, Packer, Helm, and Kubernetes components that declare a top-level `source`

## Configuration

Terraform supports workdir provisioning for local components and components that declare a top-level `source`. Helmfile, Packer, Helm, and Kubernetes require a top-level `source`; enabling workdir provisioning alone does not isolate their local component directories. For components with a `source`, a `metadata.working_directory` or `settings.working_directory` override takes precedence over the isolated workdir.

Enable workdir provisioning for a local Terraform component:

**File:** `stacks/catalog/_defaults.yaml`

```yaml
components:
  terraform:
    vpc:
      provision:
        workdir:
          enabled: true
      vars:
        cidr_block: "10.0.0.0/16"
```

## Directory Layout

When workdir provisioning is enabled, Atmos creates a per-component-instance directory under `.workdir/` and runs all toolchain commands there. Each instance gets its own `.terraform/`, varfiles, and state cache. The directory name ends with a short hash suffix (derived from the stack and component name) that keeps two component instances from colliding even when their `<stack>-<componentName>` prefixes happen to look the same.

```
.workdir/
├── terraform/
│   └── prod-ue1-vpc-b52c4d0a/        # <stack>-<componentName>-<hash>
│       ├── .terraform/
│       ├── .atmos/metadata.json
│       └── ... (component source)
└── helmfile/
    └── prod-ue1-nginx-27ff63ad/
        └── ...
```

> **Note**
>
> The `.workdir/` directory is created at runtime and should be added to `.gitignore`. It is not used by `atmos describe affected` for change detection — that command tracks the source files in `components/<type>/<name>/`, not the runtime workdir.

## Toolchain-Level Defaults

Terraform, Helm, and Kubernetes support toolchain-level provisioning defaults. Helm and Kubernetes components must declare a top-level `source` and have no working-directory override to use an isolated workdir. Helmfile and Packer require component-level configuration.

**File:** `stacks/orgs/acme/plat/dev/_defaults.yaml`

```yaml
terraform:
  provision:
    workdir:
      enabled: true   # Default for Terraform components in this stack

helm:
  provision:
    workdir:
      enabled: true   # Applies to Helm components with source and no working-directory override
```

## Component-Level Overrides

Opt a single component out of a toolchain or global default by setting `enabled: false`:

**File:** `stacks/orgs/acme/plat/dev/us-east-1.yaml`

```yaml
components:
  terraform:
    legacy-vpc:
      provision:
        workdir:
          enabled: false   # Run in the original component directory
      vars:
        # ...
```

## Global Defaults

To apply a workdir default across every stack, declare `terraform.provision` (and
`helm.provision` or `kubernetes.provision`) in a base stack manifest that all your stacks import - for example a
`_defaults.yaml` or a catalog mixin. This is the same place you set global `vars`, `metadata`, and
`secrets`, and it cascades to components of those toolchains through normal stack inheritance.
The source and working-directory restrictions above still apply. Component-level
`provision.workdir` overrides the inherited default.

**File:** `stacks/mixins/provision-workdir.yaml`

```yaml
terraform:
  provision:
    workdir:
      enabled: true       # Default for every Terraform component that imports this mixin
      ttl: "7d"           # Documents the intended cleanup window for unused workdirs

helm:
  provision:
    workdir:
      enabled: true       # Applies to Helm components with source and no working-directory override
```

- **`provision.workdir.enabled`**
  Whether components run inside an isolated workdir. Set it at the toolchain section of a shared stack manifest for a global default; component-level 
  `provision.workdir.enabled`
   still overrides it.
- **`provision.workdir.ttl`**
  Time-to-live for workdirs (e.g., 
  `"7d"`
  , 
  `"24h"`
  , 
  `"weekly"`
  ). Workdirs not accessed within this duration become candidates for cleanup by 
  [`atmos terraform workdir clean --expired`](/cli/commands/terraform/workdir)
  .

Workdir provisioning is component configuration, so its global default belongs in the stack
configuration alongside `vars`, `metadata`, and `secrets` - there is no `settings.provision.workdir`
block in `atmos.yaml`.

## Managing Workdirs

Use the [`atmos terraform workdir`](/cli/commands/terraform/workdir) commands to inspect and clean up workdirs:

| Command | Purpose |
|---|---|
| `atmos terraform workdir list` | List all workdirs |
| `atmos terraform workdir show <component> -s <stack>` | Show details for a specific workdir |
| `atmos terraform workdir clean --expired --ttl=7d` | Remove workdirs not accessed within the TTL |
| `atmos terraform workdir clean --all` | Remove every workdir (forces re-provisioning on next run) |

## Related

- [Backend Provisioning](/stacks/components/provision/backend) — The other half of the `provision:` block
- [`atmos terraform workdir`](/cli/commands/terraform/workdir) — CLI commands for managing workdirs
- [Terraform CLI Configuration](/cli/configuration/components/terraform) — `auto_provision_workdir_for_outputs` and other global Terraform settings
