Using MinIO instead of a S3 bucket

4 min read | by Jordi Prats

Since MinIO is an object storage server that implements the same public API as Amazon S3, can it be used to store terraform's state?

Yes, it is possible although we will have to set a bunch of options in order to make it work. Assuming we have a minio running on We can, for example use docker to start the service:

docker run -d -p 9000:9000 minio/minio server

We'll need to create a bucket beforehand, for example we can use rclone for this:

rclone mkdir remote:demo

The terraform configuration for the s3/minio backend it's going to be the following:

terraform {
  backend "s3" {
    bucket = "demo"
    key = "terraform.tfstate"

    endpoint = ""


    region = "main"
    skip_credentials_validation = true
    skip_metadata_api_check = true
    skip_region_validation = true
    force_path_style = true

On this github repo (pet2cattle/terraform-minio-backend) you'll be able to find a full working example. Once everything is in place it will work just as any S3 backed terraform state. We can use terraform init as usual:

$ terraform init

Initializing the backend...

Successfully configured the backend "s3"! Terraform will automatically
use this backend unless the backend configuration changes.

Initializing provider plugins...
- Finding latest version of hashicorp/null...
- Installing hashicorp/null v3.1.0...
- Installed hashicorp/null v3.1.0 (self-signed, key ID 34365D9472D7468F)

Partner and community providers are signed by their developers.
If you'd like to know more about provider signing, you can read about it here:

The following providers do not have any version constraints in configuration,
so the latest version was installed.

To prevent automatic upgrades to new major versions that may contain breaking
changes, we recommend adding version constraints in a required_providers block
in your configuration, with the constraint strings suggested below.

* hashicorp/null: version = "~> 3.1.0"

Terraform has been successfully initialized!

You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.

If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.

Any other terraform command will work as usual as well:

$ terraform plan
Refreshing Terraform state in-memory prior to plan...
The refreshed state will be used to calculate this plan, but will not be
persisted to local or remote state storage.


An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # null_resource.test will be created
  + resource "null_resource" "test" {
      + id = (known after apply)

Plan: 1 to add, 0 to change, 0 to destroy.


Note: You didn't specify an "-out" parameter to save this plan, so Terraform
can't guarantee that exactly these actions will be performed if
"terraform apply" is subsequently run.

Nevertheless, we are pushing some secrets such as the access_key and the secret_key to the terraform code. We could also set them as environment variables as follow:


Then we can just remove them from the terraform configuration and set them at every command as follows:

terraform init -backend-config="access_key=$MINIO_ACCESS_TOKEN" -backend-config="secret_key=$MINIO_SECRET_KEY"

It's not going to be the easiest way to use it, that's for granted, but some aliases might alleviate some pain

Posted on 15/06/2021