diff --git a/group_vars/nginx_rtmp.yml b/group_vars/nginx_rtmp.yml new file mode 100644 index 0000000000000000000000000000000000000000..d5626daa0dca8487e3fa234c57ca8db1076db5f8 --- /dev/null +++ b/group_vars/nginx_rtmp.yml @@ -0,0 +1,4 @@ +--- + +glob_nginx_rtmp: + uri: stream.crans.org diff --git a/hosts b/hosts index 22b567d8b4822a61c56d0bbdd78858ee602b4c11..b6c94842630b9bb96ef623050b7c4b79d4dbb828 100644 --- a/hosts +++ b/hosts @@ -25,6 +25,9 @@ # [test_vm] # re2o-test.adm.crans.org +[nginx_rtmp] +fluxx.adm.crans.org + [reverseproxy] hodaur.adm.crans.org frontdaur.adm.crans.org @@ -81,6 +84,7 @@ gitlab-ci.adm.crans.org hodaur.adm.crans.org monitoring.adm.crans.org boeing.adm.crans.org +fluxx.adm.crans.org [ovh_physical] sputnik.adm.crans.org diff --git a/plays/nginx_rtmp.yml b/plays/nginx_rtmp.yml new file mode 100644 index 0000000000000000000000000000000000000000..2ed0f0c728ce042aff81b136572ec4da2f795801 --- /dev/null +++ b/plays/nginx_rtmp.yml @@ -0,0 +1,6 @@ +#!/usr/bin/env ansible-playbook +--- +- hosts: nginx_rtmp + nginx_rtmp: "{{ glob_nginx_rtmp | combine(loc_nginx_rtmp) }}" + roles: + - nginx_rtmp diff --git a/roles/nginx-rtmp/handlers/main.yml b/roles/nginx-rtmp/handlers/main.yml new file mode 100644 index 0000000000000000000000000000000000000000..3b8f2d6927c32e1ccdb51d04f84b0944f2aa7d93 --- /dev/null +++ b/roles/nginx-rtmp/handlers/main.yml @@ -0,0 +1,7 @@ +--- + +- name: restart nginx + service: + name: nginx + state: restarted + become: true diff --git a/roles/nginx-rtmp/tasks/main.yml b/roles/nginx-rtmp/tasks/main.yml new file mode 100644 index 0000000000000000000000000000000000000000..68438fd24786e7d026ff43575ce151d5bcdcf36d --- /dev/null +++ b/roles/nginx-rtmp/tasks/main.yml @@ -0,0 +1,44 @@ +--- + +- name: Install nginx with rtmp module + apt: + name: + - nginx-full + - libnginx-mod-rtmp + register: apt_result + retries: 3 + until: apt_result is succeeded + become: yes + +- name: Copy module and site configuration files + template: + src: '{{ item }}.j2' + dest: '/etc/{{ item }}' + loop: + - nginx/modules-available/60-rtmp.conf + - nginx/sites-available/stream + notify: restart nginx + +- name: Enable site + file: + src: '/etc/nginx/sites-available/stream' + dest: '/etc/nginx/sites-enabled/stream' + state: link + notify: restart nginx + +- name: Enable module + file: + src: '/etc/nginx/modules-available/60-rtmp.conf' + dest: '/etc/nginx/modules-enabled/60-rtmp.conf' + state: link + notify: restart nginx + +- name: Create site folder + file: + path: /var/www/stream/hls + state: directory + +- name: Copy index configuration file + template: + src: index.html + dest: /var/www/stream/ diff --git a/roles/nginx-rtmp/templates/index.html b/roles/nginx-rtmp/templates/index.html new file mode 100644 index 0000000000000000000000000000000000000000..36134d85a6953600efee373f6094e6887e76631a --- /dev/null +++ b/roles/nginx-rtmp/templates/index.html @@ -0,0 +1,28 @@ +<!DOCTYPE html> +<html lang="fr"> +<head> + <meta charset="UTF-8"> + <title>Crans Live</title> + <link href="//unpkg.com/bootstrap@4.5/dist/css/bootstrap.min.css" rel="stylesheet"> + <link href="//unpkg.com/video.js@7/dist/video-js.min.css" rel="stylesheet"> +</head> +<body class="bg-dark m-2"> + <div class="container"> + <video id="my-video" class="video-js embed-responsive shadow-lg rounded-sm"></video> + </div> + + <script src="//unpkg.com/video.js@7/dist/video.min.js"></script> + <script> + const videoId = window.location.pathname.split("/").pop() + videojs('my-video', { + controls: true, + autoplay: true, + preload: 'auto', + muted: true + }).src({ + type: 'application/x-mpegURL', + src: `/hls/${videoId}.m3u8` + }); + </script> +</body> +</html> diff --git a/roles/nginx-rtmp/templates/nginx/modules-available/60-rtmp.conf.j2 b/roles/nginx-rtmp/templates/nginx/modules-available/60-rtmp.conf.j2 new file mode 100644 index 0000000000000000000000000000000000000000..dda34d59d4428d0a574c6a45cb8908a36a36ce7e --- /dev/null +++ b/roles/nginx-rtmp/templates/nginx/modules-available/60-rtmp.conf.j2 @@ -0,0 +1,16 @@ +rtmp { + server { + listen 1935; + chunk_size 4096; + application live { + live on; + hls on; + hls_path /var/www/stream/hls/; + hls_fragment 3; + hls_playlist_length 60; + + record off; + } + } +} + diff --git a/roles/nginx-rtmp/templates/nginx/sites-available/stream.j2 b/roles/nginx-rtmp/templates/nginx/sites-available/stream.j2 new file mode 100644 index 0000000000000000000000000000000000000000..9fa05998bcf0c3b0843b0fdc5a3122c1d3d72b07 --- /dev/null +++ b/roles/nginx-rtmp/templates/nginx/sites-available/stream.j2 @@ -0,0 +1,38 @@ +server { + listen 80; + listen [::]:80; + + server_name {{ nginx_rtmp.uri }}; + + root /var/www/stream; + index index.html; + + location / { + try_files $uri $uri/ /index.html; + } + + location /hls { + # Disable cache + add_header Cache-Control no-cache; + + # CORS setup + add_header 'Access-Control-Allow-Origin' '*' always; + add_header 'Access-Control-Expose-Headers' 'Content-Length'; + + # allow CORS preflight requests + if ($request_method = 'OPTIONS') { + add_header 'Access-Control-Allow-Origin' '*'; + add_header 'Access-Control-Max-Age' 1728000; + add_header 'Content-Type' 'text/plain charset=UTF-8'; + add_header 'Content-Length' 0; + return 204; + } + + types { + application/dash+xml mpd; + application/vnd.apple.mpegurl m3u8; + video/mp2t ts; + } + } +} + diff --git a/roles/nginx-rtmp/templates/rtmp.conf.j2 b/roles/nginx-rtmp/templates/rtmp.conf.j2 new file mode 100644 index 0000000000000000000000000000000000000000..f6a926f70c15af84de3f60d68d136a404b638452 --- /dev/null +++ b/roles/nginx-rtmp/templates/rtmp.conf.j2 @@ -0,0 +1,11 @@ +rtmp { + server { + listen 1935; + chunk_size 4096; + application live { + live on; + record off; + } + } +} +