Welcome to Open Streaming Platform’s documentation!

About Open Streaming Platform

OSP Logo

About

Open Streaming Platform (OSP) is an open-source, RTMP streamer software front-end for Arut’s NGINX RTMP Module.

OSP was designed a self-hosted alternative to services like Twitch.tv, Ustream.tv, and Youtube Live.

Features

  • RTMP Streaming from an input source like Open Broadcast Software (OBS).

  • Multiple Channels per User, allowing a single user to broadcast multiple streams at the same time without needing muiltiple accounts.

  • Video Stream Recording and On-Demand Playback.

  • Per Channel Real-Time Chat for Video Streams.

  • Manual Video Uploading of MP4s that are sourced outside of OSP

  • Real-Time Chat Moderation by Channel Owners (Banning/Unbanning)

  • Admin Controlled Adaptive Streaming

  • Protected Streams to allow access only to the audience you want.

  • Live Channels - Keep chatting and hang out when a stream isn’t on

  • Webhooks - Connect OSP to other services via fully customizable HTTP requests which will pass information

  • Embed your stream or video directly into another web page easily

  • Share channels or videos via Facebook or Twitter quickly

  • Ability to Customize the UI as a Theme for your own personal look

Repository Information

Contributions

Code Contributions

Open Streaming Platform is a free, open-source project that has been developed under the MIT License by developers giving their time to make something awesome for everyone that will respect your privacy. Contributions to OSP will help support the developers and allow us to rent servers and get the tools needed to keep the Open Streaming Platform alive.

Developers interested in contributing directly to the project may submit pull requests directly to our Gitlab Repository or by visiting our Discord.

Pull Request Guidelines

Coming Soon

Open Collective Donations

Those interested in providing monetary donations may do so on our Open Collective page. Donations made on Open Collective are made to a community fund which supports the developers and community of OSP. Funds donated and spend through Open Collective are transparent and viewable by the public.

Donations can be made at https://opencollective.com/open-streaming-platform

Git Branch Format

OSP’s Git Branches are setup in the following configuration

  • master - Current Release Branch

  • release/(Version) - Previous Official Releases

  • development - Current Semi-Stable Test Branch for OSP vNext

  • nightly - Current Nightly Test Branch for OSP vNext

  • feature/(Name) - In-progress Feature Builds to be merged with the Development Branch

Attribution

Dependancies

Open Streaming Platform uses a number of open source projects to work properly:

  • Python 3

  • Gunicorn - Python WSGI HTTP Server, Acts as a Reverse Proxy for Flask

  • Flask - Microframework for Python based on Werkzeug & Jinja 2

  • Flask SQL-Alchemy - Provide the Database for OSP

  • Flask Security-Too - Handle User Accounts, Login, and Registration

  • Flask Uploads - Manage User Uploads, such as Pictures

  • Dropzone.js - Handing Upload Chunking for Videos

  • Flask-RestX - Handling and Documentation of the OSP API

  • Flask-Markdown - Displaying Markdown in Jinja2 Templates

  • Easy-MDE - Markdown Interface for TextAreas

  • Bootstrap - For Building responsive, mobile-first projects on the web

  • Bootstrap-Toggle - Used to Build Toggle Buttons with Bootstrap

  • NGINX - Open-Source, high-performance HTTP server and reverse proxy

  • NGINX-RTMP-Module - NGINX Module for RTMP/HLS/MPEG-DASH live streaming

  • Socket.io - Real-Time Communications Engine Between Client and Server

  • Flask Socket.io - Interface Socket.io with Flask

  • Video.js - Handles the HTML5 Video Playback of HLS video streams and MP4 Files

  • Font Awesome - Interface Icons and Such

  • Animista - Awesome CSS Animation Generator

  • List.js - Handling List Sorting and Pagination

  • Authlib - OAuth 2 Client connection handling

  • BrowserStack - Awesome service for Cross-Platform testing and supporting the Open Source Community

  • EjabberD - XMPP Chat Server for OSP

  • Strophe.js - XMPP Javascript Interface used as the base for the OSP Chat Client

