Nginx VoD Server Configuration: Minio Integration

Written by: Bagus Facsi Aginsa
Published at: 20 Mar 2022


This is the more advanced configuration for the Nginx VoD Server. In this tutorial, we will configure Vod Server to full remote mode. It means the JSON file and the video file are not in the same server as the Nginx, but they are on Minio Object Storage. This is very important if you want to build a stateless VoD Server.

Check Prerequisite

For this configuration to work, I advice you to follow my previous tutorial first on How to Build Adaptive Bitrate VoD Server using Nginx on Ubuntu.

Get Sudo Privileges

Before starting, make sure that we have no permission issues on the installation & configuration. All the commands that will be executed need root privileges. Execute this command to get the privileges.

sudo su

Modify The JSON File

If you follow my previous tutorial, you will have a JSON file like this one

{
    "sequences": [
        {
            "clips": [
                {
                    "type": "source",
                    "path": "/etc/nginx/vod/transformers_720p.mp4"
                }
            ]
        },
        {
            "clips": [
                {
                    "type": "source",
                    "path": "/etc/nginx/vod/transformers_360p.mp4"
                }
            ]
        }
    ]
}

We need to modify the path parameter so the Nginx will access the file not on the folder, but from a URL. Change the path parameter like this

{
    "sequences": [
        {
            "clips": [
                {
                    "type": "source",
                    "path": "/http/your-minio-ip:9000/public/transformers_720p.mp4"
                }
            ]
        },
        {
            "clips": [
                {
                    "type": "source",
                    "path": "/http/your-minio-ip:9000/public/transformers_360p.mp4"
                }
            ]
        }
    ]
}

The format is a little bit weird, but that’s how to VoD module works on the Nginx. This configuration will make the nginx pull the video from http://your-minio-ip:9000/public/transformers_720p.mp4 and http://your-minio-ip:9000/public/transformers_360p.mp4

Don’t forget to change your-minio-ip that suits your use case. The /public/ on the URL is the bucket name. Later in this tutorial, we will install Minio and create a bucket called public bucket. If you want a different bucket name, you can change it later.

If you want to install the Minio on the same server with the Nginx, you can change it to 127.0.0.1 like this

http://127.0.0.1:9000/public/transformers_720p.mp4
http://127.0.0.1:9000/public/transformers_360p.mp4

Save your JSON file, we will upload it to Minio together with the video file later.

Install Minio

Setup Binary File

Before we configure the Nginx, we will install our Minio object storage first and place the JSON and video file there. You can install Minio on the different/same server with the Nginx.

To Install Minio, download the minio binary file

wget https://dl.min.io/server/minio/release/linux-amd64/minio

Give it executable permission by using this command

chmod +x minio

Place the binary file on the /usr/local/bin directory

mv minio /usr/local/bin

Create a user account named minio-user to run the minio for security reasons

useradd -r minio-user -s /sbin/nologin

Change the ownership of the binary file to minio-user

chown minio-user:minio-user /usr/local/bin/minio

Create Default Minio Configuration

Next, we will create a file to store the minio configuration. Create the configuration file

nano /etc/default/minio

Copy Paste this configuration

MINIO_VOLUMES="/var/minio/"
MINIO_OPTS="-C /etc/minio --address 0.0.0.0:9000 --console-address 0.0.0.0:9001"
MINIO_ROOT_USER="miniouser"
MINIO_ROOT_PASSWORD="miniopass"

For the MINIO_ROOT_USER and MINIO_ROOT_PASSWORD, I recommend you to use a very strong key. You can use this command to generate a very strong key, it will generate a new 32 random characters.

echo -n $RANDOM | md5sum

Create a folder to store minio data

mkdir /var/minio

Change the ownership of the folder to minio-user

chown -R minio-user:minio-user /var/minio

Create Minio Systemd File

Minio already has a systemd file for us to use. We can download it using this command

curl -O https://raw.githubusercontent.com/minio/minio-service/master/linux-systemd/minio.service

Move the file to the systemd folder

mv minio.service /etc/systemd/system

Reload the systemd unit

systemctl daemon-reload

And then you can start your minio by using this command

service minio start

To check the status, you can use this command

service minio status

Upload JSON and Video File to Minio

By now, Minio should be running and can be accessed from the browser, so let’s go to the Minio GUI. Open your browser and go to your Minio Server URL

http://minio-server-ip:9001

You should see the minio console login page like this

Minio Console Login Page

Login using MINIO_ROOT_USER and MINIO_ROOT_PASSWORD you previously set on the Minio configuration file, and then create a bucket.

Click create bucket button on Minio Home Screen

After that, type your own bucket name, In my case, I will name my bucket public, and then click Create bucket button. If you use a different bucket name, remember to edit the path parameter on your JSON file as well.

