# Manage Impreza resources with Terraform

Source: https://docs.imprezahost.com/terraform-provider.html

The Impreza provider manages Impreza Host resources through the REST API from
Terraform or OpenTofu: catalog app deployments, DNS records of registered
domains, project and environment variable groups, and onion services of
running apps. This page covers version 0.4.0, the first public release. The
source and the per-resource schema reference are in
[github.com/imprezahost/terraform-provider-impreza](https://github.com/imprezahost/terraform-provider-impreza).

## Before you start

- Terraform or OpenTofu. Write-only variable-group secrets need Terraform
  1.11 or later (OpenTofu 1.11 or later).
- An API key with its secret, created in the client area. See the
  [REST API reference](/api.html) for how the credential authorizes requests.
- The scope you want: the provider reads and writes applications and DNS, not
  billing. Orders, payments, domain registration and VPS purchases stay in
  the client area.

## Install the provider

Declare the provider in your configuration. The source address is
`imprezahost/impreza` on both the Terraform Registry and the OpenTofu Registry:

```hcl
terraform {
  required_providers {
    impreza = {
      source  = "imprezahost/impreza"
      version = "0.4.0"
    }
  }
}
```

Version availability on each registry follows that registry's own listing. If
the version you pin is not listed yet, or you prefer to pin a binary you
verified yourself, install the release archive from
[the GitHub releases](https://github.com/imprezahost/terraform-provider-impreza/releases)
through a filesystem mirror. Put the following block in the CLI configuration
file (`.terraformrc` on Unix or `terraform.rc` in the Windows application-data
directory), not in a project `.tf` file:

```hcl
provider_installation {
  filesystem_mirror {
    path    = "/usr/local/share/terraform/impreza"
    include = ["registry.terraform.io/imprezahost/impreza", "registry.opentofu.org/imprezahost/impreza"]
  }
  direct {
    exclude = ["registry.terraform.io/imprezahost/impreza", "registry.opentofu.org/imprezahost/impreza"]
  }
}
```

Verify the archive before you trust it; see [Verify a release](#verify) below.
Extract the binary for your operating system and architecture under the mirror
root at `registry.terraform.io/imprezahost/impreza/0.4.0/TARGET/` (for example,
`TARGET` is `linux_amd64`). For OpenTofu, use
`registry.opentofu.org/imprezahost/impreza/0.4.0/TARGET/` instead. Keep the
executable filename from the archive. See the
[Terraform CLI mirror layout](https://developer.hashicorp.com/terraform/cli/config/config-file#filesystem_mirror)
for the packed and unpacked layouts.

## Authenticate

The provider reads `IMPREZA_API_KEY` and `IMPREZA_API_SECRET` from the
environment. Prefer the environment: explicit credentials in the provider
block are sensitive but can be carried in a saved plan file.

```hcl
provider "impreza" {
  # IMPREZA_API_KEY / IMPREZA_API_SECRET come from the environment.
  # endpoint defaults to https://api.imprezahost.com
}
```

Optional attributes: `api_key` and `api_secret` (sensitive overrides),
`endpoint`, and Tor support through `use_tor = true`
(`socks5://127.0.0.1:9050`) or `proxy = "socks5h://host:port"`. An `.onion`
endpoint requires a proxy; HTTPS is required everywhere else. A missing
credential or an invalid endpoint is refused before any connection is made.

## Resources and data sources

Version 0.4.0 ships four resources and four data sources:

| Name | Manages |
| --- | --- |
| `impreza_app_deployment` | A catalog app installed on one of your agents, with non-secret settings. Destroy uninstalls the app and keeps its data, only with `deletion_protection = false`. |
| `impreza_dns_record` | One record in the zone of a domain registered on your account. A record is its type, host and value; changing `domain`, `type` or `host` replaces it. |
| `impreza_variable_group` | The variable group of a project or one environment. `vars` are plain; `secrets` are write-only and never stored in the plan or the state. |
| `impreza_app_onion` | Publishes an already-running app as an onion service, with a hardening `profile` (`standard`, `hardened`, `max`). |
| `impreza_account` | Data source: id, currency and balance of the credential's account. No name or e-mail. |
| `impreza_services` | Data source: your services. No IP address or domain goes to the state. |
| `impreza_deployments` | Data source: your catalog deployments, without their settings (settings may hold secrets). |
| `impreza_catalog_apps` | Data source: the app catalog, including which declared settings are secret or generated. |

A minimal configuration:

```hcl
data "impreza_account" "current" {}

resource "impreza_app_deployment" "memos" {
  app_name = "memos"
  agent_id = "agt_0123456789abcdef01234567"
  vars = {
    MODE = "prod"
  }
}

resource "impreza_app_onion" "blog" {
  deployment_id = impreza_app_deployment.memos.id
  profile       = "hardened"
}
```

Existing infrastructure is adopted with `terraform import`, never by a
create: each resource documents its import id in the repository's `docs/`
directory.

## Safety model

- Every write is sent exactly once. An uncertain answer (5xx or a lost
  connection) is not retried blindly: run `terraform plan`, and import the
  resource if the write went through.
- Secret values never enter the state. Variable-group secrets are write-only
  and re-sent when you change `secrets_version`; the onion private key is
  never exposed to the provider at all.
- A variable-group write replaces the whole group. Omitting `secrets`, or
  removing a secret name, removes those secrets on the next apply; review
  the `sealed_names` change in the plan. Destroy deletes all variables and
  secrets in the scope, and secret values cannot be read back.
- Destroy is protected: deployments and variable groups require
  `deletion_protection = false` (default `true`).
- Catalog settings marked secret or generated are refused at plan time, before
  any request is sent. Use the owner-authenticated secret entry in the client
  area for those, or a variable group.

## Deliberately not implemented

Exporting, rotating or purging the private key of an onion service are custody
actions that stay outside Terraform: the provider implements none of them, and
a test in the repository proves it never calls those API paths. Taking an
onion service away from a running app is a client-area action for the same
reason — destroying `impreza_app_onion` removes the resource from the state
only, and the onion keeps serving.

Also out of scope, by design: anything that moves money (orders, payments,
top-up), registering or transferring domains, VPS orders, data purge,
deployment-level secret settings, custom deploys, ingress, failover and PITR,
host plans, and API key management.

## Verify a release

Each release has a `SHA256SUMS` file with a detached OpenPGP signature by the
Impreza release signing key (RSA, fingerprint `6B3B5A4C AAE29C44 F5398B14 BD79F84E
ED6B38C0`). Verify the `SHA256SUMS` file against its `.sig` and the
published fingerprint before trusting a binary you installed manually:
[signing keys and release verification](/security/signing-keys.html#verify-release).

## Limits and troubleshooting

- **A DNS record you removed outside Terraform stays in the state** once its
  type holds 20 or more records: the API lists at most 20 records of one type,
  so the provider cannot prove the record is gone. Keep large record sets of
  one type outside Terraform.
- **A lowercase variable name drifts on every plan**: names are
  `UPPERCASE` (`[A-Z_][A-Z0-9_]*`). Rename the key in your configuration.
- **A secret value does not re-send after you change it in the
  configuration**: bump `secrets_version`. Terraform cannot compare a value it
  does not store.
- **Apply stops with "changed outside Terraform"**: someone edited the group
  in the portal. Run `terraform plan -refresh-only`, review, then apply.
- **Values the API masks** (for example a name containing `TOKEN`) keep the
  value from your configuration in the state; do not mark such a variable as a
  `var` if it is a secret — make it a write-only `secret`.

## Related reference

- [Provider repository and per-resource schema reference](https://github.com/imprezahost/terraform-provider-impreza)
- [Signing keys and release verification](/security/signing-keys.html)
- [REST API reference](/api.html)
- [Encrypted server disk](/security/encrypted-root.html) for the disks the
  apps run on
