Welcome to Open Streaming Platform’s documentation!
About Open Streaming Platform

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)
Clone the git repository
git clone https://gitlab.com/Deamos/flask-nginx-rtmp-manager.git
Install the Config Tool Prerequisites (if not already installed)
sudo apt-get install dialog
Run the OSP Configuration Tool
cd flask-nginx-rtmp-manager
sudo bash osp-config.sh
Select Option 1 - “Install…”
Select Option 1 - “Install OSP - Single Server”
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.
On completion, exit the OSP Config Tool.
Review the values in the OSP
/opt/osp/conf/config.py
.
NOTE:
secretKey
andpasswordSalt
should be changed from their default values.
sudo nano /opt/osp/conf/config.py
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
Recommended Install Order
Below is the recommended order of setting up split servers. This is due to some of the dependancies requires for some servers to function properly.
Centralized Storage - Have a server ready to connect to
Ejabberd
Redis
Database
OSP-Core
OSP-RTMP
OSP-Edge
OSP-Proxy
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.
Install s3fs
sudo apt-get update && sudo apt-get install s3fs
Create a password file. This will contain the S3 key and secret token:
echo S3KEY:S3TOKEN > ~/.passwd-s3fs
Set the permissions to secure the file
chmod 600 ~/.passwd-s3fs
Edit the Fuse Configurations to allow access by non-root users to files
sudo nano /etc/fuse.conf
Comment out the following line
user_allow_other
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
Create the required stub locations:
sudo mkdir -p /var/www/videos
sudo mkdir -p /var/www/images
sudo mkdir -p /var/www/stream-thumb
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>
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
Clone the git repository
git clone https://gitlab.com/Deamos/flask-nginx-rtmp-manager.git
Install the Config Tool Prerequisites (if not already installed)
sudo apt-get install dialog
Run the OSP Configuration Tool
cd flask-nginx-rtmp-manager
sudo bash osp-config.sh
Select Option 1 - “Install…”
Select Option 6 - “Install Ejabberd”
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.
On completion, exit the OSP Config Tool.
Setup a new Ejabberd admin account.
sudo /usr/local/ejabberd/bin/ejabberdctl register admin localhost <password>
Edit the
ejabberd.yml
sudo nano /usr/local/ejabberd/conf/ejabberd.yml
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>
Save the
ejabberd.yml
fileEdit the
auth_osp.py
Authentication Handler
sudo nano /usr/local/ejabberd/conf/auth_osp.py
Edit the protocol and ospAPIServer variables to match your OSP Core Instance.
protocol = "https"
ospAPIServer = "osp.example.com"
Save the
auth_osp.py
fileRestart Ejabberd
sudo systemctl restart ejabberd
Redis
Install Redis
sudo apt update
sudo apt install redis-server
Edit the
redis.conf
file
sudo nano /etc/redis/redis.conf
Find & Edit the bind location to listen on all interfaces
bind 0.0.0.0
Find and Set a Redis Password
requirepass <Password>
Save the
redis.conf
fileRestart Redis
sudo systemctl restart redis.service
Database
Install MariaDB
sudo apt-get update && sudo apt-get install mariadb-server
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
Edit the my.cnf file
sudo nano /etc/mysql/my.cnf
Edit the bind-bind address to listen on all interfaces
bind-address = 0.0.0.0
Restart MariaDB
sudo systemctl restart mysql
Log into MariaDB
sudo mysql
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>';
Quit the MariaDB Console
quit;
The Database will be initialized on the successful run of an OSP-Core Instance
OSP-Core
Clone the git repository
git clone https://gitlab.com/Deamos/flask-nginx-rtmp-manager.git
Install the Config Tool Prerequisites (if not already installed)
sudo apt-get install dialog
Run the OSP Configuration Tool
cd flask-nginx-rtmp-manager
sudo bash osp-config.sh
Select Option 1 - “Install…”
Select Option 2 - “Install OSP-Core”
On completion, exit the OSP Config Tool.
Copy the OSP
config.py.dist
file toconfig.py
sudo cp /opt/osp/conf/config.py.dist /opt/osp/conf/config.py
Edit the
config.py
file
sudo nano /opt/osp/conf/config.py
Change the dbLocation variable to match your database credentials and IP/DNS
dbLocation = 'mysql+pymysql://<user>:<password>@<db_host>/<db_name>?charset=utf8mb4'
Change the Redis variables to match the IP/DNS and password set for it
redisHost="redis.example.com"
redisPort=6379
redisPassword="redis_password"
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"
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
Restart the OSP Core Workers
sudo systemctl restart osp.target
Save the
config.py
fileInitialize the Database by running the command line upgrader
sudo bash osp-config.sh upgrade db
Open a web browser and browse to:
http://<OSPCore IP Address or DNS>
Setup OSP using the Initial Configuration Wizard
OSP-RTMP
Clone the git repository
git clone https://gitlab.com/Deamos/flask-nginx-rtmp-manager.git
Install the Config Tool Prerequisites (if not already installed)
sudo apt-get install dialog
Run the OSP Configuration Tool
cd flask-nginx-rtmp-manager
sudo bash osp-config.sh
Select Option 1 - “Install…”
Select Option 3 - “Install OSP-RTMP”
On completion, exit the OSP Config Tool.
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
Change the ospCoreAPI Variable to point at your OSP-Core instance
ospCoreAPI = "http://ospcore.example.com"
Start the OSP-RTMP Instance
sudo systemctl start osp-rtmp
Open a web browser and go to your OSP-Core Instance
http://ospcore.example.com
Log on as an Admin and Open the Admin Settings
Select RTMP Servers
Click the Plus Sign Button
Type in the IP or Fully Qualified Domain Name for your OSP-RTMP Server and click Add
OSP-Edge
Clone the git repository
git clone https://gitlab.com/Deamos/flask-nginx-rtmp-manager.git
Install the Config Tool Prerequisites (if not already installed)
sudo apt-get install dialog
Run the OSP Configuration Tool
cd flask-nginx-rtmp-manager
sudo bash osp-config.sh
Select Option 1 - “Install…”
Select Option 4 - “Install OSP-Edge”
When prompted, input the IP address of your OSP-RTMP Instance
On completion, exit the OSP Config Tool.
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
Add any additional authorize publishing IPs to stream-data and stream-data-adapt:
allow publish <IP Address>;
Restart Nginx
sudo systemctl restart nginx-osp
Open a web browser and go to your OSP-Core Instance
http://ospcore.example.com
Log on as an Admin and Open the Admin Settings
Select Edge Streamers
Add the Fully Qualified Domain Name or IP Address of the Edge Server
Add the Load Percentage that the Edge Server will use.
NOTE: The sum of all Edge Servers must equal 100%.
Restart Nginx on all OSP-Core Servers
sudo systemctl restart nginx-osp
OSP-Proxy
Clone the git repository
git clone https://gitlab.com/Deamos/flask-nginx-rtmp-manager.git
Install the Config Tool Prerequisites (if not already installed)
sudo apt-get install dialog
Run the OSP Configuration Tool
cd flask-nginx-rtmp-manager
sudo bash osp-config.sh
Select Option 1 - “Install…”
Select Option 5 - “Install OSP-Proxy”
When prompted, input the Protocol and Fully Qualified Domain Name of your OSP-Core Instance (ex: https://osp.example.com)
On completion, exit the OSP Config Tool.
If you are using TLS/SSL on your Core Site, Acquire a TLS Certificate
Edit
/usr/local/nginx/conf/custom/osp-proxy-custom-servers.conf
sudo nano /usr/local/nginx/conf/custom/osp-proxy-custom-servers.conf
Change Line 8 to match your OSP Core FQDN
valid_referers server_names osp.example.com ~.;
If you are using TLS, Comment the following Line:
listen 80 default_server;
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;
Edit the OSP-Proxy Configuration File
sudo nano /opt/osp-proxy/conf/config.py
Change the Flask Secret Key to a Random Value
# Flask Secret Key
secretKey="CHANGEME"
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"
Restart Nginx-OSP and OSP-Proxy
sudo systemctl restart nginx-osp
sudo systemctl restart osp-proxy
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.
Perform a first run of the Configuration File Generator
cd /opt/osp
sudo bash updateUpstream.sh
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
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
Add the OSP-Proxy Domain to the OSP-Core’s Admin Panel under Settings
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
OSP-Core
: https://hub.docker.com/r/deamos/osp-coreOSP-RTMP
: https://hub.docker.com/r/deamos/osp-rtmpOSP-Ejabberd
: https://hub.docker.com/r/deamos/osp-ejabberd
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 DomainOSP_REDIS_HOST
Domain/IP of Redis ServerOSP_REDIS_PORT
Redis Server PortOSP_REDIS_PASSWORD
Redis Password, if usedOSP_CORE_DB
Database Connection stringex:
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 PasswordOSP_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 Addressex: noreply@email.com
OSP_SMTP_SERVERADDRESS
SMTP Server AddressOSP_SMTP_SERVERPORT
SMTP Server PortOSP_SMTP_ENCRYPTION
SMTP Encryption Type [none | ssl | tls]OSP_SMTP_USERNAME
SMTP Authentication UsernameOSP_SMTP_PASSWORD
SMTP Authentication PasswordOSP_RTMP_SERVER
Initial OSP-RTMP Server FQDNAdds 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 APIex: http://osp.example.com
OSP_RTMP_SECRETKEY
Flask Secret Key (Should be Random Value)
OSP-Ejabberd
EJABBERD_XMLRPC_ALLOWIP
XML-RPC Allowed IP AddressesEJABBERD_PASSWORD
Ejabberd Admin PasswordEJABBERD_DOMAIN
OSP Instance Wide Domain. This should be the same as your OSP Instance Public FQDNOSP_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
Recommended Volumes/Mount Points
/var/www
- Storage of Images, Streams, and Stored Video Files/usr/local/nginx/conf
- Contains the NginX Configuration files which can be altered to suit your needs (HTTPS without something like Traefik)
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)
Install MySQL Server on Database Server or OSP Server
sudo apt-get install mysql-server
Copy the MySQL Configuration File in to MySQL
sudo cp /opt/osp/setup/mysql/mysqld.cnf /etc/mysql/my.cnf
Restart MySQL
sudo systemctl restart mysql
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';
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'
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
Copy the backup
config.py
file to/opt/osp/conf
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:
Backup your existing Database per the proceedures above.
Shut down OSP
sudo systemctl stop osp.target
Open the MySQL Console
sudo mysql
Drop the OSP Database;
drop database osp;
Exit the MySQL Console
quit;
Follow the steps for Setting up a New MySQL install, starting at Step 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:
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
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"
Edit the
/usr/local/ejabberd/conf/ejabberd.yml
file and update the fields based on your configuration Line 17-19: SetCHANGEME
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
Install Python Requirements
sudo apt-get install python3-pip
sudo pip3 install requests
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"
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
Configure the local admin account with a password. Do not change the localadmin part
sudo /usr/local/ejabberd/bin/ejabberdctl register admin localhost YOURADMINPASSWORD
Install Nginx to reverse proxy the XMPP Bosh Port
sudo apt-get install nginx
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;
}
Restart the Nginx Service
sudo systemctl restart nginx
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"
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”.
IRC: A more Twitch-Like experience.
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.
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.
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.
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.
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.
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.
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.
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:
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
Open the OSP Directory
cd /opt/osp
Run a Git Pull to pull in the most recent code
sudo git pull
Run the OSP Configuration Tool Script
sudo bash osp-config.sh
Select Option 2: Upgrade…
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
Clone the OSP Repo
git clone https://gitlab.com/osp-group/flask-nginx-rtmp-manager.git
Open the Cloned Repo
cd flask-nginx-rtmp-managher
Run the OSP Configuration Tool Script
sudo bash osp-config.sh
Select Option 2: Upgrade…
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:
Remove the existing DB Migrations folder
sudo rm -rf /opt/osp/migrations
Perform a git pull of the most recent build
sudo git pull
Run the Upgrade Script
sudo bash /opt/osp/setup/upgrade/0.9.0.sh
After Completion, edit /opt/osp/conf/config.py:
sudo nano /opt/osp/conf/config.py
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"
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}
Run the osp-config updater process as normal
On completion, exit the osp-config updater
Create the the custom directory in the /usr/local/nginx/conf folder
sudo mkdir /usr/local/nginx/conf/custom
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
Reopen the osp-config updater and run the update process a second time.
Follow the instructions below to reconfigure the new custom nginx files
The following files will need to be updated for each OSP service:
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;
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;
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;
Restart the nginx-osp service on each server
sudo systemctl restart nginx-osp
0.8.x to 0.8.x
Run the OSP config tool
sudo bash osp-config.sh
Select -> 2 Upgrade…
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/)
Perform Git Pull on your OSP directory
cd /opt/osp
sudo git pull
Run the 0.8.0.sh upgrade prep script
sudo bash /opt/osp/setup/upgrade/0.8.0.sh
Run the OSP config tool
sudo bash osp-config.sh
Select Install -> 1: Install OSP - Single Server
If prompted, reenter your OSP Ejabberd Chat Domain
Exit the OSP Config Tool after completed
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
Review any SSL/TLS Certificate Reinstalls needed for Nginx
sudo nano /usr/local/nginx/conf/nginx.conf
Restart Ejabberd
sudo systemctl restart ejabberd
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
Edit the /etc/mysql/msql.conf.d/mysqld.cnf
vi /etc/mysql/msql.conf.d/mysqld.cnf
Edit the line max_connections and increase to a larger number
max_connections = 100000
Restart the DB
sudo systemctl restart mysql
MariaDB
Edit the /etc/mysql/mariadb.conf.d/50-server.cnf
vi /etc/mysql/mariadb.conf.d/50-server.cnf
Edit the line max_connections and increase to a larger number
max_connections = 100000
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 endMake 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 spacescat /etc/fuse.conf
verify you actually removed the # in front of user_allow_otherLast 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:
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
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.
Creation
To create a new channel, go to the top bar menu under your user name and select My Channels.
Next, click the Create Channel Button and Input the information on your new channel in the windows that pops up.
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
Click on your username in the upper right corner and click “Upload Video”
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.
If the video upload is successful, the new Video page will open automatically.
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.
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 OSPHostname / IP Address
: User Side Domain used to access the OSP instanceOSP-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 ZoneMaintenance 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 recommendedTheme
: 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 PageAnnouncement 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 streamsEnabled Uploads
: Globally allows users to upload videos (Still requires uploader role)Enable Video/Clip Comments
: Globally allows users to leave comments on videos and clipsEnable 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 basisEnable RTMP Restreams
: Globally allows users to restream live streams on OSP to another RTMP serverEnable 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 restrictionMaximum Bitrate for RTMP Restream (Kb/s)
: Sets the bitrate used by the RTMP Restream processMaximum Clip Length
: Sets the maximum length a video clip can be when creating a new clipBanned Chat Words
: Sets words which are banned in chat and will be censored
Global Panels
Panel Name
: Panel name identifier for the global panelPanel Header Label
: Displayed header label for a panelPanel Type
: Sets the Panel Type to be displayedCustom Markdown/Text
: Markdown formatted panelLive Stream List
: List of all active Live Streams on the instanceVideo List
: Lists Videos on the OSP instanceClip List
: Lists Clips on the OSP instanceTopic List
: Lists Topics on the OSP instanceChannel List
: Lists Channels on the OSP InstanceFeatured Live Channel
: Displays the Live Stream of the Target Channel when Live along with Content
Panel Order
: Sets the Display Order of List Panel TypesContent
: Displays Markdown Data in the panel where available
Static Pages
Page Title
: Name of the Static PagePage URL
: URL Slug for the static page. Will be accessible via /p/$valIcon
: Icon Class Name for the Static Page. Should be the Font Awesome class name as found at https://fontawesome.com/search?m=freeDisplay in Top Navbar
: Displays the Static Page in the top navbar, instead of the left sidebarPage 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:
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
Header
{
"Content-Type": "application/json"
}
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.
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.
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
Clone the OSP Edge Streamer Repo from: https://gitlab.com/Deamos/open-streaming-platform-edge-streamer
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
Activate each Edge Streamer that will be used.
After adding your settings, you will need to restart Nginx-RTMP on the primary OSP Server
sudo systemctl restart nginx-osp
Swagger API
Overview
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"]
}