Typing bucket name, and then click create bucket button

Click the upload button on the top right to upload the JSON and video file

Click upload button on bucket page

This is my JSON and video file that has been uploaded to minio

The JSON and video file uploaded on minio

After you upload your file, you must change the bucket access policy to public. To do That, head to the minio home screen by clicking the Bucket menu on the left menu, and then click the Manage button on the public bucket

Click manage button on public bucket

You see on the manage page the access policy is private, click the access policy and change it to public.

Click the access policy button

After changing the access policy, you will see the access policy of the bucket become public.

Bucket access policy become public

Now the minio part is done! You can check that your JSON file can be accessed directly from the browser using this link, and return your JSON file:

http://your-minio-ip:9000/public/transformers.json

Nginx Configuration

First, go to the nginx directory

cd /etc/nginx

Open the Nginx configuration file

nano nginx.conf

Remove the alias directive on existing location block

    location ^~ /video/ {
        alias /etc/nginx/json/;
        vod hls;

        add_header Access-Control-Allow-Headers '*';
        add_header Access-Control-Expose-Headers 'Server,range,Content-Length,Content-Range';
        add_header Access-Control-Allow-Methods 'GET, HEAD, OPTIONS';
        add_header Access-Control-Allow-Origin '*';
        expires 100d;
    }

Add more location block like this:

    location ^~ /json/video/ {
        <mark>internal;</mark>
        <mark>proxy_pass http://jsonupstream/public/;</mark>
        <mark>proxy_set_header Host $http_host;</mark>
    }

This configuration is used to read JSON files. Previously, Nginx will read the JSON file from a folder, now Nginx will read the JSON file from a remote server.

Add another location block under previous location block

    . . .

    location ^~ /json/video/ {
        internal;
        proxy_pass http://jsonupstream/public/;
        proxy_set_header Host $http_host;
    }

    location ~ /proxy/([^/]+)/(.*) {
        internal;
        proxy_pass $1://$2;
        resolver 8.8.8.8;
    }

    . . .

And add vod_remote_upstream_location and vod_upstream_location directive under the vod_mode just like this

    . . . 

    vod_mode mapped;
    vod_upstream_location /json;
    vod_remote_upstream_location /proxy;

    . . . 

The last 2 configuration is the part where the Nginx will pull the video. Previously, Nginx just read the video from the folder defined on the JSON file.

Now Nginx will make a subrequest to vod_remote_upstream_location, in this case /proxy , and then change the “weird” looking URL from the JSON file to a proper URL format, and then pull the video from the URL.

Lastly, Add an upstream block configuration named jsonupstream above the server block:

    upstream jsonupstream {
        server your-minio-ip:9000;
    }

    server {
        listen 80;

        . . .

    }

Change the your-minio-ip to your real minio ip address or domain name.

To recap, this is the full nginx.conf configuration file:

user www-data;
worker_processes auto;
worker_rlimit_nofile 8192;
pid /run/nginx.pid;

events {
    worker_connections 4096;
}

http {
    upstream jsonupstream {
        server your-minio-ip:9000;
    }

    server {
        listen 80;

        # vod mode
        vod_mode mapped;
        vod_upstream_location /json;
        vod_remote_upstream_location /proxy;

        # vod caches
        vod_metadata_cache metadata_cache 512m;
        vod_response_cache response_cache 128m;
        vod_mapping_cache mapping_cache 5m;

        # gzip manifests
        gzip on;
        gzip_types application/vnd.apple.mpegurl;

        # file handle caching
        open_file_cache          max=1000 inactive=5m;
        open_file_cache_valid    2m;
        open_file_cache_min_uses 1;
        open_file_cache_errors   on;

        location ^~ /json/video/ {
            internal;
            proxy_pass http://jsonupstream/public/;
            proxy_set_header Host $http_host;
        }

        location ~ /proxy/([^/]+)/(.*) {
            internal;
            proxy_pass $1://$2;
            resolver 8.8.8.8;
        }

        location ^~ /video/ {
            vod hls;

            add_header Access-Control-Allow-Headers '*';
            add_header Access-Control-Expose-Headers 'Server,range,Content-Length,Content-Range';
            add_header Access-Control-Allow-Methods 'GET, HEAD, OPTIONS';
            add_header Access-Control-Allow-Origin '*';
            expires 100d;
        }
    }
}

Save the file, and then make sure there is no error in the configuration file

nginx -t

Restart the nginx (Don’t use reload. We want to clear the Nginx cache, especially the JSON file)

service nginx restart

Test the Vod Server

You can test the VoD server using VLC on your laptop by pointing the network URL to http://<your-server-ip>/video/<video-configuration-file>/master.m3u8 just like the image below.

View VoD streaming via VLC

Congratulation! You have already integrated the Nginx VoD Server with Minio object storage.