Skip to content

Instantly share code, notes, and snippets.

@ljm42
Last active Dec 7, 2020
Embed
What would you like to do?
updates to unRAID's /etc/rc.d/rc.nginx file
#!/bin/bash
#
# Nginx daemon control script.
# Written for Slackware Linux by Cherife Li <cherife-#-dotimes.com>.
# limetech: modified for unRAID
# with suggestions from forum member "ljm42"
BIN=/usr/sbin/nginx
PID=/var/run/nginx.pid
ORG=/var/run/nginx.origin
CONF=/etc/nginx/nginx.conf
EMHTTP=/etc/nginx/conf.d/emhttp-servers.conf
# read settings
if [[ -a /boot/config/ident.cfg ]]; then
/usr/bin/fromdos </boot/config/ident.cfg >/var/tmp/ident.cfg
source /var/tmp/ident.cfg
fi
# preset default values
[[ -z $START_PAGE ]] && START_PAGE=Main
[[ -z $BIND_MGT ]] && BIND_MGT=no
[[ -z $PORT ]] && PORT=80
[[ -z $PORTSSL ]] && PORTSSL=443
[[ -z $USE_SSL ]] && USE_SSL=auto
# if specified, prepend a dot for later use
[[ -n $LOCAL_TLD ]] && LOCAL_TLD=".$LOCAL_TLD"
# bind/unbind GUI
if [[ $BIND_MGT == yes ]]; then
ETH=eth0
[[ -e /sys/class/net/bond0 ]] && ETH=bond0
[[ -e /sys/class/net/br0 ]] && ETH=br0
IPV4=$(ip -4 addr show $ETH|awk '/inet /{gsub(/\/.+$/,"",$2);print $2;exit}')
IPV6=$(ip -6 addr show $ETH noprefixroute|awk '/inet6 /{gsub(/\/.+$/,"",$2);print $2;exit}')
[[ -z $IPV6 ]] && IPV6=$(ip -6 addr show $ETH scope global permanent|awk '/inet6 /{gsub(/\/.+$/,"",$2);print $2;exit}')
fi
[[ -z $IPV4 ]] && IPV4='*'
[[ -z $IPV6 ]] && IPV6='::'
# set access mode
if [[ $USE_SSL == auto ]]; then
[[ -f /boot/config/ssl/certs/certificate_bundle.pem ]] && USE_SSL=yes || USE_SSL=no
fi
# pay attention to escaping
define_servers() {
cat <<- EOF > $EMHTTP
# Generated by $0
#
# set root directory for requests
#
root /usr/local/emhttp;
#
# limit the amount of failed auth requests per IP address
#
limit_req_zone \$binary_remote_addr zone=authlimit:1m rate=30r/m;
EOF
if [[ -f /etc/nginx/htpasswd ]]; then
cat <<- 'EOF' >> $EMHTTP
#
# Authentication Settings
#
satisfy any;
allow 127.0.0.1;
allow ::1;
allow unix:;
deny all;
auth_basic "unRAID";
auth_basic_user_file /etc/nginx/htpasswd;
EOF
fi
cat <<- 'EOF' >> $EMHTTP
#
# define our servers
#
server {
#
# Listen on local socket for nchan publishers
#
listen unix:/var/run/nginx.socket default_server;
location ~ /pub/(.*)$ {
nchan_publisher;
nchan_channel_id "$1";
nchan_message_buffer_length $arg_buffer_length;
}
}
EOF
if [[ "$USE_SSL" = "yes" ]]; then
ORIGIN="https://$HOSTSSL:$PORTSSL"
cat <<- EOF >> $EMHTTP
server {
#
# Redirect http requests to https
#
listen $IPV4:$PORT default_server;
listen [$IPV6]:$PORT default_server;
return 302 $ORIGIN\$request_uri;
}
server {
#
# but http always works for localhost
#
listen 127.0.0.1:$PORT default_server;
#
# Port settings for https protocol
#
listen $IPV4:$PORTSSL ssl http2 default_server;
listen [$IPV6]:$PORTSSL ssl http2 default_server;
location ~ /wsproxy/$PORTSSL/ { return 403; }
EOF
if [[ -f /boot/config/ssl/certs/certificate_bundle.pem ]]; then
cat <<- EOF >> $EMHTTP
#
# Enable OCSP stapling
#
ssl_stapling on;
ssl_stapling_verify on;
EOF
fi
else
ORIGIN="http://$HOSTNAME$LOCAL_TLD:$PORT"
cat <<- EOF >> $EMHTTP
server {
#
# Port settings for http protocol
#
listen $IPV4:$PORT default_server;
listen [$IPV6]:$PORT default_server;
location ~ /wsproxy/$PORT/ { return 403; }
EOF
fi
if find /boot/config/*.key &> /dev/null ; then
cat <<- EOF >> $EMHTTP
#
# Default start page
#
location = / {
return 302 $START_PAGE;
}
EOF
else
cat <<- 'EOF' >> $EMHTTP
#
# If no regkey, default page is Tools/Registration
#
location = / {
return 302 Tools/Registration;
}
EOF
fi
cat <<- 'EOF' >> $EMHTTP
#
# enforce request rate limit on failed authentication (401)
#
error_page 401 @401;
location @401 {
limit_req zone=authlimit burst=20;
try_files /401.html =401;
}
#
# deny access to any hidden file (beginning with a .period)
#
location ~ /\. {
return 404;
}
#
# page files handled by template.php
#
location / {
try_files $uri /webGui/template.php$is_args$args;
}
#
# nchan subscriber endpoint
#
location ~ /sub/(.*)$ {
nchan_subscriber;
# nchan_authorize_request <url here>
nchan_channel_id "$1";
nchan_channel_id_split_delimiter ",";
}
#
# websocket proxy
#
location ~ /wsproxy/(.*)$ {
proxy_read_timeout 3600;
proxy_pass http://127.0.0.1:$1;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
}
#
# pass PHP scripts to FastCGI server listening on unix:/var/run/php5-fpm.sock
#
location ~ \.php$ {
include fastcgi_params;
}
#
# enable compression of JS/CSS files
# if version tag on querystring, tell browser to cache indefinitely
#
location ~ \.(js|css)$ {
gzip on;
gzip_disable "MSIE [1-6]\.";
gzip_types text/css application/javascript text/javascript application/x-javascript;
if ( $args ~ "v=" ) {
expires max;
}
}
#
# robots.txt available without authentication
#
location = /robots.txt {
auth_basic off;
allow all;
}
#
# proxy update.htm and logging.htm scripts to emhttpd listening on local socket
#
location = /update.htm {
keepalive_timeout 0;
proxy_read_timeout 180; # 3 minutes
proxy_pass http://unix:/var/run/emhttpd.socket:/update.htm;
}
location = /logging.htm {
proxy_read_timeout 864000; # 10 days(!)
proxy_pass http://unix:/var/run/emhttpd.socket:/logging.htm;
}
#
# proxy webterminal to ttyd server listening on unix:/var/run/ttyd.sock
#
location ~ /webterminal/(.*)$ {
proxy_read_timeout 864000; # 10 days(!)
proxy_pass http://unix:/var/run/ttyd.sock:/$1;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
}
location = /webterminal/auth_token.js {
return 204;
}
#
# proxy dockerterminal to ttyd server listening on unix:/var/tmp/<container-name>.sock
#
location ~ /dockerterminal/(.*)/(.*)$ {
proxy_read_timeout 864000; # 10 days(!)
proxy_pass http://unix:/var/tmp/$1.sock:/$2;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
}
#
# endpoint for checking if DNS rebinding protection is active
#
location = /dnscheck {
auth_basic off;
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range';
add_header 'Access-Control-Max-Age' 86400;
add_header 'Content-Type' 'text/plain; charset=utf-8';
add_header 'Content-Length' 0;
return 204;
}
#
# endpoint for logout
#
location = /logout.htm {
auth_basic_user_file /etc/nginx/htpasswd-logout;
add_header 'Cache-Control' 'no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0';
expires off;
}
}
EOF
echo $ORIGIN > $ORG
}
check_ssl() {
SSL="/boot/config/ssl"
mkdir -p $SSL/certs
HOSTNAME=$(hostname -s)
HOSTFQDN=$(hostname -f)
if [[ ! -f $SSL/dhparam.pem ]]; then
# regenerate dhparam file
# use -dsaparam per: https://security.stackexchange.com/questions/95178/diffie-hellman-parameters-still-calculating-after-24-hours
echo "Regenerating dhparam..."
openssl dhparam -dsaparam -out $SSL/dhparam.pem 2048 &>/dev/null
fi
ln -sf $SSL/dhparam.pem /etc/nginx/dhparam.pem
if [[ -f $SSL/certs/certificate_bundle.pem ]]; then
# use uploaded ssl cert if present
ln -sf $SSL/certs/certificate_bundle.pem /etc/ssl/certs/unraid_bundle.pem
else
if [[ ! -f $SSL/certs/${HOSTNAME}_unraid_bundle.pem ]]; then
# regenerate private key and certificate
echo "Regenerating private key and certificate..."
if [[ "$HOSTNAME" = "$HOSTFQDN" ]]; then
openssl_subject="/O=Self-signed/OU=unRAID/CN=${HOSTNAME}${LOCAL_TLD}"
openssl_altname="DNS:${HOSTNAME}${LOCAL_TLD},DNS:${HOSTNAME}"
else
openssl_subject="/O=Self-signed/OU=unRAID/CN=${HOSTFQDN}"
openssl_altname="DNS:${HOSTFQDN},DNS:${HOSTNAME}${LOCAL_TLD},DNS:${HOSTNAME}"
fi
openssl req -x509 -nodes -days 3650 -newkey rsa:2048 -sha512 -keyout /tmp/key.pem -out /tmp/cert.pem -subj "$openssl_subject" -extensions SAN -config <(cat /etc/ssl/openssl.cnf ; printf "[SAN]\nsubjectAltName=${openssl_altname}") &>/dev/null
cat /tmp/cert.pem /tmp/key.pem > $SSL/certs/${HOSTNAME}_unraid_bundle.pem
rm -f /tmp/cert.pem /tmp/key.pem
fi
ln -sf $SSL/certs/${HOSTNAME}_unraid_bundle.pem /etc/ssl/certs/unraid_bundle.pem
fi
HOSTSSL=$(openssl x509 -noout -subject -nameopt multiline -in /etc/ssl/certs/unraid_bundle.pem |sed -n 's/ *commonName *= //p')
define_servers
}
nginx_status() {
[[ -s $PID && -n "$(cat $PID)" && -d "/proc/$(cat $PID)" ]] && return 0 || return 1;
}
wait_nginx_status() {
for i in {1..10} ; do
if ! nginx_status ; then
break
fi
sleep 1
done
}
nginx_running() {
if ! nginx_status ; then
echo "Nginx is not running"
exit 1
fi
}
nginx_start() {
if nginx_status ; then
echo "Nginx is already running"
exit 1
fi
# Sanity checks.
if [[ ! -r $CONF ]]; then # no config file, exit:
echo "$CONF does not appear to exist. Abort."
exit 1
fi
check_ssl
# side-load ttyd
killall -q ttyd &>/dev/null
rm -f /var/run/ttyd.sock
exec ttyd -d 0 -i /var/run/ttyd.sock login -f root &>/dev/null &
# nginx does not unlink stale unix sockets before rebinding
# see: https://trac.nginx.org/nginx/ticket/753
rm -f /var/run/nginx.socket
echo "Starting Nginx server daemon..."
if [[ -x $BIN ]]; then
$BIN -c $CONF
fi
}
nginx_test_conf() {
echo "Checking configuration for correct syntax and"
echo "then trying to open files referenced in configuration..."
$BIN -t -c $CONF
}
nginx_term() {
if nginx_running ; then
echo "Shutdown Nginx quickly..."
killall -q ttyd &>/dev/null
kill -TERM $(cat $PID)
wait_nginx_status
fi
}
nginx_stop() {
if nginx_running ; then
echo "Shutdown Nginx gracefully..."
killall -q ttyd &>/dev/null
kill -QUIT $(cat $PID)
wait_nginx_status
fi
}
nginx_reload() {
# only stop working system if configuration is valid
if nginx_running ; then
check_ssl
if nginx_test_conf ; then
echo "Reloading Nginx configuration..."
kill -HUP $(cat $PID)
wait_nginx_status
else
echo "Invalid configuration, Nginx not reloaded"
return 1
fi
fi
}
nginx_restart() {
# only stop working system if configuration is valid
if nginx_running ; then
if nginx_test_conf ; then
nginx_stop
nginx_start
else
echo "Invalid configuration, Nginx not restarted"
return 1
fi
fi
}
nginx_upgrade() {
if nginx_running ; then
echo "Upgrading to the new Nginx binary."
echo "Make sure the Nginx binary has been replaced with new one"
echo "or Nginx server modules were added/removed."
kill -USR2 $(cat $PID)
wait_nginx_status
kill -QUIT $(cat $PID.oldbin)
fi
}
nginx_rotate() {
if nginx_running ; then
echo "Rotating Nginx logs..."
kill -USR1 $(cat $PID)
fi
}
case "$1" in
check)
nginx_test_conf
;;
start)
nginx_start
;;
term)
nginx_term
;;
stop)
nginx_stop
;;
reload)
nginx_reload
;;
restart)
nginx_restart
;;
port)
echo $PORT
;;
status)
if nginx_running ; then
echo "Nginx is running"
fi
;;
upgrade)
nginx_upgrade
;;
rotate)
nginx_rotate
;;
*)
echo "usage: `basename $0` {check|start|term|stop|reload|restart|status|port|upgrade|rotate}"
exit 1
esac
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment