Setting up a Multistream Server with Nginx
Table of Contents
Introduction
For a while when I've been streaming games to Twitch I have been wanting to stream to Facebook, Mixer and Youtube as well. Some services like Restream.io offer a stream to multiple services at once but some of the features such as streaming to Facebook are paid features and costing over £15 a month its quite expensive to add in.
I set out to set up a new server that would allow me to do all of the services I wanted at once. With a bit of research I was able to find out about installing an RTMP module with nginx and this meant with a bit of thought I could use nginx to push the stream to multiple sources at once.
Now that I've completed a local version of this I wanted to implement a live version that I could use, with the success of my tests I was able to reproduce a multistream service on a remote machine which I will use to now stream to all of the services I want and more.
Step 1: Setting up and configuring the server
So firstly you need to get a machine, I purchased a VPS from OVH as they offer up unlimited bandwidth on their VPS machines.
So once my machine was setup I was emailed a password and root access. I got logged into the machine and begin to setup what I needed.
You'll need to build nginx as you will be adding the custom RTMP module to the build so download the latest version for stable release from the nginx website. Go to the nginx downloads page and copy the url for the next command:
cd ~
wget http://nginx.org/download/nginx-1.12.2.tar.gz
wget https://github.com/arut/nginx-rtmp-module/archive/master.tar.gz
This will download the nginx and the module required to build rtmp for nginx.
Now untar the files:
tar -xzvf nginx-1.12.2.tar.gz
tar -xzvf master.tar.gz
With this you should now see that you have two directories and two tar files, go ahead and remove the tar files as you wont need these again:
rm nginx-1.12.2.tar.gz
rm master.tar.gz
Move into the nginx directory and configure the install:
cd nginx-1.12.2
./configure --with-http_ssl_module --without-http_gzip_module --add-module=../nginx-rtmp-module-master
You should now start preparing the module for make. If there are any errors here you should find why you are unable to build, likely it will be missing dependancies but if you are running a relatively new install of an Linux distro you should be fine.
With that we need to now make and make install
make
make install
Nginx will be built with the default values and you'll find that nginx is built straight to the /usr/local/nginx
directory.
cd /usr/local/nginx
ls
You'll hopefully see a conf folder and a html folder there, this means we are ready to configure the nginx to use. But before we do that we should add the init.d and allow nginx to start on boot!
First grab a init.d command and allow it to be executed, Jason Giedymin has a great script that will do the job on Github so I've used this for the server:
wget https://raw.githubusercontent.com/JasonGiedymin/nginx-init-ubuntu/master/nginx -O /etc/init.d/nginx
chmod +x /etc/init.d/nginx
update-rc.d nginx defaults
Perfect, should now have a working service command available.
Step 2: Additional files
For this you may need to add a few more requirements, as we will be using FFmpeg later I installed some more software using apt:
apt-get install software-properties-common
apt-get install ffmpeg
If ffmpeg isn't available you can add a custom source:
add-apt-repository ppa:kirillshkrogalev/ffmpeg-next
apt-get update
I also needed to install curl as well:
apt-get install curl
Step 3: Configuring nginx
Now that we have nginx ready we should configure nginx to allow rtmp and http requests I've copied my configuration I used for testing I have put comments explaining each line.
The file you will want to edit is /usr/local/nginx/conf/nginx.conf
:
user www-data;
worker_processes 1;
events {
worker_connections 1024;
}
# http requests allow checking that rtmp is working and being published to
http {
# turn off server tokens and hide what server version you are using
server_tokens off;
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server {
listen 80;
server_name localhost;
error_log /var/log/nginx_error.log warn;
# allows you to view stats
location /stat {
rtmp_stat all;
rtmp_stat_stylesheet stat.xsl;
}
# allow stat xml styling to be accessed
location /stat.xsl {
root html;
}
# make a internal server page and put it in html
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}
# rtmp server configuration
rtmp {
server {
# port to listen on, I've left this as a default
listen 1935;
chunk_size 8192;
# this is what you will stream to
application live {
live on;
# record off means no vod saving
record off;
# allow publishing from all (change this to your ip if you wish to lock to ip address)
allow publish all;
# uncomment this if you are going to deny every ip other than yours
# deny publish all;
# push to all sub applications we will create (one each for each application)
push rtmp://localhost/youtube;
push rtmp://localhost/facebook;
push rtmp://localhost/mixer;
# for twitch I'm being more specific so I can define how my stream looks on twitch
exec ffmpeg -i rtmp://localhost/$app/$name -c:v libx264 -preset veryfast -c:a copy
-b:v 3500k
-bufsize 3500k
-maxrate 3500k
-s 1280x720 -r 30
-f flv rtmp://localhost/twitch/$name;
}
# example youtube app
application youtube {
live on;
record off;
# only allow this machine to publish
allow publish 127.0.0.1;
deny publish all;
# push url, this will be your stream url and stream key together
push rtmp://{youtube-stream-url};
}
# example twitch app
application twitch {
live on;
record off;
# only allow this machine to publish
allow publish 127.0.0.1;
deny publish all;
# push url, this will be your stream url and stream key together
push rtmp://{twitch-stream-url};
}
application facebook {
live on;
record off;
allow publish 127.0.0.1;
deny publish all;
# push url, this will be your stream url and stream key together
push rtmp://{facebook-stream-url};
}
application mixer {
live on;
record off;
# only allow this machine to publish
allow publish 127.0.0.1;
deny publish all;
# push url, this will be your stream url and stream key together
push rtmp://{mixer-stream-url};
}
}
}
Next to be safe you should now chown the following folders for nginx to be able to run them as appropriate:
chown -R www-data:www-data /usr/local/nginx/html
With this configuration you should now be able to push to your server ip using obs with the url: rtmp://myserver.org/live
Doing this means you can publish to all of your stream locations without any authentication. If you are restricting by IP you can feel safer knowing that nobody else can stream to your channels.
Now that we have added this configuration, restart nginx and check that nginx is running:
service nginx restart
If nginx is running correctly (without an errors shown) you should be able to do:
curl localhost:80/stat
And see a response. Huzzah we have it so now we can start streaming right away.
Conclusion
Hurray! So now you should be able to stream to all of your services at once. Next article I will make will explain how to use PHP to authenticate your rtmp with a stream key which will make it more secure.