Nginx RTMP dynamic stream name - php

I'm trying to create a simple RTMP/HLS server to be able to stream to and to view streams from, however, I am unable to change the name of the directory to which nginx-rtmp-module (module) saves the data.
Everything works just fine, I am able to stream to server and then view the HLS stream in browser, however, the only way to do so is to enter the Stream Key as the target folder on the server to get the m3u8 file.
Currently I have the following settings:
Stream key is generated on the server and then shown to the client
Client enters: rtmp://live.local/live as the endpoint and then inserts the key generated in step 1
Upon the request to start the stream, module calls on_publish to http://app.local/stream/start where at first, it checks if the key exists in the database, and if it is, it then creates new database entry for stream (with UUID as the primary key), receives the key obtained through entry creation and returns it to the script
Script takes the UUID obtained in step 3, then it uses SHA-512 algorithm to generate unique string (which was planned to be used as the directory name)
After hashing is performed, script returns 301 with location header
The stream itself is now renamed, however the folder in which files are stored is still the Stream Key instead of hashed value obtained in step 4 and returned in step 5.
Does anybody know on how to:
Rename stream (I guess I've done that already)
Rename directory for the stream files
OR is there a way to dynamically rewrite all requests, for example, client requests http://live.local/stream/here_is_the_hashed_uuid/index.m3u8, php takes the hash value, gets the list of active streams, hashes every streams' uuid and if matched, returns files from the other directory
PS: Just a small example of what I have now and what I want to achieve
Stream key: test_stream_key_user_1
Hashed key: 73E179A6DB3796A3120319BFE80763427A2122253A5C1D347461268304B28CEB98CE3813DDF5FA8B7173937ED9386169FD3BF8E8C3765BC53BB151C7F5B1431E
Current directory naming: /tmp/hls/test_stream_key_user_1/index.m3u8
Desired directory naming: /tmp/hls/73E179A6DB3796A3120319BFE80763427A2122253A5C1D347461268304B28CEB98CE3813DDF5FA8B7173937ED9386169FD3BF8E8C3765BC53BB151C7F5B1431E/index.m3u8
PPS: I thought that my nginx config files might help.
RTMP configuration
server {
listen 1935;
ping 30s;
notify_method get;
notify_update_timeout 10s;
application live {
live on;
hls on;
hls_nested on;
hls_path /tmp/hls;
hls_fragment 3;
hls_playlist_length 60;
on_publish http://app.local/api/stream/start;
on_done http://app.local/api/stream/stop;
on_update http://app.local/api/stream/update;
}
}
Server Configuration (APP)
server {
listen 80;
listen [::]:80;
root #replaced#;
index index.php index.html index.htm index.nginx-debian.html;
server_name app.local www.app.local;
location / {
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
# PHP-FPM Configuration Nginx
location ~ \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass unix:/var/run/php/php7.3-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
location /api {
try_files $uri $uri/ /index.php?$query_string;
}
location /sitemap.xml {
try_files $uri $uri/ /index.php?$query_string;
}
location /login {
try_files $uri $uri/ /index.php?$query_string;
}
location /broadcasting {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ /\.ht {
deny all;
}
}
Server Configuration (LIVE)
server {
listen 80;
listen [::]:80;
root #replaced#;
index index.html index.htm index.nginx-debian.html;
server_name live.local www.live.local;
location /stat {
rtmp_stat all;
rtmp_stat_stylesheet original_stat.xsl;
}
location /control {
rtmp_control all;
}
location ~ \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass unix:/var/run/php/php7.3-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
location /stream {
try_files $uri $uri/ /index.php?$query_string;
}
location /hls {
add_header 'Access-Control-Allow-Origin' '*' always;
add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';
add_header 'Access-Control-Allow-Headers' 'Range';
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Headers' 'Range';
add_header 'Access-Control-Max-Age' 1728000;
add_header 'Content-Type' 'text/plain charset=UTF-8';
add_header 'Content-Length' 0;
return 204;
}
types {
application/dash+xml mpd;
application/vnd.apple.mpegurl m3u8;
video/mp2t ts;
}
root /tmp;
add_header Cache-Control no-cache;
}
location /dash {
root /tmp;
add_header Cache-Control no-cache;
add_header 'Access-Control-Allow-Origin' '*' always;
}
}

Related

Laravel assets and routes returning 403 after deploying on production server using nginx

The routes and assets are loading properly on local server. However, after I deployed on production server using nginx, only the root url is working which is http://calculator.example.com. But all the assets are returning 403. Also when I try to access any routes for eg: http://calculator.example.com/page-1/ it is also returning 403.
Nginx config:
server {
listen 80;
server_name calculator.example.com;
root /var/www/html/calculator/public;
add_header X-Frame-Options "SAMEORIGIN";
add_header X-XSS-Protection "1; mode=block";
add_header X-Content-Type-Options "nosniff";
index index.html index.htm index.php;
charset utf-8;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location = /favicon.ico { access_log off; log_not_found off; }
location = /robots.txt { access_log off; log_not_found off; }
error_page 404 /index.php;
location ~ .php$ {
fastcgi_pass unix:/var/run/php/php7.2-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
include fastcgi_params;
}
location ~ /.(?!well-known).* {
deny all;
}
}
If you have directory indexing off, and is having this problem, it's probably because the try_files you are using has a directory option:
location / {
try_files $uri $uri/ /index.php?$query_string;
} ^ that is the issue
Remove it and it should work:
location / {
try_files $uri /index.php?$query_string;
}
Why this happens
TL;DR: This is caused because nginx will try to index the directory, and be blocked by itself. Throwing the error mentioned by OP.
try_files $uri $uri/ means, from the root directory, try the file pointed by the uri, if that does not exists, try a directory instead (hence the /). When nginx access a directory, it tries to index it and return the list of files inside it to the browser/client, however by default directory indexing is disabled, and so it returns the error "Nginx 403 error: directory index of [folder] is forbidden".
Directory indexing is controlled by the autoindex option: https://nginx.org/en/docs/http/ngx_http_autoindex_module.html
First, you need check if requests have been passed to app.
if 403 be returned in nginx, i think issue is user run nginx not have permission to access or execute code.
if 403 be returned in php app, please debug normally.
This issue got resolved after I removed the deny all for other location:
location ~ /.(?!well-known).* {
deny all;
}

NginX - path frameworks with index.php slash path slash path

I am building a docker collection that will eventually have the following containers (and more)
web (nginx)
proxy (reverse proxy nginx)
php-fpm
the web will have the allowance for several frameworks to be added via folders and subfolders
./folder1/folder2/codeigniter
./folder3/folder4/laravel
the folders for codeigniter and laravel are symlinks to a public folder
the index.php page works and shows the default routes without issue.
but when I try to get to a different page such as
/folder3/folder4/laravel/index.php/path/somwhere
I get a 404 error message.
I want to be able to do this without mapping an nginx location directive for EVERY FOLDER...
this is what my conf files looks like:
server {
listen 8100 default_server;
listen [::]:8100 default_server ipv6only=on;
server_name localhost;
root /var/www/public;
index index.php index.html index.htm;
location / {
add_header 'Access-Control-Allow-Origin' '*';
add_header "Access-Control-Allow-Headers" "Authorization, Origin, X-Requested-With, Content-Type, Accept";
add_header "Access-Control-Allow-Methods" "GET, POST, OPTIONS, HEAD";
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' '*';
#
# Tell client that this pre-flight info is valid for 20 days
#
add_header 'Access-Control-Max-Age' 1728000;
return 204;
}
try_files $uri $uri/ =404;
}
location ~ \.php$ {
try_files $uri $uri/ index.php?$args;
fastcgi_pass php-fpm-56:9000;
fastcgi_index index.php;
fastcgi_buffers 16 16k;
fastcgi_buffer_size 32k;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
#fixes timeouts
fastcgi_read_timeout 600;
include fastcgi_params;
}
location ~ /\.ht {
deny all;
}
}
what am I doing wrong here?
keep in mind, I want to use "/folder/index.php/path/path"
I DO NOT WANT
"/folder/path/path"
nor do I want to create a location entry for every new folder I create
i try to use codeifniter,
as an example
I will access
http://192.168.100.100/CI/CI_1/CI_1/index.php/main/index
after I tried this way, the results are according to what I attach
location /CI/CI_1/CI_1 {
autoindex on;
try_files $uri $uri/ /CI/CI_1/CI_1/index.php?/$request_uri;
}
Thanks

How to deploy laravel with nginx using wildcard

I want to deploy my laravel application with nginx using wildcard domain.
But that not work correctly. I have this error:
Corrupted Content Error
The site at http://www.exemple.com/ has experienced a network protocol violation that cannot be repaired.
The page you are trying to view cannot be shown because an error in the data transmission was detected.
Please contact the website owners to inform them of this problem.
An example for my laravel routing
<?php
Route::group(['domain' => "{sub}.exemple.com"], function() {
// load site content
});
This is my nginx configuration:
server {
# Update max body size
client_max_body_size 20M;
# SSL configuration
listen 443 ssl http2 default_server;
listen [::]:443 ssl http2 default_server ipv6only=on;
ssl on;
include /etc/nginx/snippets/self-signed.conf;
include /etc/nginx/snippets/ssl-params.conf;
# Route and app index
root /var/www/site/public;
index index.php index.html;
# Make site accessible from https://www.exemple.com
server_name ~^([a-z]+)\.exemple\.com$;
location / {
if ($http_x_forwarded_proto != "https") {
return 301 https://$1.exemple.com$request_uri;
}
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass unix:/var/run/php/php7.1-fpm.sock;
fastcgi_index index.php;
fastcgi_param SERVER_NAME $host;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
location ~ /\.ht {
deny all;
}
location ~* \.(?:ico|gif|jpe?g|png)$ {
expires 7d;
add_header Pragma public;
add_header Cache-Control "public";
access_log off;
}
location ~* \.(css|js|ttf)$ {
expires 1d;
access_log off;
add_header Cache-Control "public";
}
}

Nginx - Redirecting all request including .php to single PHP script?

I've been Googling this for a while but can't seem to find a solution.
At the moment I have a config file setup on Nginx to send all requests regardless of file extension to a single index.php file. However, it ignores requests ending with .php and will throw a 404 if it's not there or, try to execute it if it is.
How can I configure Nginx to send .php requests to the index.php file too so I can use it to handle all file requests, not just non-PHP files?
My config file currently looks like the following:
server {
listen 80;
listen 443;
ssl on;
ssl_certificate /somecrt.crt;
ssl_certificate_key /somekey.key;
root /sites/;
index index.php;
server_name somesite.net;
access_log /sites/logs/access.log;
error_log /sites/logs/error.log;
location ~ /\. { deny all; }
location / {
# First attempt to serve request as file, then
# as directory then fall back to index.php
try_files $uri $uri/ /index.php?$args;
# Uncomment to enable naxsi on this location
# include /etc/nginx/naxsi.rules
}
location ~ \.php$ {
try_files $uri /index.php?$args =404;
fastcgi_pass unix:/var/run/php5-fpm.sock;
# fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
include fastcgi_params;
}
}
After some more Googling "nginx: Map single static URL to a PHP file" helped me figure out the solution. So the new config is now:
server {
listen 80;
listen 443;
ssl on;
ssl_certificate /somecrt.crt;
ssl_certificate_key /somekey.key;
root /sites/;
index index.php;
server_name somesite.net;
access_log /sites/logs/access.log;
error_log /sites/logs/error.log;
location ~ /\. { deny all; }
location / {
include fastcgi_params;
fastcgi_pass unix:/var/run/php5-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root/index.php;
}
}
With this config, all requests will be sent to the single index.php.
Of course, this will include static files such as image files which will probably impact Nginx server performance. In that case, you might want to add another location block before it if you want to exclude certain kind of requests.
For example, to exclude jpgs and gifs:
location ~ \.(jpg|gif) {
try_files $uri =404;
}

Does nginx fastcgi_pass support variables?

I would like to use dynamic host resolution with nginx and fastcgi_pass.
When fastcgi_pass $wphost:9000; is set in the conf then nginx displays the error
[error] 7#7: *1 wordpress.docker could not be resolved (3: Host not found),
but when I set fastcgi_pass wordpress.docker:9000;it is working except for the fact the that after a wordpress restart nginx still points to an old ip.
server {
listen [::]:80;
include /etc/nginx/ssl/ssl.conf;
server_name app.domain.*;
root /var/www/html;
index index.php index.html index.htm;
resolver 172.17.42.1 valid=60s;
resolver_timeout 3s;
location / {
try_files $uri $uri/ /index.php?q=$uri&$args; ## First attempt to serve request as file, then as directory, then fall back to index.html
}
#error_page 404 /404.html;
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
set $wphost wordpress.docker;
# pass the PHP scripts to FastCGI server listening on wordpress.docker
location ~ \.php$ {
client_max_body_size 25M;
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass $wphost:9000;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param SCRIPT_NAME $fastcgi_script_name;
fastcgi_index index.php;
include fastcgi_params;
}
location ~* \.(jpg|jpeg|gif|png|css|js|ico|xml)$ {
add_header Pragma public;
add_header Cache-Control "public, must-revalidate, proxy-revalidate";
access_log off;
log_not_found off;
expires 168h;
}
# deny access to . files, for security
location ~ /\. {
access_log off;
log_not_found off;
deny all;
}
}
I have different virtual host configuration where I use proxy_pass http://$hostname; and in this setup everything is working as expected and the host is found.
After trying different options I wonder if fastcgi_pass does support variables
It does work if you pass the upstream as a variable instead, for example:
upstream fastcgi_backend1 {
server php_node1:9000;
}
upstream fastcgi_backend2 {
server php_node2:9000;
}
server {
listen 80;
server_name _;
set $FASTCGI_BACKEND1 fastcgi_backend1;
set $FASTCGI_BACKEND2 fastcgi_backend2;
location ~ ^/site1/index.php$ {
fastcgi_pass $FASTCGI_BACKEND1;
}
location ~ ^/site2/index.php$ {
fastcgi_pass $FASTCGI_BACKEND2;
}
}

Categories