Minio (S3-Compatible Storage) and Terragrunt (Day 17)
With Minio running on our new storage, we've now got S3-compatible storage right. First use case: moving VM state off the local filesystem.
Setup and Configuration
Access Keys
First, head to Minio and create an access key - you'll need both the Access Key and Secret Key for the next steps.
Download the file or copy the created keys (once you close the popup the you can no longer copy the keys).

AWS CLI Configuration
After installing the AWS CLI (see installing guide here) we need to configure it:
aws configure
AWS Access Key ID [None]: <Key ID copied from minio>
AWS Secret Access Key [None]: <Secret key copied from minio>
Default region name [None]: eu-west-1
Default output format [None]:
# Set signature version
aws configure set default.s3.signature_version s3v4
Add your Minio endpoint to the config (if you are using a reverse proxy make sure the URL is pointing to port 9000, not the GUI port):
# ~/.aws/config
[default]
region = eu-west-1
endpoint_url=https://minio-s3.<your domain name> <- Add this line
s3 =
signature_version = s3v4
Quick Test
Let's make sure everything works:
# Create a bucket
aws s3 mb s3://test-minio-bucket
make_bucket: test-minio-bucket
# List buckets
aws s3 ls
2025-01-29 20:33:06 test-minio-bucket
# Remove the test bucket
aws s3 rb s3://test-minio-bucket
remove_bucket: test-minio-bucket
Terragrunt Integration
To use this with Terragrunt, you'll need to add some config to the remote_state
block. (See example repo here).
Since we're using Minio rather than actual S3, we need to disable several S3-specific features - otherwise Terragrunt will try to do S3 specific modifications to the bucket settings:
# remote_state block
remote_state {
backend = "s3"
config = {
bucket = "terragrunt-state"
key = "${path_relative_to_include()}/baldr.tfstate"
region = local.aws_region
endpoint = local.environment_vars.locals.endpoint_url
# Skip various S3 features we don't need
skip_bucket_ssencryption = true
skip_bucket_public_access_blocking = true
skip_bucket_enforced_tls = true
skip_bucket_root_access = true
skip_credentials_validation = true
force_path_style = true
}
generate = {
path = "backend.tf"
if_exists = "overwrite_terragrunt"
}
}
Note: The endpoint needs to be set in the Terragrunt config even if it's in the AWS config file - I found Terragrunt doesn't pick it up from there.