Skip to main content

HLS proxy-cache through Nginx

applies to MistServer 3.11 and newer

Why a HLS proxy cache?

MistServer creates an individual feed for every viewer from one input. This has great advantages in that every viewer has their own feed and cannot affect each other. This however is not an advantage when you're recreating the same fragments for everyone especially when TS fragment generation is one of the more CPU intensive tasks when it comes to packaging.

So the HLS proxy cache allows you to store a segment temporary and forward it to any viewer requesting the same segment after the first. Basically create it once, then re-use it while it's in buffer and finally remove it when it should no longer be available. This lowers the CPU usage for every viewer after the first requester significantly.

Playlists will be at the normal address location, segments however will all be forwarded to a local recorded file location & shared through Nginx.

Why Nginx?

Honestly, every webserver can handle this. The major reason why we pick Nginx is that it's something we're familiar with and know how to set up. It does help that it often comes out slightly ahead of other web servers when tested online, however if we were to be honest the differences are minimal. So you can use this setup for any other web server as well, you would just have to look up how a reverse proxy is set up or feel free to contact us for help if you really cannot figure it out.

Requirements

  • Webserver application (Nginx)
  • MistServer development version (script below)
  • Text editor

Preperations

Ulimit increase

Every OS has a limit in how many files may be open at the same time. This limit could be high or low, in any case it's smart to verify what your current one is set at and increase it if it's too little. You usually view this limit by opening /etc/security/limits.conf and adding a rule for the Nginx user have an increased open file limit:

USER soft nofile 65535
USER hard nofile 65535

Where USER is the USER of nginx, usually either http or www-data.

Nginx config

Nginx has various styles to note the configuration, it could be all in one file or in multiple. Generally though there's a http and a server section. If you open the configuration files Nginx has it should make sense quite quickly.

  • http needs the setup for the caching proxy.
  • server needs the location for the caching proxy

Nginx HTTP edit

This can often be found at: /etc/nginx/nginx.conf The following edits need to be made:

  • worker_connections
    • The amount of connections that can be open, this doesn't have to be as high as your server limit, but we do recommend at least 1024
  • worker_rlimit_nofile
    • Setting this makes sure there's the same file limit as set serverwide
  • http proxy_cache
    • This sets the location of the cache and the size. We've set it to /tmp so it's in RAM. This can be any location within the system though, change it accordingly. You can also set the maximum size and when files are considered inactive.
  • proxy_temp
    • temporary path within the proxy, needed for setup.

Example from Nginx configuration

user www-data;
worker_processes auto;
worker_rlimit_nofile 1048576;
pid /run/nginx.pid;
error_log /var/log/nginx/error.log;
include /etc/nginx/modules-enabled/*.conf;

events {
worker_connections 1024;
# multi_accept on;
}


http {

proxy_cache_path /tmp/www-cache levels=1:2 keys_zone=my-cache:8m max_size=100m inactive=6m;
proxy_temp_path /tmp/www-cache/tmp;

}

Nginx Server edit

For some Nginx configurations this is within the same /etc/nginx/nginx.conf file, however we've seen this often loaded in from another place, quite common seems to be: /etc/nginx/sites-enabled/default. You should be able to tell where Nginx is loading these from by looking at Nginx itself.

  • location /hlscache/
    • This sets the HLS cache location & allows buffering & uses the proxy cache for this path specifically. MistServer then needs to be told to use this location for HLS segments specifically.
    server {

location /hlscache/ {
add_header X-Cache-Status $upstream_cache_status;
proxy_ignore_headers Set-Cookie;
proxy_cache my-cache;
proxy_cache_valid 200 302 6m;
proxy_cache_valid 404 5s;
proxy_pass http://mist_upstream/;
proxy_set_header X-Real-IP $remote_addr;
proxy_buffering on;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_read_timeout 600s;
proxy_set_header Host $host;
proxy_set_header X-Mst-Path "$scheme://$host/mist";
add_header Access-Control-Allow-Private-Network true;
}

MistServer setting:

chunkpath option filled in

  • Send whole segments ticked on.
  • Prepand path for chunks: https://YOURSERVERNAME/hlscache/

Technically //YOURSERVERNAME/hlscache/ could work as well, but using https:// at the start enforces the use of https, which honestly makes sense anyway.

If you want to see if you set it up correctly you'll need to open one of your HLS streams and see where the segments come from. If set up correctly you'd see index.m3u8 come from normal /hls/ paths, and the segments from /hlscache/. Opening the index.m3u8 in a text editor should also review the path.