webinoly/usr/site
Cristhian Martínez Ochoa cc17ed8c2a ads
Donation reminder once a day.
2023-05-25 15:09:19 -07:00

456 lines
19 KiB
Bash

#!/bin/bash
# Site Manager Plugin (Create, delete and de/activate)
# Syntax: site <domain> <option> <argument>
# Options: -html, -php, -mysql, -wp, -parked, -proxy, -empty, -on, -off, -delete, -delete-all, -list, -cache, -ssl, -force-redirect, -multisite-convert, -clone-from, -replace-content, -redirection, -forward, -info, -env
# Arguments: -cache, -root, -root-path, -subdomain, -ignore-ssl, -wildcard, -raw, -external-db, -revoke, -ssl-crt, -ssl-key, -ssl-ocsp, -subfolder, -from, -to, -http-code, -regex, -manual, -overwrite, -wp-cache-plugins, -dedicated-reverse-proxy, -must-staple, -cache-valid, -skip-cache, -skip-cookie-cache, -query-string-cache, -query-string-never-cache, -query-string-cache-default, -reset, -test-cert, -db-role, -domain-mapping-wp-id
# shopt is necessary for this kind !(html|<toolsport>) of patterns
shopt -s extglob
source /opt/webinoly/lib/general
source /opt/webinoly/lib/sites
check_for_parameters $@
api-events_update sis
[[ -z $empty_param && -z $h && -z $H && -z $help ]] && check_for_nginx -ask
# Evaluate if site to create is WP ( 0 = noWP, 1 = WP ask, 2 = WP default, 3 = WP unattended, 4 = MySQL default, 5 = MySQL unattended )
type="0"
if [[ -n $wp || -n $mysql ]]; then
[[ -n $mysql ]] && type="4" || type="2"
# For legacy support
[[ $wp == "default" ]] && wp=true
[[ $mysql == "default" ]] && mysql=true
# Check for saved DB external data
if [[ ( $wp == "true" || $mysql == "true" ) && -n $(conf_read external-dbh) && -n $(conf_read external-dbu) && -n $(conf_read external-dbp) ]]; then
[[ -n $domain ]] && dona=$(echo $domain$subfolder | sed "s/[^0-9A-Za-z]/_/g") || dona="Webinoly_$(pwgen -s -1)"
if [[ -n $(conf_read external-dbh) && -n $(conf_read external-dbx) ]]; then
exth="$(conf_read external-dbh):$(conf_read external-dbx)"
elif [[ -n $(conf_read external-dbh) ]]; then
exth=$(conf_read external-dbh)
fi
[[ $wp == "true" ]] && wp="[true,true,${exth},${dona},${dona},random,wp_,$(conf_read external-dbu),$(conf_read external-dbp)]"
[[ $mysql == "true" ]] && mysql="[${exth},${dona},${dona},random,$(conf_read external-dbu),$(conf_read external-dbp)]"
echo "${blu}${dim}External DB credentials found!${end}"
fi
if [[ ( -n $wp && $wp != true ) || ( -n $mysql && $mysql != true ) ]]; then
if [[ $wp == "custom" || $mysql == "custom" ]]; then
[[ -n $mysql ]] && type="0" || type="1"
else
[[ -n $wp && $wp != true ]] && value=$wp
[[ -n $mysql && $mysql != true ]] && value=$mysql
# -wp=[setupmysql,setupwp,dbhost,dbname,dbuser,dbpass,dbpref,extdbuser,extdbpass]
custombegin=$(echo "${value}" | cut -c-1)
customlast=$(echo "${value}" | rev | cut -c-1)
if [[ $custombegin == "[" && $customlast == "]" || $mysql == true ]]; then
wpdata=${value:1:-1}
else
echo "${red}[ERROR] Please enter a valid custom value!${end}"
exit 1
fi
# Because MySQL format not have this parameters at the beggining to match WP format. Insert it!
if [[ -n $mysql && $mysql != true ]]; then
wpdata=${wpdata/#/true,false,}
# Insert wp_prefix if external db data is found.
extdata=$(echo $wpdata | cut -d',' -f 7- -s)
if [[ -n $extdata ]]; then
wpdata=$(echo $wpdata | cut -d',' -f -6 -s)
wpdata=${wpdata/%/,false,}
wpdata=${wpdata/%/$extdata}
fi
fi
# Double coma is for lower case convertion
setmsqcustom=$(echo "${wpdata,,}" | cut -d',' -f 1 -s)
setpwpcustom=$(echo "${wpdata,,}" | cut -d',' -f 2 -s)
dbhostcustom=$(echo "${wpdata}" | cut -d',' -f 3 -s)
dbnamecustom=$(echo "${wpdata}" | cut -d',' -f 4 -s)
dbusercustom=$(echo "${wpdata}" | cut -d',' -f 5 -s)
dbpasscustom=$(echo "${wpdata}" | cut -d',' -f 6 -s)
dbprefcustom=$(echo "${wpdata}" | cut -d',' -f 7 -s)
exusercustom=$(echo "${wpdata}" | cut -d',' -f 8 -s)
expasscustom=$(echo "${wpdata}" | cut -d',' -f 9 -s)
[[ ${dbpasscustom,,} == "random" ]] && dbpasscustom=`pwgen -s -1 16`
# Check if we have ALL the parameters.
if [[ $mysql != true && ( -z $setmsqcustom || -z $setpwpcustom || -z $dbhostcustom || -z $dbnamecustom || -z $dbusercustom || -z $dbpasscustom || ( -z $dbprefcustom && -z $mysql && -z $extdata ) || ( -n $exusercustom && -z $expasscustom )) ]]; then
echo "${red}[ERROR] Missing parameters!${end}"
exit 1
fi
if [[ $custombegin == "[" && $customlast == "]" && ((($setmsqcustom == "true" || $setpwpcustom == "true") && -n $dbhostcustom && -n $dbnamecustom && -n $dbusercustom && -n $dbpasscustom && (-n $dbprefcustom || ( -n $mysql && $mysql != true ))) || ($setmsqcustom == "false" && $setpwpcustom == "false")) ]]; then
[[ -n $mysql && $mysql != true ]] && type="5" || type="3"
fi
fi
fi
fi
# Check for valid WP subfolder
[[ -z $subfolder ]] && subfolder=""
if [[ -n $subfolder && ! ( $subfolder =~ ^\/([A-Za-z0-9_\/\-]+)?[^\/]$ ) ]]; then
echo "${red}[ERROR] Please, enter a valid value for subfolder!${end}"
exit 1
elif [[ -n $subfolder && -z $delete && -z $cache && -z $multisite_convert && -z $clone_from && -z $replace_content && -z $wp && -z $html && -z $php && -z $mysql && -z $proxy && -z $env && -z $info ]]; then
echo "${red}[ERROR] Subfolder option not supported!${end}"
exit 1
# Clone-from empty is here to allow -cache=on when cloning a site
elif [[ -n $subfolder && ( $cache == "on" || -n $multisite_convert || -n $replace_content ) && $(is_subfolder $domain $subfolder) != "wp" && -z $clone_from ]]; then
echo "${red}[ERROR] Subfolder not found or is not a WP site!${end}"
exit 1
else
subname=$(echo $subfolder | sed "s/\//_/g")
fi
# Check for stack packages
[[ $type == [123] || -n $php ]] && check_for_php -ask
[[ $type == [24] ]] && check_for_mysql -ask
# Delete all sites
if [[ -n $delete_all ]]; then
api-events_update si7
delete_all_sites
# Create PHP or MySQL site
elif [[ -n $mysql || ( -n $php && -n $domain ) ]]; then
if [[ -n $domain ]]; then
full_empty_not_allowed
if [[ -f /etc/nginx/sites-available/$domain && -n $subfolder && $(is_subfolder $domain $subfolder) != "false" ]]; then
echo "${red}[ERROR] Subfolder${blu} $subfolder ${red}already exists!${end}"
exit 1
elif [[ -n $subfolder ]]; then
[[ ! -f /etc/nginx/sites-available/$domain ]] && create_empty_site
php_subfolder
sudo mkdir -p /var/www/$domain/htdocs$subfolder
sudo chown -R www-data:www-data /var/www
[[ $(conf_read login-www-data) == "true" ]] && sudo chown root:root /var/www
echo "${gre}PHP Subfolder ${blu}'$subfolder' ${gre}successfully added!${end}"
else
if [[ -z $subfolder && $(is_empty_root_site $domain) == "true" ]]; then
sudo sed -i "/locations.conf;/i \ include common/php.conf;" /etc/nginx/sites-available/$domain
echo "${gre}Subfolder configuration found: Main site at${blu} $domain ${gre}root has been successfully set as PHP!${end}"
else
createsite
fi
[[ $(conf_read php-info) != "false" ]] && sudo sed -i '/common\/php.conf/c \ include common/phpx.conf;' /etc/nginx/sites-available/$domain
fi
fi
[[ -n $mysql ]] && wpinstall
# Create EMPTY site
elif [[ -n $empty && -n $domain ]]; then
full_empty_not_allowed
echo "${blu}You've created an EMPTY site, which means that you need to add your own NGINX configuration. ${dim}(/var/www/example.com/*-nginx.conf)${end}"
[[ $empty == "blank" ]] && create_empty_site -full || create_empty_site
# Create HTML site
elif [[ -n $html && -n $domain ]]; then
full_empty_not_allowed
if [[ -f /etc/nginx/sites-available/$domain && -n $subfolder && $(is_subfolder $domain $subfolder) != "false" ]]; then
echo "${red}[ERROR] Subfolder${blu} $subfolder ${red}already exists!${end}"
exit 1
fi
if [[ ( -z $subfolder || ( -n $subfolder && ! -f /etc/nginx/sites-available/$domain )) && $(is_empty_root_site $domain) == "false" ]]; then
create_empty_site
sudo sed -i '/index /c \ index index.html index.htm;' /etc/nginx/sites-available/$domain
elif [[ -z $subfolder && $(is_empty_root_site $domain) == "true" ]]; then
echo "${gre}Subfolder configuration found: Main site at${blu} $domain ${gre}root has been successfully set as HTML!${end}"
fi
sudo sed -i "/index/a \ location $subfolder/ { try_files \$uri \$uri/ =404; }" /etc/nginx/sites-available/$domain
if [[ -n $subfolder ]]; then
sudo mkdir -p /var/www/$domain/htdocs$subfolder
sudo chown -R www-data:www-data /var/www
[[ $(conf_read login-www-data) == "true" ]] && sudo chown root:root /var/www
echo "${gre}HTML Subfolder ${blu}'$subfolder' ${gre}successfully added!${end}"
fi
# Create WP site
elif [[ -n $wp && -n $domain ]]; then
full_empty_not_allowed
if [[ -z $subfolder ]]; then
if [[ $(is_empty_root_site $domain) == "true" ]]; then
wpinstall
sudo sed -i "/locations.conf;/i \ include common/php.conf;" /etc/nginx/sites-available/$domain
echo "${gre}Subfolder configuration found: Main site at${blu} $domain ${gre}root has been successfully set as WP!${end}"
else
createsite
fi
sudo sed -i '/locations.conf/i \ include common/wpcommon.conf;' /etc/nginx/sites-available/$domain
[[ $(conf_read wp-admin-auth) == "purged" ]] && sudo httpauth $domain -wp-admin=off > /dev/null 2>&1
[[ -n $env ]] && sudo site $domain -env=$env
else
if [[ -f /etc/nginx/sites-available/$domain && -n $subfolder && $type == [123] && $(is_subfolder $domain $subfolder) != "false" ]]; then
echo "${red}[ERROR] Subfolder${blu} $subfolder ${red}already exists!${end}"
exit 1
elif [[ -f /etc/nginx/sites-available/$domain && -n $subfolder && $type == [123] ]]; then
wpinstall
else
create_empty_site
fi
wp_subfolder
[[ -n $env ]] && sudo site $domain -env=$env -subfolder=$subfolder
fi
# Convert WP single to Multisite
elif [[ -n $multisite_convert && -f /etc/nginx/sites-available/$domain ]]; then
if [[ $(is_wp $domain $subfolder) == "false" ]]; then
echo "${red}[ERROR] Site${blu} $domain$subfolder ${red}is not a WP site!${end}"
exit 1
fi
wp_conf_retrieve $domain false false $subfolder
if [[ $(is_wp_installed $domain $subfolder) != "true" ]]; then
echo "${red}[ERROR] WordPress site${blu} $domain$subfolder ${red}is empty and still not configured!${end}"
exit 1
elif [[ $(is_parked $domain) == "true" ]]; then
echo "${red}[ERROR] Multisite conversion in a parked site is not allowed!${end}"
exit 1
fi
check=$(is_wp_multisite $domain $subfolder)
if ! [[ $check =~ ^(subdomain|subdirectory|false)$ ]]; then
echo "${red}[ERROR] Task aborted due to an error!${end}"
exit 1
elif [[ $check =~ ^(subdomain|subdirectory)$ ]]; then
echo "${red}[ERROR] Site${blu} $domain$subfolder ${red}is already in multisite configuration!${end}"
exit 1
fi
wp_multisite_convertion
# Parked Domain
elif [[ -n $parked && -n $domain ]]; then
full_empty_not_allowed
parked_domain
# Reverse proxy
elif [[ -n $proxy && -n $domain ]]; then
reverse_proxy
# Forward domain
elif [[ -n $forward && -n $domain ]]; then
full_empty_not_allowed
forward_domain
# Site disabled
elif [[ -n $off && ! -L /etc/nginx/sites-enabled/$domain && -f /etc/nginx/sites-available/$domain ]]; then
echo "${gre}Seems like your site${blu} $domain ${gre}is already disabled!${end}"
elif [[ -n $off && -L /etc/nginx/sites-enabled/$domain ]]; then
api-events_update si5
echo "${gre}Site${blu} $domain ${gre}has been successfully disabled!${end}"
sudo rm /etc/nginx/sites-enabled/$domain
# Site re-enabled
elif [[ -n $on && -L /etc/nginx/sites-enabled/$domain ]]; then
echo "${gre}Site${blu} $domain ${gre}is already enabled!${end}"
elif [[ -n $on && ! -L /etc/nginx/sites-enabled/$domain && -f /etc/nginx/sites-available/$domain ]]; then
api-events_update si4
sudo ln -s /etc/nginx/sites-available/$domain /etc/nginx/sites-enabled/$domain
echo "${gre}Site${blu} $domain ${gre}has been successfully enabled!${end}"
# Redirection Manager
elif [[ -n $redirection && -f /etc/nginx/sites-available/$domain ]]; then
check_for_nginx
redirection_manager
# SSL (Letsencrypt)
elif [[ -n $ssl ]]; then
if [[ $ssl == "renew" && -z $domain ]]; then
# Post-Hook removed because we always restart nginx at the end of site command
sudo certbot renew
elif [[ $ssl == "force-renewal-all" && -z $domain ]]; then
sudo certbot renew --force-renewal
elif [[ $ssl == "force-renewal" && -z $manual && -z $wildcard && -f /etc/nginx/sites-available/$domain && -f /etc/letsencrypt/live/$domain/fullchain.pem ]]; then
# Normal certs (not-manual) can be renewed easily using this way!
sudo certbot renew --cert-name $domain --force-renewal
elif [[ ( $ssl == "on" || $ssl == "force-renewal" ) && -f /etc/nginx/sites-available/$domain ]]; then
api-events_update si10
if [[ $(is_ssl $domain) == "true" && $ssl != "force-renewal" ]]; then
echo "${gre}SSL is already enabled for your site -${blu} $domain ${end}"
elif [[ -n $ssl_crt || -n $ssl_key ]]; then
if [[ -f $ssl_crt && -f $ssl_key ]]; then
ssl_nginx
echo "${gre}Your Custom SSL Cert have been successfully enabled on your site -${blu} $domain${end}"
else
echo "${red}[ERROR] Custom SSL cert files not found! ${end}"
exit 1
fi
elif [[ -n $add_to_wildcard ]]; then
if [[ $add_to_wildcard == true ]]; then
echo "${gre}Please, enter a valid Wildcard SSL Domain! ${end}"
read -p "${blu}Domain: ${end}" add_to_wildcard
add_to_wildcard=${add_to_wildcard:-NeverMatchDotCom}
fi
# Check if domain is a subdomain that can be used in the wildcard cert.
if [[ $domain == *.*."$add_to_wildcard" ]]; then
echo "${red}[ERROR] Wildcard Certs only support first-level subdomains!${end}"
exit 1
elif [[ ! -d /etc/letsencrypt/live/$add_to_wildcard ]]; then
echo "${red}[ERROR] Wildcard Cert not found!${end}"
exit 1
elif [[ $(is_ssl_wildcard $add_to_wildcard) != "true" ]]; then
echo "${red}[ERROR] Seem like you are trying to use a cert that is not Wildcard!${end}"
exit 1
elif [[ $domain == *."$add_to_wildcard" ]]; then
ssl_nginx
# No need of force-redirect check because this site is always subdomain and subdomains are not supported in force-redirect.
[[ $(is_wp $domain) == "true" ]] && wp_db_update $domain "https://${domain}"
echo "${gre}Your site${blu} $domain ${gre}have been successfully added to the${blu} $add_to_wildcard ${gre}wildcard cert.${end}"
else
echo "${red}[ERROR] Seems like your site is not a valid subdomain!${end}"
exit 1
fi
else
site_ssl_on
fi
elif [[ $ssl == "off" && -f /etc/nginx/sites-available/$domain ]]; then
api-events_update si11
[[ $(is_ssl $domain) == "true" ]] && site_ssl_off || echo "${gre}SSL is already disabled for your site${blu} $domain ${end}"
elif [[ $ssl == "off" && ! -f /etc/nginx/sites-available/$domain && -f /etc/letsencrypt/live/$domain/cert.pem ]]; then
echo "${red}[WARNING] SSL Orphan-Cert found and will be revoked automatically!${end}"
ssl_revoke
elif [[ -n $domain && ! -f /etc/nginx/sites-available/$domain ]]; then
echo "${red}[ERROR] Domain not found! ${end}"
exit 1
else
echo "${red}[ERROR] Invalid value for SSL command! ${end}"
exit 1
fi
# Force www or non-www redirect (www, root, off)
elif [[ -n $force_redirect && -f /etc/nginx/sites-available/$domain ]]; then
force_redirect
# Staging and Clone sites
elif [[ -n $clone_from ]]; then
if [[ ! -f /etc/nginx/sites-available/$clone_from ]]; then
echo "${red}[ERROR] Site/domain ${blu}'$clone_from'${red} not found!${end}"
exit 1
elif [[ -f /etc/nginx/sites-available/$domain && -z $subfolder && $overwrite != "on" ]]; then
echo "${red}[ERROR] Can not create site${blu} $domain ${red}because already exists!${end}"
exit 1
elif [[ -f /etc/nginx/sites-available/$domain && -n $subfolder && $(is_subfolder $domain $subfolder) != "false" && $overwrite != "on" ]]; then
echo "${red}[ERROR] Subfolder ${blu}'$subfolder'${red} already exists!${end}"
exit 1
elif [[ $(is_parked $clone_from) == "true" ]]; then
echo "${red}[ERROR] Cloning a parked site is not allowed!${end}"
exit 1
fi
if [[ $(is_wp $clone_from $subfolder) == "true" ]]; then
wp_conf_retrieve $clone_from true false $subfolder
iswpclone="true"
if [[ -z $wp_dbhost ||-z $wp_dbhost_host || -z $wp_dbname || -z $wp_dbpref ]]; then
echo "${red}[ERROR] Can not retrieve WP data ${dim}(WP Configuration corrupted)!${end}"
exit 1
elif [[ ( $wp_dbhost_host == "localhost" && $(check_mysql_connection localhost $mysql_param) != "true" ) || ( $wp_dbhost_host != "localhost" && $(check_mysql_connection $wp_dbhost_host $wp_dbhost_port any -login-file -master-admin) != "true" ) ]]; then
echo "${red}[ERROR] Database connection failed! ${dim}($wp_dbhost)${end}"
exit 1
elif [[ $(is_wp_multisite $clone_from $subfolder) != "false" ]]; then
echo "${red}[ERROR] WordPress Multisite can not be cloned!${end}"
exit 1
elif [[ $(is_wp_installed $clone_from $subfolder) != "true" ]]; then
echo "${dim}[INFO] WordPress is empty and still not configured in ${clone_from}${subfolder} site!${end}"
fi
elif [[ -n $subfolder && $(is_subfolder $clone_from $subfolder) == "false" ]]; then
echo "${red}[ERROR] Subfolder not found!${end}"
exit 1
fi
cloning_site
# Replace Content
elif [[ -n $replace_content && -f /etc/nginx/sites-available/$domain ]]; then
if [[ $(is_wp $domain $subfolder) != "true" ]]; then
echo "${red}[ERROR] Site${blu} $domain$subfolder ${red}is not a WordPress site!${end}"
exit 1
fi
wp_replace_content
# WordPress Environment Type (should be here after cloning site for precedence)
elif [[ -n $env && -f /etc/nginx/sites-available/$domain ]]; then
wp_env_type
nginx_not="true" # Nginx-Reload not-needed.
# ENV should be always before cache for precedence
# FastCGI Cache
elif [[ -n $cache && -f /etc/nginx/sites-available/$domain ]]; then
wp_cache
# Delete site (should be here after cache for precedence)
elif [[ -n $delete && -f /etc/nginx/sites-available/$domain ]]; then
api-events_update si6
if [[ $domain == "default" || $domain == $ADMIN_TOOLS_SITE ]]; then
echo "${red}[ERROR] System sites can not be removed!${end}"
exit 1
elif [[ -n $subfolder ]]; then
deletesite_subfolder
else
deletesite
fi
# List Sites
elif [[ -n $list && -z $redirection ]]; then
list_sites
nginx_not="true" # Nginx-Reload not-needed.
# Site Info
elif [[ -n $info && -f /etc/nginx/sites-available/$domain ]]; then
[[ -n $subfolder ]] && site_info_subfolder || site_info
nginx_not="true" # Nginx-Reload not-needed.
elif [[ -n $help || -n $h || -n $H || $empty_param == "true" ]]; then
help_message
# Catch ERROR
elif [[ -n $domain && ! -f /etc/nginx/sites-available/$domain ]]; then
echo "${red}[ERROR] Site${blu} $domain ${red}doesn't exists, please enter a valid domain name!${end}"
exit 1
else
echo "${red}[ERROR] Please, enter a valid option! ${end}"
exit 1
fi
shopt -u extglob
[[ $(conf_read nginx) == "true" && -z $nginx_not && $(conf_read nginx-reload) != "false" ]] && sudo systemctl reload nginx
ads_donate
api-events_update sie