Skip to main content

Infrastructure as Code

OpenTofu drives the Infomaniak Public Cloud (OpenStack) environment, plus DNS for rjkorteschiel.nl via the Infomaniak provider. The full config is in tofu/personal-cloud/ at the root of this repository, .tofu files throughout. Assumes Provider Setup is already done — the credentials below come from there.

Setup​

1. Install OpenTofu​

brew install opentofu

2. Create the state bucket​

The state bucket must exist before tofu init can connect to it — OpenTofu can't create its own backend. Create it once manually on first setup:

pass-cli run --env-file .env -- openstack container create tofu-state

This project's own bucket is still terraform-state — a pre-OpenTofu artefact, kept as-is to avoid migrating live state. A new deployment isn't carrying that history.

3. Run OpenTofu​

cd tofu/personal-cloud
pass-cli run --env-file .env -- tofu init
pass-cli run --env-file .env -- tofu plan
pass-cli run --env-file .env -- tofu apply

4. If state fails to persist​

Infomaniak's S3 gateway 501s on the aws-chunked trailing-checksum upload the AWS SDK v2 sends by default — third-party S3 implementations routinely don't support it. versions.tofu's skip_s3_checksum = true is meant to cover this but doesn't fully (upstream bug, hashicorp/terraform#37432) — the actual fix is .env's AWS_REQUEST_CHECKSUM_CALCULATION=when_required and AWS_RESPONSE_CHECKSUM_VALIDATION=when_required.

If apply still fails to persist state after all that, OpenTofu doesn't lose the result — it writes the in-progress state to a local errored.tfstate file instead. Recover it once the underlying issue is actually fixed:

pass-cli run --env-file .env -- tofu state push errored.tfstate

Confirm it landed with tofu state list before continuing (plan should then only show what genuinely wasn't created yet, nothing already-existing getting recreated). Delete errored.tfstate once confirmed — and don't let a file like it linger untracked-but-committed; .gitignore's tofu/**/*.tfstate* should catch it, but that pattern only exists because one already slipped through once.

Checking for drift​

tofu plan isn't just for the initial apply — re-running it periodically against the live infrastructure is how configuration drift actually gets caught: does the box still match what's documented and provisioned here, or has something changed outside this config? An undocumented change is an unaudited one. No dedicated tool needed for this — the drift detection is already built into plan, the gap is just running it on a schedule and actually reviewing the diff, not a missing product.

Destroying​

Not part of the sequence above — for if this ever actually needs tearing down. tofu destroy tears down everything currently in state — including both block volumes. A volume isn't like stopping a container — destroying one loses whatever's on it permanently, no undo. Back up /mnt/data the same way as the old VPS (see Services → Coolify → Migration) before destroying anything with real data on it.

The boot volume's delete_on_termination = false (compute.tofu) doesn't protect against this either — it only stops OpenStack from cascading a delete when the instance is removed directly. The volume is its own tracked resource, so tofu destroy destroys it too unless explicitly excluded.

To tear down only part of the config instead of everything, target the specific resource:

pass-cli run --env-file .env -- tofu destroy -target=openstack_compute_instance_v2.personal_services