kaltura / nginx-vod-module

NGINX-based MP4 Repackager
GNU Affero General Public License v3.0
2k stars 439 forks source link

Help with Cloudfront CDN setup #1453

Open cbarburescu opened 1 year ago

cbarburescu commented 1 year ago

Hello,

I am setting up an on-prem server in Europe that's supposed to stream HLS content in Europe, US and Asia. In order to decrease the loading time for US and Asia, I set up Cloudfront as a CDN.

What I need to solve is:

  1. When I use the CDN endpoint for the master.m3u8 playlist, only that file is served through the proxy; the segments and encryption key are subsequently served from the origin server. How can I set it up in order for all the subsequent requests to be serverd from the Cloudfront endpoint?
Screenshot 2023-07-18 at 18 04 29

As you can see, only the master.m3u8 is served from abc.cloudfront.net, and the rest are served from streaming.mydomain.com.

Could someone help with the configuration on nginx's/ cloudfront's side?

  1. Not caching the HLS encryption keys on the CDN. For extra privacy, I do not want to cache the encryption keys (vod_secret_key) on the CDN, so the content cannot be decoded there.

Thank you, Calin

cbarburescu commented 1 year ago

Figured out number 1: needed to set vod_base_url and vod_segments_base_url to the URL of the Cloudfront endpoint (no trailing slash - important).

vod_base_url https://abc.cloudfront.net;
vod_segments_base_url https://abc.cloudfront.net;

Still working on number 2, if anyone has any ideas.

erankor commented 1 year ago

You can configure CloudFront to cache based on the Cache-Control/Expires headers returned from the origin, and use either nginx's if directive, or 2 locations in order to return Cache-Control: no-cache for encryption key requests.

cbarburescu commented 1 year ago

Hi @erankor, thanks for responding. Could you give me an example of a config file with the location directive for the keys? I thought of it, but not sure how to set the root to the correct location of the key files on the disk.

I know if is also an option, but I already have ifs based on 2 variables and that required the use of map. Adding a 3rd variable to map will increase the combinations a little too much, and it's not so clean.

Also, from what I've researched, Cache-Control: no-store is the correct directive in order for a CDN server/ browser to not cache a certain request. Furthermore, if one would want to cache something in the browser, and not on a CDN server, one would have to use Cache-Control: private. In this situation, the latter is better, because you don't want the browser to request the key for each segment.

erankor commented 1 year ago

I don't know how your conf currently looks like... but in high level, if you have something like -

location /hls/ {
    vod hls;
    vod_expires 100d;
}

Then you can add a regex location like -

location ~ ^/hls/.*\.key$ {
    vod hls;
    vod_expires -1;
}

Regex locations have a higher priority than regular locations, so requests that end with key will be handled by the second location, and will return Cache-Control: no-cache. If you want private / no-store you will probably need to use nginx's add_header explicitly.