How to setup S3 storage along with unite cms and do image resizing using external services.

In this tutorial i will show how to setup a S3 storage, fetch the images over graphQL and do some basic image resizing using two external services. As we strongly believe in microservices, unite cms doesn’t come with a built-in image handling solution. 
We have chosen S3 as it comes with a lot of advantages, for example easy integration, easy content distribution, scalability and even more.

In this example i will show two different S3 object storage providers and two different image resizing services. I will always provide an open source alternative to keep your costs low.

All example code can be found in the small example app written in basic PHP which you can checkout!
see https://github.com/unite-cms/example-image-resizing

NOTE:
please read our blog tutorial first (if you haven’t already) https://medium.com/unite-cms/create-a-blog-using-unite-cms-vue-js-2784743bb488, i won’t show how to create a new domain, content type and a API Key again in this tutorial.


S3 Object Storage

First you have choose your S3 storage provider, two possibilities would be:

Amazon AWS S3

Amazon has introduced S3 storage and is providing the most mature S3 solution. Currently there is also a free plan for new customers for 1 year with 5GB storage to try things out. Besides that you can do a lot with AWS, it’s pretty huge and also complex in some parts.

I won’t go much into detail here, basically what you need to do is:

1. Register at https://aws.amazon.com
2. Follow “Get started with Amazon S3” button
3. Create an User / Access key under “My Security Credentials”
4. Maybe you also want to check your CORS / Bucket access settings

Some screenshots from AWS interface:

AWS interface

Check also the AWS docs:
https://docs.aws.amazon.com/AmazonS3/latest/gsg/GetStartedWithS3.html

The outcome should be the following things:
- endpoint (you can use the general endpoint https://s3.amazonaws.com or check https://docs.aws.amazon.com/general/latest/gr/rande.html for a faster endpoint for your specific region)
- bucket name
- access key
- secret key

Minio

Minio (https://github.com/minio/minio) is a open source alternative with a S3 compatible API which is pretty easy to use.
You can install it on your server or (if your’re able to host docker) use the provided docker image. A example can also be found in the docker compose file of unite cms (https://github.com/unite-cms/unite-cms).

So basically the steps are:

1. Install minio or run it with docker
2. Create a new bucket
3. Edit bucket policy for read access

Minio interface

The outcome should be the following things:
- endpoint (which is simply your url of minio)
- bucket name
- access key (which you will know on install here)
- secret key (which you will know on install here)

A list of alternative s3 providers can be found here http://www.s3-client.com/s3-storage-providers.html


Configure your S3 Storage with unite cms Image Field

Now it’s time to configure you s3 storage provider in unite cms.

See also the sample domain from the example:
https://raw.githubusercontent.com/unite-cms/example-image-resizing/master/unite_cms_domain_config.json

As can be seen in the unite cms documentation (https://www.unitecms.io/docs.html, see Sections File and Image) and the example app, the configuration is pretty straight forward:

For a AWS S3 Bucket located in EU (Frankfurt) it would be:

{
"title": "Image",
"identifier": "image",
"type": "image",
"settings": {
"bucket": {
"endpoint": "https://s3.eu-central-1.amazonaws.com",
"bucket": "my-test-bucket",
"region": "eu-central-1",
"path": "my-cool-images",
"key": "XXXX",
"secret": "XXXX"
}
}
}

For a Minio S3 bucket it would go:

{
"title": "Image",
"identifier": "image",
"type": "image",
"settings": {
"bucket": {
"endpoint": "https://my-self-hosted-minio.com",
"bucket": "my-test-bucket",
"path": "my-cool-images",
"key": "XXXX",
"secret": "XXXX"
}
}
}

If everything is working you should be able to upload a image to your s3 bucket.

unite cms image upload

Consuming your images with GraphQL

Now it’s time to fetch you images over the graphQL API.

If your Domain and API key was set up, you should be able to query your content type.

This example is written in basic PHP and is using euautomation graphQL client https://github.com/euautomation/graphql-client.

<?php
# unite cms credentials
$unite_cms_endpoint = 'https://XXXX.unitecms.io/mydomain/api';
$unite_cms_api_token = 'XXXXXXXXX';
$query = '{
findPage {
result {
headline,
image {
type,
id,
size,
name,
url
}
}
}
}';
try 
{
$client = new Client($unite_cms_endpoint);
$response = $client->response($query, [], ['Authorization' => $unite_cms_api_token])->all();
print_r($response);
} catch (\Exception $e) {
die('Error fetching data: '.$e->getMessage());
}
?>

Image resizing using external services

In this example i will use cloudimage.io (https://www.cloudimage.io) and a open source tool called thumbor (https://github.com/thumbor/thumbor) as external image resizing services. For thumbor there’s also a great docker image available, see https://github.com/APSL/docker-thumbor for more information.
Both services do work with simple url patterns as the following examples show.

Thumbor Example:

<picture>
<source media="(max-width: 480px)" srcset="https://my_thumbor.com/unsafe/480x0/my_minio.com/test-bucket/sample.png">
<source media="(max-width: 768px)" srcset="https://my_thumbor.com/unsafe/768x0/my_minio.com/test-bucket/sample.png">
<img src="https://my_thumbor.com/unsafe/1200x0/my_minio.com/test-bucket/sample.png" alt="My Image" style="width:auto;">
</picture>

cloudimage.io Example:

<picture>
<source media="(max-width: 480px)" srcset="https://xxxxxxx.cloudimg.io/width/480/x/https://s3.amazonaws.com/test-bucket/.../sample.png">
<source media="(max-width: 768px)" srcset="https://xxxxxxx.cloudimg.io/width/768/x/https://s3.amazonaws.com/test-bucket/.../sample.png">
<img src="https://xxxxxx.cloudimg.io/width/1200/x/https://s3.amazonaws.com/test-bucket/..../sample.png" alt="My Image" style="width:auto;">
</picture>

Happy image resizing!