Using Terraform with OtterStorage
Provision and version your OtterStorage buckets as code using the AWS provider pointed at the S3 endpoint.
OtterStorage is S3 API-compatible, so you can manage your buckets with Terraform's official aws provider without any extra tooling. You only need to redirect the S3 endpoint to OtterStorage and disable a few AWS-specific validations. This guide shows a complete main.tf for creating a bucket with versioning and lifecycle rules.
Prerequisites
- Terraform 1.0 or later installed.
- The
hashicorp/awsprovider, version 5.x. - An access key and a secret key for an OtterStorage bucket. See how to generate them in the documentation.
Connection details used in the examples:
- S3 endpoint:
https://es-mad-1.s3.otterstorage.io - Region:
eu-mad
Configure the provider
By default, the aws provider points at Amazon's endpoints. To use OtterStorage you have to override the S3 endpoint and disable the checks the provider would otherwise run against AWS services (credential validation, region validation, and account ID resolution), since those don't exist outside AWS.
We also enable s3_use_path_style = true: OtterStorage addresses buckets by path (https://es-mad-1.s3.otterstorage.io/mi-bucket) rather than by virtual subdomain, which avoids DNS and certificate issues.
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}
provider "aws" {
access_key = var.otter_access_key
secret_key = var.otter_secret_key
region = "eu-mad"
# OtterStorage no es AWS: desactivamos las validaciones específicas de AWS.
skip_credentials_validation = true
skip_region_validation = true
skip_requesting_account_id = true
# Direccionamiento por ruta y endpoint de OtterStorage.
s3_use_path_style = true
endpoints {
s3 = "https://es-mad-1.s3.otterstorage.io"
}
}
Variables for the credentials
Never hard-code the keys directly in your code. Declare them as sensitive variables and pass them via the environment or a .tfvars file that you don't commit to version control.
# variables.tf
variable "otter_access_key" {
description = "Access key del bucket de OtterStorage"
type = string
sensitive = true
}
variable "otter_secret_key" {
description = "Secret key del bucket de OtterStorage"
type = string
sensitive = true
}
You can supply the values through environment variables, which Terraform recognizes with the TF_VAR_ prefix:
export TF_VAR_otter_access_key="YOUR_ACCESS_KEY"
export TF_VAR_otter_secret_key="YOUR_SECRET_KEY"
Reference your bucket (created in the console)
ℹ️ Buckets are created from the console, not with Terraform: your keys are scoped to a single bucket. In Terraform you reference the bucket that already exists (by its name) to manage its configuration and objects. Create a bucket in the console.
Define the bucket name in a local so you can reuse it across the rest of your resources:
# main.tf
locals {
bucket = "easydatahost-backups" # creado previamente en el panel de OtterStorage
}
Enable versioning
Versioning is managed with a separate resource, aws_s3_bucket_versioning. With it, every overwrite or deletion preserves the object's previous versions.
resource "aws_s3_bucket_versioning" "backups" {
bucket = local.bucket
versioning_configuration {
status = "Enabled"
}
}
Lifecycle rules
With aws_s3_bucket_lifecycle_configuration you define rules to expire objects or old versions automatically. With OtterStorage you are not charged for requests or deletions, so you can set aggressive cleanup policies at no additional cost for expiration operations.
resource "aws_s3_bucket_lifecycle_configuration" "backups" {
bucket = local.bucket
# El versionado debe estar configurado antes de aplicar reglas
# sobre versiones no actuales.
depends_on = [aws_s3_bucket_versioning.backups]
rule {
id = "expirar-versiones-antiguas"
status = "Enabled"
filter {
prefix = "snapshots/"
}
# Borra el objeto actual a los 90 días.
expiration {
days = 90
}
# Borra versiones no actuales a los 30 días.
noncurrent_version_expiration {
noncurrent_days = 30
}
}
}
Complete main.tf
Putting it all together, here is a minimal, working project. You can keep it in a single main.tf or split it across providers.tf, variables.tf, and main.tf.
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}
provider "aws" {
access_key = var.otter_access_key
secret_key = var.otter_secret_key
region = "eu-mad"
skip_credentials_validation = true
skip_region_validation = true
skip_requesting_account_id = true
s3_use_path_style = true
endpoints {
s3 = "https://es-mad-1.s3.otterstorage.io"
}
}
variable "otter_access_key" {
type = string
sensitive = true
}
variable "otter_secret_key" {
type = string
sensitive = true
}
locals {
bucket = "easydatahost-backups" # creado previamente en el panel
}
resource "aws_s3_bucket_versioning" "backups" {
bucket = local.bucket
versioning_configuration {
status = "Enabled"
}
}
resource "aws_s3_bucket_lifecycle_configuration" "backups" {
bucket = aws_s3_bucket.backups.id
depends_on = [aws_s3_bucket_versioning.backups]
rule {
id = "expirar-versiones-antiguas"
status = "Enabled"
filter {
prefix = "snapshots/"
}
expiration {
days = 90
}
noncurrent_version_expiration {
noncurrent_days = 30
}
}
}
Initialize and apply
Once the files are ready and the credentials are exported, run the standard Terraform workflow:
# Descarga el provider y prepara el directorio de trabajo.
terraform init
# Muestra los cambios que se van a aplicar sin tocar nada.
terraform plan
# Crea los recursos en OtterStorage.
terraform apply
Terraform will show the plan and ask for confirmation before applying. To tear down what you created, use terraform destroy. Remember that the state (terraform.tfstate) contains sensitive data: store it in a remote backend or protect it appropriately.
Tips
- Keep
s3_use_path_style = true: it's the recommended configuration for OtterStorage. - If you manage multiple buckets with different keys, use several
provider "aws"blocks withaliasand reference them in each resource. - Because we don't bill for requests or deletions, lifecycle rules and cleanup operations add no cost at all.
- For more details on keys, regions, and limits, see the documentation.
Ready to try it out?
Create your account and get your keys in minutes.