Post

Using MinIO as a Terraform Backend

MinIO is a self-managed object storage alternative to AWS S3, DigitalOcean Spaces, GCP Cloud Storage, etc., that we can use in the homelab while using Terraform to manage your resources without worrying about losing the Terraform state. Now, let’s use MinIO by starting to create an LXC container (I use 1 CPU and 512 MB of RAM because it’s not hosting big files or being accessed regularly; hence, I created an LXC with small specs) and install MinIO based on this reference and add additional commands to make it work.

Create a user and group because minio package doesn’t create it by default.

1
2
groupadd -r minio-user
useradd -M -r -g minio-user minio-user

Create a configuration.

1
2
3
4
5
6
cat <<EOF >/etc/default/minio
MINIO_OPTS="--console-address :9001"
MINIO_ROOT_USER=minioadmin
MINIO_ROOT_PASSWORD=minioadmin
MINIO_VOLUMES="/mnt/data"
EOF

Once the installation is completed, you can access the MinIO dashboard by navigating to http://x.x.x.x:9001/. Refer to this reference for credentials: https://min.io/docs/minio/linux/administration/identity-access-management/minio-user-management.html#id4

Next, create a new bucket named terraform.

minio

You can enable versioning similar to cloud services like AWS S3.

minio

By default, the bucket is private, which is good as a security concern. To make Terraform work with this bucket, we would need to create a new secret that has access to the bucket we’ve created.

minio

There is an option to enable user policies similar to AWS IAM because MinIO is S3 API compatible and also uses the same policies.

minio

You can use the policy code below; it’s restricted to be fully accessed only to the terraform bucket.

1
2
3
4
5
6
7
8
9
10
11
12
{
   "Version": "2012-10-17",
   "Statement": [
      {
         "Action": [
            "s3:*"
         ],
         "Effect": "Allow",
         "Resource": "arn:aws:s3:::terraform/*"
      }
   ] 
}

If you want the secrets to have no expiration, you can ignore the Expiry option however, please don’t do this in a production setup.

At the end, here is the backend configuration named backend.tf in your Terraform folder.

1
2
3
4
5
6
7
8
9
10
11
12
13
terraform {
    backend "s3" {
        endpoint        = "http://x.x.x.x:9000"
        bucket          = "terraform"
        key             = "state/xxxx.tfstate"
        skip_requesting_account_id  = true
        skip_credentials_validation = true
        skip_metadata_api_check     = true
        skip_region_validation      = true
        skip_s3_checksum            = true
        force_path_style            = true
    }
}

The endpoint URL is using port 9000 because it’s for the API; 9001 is the port for the UI. The rest of the configuration instructs Terraform to ignore validation of the request to behave like AWS S3; hence, we ignore it. You can check this reference for available options in the backend configuration.

To get started, you can either define the access and secret keys in the backend file itself or use the command below.

1
terraform init -backend-config="access_key=xxxxx" -backend-config="secret_key=xxxxx"
This post is licensed under CC BY 4.0 by the author.

Trending Tags