Storing Terraform state in Pilvio S3
Pilvio offers S3-compatible object storage at s3.pilw.io. You can use it as a Terraform S3 backend, but since it's not actual AWS, several compatibility flags are required.
Prerequisites
-
S3 credentials — get your access key and secret key from the Pilvio dashboard (or API:
GET https://api.pilvio.com/v1/storage/user). -
Create the state bucket (one-time):
export AWS_ACCESS_KEY_ID="<your_access_key>" export AWS_SECRET_ACCESS_KEY="<your_secret_key>" aws s3 mb s3://my-tfstate --endpoint-url https://s3.pilw.io -
Export credentials so Terraform can find them:
export AWS_ACCESS_KEY_ID="<your_access_key>" export AWS_SECRET_ACCESS_KEY="<your_secret_key>"
Backend configuration
terraform {
backend "s3" {
bucket = "my-tfstate"
key = "project/terraform.tfstate"
# Pilvio S3 endpoint
endpoint = "https://s3.pilw.io"
region = "eu-west-1" # required by Terraform, any valid region string works
# Required for non-AWS S3-compatible providers:
skip_credentials_validation = true # Pilvio doesn't support AWS STS
skip_metadata_api_check = true # no EC2 instance metadata service
skip_requesting_account_id = true # no AWS account ID endpoint
skip_s3_checksum = true # Pilvio doesn't support AWS checksum headers
force_path_style = true # use s3.pilw.io/bucket instead of bucket.s3.pilw.io
}
}
What each flag does
| Flag | Why it's needed |
|---|---|
skip_credentials_validation | Terraform tries to validate creds via AWS STS — Pilvio doesn't have STS |
skip_metadata_api_check | Terraform looks for EC2 IMDS to get credentials — doesn't exist outside AWS |
skip_requesting_account_id | Terraform calls AWS IAM to get account ID — not available on Pilvio |
skip_s3_checksum | Pilvio doesn't support the x-amz-checksum-* headers that newer AWS SDKs send |
force_path_style | Pilvio uses path-style URLs (s3.pilw.io/bucket), not virtual-hosted (bucket.s3.pilw.io) |
Without these flags, terraform init fails with errors like "No valid credential sources found" or "failed to refresh cached credentials, no EC2 IMDS role found".
Terraform >= 1.11.2 workaround
There's a known bug where skip_s3_checksum alone doesn't fully suppress checksum headers in Terraform >= 1.11.2. Work around it by also exporting:
export AWS_REQUEST_CHECKSUM_CALCULATION=when_required
export AWS_RESPONSE_CHECKSUM_VALIDATION=when_required
Deprecated endpoint parameter
Newer Terraform versions warn that endpoint is deprecated in favor of endpoints.s3. When you see that warning, update to:
endpoints = {
s3 = "https://s3.pilw.io"
}
Verify
Once the config is in place and credentials are exported, run:
terraform init
On success you'll see Terraform has been successfully initialized! and the state file will appear in your Pilvio bucket my-tfstate under the key project/terraform.tfstate.
Verify from the command line:
aws s3 ls s3://my-tfstate/project/ --endpoint-url https://s3.pilw.io
Why this matters
The Terraform state file is the source of truth for your infrastructure. If it lives in AWS S3, your Estonian infrastructure's state file sits in US jurisdiction — CLOUD Act exposure. Keeping it in Pilvio S3 means the state file stays in Estonia, in the same jurisdiction as the rest of your infrastructure.
See also: S3 Object Storage in Estonia and the StorageVault service page.