Skip to main content

Terraform

With the lionbackup provider you manage projects and backup tokens as infrastructure code. It uses the public API and therefore the same permissions as your service account in the portal. The provider works with Terraform 1.9 or newer and with OpenTofu.

Where to get it​

The provider is not distributed through the public Terraform registry but through a network mirror run by lionbackup. Add it once to your CLI configuration ~/.terraformrc (or to the file TF_CLI_CONFIG_FILE points to):

provider_installation {
network_mirror {
url = "https://git.prod.lionbackup.cloud/terraform/providers/"
include = ["git.lionbackup.cloud/*/*"]
}
direct {
exclude = ["git.lionbackup.cloud/*/*"]
}
}

Tested with Terraform 1.16 and OpenTofu 1.12. OpenTofu reads the same configuration from ~/.tofurc or, failing that, from ~/.terraformrc.

The direct block makes Terraform fetch the lionbackup provider from the mirror only; every other provider keeps loading from its registry as usual.

Adding the provider​

The source address is git.lionbackup.cloud/lionbackup/lionbackup. Use the provider from version 0.1.4 onwards:

terraform {
required_providers {
lionbackup = {
source = "git.lionbackup.cloud/lionbackup/lionbackup"
version = "~> 0.1.4"
}
}
}

provider "lionbackup" {
# The API key comes from the environment:
# export LIONBACKUP_API_KEY=... (portal → Developer)
# environment = "prod" # default; "dev" for the development environment
}

You create the API key in the portal under Developer (see API) and pass it as the environment variable LIONBACKUP_API_KEY. The api_key attribute exists too, but a key in the configuration easily ends up in version control.

Example​

The example looks up your organization, creates a project in zone de01-1 inside it, creates a write token and exposes its secret as a sensitive output:

data "lionbackup_organizations" "mine" {}

locals {
organization_id = one([
for o in data.lionbackup_organizations.mine.organizations : o.id
if o.name == "Example Ltd"
])
}

resource "lionbackup_project" "backup" {
organization_id = local.organization_id
name = "web-servers"
availability_zone = "de01-1"
alert_email = "ops@example.com"
}

resource "lionbackup_project_token" "writer" {
project_id = lionbackup_project.backup.id
type = "write"
}

output "backup_token" {
value = lionbackup_project_token.writer.secret
sensitive = true
}

The organization is selected by name, not by its position in the list: a service account may see several organizations, the list is sorted by name, and every new organization shifts the positions. one() fails on more than one match; with none, organization_id stays empty and Terraform refuses the plan. Either way the project is never created silently in the wrong organization.

availability_zone expects the zone's name as listed on the Regions page and by the lionbackup_zones data source; the provider resolves it to the identifier.

Apply it:

export LIONBACKUP_API_KEY=...
terraform init
terraform apply
terraform output -raw backup_token

terraform init downloads the provider from the mirror and verifies it against the checksums published there. The output should end like this:

- Installing git.lionbackup.cloud/lionbackup/lionbackup v0.1.4...
- Installed git.lionbackup.cloud/lionbackup/lionbackup v0.1.4 (verified checksum)

The checksum is recorded in .terraform.lock.hcl. Commit that file, and every run installs exactly the same provider version.

If your .terraform.lock.hcl still holds an older version, terraform init rejects the constraint ~> 0.1.4; terraform init -upgrade then selects the new version and records it in the file. The lionbackup_organization data source and the payment_method attribute exist from 0.1.3 on. The anomaly_detection attribute exists from 0.1.4 on.

