#!/bin/bash ####### ### Update NGINX configuration '' with proper values and optionally copy ### to updated directory structure ####### ### text formatting ansi codes err="\e[1;31m" ok="\e[1;32m" warn="\e[93m" mag="\e[95m" cyan="\e[96m" norm="\e[0m" ### set variables # clear variables unset IP4 unset useCertbot unset CertbotDomain unset CertPath unset KeyPath unset CAChainPath unset DHPath # set variables serverNames_working=() serverNames=() detectedIP=$(ip route get 1 | sed -n 's/^.*src \([0-9.]*\) .*$/\1/p') regexIP4="(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])" regexHostname="(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])" certbotFiles=(cert.pem chain.pem fullchain.pem privkey.pem) hostname=$(hostname) configPath="./etc.${hostname}" # set tags to update tag_sslcert="" tag_sslkey="" tag_dhparam="" tag_cachain="" ### quick intro for the user echo -e "\n${mag}This script will customize the provided NGINX template files for your" echo "environment. You will be prompted for all necessary information. After that," echo "default error pages will be copied to your webroot and your NGINX configuration" echo -e "directory structure will be customized.${norm}\n" echo -e "${warn}You may accept the default option (listed in brackets) by simply" echo "pressing ENTER (i.e. no answer)." echo -e "You may exit this script at any prompt by typing 'X'${norm}\n" ### get local IP address while true; do read -p "What is this NGINX machine's primary local IP4 address? (${detectedIP}) " inputIP case "${inputIP}" in '') IP4="${detectedIP}" break ;; [Xx]*) echo -e "\n${cyan}---exiting---\n${norm}" exit 1 ;; *) # check IP for validity if [[ "${inputIP}" =~ ^${regexIP4}$ ]]; then IP4="${inputIP}" break else echo -e "\n${err}Invalid IP4 format (xxx.xxx.xxx.xxx)${norm}" fi ;; esac done ### get server names for this installation echo -e "\n${mag}NIGNX needs to know what hostnames it should answer. You can pick as many" echo "hostnames as you like. Please ensure you provide fully-qualified domain" echo "names unless you are providing special names such as 'localhost' and fully" echo "understand what that means in this context." echo -e "\nIf you're setting up this system with SSL, then make sure your hostnames" echo "match what appears on your certificates!" echo -e "\n${warn}You will be prompted to enter one hostname at a time." echo "Provide a blank-entry (hit enter) when you're done." echo -e "'X' will exit the script, as always${norm}\n" while true; do read -p "What hostnames should this server answer to? " inputServerName case "${inputServerName}" in '') break ;; [Xx]*) echo -e "\n${cyan}---exiting---\n${norm}" exit 1 ;; *) # check hostname for validity if [[ ! "${inputServerName}" =~ ^${regexHostname}$ ]]; then echo -e "\n${err}Invalid hostname${norm}" else serverNames_working+=("${inputServerName}") fi ;; esac done # create new array with unqiue values only declare -A uniqueSN for name in "${serverNames_working[@]}"; do uniqueSN["${name}"]="" done for sn in "${!uniqueSN[@]}"; do serverNames+=("${sn}") done ### SSL related options # using certbot? while true; do read -p "Are you using Certbot to handle your SSL certificates? (default: NO) " yn case "${yn}" in [Yy]*) useCertbot=1 break ;; [Nn]|'') useCertbot=0 unset CertbotDomain break ;; [Xx]*) echo -e "\n${cyan}---exiting---\n${norm}" exit 1 ;; *) echo -e "\n${err}Please answer (Y)es, (N)o, e(X)it or accept default${norm}" ;; esac done # using Certbot: get primary domain name since that how Certbot determines paths if [ "${useCertbot}" -eq 1 ]; then while true; do read -p "What is the primary domain for your Certbot Certificates? " inputCertbotDomain case "${inputCertbotDomain}" in '') echo -e "\n${err}You cannot have an empty domain name${norm}" ;; [Xx]*) echo -e "\n${cyan}---exiting---\n${norm}" exit 1 ;; *) # check hostname for validity if [[ ! "${inputCertbotDomain}" =~ ^${regexHostname}$ ]]; then echo -e "\n${err}Invalid hostname${norm}" else # check if Certbot files exist in path implied from hostname echo -e "\n${cyan}Verifying Certbot files..." echo -e "(/etc/letsencrypt/live/${inputCertbotDomain}/...)${norm}" certbotBadFile=() for certbotFile in "${certbotFiles[@]}"; do if [ -f "/etc/letsencrypt/live/${inputCertbotDomain}/$certbotFile" ]; then echo -e "File: ${certbotFile} -- ${ok}OK${norm}" else echo -e "File: ${certbotFile} -- ${err}X${norm}" certbotBadFile+=("${certbotFile}") fi done if [ -z "${certbotBadFile}" ]; then echo -e "${cyan}Certbot files seem intact${norm}\n" CertbotDomain="${inputCertbotDomain}" break else echo -e "\n${err}The following files are missing from ${inputCertbotDomain}:" echo -e "${warn}${certbotBadFile[@]}${norm}" echo -e "${err}These files are all required for proper SSL operation of NGINX using Certbot.${norm}\n" while true; do read -p "Do you want to use these settings anyways? " yn case "${yn}" in [Yy]*) CertbotDomain="${inputCertbotDomain}" break ;; [Nn]*) break ;; *) ;; esac done fi if [ -n "${CertbotDomain}" ]; then break fi fi ;; esac done fi # Generate paths from CertbotDomain if [ "${useCertbot}" -eq 1 ]; then CertPath="/etc/letsencrypt/live/${CertbotDomain}/fullchain.pem" KeyPath="/etc/letsencrypt/live/${CertbotDomain}/privkey.pem" CAChainPath="/etc/letsencrypt/live/${CertbotDomain}/chain.pem" fi # only process manual certificate paths if NOT using Certbot if [ "${useCertbot}" -eq 0 ]; then # not using Certbot: get location of certificate while true; do read -p "What is the path to your primary SSL certificate? " inputCertPath case "${inputCertPath}" in '') echo -e "\n${err}You cannot have an empty path to your SSL certificate${norm}" ;; [Xx]*) echo -e "\n${cyan}---exiting---\n${norm}" exit 1 ;; *) # validate path if [ -f "${inputCertPath}" ]; then CertPath="${inputCertPath}" break else echo -e "\n${warn}The file you specified doesn't exist${norm}" while true; do read -p "Do you want to use this path anyways? " yn case $yn in [Yy]*) CertPath="${inputCertPath}" break ;; [Nn]*) break ;; *) ;; esac done if [ -n "${CertPath}" ]; then break fi fi ;; esac done # not using Certbot: get location of private key while true; do read -p "What is the path to your primary SSL private key? " inputKeyPath case "${inputKeyPath}" in '') echo -e "\n${err}You cannot have an empty path to your SSL private key${norm}" ;; [Xx]*) echo -e "\n${cyan}---exiting---\n${norm}" exit 1 ;; *) # validate path if [ -f "${inputKeyPath}" ]; then KeyPath="${inputKeyPath}" break else echo -e "\n${warn}The file you specified doesn't exist${norm}" while true; do read -p "Do you want to use this path anyways? " yn case $yn in [Yy]*) KeyPath="${inputKeyPath}" break ;; [Nn]*) break ;; *) ;; esac done if [ -n "${KeyPath}" ]; then break fi fi ;; esac done # not using Certbot: get location of CA Certificate Chain while true; do read -p "What is the path to your primary SSL CA Chain certificate? " inputCAChainPath case "${inputCAChainPath}" in '') echo -e "\n${err}You cannot have an empty path to your SSL CA Chain certificate${norm}" ;; [Xx]*) echo -e "\n${cyan}---exiting---\n${norm}" exit 1 ;; *) # validate path if [ -f "${inputCAChainPath}" ]; then CAChainPath="${inputCAChainPath}" break else echo -e "\n${warn}The file you specified doesn't exist${norm}" while true; do read -p "Do you want to use this path anyways? " yn case $yn in [Yy]*) CAChainPath="${inputCAChainPath}" break ;; [Nn]*) break ;; *) ;; esac done if [ -n "${CAChainPath}" ]; then break fi fi ;; esac done fi # dhparam: get location of DH Parameters file while true; do read -p "What is the path to your DH Parameters file? (default: /etc/ssl/certs/dhparam.pem) " inputDHPath case "${inputDHPath}" in '') # verify default path exists inputDHPath="/etc/ssl/certs/dhparam.pem" if [ -f "${inputDHPath}" ]; then DHPath="${inputDHPath}" break else echo -e "\n${warn}The file you specified doesn't exist${norm}" while true; do read -p "Do you want to use this path anyways? " yn case $yn in [Yy]*) DHPath="${inputDHPath}" break ;; [Nn]*) break ;; *) ;; esac done if [ -n "${DHPath}" ]; then break fi fi ;; [Xx]*) echo -e "\n${cyan}---exiting---\n${norm}" exit 1 ;; *) # validate path if [ -f "${inputDHPath}" ]; then DHPath="${inputDHPath}" break else echo -e "\n${warn}The file you specified doesn't exist${norm}" while true; do read -p "Do you want to use this path anyways? " yn case $yn in [Yy]*) DHPath="${inputDHPath}" break ;; [Nn]*) break ;; *) ;; esac done if [ -n "${DHPath}" ]; then break fi fi ;; esac done ### PHP-FPM related options # get PHP-FPM usage status while true; do read -p "Are you using PHP-FPM? (default: YES) " yn case $yn in [Yy]*|'') usePHP=1 break ;; [Nn]*) usePHP=0 break ;; [Xx]*) echo -e "\n${cyan}---exiting---\n${norm}" exit 1 ;; *) echo -e "\n${err}Please answer (Y)es, (N)o, e(X)it or accept default${norm}" ;; esac done # get PHP-FPM version if [ "${usePHP}" -eq 1 ]; then while true; do read -p "What version of PHP-FPM are you using? (default: 7.2) " inputPHPVersion case $inputPHPVersion in [[:digit:]]*|+[[:digit:]]*.[[:digit:]]*) phpVersion="$inputPHPVersion" break ;; '') phpVersion=7.2 break ;; [Xx]*) echo -e "\n${cyan}---exiting---\n${norm}" exit 1 ;; *) echo -e "\n${err}That does not seem to be a valid version number${norm}" ;; esac done fi : <<'COMMENTSECTION' ### Write configurations to template files # let user know what's happening echo -e "\n${mag}---------------------${norm}" echo -e "${cyan}Updating template files now" # copy template files to working versions rm -rf "${configPath}" cp -R ./etc "${configPath}" # process SSL snippet echo "updating SSL paths in snippet file" sed -e "s%${tag_sslcert}%${CertPath}%" "${configPath}/nginx/snippets/ssl/ssl_certs.conf" sed -e "s%${tag_sslkey}%${KeyPath}%" "${configPath}/nginx/snippets/ssl/ssl_certs.conf" # process mozModern SSL configuration echo "updating SSL configuration parameters file" echo -e "s%${tag_dhparam}%${DHPath}%" "${configPath}/nginx/conf.d/mozModern_ssl.conf" echo -e "s%${tag_cachain}%${CAChainPath}%" "${configPath}/nginx/conf.d/mozModern_ssl.conf" COMMENTSECTION # debug section echo -e "\n${mag}---------------------${norm}" echo "Local IP4: $IP4" echo -e "${cyan}--------------------${norm}" echo "Using Certbot: $useCertbot" echo "CertbotDomain: $CertbotDomain" echo -e "${cyan}--------------------${norm}" echo "CertPath: $CertPath" echo "KeyPath: $KeyPath" echo "CA-Chain: $CAChainPath" echo "DHPath: $DHPath" echo -e "${cyan}--------------------${norm}" echo "usePHP: $usePHP" echo "PHP Version: $phpVersion" echo -e "${mag}---------------------${norm}\n" exit 0