Other Thanks

  • @curldev on Discord for the amazing logo!

  • All the great contributors on Open Collective (https://opencollective.com/open-streaming-platform)! We couldn’t do this without you!

  • The great community in the Discord channel for throwing ideas out and helping find bugs!

Installation

Requirements

OSP has been verified to work with the following requirements

  • Ubuntu 20.04 or later, Debian 10 or later

  • Python 3.8 or later

  • MySQL 5.7.7 or later, or MariaDB > 10.1, if not using SQLite

  • SMTP Mail Server for Email Address Validation and Subscriptions

  • FFMPEG 4 or greater

  • Dual Core Processor at 2.4 Ghz

  • 4 GB RAM

  • 120 GB HDD Storage

  • Upstream Bandwidth > 35Mbps for 720p/30fps Streams to 10 people @ 3500kbps bit rate


Install Open Streaming Platform

Script Install - Single Server (OSP-Core, OSP-RTMP, Ejabberd, Redis, MySQL)

  1. Clone the git repository

git clone https://gitlab.com/Deamos/flask-nginx-rtmp-manager.git
  1. Install the Config Tool Prerequisites (if not already installed)

sudo apt-get install dialog
  1. Run the OSP Configuration Tool

cd flask-nginx-rtmp-manager
sudo bash osp-config.sh
  1. Select Option 1 - “Install…”

  2. Select Option 1 - “Install OSP - Single Server”

  3. During the install process, the Config Tool will ask for an Ejabberd Full Qualified Domain Name (FQDN). This should be the same as the public domain name which will be used to access OSP. This should be a valid DNS entry as it is used to configure Ejabberd’s Chat Domain and by default is used by the chat client to connect users to the XMPP chat system. IP addresses may not function properly.

  4. On completion, exit the OSP Config Tool.

  5. Review the values in the OSP /opt/osp/conf/config.py.

NOTE: secretKey and passwordSalt should be changed from their default values.

sudo nano /opt/osp/conf/config.py
  1. Restart the OSP Core Workers

sudo systemctl restart osp.target

To test streaming on the server, see the “Testing OSP server” section of the Streaming page.

Script Install - Split Server Install - OSP Components on Different Servers

Starting with OSP version 0.8.0, OSP components can be split over multiple servers. This helps with spreading the load required for a busy OSP install with many viewers. In addition, splitting the components can be useful to set up load balancing by having multiple copies of the component and using a load balancer, such as HAproxy. To perform a Split Server Setup, please review the following requirements:

  • Componentaization - Multiple components can be installed on a single server to reduce cost. Doing so can also prevent needing some of the considerations in this list. For Example, if you consolidate OSP-Core and OSP-RTMP and do not require OSP-Edge Servers, you will not need Centralized storage as they

  • Centralized Storage - OSP requires some form of mounted centralized storage for Videos, Clips, & Stream/Video Thumbnails. This can be accomplished easily by using an S3-based storage bucket and using s3fs to mount the bucket to the servers file systems. Another method would be a NFS mount in the require location. Below is the required drive mounts and locations

  • Mounts

    • /var/www/videos - OSP-Core, OSP-RTMP

    • /var/www/stream-thumb - OSP-Core, OSP-RTMP

    • /var/www/images - OSP-Core

  • SSL/TLS - If OSP Core systems use HTTPS with SSL/TLS certificates, certificates will also be needed for the Ejabberd, Edge, Proxy, or OSP-RTMP (Only if using Proxy) Servers to prevent issues with HTTP(s) mixed content.

  • MySQL & Redis - the OSP Config Tool does not have an option for MySQL and Redis installs. It is recommended to be familar with their install and configuration prior to a Split Server Install In some instances, some services can be co-located on the same server. See rules below:

  • OSP-Core, OSP-RTMP, Redis, ejabberd, and Database can exist on the same server

  • OSP-Edge can not exist on the same server as OSP-RTMP

  • OSP-Proxy can not exist on the same server as OSP-Edge, OSP-Core, OSP-RTMP, or ejabberd

Centralized Storage Mounting (Use with OSP-Core and OSP-RTMP)

These instructions are intended to be used after the OSP-Core and OSP-RTMP install processes. After installing the OSP components, it is recommended to determine and establish a central storage server setup on completion of component deployment. Due to the many possible configurations of using central, shared storage, it is impossible to cover a “best” method for doing so. For the purposes of this documentation, it is assumed that an S3-compatable bucket will be used and mounting is covered below using s3fs. DO NOT USE s3fs 1.86-1. A critical bug in caching can lead to mount failure of the s3 bucket, leading to loss of recordings. Currently the latest Ubuntu LTS (20.04) only has this version of s3fs available.

  1. Install s3fs

sudo apt-get update && sudo apt-get install s3fs
  1. Create a password file. This will contain the S3 key and secret token:

echo S3KEY:S3TOKEN > ~/.passwd-s3fs
  1. Set the permissions to secure the file

chmod 600 ~/.passwd-s3fs
  1. Edit the Fuse Configurations to allow access by non-root users to files

sudo nano /etc/fuse.conf
  1. Comment out the following line user_allow_other

  2. Identify and write down the uid and gid of the www-data user. Example: uid=33(www-data) gid=33(www-data) groups=33(www-data)

sudo -u www-data id
  1. Create the required stub locations:

sudo mkdir -p /var/www/videos
sudo mkdir -p /var/www/images
sudo mkdir -p /var/www/stream-thumb
  1. Mount the directories to the S3-compatible bucket using your S3 Credentials and the identified UID & GID frm Step 6

s3fs <space_name> /var/www/videos -o url=<s3 endpoint> -o use_cache=/tmp -o allow_other -o use_path_request_style -o uid=<UID> -o gid=<GID>
s3fs <space_name> /var/www/images -o url=<s3 endpoint> -o use_cache=/tmp -o allow_other -o use_path_request_style -o uid=<UID> -o gid=<GID>
s3fs <space_name> /var/www/stream-thumb -o url=<s3 endpoint> -o use_cache=/tmp -o allow_other -o use_path_request_style -o uid=<UID> -o gid=<GID>
  1. Verify the Mount was successful. The buckets should show as a s3fs mount at the bottom of the output

mount

Note: To mount persistently, you can add the following to your fstab file

s3fs#<bucket_name> /var/www/images fuse url=<endpoint_url>,use_cache=/tmp,allow_other,use_path_request_style,_netdev,uid=33,gid=33 0 0
Ejabberd
  1. Clone the git repository

git clone https://gitlab.com/Deamos/flask-nginx-rtmp-manager.git
  1. Install the Config Tool Prerequisites (if not already installed)

sudo apt-get install dialog
  1. Run the OSP Configuration Tool

cd flask-nginx-rtmp-manager
sudo bash osp-config.sh
  1. Select Option 1 - “Install…”

  2. Select Option 6 - “Install Ejabberd”

  3. During the install process, the Config Tool will ask for an Ejabberd Full Qualified Domain Name (FQDN). This should be the same as the public domain name which will be used to access OSP. This should be a valid DNS entry. Use of an IP address may not function properly.

  4. On completion, exit the OSP Config Tool.

  5. Setup a new Ejabberd admin account.

sudo /usr/local/ejabberd/bin/ejabberdctl register admin localhost <password>
  1. Edit the ejabberd.yml

sudo nano /usr/local/ejabberd/conf/ejabberd.yml
  1. Change the following lines to match your expected configuration:

  • Line 43-44

port: 5443
ip: "::"
  • Line 55-56

port: 5280
ip: "::"
  • Line 77-78

port: 4560
ip: "::"
  • Line 91-93 (Add one line per OSP core or use CIDR Notation to allow a block of IPs)

ip:
- 127.0.0.0/8
- ::1/128
- <ip address of OSP Core>
  1. Save the ejabberd.yml file

  2. Edit the auth_osp.py Authentication Handler

sudo nano /usr/local/ejabberd/conf/auth_osp.py
  1. Edit the protocol and ospAPIServer variables to match your OSP Core Instance.

protocol = "https"
ospAPIServer = "osp.example.com"
  1. Save the auth_osp.py file

  2. Restart Ejabberd

sudo systemctl restart ejabberd
Redis
  1. Install Redis

sudo apt update
sudo apt install redis-server
  1. Edit the redis.conf file

sudo nano /etc/redis/redis.conf
  1. Find & Edit the bind location to listen on all interfaces

bind 0.0.0.0
  1. Find and Set a Redis Password

requirepass <Password>
  1. Save the redis.conf file

  2. Restart Redis

sudo systemctl restart redis.service
Database
  1. Install MariaDB

sudo apt-get update && sudo apt-get install mariadb-server
  1. Download the OSP Modifications for MariaDB

sudo wget "https://gitlab.com/Deamos/flask-nginx-rtmp-manager/-/raw/master/setup/mysql/mysqld.cnf" -O /etc/mysql/my.cnf
  1. Edit the my.cnf file

sudo nano /etc/mysql/my.cnf
  1. Edit the bind-bind address to listen on all interfaces

bind-address = 0.0.0.0
  1. Restart MariaDB

sudo systemctl restart mysql
  1. Log into MariaDB

sudo mysql
  1. Create the Database & User. Be aware the remote server ips should be the IP address(es) of the OSP-Core Systems (See https://mariadb.com/kb/en/configuring-mariadb-for-remote-client-access/#granting-user-connections-from-remote-hosts)

CREATE DATABASE osp;
CREATE USER '<username>'@'<remote_server_ip>' IDENTIFIED BY '<password>';
GRANT ALL PRIVILEGES ON osp.* TO '<username>'@'<remote_server_ip>';
  1. Quit the MariaDB Console

quit;
  1. The Database will be initialized on the successful run of an OSP-Core Instance

OSP-Core
  1. Clone the git repository

git clone https://gitlab.com/Deamos/flask-nginx-rtmp-manager.git
  1. Install the Config Tool Prerequisites (if not already installed)

sudo apt-get install dialog
  1. Run the OSP Configuration Tool

cd flask-nginx-rtmp-manager
sudo bash osp-config.sh
  1. Select Option 1 - “Install…”

  2. Select Option 2 - “Install OSP-Core”

  3. On completion, exit the OSP Config Tool.

  4. Copy the OSP config.py.dist file to config.py

sudo cp /opt/osp/conf/config.py.dist /opt/osp/conf/config.py
  1. Edit the config.py file

sudo nano /opt/osp/conf/config.py
  1. Change the dbLocation variable to match your database credentials and IP/DNS

dbLocation = 'mysql+pymysql://<user>:<password>@<db_host>/<db_name>?charset=utf8mb4'
  1. Change the Redis variables to match the IP/DNS and password set for it

redisHost="redis.example.com"
redisPort=6379
redisPassword="redis_password"
  1. Change the Ejabberd variables to match your configuration

ejabberdAdmin = "admin" <--Leave this as admin
ejabberdPass = "ejabberd_admin_password"
ejabberdHost = "localhost" <--Leave this as localhost
ejabberdServer ="ejabberd.example.com"
  1. Review the values in the OSP /opt/osp/conf/config.py.

NOTE: secretKey and passwordSalt should be changed from their default values.

sudo nano /opt/osp/conf/config.py
  1. Restart the OSP Core Workers

sudo systemctl restart osp.target
  1. Save the config.py file

  2. Initialize the Database by running the command line upgrader

sudo bash osp-config.sh upgrade db
  1. Open a web browser and browse to: http://<OSPCore IP Address or DNS>

  2. Setup OSP using the Initial Configuration Wizard

OSP-RTMP
  1. Clone the git repository

git clone https://gitlab.com/Deamos/flask-nginx-rtmp-manager.git
  1. Install the Config Tool Prerequisites (if not already installed)

sudo apt-get install dialog
  1. Run the OSP Configuration Tool

cd flask-nginx-rtmp-manager
sudo bash osp-config.sh
  1. Select Option 1 - “Install…”

  2. Select Option 3 - “Install OSP-RTMP”

  3. On completion, exit the OSP Config Tool.

  4. Copy and Edit the OSP-RTMP config.py file

sudo cp /opt/osp-rtmp/conf/config.py.dist /opt/osp-rtmp/conf/config.py
sudo nano /opt/osp-rtmp/conf/config.py
  1. Change the ospCoreAPI Variable to point at your OSP-Core instance

ospCoreAPI = "http://ospcore.example.com"
  1. Start the OSP-RTMP Instance

sudo systemctl start osp-rtmp
  1. Open a web browser and go to your OSP-Core Instance

http://ospcore.example.com
  1. Log on as an Admin and Open the Admin Settings

  2. Select RTMP Servers

  3. Click the Plus Sign Button

  4. Type in the IP or Fully Qualified Domain Name for your OSP-RTMP Server and click Add

OSP-Edge
  1. Clone the git repository

git clone https://gitlab.com/Deamos/flask-nginx-rtmp-manager.git
  1. Install the Config Tool Prerequisites (if not already installed)

sudo apt-get install dialog
  1. Run the OSP Configuration Tool

cd flask-nginx-rtmp-manager
sudo bash osp-config.sh
  1. Select Option 1 - “Install…”

  2. Select Option 4 - “Install OSP-Edge”

  3. When prompted, input the IP address of your OSP-RTMP Instance

  4. On completion, exit the OSP Config Tool.

  5. If you need to add additional authorized OSP-RTMP Instances, edit the osp-edge-rtmp.conf file for Nginx

sudo nano /usr/local/nginx/conf/services/osp-edge-rtmp.conf
  1. Add any additional authorize publishing IPs to stream-data and stream-data-adapt:

allow publish <IP Address>;
  1. Restart Nginx

sudo systemctl restart nginx-osp
  1. Open a web browser and go to your OSP-Core Instance

http://ospcore.example.com
  1. Log on as an Admin and Open the Admin Settings

  2. Select Edge Streamers

  3. Add the Fully Qualified Domain Name or IP Address of the Edge Server

  4. Add the Load Percentage that the Edge Server will use.

NOTE: The sum of all Edge Servers must equal 100%.

  1. Restart Nginx on all OSP-Core Servers

sudo systemctl restart nginx-osp
OSP-Proxy
  1. Clone the git repository

git clone https://gitlab.com/Deamos/flask-nginx-rtmp-manager.git
  1. Install the Config Tool Prerequisites (if not already installed)

sudo apt-get install dialog
  1. Run the OSP Configuration Tool

cd flask-nginx-rtmp-manager
sudo bash osp-config.sh
  1. Select Option 1 - “Install…”

  2. Select Option 5 - “Install OSP-Proxy”

  3. When prompted, input the Protocol and Fully Qualified Domain Name of your OSP-Core Instance (ex: https://osp.example.com)

  4. On completion, exit the OSP Config Tool.

  5. If you are using TLS/SSL on your Core Site, Acquire a TLS Certificate

  6. Edit /usr/local/nginx/conf/custom/osp-proxy-custom-servers.conf

sudo nano /usr/local/nginx/conf/custom/osp-proxy-custom-servers.conf
  1. Change Line 8 to match your OSP Core FQDN

valid_referers server_names osp.example.com ~.;
  1. If you are using TLS, Comment the following Line: listen 80 default_server;

  2. Uncomment the following lines and add the TLS configuration:

# listen 443 ssl http2 default_server;
# ssl_certificate /etc/letsencrypt/live/osp.example.com/fullchain.pem;
# ssl_certificate_key /etc/letsencrypt/live/osp.example.com/privkey.pem;
# ssl_protocols TLSv1.2 TLSv1.3;
  1. Edit the OSP-Proxy Configuration File

sudo nano /opt/osp-proxy/conf/config.py
  1. Change the Flask Secret Key to a Random Value

# Flask Secret Key
secretKey="CHANGEME"
  1. If you are dedicating the proxy to a specific source (An Edge or Another Proxy), uncomment the ForceDestination Lines and set to match your source

# Force Destination - Use to point to Specified Edge Server or Tiered Proxy. Uncomment to override API's RTMP List and use the destination you list
forceDestination = "edge.example.com"
forceDestinationType = "edge" # Choices are "edge", "proxy"
  1. Restart Nginx-OSP and OSP-Proxy

sudo systemctl restart nginx-osp
sudo systemctl restart osp-proxy
  1. Ensure all Edge or RTMP Servers are listed in the OSP-Core Admin Panel. OSP-Proxy will query the OSP API and generate configurations to handle the proxy connection to retrieve the HLS fragments.

  2. Perform a first run of the Configuration File Generator

cd /opt/osp
sudo bash updateUpstream.sh
  1. Connect to each OSP-RTMP/Single Server and perform the following on each:

  • If using TLS on the Core, Generate a TLS certificate

  • Edit the /usr/local/nginx/conf/custom/osp-rtmp-custom-authorizeproxy.conf

sudo nano /usr/local/nginx/conf/custom/osp-rtmp-custom-authorizeproxy.conf
  • Add the IP Address of each OSP-Proxy that will be accessing the source for /stream-thumb, /live-adapt, and /live:

# allow <ip of proxy>;
allow 201.13.12.50;
allow 193.10.3.9;
  • If using TLS, Edit the /usr/local/nginx/conf/custom/osp-rtmp-custom-server

sudo nano /usr/local/nginx/conf/custom/osp-rtmp-custom-server
  • Comment out the first line, uncomment the TLS information and add your certificate info (Note: Port 5999 will stay the same):

#listen 5999 default_server;
### Comment Above and Uncomment/Edit Below for OSP-Proxy TLS ###
listen 5999 ssl http2 default_server;
ssl_certificate /etc/letsencrypt/live/osp.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/osp.example.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
  • Restart the Nginx-OSP instance

sudo systemctl restart nginx-osp
  1. If you forced an Edge Server on Step 14, Connect to the Edge Server and edit /usr/local/nginx/conf/locations/osp-edge-redirects.conf

sudo nano /usr/local/nginx/conf/custom/osp-edge-redirects.conf
  • Comment the add_headers line for /edge and /edge-adapt

#add_header 'Access-Control-Allow-Origin' "*" always;
  • Edit the custom referes file at /usr/local/nginx/conf/custom/osp-edge-custom-refer.conf

sudo nano /usr/local/nginx/conf/custom/osp-edge-custom-refer.conf
  • Add the OSP Core Server to the Valid Referers list for /edge and /edge-adapt

valid_referers server_names osp.example.com ~.;
  • Restart Nginx-OSP

sudo systemctl restart nginx-osp
  1. Add the OSP-Proxy Domain to the OSP-Core’s Admin Panel under Settings

  2. Test a Stream and verify that the video is displaying


Manual Install

Coming Soon


Docker Install

A Dockerfile has been provided for running OSP in a container. However due to the way NginX, Gunicorn, Flask, and Docker work, for OSP to work properly, the Frontend must be exposed using Port 80 or 443 and the RTSP port from OBS or other streaming software must be exposed on Port 1935. This accomplished easily by using a reverse proxy in Docker such as Traefik. However, Port 1935 will not be proxied and must be mapped to the same port on the host. An external Redis server/container is required to handling asynchronous communications between the internal Gunicorn worker instances.

Docker-Compose

The recommended method for OSP Deployment in Docker is to use the provided docker-compose.yml file which can be found here: https://gitlab.com/osp-group/open-streaming-platform-docker/-/blob/master/docker-compose.yml
If you prefer pre-built containers you don’t have to clone the whole repository to set up all needed containers, just edit docker-compose.yml and change the build lines to the already provided image ones by removing/adding # in front of those accordingly. Before running docker-compose up make sure you edit all environment variables accordingly as it is a requirement to set those beforehand! There are multiple similar ones for each container which all need to be set to the exact same value for the setup process to run through smoothly, simply search/replace those for a faster workflow.

Docker Hub URLs
Environment Variables

Remember to set the required variables according to the comments inside the docker-compose.yml file before running docker-compose up! Else you may misconfigure those containers and need to start from scratch!

OSP-Core
  • OSP_SERVER_ADDRESS FQDN of the OSP Domain

  • OSP_REDIS_HOST Domain/IP of Redis Server

  • OSP_REDIS_PORT Redis Server Port

  • OSP_REDIS_PASSWORD Redis Password, if used

  • OSP_CORE_DB Database Connection string

    • ex: mysql+pymysql://\<DB User\>:\<DB Password>@\<DB Server>/osp

  • OSP_CORE_SECRETKEY Flask Secret Key (Should be Random Value)

  • OSP_CORE_PASSWORD_SALT User DB Salt Value (Should be Random Value)

  • OSP_CORE_ALLOWREGISTRATION Allow Users to Register (Bool)

  • OSP_CORE_REQUIREEMAILREGISTRATION Require Email Validation (Bool)

  • OSP_EJABBERD_PASSWORD EJabberd Admin Password

  • OSP_EJABBERD_RPCHOST Ejabberd XML-RPC FQDN/IP (OSP-Core -> Ejabberd)

  • OSP_EJABBERD_BOSHDOMAIN Ejabberd BOSH-HTTP FQDN/IP (Users -> Ejabberd)

  • OSP_SMTP_SENDAS SMTP Emails Send As Email Address

    • ex: noreply@email.com

  • OSP_SMTP_SERVERADDRESS SMTP Server Address

  • OSP_SMTP_SERVERPORT SMTP Server Port

  • OSP_SMTP_ENCRYPTION SMTP Encryption Type [none | ssl | tls]

  • OSP_SMTP_USERNAME SMTP Authentication Username

  • OSP_SMTP_PASSWORD SMTP Authentication Password

  • OSP_RTMP_SERVER Initial OSP-RTMP Server FQDN

    • Adds an RTMP Server to the OSP Configuration

  • OSP_CORE_TYPE Sets the type of OSP-Core Deployment [core | celery | beat]

    • If not defined, defaults to core

OSP-RTMP
  • OSP_API_HOST Protocol and Domain for OSP API

    • ex: http://osp.example.com

  • OSP_RTMP_SECRETKEY Flask Secret Key (Should be Random Value)

OSP-Ejabberd
  • EJABBERD_XMLRPC_ALLOWIP XML-RPC Allowed IP Addresses

  • EJABBERD_PASSWORD Ejabberd Admin Password

  • EJABBERD_DOMAIN OSP Instance Wide Domain. This should be the same as your OSP Instance Public FQDN

  • OSP_API_PROTOCOL Protocol for accessing the OSP API [http | https]

  • OSP_API_DOMAIN Public FQDN for Accessing the OSP API. This should be the same as your OSP Public FQDN


Database Setup

Installation

Set Up MySQL

Prior to using MySQL with OSP the first time, do the following to configure OSP for full Unicode Support (UTF8MB4)

  1. Install MySQL Server on Database Server or OSP Server

sudo apt-get install mysql-server
  1. Copy the MySQL Configuration File in to MySQL

sudo cp /opt/osp/setup/mysql/mysqld.cnf /etc/mysql/my.cnf
  1. Restart MySQL

sudo systemctl restart mysql
  1. Open MySQL and create the OSP Database and User

sudo mysql
CREATE DATABASE osp;
CREATE USER 'newuser'@'localhost' IDENTIFIED BY 'password';
GRANT ALL PRIVILEGES ON osp.* TO 'newuser'@'localhost';
  1. Edit the OSP Configuration File to use MySQL

sudo vi /opt/osp/conf/config.py

From:

dbLocation="sqlite:///db/database.db"

To:

dbLocation = 'mysql+pymysql://username:password@localhost/osp?charset=utf8mb4'
  1. Restart OSP

sudo systemctl restart osp.target

Note: For Servers that have upgraded from versions prior to Beta 6, see Installation > Tweaks > Database on the sidebar to convert from UTF8 to UTF8MB4 for Full Unicode Support

Backup and Restore

Backup

System backups can be performed via making a backup copy of the /opt/osp/conf/config.py file and taking a SQL dump of the database using a tool like mysqldump

sudo mysqldump --databases osp > dump.sql
Restore
  1. Copy the backup config.py file to /opt/osp/conf

  2. Restore the SQL backup taken

mysql < dump.sql

Migration

Moving from UTF8 to UTF8MB4 in MySQL

Installs prior to Beta 6 were not configured to fully use UTF8MB4 and may not be able to use the full Unicode set. To correct this issue, do the following:

  1. Backup your existing Database per the proceedures above.

  2. Shut down OSP

sudo systemctl stop osp.target
  1. Open the MySQL Console

sudo mysql
  1. Drop the OSP Database;

drop database osp;
  1. Exit the MySQL Console

quit;
  1. Follow the steps for Setting up a New MySQL install, starting at Step 2

  2. On the Insital Setup Wizard, Restore your Database Per the Steps under Restore Above.


Chat (XMPP)

Beginning with OSP v0.7.0, Chat has been moved to an XMPP based system using ejabberd. Channel chatrooms now maintain a temporary history and can be accessed by Guests, if configured.

Installation

Single Server

By default, OSP will automatically install and configure XMPP components for use during install or upgrade to versions 0.7.0 or above. During the upgrade process, you will be prompted to enter the OSP Site Address. This address must match the OSP Site Address (Typically the OSP Fully Qualified Domain Name (FQDN) or IP Address of OSP) Failure to enter the correct address will cause the Chat system to not function properly. If you must change your OSP Site Address, this change must also be made to the ejabberd.yml configuration file and ejabberd restarted. You can find the ejabberd.yml file in /usr/local/ejabberd/conf/ejabberd.yml and edit the following lines: Line 17-19

hosts:
- localhost
- CHANGEME <---Your OSP Site Address

Line 167-173

host_config:
"CHANGEME": <---Your OSP Site Address
auth_method:
- external
- anonymous
allow_multiple_connections: true
anonymous_protocol: login_anon
sudo systemctl restart ejabberd

OSP will also automatically set the ownership for each created OSP Channel and set the Channel Owner to Admin/Owner for the XMPP channel on start of the OSP service. If you have an issue with ownership, it is recommended to restart OSP to perform an XMPP Rebuild.

External Server

Supported on versions >= 0.7.9 {.is-info} Ejabberd can be configured to run an an external service. However, some manual changes must be made to allow it to operate with OSP properly. To setup an external ejabberd server, do the following:

  1. Install ejabberd on a separate server

sudo wget -O "/tmp/ejabberd-20.04-linux-x64.run" "https://www.process-one.net/downloads/downloads-action.php?file=/20.04/ejabberd-20.04-linux-x64.run"
chmod +x /tmp/ejabberd-20.04-linux-x64.run
/tmp/ejabberd-20.04-linux-x64.run ----unattendedmodeui none --mode unattended --prefix /usr/local/ejabberd --cluster 0
  1. Create the conf directory and copy the ejabberd configuration yml, inetrc, and auth_osp.py from the OSP Repo to the directory

sudo mkdir /usr/local/ejabberd/conf
wget -O "/usr/local/ejabberd/conf/ejabberd.yml" "https://gitlab.com/osp-group/flask-nginx-rtmp-manager/-/raw/master/installs/ejabberd/setup/ejabberd.yml"
wget -O "/usr/local/ejabberd/conf/inetrc" "https://gitlab.com/osp-group/flask-nginx-rtmp-manager/-/raw/master/installs/ejabberd/setup/inetrc"
wget -O "/usr/local/ejabberd/conf/auth_osp.py" "https://gitlab.com/osp-group/flask-nginx-rtmp-manager/-/raw/master/installs/ejabberd/setup/auth_osp.py"
  1. Edit the /usr/local/ejabberd/conf/ejabberd.yml file and update the fields based on your configuration Line 17-19: Set CHANGEME to your OSP’s FQDN

hosts:
- localhost
- OSP.example.com

Line 43-53: Change ip to “::”

port: 5443
ip: "::"
module: ejabberd_http
tls: true
request_handlers:
/admin: ejabberd_web_admin
/api: mod_http_api
/bosh: mod_bosh
/captcha: ejabberd_captcha
/upload: mod_http_upload
/ws: ejabberd_http_ws

Line 55-65: Change ip to “::”

port: 5280
ip: "::"
module: ejabberd_http
request_handlers:
/admin: ejabberd_web_admin
/api: mod_http_api
/bosh: mod_bosh
/captcha: ejabberd_captcha
/upload: mod_http_upload
/ws: ejabberd_http_ws
/.well-known/acme-challenge: ejabberd_acme

Line 77-83: Change ip to “::”

port: 4560
ip: "::"
module: ejabberd_xmlrpc
access_commands:
admin:
commands: all
options: []

Line 87-96: Add the IP Address to your OSP Instances in the ip block

acl:
local:
user_regexp: ""
loopback:
ip:
- 127.0.0.0/8
- ::1/128
- YOUR OSP IP HERE
admin:
user:
- "admin@localhost"

Line 164: Change the location of the auth_osp.py file to match below

extauth_program: "/usr/bin/python3 /usr/local/ejabberd/conf/auth_osp.py"

Line 167-173: Set CHANGEME to your OSP’s FQDN

host_config:
"OSP.example.com":
auth_method:
- external
- anonymous
allow_multiple_connections: true
anonymous_protocol: login_anon
  1. Install Python Requirements

sudo apt-get install python3-pip
sudo pip3 install requests
  1. Edit the /usr/local/ejabberd/conf/auth_osp.py file Line 4-5: Change the protocol and ospAPIServer values to match your OSP Instance

protocol = "http"
ospAPIServer = "OSP.example.com"
  1. Copy the ejabberd SystemD file

sudo cp /usr/local/ejabberd/bin/ejabberd.service /etc/systemd/system/ejabberd.service
sudo systemctl daemon-reload
sudo systemctl enable ejabberd
sudo systemctl start ejabberd
  1. Configure the local admin account with a password. Do not change the localadmin part

sudo /usr/local/ejabberd/bin/ejabberdctl register admin localhost YOURADMINPASSWORD
  1. Install Nginx to reverse proxy the XMPP Bosh Port

sudo apt-get install nginx
  1. Edit the default Nginx site file for the reverse proxy and add the following in the server directive block

sudo vi /etc/nginx/sites-available/default
location /http-bind/ { # BOSH XMPP-HTTP
proxy_pass http://localhost:5280/bosh;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_redirect off;
proxy_buffering off;
proxy_read_timeout 65s;
proxy_send_timeout 65s;
keepalive_timeout 65s;
tcp_nodelay on;
}
  1. Restart the Nginx Service

sudo systemctl restart nginx
  1. On the OSP Server, update the ejabberd admin password and add the ejabberdServer variable to the /opt/osp/conf/config.py file

sudo vi /opt/osp/conf/config.py
# EJabberD Configuration
ejabberdAdmin = "admin"
ejabberdPass = "YOURADMINPASSWORD"
ejabberdHost = "localhost"
ejabberdServer = "ejabberd.example.com"
  1. Restart the OSP Server

sudo systemctl restart osp.target

Network Configuration

OSP’s XMPP configuration requires the following open ports for chat to function:

  • TCP/5222: Used for ejabberd Client to Server connections

  • TCP/5269: Used for ejabberd Server to Server connections

  • TCP/5443: External Server Jabber HTTPS-BOSH connection External Server Only

  • TCP/5280: External Server Jabber HTTP-BOSH connection External Server Only

  • TCP/4560: External Server XML-RPC Server Control External Server Only

OSP Configuration

XMPP Channels are configured on a channel by channel basis. You can find the settings under My Channels -> Chat Channel configuration allows you to define who is allowed to chat, how chat is managed, and who can manage it.

  • Room Title: Name of Room, displayed to XMPP Chat Clients

  • Description: Room description, displayed to XMPP Chat Clients

  • Chat message format: Changes the appearance of chat messages.

    • Messenger: Separates every message into it’s own “bubble”.
      Chat Message Format - Messenger

    • IRC: A more Twitch-Like experience.
      Chat Message Format - IRC

  • Moderated: Only Users Identified as Participants may Chat

  • Allow guests to join room: Allow Unauthenticated Guest Users to Join the Chat

  • Allow guests to chat: Automatically set Unauthenticated Guest Users as Participants.

  • Allow guests to set their Nickname: Allows and asks Unauthenticated Guest Users to set a Nickname.

  • Show join and part messages: Shows in chat when Users connect and disconnect from the Chat.

  • Chat history: How long chat messages should be displayed in the Web Chat. (Does not affect 3rd Party Clients! Restart ejabberd to clear history!)

  • Moderators: Add and Remove Chat Moderators from this Channel.

  • Chat Stickers: Upload and Manage stickers (essentially custom emojis) for this channel. The OSP Instance Admin can also define Global Stickers which will show up on all channels.

Usage

The Chat Window is a basic display of conversations and moderation controls for users and admins. You can view who is in a channel, view their profile, or control basic functions such as ban lists or channel roles.
Chat

All users are set as one the following roles:

  • Moderator: Able to control the room and has access to all moderator controls

  • Participant: Able to Chat in the room (ie: has voice)

  • Guest: Able to view Chat in the room, but can not chat. Any role changes made by a moderator are set as permanent and will remain on joining / leaving a room.

User Options

By clicking on a username in chat or in the User List, users and moderators are displayed options targeting that user.
Chat User

User Controls

  • Profile: Opens a Popup that displays the User’s Bio and any Channels, Streams, Videos, or Clips they may own.

  • Mute: Hides all chat from a user for your account. You will no longer see any messages from the user until you unmute them.
    Chat User - Mod Controls

Mod Controls

  • Kick: Removes the user from the chatroom.

  • Ban: Removes the user from the chatroom and flags their username as banned.

  • Change Role / Set as Moderator: Sets the User to have Moderator Controls

  • Change Role / Set as Participant: Sets the User to be a Participant (Able to Chat if Channel is set to Moderated)

  • Change Role / Set as Guest: Sets the User to be a Guest (Can’t Chat if Channel is set to Moderated)

  • Channel Voice Controls / Voice: Temporarily grants Participant Status

  • Channel Voice Controls / Devoice: Temporarily removes Participant Status

Authentication

Each User maintains a XMPP username and password which is required to authenticate to the Chat Server. This is handled by OSP by default, but the login info can also be used to authenticate using an XMPP client. To find you XMPP login info, you can go to your user settings and copy the XMPP username and password at the top.
XMPP Username and Password
In addition to user specific XMPP login info, each channel also maintains a XMPP token to be used when a Channel is set to be protected. In these instances, users may use the Channel XMPP Token to join the Chatroom using an external client.
Protected Channel XMPP Token

Two Way Integration with Other Chat Clients

(Provided by djetaine on Discord)

Using Matterbridge, you can integrate your OSP Instance with multiple chat clients like Discord, IRC, Twitch, Telegram, etc. Each platform should have its own “Bot” relay account that you will need to create. For additional information and configuration instructions visit the Matterbridge Wiki directly.

Installation - OSP

To facilitate certificate retrieval through the default nginx conf file will need to be modified. If you cannot connect after you finish the installation, look at the ejabberd logs. In some instances you will need to manually create your cert files which can be done using the instructions under “Troubleshooting” Create a backup folder and make a copy of your conf file

mkdir ~/backups
cp /usr/local/nginx/conf/nginx.conf ~/backups/nginx.conf

Open an editor to modify your conf

nano /usr/local/nginx/conf/nginx.conf

Add the following to your nginx conf file below the 443 server block

##Allow for ejabberd acme-challenge
server {
listen 80;
server_name conference.subdomain.domain.tld;
location / {
proxy_pass http://localhost:5280;
}
}
server {
listen 80;
server_name proxy.subdomain.domain.tld;
location / {
proxy_pass http://localhost:5280;
}
}
server {
listen 80;
server_name pubsub.subdomain.domain.tld;
location / {
proxy_pass http://localhost:5280;
}
}

Create DNS Records on your domain registrar for each of the subdomains required by ejabberd. proxy.subdomain, pubsub.subdomain, conference.subdomain Perform an nslookup or ping to very name resolution, restart osp and ejabberd then verify connectivity

sudo systemctl restart osp.target
sudo systemctl restart ejabberd
cat /usr/local/ejabberd/logs/ejabberd.log

If the certificate retrieval was successful, you will see success messages for the certificate. Don’t worry about the local host warnings. If you see warnings for your FQDN, verify that your DNS entries are valid. Certificate Retrieval Log Outputs Allow ejabberd traffic through your firewall. If you are hosting from home, be sure to port forward to your OSP host.

sudo ufw allow 5222/tcp
sudo ufw allow 5269/tcp
sudo ufw allow 5280/tcp

You can quickly test the external connectivity with an online xmpp client like conversejs Get your xmpp username and password from your OSP profile settings page at the bottom, then login at https://conversejs.org/fullscreen.html If you can connect, move forward.

Install Matterbridge

Matterbridge will run on many different operating systems and container platforms. In this case we will focus on a digital ocean droplet running ubuntu minimal. See the github page for more information on other installations. Get your instance of ubuntu up and running Create Matterbridge user, download binaries, set permissions and create the directory

sudo adduser --system --no-create-home --group matterbridge
sudo wget https://github.com/42wim/matterbridge/releases/download/v1.22.3/matterbridge-1.22.3-linux-64bit -O /usr/bin/matterbridge
sudo chmod 755 /usr/bin/matterbridge
sudo mkdir /etc/matterbridge

You will now create your configuration file. There are a lot of integrations available but this document will focus on Twitch and Discord. More config help can be found in the Matterbridge Wiki.

For discord, you will need to create a bot and get it’s auth token.

  • Create a Discord Bot

  • Get your Server ID and Channel ID by turning on developer mode, then right clicking each to copy the ID.

For twitch, you can create a new “bot” user or user your own.

  • Login to the account you wish to use as a relay

  • Go to https://twitchapps.com/tmi to get your oauth password. You need the whole thing, including the oauth:
    Twitch Chat OAuth Password Generator Example

Open an editor to create the config

sudo nano /etc/matterbridge/matterbridge.toml

You may copy this config file entering your own settings for FQDN, token, server, etc.

[discord.mydiscord]
Token="yourDiscordBotsToken"
Server="YourServerID"
RemoteNickFormat="{PROTOCOL}-**<{NICK}>** "
[irc.twitch]
#Add the oauth token here you got from [https://twitchapps.com/tmi/](https://twitchapps.com/tmi/)
Password="oauth:SomeLettersAndNumbers"
Nick="YourTwitchBotsName"
Server="irc.twitch.tv:6667"
UseTLS=false
RemoteNickFormat="{PROTOCOL}-[{NICK}] "
[xmpp.myxmpp]
Server="fqdn.of.your.OSP.Server:5222"
#Jid your userid
Jid="OSPUserName@yourserver.tld"
Password="PasswordFromUserSettings"
Muc="conference.your.fqdn"
Nick="YourFriendlyUserName"
RemoteNickFormat="{PROTOCOL}-[{NICK}] "
[[gateway]]
name="gateway1"
enable=true
[[gateway.inout]]
account="irc.twitch"
channel="#YourTwitchChannel"
[[gateway.inout]]
account="xmpp.myxmpp"
channel="YourOSPChannelUID"
[[gateway.inout]]
account="discord.mydiscord"
channel="ChannelNameYouWantToSendTo"

Test your configuration by starting matterbridge.

/usr/bin/matterbridge -debug -conf /etc/matterbridge/matterbridge.toml

If all went well, create a service for matterbridge to run as.

sudo nano /etc/systemd/system/matterbridge.service

Paste the following and save the file

[Unit]
Description=matterbridge
After=network.target
[Service]
ExecStart=/usr/bin/matterbridge -conf /etc/matterbridge/matterbridge.toml
User=matterbridge
Group=matterbridge
[Install]
WantedBy=multi-user.target

Enable and run the service

sudo systemctl daemon-reload
sudo systemctl enable matterbridge
sudo systemctl start matterbridge

Set the service to run at startup

sudo systemctl enable matterbridge

You should now have a fully integrated chat with Twitch, OSP and Discord.

Troubleshooting

The two files that will be most important are the ejabberd log and the debug of the matterbridge service. OSP Server

/usr/local/ejabberd/logs/ejabberd.log

Matterbridge Server re-run the matterbridge application with the -debug flag

/usr/bin/matterbridge -debug -conf /etc/matterbridge/matterbridge.toml

Manually configuring certificates if auto creation is not functioning

If the automated acme-challenge isnt working for one reason or another, you can create a cert and assign it manually. Run this command replacing subdomain.domain.tld with your fqdn

sudo certbot certonly --manual -d conference.subdomain.domain.tld -d proxy.subdomain.domain.tld -d pubsub.subdomain.domain.tld -d subdomain.domain.tld --agree-tos --no-bootstrap --manual-public-ip-logging-ok --preferred-challenges dns-01 --server [https://acme-v02.api.letsencrypt.org/directory](https://acme-v02.api.letsencrypt.org/directory)

Create txt records on your dns when asked. You will require a txt record for each subdomain. Combine the full chain you create with the private key

cat etc/letsencrypt/live/yoursite/privkey.pem /etc/letsencrypt/live/yoursite/fullchain.pem > ~/combined.pem

Move your newly created combined pem file to a better location (something like /etc/ssl/ejabberd) Uncomment the following lines in /usr/local/ejabberd/conf/ejabberd.yml

certfiles:

Add directly beneath

- /etc/ssl/ejabberd/combined.pem

Be SURE to line up your - /etc with the rest of the dashes in the yml file. YAML is very picky about spacing. It must tbe exact.

Let’s Encrypt Setup

The focus of this guide will be to provide an example of how to setup SSL with LetsEncrypt and Certbot. For this example we are using a default install of OSP on Ubuntu 20.04 (or 18.04) LTS

Step one, install Certbot

Install certbot (running with Nginx) as described at https://certbot.eff.org/instructions Installion of certbot in short (for most systems) works with snap as follows:

# sudo snap install core; sudo snap refresh core
# sudo snap install --classic certbot
# sudo ln -s /snap/bin/certbot /usr/bin/certbot

Verify certbot is installed:

# certbot --version
certbot 1.13.0
Create a location for certbot verification outside of the actual webroot
# mkdir /var/certbot
# chmod 755 /var/certbot

Edit the OSP nginx config to use this location for the certbot verification by adding the following lines to /usr/local/nginx/conf/nginx.conf

location /.well-known/acme-challenge {
root /var/certbot;
}

These lines should go under your port 80 server, in my config I put them right below the line “include /usr/local/nginx/conf/locations/*.conf;

# NGINX to HTTP Reverse Proxies
server {
include /usr/local/nginx/conf/custom/osp-custom-servers.conf;
# set client body size to 16M #
client_max_body_size 16M;
include /usr/local/nginx/conf/locations/*.conf;
location /.well-known/acme-challenge {
 root /var/certbot;
}
# redirect server error pages to the static page /50x.html
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
include /usr/local/nginx/conf/custom/osp-custom-serversredirect.conf;
Restart Nginx

sudo systemctl restart nginx-osp

Run certbot to request certs from LetsEncrypt
# sudo certbot certonly --webroot -w /var/certbot -d <domain>

This command will prompt you for a few pieces of information and then it will save your certs in /etc/letsencrypt/live/

- Congratulations! Your certificate and chain have been saved at:
/etc/letsencrypt/live/<domain>/fullchain.pem
Your key file has been saved at:
/etc/letsencrypt/live/<domain>/privkey.pem
Your cert will expire on <date>. To obtain a new or tweaked
version of this certificate in the future, simply run certbot
again. To non-interactively renew *all* of your certificates, run
"certbot renew"
Configure nginx-osp to use SSL and the certificates you have requested

Edit /usr/local/nginx/conf/custom/osp-custom-servers.conf and edit the section to similar to below: Remember to change your domain name and certificate location to match the step above.

#listen 80 default_server;
### Comment Above and Uncomment/Edit Below for OSP-Proxy TLS ###
listen 443 ssl http2 default_server;
ssl_certificate /etc/letsencrypt/live/osp.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/osp.example.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
Configure nginx-osp to do http to https redirect

Uncomment all lines in /usr/local/nginx/conf/custom/osp-custom-serversredirect.conf to read as follows:

server {
listen 80;
server_name _;
return 301 https://$host$request_uri;
}

Restart nginx.osp

# sudo systemctl restart nginx-osp

HAProxy Load Balancing

Pre-requisites

This guide is designed for people running OSP Split server and not single server installations. This guide assumes that you currently have a working setup with at least 1 core server. Tested working on Ubuntu 20.04 (LTS) on 2021.10.11. VPS Spec: 2GB RAM, 1 vCPU and 50GB Disk. Cloud Provider: Digital Ocean. For SSL installation your FQDN must be pointing at your HAProxy Server IP Address. To Install, do the following:

apt-get update
apt-get upgrade
apt install -y haproxy
apt install -y certbot

After installing run haproxy -v to confirm installed and working as intended. You should get an output like: HA-Proxy version 2.0.13-2ubuntu0.3 2021/08/27 - https://haproxy.org/

Setup Config File

Once the install is done you can then configure the Config file

nano /etc/haproxy/haproxy.cfg

Under the defaults section, enter the following lines, replacing words (and the dashes) with your own information.

frontend --name to define frontend http--
# Define Port to Bind To and set the mode
bind :80
bind :::80
mode http
# Used to redirect HTTP Requests to HTTPS
# http-request redirect scheme https unless { ssl_fc }
# Enable this if you want to view stats
# stats uri /haproxy?stats
# Sets the default backend for servers
default_backend --name to define below backend (MUST MATCH)--
# Certbot SSL Installation
acl is_certbot path_beg /.well-known/acme-challenge/
use_backend backend-certbot if is_certbot
#frontend --name to define frontend https--
# bind :443 ssl crt /etc/haproxy/ssl/
# bind :::443 ssl crt /etc/haproxy/ssl/
# mode http
# ACL for detecting Let's Encrypt validtion requests
# acl is_certbot path_beg /.well-known/acme-challenge/
# use_backend backend-certbot if is_certbot
# default_backend --name to define below backend (MUST MATCH)--
backend --name to define below backend (MUST MATCH ABOVE default_backed)--
mode http
balance leastconn
server --yourservername-- --server internal or public ip--:80 check inter 5s rise 3 fall 2
backend backend-certbot
server letsencrypt 127.0.0.1:9080

Once that is done run

systemctl reload haproxy

The above config will get you running with HTTP. You must make sure that the default_backend under http and https match the backend name in the non backend-certbot section or haproxy wont start. You can change the server checks yourself but the above will check each core server every 5 seconds for a response. It it fails twice it will not use that server in the balancer. If you want to be able to view your haproxy stats you can uncomment line 9 above and run

systemctl reload haproxy

You can then go to http://haproxyipaddress/fqdn/haproxy?stats or http://fqdn/haproxy?stats

SSL Setup

In order to setup SSL Using LetsEncrypt your FQDN must be pointing to the public IP address of your haproxy server. You also need to have certbot installed. Run the following, replacing mydomain.com with your FQDN and me@mydomain.com with your email address. You should get a message saying that your certificate and chain have been saved etc.

certbot certonly --standalone --preferred-challenges http --http-01-address 127.0.0.1 --http-01-port 9080 -d mydomain.com --email me@mydomain.com --agree-tos --non-interactive

We then need to combine those files into one for haproxy.

sudo nano /etc/haproxy/prepareLetsEncryptCertificates.sh

Then add the following:

#!/bin/bash
# Loop through all Let's Encrypt certificates
for CERTIFICATE in `find /etc/letsencrypt/live/* -type d`; do
CERTIFICATE=`basename $CERTIFICATE`
# Combine certificate and private key to single file
cat /etc/letsencrypt/live/$CERTIFICATE/fullchain.pem /etc/letsencrypt/live/$CERTIFICATE/privkey.pem > /etc/haproxy/ssl/$CERTIFICATE.pem
done

Create the SSL Directory

mkdir /etc/haproxy/ssl

Execute all the things!

chmod +x /etc/haproxy/prepareLetsEncryptCertificates.sh
sh /etc/haproxy/prepareLetsEncryptCertificates.sh

If the above has all gone well you should now be able to edit your haproxy config file and enable SSL by uncommenting the following lines in the config below (copied from above): Line 7 - if you want to force SSL Lines 16-19 Lines 21-23

frontend --name to define frontend http--
# Define Port to Bind To and set the mode
bind :80
bind :::80
mode http
# Used to redirect HTTP Requests to HTTPS
# http-request redirect scheme https unless { ssl_fc }
# Enable this if you want to view stats
# stats uri /haproxy?stats
# Sets the default backend for servers
default_backend --name to define below backend (MUST MATCH)--
# Certbot SSL Installation
acl is_certbot path_beg /.well-known/acme-challenge/
use_backend backend-certbot if is_certbot
#frontend --name to define frontend https--
# bind :443 ssl crt /etc/haproxy/ssl/
# bind :::443 ssl crt /etc/haproxy/ssl/
# mode http
# ACL for detecting Let's Encrypt validtion requests
# acl is_certbot path_beg /.well-known/acme-challenge/
# use_backend backend-certbot if is_certbot
# default_backend --name to define below backend (MUST MATCH)--
backend --name to define below backend (MUST MATCH ABOVE default_backed)--
mode http
balance leastconn
server --yourservername-- --server internal or public ip--:80 check inter 5s rise 3 fall 2
backend backend-certbot
server letsencrypt 127.0.0.1:9080

Automatic Certificate Renewals and File Merging

Create a script to automate the certbot renewal and then merge the files and reload haproxy.

sudo nano /etc/haproxy/renewLetsEncryptCertificates.sh

Then Add:

#!/bin/bash
certbot renew --standalone --preferred-challenges http --http-01-address 127.0.0.1 --http-01-port 9080 --post-hook "/etc/haproxy/prepareLetsEncryptCertificates.sh && systemctl reload haproxy.service" --quiet

And make it executable:

chmod +x /etc/haproxy/renewLetsEncryptCertificates.sh

Create a cronjob to get the script to check for certificate renewals and run the certificate merge:

crontab -e
0 0 * * * /bin/sh /etc/haproxy/renewLetsEncryptCertificates.sh

Job done!

Lock Down Stats Page

If you want the stats page to be active then haproxy have a good blog post on how to lock it down and also what all of the metrics mean below: https://www.haproxy.com/blog/exploring-the-haproxy-stats-page/

Upgrades

Standard Upgrade

To upgrade any version, make sure that you are on the correct branch (usually master), and follow the steps as listed below:


Versions 0.9.x to x.x.x.x

For all versions of OSP 0.9.0 and greater, the standard upgrade procedure has been changed to the following steps to prevent requiringa separate upgrade script moving forward.

Single Server Install

  1. Open the OSP Directory

cd /opt/osp
  1. Run a Git Pull to pull in the most recent code

sudo git pull
  1. Run the OSP Configuration Tool Script

sudo bash osp-config.sh
  1. Select Option 2: Upgrade…

  2. Select Option 1: Upgrade OSP - Single Server

Split Server Installs


Split Server Installs will typically not use the /opt/osp directory as the Git Repository. In these instances, it would be best to clone the OSP respository

  1. Clone the OSP Repo

git clone https://gitlab.com/osp-group/flask-nginx-rtmp-manager.git
  1. Open the Cloned Repo

cd flask-nginx-rtmp-managher
  1. Run the OSP Configuration Tool Script

sudo bash osp-config.sh
  1. Select Option 2: Upgrade…

  2. Select the Option Listed for the Component you are updating

To upgrade any version, make sure that you are on the correct branch (usually master), run osp-config.sh and select the compontent to upgrade. If further steps are required for specific versions, they are described below.


Version 0.8.x to Version 0.9.x

Due to changes made with the database upgrade structure, an update script has been made to help reset the state of the database upgrade tracking table. In the process, Nginx will also be updated so it is recommended to backup any customizations made in /usr/local/nginx/conf. This includes TLS/SSL Cert configurations.

To update to 0.9.x, perform the following:

  1. Remove the existing DB Migrations folder

sudo rm -rf /opt/osp/migrations
  1. Perform a git pull of the most recent build

sudo git pull
  1. Run the Upgrade Script

sudo bash /opt/osp/setup/upgrade/0.9.0.sh
  1. After Completion, edit /opt/osp/conf/config.py:

sudo nano /opt/osp/conf/config.py
  1. Add your SMTP Configuration to the config.py file

# Email Settings
smtpSendAs="sendAs@email.com"
smtpServerAddress="smtp.email.com"
smtpServerPort=25
smtpUsername=""
smtpPassword=""
# SMTP Encryption Options are ['none', 'tls', 'ssl']
smtpEncryption="none"
  1. Restart OSP

sudo systemctl restart osp.target

Versions < 0.8.8 to Versions > 0.8.8

Due to changes made in v0.8.8 to simplify Nginx Configurations, the upgrade to versions greater to 0.8. will require an extra step to move your server specific changes to the new setup.

Note: Prior to the upgrade, it is recommended you backup the /usr/local/nginx/conf directory to have a copy of your original settings to transpose to the new setup

Important Note: When updating, do the following to get the files into alignment: {.is-warning}

  1. Run the osp-config updater process as normal

  2. On completion, exit the osp-config updater

  3. Create the the custom directory in the /usr/local/nginx/conf folder

sudo mkdir /usr/local/nginx/conf/custom
  1. Copy the new custom files from the clone repo as listed below to /usr/local/nginx/conf/custom/:

  • OSP-Core, ejabberd, OSP-Edge, Single Servers: $Repo/installs/nginx-core/osp-custom-*.conf

  • OSP-Edge: $Repo/installs/osp-edge/setup/nginx/custom/osp-edge-custom-*.conf

  • OSP-RTMP: $Repo/installs/osp-rtmp/setup/nginx/custom/osp-rtmp-custom-*.conf

  1. Reopen the osp-config updater and run the update process a second time.

  2. Follow the instructions below to reconfigure the new custom nginx files

The following files will need to be updated for each OSP service:

  1. OSP-Core, OSP-Edge, ejabberd, Single Servers: SSL/TLS Certificates will need to be transposed to the new location “/usr/local/nginx/conf/custom/osp-custom-servers.conf”. The original information is located in the original /usr/local/nginx/conf/nginx.conf file

  • Edit the /usr/local/nginx/conf/custom/osp-custom-servers.conf

sudo nano /usr/local/nginx/conf/custom/osp-custom-servers.conf
  • Comment the following Line: listen 80 default_server;

  • Uncomment the following lines and input the information for your TLS/SSL Certificate

# listen 443 ssl http2 default_server;
# ssl_certificate /etc/letsencrypt/live/osp.example.com/fullchain.pem;
# ssl_certificate_key /etc/letsencrypt/live/osp.example.com/privkey.pem;
# ssl_protocols TLSv1.2 TLSv1.3;
  1. OSP-RTMP: This step is only needed when configuring OSP-RTMP to work with OSP-Proxy.

  • Edit the /usr/local/nginx/conf/custom/osp-rtmp-custom-authorizeproxy.conf file

  • Replace the following line with a list of allow statements for each IP address of OSP-Proxy that will be accessing the RTMP Server’s HLS files

# allow <ip of proxy>;

to (example)

allow 23.10.1.34;
allow 23.10.1.35;
  • Edit the /usr/local/nginx/conf/custom/osp-rtmp-custom-server.conf if using SSL/TLS on your OSP-Core service

sudo nano /usr/local/nginx/conf/custom/osp-rtmp-custom-server.conf
  • Comment out the following line: listen 5999 default_server;

  • Uncomment the following lines and change the information for your TLS/SSL Certificate

Note: The port will remain as 5999

# listen 5999 ssl http2 default_server;
# ssl_certificate /etc/letsencrypt/live/osp.example.com/fullchain.pem;
# ssl_certificate_key /etc/letsencrypt/live/osp.example.com/privkey.pem;
# ssl_protocols TLSv1.2 TLSv1.3;
  1. OSP-Edge: This step is only needed if you are using an external OSP-Edge Service or plan on continuing to use one

  • Edit the /usr/local/nginx/conf/custom/osp-edge-custom-allowedpub.conf file

sudo nano /usr/local/nginx/conf/custom/osp-edge-custom-allowedpub.conf
  • Replace the following line and add the IP Addresses of all OSP-RTMP Instances #allow publish CHANGEME; to (example)

allow publish 23.10.2.2;
allow publish 23.10.2.3;
  • Edit /usr/local/nginx/conf/custom/osp-edge-custom-nginxstat.conf

sudo nano /usr/local/nginx/conf/custom/osp-edge-custom-nginxstat.conf
  • Replace the following line and add the IP addresses of all of your OSP-Core Instances #allow CHANGEME; to (example)

allow 23.10.3.2;
allow 23.10.3.3;
  1. Restart the nginx-osp service on each server

sudo systemctl restart nginx-osp

0.8.x to 0.8.x

  1. Run the OSP config tool

sudo bash osp-config.sh
  1. Select -> 2 Upgrade…

  2. Select the component to upgrade (-> 1 if single server installation)


0.7.x to 0.8.x

Note: SQLite is no longer supported, starting with OSP Version 0.8.0. Migrate to MySQL before upgrading or export a copy of the SQLite Database and reimport into a new MySQL DB while upgrading. (https://dbconvert.com/sqlite/mysql/)

  1. Perform Git Pull on your OSP directory

cd /opt/osp
sudo git pull
  1. Run the 0.8.0.sh upgrade prep script

sudo bash /opt/osp/setup/upgrade/0.8.0.sh
  1. Run the OSP config tool

sudo bash osp-config.sh
  1. Select Install -> 1: Install OSP - Single Server

  2. If prompted, reenter your OSP Ejabberd Chat Domain

  3. Exit the OSP Config Tool after completed

  4. Review the OSP config.py and copy your dbLocation Information from the config.py.old

cat /opt/osp/conf/config.py.old
sudo nano /opt/osp/conf/config.py
  1. Review any SSL/TLS Certificate Reinstalls needed for Nginx

sudo nano /usr/local/nginx/conf/nginx.conf
  1. Restart Ejabberd

sudo systemctl restart ejabberd
  1. Restart OSP

sudo systemctl restart osp.target

Resetting DB Migrations

In some instances, when upgrading you may receive an error about duplicate columns existing. If this occurs, you can reset the Flask-Migrate settings to allow the system to perform a reset upgrade.

1: Delete the migrations directory

sudo rm -rf /opt/osp/migrations

2: Open the DB using a Database tool (mysql for mysql-server or sqlite3 for sqllite)

sudo mysql

3: Select the OSP Database

use osp;

4: Drop the Alembic Versions Table

drop table alembic_version;

5: Exit and Rerun a Database Upgrade

exit;
sudo bash /opt/osp/osp-config.sh upgrade_db

Tweaks

Network

TCP Tweaks

Starting with 0.7.2, OSP has a sysctl.d tweak to optimize TCP connections in Linux where there may be problems causing packetloss and bufferbloat To Install, do the following:

sudo cp /opt/osp/setup/sysctl.d/30-osp-tcp.conf /etc/sysctl.d/
sudo sysctl -p /etc/sysctl.d/30-osp-tcp.conf

Reverse Proxy

In some instances where you are using OSP in a shared environment (Docker or other shared services) you may be required to have a reverse proxy in front of OSP. In these instances, some additional configuration may be required for your Edge Reverse Proxy.

Traefik

The Traefik reverse proxy should work out of the box for port 80 and 443. However, the RTMP port must have direct access for OSP to Stream properly.

Nginx

For Nginx to work properly as a reverse proxy in front of the OSP stack, you must ensure Nginx is setting the proper headers to forward to OSP’s Nginx. When setting the location going to OSP, ensure that the following settings are set for the Edge Reverse Proxy:

location / {
proxy_pass http://IPADDRESS;
proxy_redirect off;
proxy_set_header Host $host:$server_port;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
location /socket.io {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_set_header X-NginX-Proxy true;
# prevents 502 bad gateway error
 proxy_buffers 8 32k;
proxy_buffer_size 64k;
proxy_redirect off;
# enables WS support
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_pass http://IPADDRESS/socket.io;
}

Database

Caching

MySQL and associated DBs can be configured to Cache SQL Queries:

Warning: Newer versions of MySQL have depricated the below commands and can cause MySQL to not load {.is-warning} Add/Adjust the following lines in your mysqld.cnf

query_cache_limit = 1M
query_cache_type = 1
query_cache_size = 16M

Max Connections

In larger instances, it is recommended to increate the number of allowed database connections by editing the database configuration file:

MySQL
  1. Edit the /etc/mysql/msql.conf.d/mysqld.cnf

vi /etc/mysql/msql.conf.d/mysqld.cnf
  1. Edit the line max_connections and increase to a larger number

max_connections = 100000
  1. Restart the DB

sudo systemctl restart mysql
MariaDB
  1. Edit the /etc/mysql/mariadb.conf.d/50-server.cnf

vi /etc/mysql/mariadb.conf.d/50-server.cnf
  1. Edit the line max_connections and increase to a larger number

max_connections = 100000
  1. Restart the DB

sudo systemctl restart mariadb

Transcoding Tweaks

Use Hardware Accelerated Transcoding

NVIDIA GPU Transcoding (Ubuntu Server)

(As Submitted by multi.flexi on 18/6/2021)

1: Install Dependencies (not sure if all necessary)

sudo apt install ladspa-sdk-dev libaom-dev libass-dev libbluray-dev libbs2b-dev libcaca-dev libcdio-paranoia-dev libcodec2-dev flite1-dev libfribidi-dev libgme-dev libgsm1-dev libjack-dev libmp3lame-dev libmysofa-dev libopenmpt-dev libopus-dev libpulse-dev librsvg2-dev librubberband-dev libshine-dev libsnappy-dev libsoxr-dev libspeex-dev libssh-dev libtheora-dev libtwolame-dev libvidstab-dev libvorbis-dev libvpx-dev libwavpack-dev libwebp-dev libx264-dev libx265-dev libxml2-dev libxvidcore-dev libzmq3-dev libzvbi-dev libomxil-bellagio-dev libopenal-dev libsdl2-dev libdc1394-22-dev libchromaprint-dev frei0r-plugins-dev libfreetype6-dev build-essential nasm yasm libgnutls28-dev liblilv-dev libdrm-dev libopenjp2-7-dev

2: Install NVIDIA Driver Set

sudo apt install --no-install-recommends nvidia-driver-460

3: Install NVIDIA CUDA Toolkit

sudo apt install nvidia-cuda-toolkit

4: Remove Existing FFmpeg

sudo apt remove ffmpeg

5: Download and Compile FFmpeg nVidia headers

cd /tmp
git clone https://git.videolan.org/git/ffmpeg/nv-codec-headers.git
cd nv-codec-headers
make && sudo make install

6: Download and Compile FFmpeg

cd /tmp
wget -O ffmpeg-snapshot.tar.bz2 https://ffmpeg.org/releases/ffmpeg-snapshot.tar.bz2 && tar xjvf ffmpeg-snapshot.tar.bz2
cd ffmpeg
./configure --prefix=/usr --extra-version='0york0~20.04' --toolchain=hardened --libdir=/usr/lib/x86_64-linux-gnu --incdir=/usr/include/x86_64-linux-gnu --arch=amd64 --enable-gpl --disable-stripping --enable-gnutls --enable-ladspa --enable-libaom --enable-libass --enable-libbluray --enable-libbs2b --enable-libcaca --enable-libcdio --enable-libcodec2 --enable-libflite --enable-libfontconfig --enable-libfreetype --enable-libfribidi --enable-libgme --enable-libgsm --enable-libjack --enable-libmp3lame --enable-libmysofa --enable-libopenjpeg --enable-libopenmpt --enable-libopus --enable-libpulse --enable-librsvg --enable-librubberband --enable-libshine --enable-libsnappy --enable-libsoxr --enable-libspeex --enable-libssh --enable-libtheora --enable-libtwolame --enable-libvidstab --enable-libvorbis --enable-libvpx --enable-libwebp --enable-libx265 --enable-libxml2 --enable-libxvid --enable-libzmq --enable-libzvbi --enable-lv2 --enable-omx --enable-openal --enable-opengl --enable-sdl2 --enable-libdc1394 --enable-libdrm --enable-chromaprint --enable-frei0r --enable-libx264 --enable-shared --enable-cuda --enable-cuvid --enable-nvenc --enable-nonfree --enable-libnpp
make -j
sudo make install

7: Edit the osp-rtmp.conf file to transpile on the GPU

  • Under application stream-data-adapt and streamrec-data-adapt:

exec ffmpeg -y -vsync 0 -hwaccel cuda -hwaccel_output_format cuda -i rtmp://127.0.0.1:1935/live/$name
-c:v h264_nvenc -c:a aac -b:v 768k -b:a 96k -vf "scale_npp=852:trunc(ow/a/2)*2" -preset llhq -tune ll -zerolatency 1 -f flv rtmp://localhost:1935/show/$name_480
-c:v h264_nvenc -c:a aac -b:v 1920k -b:a 128k -vf "scale_npp=1280:trunc(ow/a/2)*2" -preset llhq -tune ll -zerolatency 1 -f flv rtmp://localhost:1935/show/$name_720
-c copy -f flv rtmp://localhost:1935/show/$name_src;

8: Restart Nginx

service nginx-osp restart

Storing transcoded data in a RAM-Disk

(Written by who, 30/7/2021)

Warning: This is only recommended, if you are having 16GB (or more) RAM in your server. {.is-warning} Since the files from the transcoding process are written and read quite often to/from your disk and are not needed anymore after a reboot, those files can be stored in a RAM-Disk (tmpfs). Basically this is good for your disk health and improves the read and write speed. You just have to add a new line to /etc/fstab with the following command:

sudo echo "tmpfs /var/www/live-adapt tmpfs defaults,mode=0755,uid=$(id -u www-data),gid=$(id -g www-data) 0 0" >> /etc/fstab

After that, you have to make sure to mount your new tmpfs and restart the nginx afterwards.

sudo mount -a
sudo systemctl restart nginx-osp.service

The new filesystem should now occur, if you execute df -h -t tmpfs.


Scaling

Using Digital Ocean Spaces

(Written by djetaine) Digital Ocean is a cloud provider that has multiple offerings including k8s, docker, standard vps but most importantly, s3 compatible object storage called Spaces. This guide will show you how to use DO Spaces to store and deliver OSP video content

Prerequisites:
  • Create an account with digital ocean and create a project.

  • This is a paid service. While DO does offer (at the time of this writing) 100 dollars of free credit for 30 days, it will eventually cost you money. Pay attention to your statistics and plan accordingly.

  • A DO Space in your closest datacenter.

  • DO does offer a CDN you can use in front of your Space. This document does not currently cover content delivery networks.

  • Digital Ocean API Keys

  • This assumes a new installation. If you already have videos, there will be more work to do and you will need to copy the files to your space and run the mount command with the -o nonempty flag at the end

  • Make a backup of your /var/www/videos directory

  • Actually make a backup of your /var/www/videos directory

Setting up your server to accept the space
  • Getting your Digital Ocean API Keys

  • Click “API” at the bottom of the nav pan on the left in your DO Administrative Console.

  • Generate a space access key [key] and a personal access token [token] . Save this somewhere you can access them easily for copy and paste

  • Mounting an s3 compatible bucket requires s3fs to be installed on your OSP server

sudo apt-get update
sudo apt-get install s3fs
  • Create your password file. Your key and token here are what you obtained from the API. Enter these without the <> Example: echo AFRKWOTYASFKNAF:dahAuyaf7856aADha7863haDAD86568 > ~/.passwd-s3fs echo <key>:<token> > ~/.passwd-s3fs

  • Set the permissions so only the owner can read/write this file chmod 600 ~/.passwd-s3fs

  • Edit the fuse configuration to allow access by non root users to files created through the DO web UI if needed. sudo nano /etc/fuse.conf uncomment (remove the #) from the following line: user_allow_other

  • Find the id of www-data for use in mounting as a writable user id Find the user named www-data and note the uid and gid. example output: uid=1234(www-data) gid=1234(www-data) groups=1234(user) So our uid and gid are 1234 here.

  • Mount the space to the videos folder using your space name that you created when you made your space, your uid, gid and space_region s3fs <space_name> /var/www/videos -o url=https://<space_region>.digitaloceanspaces.com -o use_cache=/tmp -o allow_other -o use_path_request_style -o uid=<UID> -o gid=GID Example using the information we got before: s3fs OSPVideos /var/www/videos -o url=https://nyc3.digitaloceanspaces.com -o use_cache=/tmp -o allow_other -o use_path_request_style -o uid=1234 -o gid=1234

  • Verify that the mount was successful mount At the bottom of the output you should see your space listed as an s3fs mount.

Troubleshooting
  • You receive a message about the directory not being empty. See the prereqs above.

  • The command runs but it does not mount and you see no error:

  • Verify that you do not have an additional mount with the same name (possible in error). If you do, unmount it with umount /var/www/videos

  • Check your syslog for credential validation errors

  • Syslog says “Invalid Credentials

  • cat ~/.passwd-s3fs this should have a single line in it with your key:your token with no spaces

  • cat /etc/fuse.conf verify you actually removed the # in front of user_allow_other

  • Last resort, recreate your space access and personal keys from Digital Ocean on the Spaces admin panel. Once recreated, delete/recreate the .passwd-s3fs file

Streaming

Stream URL

In order to stream to OSP, a channel with a valid stream key is needed. After creating a channel, the streaming program must be set to the corresponding URL: rtmp://$IPorFQDN/stream

Stream Keys

You will find your stream key at the bottom of the Channel configuration page as follows: /_images/user_channels_page.png

Note that only registered users with the streamer role are able to stream to OSP.

OSP Nginx-RTMP Default Configuration

OSP is configured by default with the following settings:

  • hls_framents: 1 second

  • hls_playlist_length: 10 seconds

Due to these settings, the key to creating low delay streams is to ensure your Keyframe Interval for your RTMP Source is set to 1 second.

Alterations to the the Nginx-RTMP configuration can be made by editing the osp-rtmp.conf file in /usr/local/nginx/conf. More information on the Nginx-RTMP directives can be found at https://github.com/arut/nginx-rtmp-module/wiki/Directives

Latency

OSP uses HLS to serve RTMP streams to clients. This brings a certain latency by design. The default configuration of nginx is fine-tuned to reduce the latency as far as possible while providing stable HLS streams. For this configuration it is imporant that the encoder sends a keyframe every second! The latency should be 4.5 to 5 seconds.

If streams are buffering, it’s most likely because of a suboptimal network connection. In this case, increase the hls_playlist_length in the osp-rtmp.conf. The latency will increase with a longer playlist length.

RTMP capable players (e.g. VLC) can access the RTMP stream directly. The URL is available in the share dialog below the stream. The latency of the RTMP stream should be 1 to 2 seconds.

Transcoding

Transcoding or adaptive streaming is possible with OSP. It can be enabled globally in the admin settings. However, this feature uses the CPU of the server to re-encode the streams and requires a lot of CPU power. It’s possible to utilize GPUs instead by changing the encoder used by ffmpeg in the osp-rtmp.conf. Enabling transcoding will increase the stream latency. It may be necessary to increase the playlist length.

By default, nginx has been configured to transcode 1080p, 720p, 480p, & 360p. You can optimize how streams are transcoded by editing the osp-rtmp.conf file and following the instructions here.

RTMP Streamer Software Configurations

Below is a listing of tested configurations for RTMP Source Configurations which produce the lowest delay (around 5s delay)

Open Broadcaster Software

Medium Quality (720p) / Low Delay Setup

/_images/obs_lowlatency.jpg

ffMPEG

ffmpeg can be used to stream directly to OSP in various situations which can add additional flexibility that is not available using another client software:

Stream from a local camera without a UI
ffmpeg -re -f video4linux2 -i $VideoDeviceLocation -vcodec libx264 -vprofile baseline -acodec aac -strict -2 -f flv rtmp://$OSPIP/stream/$StreamKey
Stream from a video file
ffmpeg -re -i "$file" -acodec copy -vcodec copy -f flv rtmp://$OSPIP/stream/$key
Restream from another RTMP Stream
ffmpeg -i $sourceStream -vcodec libx264 -vprofile baseline -acodec aac -strict -2 -f flv rtmp://$OSPIP/stream/$StreamKey
Testing OSP server

We can use ffmpg to test the streaming ability of an OSP server. Log into OSP with an account that has permission to stream, go to a channel (creating one if necessary), and get the stream key as described above.

Next we need some media to play. We suggest Big Buck Bunny as a wonderful test file.

In a terminal, set environment variables for your filename, server, and key. Then ffmpeg can be used to stream your video to the OSP server. The RTMP format can not handle a sample rate of 48000, so we will use options in ffmpeg to downconvert it to 44100). For example:

file=bbb_sunflower_1080p_30fps_normal.mp4
fqdn=<OSP-RTMP FQDN/IP>
key=REDACTED

ffmpeg -re -i "$file" -acodec libmp3lame -ar 44100 -vcodec copy -f flv rtmp://$fqdn/stream/$key

This should start streaming the video to the server. In order to verify everything is working as expected, use your browser to tune into the channel.

Channels

OSP’s core concept is the idea of Channels. Channels act as a separate unit of configuration for videos, clips, and streams. By changing OSP Channel Settings, you can enable invite-only settings, turn on/off chat, set offline stream images, set channel-level webhooks and more. All videos associated with a channel will take the settings of the channel, including invite protections. Each channel with also maintain its own Stream Key. User Channel Settings Screen

Creation

To create a new channel, go to the top bar menu under your user name and select My Channels. User Channels Setting Dropdown

Next, click the Create Channel Button and Input the information on your new channel in the windows that pops up. User Channels Setting Create Button User Channels Setting Create Modal

Protection

OSP offers the ability to require authentication to view Channel Streams, Videos, and Clips. By default, this setting is disabled to reduce overhead. When enabled, OSP verified that users are authorized to view all media, which can cause a delay while the system queries access.

To enable Channel Protections, go to the Admin Page -> Settings and turn on “Enable Channel Protections”. Once this setting has been enabled Channel Owners can enable protection on their channels and require viewers have been explicitly invited or have an invite code, that has been generated by the channel owner.

Chat Settings

Check Installation > OSP Configuration for a more detailed description of the individual settings.

Uploading Video

OSP provides the ability for Users to upload video directly to the system without streaming. This may be useful in cases where post-production needs to be added to a previously recorded video.

Setup

To upload video to OSP, a few settings must be configured by the Administrator

Under Admin -> Settings, the “Allow Users to Upload Video” setting must be enabled. Users which will be uploading video must be granted the Uploader Role under Admin -> Users

Limitations

  • Users must have a channel setup prior to uploading

  • Videos must be in H.264 MP4 fomat

  • Videos must be 4 GB or less

How to Upload

  1. Click on your username in the upper right corner and click “Upload Video” Upload Video Menu Dropdown

  2. Add A Title, Select your Channel, and Add a Video File. Thumbnail and Description are optional. If no thumbnail is added, one will be generated automatically. Click Upload when you are Done. Upload Video Metadata Modal

  3. If the video upload is successful, the new Video page will open automatically. Upload Video Redirect Screen

Admin Settings

Dashboard

The OSP Dashboard contains a snapshot of information regarding the active state of the system. OSP Version number, Current Live Streams, Current Viewers, System Status, and System Logs can be found here.

Dashboard

Settings

General Settings

  • Server Name: Sets the Displayed Name of the OSP Instance. This is shown in the navbar, emails, headers, etc.

  • Protocol: This should be the User Side HTTP(S) protocol used to access OSP

  • Hostname / IP Address: User Side Domain used to access the OSP instance

  • OSP-Proxy Hostname: Fully Qualified Domain Name for OSP-Proxy, if used. Should be blank if no OSP-Proxy in use.

    • If you are using more than one proxy, this should be the Fully Qualified Domain Name for your OSP-Proxy Load Balancer

  • Time Zone: System Timezone of the OSP Server. This will adjust Date Time values to match the set Time Zone

  • Maintenance Mode: Places OSP into Maintenance Mode where a Static Page will show for all users. Only Admins may log in.

Appearance

  • Logo: OSP System Logo to be shown for the server. 42w x 42h is recommended

  • Theme: Server Theme to be displayed to all users.

  • Front Page Layout: Global Panels and Order of Display on the Main Page (http(s)://osp.example.com/)

    • Only Global Panels may be added to this list

    • You can reorder by dragging the entry in the list and click Save

  • Show Empty Channels and Topics on Built-in Pages: This will show Channels and Topics which do not have a Live Stream, Video, or Clip Associated with them. If turned off, these will not display in the list when empty.

  • Server Announcement Header Title: Header Title of the System Announcement Bar shown on the Main Page

  • Announcement Message: System Announcement Shown on the top of the Main Page. Leave Blank to not display.

Channels

  • Enable Recordings: Globally allows users to record live streams

  • Enabled Uploads: Globally allows users to upload videos (Still requires uploader role)

  • Enable Video/Clip Comments: Globally allows users to leave comments on videos and clips

  • Enable Channel Protection System: Globally enables OSP’s channel protection system, allowing users to prevent unauthorized viewers from accessing channel content. Users can set channel protection on a per-channel basis

  • Enable RTMP Restreams: Globally allows users to restream live streams on OSP to another RTMP server

  • Enable Adaptive Streams: Globally enables Adaptive Streaming.

    • Important Note: Adaptive Streams are significantly CPU intensive and should only be enabled on servers which have FFMPEG Hardware Acceleration configured and have modified the Nginx-RTMP Conf Files to use HW Acceleration. If you have not done this, DO NOT TURN THIS ON.

  • Maximum Retention for Recordings Before Deletion (days): Sets the Retention for Videos and Clips. Users will be notified when nearing the retention date for a video/clip. Setting to 0 will set for indefinite retention. This setting will take precedent if a user sets a higher retention setting in their channel.

  • Maximum Allowed # of Channels per User: Maximum number of channels a user can create in their account. Set to 0 for no restriction

  • Maximum Bitrate for RTMP Restream (Kb/s): Sets the bitrate used by the RTMP Restream process

  • Maximum Clip Length: Sets the maximum length a video clip can be when creating a new clip

  • Banned Chat Words: Sets words which are banned in chat and will be censored

Global Panels

  • Panel Name: Panel name identifier for the global panel

  • Panel Header Label: Displayed header label for a panel

  • Panel Type: Sets the Panel Type to be displayed

    • Custom Markdown/Text: Markdown formatted panel

    • Live Stream List: List of all active Live Streams on the instance

    • Video List: Lists Videos on the OSP instance

    • Clip List: Lists Clips on the OSP instance

    • Topic List: Lists Topics on the OSP instance

    • Channel List: Lists Channels on the OSP Instance

    • Featured Live Channel: Displays the Live Stream of the Target Channel when Live along with Content

  • Panel Order: Sets the Display Order of List Panel Types

  • Content: Displays Markdown Data in the panel where available

Static Pages

  • Page Title: Name of the Static Page

  • Page URL: URL Slug for the static page. Will be accessible via /p/$val

  • Icon: Icon Class Name for the Static Page. Should be the Font Awesome class name as found at https://fontawesome.com/search?m=free

  • Display in Top Navbar: Displays the Static Page in the top navbar, instead of the left sidebar

  • Page Content: Markdown Content to be displayed

OAuth Configuration

Starting with Beta 6, OSP includes a configuration option to add oAuth Sign-On using preconfigured and custom OAuth2 Servers, such as Discord, Reddit, Azure Active Directory, etc.

OSP OAuth configuration uses AuthLib (https://github.com/lepture/authlib).

Adding an OAuth2 Provider

You can add a new provider from the Admin Screen->oAuth Providers, as seen below:

OAuth Admin Screen

When adding a new provider, you will be required to enter configuration settings based on the provider. In the provider configuration below this section, we will compile a listing of know and working settings, but be aware not every service is the same. Most providers will require you to set up oAuth on their site, usually in a developer or application section.

New oAuth Provider Settings Window

  • Authentication Type: Select Preconfigured Providers or a Custom OAuth2 Configuration

  • OAuth Provider ID: Shortname identifier for OSP to identify the OAuth Provider. This ID is used in URL shortcuts and can not have spaces.

  • OAuth Provider Friendly Name: Display Name used on Login and Registration Pages to identify the service users will be logging in with.

  • Login Button Color: Custom Color of the Login Button used on the Login and Registration Pages

  • Client ID: Client ID or Application ID provided by the oAuth Provider

  • Client Secret: Client Secret Key provided by the oAuth Provider

  • Access Token URL: Access Token Retrieval endpoint for OAuth 2

  • Access Token Params: Additional Parameters required for the Access Token Endpoint. Expressed as a JSON Value.

  • Authorize URL: Endpoint for User Authorization of OAuth 2

  • Authorize Token Params: Additional Parameters required for User Authorization. Expressed as a JSON Value.

  • API Base URL: Full URI for API Requests to the Provider. (Ex: https://example.com/api/)

  • Client Kwargs: Additional Arguments required to build an OAuth2 Session (https://docs.authlib.org/en/latest/client/api.html#authlib.integrations.requests_client.OAuth2Session). This is typically where you will place Authentication Scope such as:{"scope":"email"}

  • Profile Endpoint: Path of API Base URL where User Profile information can be retrieved (Ex: me/@profile)

  • ID Profile Value: Result Variable found in the results of a query to the Profile Endpoint which contains a unique ID value, typically “id”

  • User Profile Value: Result Variable found in the results of a query to the Profile Endpoint which contains a username

  • Email Profile Value: Result Variable found int the results of a query Profile Endpoint which contains an email address.

Note: Not all services provide access to Email Addresses in their API. In this case, if OSP can not retrieve an email address, users will be prompted to add one when they log in.

Additional Information

  • Custom OAuth 2 services will not automatically download user photos to OSP. If you have a service that you have configured and would like automatic picture downloads, please open a feature request with your configuration settings and instructions on how to retrieve the pictures to be added into future OSP versions.

  • Redirect URI Settings on OAuth2 Providers will be http(s)://<FQDN>/oauth/authorize/<oAuthProviderID>

  • Users who log in using an OAuth2 provider whose email address matches an existing local OSP account will be prompted to convert their local account into an oAuth account. During the process, the user will need to enter their local OSP account password to complete the process. Services which do not provide an email address in their user profile will not be able to convert local accounts at this time.

Known OAuth Configurations

Coming Soon

Webhooks

OSP can send HTTP requests (GET, POST, PUT, DELETE) to notify other services about various triggers. Webhooks can be set globally in the admin settings and per channel by users. The HTTP requests are entirely definable by the by JSON.

Currently supported triggers:

  • At the Start of a Live Stream

  • At the End of a Live Stream

  • On a New Viewer Joining a Live Stream

  • On a Stream Upvote

  • On a Stream Metadata Change (Name/Topic)

  • On a Stream Chat Message

  • On Posting of a New Video to a Channel

  • On a New Video Comment

  • On a Video Upvote

  • On a Video Metadata Change (Name/Topic)

Webhook Variables

When defining a webhook payload, various variables can be set which will be replaced with live data at the time the webhook is run. Webhook variables are defined as the following:

  • %channelname%

  • %channelurl%

  • %channeltopic%

  • %channelimage%

  • %streamer%

  • %channeldescription%

  • %streamname%

  • %streamurl%

  • %streamtopic%

  • %streamimage%

  • %user%

  • %userpicture%

  • %videoname%

  • %videodate%

  • %videodescription%

  • %videotopic%

  • %videourl%

  • %videothumbnail%

  • %comment%

Examples

Discord

Type: POST

Trigger event: Stream start

Payload
{
   "content":"%channelname% went live on the OSP Demo Server",
   "username":"OSP Bot",
   "embeds":[
      {
         "title":"%streamurl%",
         "url":"%streamurl%",
         "color":6570404,
         "image":{
            "url":"%channelimage%"
         },
         "author":{
            "name":"%streamer% is now streaming"
         },
         "fields":[
            {
               "name":"Channel",
               "value":"%channelname%",
               "inline":true
            },
            {
               "name":"Topic",
               "value":"%streamtopic%",
               "inline":true
            },
            {
               "name":"Stream Name",
               "value":"%streamname%",
               "inline":true
            },
            {
               "name":"Description",
               "value":"%channeldescription%",
               "inline":true
            }
         ]
      }
   ]
}

Mastodon

Type: POST

Trigger event: Stream start

URL
https://$FQDN/api/v1/statuses?access_token=$TOKEN
Header
{
    "Content-Type": "application/json"
}
Payload
{
"status": "New Live Stream on OSP.\n\nURL: %streamurl%\nChannel: %channelname%\nTopic: %streamtopic%\nDescription: %channeldescription%"
}

Troubleshooting

  • OSP opens fine but when you try to stream to it, the stream never displays on the live channel page

    • Check the Admin Settings under Site Protocol and Site Address. Incorrect values can cause the system to not pass the stream off properly to Nginx-RTMP.

  • OSP doesn’t open properly. The tv static error pages doesn’t show and instead, a basic 500 error page is given

    • Ensure the OSP service (sudo systemctl start osp.target) has been started. If it continues to fail, check the OSP logs:

cat /opt/osp/logs/osp-error.log
  • OSP gives a 500 Internal Server Error when attempting to log in/post forms.

    • This can happen when another reverse proxy is placed in front of OSP, usually Nginx. If the Edge Reverse proxy is not configured properly to forward the proxied address to OSP’s Nginx install, it is seen as 127.0.0.1 to the inside reverse proxy. To correct, ensure you have the following configuration on your Edge Reverse Proxy (Per the OSP Tweaks Page):

location / {
proxy_pass http://IPADDRESS;
proxy_redirect off;
proxy_set_header Host $host:$server_port;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
location /socket.io {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_set_header X-NginX-Proxy true;
# prevents 502 bad gateway error
proxy_buffers 8 32k;
proxy_buffer_size 64k;
proxy_redirect off;
# enables WS support
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_pass http://IPADDRESS/socket.io;
}

OSP-Proxy

Starting with v0.8.8, you can use OSP-Proxy to help with load balancing of live streams. OSP Proxy works in the opposite fashion of OSP Edge. Instead of receiving a RTMP push of all streams from an RTMP server, OSP Proxy fetches a copy of the HLS files from RTMP servers and caches them for viewing. In addition, OSP Proxy does not need to do additional transcoding if using Adaptive Streaming. This is in contrast to OSP Edge, which must perform transcoding when Adaptive Streaming is turned on.

Proxy Diagram

Setting Up

OSP Proxy can be installed via the osp-config.sh script. It must be installed on its own separate server to prevent conflicting with any other OSP service. The Proxy service requires configuration to reach the OSP-Core’s API. This allows the Proxy to determine which RTMP source a stream is coming from and adjust accordingly. This is set in the proxy’s config.py file located at /opt/osp-proxy/conf/config.py

# OSP Core API Site ex:http://osp.example.com
ospCoreAPI = "#CHANGEMETOOSPCORE"

In addition, OSP-Proxy has the ability to work with existing OSP-Edge Systems or other OSP-Proxy installs. The Proxy can be forced to pull from a specific server using the forceDestination option in the config.py file

# Force Destination - Use to point to Specified Edge Server or Tiered Proxy. Uncomment to override API's RTMP List and use the destination you list
#forceDestination = "example.com"
#forceDestinationType = "edge" # Choices are "edge", "proxy"

Finally, RTMP Servers must be configured to allow the proxy to access the HLS files. Each OSP-RTMP server will need to have the following files edited and the nginx-osp service restarted:

  • /usr/local/nginx/conf/custom/osp-rtmp-custom-authorizeproxy.conf

  • add an allow <ip>; line for each proxy in use

allow <ip of proxy>;
deny all;
  • /usr/local/nginx/conf/custom/osp-rtmp-custom-server.conf

  • If using TLS for your primary server, comment listen 5999 default_server; and uncomment the SSL/TLS lines

#listen 5999 default_server;
### Comment Above and Uncomment/Edit Below for OSP-Proxy TLS ###
listen 5999 ssl http2 default_server;
ssl_certificate /etc/letsencrypt/live/osp.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/osp.example.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;

Restart the nginx-osp service

sudo systemctl restart nginx-osp

Finally, add the FQDN of the OSP Proxy to the Admin/Settings Screen on the main OSP site. OSP will automatically redirect all Video Stream requests to the Proxy, which will redirect and cache based on active RTMP servers and where streams are being sent to.

Additional Notes

  • Multiple OSP Proxy services can be used, but will require a reverse proxy/HAProxy in front of them.

  • OSP Proxies will not require significant storage (15 Gigs are set aside for caching) or any shared storage mounting

  • OSP Proxy will automatically rebuild its needed Nginx Mappings every 5 minutes. If you add another RTMP server and need to test immediately, you can manually run the updateUpstream.sh script

sudo bash /opt/osp-proxy/updateUpstream.sh

OSP-Edge

The OSP Edge Streamer acts as a load balanced endpoint for OSP, allowing Live Stream viewers to be offloaded from the primary OSP Node to a cluster of Nginx-RTMP servers configured to receive RTMP restreams from the master. A minimum of Beta 5 is required to use.

OSP Edge Diagram

As many OSP Edge Streamer Nodes are needed can be created and added to OSP by an admin under the Admin -> Edge Streamers Configuration options.

Setup OSP Edge Streamer

  1. Clone the OSP Edge Streamer Repo from: https://gitlab.com/Deamos/open-streaming-platform-edge-streamer

  2. Once the server has finished setting up, Go to OSP and add the Fully qualified domain name to the Edge Streamer section in the Admin Settings.

  • Load should be set to equal 100% between all Edge Streamers.

Note: Edge Streamers must be setup with the same protocol (HTTP/HTTPS) as the main OSP site.

Note: Port 443 and 80 are not passed to the configuration file since it is handled by OSP’s protocol. Only change these values if you are using a non-standard port

Note: Starting in Beta 6, the Master OSP Server can act as an Edge Node. This can be manually added by using the Master OSP Server’s Site Address, as set in the Admin Settings Screen

OSP Edge Add Modal

  1. Activate each Edge Streamer that will be used.

  2. After adding your settings, you will need to restart Nginx-RTMP on the primary OSP Server

sudo systemctl restart nginx-osp

Swagger API

Overview

API Screenshot The API can be accessed at: http(s)://<fqdn>/apiv1.

For authenticated endpoints, an API key is needed, which can be created by users with the streamer role in the user menu to the top right. Requests to authenticated endpoints must have the ‘X-API-KEY’: header field set with a valid API key.

Example

In this example a chat message is sent to a chat channel endpoint.

Username: botname
Message: beep bob
Endpoint: channels/chat/72223bf3-be79-4a2a-88d9-c7bdce271f0e
API Key: d26de1eb2d48a784e109b29025632fc1a0211a2ffbede09672c8cf6f4321fb0000c49cb243e2d07e

curl -X POST "http://localhost/apiv1/channels/chat/72223bf3-be79-4a2a-88d9-c7bdce271f0e?username=botname&message=beep%20bop" \    -H  "accept: application/json" -H  "X-API-KEY: d26de1eb2d48a784e109b29025632fc1a0211a2ffbede09672c8cf6f4321fb0000c49cb243e2d07e"

Theme Customization

OSP Supports Custom HTML and CSS theming via creation of another directory under the /opt/osp/templates/themes directory.

When theming, you must include at a minimum a layout.html. Use the Default Theme as a template to build your own theme. Custom CSS can be created under the /opt/osp/static/css directory under the directory name $ThemeName and the css file name as theme.css.

Example Format

/opt/osp/static/css
	mytheme/
  	theme.css
      
/opt/osp/templates/themes
	mytheme/
  	layout.html

Themes also must contain a theme.json file to work properly with OSP. Any file that will be overridden must be listed in the Override list in the json file. Any file not listed in the override will use Defaultv3, but with the custom theme’s CSS file.

theme.json:

{
  "Name": "Example",
  "Maintainer": "Some User",
  "Version": "1.0",
  "Description": "Description of Theme",
  "Override": ["channelplayer.html"] 
}

Indices and tables