MinIO + Rails Active Storage
Tags: ruby, rails, minio
Published: 2023-07-31 23:24:46

Currently, at the company I work for, we are working on rebuilding some modules of older applications. During this process, we decided to replace CarrierWave (a system we used for avatar uploads, for example) with Active Storage, as we believe it better suits our needs.

To understand the differences between the CarrierWave gem and Active Storage, I recommend reading two excellent articles:
[From CarrierWave to Active Storage](https://huy-hoang.medium.com/from-carrierwave-to-active-storage-b2fd3e71407f)
and
[Active Storage in production: lessons learned and in-depth look at how it works](https://discuss.rubyonrails.org/t/active-storage-in-production-lessons-learned-and-in-depth-look-at-how-it-works/83289)


Once the decision to use Active Storage was made, we needed to consider the method or service for storing these files. This is important because we have other applications that also need to load these files. An important point is that we have powerful local servers available, so if possible, we would prefer to use these servers instead of a service like Amazon S3 or Azure for example. This led us to choose [Min.io](https://min.io/), and this is what this article will talk about.

Min.io is a high-performance, distributed object storage system designed for large-scale private cloud infrastructure. The great advantage is that it is fully compatible with Amazon S3.

To use Min.io, all we have to do is configure Active Storage through `config/storage.yml` as if we were using S3, but point it to a different endpoint, which will be our server running MinIO. In our example, the endpoint will be our own machine, so we will use `localhost`.

#Running MinIO#
In our example, we will run MinIO directly on our machine (Linux), but it is also possible to run it using Docker, Kubernetes, or other non-Linux operating systems. For more information, refer to the [Min.io documentation](https://min.io/docs/minio/kubernetes/upstream/).

After installing MinIO as following the instructions in documentation, we can start the server with the following command: `minio server ~/minio`. We will know the server is running when our terminal displays the following information:
```
MinIO Object Storage Server
Copyright: 2015-2023 MinIO, Inc.
License: GNU AGPLv3 <https://www.gnu.org/licenses/agpl-3.0.html>
Version: RELEASE.2023-07-21T21-12-44Z (go1.19.11 linux/amd64)

Status: 1 Online, 0 Offline.
S3-API: http://192.168.1.7:9000  http://127.0.0.1:9000
RootUser: minioadmin
RootPass: minioadmin

Console: http://192.168.1.7:36187 http://127.0.0.1:36187
RootUser: minioadmin
RootPass: minioadmin

Command-line: https://min.io/docs/minio/linux/reference/minio-mc.html#quickstart
   $ mc alias set myminio http://192.168.1.7:9000 minioadmin minioadmin

Documentation: https://min.io/docs/minio/linux/index.html
Warning: The standard parity is set to 0. This can lead to data loss.
```

#Accessing MinIO through the browser and creating a bucket#
Once our MinIO server is running, we need to create a bucket. To do this, we must access one of the addresses listed in our terminal from the previous step; let's use `http://127.0.0.1:9000`. We will log in to the system using the username and password `minioadmin`, and in the menu, we will go to the Bucket option and create a new bucket. In our case, we will name it `rails-bucket`.

#Configuring `config/storage.yml`#
With everything set up, we will now configure the 'config/storage.yml' file to make everything work. We will configure it as if we were using S3 as the service but add a different endpoint. Our configuration will look like this:

```yml
local:
  service: S3
  endpoint: http://127.0.0.1:9000
  access_key_id: minioadmin
  secret_access_key: minioadmin
  region: us-east-1
  bucket: rails-bucket
  force_path_style: true
```

In this example, I left the `access_key_id` and `secret_access_key` visible for didactic purposes, but I recommend using Rails Credentials to store these keys securely. Additionally, it is necessary to include `force_path_style: true` because otherwise, Active Storage will use a bucket context as a subdomain, and MinIO expects the `bucket` to be included after the domain.

It is also important to note that we used the name `local:` for this service in `storage.yml`, so in our `development.rb` file, we need to have the same service name in the configurations: `config.active_storage.service = :local`. If you used a different name in `storage.yml`, be sure to change it accordingly in `development.rb`.

Furthermore, we need to add the gem `aws-sdk-s3` to our Gemfile.

Everything is now ready, and our application is set to use MinIO together with Active Storage. The next time we upload a file, it will go directly to our bucket in MinIO, on our local server.

I hope this helps! :)