WordPress is the leading content management system and it is often thought that WordPress cannot scale. That assertion is a bit misleading. It is true that out of the box WordPress does not scale well, however, WordPress has a flexible hooks system that provides developers with the ability to tap into and alter many of its features. With a little effort, WordPress can indeed be made to be highly performant and infinitely scalable.

One of the first steps that must be taken when building any highly performant and scalable website is to offload the uploaded media files from the web servers. Amazon’s S3 is the top contender in this area, but there are many reasons why it may be desirable to host the files on your own server. Minio is an open source project that allows you to run and host your own S3 compliant service. Minio can be run as a standalone or fully distributed service and has been used to power sites with many terabytes of media.

In this article I am going to show you how I was able to leverage the WordPress WP Offload Media plugin to host uploaded media files on a Minio service.

Both WordPress and Minio have well written installation guides. You will need both set up if you are following along:

There are two versions of WP Offload Media:

The Lite version is free and provides everything you need to host new images on Minio. The Pro version has some nice additional features, such as the ability to migrate existing files in the Media Library. Both versions are excellent. Which you need will be dependent upon your use case.

For the rest of this article, I will be using on of my own websites for demonstration purposes. The site is live and available at https://lobaugh.fish. Raising fish has been a hobby of mine since I was a child. This is a site I have been working on that will allow anyone to share my passion, and get a glimpse into my tanks.

At the this articles was published, the site architecture was:

The site already existed when I decided to add support for Minio. Because there were existing media files that needed to be offloaded, I chose to go with WP Offload Media Pro version, for its ability to offload existing content. To save disk space on the web server, I also opted to remove all uploaded files from the web server as soon as they transferred to the Minio server.

After the initial installation, WP Offload Media will present you with a storage provider page where you can fill in an Amazon S3 access key and secret.

Because I am hosting on Minio, I am going to ignore the storage provider form completely and manually add the keys to the wp-config.php file. Even if you are using S3, I recommend putting the configuration into the wp-config.php file. Using the database option will cause delays as the site queries the database, and have a negative performance impact, especially on high traffic sites.

Place the following in the wp-config.php file:

define( 'AS3CF_SETTINGS', serialize( array(
'provider' => 'aws',
'access-key-id' => 'minio-key',
'secret-access-key' => 'minio-secret',
) ) );

Notice the provider key says aws and there is no mention of our Minio server? Out of the box, WP Offload Media does not have an option for Minio, however, because Minio is fully S3 compatible, we can alter the URL for the provider away from S3 and to our own services with the following code:

function minio_s3_client_args( $args ) {
$args['endpoint'] = 'http://lobaugh.fish.minio:9000';
$args['use_path_style_endpoint'] = true;return $args;
}add_filter( 'as3cf_aws_s3_client_args', 'minio_s3_client_args' );

I put that code into an mu-plugin, to ensure it runs all the time and cannot easily be disabled by plugin deactivation or theme changes.

The URL http://lobaugh.fish.minio:9000 is not a web accessible domain. It is how the web server Docker container communicates with the other container that is running Minio*. In your use case, it may be a web accessible domain that is pointed to.

Media files are accessible at https://assets.lobaugh.fish. This is managed by another small snippet of code that creates the URL string for the media file:

add_filter( 'as3cf_aws_s3_url_domain', 'minio_s3_url_domain' , 10, 2 );function minio_s3_url_domain( $domain, $bucket ) {
return 'assets.lobaugh.fish/' . $bucket;

Back on the storage provider page, pick the bucket you would like to save the images in. Then update the rest of the settings to your liking.

My config is:

  • Provider: Amazon S3
  • Bucket: media
  • Copy files to Bucket: true
  • Path: off
  • Year/Month: off
  • Object Versioning: off
  • Rewrite Media URLs: on
  • Force HTTPS: off (The webserver handles this for use)
  • Remove Files from Server: Yes

I then clicked the offload existing media button and began to see files appear on the Minio server immediately.

Load the site and validate the media URLs are pointing to the Minio URL.

That is all it took to offload the WordPress Media Library to Minio!

Offloading the Media Library is one of the components required to build a highly performant and scalable WordPress site. This will allow you to increase the number of web server instances near limitlessly, without worrying about file system replication or syncing issues. You have now seen how easily this can be accomplished with Minio. I challenge you to go forth and conquer Minio on your own WordPress powered site!