webinoly/lib/install
Cristhian Martínez Ochoa 6debbfc634 hotfix
Error detecting empty files.
2023-10-19 18:05:33 -07:00

1123 lines
53 KiB
Bash

#!/bin/bash
source /opt/webinoly/lib/general
source /opt/webinoly/lib/headers
readonly cores=$(grep ^processor /proc/cpuinfo | wc -l)
readonly swapm=$(($(grep SwapTotal /proc/meminfo | cut -f 2 -d ':' | tr -d ' ' | cut -f 1 -d 'k')/1024))
readonly swap=$(($swapm/1000))
readonly ramk=$(grep MemTotal /proc/meminfo | cut -f 2 -d ':' | tr -d ' ' | cut -f 1 -d 'k')
readonly ramb=$(($ramk/1000))
[[ $(($ramb%1000)) -gt 700 ]] && readonly ram=$((($ramb/1000)+1)) || readonly ram=$(($ramb/1000))
[[ $(($ramb*30)) -lt 65535 ]] && readonly fd_per_process=65535 || readonly fd_per_process=$(($ramb*30)) # File descriptors per process 3%
# Validation
[[ $cores =~ ^[0-9]+$ ]] || echo "${red}[ERROR] System info (cores) retrieve corrupted!${end}"
[[ $swapm =~ ^[0-9]+$ ]] || echo "${red}[ERROR] System info (swap) retrieve corrupted!${end}"
[[ $ramk =~ ^[0-9]+$ ]] || echo "${red}[ERROR] System info (ram) retrieve corrupted!${end}"
if [[ $(conf_read db-engine) == "mysql" && $ram -lt 1 ]]; then
echo "${red}[ERROR] MySQL is set as database engine!${dim} (Not enough RAM: ${ramb}MB)"
echo "You should consider MariaDB instead for small servers under 2GB.${end}"
exit 1
fi
linux_optim() {
api-events_update ic1
[[ $(conf_read linux-optim) == "true" ]] && return
# Kernel Optimization
if [[ $(conf_read kernel-optim) != "false" ]]; then
echo "${gre}Wait while Webinoly optimize your Ubuntu Operating System...${end}"
api-events_update ic2
[[ -f /etc/sysctl.d/90-webinoly.conf ]] && sudo rm -rf /etc/sysctl.d/90-webinoly.conf
sudo cp /opt/webinoly/templates/general/sysctl /etc/sysctl.d/90-webinoly.conf
sudo modprobe tcp_bbr
# https://github.com/amazonlinux/autotune
# https://github.com/amzn/amzn-drivers/blob/master/kernel/linux/ena/ENA_Linux_Best_Practices.rst
# https://www.brendangregg.com/Slides/AWSreInvent2017_performance_tuning_EC2.pdf
# https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/6/html/performance_tuning_guide/s-memory-tunables
# https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/7/html/performance_tuning_guide/sect-red_hat_enterprise_linux-performance_tuning_guide-configuration_tools-configuring_system_memory_capacity
if [[ $ram -gt 28 ]]; then
# https://mariadb.com/kb/en/configuring-swappiness/
sudo sed -i "/vm.swappiness =/c \vm.swappiness = 1" /etc/sysctl.d/90-webinoly.conf
sudo sed -i "/vm.min_free_kbytes =/c \vm.min_free_kbytes = $(($ramb*20))" /etc/sysctl.d/90-webinoly.conf
sudo sed -i "/vm.dirty_ratio =/c \vm.dirty_ratio = 0" /etc/sysctl.d/90-webinoly.conf
sudo sed -i "/vm.dirty_background_ratio =/c \vm.dirty_background_ratio = 0" /etc/sysctl.d/90-webinoly.conf
sudo sed -i "/vm.dirty_expire_centisecs =/c \vm.dirty_expire_centisecs = 500" /etc/sysctl.d/90-webinoly.conf
sudo sed -i "/#vm.dirty_bytes =/c \vm.dirty_bytes = 5505024000" /etc/sysctl.d/90-webinoly.conf
sudo sed -i "/#vm.dirty_background_bytes =/c \vm.dirty_background_bytes = 917504000" /etc/sysctl.d/90-webinoly.conf
sudo sed -i "/#vm.dirty_writeback_centisecs =/c \vm.dirty_writeback_centisecs = 100" /etc/sysctl.d/90-webinoly.conf
elif [[ $ram -gt 2 ]]; then
# Default is 65M, if RAM >= 3Gb take 3%, and > 28Gb only 2%
sudo sed -i "/vm.min_free_kbytes =/c \vm.min_free_kbytes = $(($ramb*30))" /etc/sysctl.d/90-webinoly.conf
# https://lonesysadmin.net/2013/12/22/better-linux-disk-caching-performance-vm-dirty_ratio/
sudo sed -i "/vm.dirty_ratio =/c \vm.dirty_ratio = 30" /etc/sysctl.d/90-webinoly.conf
sudo sed -i "/vm.dirty_expire_centisecs =/c \vm.dirty_expire_centisecs = 900" /etc/sysctl.d/90-webinoly.conf
sudo sed -i "/vm.swappiness =/c \vm.swappiness = 5" /etc/sysctl.d/90-webinoly.conf
fi
if [[ $ram -gt 1 ]]; then
local shmmni=$(($ram*256))
local msgmni=$(($ram*1024))
else
local shmmni=256
local msgmni=1024
fi
# Although you can apply values larger than 32768 by using the boot parameter ipcmni_extend, the values are still capped to 32768 internally.
[[ $shmmni -gt 32768 ]] && local shmmni=32768
[[ $msgmni -gt 32768 ]] && local msgmni=32768
# https://www.ibm.com/docs/en/db2/11.1?topic=unix-modifying-kernel-parameters-linux
sudo sed -i "/kernel.shmmni =/c \kernel.shmmni = $shmmni" /etc/sysctl.d/90-webinoly.conf
sudo sed -i "/kernel.shmmax =/c \kernel.shmmax = $(($ramk*800))" /etc/sysctl.d/90-webinoly.conf # Less than 80% of total ram
sudo sed -i "/kernel.shmall =/c \kernel.shmall = $(($(getconf PAGE_SIZE)*2))" /etc/sysctl.d/90-webinoly.conf
sudo sed -i "/kernel.msgmni =/c \kernel.msgmni = $msgmni" /etc/sysctl.d/90-webinoly.conf
sudo sed -i "/kernel.sem =/c \kernel.sem = 250 1024000 32 $shmmni" /etc/sysctl.d/90-webinoly.conf
# Also: 'sudo service procps force-reload' but we prefer this method to better display errors (just in case)
sudo sysctl -p -q /etc/sysctl.d/90-webinoly.conf
api-events_update ic3
fi
# File directors per process
[[ -n $(ulimit -Hn) && $fd_per_process -lt $(ulimit -Hn) ]] && local rootfd=$(ulimit -Hn) || local rootfd=$fd_per_process
sudo sed -i "/End of file/i \# WebinolyStart - Don't delete" /etc/security/limits.conf
sudo sed -i "/End of file/i \root - nofile ${rootfd}" /etc/security/limits.conf
sudo sed -i "/End of file/i \* - nofile ${fd_per_process}" /etc/security/limits.conf
# https://mariadb.com/kb/en/configuring-linux-for-mariadb/
sudo sed -i "/End of file/i \mysql soft core unlimited" /etc/security/limits.conf
sudo sed -i "/End of file/i \mysql hard core unlimited" /etc/security/limits.conf
sudo sed -i "/End of file/i \mysql soft nofile 65535" /etc/security/limits.conf
sudo sed -i "/End of file/i \mysql hard nofile 65535" /etc/security/limits.conf
sudo sed -i "/End of file/i \# WebinolyEnd" /etc/security/limits.conf
# File directors for Nginx
[[ ! -d /etc/systemd/system/nginx.service.d ]] && sudo mkdir /etc/systemd/system/nginx.service.d
[[ ! -f /etc/systemd/system/nginx.service.d/nofile_limit.conf ]] && sudo touch /etc/systemd/system/nginx.service.d/nofile_limit.conf
[[ ! -s /etc/systemd/system/nginx.service.d/nofile_limit.conf || -z $(cat -v /etc/systemd/system/nginx.service.d/nofile_limit.conf | grep -m 1 '[^[:space:]]') ]] && sudo echo "[Service]
LimitNOFILE=$fd_per_process" >> /etc/systemd/system/nginx.service.d/nofile_limit.conf
# Disable Transparent Huge Pages
# Just to be sure is disabled, most cloud providers bring this settings disabled by default.
# "madvise" can be good in some cases.
if [[ ! -f /etc/systemd/system/webinoly-disable-thp.service ]]; then
sudo touch /etc/systemd/system/webinoly-disable-thp.service
echo "[Unit]
Description=Disable Transparent Huge Pages (THP)
[Service]
Type=simple
ExecStart=/bin/sh -c \"echo never > /sys/kernel/mm/transparent_hugepage/enabled && echo never > /sys/kernel/mm/transparent_hugepage/defrag\"
[Install]
WantedBy=multi-user.target" >> /etc/systemd/system/webinoly-disable-thp.service
fi
sudo systemctl start webinoly-disable-thp
sudo systemctl enable webinoly-disable-thp > /dev/null 2>&1
# RAM: By default linux takes 10% for /run, we increase this value to 25%! https://github.com/QROkes/webinoly/issues/19
echo "tmpfs /run tmpfs nodev,nosuid,size=$(check_var run-folder-size)%,mode=755 0 0" >> /etc/fstab
sudo mount -o remount tmpfs
swap_create
[[ -n $(conf_read timezone) ]] && set_timezone
sudo systemctl daemon-reload
[[ $(conf_read nginx) == "true" ]] && sudo systemctl restart nginx # We need to kill the process, don't use reload
conf_write linux-optim true
api-events_update ic6
}
linux_purge() {
if [[ $(conf_read linux-optim) == "true" ]]; then
api-events_update pn7
sudo rm -rf /etc/systemd/system/nginx.service.d
sudo rm -rf /etc/sysctl.d/90-webinoly.conf
sudo sed -i '/WebinolyStart/,/WebinolyEnd/{/.*/d}' /etc/security/limits.conf
#sudo sysctl -p -q /etc/sysctl.d/90-webinoly.conf - reload all sysctl, webinoly file doesn't exist at this point!
sudo service procps force-reload
sudo sed -i '/\/run/d' /etc/fstab
sudo mount -o remount tmpfs
# Check in case of upgrading old stacks (before 1.14.0) when this service still not included
if [[ -f /etc/systemd/system/webinoly-disable-thp.service ]]; then
sudo systemctl stop webinoly-disable-thp
sudo systemctl disable webinoly-disable-thp > /dev/null 2>&1
sudo rm /etc/systemd/system/webinoly-disable-thp.service
fi
[[ $recalculate == "on" ]] && swap_delete
sudo systemctl daemon-reload
# Never reload/restart nginx here!
conf_write linux-optim purged
api-events_update pn8
fi
}
nginx_install() {
api-events_update in1
sudo apt -y install nginx
[[ ! -d /var/www ]] && sudo mkdir /var/www
[[ ! -d /etc/nginx/sites-available ]] && sudo mkdir /etc/nginx/sites-available
[[ ! -d /etc/nginx/sites-enabled ]] && sudo mkdir /etc/nginx/sites-enabled
[[ ! -d /etc/nginx/apps.d ]] && sudo mkdir /etc/nginx/apps.d
# In reinstalation (after purge with keep-data) this file don't exist
if [[ -f /etc/nginx/conf.d/default.conf ]]; then
sudo sed -i 's/listen.*80;/listen 80 default_server;/' /etc/nginx/conf.d/default.conf
sudo sed -i 's/listen.*\[::\]:80;/listen [::]:80 default_server;/' /etc/nginx/conf.d/default.conf
sudo mv /etc/nginx/conf.d/default.conf /etc/nginx/sites-available/default
sudo ln -s /etc/nginx/sites-available/default /etc/nginx/sites-enabled/default
fi
sudo nginx -t && sudo systemctl start nginx
sudo systemctl enable nginx
conf_write nginx true
if [[ -d /etc/nginx ]] && systemctl is-active --quiet nginx; then
echo "${gre}Nginx has been installed successfully! ${end}"
else
# Don't need a flag or anything else, because it will be also detected during verify process!
echo "${red}[ERROR] Unexpected error during Nginx installation!${end}"
fi
api-events_update in2
}
php_install() {
api-events_update ip1
if [[ -n $(conf_read php-ver) && $(check_php_version $(conf_read php-ver)) == "true" ]]; then
echo "${gre}PHP version '$(conf_read php-ver)' is set as default.${end}"
else
# Default PHP version
conf_write php-ver $php_default
fi
local ver=$(conf_read php-ver)
sudo apt -y install php${ver}-common php${ver}-cli php${ver}-fpm php${ver}-curl php${ver}-gd php${ver}-imap php${ver}-readline php${ver}-mysql php${ver}-mbstring php${ver}-bcmath php${ver}-opcache php${ver}-zip php${ver}-xml php${ver}-soap php${ver}-imagick php${ver}-msgpack php${ver}-igbinary php${ver}-intl php-pear graphviz ghostscript
conf_write php true
if [[ -d /etc/php/${ver}/fpm ]] && systemctl is-active --quiet php${ver}-fpm; then
echo "${gre}PHP has been installed successfully! ${end}"
else
# Don't need a flag or anything else, because it will be also detected during verify process!
echo "${red}[ERROR] Unexpected error during PHP installation!${end}"
fi
api-events_update ip2
}
mysql_install() {
api-events_update im3
echo "${gre}MySQL/MariaDB version '$(conf_read mysql-ver)' is set as default.${end}"
# debconf-utils for unattended scripts
# debconf-get-selections | grep phpmyadmin <<-- list conf variables
# Generate mysql user passwords
if [[ -z $(conf_read mysql-root) || -z $(conf_read mysql-admin) ]]; then
local AUTOGENPASS_ROOT=`pwgen -s -1 16`
local AUTOGENPASS_ADMIN=`pwgen -s -1 16`
local enc_pass_root=$( echo $AUTOGENPASS_ROOT | openssl enc -a -salt )
local enc_pass_admin=$( echo $AUTOGENPASS_ADMIN | openssl enc -a -salt )
conf_write mysql-root $enc_pass_root
conf_write mysql-admin $enc_pass_admin
else
# In case of re-installation after purge with keep-data option.
local AUTOGENPASS_ROOT=$( echo $(conf_read mysql-root) | openssl enc -d -a -salt )
local AUTOGENPASS_ADMIN=$( echo $(conf_read mysql-admin) | openssl enc -d -a -salt )
conf_write mysql-reinstall true
fi
# MySQL/MariaDB Installation
if [[ $(conf_read db-engine) == "mysql" ]]; then
# We set the root password in the next step after installation.
echo "mysql-community-server mysql-community-server/root-pass password " | debconf-set-selections
#echo "mysql-community-server mysql-community-server/re-root-pass password $AUTOGENPASS_ROOT" | debconf-set-selections
echo "mysql-community-server mysql-server/default-auth-override select Use Strong Password Encryption (RECOMMENDED)" | debconf-set-selections
sudo apt -y install mysql-server
else
# This option is no longer available in recent MariaDB versions, so we set the root password in the next step after installation.
#local ver=$(conf_read mysql-ver)
#echo "mariadb-server-${ver} mysql-server/root_password password $AUTOGENPASS_ROOT" | debconf-set-selections
#echo "mariadb-server-${ver} mysql-server/root_password_again password $AUTOGENPASS_ROOT" | debconf-set-selections
sudo apt -y install apt-transport-https dirmngr mariadb-server
fi
conf_write mysql true
#Instead of mysql_secure_installation we do this: (same but manually, because not acept unattended)
# - Set a password for root accounts
# - Remove the root accounts accessible from outside the localhost.
# - Remove anonymous-user accounts.
# - Delete the test database, accessible by anonymous users.
# - Reload the user privileges tables.
if [[ $(conf_read mysql-reinstall) != "true" ]]; then # Just for new and fresh installations! (not needed when reinstalling)
echo "${blu}${dim}MySQL/MariaDB Secure Installation! ${end}"
sudo mysql --user=root <<_EOF_
DELETE FROM mysql.user WHERE User='';
DELETE FROM mysql.user WHERE User='root' AND Host NOT IN ('localhost', '127.0.0.1', '::1');
DROP DATABASE IF EXISTS test;
DELETE FROM mysql.db WHERE Db='test' OR Db='test\\_%';
CREATE USER IF NOT EXISTS 'admin'@'localhost' IDENTIFIED BY '${AUTOGENPASS_ADMIN}';
GRANT ALL PRIVILEGES ON *.* TO 'admin'@'localhost' WITH GRANT OPTION;
FLUSH PRIVILEGES;
_EOF_
if [[ $(conf_read db-engine) == "mysql" ]]; then
sudo mysql --user=root -e "ALTER USER 'root'@'localhost' IDENTIFIED WITH caching_sha2_password BY '${AUTOGENPASS_ROOT}';FLUSH PRIVILEGES;"
else
sudo mysql --user=root -e "ALTER USER 'root'@'localhost' IDENTIFIED BY '${AUTOGENPASS_ROOT}';FLUSH PRIVILEGES;"
fi
fi
sudo rm -rf $MYSQL_CONF_PATH/${MYSQL_CONF_PREF}-webinoly-login.cnf
if [[ -d /etc/mysql ]] && systemctl is-active --quiet mysql; then
echo "${gre}MySQL/MariaDB has been installed successfully! ${end}"
else
# Don't need a flag or anything else, because it will be also detected during verify process!
echo "${red}[ERROR] Unexpected error during MySQL/MariaDB installation!${end}"
fi
api-events_update im4
}
mysql_client_install() {
api-events_update im1
[[ $(conf_read db-engine) != "mysql" ]] && sudo apt -y install mariadb-client || sudo apt -y install mysql-client
conf_write mysql-client true
if [[ -d /etc/mysql ]] && which mysql >/dev/null ; then
echo "${gre}MySQL/MariaDB Client has been successfully installed!${end}"
else
# Don't need a flag or anything else, because it will be also detected during verify process!
echo "${red}[ERROR] Unexpected error during MySQL/MariaDB installation!${end}"
fi
api-events_update im2
}
#NGINX OPTIM
nginx_optim() {
api-events_update in3
if [[ ! -d /etc/nginx ]]; then
echo "${red}[ERROR] Nginx Optimization process aborted!${end}"
return
fi
# Check if exists in case of server-reset
[[ ! -f /opt/webinoly/templates/source/default ]] && sudo cp -p /etc/nginx/sites-available/default /opt/webinoly/templates/source/
[[ ! -f /opt/webinoly/templates/source/nginx.conf ]] && sudo cp -p /etc/nginx/nginx.conf /opt/webinoly/templates/source/
sudo chown -R www-data:www-data /var/www
[[ $(conf_read login-www-data) == "true" ]] && sudo chown root:root /var/www
if [[ ! -f /etc/ssl/dhparam.pem ]]; then
sudo openssl dhparam -out /etc/ssl/dhparam.pem 2048
sudo chmod 600 /etc/ssl/dhparam.pem
fi
sudo cp -R /opt/webinoly/templates/nginx/common /etc/nginx/common
sudo cp -R /opt/webinoly/templates/nginx/conf.d/* /etc/nginx/conf.d/
sudo cat /opt/webinoly/templates/nginx/nginx.conf > /etc/nginx/nginx.conf
sudo sed -i "/client_max_body_size /c \ client_max_body_size $(check_var max-mb-uploads)m;" /etc/nginx/nginx.conf
sudo sed -i "/worker_rlimit_core /c \worker_rlimit_core $fd_per_process;" /etc/nginx/nginx.conf
sudo sed -i "/worker_rlimit_nofile /c \worker_rlimit_nofile $fd_per_process;" /etc/nginx/nginx.conf
sudo sed -i "/open_file_cache max /c \ open_file_cache max=$(($fd_per_process/3)) inactive=5m;" /etc/nginx/nginx.conf
# Locations
sudo sed -i "s&<locations-deny-extensions>&$(check_var locations-deny-extensions)&" /etc/nginx/common/locations.conf
sudo sed -i "s#<locations-deny-files>#$(check_var locations-deny-files)#" /etc/nginx/common/locations.conf
# WP Cache
[[ $(check_var wpcache-query-strings) == "all" ]] && sudo sed -i '/# URL with a query string should always go to php/,/\} #End/{/.*/d}' /etc/nginx/common/wpfc.conf
sudo sed -i "s#<wpcache-exclude-url>#$(check_var wpcache-exclude-url)#" /etc/nginx/common/wpfc.conf
sudo sed -i "s#<wpcache-exclude-cookie>#$(check_var wpcache-exclude-cookie)#" /etc/nginx/common/wpfc.conf
# Remove it, then add it again to prevent multiple # for each server-reset
sudo sed -i '/ SERVER_NAME /s/#//' /etc/nginx/fastcgi_params
sudo sed -i '/ SERVER_NAME /s/^/#/' /etc/nginx/fastcgi_params
# Needed to prevent duplicates in server-reset, also in reinstallation (after purge with keep-data)
sudo sed -i '/WebinolyCustom/,/WebinolyCustomEnd/{/.*/d}' /etc/nginx/fastcgi_params
echo '# WebinolyCustom
fastcgi_param SCRIPT_FILENAME $request_filename;
fastcgi_param SERVER_NAME $host;
fastcgi_param HTTP_HOST $http_host;
fastcgi_param HTTP_PROXY "";
fastcgi_param HTTP_ACCEPT_ENCODING "";
# WebinolyCustomEnd' >> /etc/nginx/fastcgi_params
# FastCGI Cache size: We take 90% of /run folder size! https://github.com/QROkes/webinoly/issues/19
sudo sed -i "/fastcgi_cache_path/c \fastcgi_cache_path /run/nginx-cache levels=1:2 keys_zone=WORDPRESS:50m max_size=$(((9*$ramb*$(check_var run-folder-size))/1000))m inactive=7d;" /etc/nginx/conf.d/fastcgi.conf
sudo sed -i "/fastcgi_read_timeout/c \fastcgi_read_timeout $(check_var php-max-time)s;" /etc/nginx/conf.d/fastcgi.conf
# www-data sftp default uploads permissions 755 and 644, instead of 775 and 664.
sudo sed -i '/USERGROUPS_ENAB/c \USERGROUPS_ENAB no' /etc/login.defs
# Check for dynamic variables.
sudo systemctl restart nginx # We need to kill the process, don't use reload (I don't know why here, but it's needed!)
[[ -n $(conf_read default-response) ]] && sudo webinoly -default-site=$(conf_read default-response)
[[ -n $(conf_read tools-port-set) ]] && sudo webinoly -tools-port=$(conf_read tools-port-set)
[[ -n $(conf_read tools-site) ]] && sudo webinoly -tools-site=$(conf_read tools-site)
[[ $(conf_read global-access-log-off) =~ ^(false|purged)$ ]] && sudo log -only-error=off || sudo log -only-error=on
[[ -n $(conf_read fastcgi-conf) ]] && sudo webinoly -cache-valid=[$(conf_read fastcgi-conf)]
[[ -n $(conf_read auth-whitelist-ip) ]] && sudo httpauth -whitelist=$(conf_read auth-whitelist-ip)
[[ -n $(conf_read blockip) ]] && sudo webinoly -blockip=$(conf_read blockip)
[[ $(conf_read sftp-www-data) == "true" ]] && sudo webinoly -login-www-data=on
[[ $(conf_read sftp-www-data) == "false" ]] && sudo webinoly -login-www-data=off
http_header_referrer
http_header_hsts
http_header_cache_control
http_header_csp
http_header_permissions_policy
http_header_robots
http_header_xssp
http_header_xcto
http_header_xfo
[[ $(conf_read header-custom) == "true" ]] && sudo webinoly -custom-headers=reload
if [[ $(conf_read xmlrpc) =~ ^(blocked|limited|open)$ ]]; then
if [[ $(conf_read xmlrpc) != "limited" ]]; then
sudo sed -i '/WPxmlrpcStart/,/WPxmlrpcEnd/{/.*/d}' /etc/nginx/common/wpcommon.conf
sudo sed -i '/WPxmlrpcStart/,/WPxmlrpcEnd/{/.*/d}' /etc/nginx/common/wpcommon-noauth.conf
fi
if [[ $(conf_read xmlrpc) == "blocked" ]]; then
echo "# WPxmlrpcStart
location = /xmlrpc.php {
return 403;
}
# WPxmlrpcEnd" >> /etc/nginx/common/wpcommon.conf
echo "# WPxmlrpcStart
location = /xmlrpc.php {
return 403;
}
# WPxmlrpcEnd" >> /etc/nginx/common/wpcommon-noauth.conf
fi
echo "${gre}WordPress XMLRPC successfully configured!${dim} ($(conf_read xmlrpc))${end}"
fi
# Create Direct Access for easy navigation
if [[ ! -L $CURRENT_HOME/sites-available ]]; then
ln -s /etc/nginx/sites-available $CURRENT_HOME
sudo chown -h ${CURRENT_USER}:${CURRENT_USER} $CURRENT_HOME/sites-available
fi
if [[ ! -L $CURRENT_HOME/www ]]; then
ln -s /var/www $CURRENT_HOME
sudo chown -h ${CURRENT_USER}:${CURRENT_USER} $CURRENT_HOME/www
fi
conf_write server-version $svr_version
conf_write nginx-optim true
sudo systemctl reload nginx
echo "${gre}Nginx has been successfully Optimized by Webinoly! ${end}"
api-events_update in4
}
# PHP OPTIM
php_optim() {
api-events_update ip3
local ver=$(conf_read php-ver)
if [[ ! -d /etc/php/${ver}/fpm ]]; then
echo "${red}[ERROR] PHP Optimization process aborted!${end}"
return
fi
# Check if exist in case of server-reset
[[ ! -f /opt/webinoly/templates/source/php.ini ]] && sudo cp -p /etc/php/${ver}/fpm/php.ini /opt/webinoly/templates/source/
[[ ! -f /opt/webinoly/templates/source/www.conf ]] && sudo cp -p /etc/php/${ver}/fpm/pool.d/www.conf /opt/webinoly/templates/source/
[[ ! -f /opt/webinoly/templates/source/php-fpm.conf ]] && sudo cp -p /etc/php/${ver}/fpm/php-fpm.conf /opt/webinoly/templates/source/
sudo sed -i -r "/^[;]?max_execution_time =/c\max_execution_time = $(check_var php-max-time)" /etc/php/$ver/fpm/php.ini
sudo sed -i -r '/^[;]?session.cookie_httponly =/c\session.cookie_httponly = 1' /etc/php/$ver/fpm/php.ini
sudo sed -i -r '/^[;]?expose_php =/c\expose_php = Off' /etc/php/$ver/fpm/php.ini
# post_max must be a little larger and memory a little more larger - https://www.php.net/manual/en/ini.core.php#ini.post-max-size
sudo sed -i -r "/^[;]?upload_max_filesize =/c\upload_max_filesize = $(check_var max-mb-uploads)M" /etc/php/$ver/fpm/php.ini
sudo sed -i -r "/^[;]?post_max_size =/c\post_max_size = $(($(check_var max-mb-uploads)+1))M" /etc/php/$ver/fpm/php.ini
sudo sed -i -r "/^[;]?max_file_uploads =/c\max_file_uploads = $(check_var php-max-files)" /etc/php/$ver/fpm/php.ini
[[ $(check_var php-max-mem) -gt $(($(check_var max-mb-uploads)+1)) ]] && local phpmem=$(check_var php-max-mem) || local phpmem=$(($(check_var max-mb-uploads)+10))
sudo sed -i -r "/^[;]?memory_limit =/c\memory_limit = ${phpmem}M" /etc/php/$ver/fpm/php.ini
sudo sed -i -r "/^[;]?max_input_vars =/c\max_input_vars = $(check_var php-max-input-vars)" /etc/php/$ver/fpm/php.ini
sudo sed -i -r "/^[;]?opcache.memory_consumption=/c\opcache.memory_consumption=$(check_var php-max-mem)" /etc/php/$ver/fpm/php.ini
sudo sed -i -r '/^[;]?opcache.interned_strings_buffer=/c\opcache.interned_strings_buffer=16' /etc/php/$ver/fpm/php.ini
sudo sed -i -r '/^[;]?opcache.max_accelerated_files=/c\opcache.max_accelerated_files=100000' /etc/php/$ver/fpm/php.ini
sudo sed -i -r '/^[;]?opcache.max_wasted_percentage=/c\opcache.max_wasted_percentage=10' /etc/php/$ver/fpm/php.ini
sudo sed -i -r '/^[;]?opcache.enable_cli=/c\opcache.enable_cli=1' /etc/php/$ver/fpm/php.ini
sudo sed -i -r '/^[;]?opcache.enable=/c\opcache.enable=1' /etc/php/$ver/fpm/php.ini
# Not set, unless non-empty!
if [[ $(check_var php-opcache-timestamps) != "false" ]]; then
sudo sed -i -r "/^[;]?opcache.validate_timestamps=/c\opcache.validate_timestamps=$(check_var php-opcache-timestamps)" /etc/php/$ver/fpm/php.ini
fi
if [[ $(check_var php-opcache-reval) != "false" ]]; then
sudo sed -i -r "/^[;]?opcache.revalidate_freq=/c\opcache.revalidate_freq=$(check_var php-opcache-reval)" /etc/php/$ver/fpm/php.ini
fi
[[ -n $(conf_read timezone) ]] && set_timezone
sudo sed -i -r "/^[;]?pm =/c\pm = $(check_var php-pm)" /etc/php/$ver/fpm/pool.d/www.conf
sudo sed -i -r "/^[;]?pm.max_children =/c\pm.max_children = $(check_var php-max-child)" /etc/php/$ver/fpm/pool.d/www.conf
sudo sed -i -r "/^[;]?pm.start_servers =/c\pm.start_servers = $(($(check_var php-max-child)/3))" /etc/php/$ver/fpm/pool.d/www.conf
sudo sed -i -r "/^[;]?pm.min_spare_servers =/c\pm.min_spare_servers = $(($(check_var php-max-child)/3))" /etc/php/$ver/fpm/pool.d/www.conf
sudo sed -i -r "/^[;]?pm.max_spare_servers =/c\pm.max_spare_servers = $((2*($(check_var php-max-child)/3)))" /etc/php/$ver/fpm/pool.d/www.conf
sudo sed -i -r "/^[;]?request_terminate_timeout =/c\request_terminate_timeout = $(check_var php-max-time)" /etc/php/$ver/fpm/pool.d/www.conf
sudo sed -i -r '/^[;]?pm.max_requests =/c\pm.max_requests = 1000' /etc/php/$ver/fpm/pool.d/www.conf
sudo sed -i -r '/^[;]?pm.status_path =/c\pm.status_path = /status' /etc/php/$ver/fpm/pool.d/www.conf
sudo sed -i -r '/^[;]?ping.path =/c\ping.path = /ping' /etc/php/$ver/fpm/pool.d/www.conf
sudo sed -i -r '/^[;]?listen = /c\listen = 127.0.0.1:9000' /etc/php/$ver/fpm/pool.d/www.conf
sudo sed -i -r '/^[;]?listen.allowed_clients = /c\listen.allowed_clients = 127.0.0.1' /etc/php/$ver/fpm/pool.d/www.conf
[[ $(conf_read php-tool-redis) == "true" && -n $(conf_read redis-max-mem) ]] && redis_optim
conf_write php-optim true
sudo systemctl restart php${ver}-fpm
echo "${gre}PHP has been successfully Optimized by Webinoly! ${end}"
api-events_update ip4
}
# MySQL/MariaDB OPTIM
mysql_optim() {
api-events_update im5
if [[ ! -d /etc/mysql ]]; then
echo "${red}[ERROR] MySQL/MariaDB Optimization process aborted!${end}"
return
fi
mysql_default_cnf
# MySQL/MariaDB login data
mysql_login_cnf
if [[ -n $(conf_read mysql-admin) ]]; then
sudo sed -i '/\[client\]/,/# ClientEnd/{/.*/d}' $MYSQL_CONF_PATH/${MYSQL_CONF_PREF}-webinoly-login.cnf
echo "[client]
user = admin
password = $( echo $(conf_read mysql-admin) | openssl enc -d -a -salt )
host = localhost
# ClientEnd" >> $MYSQL_CONF_PATH/${MYSQL_CONF_PREF}-webinoly-login.cnf
fi
# If value is empty we will do nothing, to prevent undesired things (before 1.17.1 these dynvars were not used via command only conf file, now are both).
[[ $(conf_read mysql-log-binary) == "true" ]] && sudo log -mysql=binary -enable
[[ $(conf_read mysql-log-binary) == "false" ]] && sudo log -mysql=binary -disable
[[ $(conf_read mysql-log-general) == "true" ]] && sudo log -mysql=general -enable
[[ $(conf_read mysql-log-general) == "false" ]] && sudo log -mysql=general -disable
[[ $(conf_read mysql-log-slow) == "true" && -z $(conf_read mysql-long-query-time) ]] && sudo log -mysql=slow -enable
[[ $(conf_read mysql-log-slow) == "true" && -n $(conf_read mysql-long-query-time) ]] && sudo log -mysql=slow -enable -long-query-time=$(conf_read mysql-long-query-time)
[[ $(conf_read mysql-log-slow) == "false" ]] && sudo log -mysql=slow -disable
[[ $(conf_read mysql-public-access) == "true" ]] && sudo webinoly -mysql-public-access=on
[[ $(conf_read mysql-public-access) == "false" ]] && sudo webinoly -mysql-public-access=off
# https://mariadb.com/kb/en/mysql_upgrade/
# The mysql_upgrade client is deprecated in MySQL 8. (This process is done automatically)
# Should do it using admin user, root has password and it may be removed in conf file.
# Should be here in optim, because when reinstalling admin login CNF is removed.
if [[ $(conf_read mysql-reinstall) == "true" && $(conf_read db-engine) != "mysql" ]]; then
echo "${blu}${dim}Seems like you are reinstalling MySQL/MariaDB... Upgrading your old tables!${end}"
sudo mysql_upgrade --user=admin --force --silent
conf_delete mysql-reinstall
fi
conf_write mysql-optim true
echo "${gre}MySQL/MariaDB has been successfully Optimized by Webinoly! ${end}"
api-events_update im6
}
nginx_tool_site() {
# Tools site creation
[[ -z $(conf_read tools-port) ]] && conf_write tools-port $tools_port_default
# Don't overwrite in case that exist (after purge with keep-data, for instance)
if [[ ! -f /etc/nginx/sites-available/$ADMIN_TOOLS_SITE ]]; then
sudo site $ADMIN_TOOLS_SITE -empty > /dev/null 2>&1
sudo cp /opt/webinoly/templates/general/admin_tools.conf /etc/nginx/sites-available/$ADMIN_TOOLS_SITE
sudo sed -i "s/<port>/$(conf_read tools-port)/g" /etc/nginx/sites-available/$ADMIN_TOOLS_SITE
sudo sed -i "s/<admin_tools_sitename>/$ADMIN_TOOLS_SITE/g" /etc/nginx/sites-available/$ADMIN_TOOLS_SITE
sudo nginx -t && sudo systemctl reload nginx
fi
# Don't overwrite in case that exist (after purge with keep-data, for instance)
if [[ ! -f /var/www/$ADMIN_TOOLS_SITE/htdocs ]]; then
# Nginx Status Page
sudo touch /var/www/$ADMIN_TOOLS_SITE/htdocs/nginx_status
# Robots.txt file in case someone remove HTTP Auth
sudo touch /var/www/$ADMIN_TOOLS_SITE/htdocs/robots.txt
echo '# Just in case someone remove HTTP Auth protection.
Disallow: /' > /var/www/$ADMIN_TOOLS_SITE/htdocs/robots.txt
sudo chmod 644 /var/www/$ADMIN_TOOLS_SITE/htdocs/robots.txt
sudo chown -R www-data:www-data /var/www/$ADMIN_TOOLS_SITE/htdocs
fi
# in case php was installed before nginx
[[ $(conf_read php) == "true" && ! -f /var/www/$ADMIN_TOOLS_SITE/htdocs/php/index.php ]] && php_tool_site
}
php_tool_site() {
[[ $(conf_read nginx) != "true" ]] && return
# Just for legacy support when tools site were created only with PHP support, today is created since Nginx always.
[[ ! -f /etc/nginx/sites-available/$ADMIN_TOOLS_SITE ]] && nginx_tool_site
# Add PHP options in tools site.
# Status pages
sudo touch /var/www/$ADMIN_TOOLS_SITE/htdocs/ping
sudo touch /var/www/$ADMIN_TOOLS_SITE/htdocs/status
#PHP info site
sudo mkdir -p /var/www/$ADMIN_TOOLS_SITE/htdocs/php
sudo touch /var/www/$ADMIN_TOOLS_SITE/htdocs/php/index.php
sudo echo '<?php phpinfo(); ?>' >> /var/www/$ADMIN_TOOLS_SITE/htdocs/php/index.php
sudo chown -R www-data:www-data /var/www/$ADMIN_TOOLS_SITE/htdocs
}
nginx_tool_ssl() {
api-events_update in5
# Install LetsEncrypt
local certb=0
while [[ $certb -le 3 ]]
do
sudo snap install --classic certbot
# SNAP Repo fails a lot, so we need to be sure and retry!!!
if [[ ! -f /snap/bin/certbot ]]; then
local certb=$(($certb+1))
[[ $certb -le 3 ]] && echo "${red}[ERROR] Certbot installation failed!${dim} We will retry in a moment...($(($certb*30))s)${end}"
[[ $certb -gt 3 ]] && echo "${red}[ERROR] Fatal Error: Certbot cannot be installed after 3 retries!${end}" || sleep $(($certb*20))
else
break
fi
done
[[ ! -L /usr/bin/certbot ]] && sudo ln -s /snap/bin/certbot /usr/bin/certbot
conf_write nginx-tool-ssl true
if which certbot >/dev/null ; then
echo "${gre}Let's Encrypt (certbot) has been installed successfully! ${end}"
else
# Don't need a flag or anything else, because it will be also detected during verify process!
echo "${red}[ERROR] Unexpected error during Let's Encrypt (certbot) installation!${end}"
fi
api-events_update in6
}
nginx_tool_bkp() {
api-events_update in7
# Instalar Duply & Duplicity with S3 support
# Now there is an Official PPA: https://launchpad.net/~duplicity-team/+archive/ubuntu/duplicity-release-git
# We removed SNAP because they removed ARM support, also they are having a lot of issues, they are mentioned they are considering removing snap support.
# https://gitlab.com/duplicity/duplicity/-/issues
# Minimum required, most of them are already installed by default, but we need to be sure: https://gitlab.com/duplicity/duplicity/-/blob/master/debian/control
# Also needed: python3-pip
# Backend for S3: python3-boto3
sudo apt install -y debhelper dh-python python3 gnupg librsync-dev par2 pep8 pylint python3-pytest python3-pytest-cov python3-pytest-runner python3-dev python3-fasteners python3-future python3-mock python3-pexpect python3-setuptools python3-setuptools-scm rdiff rename rsync python3-pip python3-boto3
# Duplicity installation directly from source
# Temporal fix to remove warning - wait for: https://github.com/pypa/pip/issues/10556 - remove from stack purge too! --root-user-action=ignore | Remove from update function also
sudo pip3 install duplicity 2>&1 | grep -v "pip as the 'root' user"
# In future, we need to do the correct way - using virtual env
#sudo apt install python3-venv
#sudo python3 -m venv /opt/duplicity/
#sudo /opt/duplicity/bin/pip install --upgrade pip
#sudo /opt/duplicity/bin/pip install duplicity
#sudo ln -s /opt/duplicity/bin/duplicity /usr/bin/duplicity
# https://sourceforge.net/projects/ftplicity/files/duply%20%28simple%20duplicity%29/
sudo cp /opt/webinoly/templates/general/duply /usr/bin/
sudo chmod 755 /usr/bin/duply
conf_write nginx-tool-bkp true
if which duply >/dev/null && which duplicity >/dev/null ; then
echo "${gre}BackUp packages has been installed successfully! ${end}"
else
# Don't need a flag or anything else, because it will be also detected during verify process!
echo "${red}[ERROR] Unexpected error during BackUp packages installation!${end}"
fi
api-events_update in8
}
php_tool_postfix() {
api-events_update ip5
# Postfix mail
echo "postfix postfix/main_mailer_type select Internet Site" | debconf-set-selections
echo "postfix postfix/mailname string $hostname" | debconf-set-selections
sudo apt -y install postfix
sudo cp -p /etc/postfix/main.cf /opt/webinoly/templates/source/
sudo sed -i '/mydestination =/c \mydestination = localhost' /etc/postfix/main.cf
sudo sed -i '/smtpd_banner =/c \smtpd_banner = $myhostname ESMTP' /etc/postfix/main.cf # https://cisofy.com/lynis/controls/MAIL-8818/
sudo systemctl reload postfix
conf_write php-tool-postfix true
if [[ -d /etc/postfix ]] && systemctl is-active --quiet postfix; then
echo "${gre}Postfix has been installed successfully! ${end}"
else
# Don't need a flag or anything else, because it will be also detected during verify process!
echo "${red}[ERROR] Unexpected error during Postfix installation!${end}"
fi
api-events_update ip6
}
redis_optim() {
if [[ ! -d /etc/redis ]]; then
echo "${red}[ERROR] Redis Optimization process aborted!${end}"
return
fi
local maxmem=$((($(grep MemTotal /proc/meminfo | cut -f 2 -d ':' | tr -d ' ' | cut -f 1 -d 'k')*$(check_var redis-max-mem))/100000))
sudo sed -i "/# maxmemory <bytes>/c\maxmemory ${maxmem}mb" /etc/redis/redis.conf
sudo sed -i "/^maxmemory /c\maxmemory ${maxmem}mb" /etc/redis/redis.conf
sudo sed -i "/# maxmemory-policy/c\maxmemory-policy allkeys-lfu" /etc/redis/redis.conf
sudo systemctl restart redis-server
}
php_tool_redis() {
api-events_update ip7
local ver=$(conf_read php-ver)
# Redis (Object Cache)
sudo apt -y install redis-server php${ver}-redis
redis_optim
sudo systemctl enable redis-server
conf_write php-tool-redis true
if [[ -d /etc/redis ]] && systemctl is-active --quiet redis-server; then
echo "${gre}Redis has been installed successfully! ${end}"
else
# Don't need a flag or anything else, because it will be also detected during verify process!
echo "${red}[ERROR] Unexpected error during Redis installation!${end}"
fi
api-events_update ip8
}
php_tool_memcached() {
api-events_update ip9
local ver=$(conf_read php-ver)
# Memcached (Object Cache)
sudo apt -y install php${ver}-memcached php${ver}-memcache memcached
conf_write php-tool-memcached true
if systemctl is-active --quiet memcached; then
echo "${gre}Memcached has been installed successfully! ${end}"
else
# Don't need a flag or anything else, because it will be also detected during verify process!
echo "${red}[ERROR] Unexpected error during Memcached installation!${end}"
fi
api-events_update ip10
}
mysql_tool_pma() {
api-events_update im7
echo "${blu}${dim}Downloading phpMyAdmin...${end}"
sudo mkdir -p /var/www/$ADMIN_TOOLS_SITE/htdocs/pma
sudo wget --timeout=15 -t 1 -qrO /var/www/$ADMIN_TOOLS_SITE/htdocs/pma.tar.xz https://www.phpmyadmin.net/downloads/phpMyAdmin-latest-all-languages.tar.xz
if [[ -s /var/www/$ADMIN_TOOLS_SITE/htdocs/pma.tar.xz ]]; then
sudo tar -xf /var/www/$ADMIN_TOOLS_SITE/htdocs/pma.tar.xz -C /var/www/$ADMIN_TOOLS_SITE/htdocs/pma
sudo mv /var/www/$ADMIN_TOOLS_SITE/htdocs/pma/phpMyAdmin-*-all-languages/* /var/www/$ADMIN_TOOLS_SITE/htdocs/pma/
sudo rm -rf /var/www/$ADMIN_TOOLS_SITE/htdocs/pma/phpMyAdmin-*-all-languages
sudo rm -rf /var/www/$ADMIN_TOOLS_SITE/htdocs/pma/test
sudo rm -rf /var/www/$ADMIN_TOOLS_SITE/htdocs/pma/setup
sudo rm /var/www/$ADMIN_TOOLS_SITE/htdocs/pma.tar.xz
sudo cp /var/www/$ADMIN_TOOLS_SITE/htdocs/pma/config.sample.inc.php /var/www/$ADMIN_TOOLS_SITE/htdocs/pma/config.inc.php
sudo sed -i "/blowfish_secret/c \$cfg['blowfish_secret'] = '$(pwgen -s -1 32)';" /var/www/$ADMIN_TOOLS_SITE/htdocs/pma/config.inc.php
sudo chown -R www-data:www-data /var/www/$ADMIN_TOOLS_SITE/htdocs/pma
sudo find /var/www/$ADMIN_TOOLS_SITE/htdocs/pma -type f -print0 | sudo xargs -r -0 chmod 644
sudo find /var/www/$ADMIN_TOOLS_SITE/htdocs/pma -type d -print0 | sudo xargs -r -0 chmod 755
conf_write mysql-tool-pma true
if [[ -s /var/www/$ADMIN_TOOLS_SITE/htdocs/pma/config.inc.php ]]; then
echo "${gre}phpMyAdmin has been installed successfully! ${end}"
else
# Don't need a flag or anything else, because it will be also detected during verify process!
echo "${red}[ERROR] Unexpected error during phpMyAdmin installation!${end}"
fi
else
echo "${red}[ERROR] Downloading phpMyAdmin failed!${end}"
fi
api-events_update im8
}
set_timezone() {
if [[ -n $(conf_read timezone) ]] && grep -Fxq $(conf_read timezone) /opt/webinoly/lib/timezone.dat; then
sudo timedatectl set-timezone $(conf_read timezone)
if [[ $(conf_read php) == "true" ]]; then
sudo sed -i "/date.timezone =/c\date.timezone = $(conf_read timezone)" /etc/php/$(conf_read php-ver)/fpm/php.ini
# Don't reload if running inside php-optim process.
[[ $(conf_read status-api) != "ip3" ]] && sudo systemctl reload php$(conf_read php-ver)-fpm
fi
sudo systemctl restart cron
echo "${gre}Timezone has been successfully set!${dim} ($(conf_read timezone)) ${end}"
else
echo "${red}Timezone not found or not valid!${end}"
return 1
fi
}
swap_delete() {
if [[ -n $swap && $swap =~ ^[0-9]+$ && $(conf_read swap-owner) == "webinoly" ]]; then
api-events_update pn9
sudo swapoff -a -v && sudo rm -rf /swapfile
if [[ ! -f /swapfile ]]; then
sudo sed -i '/\/swapfile/d' /etc/fstab
conf_write swap-owner purged
api-events_update pn10
else
echo "${dim}SWAP file is busy or can't be removed!${end}"
fi
fi
}
swap_create() {
# Need a fresh value here, not use the global var.
local sw=$(($(grep SwapTotal /proc/meminfo | cut -f 2 -d ':' | tr -d ' ' | cut -f 1 -d 'k')/1024000))
# https://help.ubuntu.com/community/SwapFaq
if [[ -z $sw || $sw == "0" ]]; then
api-events_update ic4
if [[ -n $(conf_read swap-mem) && $(conf_read swap-mem) =~ ^[0-9]+$ ]]; then
local newswap=$(conf_read swap-mem)
elif [[ $ram -le 2 ]]; then
local newswap="1"
elif [[ $ram -le 6 ]]; then
local newswap="2"
elif [[ $ram -le 12 ]]; then
local newswap="3"
elif [[ $ram -le 16 ]]; then
local newswap="4"
elif [[ $ram -le 24 ]]; then
local newswap="5"
elif [[ $ram -le 32 ]]; then
local newswap="6"
elif [[ $ram -le 64 ]]; then
local newswap="8"
elif [[ $ram -le 128 ]]; then
local newswap="11"
elif [[ $ram -le 256 ]]; then
local newswap="16"
elif [[ $ram -le 512 ]]; then
local newswap="23"
elif [[ $ram -le 1024 ]]; then
local newswap="32"
elif [[ $ram -le 2048 ]]; then
local newswap="46"
elif [[ $ram -le 4096 ]]; then
local newswap="64"
elif [[ $ram -le 8192 ]]; then
local newswap="91"
elif [[ $ram -gt 8192 ]]; then
local newswap="100"
else
local newswap="0"
fi
# Check if disk available space is enough!
local avail=$(df -hBG --output=avail / | grep -Eo "[0-9]+" | head -n 1)
if [[ -n $avail && -n $newswap && $(($newswap+1)) -ge $avail ]]; then
echo "${red}[ERROR] No disk space available for SWAP!${dim} (Needed: ${newswap}Gb Available: ${avail}Gb ) ${end}"
local newswap="0"
else
echo "${blu}${dim}Swap size: ${newswap}Gb (Available: ${avail}Gb) ${end}"
fi
if [[ -z $newswap || $newswap == 0 ]]; then
echo "${red}[ERROR] Webinoly could not create a new SWAP file! ${end}"
else
# Create SWAP Partition
sudo dd if=/dev/zero of=/swapfile bs=${newswap}M count=1024
sudo echo "/swapfile none swap sw 0 0" >> /etc/fstab
sudo chown root:root /swapfile
sudo chmod 0600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
conf_write swap-owner webinoly
echo "${gre}A new SWAP file (${newswap}Gb) has been created! ${end}"
fi
api-events_update ic5
elif [[ -n $sw && $sw =~ ^[0-9]+$ ]]; then
[[ $(conf_read swap-owner) != "webinoly" ]] && conf_write swap-owner system
echo "${gre}SWAP file (${sw}Gb) detected!${end}"
else
echo "${red}[ERROR] Unexpected error while trying to read your SWAP file!${end}"
fi
}
message_welcome() {
# Only displayed once, when pre-pack is installed!
echo "${blu}"
echo "***************************************************************"
echo "***************** ${bol}Welcome to Webinoly ${end}${blu}*********************"
echo "********** ${dim}Stack Builder & Configuration Manager ${end}${blu}**********"
echo "***************************************************************"
if [[ $1 =~ ^(full|basic|light|partial)$ ]]; then
echo "${dim} - - - - - - - - - - - - ${end}${blu}"
echo ""
[[ $1 == "full" ]] && echo "Build Profile: ${dim}Full Stack (Nginx, PHP, MySQL/MariaDB and ALL the additional tools)"
[[ $1 == "basic" ]] && echo "Build Profile: ${dim}Basic Stack (Only the most essential tools)"
[[ $1 == "light" ]] && echo "Build Profile: ${dim}Light Stack (Only core packages, NO additional tools will be installed)"
[[ $1 == "partial" ]] && echo "Build Profile: ${dim}Partial Stack"
fi
echo "${end}"
}
stack_builder() {
# Example: stack_builder nginx php mysql
# Example: stack_builder nginx false false
# Example: stack_builder false false mysql-client
# Example: stack_builder <empty> - just update and install pre-packs
# Prevent asking for restaring services when installing packages.
if [[ -f /etc/needrestart/needrestart.conf && ! -f /etc/needrestart/conf.d/webinoly.conf ]]; then
sudo touch /etc/needrestart/conf.d/webinoly.conf
echo "\$nrconf{restart} = 'a';" >> /etc/needrestart/conf.d/webinoly.conf
fi
# Backups can be installed alone...
[[ $4 == "letsencrypt" || $4 == "pma" ]] && check_for_nginx -ask
[[ $4 == "postfix" || $4 == "redis" || $4 == "memcached" || $4 == "pma" ]] && check_for_php -ask
[[ $4 == "pma" ]] && check_for_mysql -ask && local code=0
# Check for missing essential packages
if [[ $(conf_read pre-packs) != true ]]; then
# Set Welcome Message
[[ -n $4 ]] && local mess=$4 || local mess="partial" # We trust in build variable validation
[[ -n $lemp && -z $4 ]] && local mess="full"
message_welcome $mess # Only displayed once, when pre-pack is installed!
# Any action run after the meesage is displayed!
api-events_update ics
sudo apt -qq update
# Usually comes by default with Ubuntu. Ensure we have it always! (software-properties-common debconf-utils zip)
# Webinoly tools (pwgen unzip)
# Fix issue installing in some Digital Ocean droplets (dialog)
sudo apt -y -qq install software-properties-common debconf-utils zip pwgen unzip dialog
# Snap is installed by default since 16.04, but better be sure!
sudo snap install core
sudo snap refresh core
linux_optim
conf_write pre-packs true
api-events_update ice
fi
# PPA's
api-events_update iks
if [[ $1 == "nginx" && $(conf_read nginx) != "true" ]]; then
[[ $nginx =~ ^(stable|mainline)$ ]] && conf_write nginx-ppa $nginx
[[ $lemp =~ ^(stable|mainline)$ ]] && conf_write nginx-ppa $lemp
if [[ $(lsb_release -c | cut -d':' -f 2 | xargs) =~ ^(bionic|focal)$ ]]; then
sudo apt-key adv --fetch-keys 'https://nginx.org/keys/nginx_signing.key'
if [[ $(conf_read nginx-ppa) == "mainline" ]]; then
echo | sudo add-apt-repository "deb https://nginx.org/packages/mainline/ubuntu/ $(check_osname) nginx"
else
echo | sudo add-apt-repository "deb https://nginx.org/packages/ubuntu/ $(check_osname) nginx"
fi
else
[[ -f /usr/share/keyrings/nginx-archive-keyring.gpg && ( ! -s /usr/share/keyrings/nginx-archive-keyring.gpg || -z $(cat -v /usr/share/keyrings/nginx-archive-keyring.gpg | grep -m 1 '[^[:space:]]')) ]] && sudo rm -rf /usr/share/keyrings/nginx-archive-keyring.gpg # Prevent issues!
[[ ! -f /usr/share/keyrings/nginx-archive-keyring.gpg ]] && wget -nv -O- https://nginx.org/keys/nginx_signing.key | sudo gpg --dearmor -o /usr/share/keyrings/nginx-archive-keyring.gpg
if [[ $(conf_read nginx-ppa) == "mainline" ]]; then
echo "deb [signed-by=/usr/share/keyrings/nginx-archive-keyring.gpg] https://nginx.org/packages/mainline/ubuntu/ $(lsb_release -cs) nginx" | sudo tee /etc/apt/sources.list.d/nginx.list
else
echo "deb [signed-by=/usr/share/keyrings/nginx-archive-keyring.gpg] https://nginx.org/packages/ubuntu/ $(lsb_release -cs) nginx" | sudo tee /etc/apt/sources.list.d/nginx.list
fi
fi
local code="run"
api-events_update ikn
elif [[ $1 == "nginx" ]]; then
echo "${dim}Nginx is already installed!${end}"
local code=0
fi
if [[ $2 == "php" && $(conf_read php) != "true" ]]; then
if [[ $(lsb_release -c | cut -d':' -f 2 | xargs) =~ ^(bionic|focal)$ ]]; then
# Fix ondrej issue - https://github.com/oerdnj/deb.sury.org/issues/56
#sudo apt install -y language-pack-en-base
sudo LC_ALL=C.UTF-8 add-apt-repository -y ppa:ondrej/php
else
[[ -f /usr/share/keyrings/php-archive-keyring.gpg && ( ! -s /usr/share/keyrings/php-archive-keyring.gpg || -z $(cat -v /usr/share/keyrings/php-archive-keyring.gpg | grep -m 1 '[^[:space:]]')) ]] && sudo rm -rf /usr/share/keyrings/php-archive-keyring.gpg # Prevent issues!
[[ ! -f /usr/share/keyrings/php-archive-keyring.gpg ]] && wget -nv -O- 'https://keyserver.ubuntu.com/pks/lookup?op=get&search=0x14aa40ec0831756756d7f66c4f4ea0aae5267a6c' | sudo gpg --dearmor -o /usr/share/keyrings/php-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/php-archive-keyring.gpg] https://ppa.launchpadcontent.net/ondrej/php/ubuntu $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/php.list
fi
api-events_update ikp
local code="run"
elif [[ $2 == "php" ]]; then
echo "${dim}PHP is already installed!${end}"
[[ $code != "run" ]] && local code=0
fi
if [[ ( $2 == "php" || $4 == "redis" ) && $(conf_read php-tool-redis) != "true" ]] && ! [[ $4 =~ ^(light|basic)$ ]]; then
if [[ $(lsb_release -c | cut -d':' -f 2 | xargs) =~ ^(bionic|focal)$ ]]; then
# Now there is an Official PPA: https://github.com/redis/redis-debian - https://launchpad.net/~redislabs/+archive/ubuntu/redis
# Snap is available but it has no support for ARM architecture: https://snapcraft.io/redis
echo | sudo add-apt-repository ppa:redislabs/redis
else
[[ -f /usr/share/keyrings/redis-archive-keyring.gpg && ( ! -s /usr/share/keyrings/redis-archive-keyring.gpg || -z $(cat -v /usr/share/keyrings/redis-archive-keyring.gpg | grep -m 1 '[^[:space:]]')) ]] && sudo rm -rf /usr/share/keyrings/redis-archive-keyring.gpg # Prevent issues!
[[ ! -f /usr/share/keyrings/redis-archive-keyring.gpg ]] && wget -nv -O- https://packages.redis.io/gpg | sudo gpg --dearmor -o /usr/share/keyrings/redis-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/redis-archive-keyring.gpg] https://packages.redis.io/deb $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/redis.list
fi
api-events_update ikr
local code="run"
fi
if [[ $3 =~ ^(mysql|mysql-client)$ && $(conf_read mysql-client) != "true" ]]; then
if [[ -n $(conf_read mysql-ver) && $(check_mysql_version $(conf_read mysql-ver)) == "true" ]]; then
echo "${blu}Retrieving a saved MySQL/MariaDB version configured before...${dim}${end}"
else
echo "${blu}Setting the default MySQL/MariaDB version...${dim}${end}"
[[ $(conf_read db-engine) == "mysql" ]] && conf_write mysql-ver $mysql_default || conf_write mysql-ver $mariadb_default
fi
if [[ $(conf_read db-engine) == "mysql" ]]; then
[[ -f /usr/share/keyrings/mysql-archive-keyring.gpg && ( ! -s /usr/share/keyrings/mysql-archive-keyring.gpg || -z $(cat -v /usr/share/keyrings/mysql-archive-keyring.gpg | grep -m 1 '[^[:space:]]')) ]] && sudo rm -rf /usr/share/keyrings/mysql-archive-keyring.gpg # Prevent issues!
[[ ! -f /usr/share/keyrings/mysql-archive-keyring.gpg ]] && wget -nv -O- 'https://repo.mysql.com/RPM-GPG-KEY-mysql-2022' | sudo gpg --dearmor -o /usr/share/keyrings/mysql-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/mysql-archive-keyring.gpg] http://repo.mysql.com/apt/ubuntu $(lsb_release -cs) mysql-8.0" | sudo tee /etc/apt/sources.list.d/mysql.list
# https://mariadb.org/download/?t=repo-config
elif [[ $(lsb_release -c | cut -d':' -f 2 | xargs) =~ ^(bionic|focal)$ ]]; then
sudo apt-key adv --fetch-keys 'https://mariadb.org/mariadb_release_signing_key.asc'
echo | sudo add-apt-repository "deb [arch=amd64,arm64,ppc64el] http://mirrors.syringanetworks.net/mariadb/repo/$(conf_read mysql-ver)/ubuntu $(check_osname) main"
else
[[ -f /usr/share/keyrings/mariadb-archive-keyring.gpg && ( ! -s /usr/share/keyrings/mariadb-archive-keyring.gpg || -z $(cat -v /usr/share/keyrings/mariadb-archive-keyring.gpg | grep -m 1 '[^[:space:]]' )) ]] && sudo rm -rf /usr/share/keyrings/mariadb-archive-keyring.gpg # Prevent issues!
[[ ! -f /usr/share/keyrings/mariadb-archive-keyring.gpg ]] && wget -nv -O- 'https://mariadb.org/mariadb_release_signing_key.asc' | sudo gpg --dearmor -o /usr/share/keyrings/mariadb-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/mariadb-archive-keyring.gpg] http://mirrors.syringanetworks.net/mariadb/repo/$(conf_read mysql-ver)/ubuntu $(check_osname) main" | sudo tee /etc/apt/sources.list.d/mariadb.list
fi
api-events_update ikm
local code="run"
elif [[ $3 == "mysql-client" && $(conf_read mysql-client) == "true" ]]; then
echo "${dim}MySQL/MariaDB Client is already installed!${end}"
[[ $code != "run" ]] && local code=0
elif [[ $3 == "mysql" && $(conf_read mysql) == "true" ]]; then
echo "${dim}MySQL/MariaDB is already installed!${end}"
[[ $code != "run" ]] && local code=0
elif [[ $3 == "mysql" && $(conf_read mysql-client) == "true" ]]; then
echo "${dim}MySQL/MariaDB Client is already installed!${end}"
local code="run"
fi
api-events_update ike
# Exit before update!
# Don't run the "update" if nothing will be installed!
# This validation only runs when core package is already instaled, so we need to check if a tool will be installed.
# We need this validation, because for example, LEMP can install additional tools when main package is already installed.
if [[ $code == 0 && $4 != "light" ]]; then
[[ ( $1 == "nginx" || $4 == "letsencrypt" ) && $(conf_read nginx) == "true" && $(conf_read nginx-tool-ssl) != "true" ]] && unset code
[[ ( $1 == "nginx" || $4 == "backups" ) && $(conf_read nginx-tool-bkp) != "true" ]] && unset code # Backups doesn't need nginx, can be installed alone!
[[ ( $2 == "php" || $4 == "postfix" ) && $(conf_read php) == "true" && $(conf_read php-tool-postfix) != "true" ]] && unset code
if [[ $4 != "basic" ]]; then
#[[ ( $2 == "php" || $4 == "redis" ) && $(conf_read php) == "true" && $(conf_read php-tool-redis) != "true" ]] && unset code # Unset in PPA
[[ ( $2 == "php" || $4 == "memcached" ) && $(conf_read php) == "true" && $(conf_read php-tool-memcached) != "true" ]] && unset code
[[ -n $code && ( $3 == "mysql" || $4 == "pma" ) && $(conf_read mysql) == "true" && $(conf_read mysql-tool-pma) != "true" ]] && local code="noupd"
fi
fi
if [[ $code != 0 ]]; then
# PMA doesn't need update!
[[ $code != "noupd" ]] && sudo apt -qq update
# Install Packages!
[[ $1 == "nginx" && $(conf_read nginx) != "true" ]] && nginx_install && nginx_optim && nginx_tool_site
[[ ( $1 == "nginx" || $4 == "letsencrypt" ) && $(conf_read nginx) == "true" && $(conf_read nginx-tool-ssl) != "true" && $4 != "light" ]] && nginx_tool_ssl
[[ ( $1 == "nginx" || $4 == "backups" ) && $(conf_read nginx-tool-bkp) != "true" && $4 != "light" ]] && nginx_tool_bkp # Backups doesn't need nginx, can be installed alone!
[[ $2 == "php" && $(conf_read php) != "true" ]] && php_install && php_optim && php_tool_site
[[ ( $2 == "php" || $4 == "postfix" ) && $(conf_read php) == "true" && $(conf_read php-tool-postfix) != "true" && $4 != "light" ]] && php_tool_postfix
[[ ( $2 == "php" || $4 == "redis" ) && $(conf_read php) == "true" && $(conf_read php-tool-redis) != "true" ]] && ! [[ $4 =~ ^(light|basic)$ ]] && php_tool_redis
[[ ( $2 == "php" || $4 == "memcached" ) && $(conf_read php) == "true" && $(conf_read php-tool-memcached) != "true" ]] && ! [[ $4 =~ ^(light|basic)$ ]] && php_tool_memcached
[[ $3 == "mysql-client" && $(conf_read mysql-client) != "true" ]] && mysql_client_install
[[ $3 == "mysql" && $(conf_read mysql) != "true" ]] && mysql_client_install && mysql_install && local mysql_pass_display="true" && mysql_optim
[[ ( $3 == "mysql" || $4 == "pma" ) && $(conf_read mysql) == "true" && $(conf_read mysql-tool-pma) != "true" ]] && ! [[ $4 =~ ^(light|basic)$ ]] && mysql_tool_pma
# This message is now only for legacy support!
# People expects the passwords displayed, so we keep this message to prevent people asking!
if [[ $mysql_pass_display == "true" && -z $block_password_display ]]; then
echo ""
echo "${gre}"
echo "****************************************************************************"
echo "******${bol} INSTALLATION HAS FINISHED SUCCESSFULLY ${end}${gre}******"
echo "****************************************************************************"
echo "******** MySQL/MariaDB properly configured and secured! ********"
echo "************${dim} Passwords no longer displayed here. ${end}${gre}************"
echo "****************************************************************************"
echo "${blu}For passwords, read:${end}${dim} https://webinoly.com/documentation/webinolys/#dbdata"
echo "${end}"
fi
fi
[[ $code != 0 || -n $(conf_read stack-build-error-flag) ]] && sudo webinoly -verify=critical || return 0 # Never end a function with negative open!
}