Update: I can’t guarantee this works. Consider following this guide instead: https://live.sleeping.town

I like to stream things sometimes. Usually video games. I set up the nginx rtmp module a while (years) ago, and that worked alright, but RTMP and Flash are very closely tied together, so RTMP’s days are numbered. When I tried to set things up again, I saw that not only was I using the wrong RTMP module (there’s a fork that’s much more actively maintained these days), but that HLS (HTTP Live Streaming) was the way to go. I saw a few tutorials, but none of them handled my specific use case of “I already have an existing nginx server with HTTPS enabled, how do I add HLS to it.” So I figured it out, and now you can see it.

The first thing I did was follow this tutorial which covers downloading, compiling, and installing the new version of nginx well enough. The only thing you might want to do if you have an existing nginx installation is run nginx -V first and copy everything after configure arguments and pass that to ./configure when you build your new nginx so it has all the capabilities of the one you already have installed. I had to take some stuff out, so in the end my ./configure command line ended up looking like this:

./configure --with-cc-opt='-g -O2 -fdebug-prefix-map=/build/nginx-mcUg8N/nginx-1.14.0=. -fstack-protector-strong -Wformat -Werror=format-security -fPIC -D_FORTIFY_SOURCE=2' --with-ld-opt='-Wl,-Bsymbolic-functions -Wl,-z,relro -Wl,-z,now -fPIC' --prefix=/usr/local/nginx --conf-path=/etc/nginx/nginx.conf --http-log-path=/var/log/nginx/access.log --error-log-path=/var/log/nginx/error.log --lock-path=/var/lock/nginx.lock --pid-path=/run/nginx.pid --modules-path=/usr/lib/nginx/modules --http-client-body-temp-path=/var/lib/nginx/body --http-fastcgi-temp-path=/var/lib/nginx/fastcgi --http-proxy-temp-path=/var/lib/nginx/proxy --http-scgi-temp-path=/var/lib/nginx/scgi --http-uwsgi-temp-path=/var/lib/nginx/uwsgi --with-debug --with-pcre-jit --with-http_ssl_module --with-http_stub_status_module --with-http_realip_module --with-http_auth_request_module --with-http_v2_module --with-http_dav_module --with-http_slice_module --with-threads --with-http_addition_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_sub_module --with-stream=dynamic --with-stream_ssl_module --with-mail=dynamic --with-mail_ssl_module --add-module=./nginx-rtmp-module

But all you really need is the --add-module=./nginx-rtmp-module and the one that enables HTTPS, which I think is --with-http_ssl_module.

I’m sure their instructions work well enough if this is all you’ll be using the computer for, but I had an existing nginx installation with HTTPS and HSTS set up, so it wasn’t as easy for me. Here’s what I did that worked for me.

At the bottom of your /etc/nginx/nginx.conf (or wherever you put it) file, add this block:

rtmp {
server {
	ping 30s;
	notify_method get;
listen 1935;
chunk_size 4096;

application live {
live on;

hls on;
hls_path /tmp/hls;
hls_fragment 3;
hls_playlist_length 60;

deny play all;

If you want to try and also support RTMP streaming, delete that deny play all line, though I haven’t had much luck with RTMP streaming lately.

Second, make a new file in /etc/nginx/sites-enabled/hls (or make it in sites-available and symlink to it) with this in it:

Notice the ssl after listen 8080. I had to add this because my site is HTTPS only after going on the HSTS preload list. If this doesn’t describe you, you can probably get away with not doing this and copying over all your HTTPS stuff.

server {
        listen 8080 ssl;

	#Insert all the SSL stuff you use for your regular HTTPS setup here.
  #Just copy and paste it over. 

        location / {
            # Disable cache
            add_header 'Cache-Control' 'no-cache';

            # CORS setup
            add_header 'Access-Control-Allow-Origin' '*' always;
            add_header 'Access-Control-Expose-Headers' 'Content-Length';

            # allow CORS preflight requests
            if ($request_method = 'OPTIONS') {
                add_header 'Access-Control-Allow-Origin' '*';
                add_header 'Access-Control-Max-Age' 1728000;
                add_header 'Content-Type' 'text/plain charset=UTF-8';
                add_header 'Content-Length' 0;
                return 204;

            types {
                application/dash+xml mpd;
                application/vnd.apple.mpegurl m3u8;
                video/mp2t ts;

            root /tmp/;

Then, do nginx -s reload (or /usr/local/nginx/sbin/nginx -s reload , wherever you installed your nginx to).

To test, I use OBS. You have two options here.

You can point it at rtmp://[your-ip-or-url]/live or rtmp://[your-ip-or-url]/dash . Type whatever you want as the stream key, but remember it. Type test if you need something to type. Start streaming.

If you picked /live, point cytube, VLC, or whatever at https://[your-ip-or-url]/hls/[stream key].m3u8. If you picked /dash, point cytube, VLC, or whatever at https://[your-ip-or-url]/dash/[stream key].mpd. (I don’t think cytube likes .mpd streams right now, but VLC will play them fine)

Happy streaming!