What you should know​

  • terraform destroy closes a project, it does not delete it. That is the platform's semantics: write tokens are revoked immediately, stored backups remain readable until retention ends. A closed project disappears from the Terraform state. Tokens managed by the same configuration are revoked as well, read tokens included. To keep a read token through the teardown, remove it from the state first (terraform state rm <address>) or create it in the portal.
  • Any change to a token replaces it. Every attribute of a lionbackup_project_token is chosen at creation time; changing one gives you a new token (old one revoked, new one created) — and with it a new secret.
  • The secret lives in the state. The API hands out a backup token exactly once; the provider keeps it as the sensitive attribute secret in the Terraform state. Protect the state file like a password — for instance in an encrypted remote backend.
  • Zone, organization and immutability are create-time decisions. Changing organization_id, availability_zone, immutable_storage, retention_days or auto_delete_after_retention replaces the project (plan: must be replaced). name, alert_email, billing_reference and anomaly_detection can be changed in place.
  • anomaly_detection follows the configuration. Without the attribute it is false, so an apply switches off an anomaly detection that was switched on in the portal. Manage the setting in one place, or add lifecycle { ignore_changes = [anomaly_detection] }.
  • Rate limits. The API allows 60 requests per minute per service account and per IP address. The provider retries 429 and 503 up to three times, waiting for the announced Retry-After; a large apply slows down instead of failing.
  • Permissions. The provider can do exactly what the human who owns the service account can. Creating and closing projects requires the role owner or admin in the organization.

Reference​

Provider​

AttributeMeaning
api_keyAPI key; prefer LIONBACKUP_API_KEY in the environment
environmentprod (default) or dev; selects the API and token endpoints
api_urlcustom base URL of the API, overrides environment
token_urlcustom token endpoint, overrides environment

Resource lionbackup_project​

AttributeRequiredMeaning
organization_idyesorganization identifier (data source lionbackup_organizations)
nameyesproject name, at most 100 characters
availability_zoneyeszone name, for example de01-1
alert_emailnoaddress for notifications
billing_referencenofree text for your own accounting
anomaly_detectionnoswitch on the anomaly detection for the project's backups, default false
immutable_storagenoimmutable storage, default false
retention_daysnoretention for immutable storage; the platform default when omitted
auto_delete_after_retentionnodefault true
id, status—assigned by the platform

Resource lionbackup_project_token​

AttributeRequiredMeaning
project_idyesproject identifier
typenowrite (default) for backups, read for restores
operating_systemnoLinux (default), Windows or macOS (beta)
usage_count_limitnoat most this many uses
rate_limit_per_minutenorequests per minute for this token
rate_limit_per_hournorequests per hour for this token
id—assigned by the platform
secret—the backup token, sensitive, only in the state

Data sources​

lionbackup_organizations returns organizations, sorted by name, with id, name, status, role (your role in the organization) and payment_method: sepa_debit while a SEPA direct debit mandate is active, transfer otherwise, and null where your role is only member. lionbackup_zones returns zones with id, name, status, provider, location_city and storage_type; zones with status = active can be booked.

lionbackup_organization reads one organization by its id: its payment_method and the sepa_mandate block with status, reference, iban_masked, account_holder, granted_at and revoked_at (UTC, YYYY-MM-DD HH:MM:SS). Without a mandate the block is null; after a revocation it shows the revoked mandate until a new one is granted. The IBAN is masked, the BIC is not exposed. Every role may read it except member, which sees no payment data in the portal either.

Also lionbackup_projects (every project of one organization, set organization_id, closed ones included), lionbackup_project (one project by its id) and lionbackup_whoami (the acting service account, its owner and the owner's role per organization).

OpenTofu​

OpenTofu uses the same configuration. Put the provider_installation block into ~/.tofurc (if that file is missing, OpenTofu also reads ~/.terraformrc) and replace terraform with tofu in the commands. tofu init reports verified checksum as well.

Development environment​

For tests against the development environment set environment = "dev" in the provider and use a key created there. The provider itself can additionally be fetched from the development environment's mirror; for that, swap the URL in ~/.terraformrc:

url = "https://git.dev.lionbackup.cloud/terraform/providers/"

The source address git.lionbackup.cloud/lionbackup/lionbackup stays the same in both cases.