Rails ActiveStorage Configuration for Minio
You are looking at Rails 5.2 and its shiny new ActiveStorage – a built-in abstraction/mechanism to handle file storage. You decide to give it a try and remove a dependency you normally use (i.e., CarrierWave or Paperclip).
For some reason, you decide to use Minio – an Amazon S3 compatible open source project.
Now it is time to try running everything, but with Minio as your file storage. Looking at your
config/storage.yml you’ll see the template for Amazon’s S3:
amazon: service: S3 access_key_id: <%= Rails.application.credentials.dig(:aws, :access_key_id) %> secret_access_key: <%= Rails.application.credentials.dig(:aws, :secret_access_key) %> region: us-east-1 bucket: your_own_bucket
Now it’s time to figure out how to use the S3 service in conjunction with your Minio server…
Your Minio server doesn’t really support regions like Amazon’s S3. Just keep it as
us-east-1 or your closest S3 region (although it really could be any string). From what I’ve seen, this is just used at the Amazon S3-level, and for your hosted Minio server it does not matter.
region value is simply used to satisfy ActiveStorage and the
aws-sdk-s3 gem. If you omit the
region option you get the following exception
missing keyword: region (ArgumentError). If you use an empty string for
region you will see
missing region; use :region option or export region name to ENV['AWS_REGION'] (Aws::Errors::MissingRegionError).
Your Minio server is hosted at some URL (i.e., https://minio123.com), so you’ll need to inform ActiveStorage’s S3 service about this endpoint. Luckily, it is just a matter of adding the URL endpoint to your configuration:
endpoint: "https://minio123.com" # Points to your Minio server
You can also use ports on the endpoint (i.e., “http://localhost:9000”).
So you have the endpoint and region all setup from a configuration standpoint. Your Minio server is also up and running, along with a bucket,
your_own_bucket. You try to upload a file and see the following exception:
Aws::Errors::NoSuchEndpointError (Encountered a `SocketError` while attempting to connect to: https://you_own_bucket.minio123.com/RJioqjrTT4VmFobw5FhXkSby This is typically the result of an invalid `:region` option or a poorly formatted `:endpoint` option. * Avoid configuring the `:endpoint` option directly. Endpoints are constructed from the `:region`. The `:endpoint` option is reserved for connecting to non-standard test endpoints.
Hmm… Well that didn’t work out. If we look at the URL (https://your_own_bucket.minio123.com), we can see that it uses a bucket subdomain approach. However, Minio expects the bucket after the domain (i.e., https://minio123.com/your_own_bucket). Again, fortunately there is an configuration option we can add to force this path style:
force_path_style: true # Needed to be compliant with how Minio serves the bucket
At this point we covered all the configuration gotchas to set up ActiveStorage with Minio. Namely, the missing and (mostly undocumented)
force_path_style options. The following is a complete configuration.
minio: service: S3 access_key_id: <%= Rails.application.credentials.dig(:minio, :access_key_id) %> secret_access_key: <%= Rails.application.credentials.dig(:minio, :secret_access_key) %> region: us-east-1 bucket: your_own_bucket endpoint: "https://minio123.com" force_path_style: true
It isn’t a bad idea to have the configuration named
minio, just so it is clear that it’s a Minio file storage instead of the typical Amazon S3.