diff --git a/README.md b/README.md index 50f4116..30c640a 100644 --- a/README.md +++ b/README.md @@ -5,10 +5,12 @@ ### https://www.hanssonit.se/wordpress-vm/ - Ubuntu 18.04 -- MariaDB 10.2 -- NGINX 1.16 -- PHP-FPM 7.2 +- MariaDB 10.5 +- NGINX 1.18 +- PHP-FPM 7.4 - Latest Wordpress (updates automatically) - WP-CLI - Redis Cache +- Igbinary for PHP +- APCu Cache - and [more](https://docs.hanssonit.se/s/W6fMouPiqQz3_Mog/virtual-machines-vm/d/W7jL1OPiqQz3_MtV/wordpress-vm-machine-configuration). diff --git a/addons/automatic_updates.sh b/addons/automatic_updates.sh new file mode 100644 index 0000000..a5b0e7e --- /dev/null +++ b/addons/automatic_updates.sh @@ -0,0 +1,45 @@ +#!/bin/bash + +# T&M Hansson IT AB © - 2020, https://www.hanssonit.se/ + +# shellcheck disable=2034,2059 +true +SCRIPT_NAME="Automatic Updates" +# shellcheck source=lib.sh +source /var/scripts/fetch_lib.sh || source <(curl -sL https://raw.githubusercontent.com/techandme/wordpress-vm/master/lib.sh) + +print_text_in_color "$ICyan" "Configuring automatic updates..." + +# Check for errors + debug code and abort if something isn't right +# 1 = ON +# 0 = OFF +DEBUG=0 +debug_mode + +# Check if root +root_check + +msg_box "This option will update your server every week on Saturdays at $AUT_UPDATES_TIME:00. +The update will run the built in script '$SCRIPTS/update.sh' which will update both the server packages and Wordpress itself. + +Please keep in mind that automatic updates might fail hence it's +important to have a proper backup in place if you plan to run this option. + +You can disable the automatic updates by entering the crontab file like this: +'sudo crontab -e -u root' +Then just put a hash (#) in front of the row that you want to disable. + +In the next step you will be able to choose to proceed or exit." "$SUBTITLE" + +if yesno_box_yes "Do you want to enable automatic updates?" +then + # TODO: delete the following line after a few releases. It was copied to the install-script. + touch $VMLOGS/update.log + crontab -u root -l | { cat; echo "0 $AUT_UPDATES_TIME * * 6 $SCRIPTS/update.sh >> $VMLOGS/update.log"; } | crontab -u root - + if yesno_box_yes "Do you want to reboot your server after every update? *recommended*" + then + sed -i "s|exit|/sbin/shutdown -r +1|g" "$SCRIPTS"/update.sh + echo "exit" >> "$SCRIPTS"/update.sh + fi + msg_box "Please remember to keep backups in case something should go wrong, you never know." "$SUBTITLE" +fi diff --git a/addons/locales.sh b/addons/locales.sh new file mode 100644 index 0000000..a272a3c --- /dev/null +++ b/addons/locales.sh @@ -0,0 +1,44 @@ +#!/bin/bash + +# T&M Hansson IT AB © - 2020, https://www.hanssonit.se/ + +# shellcheck disable=2034,2059,1091 +true +SCRIPT_NAME="Locales" +# shellcheck source=lib.sh +source /var/scripts/fetch_lib.sh || source <(curl -sL https://raw.githubusercontent.com/techandme/wordpress-vm/master/lib.sh) + +# Check for errors + debug code and abort if something isn't right +# 1 = ON +# 0 = OFF +DEBUG=0 +debug_mode + +# Must be root +root_check + +################################################################## + +# Set locales +print_text_in_color "$ICyan" "Setting locales..." +if [ "$KEYBOARD_LAYOUT" = "us" ] +then + print_text_in_color "$ICyan" "US locales are already set." +elif [ "$KEYBOARD_LAYOUT" = "se" ] +then + sudo locale-gen "sv_SE.UTF-8" && sudo dpkg-reconfigure --frontend=noninteractive locales +elif [ "$KEYBOARD_LAYOUT" = "de" ] +then + sudo locale-gen "de_DE.UTF-8" && sudo dpkg-reconfigure --frontend=noninteractive locales +elif [ "$KEYBOARD_LAYOUT" = "us" ] +then + sudo locale-gen "en_US.UTF-8" && sudo dpkg-reconfigure --frontend=noninteractive locales +elif [ "$KEYBOARD_LAYOUT" = "fr" ] +then + sudo locale-gen "fr_FR.UTF-8" && sudo dpkg-reconfigure --frontend=noninteractive locales +elif [ "$KEYBOARD_LAYOUT" = "ch" ] +then + sudo locale-gen "de_CH.UTF-8" && sudo dpkg-reconfigure --frontend=noninteractive locales +fi + +# TODO: "localectl list-x11-keymap-layouts" and pair with "cat /etc/locale.gen | grep UTF-8" diff --git a/addons/locate_mirror.sh b/addons/locate_mirror.sh new file mode 100644 index 0000000..bbc33b3 --- /dev/null +++ b/addons/locate_mirror.sh @@ -0,0 +1,58 @@ +#!/bin/bash + +# T&M Hansson IT AB © - 2020, https://www.hanssonit.se/ + +# shellcheck disable=2034,2059 +true +SCRIPT_NAME="Locate Mirror" +# shellcheck source=lib.sh +source /var/scripts/fetch_lib.sh || source <(curl -sL https://raw.githubusercontent.com/techandme/wordpress-vm/master/lib.sh) + +# Must be root +root_check + +# Use another method if the new one doesn't work +if [ -z "$REPO" ] +then + REPO=$(apt update -q4 && apt-cache policy | grep http | tail -1 | awk '{print $2}') +fi + +# Check where the best mirrors are and update +msg_box "To make downloads as fast as possible when updating Ubuntu \ +you should have download mirrors that are as close to you as possible. + +Please note that there are no gurantees that the download mirrors \ +this script will find are staying up for the lifetime of this server. +Because of this, we don't recommend to change the mirror, except you live far away from the default mirror. + +This is the method used: https://github.com/jblakeman/apt-select" +msg_box "Your current server repository is: $REPO" + +if ! yesno_box_no "Do you want to try to find a better mirror?" +then + print_text_in_color "$ICyan" "Keeping $REPO as mirror..." + sleep 1 +else + if [[ "$KEYBOARD_LAYOUT" =~ ,|/|_ ]] + then + msg_box "Your keymap contains more than one language, or a special character. ($KEYBOARD_LAYOUT) +This script can only handle one keymap at the time.\nThe default mirror ($REPO) will be kept." + exit 1 + fi + print_text_in_color "$ICyan" "Locating the best mirrors..." + curl_to_dir https://bootstrap.pypa.io get-pip.py /tmp + install_if_not python3 + install_if_not python3-testresources + install_if_not python3-distutils + cd /tmp && python3 get-pip.py + pip install \ + --upgrade pip \ + apt-select + check_command apt-select -m up-to-date -t 4 -c -C "$KEYBOARD_LAYOUT" + sudo cp /etc/apt/sources.list /etc/apt/sources.list.backup && \ + if [ -f sources.list ] + then + sudo mv sources.list /etc/apt/ + fi + msg_box "The apt-mirror was successfully changed." +fi diff --git a/static/redis-server-ubuntu.sh b/addons/redis-server-ubuntu.sh similarity index 59% rename from static/redis-server-ubuntu.sh rename to addons/redis-server-ubuntu.sh index 0839b13..d8b5144 100644 --- a/static/redis-server-ubuntu.sh +++ b/addons/redis-server-ubuntu.sh @@ -1,10 +1,11 @@ #!/bin/bash # shellcheck disable=2034,2059 true +SCRIPT_NAME="Redis Server Ubuntu" # shellcheck source=lib.sh -. <(curl -sL https://raw.githubusercontent.com/techandme/wordpress-vm/master/lib.sh) +source /var/scripts/fetch_lib.sh || source <(curl -sL https://raw.githubusercontent.com/techandme/wordpress-vm/master/lib.sh) -# T&M Hansson IT AB © - 2019, https://www.hanssonit.se/ +# T&M Hansson IT AB © - 2020, https://www.hanssonit.se/ # Check for errors + debug code and abort if something isn't right # 1 = ON @@ -16,26 +17,24 @@ debug_mode root_check # Check Ubuntu version -print_text_in_color "$ICyan" "Checking server OS and version..." -if [ "$OS" != 1 ] +if ! version 16.04 "$DISTRO" 20.04.6 then - print_text_in_color "$IRed" "Ubuntu Server is required to run this script." - print_text_in_color "$IRed" "Please install that distro and try again." + msg_box "Your current Ubuntu version is $DISTRO but must be between 16.04 - 20.04.6 to run this script." + msg_box "Please contact us to get support for upgrading your server: +https://www.hanssonit.se/#contact +https://shop.hanssonit.se/" exit 1 fi - -if ! version 18.04 "$DISTRO" 18.04.4; then - print_text_in_color "$IRed" "Ubuntu version $DISTRO must be between 18.04 - 18.04.4" - exit -fi - # Check if dir exists if [ ! -d $SCRIPTS ] then mkdir -p $SCRIPTS fi - + +# Check the current PHPVER +check_php + # Install Redis install_if_not php"$PHPVER"-dev pecl channel-update pecl.php.net @@ -44,26 +43,17 @@ then msg_box "PHP module installation failed" exit 1 else - print_text_in_color "$IGreen" "PHP module installation OK!" + printf "${IGreen}\nPHP module installation OK!${Color_Off}\n" fi install_if_not redis-server +# Setting direct to PHP-FPM as it's installed with PECL (globally doesn't work) +print_text_in_color "$ICyan" "Adding extension=redis.so to $PHP_INI..." # FPM is needed for frontend echo 'extension=redis.so' >> /etc/php/"$PHPVER"/fpm/php.ini # CLI is needed for backend echo 'extension=redis.so' >> /etc/php/"$PHPVER"/cli/php.ini -service php"$PHPVER"-fpm restart -service nginx restart - -# Install Redis -if ! apt -y install redis-server -then - print_text_in_color "$IRed" "Installation failed." - sleep 3 - exit 1 -else - print_text_in_color "$IGreen" "Redis installation OK!" -fi +restart_webserver ## Redis performance tweaks ## if ! grep -Fxq "vm.overcommit_memory = 1" /etc/sysctl.conf @@ -77,13 +67,19 @@ then echo "never" > /sys/kernel/mm/transparent_hugepage/enabled fi +# Raise TCP backlog +#if ! grep -Fxq "net.core.somaxconn" /proc/sys/net/core/somaxconn +#then +# sed -i "s|net.core.somaxconn.*||g" /etc/sysctl.conf +# sysctl -w net.core.somaxconn=512 +# echo "net.core.somaxconn = 512" >> /etc/sysctl.conf +#fi sed -i "s|# unixsocket .*|unixsocket $REDIS_SOCK|g" $REDIS_CONF sed -i "s|# unixsocketperm .*|unixsocketperm 777|g" $REDIS_CONF sed -i "s|^port.*|port 0|" $REDIS_CONF sed -i "s|# requirepass .*|requirepass $(cat $REDISPTXT)|g" $REDIS_CONF sed -i 's|# rename-command CONFIG ""|rename-command CONFIG ""|' $REDIS_CONF redis-cli SHUTDOWN -rm -f $REDISPTXT # Secure Redis chown redis:root /etc/redis/redis.conf @@ -92,5 +88,6 @@ chmod 600 /etc/redis/redis.conf apt update -q4 & spinner_loading apt autoremove -y apt autoclean +rm -f "$REDISPTXT" exit diff --git a/addons/smtp-mail.sh b/addons/smtp-mail.sh new file mode 100644 index 0000000..9a4e705 --- /dev/null +++ b/addons/smtp-mail.sh @@ -0,0 +1,270 @@ +#!/bin/bash + +# T&M Hansson IT AB © - 2020, https://www.hanssonit.se/ + +# shellcheck disable=2034,2059 +true +SCRIPT_NAME="SMTP Relay with msmtp" +SCRIPT_EXPLAINER="This script will setup an SMTP Relay (Mail Server) in your Wordpress Server \ +that will be used to send emails about failed cronjob's and such." +# shellcheck source=lib.sh +source /var/scripts/fetch_lib.sh || source <(curl -sL https://raw.githubusercontent.com/techandme/wordpress-vm/master/lib.sh) + +# Check for errors + debug code and abort if something isn't right +# 1 = ON +# 0 = OFF +DEBUG=0 +debug_mode + +# Must be root +root_check + +# Check if Smtp Relay was already configured +if ! [ -f /etc/msmtprc ] +then + # Ask for installing + install_popup "$SCRIPT_NAME" +else + # Ask for removal or reinstallation + reinstall_remove_menu "$SCRIPT_NAME" + # Removal + apt-get purge msmtp -y + apt-get purge msmtp-mta -y + apt-get purge mailutils -y + apt autoremove -y + rm -f /etc/mail.rc + rm -f /etc/msmtprc + rm -f /var/log/msmtp + echo "" > /etc/aliases + # Show successful uninstall if applicable + removal_popup "$SCRIPT_NAME" +fi + +# Install needed tools +install_if_not msmtp +install_if_not msmtp-mta +install_if_not mailutils + +# Enter Mail Server +MAIL_SERVER=$(input_box_flow "Please enter the SMTP Relay URL that you want to use.\nE.g. smtp.mail.com") + +# Enter if you want to use ssl +PROTOCOL=$(whiptail --title "$TITLE" --nocancel --menu \ +"Please choose the encryption protocol for your SMTP Relay. +$MENU_GUIDE\n\n$RUN_LATER_GUIDE" "$WT_HEIGHT" "$WT_WIDTH" 4 \ +"SSL" "" \ +"STARTTLS" "" \ +"NO-ENCRYPTION" "" 3>&1 1>&2 2>&3) + +if [ -z "$PROTOCOL" ] +then + exit 1 +fi + +case "$PROTOCOL" in + "SSL") + DEFAULT_PORT=465 + ;; + "STARTTLS") + DEFAULT_PORT=587 + ;; + "NO-ENCRYPTION") + DEFAULT_PORT=25 + ;; + *) + ;; +esac + +# Enter custom port or just use the default port +SMTP_PORT=$(whiptail --title "$TITLE" --nocancel --menu \ +"Based on your selection of encryption the default port is $DEFAULT_PORT. Would you like to use that port or something else? +$MENU_GUIDE\n\n$RUN_LATER_GUIDE" "$WT_HEIGHT" "$WT_WIDTH" 4 \ +"Use default port" "($DEFAULT_PORT)" \ +"Enter another port" "" 3>&1 1>&2 2>&3) + +if [ -z "$SMTP_PORT" ] +then + exit 1 +fi + +case "$SMTP_PORT" in + "Use default port") + SMTP_PORT="$DEFAULT_PORT" + ;; + "Enter another port") + SMTP_PORT="$(input_box_flow 'Please enter the port for your SMTP Relay.')" + ;; + *) + ;; +esac + +# Enter your SMTP username +if yesno_box_yes "Does $MAIL_SERVER require any credenitals, like username and password?" +then + MAIL_USERNAME=$(input_box_flow "Please enter the SMTP username to your email provider.\nE.g. you@mail.com") + + # Enter your mailuser password + MAIL_PASSWORD=$(input_box_flow "Please enter the SMTP password to your email provider.") +fi + +# Enter the recipient +RECIPIENT=$(input_box_flow "Please enter the recipient email address that shall receive all mails.\nE.g. recipient@mail.com") + +# Present what we gathered, if everything okay, write to files +msg_box "These are the settings that will be used. Please check that everything seems correct. + +SMTP Relay URL=$MAIL_SERVER +Encryption=$PROTOCOL +SMTP Port=$SMTP_PORT +SMTP Username=$MAIL_USERNAME +SMTP Password=$MAIL_PASSWORD +Recipient=$RECIPIENT" + +# Ask if everything is okay +if ! yesno_box_yes "Does everything look correct?" +then + exit +fi + +# Add the encryption settings to the file as well +if [ "$PROTOCOL" = "SSL" ] +then + MSMTP_ENCRYPTION1="tls on" + MSMTP_ENCRYPTION2="tls_starttls off" +elif [ "$PROTOCOL" = "STARTTLS" ] +then + MSMTP_ENCRYPTION1="tls on" + MSMTP_ENCRYPTION2="tls_starttls on" +elif [ "$PROTOCOL" = "NO-ENCRYPTION" ] +then + MSMTP_ENCRYPTION1="tls off" + MSMTP_ENCRYPTION2="tls_starttls off" +fi + +# Check if auth should be set or not +if [ -z "$MAIL_USERNAME" ] +then + MAIL_USERNAME="no-reply@hanssonit.com" + +# Without AUTH (Username and Password) +cat << MSMTP_CONF > /etc/msmtprc +# Set default values for all following accounts. +defaults +auth off +aliases /etc/aliases +$MSMTP_ENCRYPTION1 +$MSMTP_ENCRYPTION2 + +tls_trust_file /etc/ssl/certs/ca-certificates.crt +# logfile /var/log/msmtp + +# Account to send emails +account $MAIL_USERNAME +host $MAIL_SERVER +port $SMTP_PORT +from $MAIL_USERNAME + +account default : $MAIL_USERNAME + +### DO NOT REMOVE THIS LINE (it's used in one of the functions in on the Wordpress Server) +# recipient=$RECIPIENT +MSMTP_CONF +else +# With AUTH (Username and Password) +cat << MSMTP_CONF > /etc/msmtprc +# Set default values for all following accounts. +defaults +auth on +aliases /etc/aliases +$MSMTP_ENCRYPTION1 +$MSMTP_ENCRYPTION2 + +tls_trust_file /etc/ssl/certs/ca-certificates.crt +logfile /var/log/msmtp + +# Account to send emails +account $MAIL_USERNAME +host $MAIL_SERVER +port $SMTP_PORT +from $MAIL_USERNAME +user $MAIL_USERNAME +password $MAIL_PASSWORD + +account default : $MAIL_USERNAME + +### DO NOT REMOVE THIS LINE (it's used in one of the functions in on the Wordpress Server) +# recipient=$RECIPIENT + +MSMTP_CONF +fi + +# Secure the file +chmod 600 /etc/msmtprc + +# Create logs +rm -f /var/log/msmtp +touch /var/log/msmtp +chmod 666 /var/log/msmtp + +# Create aliases +cat << ALIASES_CONF > /etc/aliases +root: $RECIPIENT +default: $RECIPIENT +cron: $RECIPIENT +ALIASES_CONF + +# Store message in a variable +TEST_MAIL="Congratulations! + +Since this email reached you, it seems like everything is working properly. :) + +To change the settings please check /etc/msmtprc on your server, or simply just run the setup script again. + +YOUR CURRENT SETTINGS: +------------------------------------------- +$(grep -v password /etc/msmtprc) +------------------------------------------- + +Best regards +The Wordpress VM team +https://www.hanssonit.com" + +# Define the mail-program +echo 'set sendmail="/usr/bin/msmtp -t"' > /etc/mail.rc + +# Test mail +if ! echo -e "$TEST_MAIL" | mail -s "Test email from your NcVM" "$RECIPIENT" >> /var/log/msmtp 2>&1 +then + # Test another version + echo 'set sendmail="/usr/bin/msmtp"' > /etc/mail.rc + + # Second try + if ! echo -e "$TEST_MAIL" | mail -s "Test email from your NcVM" "$RECIPIENT" >> /var/log/msmtp 2>&1 + then + # Fail message + msg_box "It seems like something has failed. +You can look at /var/log/msmtp for further logs. +Please run this script once more if you want to make another try." + + # Let the user decide if configs/packets shall get resetted/uninstalled + if yesno_box_yes "Do you want to reset all configs and uninstall all packets \ +that were made/installed by this script so that you keep a clean system? +This will make debugging more complicated since you will only have the log file to debug this." + then + apt-get purge msmtp -y + apt-get purge msmtp-mta -y + apt-get purge mailutils -y + apt autoremove -y + rm -f /etc/mail.rc + rm -f /etc/msmtprc + echo "" > /etc/aliases + msg_box "Uninstallation of MSMTP was successfully done" + fi + exit 1 + fi +fi + +# Success message +msg_box "Congratulations, the test email was successfully sent! +Please check the inbox for $RECIPIENT. The test email should arrive soon." +exit diff --git a/apps/adminer.sh b/apps/adminer.sh index 2dc47f9..47d59e1 100644 --- a/apps/adminer.sh +++ b/apps/adminer.sh @@ -1,14 +1,13 @@ #!/bin/bash -# T&M Hansson IT AB © - 2019, https://www.hanssonit.se/ - -# Prefer IPv4 -sed -i "s|#precedence ::ffff:0:0/96 100|precedence ::ffff:0:0/96 100|g" /etc/gai.conf +# T&M Hansson IT AB © - 2020, https://www.hanssonit.se/ # shellcheck disable=2034,2059 true +SCRIPT_NAME="Adminer" +SCRIPT_EXPLAINER="Adminer is a full-featured database management tool written in PHP." # shellcheck source=lib.sh -. <(curl -sL https://raw.githubusercontent.com/techandme/wordpress-vm/master/lib.sh) +source /var/scripts/fetch_lib.sh || source <(curl -sL https://raw.githubusercontent.com/techandme/wordpress-vm/master/lib.sh) # Check for errors + debug code and abort if something isn't right # 1 = ON @@ -17,73 +16,101 @@ DEBUG=0 debug_mode # Check if root -if ! is_root -then - printf "\n${Red}Sorry, you are not root.\n${Color_Off}You must type: ${Cyan}sudo ${Color_Off}bash %s/wordpress_install.sh\n" "$SCRIPTS" - exit 1 -fi +root_check - -print_text_in_color "$ICyan" "Installing and securing Adminer..." - -# Check Ubuntu version -if [ "$OS" != 1 ] +# Check if adminer is already installed +if ! is_this_installed adminer then - print_text_in_color "$IRed" "Ubuntu Server is required to run this script." - print_text_in_color "$IRed" "Please install that distro and try again." - sleep 3 - exit 1 + # Ask for installing + install_popup "$SCRIPT_NAME" +else + # Ask for removal or reinstallation + reinstall_remove_menu "$SCRIPT_NAME" + # Removal + check_command apt-get purge adminer -y + rm -f $ADMINER_CONF + rm -rf $ADMINERDIR + restart_webserver + # Show successful uninstall if applicable + removal_popup "$SCRIPT_NAME" fi +# Check that the script can see the external IP (apache fails otherwise) +check_external_ip -if ! version 16.04 "$DISTRO" 18.04.4; then - print_text_in_color "$IRed" "Ubuntu version seems to be $DISTRO" - print_text_in_color "$IRed" "It must be between 16.04 - 18.04.4" - print_text_in_color "$IRed" "Please install that version and try again." - exit 1 -fi +# Check distrobution and version +check_distro_version # Install Adminer apt update -q4 & spinner_loading install_if_not adminer -sudo wget -q "http://www.adminer.org/latest.php" -O "$ADMINERDIR"/latest.php -sudo ln -s "$ADMINERDIR"/latest.php "$ADMINERDIR"/adminer.php +curl_to_dir "http://www.adminer.org" "latest.php" "$ADMINERDIR" +curl_to_dir "https://raw.githubusercontent.com/Niyko/Hydra-Dark-Theme-for-Adminer/master" "adminer.css" "$ADMINERDIR" +check_command mv "$ADMINERDIR"/latest.php "$ADMINERDIR"/adminer.php + +# Only add TLS 1.3 on Ubuntu later than 20.04 +if version 20.04 "$DISTRO" 20.04.10 +then + TLS13="+TLSv1.3" +fi cat << ADMINER_CREATE > "$ADMINER_CONF" server { + listen 443 ssl http2; + listen [::]:443 ssl http2; - # Listen on port 81 - listen 81; - - # Server name being used (exact name, wildcards or regular expression) - # server_name adminer.my; - + ## Your website name goes here. + # server_name example.com; + ## Your only path reference. root /usr/share/adminer/adminer; - - # Logging - error_log /var/log/adminer.access_log; - access_log /var/log/adminer.error_log; - + ## This should be in your http block and if it is, it's not needed here. + index adminer.php; + resolver $GATEWAY; + + ## Show real IP behind proxy (change to the proxy IP) +# set_real_ip_from $GATEWAY/24; +# set_real_ip_from $GATEWAY; +# set_real_ip_from 2001:0db8::/32; +# real_ip_header X-Forwarded-For; +# real_ip_recursive on; + + # certs sent to the client in SERVER HELLO are concatenated in ssl_certificate + ssl_certificate /etc/ssl/certs/ssl-cert-snakeoil.pem; + ssl_certificate_key /etc/ssl/private/ssl-cert-snakeoil.key; + ssl_session_timeout 1d; + ssl_session_cache shared:SSL:50m; + ssl_session_tickets off; + # Diffie-Hellman parameter for DHE ciphersuites, recommended 4096 bits + # ssl_dhparam /path/to/dhparam.pem; + # intermediate configuration. tweak to your needs. + ssl_protocols TLSv1 TLSv1.1 TLSv1.2; + ssl_ciphers 'ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS'; + ssl_prefer_server_ciphers on; + # HSTS (ngx_http_headers_module is required) (15768000 seconds = 6 months) + add_header Strict-Transport-Security max-age=15768000; + # OCSP Stapling --- + # fetch OCSP records from URL in ssl_certificate and cache them + ssl_stapling on; + ssl_stapling_verify on; + ## verify chain of trust of OCSP response using Root CA and Intermediate certs + # ssl_trusted_certificate /path/to/root_CA_cert_plus_intermediates; location / { index index.php; allow $GATEWAY/24; deny all; } - location ~* ^/adminer/(.+\.(jpg|jpeg|gif|css|png|js|ico|html|xml|txt))$ { root /usr/share/adminer/; } - + location ~ /\.ht { deny all; } - location ~ /(libraries|setup/frames|setup/libs) { deny all; return 404; } - # Pass the PHP scripts to FastCGI server location ~* \\.php$ { #NOTE: You should have "cgi.fix_pathinfo = 0;" in php.ini @@ -102,10 +129,7 @@ server { } ADMINER_CREATE -# Enable config -ln -s /etc/nginx/sites-available/adminer.conf /etc/nginx/sites-enabled/adminer.conf - -if ! service nginx restart +if ! systemctl restart nginx.service then msg_box "Nginx could not restart... The script will exit." @@ -113,12 +137,9 @@ The script will exit." else msg_box "Adminer was sucessfully installed and can be reached here: http://$ADDRESS:81 - -You can download more plugins and get more information here: +You can download more plugins and get more information here: https://www.adminer.org - -Your MariaDB connection information can be found in /root/.my.cnf - +Your MariaDB connection information can be found in $WPATH/wp-config.php In case you try to access Adminer and get 'Forbidden' you need to change the IP in: $ADMINER_CONF" fi diff --git a/apps/bpytop.sh b/apps/bpytop.sh new file mode 100644 index 0000000..932db70 --- /dev/null +++ b/apps/bpytop.sh @@ -0,0 +1,74 @@ +#!/bin/bash + +# T&M Hansson IT AB © - 2020, https://www.hanssonit.se/ + +# shellcheck disable=2034,2059 +true +SCRIPT_NAME="BPYTOP" +SCRIPT_EXPLAINER="BPYTOP is an amazing alternative to resource-monitor software like top or htop." +# shellcheck source=lib.sh +source /var/scripts/fetch_lib.sh || source <(curl -sL https://raw.githubusercontent.com/techandme/wordpress-vm/master/lib.sh) + +# Check for errors + debug code and abort if something isn't right +# 1 = ON +# 0 = OFF +DEBUG=0 +debug_mode + +# Must be root +root_check + +# Needed for snaps to run +install_if_not snapd + +# Check if bpytop is already installed +if ! snap list | grep -q bpytop +then + # Ask for installing + install_popup "$SCRIPT_NAME" +else + # Ask for removal or reinstallation + reinstall_remove_menu "$SCRIPT_NAME" + # Removal + if [ -f /home/"$UNIXUSER"/.bash_aliases ] + then + sed -i "s|.*bpytop'||g" /home/"$UNIXUSER"/.bash_aliases + fi + if [ -f /root/.bash_aliases ] + then + sed -i "s|.*bpytop'||g" /root/.bash_aliases + fi + snap remove bpytop + # Show successful uninstall if applicable + removal_popup "$SCRIPT_NAME" +fi + +# Install it! +if snap install bpytop +then + snap connect bpytop:mount-observe + snap connect bpytop:network-control + snap connect bpytop:hardware-observe + snap connect bpytop:system-observe + snap connect bpytop:process-control + snap connect bpytop:physical-memory-observe + hash -r + msg_box "BPYTOP is now installed! Check out the amazing stats by runnning 'bpytop' from your CLI. +You can check out their Gihub repo here: https://github.com/aristocratos/bpytop/blob/master/README.md" + # Ask for aliases + if yesno_box_yes "Would you like to add an alias for bpytop to replace both htop and top?" + then + echo "alias top='bpytop'" >> /root/.bash_aliases + echo "alias htop='bpytop'" >> /root/.bash_aliases + if [ -d /home/"$UNIXUSER" ] + then + touch /home/"$UNIXUSER"/.bash_aliases + chown "$UNIXUSER":"$UNIXUSER" /home/"$UNIXUSER"/.bash_aliases + echo "alias top='bpytop'" >> /home/"$UNIXUSER"/.bash_aliases + echo "alias htop='bpytop'" >> /home/"$UNIXUSER"/.bash_aliases + fi + msg_box "Alias for bpytop is now set! You can now type both 'htop' and 'top' in your CLI to use bpytop." + fi +else + msg_box "It seems like the installation of BPYTOP failed. Please try again." +fi diff --git a/apps/fail2ban.sh b/apps/fail2ban.sh index 5130293..8a73456 100644 --- a/apps/fail2ban.sh +++ b/apps/fail2ban.sh @@ -1,11 +1,18 @@ #!/bin/bash -# T&M Hansson IT AB © - 2019, https://www.hanssonit.se/ +# T&M Hansson IT AB © - 2020, https://www.hanssonit.se/ +# Inspired by https://github.com/nextcloud/nextcloudpi/blob/master/etc/nextcloudpi-config.d/fail2ban.sh # shellcheck disable=2034,2059 true +SCRIPT_NAME="Fail2ban" +SCRIPT_EXPLAINER="Fail2ban provides extra Brute Force protextion for Wordpress. +It scans the Wordpress and SSH log files and bans IPs that show malicious \ +signs -- too many password failures, seeking for exploits, etc. +Generally Fail2Ban is then used to update firewall rules to \ +reject the IP addresses for a specified amount of time." # shellcheck source=lib.sh -. <(curl -sL https://raw.githubusercontent.com/techandme/wordpress-vm/master/lib.sh) +source /var/scripts/fetch_lib.sh || source <(curl -sL https://raw.githubusercontent.com/techandme/wordpress-vm/master/lib.sh) # Check for errors + debug code and abort if something isn't right # 1 = ON @@ -14,35 +21,46 @@ DEBUG=0 debug_mode # Check if root -if ! is_root +root_check + +# Check if fail2ban is already installed +if ! is_this_installed fail2ban then - printf "\n${Red}Sorry, you are not root.\n${Color_Off}You must type: ${Cyan}sudo ${Color_Off}bash %s/fail2ban.sh\n" "$SCRIPTS" - sleep 3 - exit 1 + # Ask for installing + install_popup "$SCRIPT_NAME" +else + # Ask for removal or reinstallation + reinstall_remove_menu "$SCRIPT_NAME" + # Removal + print_text_in_color "$ICyan" "Unbanning all currently blocked IPs..." + fail2ban-client unban --all + check_command update-rc.d fail2ban disable + check_command apt-get purge fail2ban -y + rm -Rf /etc/fail2ban/ + wp_cli_cmd plugin delete wp-fail2ban + # Show successful uninstall if applicable + removal_popup "$SCRIPT_NAME" fi ### Local variables ### # location of logs AUTHLOG="/var/log/auth.log" # time to ban an IP that exceeded attempts -BANTIME_=600000 +BANTIME_=1209600 # cooldown time for incorrect passwords FINDTIME_=1800 -#bad attempts before banning an IP -MAXRETRY_=10 - -print_text_in_color "$ICyan" "Installing Fail2ban..." +# failed attempts before banning an IP +MAXRETRY_=20 apt update -q4 & spinner_loading -check_command apt install fail2ban -y +install_if_not fail2ban check_command update-rc.d fail2ban disable # Install WP-Fail2ban and activate conf -cd $WPATH wp_cli_cmd plugin install wp-fail2ban --activate curl https://plugins.svn.wordpress.org/wp-fail2ban/trunk/filters.d/wordpress-hard.conf > /etc/fail2ban/filter.d/wordpress.conf -if [ ! -f $AUTHLOG ] +if [ ! -f "$AUTHLOG" ] then print_text_in_color "$IRed" "$AUTHLOG not found" exit 1 @@ -59,6 +77,14 @@ cat << FCONF > /etc/fail2ban/jail.d/wordpress.conf # defined using space separator. ignoreip = 127.0.0.1/8 192.168.0.0/16 172.16.0.0/12 10.0.0.0/8 +# "bantime" is the number of seconds that a host is banned. +bantime = $BANTIME_ + +# A host is banned if it has generated "maxretry" during the last "findtime" +# seconds. +findtime = $FINDTIME_ +maxretry = $MAXRETRY_ + # # ACTIONS # @@ -70,6 +96,15 @@ action_mw = %(banaction)s[name=%(__name__)s, port="%(port)s", protocol="%(protoc action_mwl = %(banaction)s[name=%(__name__)s, port="%(port)s", protocol="%(protocol)s", chain="%(chain)s"] action = %(action_)s +# +# SSH +# + +[sshd] + +enabled = true +maxretry = $MAXRETRY_ + # # HTTP servers # @@ -87,11 +122,12 @@ FCONF # Update settings check_command update-rc.d fail2ban defaults check_command update-rc.d fail2ban enable -check_command service fail2ban restart +check_command systemctl restart fail2ban.service # The End msg_box "Fail2ban is now sucessfully installed. -Please use 'fail2ban-client set wordpress unbanip ' to unban certain IPs + +Please use 'fail2ban-client set nextcloud unbanip ' to unban certain IPs You can also use 'iptables -L -n' to check which IPs that are banned" -clear +exit diff --git a/apps/midnight-commander.sh b/apps/midnight-commander.sh new file mode 100644 index 0000000..220cdc0 --- /dev/null +++ b/apps/midnight-commander.sh @@ -0,0 +1,72 @@ +#!/bin/bash + +# T&M Hansson IT AB © - 2020, https://www.hanssonit.se/ +# Copyright © 2020 Simon Lindner (https://github.com/szaimen) + +# shellcheck disable=2034,2059 +true +SCRIPT_NAME="Midnight Commander" +SCRIPT_EXPLAINER="The Midnight Commander is a directory browsing and file manipulation program \ +that provides a flexible, powerful, and convenient set of file and directory operations. +It is capable of running in either a console or an xterm under X11. +Its basic operation is easily mastered by the novice while providing a rich feature set and extensive customization." +# shellcheck source=lib.sh +source /var/scripts/fetch_lib.sh || source <(curl -sL https://raw.githubusercontent.com/techandme/wordpress-vm/master/lib.sh) + +# Check for errors + debug code and abort if something isn't right +# 1 = ON +# 0 = OFF +DEBUG=0 +debug_mode + +# Check if root +root_check + +# Check if webmin is already installed +if ! is_this_installed mc +then + # Ask for installing + install_popup "$SCRIPT_NAME" +else + # Ask for removal or reinstallation + reinstall_remove_menu "$SCRIPT_NAME" + # Removal + apt purge mc -y + apt autoremove -y + # Show successful uninstall if applicable + removal_popup "$SCRIPT_NAME" +fi + +# Install mc +check_command apt install mc -y + +# Show successful installation +msg_box "Midnight Commander was successfully installed. +You can launch it by running 'mc' in the CLI." + +# Allow to install a dark theme +if ! yesno_box_yes "Do you want to install a dark theme for Midnight Commander?" +then + exit +fi + +# Install dark theme +print_text_in_color "$ICyan" "Installing dark theme for Midnight Commander..." +USER_HOMES=$(find /home -mindepth 1 -maxdepth 1 -type d) +mapfile -t USER_HOMES <<< "$USER_HOMES" +USER_HOMES+=(/root) +for user_home in "${USER_HOMES[@]}" +do + mkdir -p "$user_home/.config/mc" + cat << MC_INI > "$user_home/.config/mc/ini" +[Colors] +base_color=linux:normal=white,black:marked=yellow,black:input=,green:menu=black:menusel=white:\ +menuhot=red,:menuhotsel=black,red:dfocus=white,black:dhotnormal=white,black:\ +dhotfocus=white,black:executable=,black:directory=white,black:link=white,black:\ +device=white,black:special=white,black:core=,black:stalelink=red,black:editnormal=white,black +MC_INI +done + +# Inform the user +msg_box "The dark theme for Midnight Commander was successfully applied." +exit diff --git a/apps/netdata.sh b/apps/netdata.sh new file mode 100644 index 0000000..b1f2d06 --- /dev/null +++ b/apps/netdata.sh @@ -0,0 +1,101 @@ +#!/bin/bash + +# T&M Hansson IT AB © - 2020, https://www.hanssonit.se/ + +# shellcheck disable=2034,2059 +true +SCRIPT_NAME="Netdata" +SCRIPT_EXPLAINER="Netdata is an open source tool designed to collect real-time metrics, \ +such as CPU usage, disk activity, bandwidth usage, website visits, etc., \ +and then display them in live, easy-to-interpret charts. +The tool is designed to visualize activity in the greatest possible detail, \ +allowing the user to obtain an overview of what is happening \ +and what has just happened in their system or application." +# shellcheck source=lib.sh +source /var/scripts/fetch_lib.sh || source <(curl -sL https://raw.githubusercontent.com/techandme/wordpress-vm/master/lib.sh) + +# Check for errors + debug code and abort if something isn't right +# 1 = ON +# 0 = OFF +DEBUG=0 +debug_mode + +# Must be root +root_check + +# Can't be run as pure root user +if [ -z "$UNIXUSER" ] +then + msg_box "You can't run this script as a pure root user. You need to issue the following command: +sudo -u regular_user sudo bash $SCRIPTS/menu.sh + +Then choose Additional Apps --> Netdata" + exit 1 +fi + +# Check if netdata is already installed +if ! [ -d /etc/netdata ] +then + # Ask for installing + install_popup "$SCRIPT_NAME" +else + # Ask for removal or reinstallation + reinstall_remove_menu "$SCRIPT_NAME" + # Removal + if [ -f /usr/src/netdata.git/netdata-uninstaller.sh ] + then + if ! yes no | bash /usr/src/netdata.git/netdata-uninstaller.sh --force + then + rm -Rf /usr/src/netdata.git + fi + elif [ -f /usr/libexec/netdata-uninstaller.sh ] + then + yes no | bash /usr/libexec/netdata-uninstaller.sh --yes + elif [ -f /usr/libexec/netdata/netdata-uninstaller.sh ] + then + bash /usr/libexec/netdata/netdata-uninstaller.sh --force --yes + else + check_command curl_to_dir https://raw.githubusercontent.com/netdata/netdata/master/packaging/installer netdata-uninstaller.sh $SCRIPTS + check_command bash $SCRIPTS/netdata-uninstaller.sh --force --yes + rm $SCRIPTS/netdata-uninstaller.sh + rm -rf /var/lib/netdata + fi + rm -rf /etc/netdata + # Show successful uninstall if applicable + removal_popup "$SCRIPT_NAME" +fi + +# Install +is_process_running dpkg +is_process_running apt +apt update -q4 & spinner_loading +curl_to_dir https://my-netdata.io kickstart.sh $SCRIPTS +sudo -u "$UNIXUSER" bash $SCRIPTS/kickstart.sh all --dont-wait --no-updates --stable-channel +rm -f $SCRIPTS/kickstart.sh + +# Check Netdata instructions after script is done +any_key "Please check information above and press any key to continue..." + +# Installation done? +if [ -d /etc/netdata ] +then + msg_box "Netdata is now installed and can be accessed from this address: + +http://$ADDRESS:19999 + +If you want to reach it from the internet you need to open port 19999 in your firewall. +If you don't know how to open ports, please follow this guide: +https://www.techandme.se/open-port-80-443/ + +After you have opened the correct port, then you can visit Netdata from your domain: + +http://$(hostname -f):19999 and or http://yourdomanin.com:19999 + +You can find more configuration options in their WIKI: +https://docs.netdata.cloud/daemon/config#configuration-guide" + +# Cleanup +rm -rf /tmp/netdata* +fi + +exit diff --git a/apps/webmin.sh b/apps/webmin.sh index 865da45..6fd978e 100644 --- a/apps/webmin.sh +++ b/apps/webmin.sh @@ -1,11 +1,18 @@ #!/bin/bash -# T&M Hansson IT AB © - 2019, https://www.hanssonit.se/ +# T&M Hansson IT AB © - 2020, https://www.hanssonit.se/ # shellcheck disable=2034,2059 true +SCRIPT_NAME="Webmin" +SCRIPT_EXPLAINER="Webmin is a web-based interface for system administration for Unix. +Using any modern web browser, you can setup user accounts, Apache, DNS, file sharing and much more. +Webmin removes the need to manually edit Unix configuration files like /etc/passwd, \ +and lets you manage a system from the console or remotely. +See the following page with standard modules for a list of all the functions built into Webmin: \ +https://webmin.com/standard.html" # shellcheck source=lib.sh -. <(curl -sL https://raw.githubusercontent.com/techandme/wordpress-vm/master/lib.sh) +source /var/scripts/fetch_lib.sh || source <(curl -sL https://raw.githubusercontent.com/techandme/wordpress-vm/master/lib.sh) # Check for errors + debug code and abort if something isn't right # 1 = ON @@ -13,13 +20,55 @@ true DEBUG=0 debug_mode +# Check if root +root_check + +# Check if webmin is already installed +if ! is_this_installed webmin +then + # Ask for installing + install_popup "$SCRIPT_NAME" +else + # Ask for removal or reinstallation + reinstall_remove_menu "$SCRIPT_NAME" + # Removal + check_command apt-get purge webmin -y + rm -rf /etc/apt/sources.list.d/webmin.list + # Show successful uninstall if applicable + removal_popup "$SCRIPT_NAME" +fi + # Install packages for Webmin -apt install -y zip perl libnet-ssleay-perl openssl libauthen-pam-perl libpam-runtime libio-pty-perl apt-show-versions python +install_if_not apt-transport-https +install_if_not perl +install_if_not libnet-ssleay-perl +install_if_not openssl +install_if_not libauthen-pam-perl +install_if_not libpam-runtime +install_if_not libio-pty-perl +install_if_not apt-show-versions +install_if_not python2 # Install Webmin -sed -i '$a deb http://download.webmin.com/download/repository sarge contrib' /etc/apt/sources.list -if wget -q http://www.webmin.com/jcameron-key.asc -O- | sudo apt-key add - +if curl -fsSL http://www.webmin.com/jcameron-key.asc | sudo apt-key add - then + echo "deb https://download.webmin.com/download/repository sarge contrib" > /etc/apt/sources.list.d/webmin.list apt update -q4 & spinner_loading - apt install webmin -y + install_if_not webmin fi + +print_text_in_color "$ICyan" "Configuring Webmin..." +# redirect access on http to https +check_command systemctl stop webmin +# Redirect http to https on the LAN IP +check_command sed -i '/^ssl=.*/a ssl_redirect=1' /etc/webmin/miniserv.conf +check_command sed -i "/^port=.*/a host=$ADDRESS" /etc/webmin/miniserv.conf +start_if_stopped webmin + +msg_box "Webmin is now installed and can be accessed from this address: + +https://$ADDRESS:10000 + +You can log in with your Ubuntu CLI user: $UNIXUSER." + +exit diff --git a/lets-encrypt/activate-ssl.sh b/lets-encrypt/activate-ssl.sh deleted file mode 100644 index 7885f5b..0000000 --- a/lets-encrypt/activate-ssl.sh +++ /dev/null @@ -1,328 +0,0 @@ -#!/bin/bash -# shellcheck disable=2034,2059 -true -# shellcheck source=lib.sh -. <(curl -sL https://raw.githubusercontent.com/techandme/wordpress-vm/master/lib.sh) - -# T&M Hansson IT AB © - 2019, https://www.hanssonit.se/ - -# Check for errors + debug code and abort if something isn't right -# 1 = ON -# 0 = OFF -DEBUG=0 -debug_mode - -# Check if root -root_check - -# Information -msg_box "Important! Please read this: - -This script will install SSL from Let's Encrypt. -It's free of charge, and very easy to maintain. - -Before we begin the installation you need to have -a domain that the SSL certs will be valid for. -If you don't have a domain yet, get one before -you run this script! - -You also have to open port 80+443 against this VMs -IP address: $ADDRESS - do this in your router/FW. -Here is a guide: https://goo.gl/Uyuf65 - -You can find the script here: $SCRIPTS/activate-ssl.sh -and you can run it after you got a domain. - -Please don't run this script if you don't have -a domain yet. You can get one for a fair price here: -https://store.binero.se/?lang=en-US" - -if [[ "no" == $(ask_yes_or_no "Are you sure you want to continue?") ]] -then -msg_box "OK, but if you want to run this script later, -just type: sudo bash $SCRIPTS/activate-ssl.sh" - exit -fi - -if [[ "no" == $(ask_yes_or_no "Have you forwarded port 80+443 in your router?") ]] -then -msg_box "OK, but if you want to run this script later, -just type: sudo bash /var/scripts/activate-ssl.sh" - exit -fi - -if [[ "yes" == $(ask_yes_or_no "Do you have a domain that you will use?") ]] -then - sleep 1 -else -msg_box "OK, but if you want to run this script later, -just type: sudo bash /var/scripts/activate-ssl.sh" - exit -fi - -echo -while true -do -# Ask for domain name -cat << ENTERDOMAIN -+---------------------------------------------------------------+ -| Please enter the domain name you will use for Wordpress: | -| Like this: example.com, or wordpress.example.com | -+---------------------------------------------------------------+ -ENTERDOMAIN -echo -read -r domain -echo -if [[ "yes" == $(ask_yes_or_no "Is this correct? $domain") ]] -then - break -fi -done - -# Check if port is open with NMAP -sed -i "s|127.0.1.1.*|127.0.1.1 $domain wordpress|g" /etc/hosts -network_ok -check_open_port 80 "$domain" -check_open_port 443 "$domain" - -# Fetch latest version of test-new-config.sh -check_command download_le_script test-new-config - -# Check if $domain exists and is reachable -echo -print_text_in_color "$ICyan" "Checking if $domain exists and is reachable..." -if wget -q -T 10 -t 2 --spider "$domain"; then - sleep 1 -elif wget -q -T 10 -t 2 --spider --no-check-certificate "https://$domain"; then - sleep 1 -elif curl -s -k -m 10 "$domain"; then - sleep 1 -elif curl -s -k -m 10 "https://$domain" -o /dev/null ; then - sleep 1 -else -msg_box "Nope, it's not there. You have to create $domain and point -it to this server before you can run this script." - exit 1 -fi - -# Install certbot (Let's Encrypt) -install_certbot - -#Fix issue #28 -ssl_conf="/etc/nginx/sites-available/"$domain.conf"" - -# DHPARAM -DHPARAMS="$CERTFILES/$domain/dhparam.pem" - -# Check if "$ssl.conf" exists, and if, then delete -if [ -f "$ssl_conf" ] -then - rm -f "$ssl_conf" -fi - -# Generate vhost.conf -if [ ! -f "$ssl_conf" ] -then - touch "$ssl_conf" - print_text_in_color "$IGreen" "$ssl_conf was successfully created." - sleep 2 - cat << SSL_CREATE > "$ssl_conf" -server { - listen 80; - server_name $domain; - return 301 https://$domain\$request_uri; -} - -server { - listen 443 ssl http2; - listen [::]:443 ssl http2; - - ## Your website name goes here. - server_name $domain; - ## Your only path reference. - root $WPATH; - ## This should be in your http block and if it is, it's not needed here. - index index.php; - - resolver $GATEWAY; - - ## Show real IP behind proxy (change to the proxy IP) -# set_real_ip_from $GATEWAY/24; -# set_real_ip_from $GATEWAY; -# set_real_ip_from 2001:0db8::/32; -# real_ip_header X-Forwarded-For; -# real_ip_recursive on; - - # certs sent to the client in SERVER HELLO are concatenated in ssl_certificate - ssl_certificate $CERTFILES/$domain/fullchain.pem; - ssl_certificate_key $CERTFILES/$domain/privkey.pem; - ssl_session_timeout 1d; - ssl_session_cache shared:SSL:50m; - ssl_session_tickets off; - # Diffie-Hellman parameter for DHE ciphersuites, recommended 4096 bits - ssl_dhparam $DHPARAMS; - # intermediate configuration. tweak to your needs. - ssl_protocols TLSv1 TLSv1.1 TLSv1.2; - ssl_ciphers 'ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS'; - ssl_prefer_server_ciphers on; - # HSTS (ngx_http_headers_module is required) (15768000 seconds = 6 months) - add_header Strict-Transport-Security max-age=15768000; - # OCSP Stapling --- - # fetch OCSP records from URL in ssl_certificate and cache them - ssl_stapling on; - ssl_stapling_verify on; - - location / { - try_files \$uri \$uri/ /index.php?\$args; - # https://veerasundar.com/blog/2014/09/setting-expires-header-for-assets-nginx/ - if (\$request_uri ~* ".(ico|css|js|gif|jpe?g|png)$") { - expires 15d; - access_log off; - add_header Pragma public; - add_header Cache-Control "public"; - break; - } - } - location /.well-known { - root /usr/share/nginx/html; - } - location ~ /\\. { - access_log off; - log_not_found off; - deny all; - } - location = /favicon.ico { - log_not_found off; - access_log off; - } - location = /robots.txt { - allow all; - log_not_found off; - access_log off; - } - location ~* \.php$ { - location ~ \wp-login.php$ { - allow $GATEWAY/24; - #allow $ADDRESS; - #allow $WAN4IP; - deny all; - include fastcgi.conf; - fastcgi_intercept_errors on; - fastcgi_pass unix:/var/run/php/php7.2-fpm-wordpress.sock; - } - fastcgi_split_path_info ^(.+\.php)(/.+)$; - try_files \$uri =404; - fastcgi_index index.php; - include fastcgi.conf; - include fastcgi_params; - fastcgi_intercept_errors on; - fastcgi_pass unix:$PHP_FPM_SOCK; - fastcgi_buffers 16 16k; - fastcgi_buffer_size 32k; - fastcgi_param SCRIPT_FILENAME \$document_root\$fastcgi_script_name; - fastcgi_param SCRIPT_NAME \$fastcgi_script_name; - } - location ~* \\.(js|css|png|jpg|jpeg|gif|ico)$ { - expires max; - log_not_found off; - } -} -SSL_CREATE -fi - -# Methods -# https://certbot.eff.org/docs/using.html#certbot-command-line-options -default_le="--rsa-key-size 4096 --renew-by-default --no-eff-email --agree-tos --uir --hsts --server https://acme-v02.api.letsencrypt.org/directory -d $domain" - -standalone() { -# Generate certs -if eval "certbot certonly --standalone --pre-hook 'service nginx stop' --post-hook 'service nginx start' $default_le" -then - echo "success" > /tmp/le_test -else - echo "fail" > /tmp/le_test -fi -} -tls-alpn-01() { -if eval "certbot certonly --preferred-challenges tls-alpn-01 $default_le" -then - echo "success" > /tmp/le_test -else - echo "fail" > /tmp/le_test -fi -} -dns() { -if eval "certbot certonly --manual --manual-public-ip-logging-ok --preferred-challenges dns $default_le" -then - echo "success" > /tmp/le_test -else - echo "fail" > /tmp/le_test -fi -} - -methods=(standalone dns) - -create_config() { -# $1 = method -local method="$1" -# Check if $CERTFILES exists -if [ -d "$CERTFILES" ] - then - # Generate DHparams chifer - if [ ! -f "$DHPARAMS" ] - then - openssl dhparam -dsaparam -out "$DHPARAMS" 4096 - fi - # Activate new config - check_command bash "$SCRIPTS/test-new-config.sh" "$domain.conf" - exit -fi -} - -attempts_left() { -local method="$1" -if [ "$method" == "standalone" ] -then - printf "%b" "${ICyan}It seems like no certs were generated, we will do 1 more try.\n${Color_Off}" - any_key "Press any key to continue..." -#elif [ "$method" == "tls-alpn-01" ] -#then -# printf "%b" "${ICyan}It seems like no certs were generated, we will do 1 more try.\n${Color_Off}" -# any_key "Press any key to continue..." -elif [ "$method" == "dns" ] -then - printf "%b" "${IRed}It seems like no certs were generated, please check your DNS and try again.\n${Color_Off}" - any_key "Press any key to continue..." -fi -} - -# Generate the cert -for f in "${methods[@]}"; do "$f" -if [ "$(grep 'success' /tmp/le_test)" == 'success' ]; then - rm -f /tmp/le_test - create_config "$f" -else - rm -f /tmp/le_test - attempts_left "$f" -fi -done - -# Failed -msg_box "Sorry, last try failed as well. :/ - -The script is located in $SCRIPTS/activate-ssl.sh -Please try to run it again some other time with other settings. - -There are different configs you can try in Let's Encrypt's user guide: -https://letsencrypt.readthedocs.org/en/latest/index.html -Please check the guide for further information on how to enable SSL. - -This script is developed on GitHub, feel free to contribute: -https://github.com/techandme/wordpress-vm - -The script will now do some cleanup and revert the settings." - -# Cleanup -apt remove certbot -y -apt autoremove -y -clear diff --git a/lets-encrypt/activate-tls.sh b/lets-encrypt/activate-tls.sh new file mode 100644 index 0000000..9b210a4 --- /dev/null +++ b/lets-encrypt/activate-tls.sh @@ -0,0 +1,247 @@ +#!/bin/bash +# shellcheck disable=2034,2059 +true +SCRIPT_NAME="Activate TLS" +# shellcheck source=lib.sh +source /var/scripts/fetch_lib.sh || source <(curl -sL https://raw.githubusercontent.com/techandme/wordpress-vm/master/lib.sh) + +# T&M Hansson IT AB © - 2020, https://www.hanssonit.se/ + +# Check for errors + debug code and abort if something isn't right +# 1 = ON +# 0 = OFF +DEBUG=0 +debug_mode + +# Check if root +root_check + +# Information +# Information +msg_box "Before we begin the installation of your TLS certificate you need to: + +1. Have a domain like: wordpress.example.com +If you want to get a domain at a fair price, please check this out: https://store.binero.se/?lang=en-US + +2. Open port 80 and 443 against this servers IP address: $ADDRESS. +Here is a guide: https://www.techandme.se/open-port-80-443 +It's also possible to automatically open ports with UPNP, if you have that enabled in your firewall/router. + +PLEASE NOTE: +This script can be run again by executing: sudo bash $SCRIPTS/menu.sh, and choose 'Server Configuration' --> 'Activate TLS'" + +if ! yesno_box_yes "Are you sure you want to continue?" +then + msg_box "OK, but if you want to run this script later, just execute this in your CLI: sudo \ +bash /var/scripts/menu.sh and choose 'Server Configuration' --> 'Activate TLS'" + exit +fi + +if ! yesno_box_yes "Have you opened port 80 and 443 in your router, or are you using UPNP?" +then + msg_box "OK, but if you want to run this script later, just execute this in your CLI: sudo \ +bash /var/scripts/menu.sh and choose 'Server Configuration' --> 'Activate TLS'" + exit +fi + +if ! yesno_box_yes "Do you have a domain that you will use?" +then + msg_box "OK, but if you want to run this script later, just execute this in your CLI: sudo \ +bash /var/scripts/menu.sh and choose 'Server Configuration' --> 'Activate TLS'" + exit +fi + +# Wordpress Main Domain (activate-tls.sh) +TLSDOMAIN=$(input_box_flow "Please enter the domain name you will use for Wordpress. +Make sure it looks like this:\nyourdomain.com, or www.yourdomain.com") + +msg_box "Before continuing, please make sure that you have you have edited the DNS settings for $TLSDOMAIN, \ +and opened port 80 and 443 directly to this servers IP. A full exstensive guide can be found here: +https://www.techandme.se/open-port-80-443 + +This can be done automatically if you have UNNP enabled in your firewall/router. \ +You will be offered to use UNNP in the next step." + +if yesno_box_no "Do you want to use UPNP to open port 80 and 443?" +then + unset FAIL + open_port 80 TCP + open_port 443 TCP + cleanup_open_port +fi + +# Curl the lib another time to get the correct https_conf +# shellcheck source=lib.sh +source /var/scripts/fetch_lib.sh || source <(curl -sL https://raw.githubusercontent.com/techandme/wordpress-vm/w0.04_testing/lib.sh) + +# Check if $TLSDOMAIN exists and is reachable +echo +print_text_in_color "$ICyan" "Checking if $TLSDOMAIN exists and is reachable..." +domain_check_200 "$TLSDOMAIN" + +# Check if port is open with NMAP +sed -i "s|127.0.1.1.*|127.0.1.1 $TLSDOMAIN wordpress|g" /etc/hosts +network_ok +check_open_port 80 "$TLSDOMAIN" +check_open_port 443 "$TLSDOMAIN" + +# Fetch latest version of test-new-config.sh +check_command download_script LETS_ENC test-new-config + +# Install certbot (Let's Encrypt) +install_certbot + +#Fix issue #28 +tls_conf="$SITES_AVAILABLE/$TLSDOMAIN.conf" + +# Check if "$tls.conf" exists, and if, then delete +if [ -f "$tls_conf" ] +then + rm -f "$tls_conf" +fi + +# Check current PHP version --> PHPVER +# To get the correct version for the Nginx conf file +check_php + +# Generate wordpress_tls_domain.conf +if [ ! -f "$tls_conf" ] +then + touch "$tls_conf" + print_text_in_color "$IGreen" "$tls_conf was successfully created." + sleep 2 + cat << TLS_CREATE > "$tls_conf" +server { + listen 80; + server_name $TLSDOMAIN; + return 301 https://$TLSDOMAIN\$request_uri; +} +server { + listen 443 ssl http2; + listen [::]:443 ssl http2; + + ## Your website name goes here. + server_name $TLSDOMAIN; + ## Your only path reference. + root $WPATH; + ## This should be in your http block and if it is, it's not needed here. + index index.php; + + resolver $GATEWAY; + + ## Show real IP behind proxy (change to the proxy IP) +# set_real_ip_from $GATEWAY/24; +# set_real_ip_from $GATEWAY; +# set_real_ip_from 2001:0db8::/32; +# real_ip_header X-Forwarded-For; +# real_ip_recursive on; + + # certs sent to the client in SERVER HELLO are concatenated in ssl_certificate + ssl_certificate $CERTFILES/$TLSDOMAIN/fullchain.pem; + ssl_certificate_key $CERTFILES/$TLSDOMAIN/privkey.pem; + ssl_session_timeout 1d; + ssl_session_cache shared:SSL:50m; + ssl_session_tickets off; + # Diffie-Hellman parameter for DHE ciphersuites, recommended 4096 bits + ssl_dhparam $DHPARAMS; + # intermediate configuration. tweak to your needs. + ssl_protocols TLSv1.2 TLSv1.3; + ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384; + ssl_prefer_server_ciphers on; + # HSTS (ngx_http_headers_module is required) (15768000 seconds = 6 months) + add_header Strict-Transport-Security max-age=15768000; + # OCSP Stapling --- + # fetch OCSP records from URL in ssl_certificate and cache them + ssl_stapling on; + ssl_stapling_verify on; + + location / { + try_files \$uri \$uri/ /index.php?\$args; + # https://veerasundar.com/blog/2014/09/setting-expires-header-for-assets-nginx/ + if (\$request_uri ~* ".(ico|css|js|gif|jpe?g|png)$") { + expires 15d; + access_log off; + add_header Pragma public; + add_header Cache-Control "public"; + break; + } + } + location /.well-known { + root /usr/share/nginx/html; + } + location ~ /\\. { + access_log off; + log_not_found off; + deny all; + } + location = /favicon.ico { + log_not_found off; + access_log off; + } + location = /robots.txt { + allow all; + log_not_found off; + access_log off; + } + location ~* \.php$ { + location ~ \wp-login.php$ { + allow $GATEWAY/24; + #allow $ADDRESS; + #allow $WAN4IP; + deny all; + include fastcgi.conf; + fastcgi_intercept_errors on; + fastcgi_pass unix:/var/run/php/php7.2-fpm-wordpress.sock; + } + fastcgi_split_path_info ^(.+\.php)(/.+)$; + try_files \$uri =404; + fastcgi_index index.php; + include fastcgi.conf; + include fastcgi_params; + fastcgi_intercept_errors on; + fastcgi_pass unix:$PHP_FPM_SOCK; + fastcgi_buffers 16 16k; + fastcgi_buffer_size 32k; + fastcgi_param SCRIPT_FILENAME \$document_root\$fastcgi_script_name; + fastcgi_param SCRIPT_NAME \$fastcgi_script_name; + } + location ~* \\.(js|css|png|jpg|jpeg|gif|ico)$ { + expires max; + log_not_found off; + } +} +TLS_CREATE +fi + +# Check if PHP-FPM is installed and if not, then remove PHP-FPM related lines from config +if ! pgrep php-fpm +then + sed -i "s| /dev/null then - service nginx start + start_if_stopped nginx.service fi CRONTAB } @@ -71,14 +74,16 @@ chmod +x $SCRIPTS/letsencryptrenew.sh # Cleanup rm -f $SCRIPTS/test-new-config.sh -rm -f $SCRIPTS/activate-ssl.sh +rm -f $SCRIPTS/activate-tls.sh else + + + # If it fails, revert changes back to normal - rm -f /etc/nginx/sites-enabled/"$1" - ln -s /etc/nginx/sites-available/wordpress_port_80.conf /etc/nginx/sites-enabled/ + rm -f "$SITES_ENABLED"/"$1" + ln -s "$$SITES_AVAILABLE/$HTTP_CONF" "$SITES_ENABLED" restart_webserver - printf "${ICyan}Couldn't load new config, reverted to old settings. Self-signed SSL is OK!${Color_Off}\n" - any_key "Press any key to continue... " + msg_box "Couldn't load new config, reverted to old settings. Self-signed TLS is OK!" exit 1 fi diff --git a/lib.sh b/lib.sh index 4cc0e0b..42cdd2a 100644 --- a/lib.sh +++ b/lib.sh @@ -3,92 +3,152 @@ true # see https://github.com/koalaman/shellcheck/wiki/Directive -## variables +## VARIABLES + # Dirs SCRIPTS=/var/scripts WWW_ROOT=/var/www/html WPATH=$WWW_ROOT/wordpress GPGDIR=/tmp/gpg +VMLOGS=/var/log/wordpress + +# Helper function for generating random passwords +gen_passwd() { + local length=$1 + local charset="$2" + local password="" + while [ ${#password} -lt "$length" ] + do + password=$(echo "$password""$(head -c 100 /dev/urandom | LC_ALL=C tr -dc "$charset")" | fold -w "$length" | head -n 1) + done + echo "$password" +} # Ubuntu OS -DISTRO=$(lsb_release -sd | cut -d ' ' -f 2) -OS=$(grep -ic "Ubuntu" /etc/issue.net) +DISTRO=$(lsb_release -sr) +KEYBOARD_LAYOUT=$(localectl status | grep "Layout" | awk '{print $3}') +# Hypervisor +# HYPERVISOR=$(dmesg --notime | grep -i hypervisor | cut -d ':' -f2 | head -1 | tr -d ' ') TODO +SYSVENDOR=$(cat /sys/devices/virtual/dmi/id/sys_vendor) # Network -[ -n "$FIRST_IFACE" ] && IFACE=$(lshw -c network | grep "logical name" | awk '{print $3; exit}') +IFACE=$(ip r | grep "default via" | awk '{print $5}') IFACE2=$(ip -o link show | awk '{print $2,$9}' | grep 'UP' | cut -d ':' -f 1) -[ -n "$CHECK_CURRENT_REPO" ] && REPO=$(apt-get update | grep -m 1 Hit | awk '{ print $2}') +REPO=$(grep deb-src /etc/apt/sources.list | grep http | awk '{print $3}' | head -1) ADDRESS=$(hostname -I | cut -d ' ' -f 1) -WGET="/usr/bin/wget" -WANIP4=$(curl -s -m 5 ipinfo.io/ip) -[ -n "$LOAD_IP6" ] && WANIP6=$(curl -s -k -m 7 https://6.ifcfg.me) -IFCONFIG="/sbin/ifconfig" + +# WANIP4=$(dig +short myip.opendns.com @resolver1.opendns.com) # as an alternative +WANIP4=$(curl -s -k -m 5 https://ipv4bot.whatismyipaddress.com) INTERFACES="/etc/netplan/01-netcfg.yaml" -NETMASK=$($IFCONFIG | grep -w inet |grep -v 127.0.0.1| awk '{print $4}' | cut -d ":" -f 2) -GATEWAY=$(route -n|grep "UG"|grep -v "UGH"|cut -f 10 -d " ") +GATEWAY=$(ip route | grep default | awk '{print $3}') + +# Internet DNS +INTERNET_DNS="9.9.9.9" + +# Default Quad9 DNS servers, overwritten by the systemd global DNS defined servers, if set DNS1="9.9.9.9" DNS2="149.112.112.112" +use_global_systemd_dns() { +if [ -f "/etc/systemd/resolved.conf" ] +then + local resolvedDns1 + resolvedDns1=$(grep -m 1 -E "^DNS=.+" /etc/systemd/resolved.conf | sed s/^DNS=// | awk '{print $1}') + if [ -n "$resolvedDns1" ] + then + DNS1="$resolvedDns1" + + local resolvedDns2 + resolvedDns2=$(grep -m 1 -E "^DNS=.+" /etc/systemd/resolved.conf | sed s/^DNS=// | awk '{print $2}') + if [ -n "$resolvedDns2" ] + then + DNS2="$resolvedDns2" + else + DNS2= + fi + fi +fi +} +use_global_systemd_dns + +# Whiptails +TITLE="Wordpress VM - $(date +%Y)" +[ -n "$SCRIPT_NAME" ] && TITLE+=" - $SCRIPT_NAME" +CHECKLIST_GUIDE="Navigate with the [ARROW] keys and (de)select with the [SPACE] key. \ +Confirm by pressing [ENTER]. Cancel by pressing [ESC]." +MENU_GUIDE="Navigate with the [ARROW] keys and confirm by pressing [ENTER]. Cancel by pressing [ESC]." +RUN_LATER_GUIDE="You can view this script later by running 'sudo bash $SCRIPTS/menu.sh'." # Repo GITHUB_REPO="https://raw.githubusercontent.com/techandme/wordpress-vm/master" STATIC="$GITHUB_REPO/static" LETS_ENC="$GITHUB_REPO/lets-encrypt" -ISSUES="https://github.com/techandme/wordpress-vm/issues" APP="$GITHUB_REPO/apps" +OLD="$GITHUB_REPO/old" +ADDONS="$GITHUB_REPO/addons" +MENU="$GITHUB_REPO/menu" +DISK="$GITHUB_REPO/disk" +NETWORK="$GITHUB_REPO/network" +ISSUES="https://github.com/techandme/wordpress-vm/vm/issues" # User information -WPDBNAME=wordpress_by_www_hanssonit_se -WPADMINUSER=change_this_user +WPPASS=wordpress +WPUSER=wordpress UNIXUSER=$SUDO_USER UNIXUSER_PROFILE="/home/$UNIXUSER/.bash_profile" ROOT_PROFILE="/root/.bash_profile" -# PHP-FPM -PHPVER=7.2 -PHP_INI=/etc/php/"$PHPVER"/fpm/php.ini -PHP_POOL_DIR=/etc/php/"$PHPVER"/fpm/pool.d -PHP_FPM_SOCK=/var/run//php/php"$PHPVER"-fpm-wordpress.sock - -# MARIADB +# Database SHUF=$(shuf -i 25-29 -n 1) +WPDBNAME=wordpress_by_www_hanssonit_se +WPADMINUSER=wordpress_gui_admin_user MARIADB_PASS=$(tr -dc "a-zA-Z0-9@#*=" < /dev/urandom | fold -w "$SHUF" | head -n 1) WPDBPASS=$(tr -dc "a-zA-Z0-9@#*=" < /dev/urandom | fold -w "$SHUF" | head -n 1) NEWMARIADBPASS=$(tr -dc "a-zA-Z0-9@#*=" < /dev/urandom | fold -w "$SHUF" | head -n 1) -WPDBUSER=wordpress_user +WPDBUSER=wordpress_db_user WPADMINPASS=$(tr -dc "a-zA-Z0-9@#*=" < /dev/urandom | fold -w "$SHUF" | head -n 1) -[ -n "$WPDB" ] && WPCONFIGDB=$(grep "DB_PASSWORD" /var/www/html/wordpress/wp-config.php | awk '{print $3}' | cut -d "'" -f2) -MYCNF=/root/.my.cnf -[ -n "$MYCNFPW" ] && MARIADBMYCNFPASS=$(grep "password" $MYCNF | sed -n "/password/s/^password='\(.*\)'$/\1/p") + +# Set the hour for automatic updates. This would be 18:00 as only the hour is configurable. +AUT_UPDATES_TIME="18" + +# Keys +OpenPGP_fingerprint='28806A878AE423A28372792ED75899B9A724937A' + +# Letsencrypt +SITES_AVAILABLE="/etc/nginx/sites-available" +SITES_ENABLED="/etc/nginx/sites-enabled" +LETSENCRYPTPATH="/etc/letsencrypt" +CERTFILES="$LETSENCRYPTPATH/live" +DHPARAMS_TLS="$CERTFILES/$TLSDOMAIN/dhparam.pem" +DHPARAMS_SUB="$CERTFILES/$SUBDOMAIN/dhparam.pem" +TLS_CONF="wordpress_tls_domain_self_signed.conf" +HTTP_CONF="wordpress_http_domain_self_signed.conf" + # Path to specific files SECURE="$SCRIPTS/wp-permissions.sh" -SSL_CONF="/etc/nginx/sites-available/wordpress_port_443.conf" -HTTP_CONF="/etc/nginx/sites-available/wordpress_port_80.conf" ETCMYCNF="/etc/mysql/my.cnf" NGINX_CONF="/etc/nginx/nginx.conf" -NGINX_DEF="/etc/nginx/sites-available/default" +NGINX_DEF="$SITES_AVAILABLE/default" -# Letsencrypt -LETSENCRYPTPATH="/etc/letsencrypt" -CERTFILES="$LETSENCRYPTPATH/live" -DHPARAMS="$CERTFILES/$SUBDOMAIN/dhparam.pem" +# PHP-FPM +PHPVER=7.4 +PHP_FPM_DIR=/etc/php/$PHPVER/fpm +PHP_INI=$PHP_FPM_DIR/php.ini +PHP_POOL_DIR=$PHP_FPM_DIR/pool.d +PHP_MODS_DIR=/etc/php/"$PHPVER"/mods-available +PHP_FPM_SOCK=/var/run/php"$PHPVER"-fpm-wordpress.sock # Adminer ADMINERDIR=/usr/share/adminer -ADMINER_CONF=/etc/nginx/sites-available/adminer.conf +ADMINER_CONF="$SITES_ENABLED/adminer.conf" # Redis REDIS_CONF=/etc/redis/redis.conf REDIS_SOCK=/var/run/redis/redis-server.sock RSHUF=$(shuf -i 30-35 -n 1) -REDIS_PASS=$(tr -dc "a-zA-Z0-9@#*=" < /dev/urandom | fold -w "$RSHUF" | head -n 1) +REDIS_PASS=$(gen_passwd "$SHUF" "a-zA-Z0-9@#*=") REDISPTXT=/tmp/redispasstxt -# Extra security -SPAMHAUS=/etc/spamhaus.wl -ENVASIVE=/etc/apache2/mods-available/mod-evasive.load -APACHE2=/etc/apache2/apache2.conf - -## functions +## FUNCTIONS # If script is running as root? # @@ -114,22 +174,190 @@ is_root() { root_check() { if ! is_root then -msg_box "Sorry, you are not root. You now have two options: + msg_box "Sorry, you are not root. You now have two options: + 1. With SUDO directly: a) :~$ sudo bash $SCRIPTS/name-of-script.sh + 2. Become ROOT and then type your command: a) :~$ sudo -i - b) :~# $SCRIPTS/name-of-script.sh + b) :~# bash $SCRIPTS/name-of-script.sh + In both cases above you can leave out $SCRIPTS/ if the script is directly in your PATH. + More information can be found here: https://unix.stackexchange.com/a/3064" exit 1 fi } +debug_mode() { +if [ "$DEBUG" -eq 1 ] +then + set -ex +fi +} + +msg_box() { + [ -n "$2" ] && local SUBTITLE=" - $2" + whiptail --title "$TITLE$SUBTITLE" --msgbox "$1" "$WT_HEIGHT" "$WT_WIDTH" 3>&1 1>&2 2>&3 +} + +yesno_box_yes() { + [ -n "$2" ] && local SUBTITLE=" - $2" + if (whiptail --title "$TITLE$SUBTITLE" --yesno "$1" "$WT_HEIGHT" "$WT_WIDTH" 3>&1 1>&2 2>&3) + then + return 0 + else + return 1 + fi +} + +yesno_box_no() { + [ -n "$2" ] && local SUBTITLE=" - $2" + if (whiptail --title "$TITLE$SUBTITLE" --defaultno --yesno "$1" "$WT_HEIGHT" "$WT_WIDTH" 3>&1 1>&2 2>&3) + then + return 0 + else + return 1 + fi +} + +input_box() { + [ -n "$2" ] && local SUBTITLE=" - $2" + local RESULT && RESULT=$(whiptail --title "$TITLE$SUBTITLE" --nocancel --inputbox "$1" "$WT_HEIGHT" "$WT_WIDTH" 3>&1 1>&2 2>&3) + echo "$RESULT" +} + +input_box_flow() { + local RESULT + while : + do + RESULT=$(input_box "$1" "$2") + if [ -z "$RESULT" ] + then + msg_box "Input is empty, please try again." "$2" + elif ! yesno_box_yes "Is this correct? $RESULT" "$2" + then + msg_box "OK, please try again." "$2" + else + break + fi + done + echo "$RESULT" +} + +install_popup() { + msg_box "$SCRIPT_EXPLAINER" + if yesno_box_yes "Do you want to install $1?" + then + print_text_in_color "$ICyan" "Installing $1..." + else + if [ -z "$2" ] || [ "$2" = "exit" ] + then + exit 1 + elif [ "$2" = "sleep" ] + then + sleep 1 + elif [ "$2" = "return" ] + then + return 1 + else + exit 1 + fi + fi +} + +reinstall_remove_menu() { + REINSTALL_REMOVE=$(whiptail --title "$TITLE" --menu \ +"It seems like $1 is already installed.\nChoose what you want to do. +$MENU_GUIDE\n\n$RUN_LATER_GUIDE" "$WT_HEIGHT" "$WT_WIDTH" 4 \ +"Reinstall" " $1" \ +"Uninstall" " $1" 3>&1 1>&2 2>&3) + if [ "$REINSTALL_REMOVE" = "Reinstall" ] + then + print_text_in_color "$ICyan" "Reinstalling $1..." + elif [ "$REINSTALL_REMOVE" = "Uninstall" ] + then + print_text_in_color "$ICyan" "Uninstalling $1..." + elif [ -z "$REINSTALL_REMOVE" ] + then + if [ -z "$2" ] || [ "$2" = "exit" ] + then + exit 1 + elif [ "$2" = "sleep" ] + then + sleep 1 + elif [ "$2" = "return" ] + then + return 1 + else + exit 1 + fi + fi +} + +removal_popup() { + if [ "$REINSTALL_REMOVE" = "Uninstall" ] + then + msg_box "$1 was successfully uninstalled." + if [ -z "$2" ] || [ "$2" = "exit" ] + then + exit 1 + elif [ "$2" = "sleep" ] + then + sleep 1 + elif [ "$2" = "return" ] + then + return 1 + else + exit 1 + fi + elif [ "$REINSTALL_REMOVE" = "Reinstall" ] + then + print_text_in_color "$ICyan" "Reinstalling $1..." + else + msg_box "It seems like neither Uninstall nor Reinstall is chosen, \ +something is wrong here. Please report this to $ISSUES" + exit 1 + fi +} + wp_cli_cmd() { -export WP_CLI_CACHE_DIR=$WPATH/.wp-cli/cache -check_command sudo -u www-data /usr/local/bin/wp "$@"; +# Check if Wordpress is installed in the regular path or try to find it +if [ ! -d "$WPATH" ] +then + WPATH="/var/www/$(find /var/www/* -type d | grep wp | head -1 | cut -d "/" -f4)" + export WPATH + if [ ! -d "$WPATH"/wp-admin ] + then + WPATH="/var/www/$(find /var/www/* -type d | grep wp | tail -1 | cut -d "/" -f4)" + export WPATH + if [ ! -d "$WPATH"/wp-admin ] + then + WPATH="/var/www/html/$(find /var/www/html/* -type d | grep wp | head -1 | cut -d "/" -f5)" + export WPATH + if [ ! -d "$WPATH"/wp-admin ] + then + WPATH="/var/www/html/$(find /var/www/html/* -type d | grep wp | tail -1 | cut -d "/" -f5)" + export WPATH + if [ ! -d "$WPATH"/wp-admin ] + then + msg_box "Wordpress doesn't seem to be installed in the regular path. We tried to find it, but didn't succeed. + +The script will now exit." + exit 1 + fi + fi + fi + fi +fi +# If everytthing seems OK, then run wp cli +cd "$WPATH" +export WP_CLI_CACHE_DIR="$WPATH/.wp-cli/cache" +check_command sudo -u www-data /usr/local/bin/wp --path="$WPATH" "$@"; +# Go back to user dir +cd } # Check if process is runnnig: is_process_running dpkg @@ -143,37 +371,180 @@ do if [ "${RESULT:-null}" = null ]; then break else - print_text_in_color "$ICyan" "${PROCESS} is running. Waiting for it to stop..." + print_text_in_color "$ICyan" "${PROCESS} is running, waiting for it to stop..." sleep 10 fi done } -debug_mode() { -if [ "$DEBUG" -eq 1 ] +# Checks if site is reachable with a HTTP 200 status +site_200() { +print_text_in_color "$ICyan" "Checking connection..." + CURL_STATUS="$(curl -LI "${1}" -o /dev/null -w '%{http_code}\n' -s)" + if [[ "$CURL_STATUS" = "200" ]] + then + return 0 + else + print_text_in_color "$IRed" "curl didn't produce a 200 status, is ${1} reachable?" + return 1 + fi +} + +# Do a DNS lookup and compare the WAN address with the A record +domain_check_200() { + print_text_in_color "$ICyan" "Doing a DNS lookup for ${1}..." + install_if_not dnsutils + + # Try to resolve the domain with nslookup using $DNS as resolver + if nslookup "${1}" "$INTERNET_DNS" >/dev/null 2>&1 + then + print_text_in_color "$IGreen" "DNS seems correct when checking with nslookup!" + else + print_text_in_color "$IRed" "DNS lookup failed with nslookup." + print_text_in_color "$IRed" "Please check your DNS settings! Maybe the domain isn't propagated?" + print_text_in_color "$ICyan" "Please check https://www.whatsmydns.net/#A/${1} if the IP seems correct." + nslookup "${1}" "$INTERNET_DNS" + return 1 + fi + + # Is the DNS record same as the external IP address of the server? + if dig +short "${1}" @resolver1.opendns.com | grep -q "$WANIP4" + then + print_text_in_color "$IGreen" "DNS seems correct when checking with dig!" + else + msg_box "DNS lookup failed with dig. The external IP ($WANIP4) \ +address of this server is not the same as the A-record ($DIG). +Please check your DNS settings! Maybe the domain isn't propagated? +Please check https://www.whatsmydns.net/#A/${1} if the IP seems correct." + + msg_box "As you noticed your WAN IP and DNS record doesn't match. \ +This can happen when using DDNS for example, or in some edge cases. +If you feel brave, or are sure that everything is setup correctly, \ +then you can choose to skip this test in the next step. + +You can always contact us for further support if you wish: \ +https://shop.hanssonit.se/product/premium-support-per-30-minutes/" + if ! yesno_box_no "Do you feel brave and want to continue?" + then + exit + fi + fi +} + +# A function to set the systemd-resolved default DNS servers based on the +# current Internet facing interface. This is needed for docker interfaces +# that might not use the same DNS servers otherwise. +set_systemd_resolved_dns() { +local iface="$1" +local pattern="$iface(?:.|\n)*?DNS Servers: ((?:[0-9a-f.: ]|\n)*?)\s*(?=\n\S|\n.+: |$)" +local dnss +dnss=$( systemd-resolve --status | perl -0777 -ne "if ((\$v) = (/$pattern/)) {\$v=~s/(?:\s|\n)+/ /g;print \"\$v\n\";}" ) +if [ -n "$dnss" ] then - set -ex + sed -i "s/^#\?DNS=.*$/DNS=${dnss}/" /etc/systemd/resolved.conf + systemctl restart systemd-resolved &>/dev/null + sleep 1 +fi +} + +# A function to fetch a file with curl to a directory +# 1 = https://example.com +# 2 = name of file +# 3 = directory that the file should end up in +curl_to_dir() { +if [ ! -d "$3" ] +then + mkdir -p "$3" +fi + rm -f "$3"/"$2" + curl -sfL "$1"/"$2" -o "$3"/"$2" +} + +start_if_stopped() { +if ! pgrep "$1" +then + print_text_in_color "$ICyan" "Starting $1..." + systemctl start "$1".service +fi +} + +# Compatibility with older VMs +calculate_max_children() { + calculate_php_fpm +} + +test_connection() { +version(){ + local h t v + + [[ $2 = "$1" || $2 = "$3" ]] && return 0 + + v=$(printf '%s\n' "$@" | sort -V) + h=$(head -n1 <<<"$v") + t=$(tail -n1 <<<"$v") + + [[ $2 != "$h" && $2 != "$t" ]] +} +if ! version 18.04 "$DISTRO" 20.04.6 +then + print_text_in_color "$IRed" "Your current Ubuntu version is $DISTRO but must be between \ +18.04 - 20.04.4 to run this script." + print_text_in_color "$ICyan" "Please contact us to get support for upgrading your server:" + print_text_in_color "$ICyan" "https://www.hanssonit.se/#contact" + print_text_in_color "$ICyan" "https://shop.hanssonit.se/" + sleep 300 +fi + +# Install dnsutils if not existing +if ! dpkg-query -W -f='${Status}' "dnsutils" | grep -q "ok installed" +then + apt update -q4 & spinner_loading && apt install dnsutils -y +fi +# Install net-tools if not existing +if ! dpkg-query -W -f='${Status}' "net-tools" | grep -q "ok installed" +then + apt update -q4 & spinner_loading && apt install net-tools -y +fi +# After applying Netplan settings, try a DNS lookup. +# Restart systemd-networkd if this fails and try again. +# If this second check also fails, consider this a problem. +print_text_in_color "$ICyan" "Checking connection..." +netplan apply +sleep 2 +if ! nslookup github.com +then + print_text_in_color "$ICyan" "Trying to restart netplan service..." + check_command systemctl restart systemd-networkd && sleep 2 + if ! nslookup github.com + then + msg_box "Network NOT OK. You must have a working network connection to run this script. +If you think that this is a bug, please report it to https://github.com/techandme/wordpress-vm/issues." + return 1 + fi fi +print_text_in_color "$IGreen" "Online!" +return 0 } -ask_yes_or_no() { - read -r -p "$1 ([y]es or [N]o): " - case ${REPLY,,} in - y|yes) - echo "yes" - ;; - *) - echo "no" - ;; - esac + +# Check that the script can see the external IP (nginx fails otherwise), used e.g. in the adminer app script. +check_external_ip() { +if [ -z "$WANIP4" ] +then + print_text_in_color "$IRed" "WANIP4 is an emtpy value, Nginx will fail on reboot due to this. \ +Please check your network and try again." + sleep 3 + exit 1 +fi } restart_webserver() { -check_command systemctl restart nginx +check_command systemctl restart nginx.service if is_this_installed php"$PHPVER"-fpm then check_command systemctl restart php"$PHPVER"-fpm.service fi + } # Install certbot (Let's Encrypt) @@ -182,44 +553,168 @@ certbot --version 2> /dev/null LE_IS_AVAILABLE=$? if [ $LE_IS_AVAILABLE -eq 0 ] then - certbot --version + certbot --version 2> /dev/null else print_text_in_color "$ICyan" "Installing certbot (Let's Encrypt)..." - apt update -q4 & spinner_loading - apt install software-properties-common - add-apt-repository ppa:certbot/certbot -y - apt update -q4 & spinner_loading - apt install certbot -y -q - apt update -q4 & spinner_loading - apt dist-upgrade -y + install_if_not snapd + snap install certbot --classic + # Update $PATH in current session (login and logout is required otherwise) + check_command hash -r +fi +} + +# Generate certs and configure it automatically +# https://certbot.eff.org/docs/using.html#certbot-command-line-options +generate_cert() { +uir_hsts="" +if [ -z "$SUBDOMAIN" ] +then + uir_hsts="--uir --hsts" +fi +rm -f "$SITES_ENABLED"/default.conf +rm -f "$SITES_ENABLED"/default +systemctl reload nginx.service +default_le="--rsa-key-size 4096 --renew-by-default --no-eff-email --agree-tos $uir_hsts --server https://acme-v02.api.letsencrypt.org/directory -d $1" +#http-01 +local standalone="certbot certonly --standalone --pre-hook \"systemctl stop nginx.service\" --post-hook \"systemctl start nginx.service\" $default_le" +#tls-alpn-01 +local tls_alpn_01="certbot certonly --preferred-challenges tls-alpn-01 $default_le" +#dns +local dns="certbot certonly --manual --manual-public-ip-logging-ok --preferred-challenges dns $default_le" +local methods=(standalone dns) + +for f in ${methods[*]} +do + print_text_in_color "${ICyan}" "Trying to generate certs and validate them with $f method." + current_method="" + eval current_method="\$$f" + if eval "$current_method" + then + return 0 + elif [ "$f" != "${methods[$((${#methods[*]} - 1))]}" ] + then + msg_box "It seems like no certs were generated when trying \ +to validate them with the $f method. We will do more tries." + else + msg_box "It seems like no certs were generated when trying \ +to validate them with the $f method. We have tried all the methods. Please check your DNS and try again." + return 1; + fi +done +} + +# Last message depending on with script that is being run when using the generate_cert() function +last_fail_tls() { + msg_box "All methods failed. :/ + +You can run the script again by executing: sudo bash $SCRIPTS/menu.sh +Please try to run it again some other time with other settings. + +There are different configs you can try in Let's Encrypt's user guide: +https://letsencrypt.readthedocs.org/en/latest/index.html +Please check the guide for further information on how to enable TLS. + +This script is developed on GitHub, feel free to contribute: +https://github.com/techandme/wordpress-vm" + +if [ -n "$2" ] +then + msg_box "The script will now do some cleanup and revert the settings." + # Cleanup + snap remove certbot + rm -f "$SCRIPTS"/test-new-config.sh fi + +# Restart webserver services +restart_webserver +} + +# Use like this: open_port 443 TCP +# or e.g. open_port 3478 UDP +open_port() { + install_if_not miniupnpc + print_text_in_color "$ICyan" "Trying to open port $1 automatically..." + if ! upnpc -a "$ADDRESS" "$1" "$1" "$2" &>/dev/null + then + msg_box "Failed to open port $1 $2 automatically. You have to do this manually." + FAIL=1 + fi +} + +cleanup_open_port() { + if [ -n "$FAIL" ] + then + apt-get purge miniupnpc -y + apt autoremove -y + fi } # Check if port is open # check_open_port 443 domain.example.com check_open_port() { -print_text_in_color "${ICyan}" "Checking if port ${1} is open with https://ports.yougetsignal.com..." +print_text_in_color "$ICyan" "Checking if port ${1} is open with https://www.networkappers.com/tools/open-port-checker..." install_if_not curl # WAN Adress -if check_command curl -s -H 'Cache-Control: no-cache' 'https://ports.yougetsignal.com/check-port.php' --data "remoteAddress=${WANIP4}&portNumber=${1}" | grep -q "is open on" +if check_command curl -s -H 'Cache-Control: no-cache' -H 'Referer: https://www.networkappers.com/tools/open-port-checker' "https://networkappers.com/api/port.php?ip=${WANIP4}&port=${1}" | grep -q "open" then - print_text_in_color "${IGreen}" "Port ${1} is open on ${WANIP4}!" + print_text_in_color "$IGreen" "Port ${1} is open on ${WANIP4}!" # Domain name -elif check_command curl -s -H 'Cache-Control: no-cache' 'https://ports.yougetsignal.com/check-port.php' --data "remoteAddress=${2}&portNumber=${1}" | grep -q "is open on" +elif check_command curl -s -H 'Cache-Control: no-cache' -H 'Referer: https://www.networkappers.com/tools/open-port-checker' "https://www.networkappers.com/api/port.php?ip=${2}&port=${1}" | grep -q "open" then - print_text_in_color "${IGreen}" "Port ${1} is open on ${2}!" + print_text_in_color "$IGreen" "Port ${1} is open on ${2}!" else - msg_box "Port $1 is not open on either ${WANIP4} or ${2}.\n\nPlease follow this guide to open ports in your router or firewall:\nhttps://www.techandme.se/open-port-80-443/" - any_key "Press any key to exit..." - exit 1 + msg_box "It seems like the port ${1} is closed. This could happend when your +ISP has blocked the port, or that the port isn't open. + +If you are 100% sure the port ${1} is open you can now choose to +continue. There are no guarantees that it will work anyway though, +since the service depend on that the port ${1} is open and +accessible from outside your network." + if ! yesno_box_no "Are you 100% sure the port ${1} is open?" + then + msg_box "Port $1 is not open on either ${WANIP4} or ${2}. + +Please follow this guide to open ports in your router or firewall:\nhttps://www.techandme.se/open-port-80-443/" + any_key "Press any key to exit..." + exit 1 + fi fi } -msg_box() { -local PROMPT="$1" - whiptail --msgbox "${PROMPT}" "$WT_HEIGHT" "$WT_WIDTH" +check_distro_version() { +# Check Ubuntu version +if lsb_release -sc | grep -ic "bionic" &> /dev/null || lsb_release -sc | grep -ic "focal" &> /dev/null +then + OS=1 +elif lsb_release -i | grep -ic "Ubuntu" &> /dev/null +then + OS=1 +elif uname -a | grep -ic "bionic" &> /dev/null || uname -a | grep -ic "focal" &> /dev/null +then + OS=1 +elif uname -v | grep -ic "Ubuntu" &> /dev/null +then + OS=1 +fi + +if [ "$OS" != 1 ] +then + msg_box "Ubuntu Server is required to run this script. +Please install that distro and try again. + +You can find the download link here: https://www.ubuntu.com/download/server" + exit 1 +fi + +if ! version 18.04 "$DISTRO" 20.04.4; then + msg_box "Your current Ubuntu version is $DISTRO but must be between 18.04 - 20.04.4 to run this script." + msg_box "Please contact us to get support for upgrading your server: +https://www.hanssonit.se/#contact +https://shop.hanssonit.se/" + exit 1 +fi } -# Check if program is installed (stop_if_installed apache2) +# Check if program is installed (stop_if_installed nginx) stop_if_installed() { if [ "$(dpkg-query -W -f='${Status}' "${1}" 2>/dev/null | grep -c "ok installed")" == "1" ] then @@ -228,7 +723,7 @@ then fi } -# Check if program is installed (is_this_installed apache2) +# Check if program is installed (is_this_installed nginx) is_this_installed() { if dpkg-query -W -f='${Status}' "${1}" | grep -q "ok installed" then @@ -239,29 +734,10 @@ fi } # Install_if_not program -install_if_not () { -if [[ "$(stop_if_installed "${1}")" != "${1} is installed, it must be a clean server." ]] +install_if_not() { +if ! dpkg-query -W -f='${Status}' "${1}" | grep -q "ok installed" then - apt update -q4 & spinner_loading && apt install "${1}" -y -fi -} - -test_connection() { -install_if_not dnsutils -install_if_not network-manager -check_command service network-manager restart -ip link set "$IFACE" down -wait -ip link set "$IFACE" up -wait -check_command service network-manager restart -print_text_in_color "$ICyan" "Checking connection..." -sleep 3 -if ! nslookup github.com -then -msg_box "Network NOT OK. You must have a working network connection to run this script -If you think that this is a bug, please report it to https://github.com/nextcloud/vm/issues." - exit 1 + apt update -q4 & spinner_loading && RUNLEVEL=1 apt install "${1}" -y fi } @@ -269,18 +745,21 @@ fi # Call it like this: ram_check [amount of min RAM in GB] [for which program] # Example: ram_check 2 Wordpress ram_check() { +install_if_not bc mem_available="$(awk '/MemTotal/{print $2}' /proc/meminfo)" -if [ "${mem_available}" -lt "$((${1}*1002400))" ] +mem_available_gb="$(LC_NUMERIC="en_US.UTF-8" printf '%0.2f\n' "$(echo "scale=3; $mem_available/(1024*1024)" | bc)")" +mem_required="$((${1}*(924*1024)))" # 100MiB/GiB margin and allow 90% to be able to run on physical machines +if [ "${mem_available}" -lt "${mem_required}" ] then - print_text_in_color "${Red}" "Error: ${1} GB RAM required to install ${2}!" >&2 - print_text_in_color "${Red}" "Current RAM is: ("$((mem_available/1002400))" GB)" >&2 + print_text_in_color "$IRed" "Error: ${1} GB RAM required to install ${2}!" >&2 + print_text_in_color "$IRed" "Current RAM is: ($mem_available_gb GB)" >&2 sleep 3 - msg_box "If you want to bypass this check you could do so by commenting out (# before the line) 'ram_check X' in the script that you are trying to run. - In nextcloud_install_production.sh you can find the check somewhere around line #34. - Please notice that things may be veery slow and not work as expeced. YOU HAVE BEEN WARNED!" + msg_box "** Error: insufficient memory. ${mem_available_gb}GB RAM installed, ${1}GB required. + +Please shutdown the server, raise your RAM and then try again" exit 1 else - print_text_in_color "${IGreen}" "RAM for ${2} OK! ($((mem_available/1002400)) GB)" + print_text_in_color "$IGreen" "RAM for ${2} OK! ($mem_available_gb GB)" fi } @@ -291,38 +770,65 @@ cpu_check() { nr_cpu="$(nproc)" if [ "${nr_cpu}" -lt "${1}" ] then - print_text_in_color "${Red}" "Error: ${1} CPU required to install ${2}!" >&2 - print_text_in_color "${Red}" "Current CPU: ($((nr_cpu)))" >&2 + print_text_in_color "$IRed" "Error: ${1} CPU required to install ${2}!" >&2 + print_text_in_color "$IRed" "Current CPU: ($((nr_cpu)))" >&2 sleep 3 exit 1 else - print_text_in_color "${IGreen}" "CPU for ${2} OK! ($((nr_cpu)))" + print_text_in_color "$IGreen" "CPU for ${2} OK! ($((nr_cpu)))" fi } check_command() { - if ! "$@"; - then - print_text_in_color "${Red}" "Sorry but something went wrong. Please report this issue to $ISSUES and include the output of the error message. Thank you!" - print_text_in_color "$IRed" "$* failed" +if ! "$@"; +then + print_text_in_color "$ICyan" "Sorry but something went wrong. Please report \ +this issue to $ISSUES and include the output of the error message. Thank you!" + print_text_in_color "$IRed" "$* failed" exit 1 - fi +fi } network_ok() { +version(){ + local h t v + + [[ $2 = "$1" || $2 = "$3" ]] && return 0 + + v=$(printf '%s\n' "$@" | sort -V) + h=$(head -n1 <<<"$v") + t=$(tail -n1 <<<"$v") + + [[ $2 != "$h" && $2 != "$t" ]] +} +if version 18.04 "$DISTRO" 20.04.6 +then print_text_in_color "$ICyan" "Testing if network is OK..." - install_if_not network-manager - if ! service network-manager restart > /dev/null + if ! netplan apply then - service networking restart > /dev/null + systemctl restart systemd-networkd > /dev/null fi - sleep 2 - if wget -q -T 20 -t 2 http://github.com -O /dev/null & spinner_loading + # Check the connention + countdown 'Waiting for network to restart...' 3 + if ! site_200 github.com then - return 0 - else - return 1 + # sleep 10 seconds so that some slow networks have time to restart + countdown 'Not online yet, waiting a bit more...' 10 + if ! site_200 github.com + then + # sleep 30 seconds so that some REALLY slow networks have time to restart + countdown 'Not online yet, waiting a bit more (last try)...' 30 + site_200 github.com + fi fi +else + msg_box "Your current Ubuntu version is $DISTRO but must be between 18.04 - 20.04.6 to run this script." + msg_box "Please contact us to get support for upgrading your server: +https://www.hanssonit.se/#contact +https://shop.hanssonit.se/" + msg_box "We will now pause for 60 seconds. Please press CTRL+C when prompted to do so." + countdown "Please press CTRL+C to abort..." 60 +fi } # Whiptail auto-size @@ -340,30 +846,55 @@ calc_wt_size() { export WT_MENU_HEIGHT } -# Initial download of script in ../static -# call like: download_static_script name_of_script -download_static_script() { - # Get ${1} script - rm -f "${SCRIPTS}/${1}.sh" "${SCRIPTS}/${1}.php" "${SCRIPTS}/${1}.py" - if ! { wget -q "${STATIC}/${1}.sh" -P "$SCRIPTS" || wget -q "${STATIC}/${1}.php" -P "$SCRIPTS" || wget -q "${STATIC}/${1}.py" -P "$SCRIPTS"; } +# call like: download_script folder_variable name_of_script +# e.g. download_script MENU additional_apps +# Use it for functions like download_static_script +download_script() { + rm -f "${SCRIPTS}/${2}.sh" "${SCRIPTS}/${2}.php" "${SCRIPTS}/${2}.py" + if ! { curl_to_dir "${!1}" "${2}.sh" "$SCRIPTS" || curl_to_dir "${!1}" "${2}.php" "$SCRIPTS" || curl_to_dir "${!1}" "${2}.py" "$SCRIPTS"; } then - print_text_in_color "$IRed" "{$1} failed to download. Please run: 'sudo wget ${STATIC}/${1}.sh|.php|.py' again." - print_text_in_color "$IRed" "If you get this error when running the wordpress-startup-script then just re-run it with:" - print_text_in_color "$IRed" "'sudo bash $SCRIPTS/wordpress-startup-script.sh' and all the scripts will be downloaded again" + print_text_in_color "$IRed" "{$2} failed to download." + sleep 2 + if ! yesno_box_yes "Are you running the first setup of this server?" + then + msg_box "Please run sudo bash '$SCRIPTS/update.sh' \ +from your CLI to get the latest scripts from Github, needed for a successful run." + else + msg_box "If you get this error when running the first setup script, \ +then just re-run it with: 'sudo bash $SCRIPTS/wordpress-startup-script.sh' \ +from your CLI, and all the scripts will be downloaded again. + +If it still fails, please report this issue to: $ISSUES." + fi exit 1 fi } -# Initial download of script in ../lets-encrypt -# call like: download_le_script name_of_script -download_le_script() { - # Get ${1} script - rm -f "${SCRIPTS}/${1}.sh" "${SCRIPTS}/${1}.php" "${SCRIPTS}/${1}.py" - if ! { wget -q "${LETS_ENC}/${1}.sh" -P "$SCRIPTS" || wget -q "${LETS_ENC}/${1}.php" -P "$SCRIPTS" || wget -q "${LETS_ENC}/${1}.py" -P "$SCRIPTS"; } +# call like: run_script folder_variable name_of_script +# e.g. run_script MENU additional_apps +# Use it for functions like run_script STATIC +run_script() { + rm -f "${SCRIPTS}/${2}.sh" "${SCRIPTS}/${2}.php" "${SCRIPTS}/${2}.py" + if download_script "${1}" "${2}" then - print_text_in_color "$IRed" "{$1} failed to download. Please run: 'sudo wget ${STATIC}/${1}.sh|.php|.py' again." - print_text_in_color "$IRed" "If you get this error when running the wordpress-startup-script then just re-run it with:" - print_text_in_color "$IRed" "'sudo bash $SCRIPTS/wordpress-startup-script.sh' and all the scripts will be downloaded again" + if [ -f "${SCRIPTS}/${2}".sh ] + then + bash "${SCRIPTS}/${2}.sh" + rm -f "${SCRIPTS}/${2}.sh" + elif [ -f "${SCRIPTS}/${2}".php ] + then + php "${SCRIPTS}/${2}.php" + rm -f "${SCRIPTS}/${2}.php" + elif [ -f "${SCRIPTS}/${2}".py ] + then + install_if_not python3 + python3 "${SCRIPTS}/${2}.py" + rm -f "${SCRIPTS}/${2}.py" + fi + else + print_text_in_color "$IRed" "Running ${2} failed" + print_text_in_color "$ICyan" "Script failed to execute. Please run: \ +'sudo curl -sLO ${!1}/${2}.sh|php|py' and try again." exit 1 fi } @@ -371,71 +902,7 @@ download_le_script() { # Run any script in ../master # call like: run_main_script name_of_script run_main_script() { - rm -f "${SCRIPTS}/${1}.sh" "${SCRIPTS}/${1}.php" "${SCRIPTS}/${1}.py" - if wget -q "${GITHUB_REPO}/${1}.sh" -P "$SCRIPTS" - then - bash "${SCRIPTS}/${1}.sh" - rm -f "${SCRIPTS}/${1}.sh" - elif wget -q "${GITHUB_REPO}/${1}.php" -P "$SCRIPTS" - then - php "${SCRIPTS}/${1}.php" - rm -f "${SCRIPTS}/${1}.php" - elif wget -q "${GITHUB_REPO}/${1}.py" -P "$SCRIPTS" - then - python "${SCRIPTS}/${1}.py" - rm -f "${SCRIPTS}/${1}.py" - else - print_text_in_color "$IRed" "Downloading ${1} failed" - print_text_in_color "$IRed" "Script failed to download. Please run: 'sudo wget ${GITHUB_REPO}/${1}.sh|php|py' again." - sleep 3 - fi -} - -# Run any script in ../static -# call like: run_static_script name_of_script -run_static_script() { - # Get ${1} script - rm -f "${SCRIPTS}/${1}.sh" "${SCRIPTS}/${1}.php" "${SCRIPTS}/${1}.py" - if wget -q "${STATIC}/${1}.sh" -P "$SCRIPTS" - then - bash "${SCRIPTS}/${1}.sh" - rm -f "${SCRIPTS}/${1}.sh" - elif wget -q "${STATIC}/${1}.php" -P "$SCRIPTS" - then - php "${SCRIPTS}/${1}.php" - rm -f "${SCRIPTS}/${1}.php" - elif wget -q "${STATIC}/${1}.py" -P "$SCRIPTS" - then - python "${SCRIPTS}/${1}.py" - rm -f "${SCRIPTS}/${1}.py" - else - print_text_in_color "$IRed" "Downloading ${1} failed" - print_text_in_color "$IRed" "Script failed to download. Please run: 'sudo wget ${STATIC}/${1}.sh|php|py' again." - sleep 3 - fi -} - -# Run any script in ../apps -# call like: run_app_script collabora|nextant|passman|spreedme|contacts|calendar|webmin|previewgenerator -run_app_script() { - rm -f "${SCRIPTS}/${1}.sh" "${SCRIPTS}/${1}.php" "${SCRIPTS}/${1}.py" - if wget -q "${APP}/${1}.sh" -P "$SCRIPTS" - then - bash "${SCRIPTS}/${1}.sh" - rm -f "${SCRIPTS}/${1}.sh" - elif wget -q "${APP}/${1}.php" -P "$SCRIPTS" - then - php "${SCRIPTS}/${1}.php" - rm -f "${SCRIPTS}/${1}.php" - elif wget -q "${APP}/${1}.py" -P "$SCRIPTS" - then - python "${SCRIPTS}/${1}.py" - rm -f "${SCRIPTS}/${1}.py" - else - print_text_in_color "$IRed" "Downloading ${1} failed" - print_text_in_color "$IRed" "Script failed to download. Please run: 'sudo wget ${APP}/${1}.sh|php|py' again." - sleep 3 - fi +run_script GITHUB_REPO "${1}" } version(){ @@ -473,12 +940,106 @@ spinner_loading() { any_key() { local PROMPT="$1" - read -r -p "$(printf "${Green}${PROMPT}${Color_Off}")" -n1 -s - echo + read -r -sn 1 -p "$(printf "%b" "${IGreen}${PROMPT}${Color_Off}")";echo +} + +# Check universe reposiroty +check_universe() { +UNIV=$(apt-cache policy | grep http | awk '{print $3}' | grep universe | head -n 1 | cut -d "/" -f 2) +if [ "$UNIV" != "universe" ] +then + print_text_in_color "$ICyan" "Adding required repo (universe)." + add-apt-repository universe +fi +} + +# Check universe reposiroty +check_multiverse() { +MULTIV=$(apt-cache policy | grep http | awk '{print $3}' | grep multiverse | head -n 1 | cut -d "/" -f 2) +if [ "$MULTIV" != "multiverse" ] +then + print_text_in_color "$ICyan" "Adding required repo (multiverse)." + add-apt-repository multiverse +fi +} + +# countdown 'message looks like this' 10 +countdown() { +print_text_in_color "$ICyan" "$1" +secs="$(($2))" +while [ $secs -gt 0 ]; do + echo -ne "$secs\033[0K\r" + sleep 1 + : $((secs--)) +done } print_text_in_color() { - printf "%b%s%b\n" "$1" "$2" "$Color_Off" +printf "%b%s%b\n" "$1" "$2" "$Color_Off" +} + + +# Check if the value is a number +# EXAMPLE: https://github.com/nextcloud/vm/pull/1012 +check_if_number() { +case "${1}" in + ''|*[!0-9]*) return 1 ;; + *) return 0 ;; +esac +} + +# Use this to send system mails +# e.g.: send_mail "subject" "text" +send_mail() { + local RECIPIENT + if [ -f /etc/msmtprc ] + then + RECIPIENT=$(grep "recipient=" /etc/msmtprc) + RECIPIENT="${RECIPIENT##*recipient=}" + if [ -n "$RECIPIENT" ] + then + print_text_in_color "$ICyan" "Sending '$1' to $RECIPIENT" + echo -e "$2" | mail --subject "NcVM - $1" "$RECIPIENT" + fi + fi +} + +check_php() { +print_text_in_color "$ICyan" "Getting current PHP-version..." +GETPHP="$(php -v | grep -m 1 PHP | awk '{print $2}' | cut -d '-' -f1)" + +if [ -z "$GETPHP" ] +then + print_text_in_color "$IRed" "Can't find proper PHP version, aborting..." + exit 1 +fi + +if grep 7.0 <<< "$GETPHP" >/dev/null 2>&1 +then + export PHPVER=7.0 +elif grep 7.1 <<< "$GETPHP" >/dev/null 2>&1 +then + export PHPVER=7.1 +elif grep 7.2 <<< "$GETPHP" >/dev/null 2>&1 +then + export PHPVER=7.2 +elif grep 7.3 <<< "$GETPHP" >/dev/null 2>&1 +then + export PHPVER=7.3 +elif grep 7.4 <<< "$GETPHP" >/dev/null 2>&1 +then + export PHPVER=7.4 +elif grep 8.0 <<< "$GETPHP" >/dev/null 2>&1 +then +# export PHPVER=8.0 + msg_box "Sorry, but PHP 8 is not supported yet." + exit 1 +fi + +export PHP_INI=/etc/php/"$PHPVER"/fpm/php.ini +export PHP_POOL_DIR=/etc/php/"$PHPVER"/fpm/pool.d + +print_text_in_color "$IGreen" PHPVER="$PHPVER" } ## bash colors diff --git a/menu/additional_apps.sh b/menu/additional_apps.sh new file mode 100644 index 0000000..6d3ad2a --- /dev/null +++ b/menu/additional_apps.sh @@ -0,0 +1,76 @@ +#!/bin/bash + +# T&M Hansson IT AB © - 2020, https://www.hanssonit.se/ + +# shellcheck disable=2034,2059 +true +SCRIPT_NAME="Additional Apps Menu" +# shellcheck source=lib.sh +source /var/scripts/fetch_lib.sh || source <(curl -sL https://raw.githubusercontent.com/techandme/wordpress-vm/master/lib.sh) + +# Check for errors + debug code and abort if something isn't right +# 1 = ON +# 0 = OFF +DEBUG=0 +debug_mode + +# Must be root +root_check + +# Set the startup switch +if [ -f "$SCRIPTS/wordpress-startup-script.sh" ] +then + STARTUP_SWITCH="ON" +else + STARTUP_SWITCH="OFF" +fi + +# Show a msg_box during the startup script +if [ -f "$SCRIPTS/wordpress-startup-script.sh" ] +then + msg_box "In the next step, you will be offered to easily install apps that are made to enhance your server and experiance. +We have pre-selected apps that we recommend for any installation. + +PLEASE NOTE: For stability reasons you should *not* select apps just for the sake of it. +It's better to run: sudo bash $SCRIPTS/menu.sh when the first setup is complete, and after you've made a snapshot/backup of the server." +fi + +# Install Apps +choice=$(whiptail --title "$TITLE" --checklist \ +"Which apps do you want to install?\n\nAutomatically configure and install selected apps +$CHECKLIST_GUIDE\n\n$RUN_LATER_GUIDE" "$WT_HEIGHT" "$WT_WIDTH" 4 \ +"Fail2ban " "(Extra Bruteforce protection)" "$STARTUP_SWITCH" \ +"Adminer" "(Database Administraton GUI)" OFF \ +"Netdata" "(Real-time server monitoring in Web GUI)" OFF \ +"BPYTOP" "(Real-time server monitoring in CLI)" OFF \ +"Midnight Commander" "(CLI file manager)" OFF \ +"Webmin" "(Server GUI like Cpanel)" "$STARTUP_SWITCH" 3>&1 1>&2 2>&3) +case "$choice" in + *"Fail2ban "*) + print_text_in_color "$ICyan" "Downloading the Fail2ban Menu..." + run_script MENU fail2ban_menu + ;;& + *"Adminer"*) + print_text_in_color "$ICyan" "Downloading the Adminer script..." + run_script APP adminer + ;;& + *"Netdata"*) + print_text_in_color "$ICyan" "Downloading the Netdata script..." + run_script APP netdata + ;;& + *"BPYTOP"*) + print_text_in_color "$ICyan" "Downloading the BPYTOP script..." + run_script APP bpytop + ;;& + *"Midnight Commander"*) + print_text_in_color "$ICyan" "Downloading the Midnight Commander script..." + run_script APP midnight-commander + ;;& + *"Webmin"*) + print_text_in_color "$ICyan" "Downloading the Webmin script..." + run_script APP webmin + ;;& + *) + ;; +esac +exit diff --git a/menu/fail2ban_menu.sh b/menu/fail2ban_menu.sh new file mode 100644 index 0000000..e00022a --- /dev/null +++ b/menu/fail2ban_menu.sh @@ -0,0 +1,52 @@ +#!/bin/bash + +# T&M Hansson IT AB © - 2020, https://www.hanssonit.se/ + +# shellcheck disable=2034,2059 +true +SCRIPT_NAME="Fail2ban Menu" +# shellcheck source=lib.sh +source /var/scripts/fetch_lib.sh || source <(curl -sL https://raw.githubusercontent.com/techandme/wordpress-vm/master/lib.sh) + +# Check for errors + debug code and abort if something isn't right +# 1 = ON +# 0 = OFF +DEBUG=0 +debug_mode + +# Must be root +root_check + +# Set the startup switch +if [ -f "$SCRIPTS/wordpress-startup-script.sh" ] +then + STARTUP_SWITCH="ON" +else + STARTUP_SWITCH="OFF" +fi + +choice=$(whiptail --title "$TITLE" --checklist \ +"Automatically install and configure Fail2ban. +$CHECKLIST_GUIDE\n\n$RUN_LATER_GUIDE" "$WT_HEIGHT" "$WT_WIDTH" 4 \ +"Install-Fail2ban" "(Install Fail2ban and protect Wordpress + SSH)" "$STARTUP_SWITCH" \ +"Fail2ban-Statuscheck" "(Check status of currently blocked attacks)" OFF 3>&1 1>&2 2>&3) + +case "$choice" in + *"Install-Fail2ban"*) + print_text_in_color "$ICyan" "Downloading the Fail2ban install script..." + run_script APP fail2ban + ;;& + *"Fail2ban-Statuscheck"*) + SUBTITLE="Fail2ban Statuscheck" + if is_this_installed fail2ban && [ -f "/etc/fail2ban/filter.d/nextcloud.conf" ] + then + msg_box "$(fail2ban-client status wordpress && fail2ban-client status sshd && iptables -L -n)" "$SUBTITLE" + else + msg_box "Fail2ban isn't installed. Please run 'sudo bash /var/scripts/menu.sh' to install it." "$SUBTITLE" + fi + ;;& + *) + ;; +esac +exit + diff --git a/menu/main_menu.sh b/menu/main_menu.sh new file mode 100644 index 0000000..391e0f5 --- /dev/null +++ b/menu/main_menu.sh @@ -0,0 +1,58 @@ +#!/bin/bash + +# T&M Hansson IT AB © - 2020, https://www.hanssonit.se/ + +# shellcheck disable=2034,2059,1091 +true +SCRIPT_NAME="Main Menu" +# shellcheck source=lib.sh +source /var/scripts/fetch_lib.sh || source <(curl -sL https://raw.githubusercontent.com/techandme/wordpress-vm/master/lib.sh) + +# Check for errors + debug code and abort if something isn't right +# 1 = ON +# 0 = OFF +DEBUG=0 +debug_mode + +# Must be root +root_check + +################################################################## + +# Main menu +choice=$(whiptail --title "$TITLE" --menu \ +"Choose what you want to do. +$MENU_GUIDE\n\n$RUN_LATER_GUIDE" "$WT_HEIGHT" "$WT_WIDTH" 4 \ +"Additional Apps" "(Choose which apps to install)" \ +"Startup Configuration" "(Choose between available startup configurations)" \ +"Server Configuration" "(Choose between available server configurations)" \ +"Update Wordpress" "(Update Wordpress to the latest release)" 3>&1 1>&2 2>&3) + +case "$choice" in + "Additional Apps") + print_text_in_color "$ICyan" "Downloading the Additional Apps Menu..." + run_script MENU additional_apps + ;; + "Startup Configuration") + print_text_in_color "$ICyan" "Downloading the Startup Configuration Menu..." + run_script MENU startup_configuration + ;; + "Server Configuration") + print_text_in_color "$ICyan" "Downloading the Server Configuration Menu..." + run_script MENU server_configuration + ;; + "Update Wordpress") + if [ -f "$SCRIPTS"/update.sh ] + then + bash "$SCRIPTS"/update.sh + else + print_text_in_color "$ICyan" "Downloading the Update script..." + download_script STATIC update + chmod +x "$SCRIPTS"/update.sh + bash "$SCRIPTS"/update.sh + fi + ;; + *) + ;; +esac +exit diff --git a/menu/menu.sh b/menu/menu.sh new file mode 100644 index 0000000..e866d09 --- /dev/null +++ b/menu/menu.sh @@ -0,0 +1,31 @@ +#!/bin/bash + +# T&M Hansson IT AB © - 2020, https://www.hanssonit.se/ + +# shellcheck disable=2034,2059,1091 +true +SCRIPT_NAME="Main Menu" +# shellcheck source=lib.sh +source /var/scripts/fetch_lib.sh || source <(curl -sL https://raw.githubusercontent.com/techandme/wordpress-vm/master/lib.sh) + +# Check for errors + debug code and abort if something isn't right +# 1 = ON +# 0 = OFF +DEBUG=0 +debug_mode + +# Must be root +root_check + +################################################################## + +mkdir -p "$SCRIPTS" +print_text_in_color "$ICyan" "Running the main menu script..." + +if network_ok +then + # Delete, download, run + run_script MENU main_menu +fi + +exit diff --git a/menu/server_configuration.sh b/menu/server_configuration.sh new file mode 100644 index 0000000..95baa36 --- /dev/null +++ b/menu/server_configuration.sh @@ -0,0 +1,101 @@ +#!/bin/bash + +# T&M Hansson IT AB © - 2020, https://www.hanssonit.se/ + +# shellcheck disable=2034,2059 +true +SCRIPT_NAME="Server Configuration Menu" +# shellcheck source=lib.sh +source /var/scripts/fetch_lib.sh || source <(curl -sL https://raw.githubusercontent.com/techandme/wordpress-vm/master/lib.sh) + +# Check for errors + debug code and abort if something isn't right +# 1 = ON +# 0 = OFF +DEBUG=0 +debug_mode + +# Must be root +root_check + +# Set the correct switch for activate_tls +if [ -f "$SCRIPTS"/activate-tls.sh ] +then + ACTIVATE_TLS_SWITCH="ON" +else + ACTIVATE_TLS_SWITCH="OFF" +fi + +# Set the startup switch +if [ -f "$SCRIPTS/wordpress-startup-script.sh" ] +then + STARTUP_SWITCH="ON" +else + STARTUP_SWITCH="OFF" +fi + +# Show a msg_box during the startup script +if [ -f "$SCRIPTS/wordpress-startup-script.sh" ] +then + msg_box "In the next step, you will be offered to easily install different configurations that are made to enhance your server and experiance. +We have pre-selected some choices that we recommend for any installation. + +PLEASE NOTE: For stability reasons you should *not* select everything just for the sake of it. +It's better to run: sudo bash $SCRIPTS/menu.sh when the first setup is complete, and after you've made a snapshot/backup of the server." +fi + +# Server configurations +choice=$(whiptail --title "$TITLE" --checklist \ +"Choose what you want to configure +$CHECKLIST_GUIDE\n\n$RUN_LATER_GUIDE" "$WT_HEIGHT" "$WT_WIDTH" 4 \ +"Static IP" "(Set static IP in Ubuntu with netplan.io)" OFF \ +"DDclient Configuration" "(Use ddclient for automatic DDNS updates)" OFF \ +"Activate TLS" "(Enable HTTPS with Let's Encrypt)" "$ACTIVATE_TLS_SWITCH" \ +"Automatic updates" "(Automatically update your server every week on Sundays)" OFF \ +"SMTP Mail" "(Enable beeing notified by mail from your server)" OFF 3>&1 1>&2 2>&3) + +case "$choice" in + *"Static IP"*) + print_text_in_color "$ICyan" "Downloading the Static IP script..." + run_script NETWORK static_ip + ;;& + *"DDclient Configuration"*) + print_text_in_color "$ICyan" "Downloading the DDclient Configuration script..." + run_script NETWORK ddclient-configuration + ;;& + *"Activate TLS"*) + SUBTITLE="Activate TLS" + msg_box "The following script will install a trusted +TLS certificate through Let's Encrypt. +It's recommended to use TLS (https) together with Wordpress. +Please open port 80 and 443 to this servers IP before you continue. +More information can be found here: +https://www.techandme.se/open-port-80-443/" "$SUBTITLE" + + if yesno_box_yes "Do you want to install TLS?" "$SUBTITLE" + then + if [ -f $SCRIPTS/activate-tls.sh ] + then + bash $SCRIPTS/activate-tls.sh + else + print_text_in_color "$ICyan" "Downloading the Let's Encrypt script..." + download_script LETS_ENC activate-tls + bash $SCRIPTS/activate-tls.sh + fi + else + msg_box "OK, but if you want to run it later, just type: sudo bash $SCRIPTS/activate-tls.sh" "$SUBTITLE" + fi + # Just make sure it is gone + rm -f "$SCRIPTS/test-new-config.sh" + ;;& + *"Automatic updates"*) + print_text_in_color "$ICyan" "Downloading the Automatic Updates script..." + run_script ADDONS automatic_updates + ;;& + *"SMTP Mail"*) + print_text_in_color "$ICyan" "Downloading the SMTP Mail script..." + run_script ADDONS smtp-mail + ;;& + *) + ;; +esac +exit diff --git a/menu/startup_configuration.sh b/menu/startup_configuration.sh new file mode 100644 index 0000000..a1ab900 --- /dev/null +++ b/menu/startup_configuration.sh @@ -0,0 +1,125 @@ +#!/bin/bash + +# T&M Hansson IT AB © - 2020, https://www.hanssonit.se/ + +# shellcheck disable=2034,2059 +true +SCRIPT_NAME="Startup Configuration Menu" +# shellcheck source=lib.sh +source /var/scripts/fetch_lib.sh || source <(curl -sL https://raw.githubusercontent.com/techandme/wordpress-vm/master/lib.sh) + +# Check for errors + debug code and abort if something isn't right +# 1 = ON +# 0 = OFF +DEBUG=0 +debug_mode + +# Must be root +root_check + +# Get the correct keyboard layout switch +if [ "$KEYBOARD_LAYOUT" = "us" ] +then + KEYBOARD_LAYOUT_SWITCH="ON" +else + KEYBOARD_LAYOUT_SWITCH="OFF" +fi + +# Get the correct timezone switch +if [ "$(cat /etc/timezone)" = "Etc/UTC" ] +then + TIMEZONE_SWITCH="ON" +else + TIMEZONE_SWITCH="OFF" +fi + +# Get the correct apt-mirror +if [ "$REPO" = 'http://archive.ubuntu.com/ubuntu' ] +then + MIRROR_SWITCH="ON" +else + MIRROR_SWITCH="OFF" +fi + +# Show a msg_box during the startup script +if [ -f "$SCRIPTS/wordpress-startup-script.sh" ] +then + msg_box "Running a server, it's important that certain things are correct. +In the following menu you will be asked to setup the most basic stuff of your server. + +The script is smart, and have already pre-selected the values that you'd want to change based on the current settings." +fi + +# Startup configurations +choice=$(whiptail --title "$TITLE" --checklist \ +"Choose what you want to change. +$CHECKLIST_GUIDE\n\n$RUN_LATER_GUIDE" "$WT_HEIGHT" "$WT_WIDTH" 4 \ +"Keyboard Layout" "(Change the keyboard layout from '$KEYBOARD_LAYOUT')" "$KEYBOARD_LAYOUT_SWITCH" \ +"Timezone" "(Change the timezone from $(cat /etc/timezone))" "$TIMEZONE_SWITCH" \ +"Locate Mirror" "(Change the apt-mirror from $REPO)" OFF 3>&1 1>&2 2>&3) + +case "$choice" in + *"Keyboard Layout"*) + SUBTITLE="Keyboard Layout" + msg_box "Current keyboard layout is $KEYBOARD_LAYOUT." "$SUBTITLE" + if ! yesno_box_yes "Do you want to change keyboard layout?" "$SUBTITLE" + then + print_text_in_color "$ICyan" "Not changing keyboard layout..." + sleep 1 + else + # Change layout + dpkg-reconfigure keyboard-configuration + setupcon --force + # Set locales + run_script ADDONS locales + input_box "Please try out all buttons (e.g: @ # \$ : y n) \ +to find out if the keyboard settings were correctly applied. +If the keyboard is still wrong, you will be offered to reboot the server in the next step. + +Please continue by hitting [ENTER]" "$SUBTITLE" >/dev/null + if ! yesno_box_yes "Did the keyboard work as expected?\n\nIf you choose 'No' \ +the server will be rebooted. After the reboot, please login as usual and run this script again." "$SUBTITLE" + then + reboot + fi + fi + ;;& + *"Timezone"*) + SUBTITLE="Timezone" + msg_box "Current timezone is $(cat /etc/timezone)" "$SUBTITLE" + if ! yesno_box_yes "Do you want to change the timezone?" "$SUBTITLE" + then + print_text_in_color "$ICyan" "Not changing timezone..." + sleep 1 + else + if dpkg-reconfigure tzdata + then + # Change timezone in php and logging if the startup script not exists + if ! [ -f "$SCRIPTS/nextcloud-startup-script.sh" ] + then + # Change timezone in PHP + sed -i "s|;date.timezone.*|date.timezone = $(cat /etc/timezone)|g" "$PHP_INI" + + # Change timezone for logging + nextcloud_occ config:system:set logtimezone --value="$(cat /etc/timezone)" + msg_box "The timezone was changed successfully." "$SUBTITLE" + fi + fi + fi + ;;& + *"Locate Mirror"*) + SUBTITLE="apt-mirror" + msg_box "Current apt-mirror is $REPO" "$SUBTITLE" + if ! yesno_box_yes "Do you want to change the apt-mirror?" "$SUBTITLE" + then + print_text_in_color "$ICyan" "Not changing the apt-mirror..." + sleep 1 + else + print_text_in_color "$ICyan" "Downloading the Locate Mirror script..." + run_script ADDONS locate_mirror + fi + ;;& + *) + ;; +esac +exit diff --git a/network/ddclient-configuration.sh b/network/ddclient-configuration.sh new file mode 100644 index 0000000..9f182f8 --- /dev/null +++ b/network/ddclient-configuration.sh @@ -0,0 +1,172 @@ +#!/bin/bash + +# T&M Hansson IT AB © - 2020, https://www.hanssonit.se/ +# Copyright © 2020 Simon Lindner (https://github.com/szaimen) + +# shellcheck disable=2034,2059 +true +SCRIPT_NAME="DynDNS with ddclient" +SCRIPT_EXPLAINER="This script lets you setup DynDNS by using the Linux ddclient software." +# shellcheck source=lib.sh +source /var/scripts/fetch_lib.sh || source <(curl -sL https://raw.githubusercontent.com/techandme/wordpress-vm/master/lib.sh) + +# Check for errors + debug code and abort if something isn't right +# 1 = ON +# 0 = OFF +DEBUG=0 +debug_mode + +# Check if root +root_check + +# Check if ddclient is already installed +if ! is_this_installed ddclient +then + # Ask for installing + install_popup "$SCRIPT_NAME" +else + # Ask for removal or reinstallation + reinstall_remove_menu "$SCRIPT_NAME" + # Removal + apt purge ddclient -y + if is_this_installed libjson-any-perl + then + apt purge libjson-any-perl -y + fi + apt autoremove -y + rm -f /etc/ddclient.conf + # Show successful uninstall if applicable + removal_popup "$SCRIPT_NAME" +fi + +# install needed tool +DEBIAN_FRONTEND=noninteractive install_if_not ddclient + +# Test if file exists +if [ ! -f /etc/ddclient.conf ] +then + msg_box "The default ddclient.conf doesn't seem to exist.\nPlease report this to\n$ISSUES." + exit 1 +fi + +choice=$(whiptail --title "$TITLE" --menu \ +"Please choose your DynDNS-Provider.\nYou have to setup an account before you can start.\n +If your DDNS provider isn't already supported, please open a new issue here:\n$ISSUES +$MENU_GUIDE\n\n$RUN_LATER_GUIDE" "$WT_HEIGHT" "$WT_WIDTH" 4 \ +"Cloudflare" "(cloudflare.com)" \ +"deSEC" "(desec.io)" \ +"Duck DNS" "(duckdns.org)" \ +"Strato" "(strato.de)" 3>&1 1>&2 2>&3) + +case "$choice" in + "Cloudflare") + PROVIDER="Cloudflare" + INSTRUCTIONS="register an email address for your domain and get an Cloudflare API-key" + GUIDE="https://www.techandme.se/setup-multiple-accounts-with-ddclient-and-cloudflare/" + PROTOCOL="cloudflare" + SERVER="www.cloudflare.com" + USE_SSL="yes" + ;; + "deSEC") + PROVIDER="deSEC" + INSTRUCTIONS="get a DDNS account with password" + GUIDE="https://desec.io/#" + PROTOCOL="dyndns2" + SERVER="update.dedyn.io" + USE_SSL="yes" + ;; + "Duck DNS") + PROVIDER="Duck DNS" + INSTRUCTIONS="get a DDNS account with password" + GUIDE="https://www.duckdns.org/faqs.jsp" + PROTOCOL="duckdns" + SERVER="www.duckdns.org" + USE_SSL="yes" + ;; + "Strato") + PROVIDER="Strato" + INSTRUCTIONS="activate DynDNS for your Domain" + GUIDE="https://www.strato.de/faq/domains/so-einfach-richten-sie-dyndns-fuer-ihre-domains-ein/" + PROTOCOL="dyndns2" + SERVER="dyndns.strato.com" + USE_SSL="yes" + ;; + "") + msg_box "You haven't selected any option. Exiting!" + exit 1 + ;; + *) + ;; +esac + +# Instructions +msg_box "Before you can continue, you have to access $PROVIDER and $INSTRUCTIONS.\n\nHere is a guide:\n$GUIDE" + +# Ask if everything is prepared +if ! yesno_box_yes "Are you ready to continue?" +then + exit +fi + +# Enter your Hostname +HOSTNAME=$(input_box_flow "Please enter the Host that you want to configure DDNS for.\nE.g. 'example.com'") + +# Enter your login +LOGIN=$(input_box_flow "Please enter the login for your DDNS provider.\nIt will be most likely the domain \ +or registered email address depending on your DDNS Provider.\nE.g. 'example.com' or 'mail@example.com' +If you are not sure, please refer to the documentation of your DDNS provider.") + +# Enter your password +PASSWORD=$(input_box_flow "Please enter the password or api-key that you've got for DynDNS from your DDNS provider. +If you are not sure, please refer to the documentation of your DDNS provider.") + +# Present what we gathered +msg_box "You will see now a list of all entered information. Please check that everything seems correct.\n +Provider=$PROVIDER +Host=$HOSTNAME +Login=$LOGIN +Password=$PASSWORD" + +# If everything okay, write to file +if ! yesno_box_yes "Do you want to proceed?" +then + exit +fi + +# needed for cloudflare to work +if [ "$PROVIDER" = "Cloudflare" ] +then + install_if_not libjson-any-perl +fi + +# Write information to ddclient.conf +cat << DDCLIENT_CONF > "/etc/ddclient.conf" +# Configuration file for ddclient generated by debconf +# +# /etc/ddclient.conf + +# Default system settings +use=if, if=$IFACE +use=web, web=https://ipv4bot.whatismyipaddress.com + +# DDNS-service specific setting +# Provider=$PROVIDER +protocol=$PROTOCOL +server=$SERVER +ssl=$USE_SSL + +# user specific setting +login=$LOGIN +password=$PASSWORD + +# Hostname follows: +zone=$HOSTNAME +$HOSTNAME +DDCLIENT_CONF + +# Test connection +msg_box "Everything is setup by now and we will check the connection." +OUTPUT="$(ddclient -verbose)" +msg_box "Please check the logs below and make sure that everything looks good. If not, just run this script again. +If you are certain that you entered all things correctly and it didn't work, please report this to\n$ISSUES\n\n$OUTPUT" +exit diff --git a/network/static_ip.sh b/network/static_ip.sh new file mode 100644 index 0000000..e2593af --- /dev/null +++ b/network/static_ip.sh @@ -0,0 +1,241 @@ +#!/bin/bash + +# T&M Hansson IT AB © - 2020, https://www.hanssonit.se/ + +# Use local lib file in case there is no internet connection +if printf "Testing internet connection..." && ping github.com -c 2 >/dev/null 2>&1 +then +# shellcheck disable=2034,2059 +true +SCRIPT_NAME="Static IP" +# shellcheck source=lib.sh +source /var/scripts/fetch_lib.sh || source <(curl -sL https://raw.githubusercontent.com/techandme/wordpress-vm/master/lib.sh) + # If we have internet, then use the latest variables from the lib remote file +elif [ -f /var/scripts/lib.sh ] +then +# shellcheck disable=2034,2059 +true +SCRIPT_NAME="Static IP" +# shellcheck source=lib.sh +source /var/scripts/lib.sh +else + printf "You don't seem to have a working internet connection, and \ +/var/scripts/lib.sh is missing so you can't run this script." + printf "Please report this to https://github.com/nextcloud/vm/issues/" + exit 1 +fi + +# Check for errors + debug code and abort if something isn't right +# 1 = ON +# 0 = OFF +DEBUG=0 +debug_mode + +# Must be root +root_check + +# Check Ubuntu version +check_distro_version + +# Copy old interfaces files +msg_box "Copying old netplan.io config files file to: + +/tmp/netplan_io_backup/" +if [ -d /etc/netplan/ ] +then + mkdir -p /tmp/netplan_io_backup + check_command cp -vR /etc/netplan/* /tmp/netplan_io_backup/ +fi + +msg_box "Please note that if the IP address changes during an (remote) SSH connection \ +(via Putty, or CLI for example), the connection will break and the IP will reset to \ +DHCP or the IP you had before you started this script. + +To avoid issues with lost connectivity, please use the VM Console directly, and not SSH." +if yesno_box_yes "Are you connected via SSH?" +then + msg_box "Please use the VM Console instead." + sleep 1 + exit +fi + +# Loop until working network settings are validated or the user asks to quit +echo +while : +do + # Loop until user is happy with the IP address and subnet + echo + while : + do + # Ask for IP address + LANIP=$(input_box "Please enter the static IP address you want to set, \ +including the subnet.\nExample: 192.168.1.100/24") + if [[ $LANIP == *"/"* ]] + then + if yesno_box_yes "Is this correct? $LANIP" + then + break + fi + else + msg_box "Did you forget the /subnet?" + fi + done + + # Loop until user is happy with the default gateway + echo + while : + do + # Ask for domain name + GATEWAYIP=$(input_box "Please enter the gateway address you want to set. +Just hit enter to choose the current gateway.\nYour current gateway is: $GATEWAY") + if [ -z "$GATEWAYIP" ] + then + GATEWAYIP="$GATEWAY" + fi + if yesno_box_yes "Is this correct? $GATEWAYIP" + then + break + fi + done + + # DNS + msg_box "You will now be provided with the option to set your own local DNS. + +If you're not sure what DNS is, or if you don't have a local DNS server, +please don't touch this setting. + +If something goes wrong here, you will not be +able to get any deb packages, download files, or reach the internet. + +The current nameservers are: +$DNS1 +$DNS2 +" + + # Set the variable used to fill in the Netplan nameservers. The existing + # values are used if the user does not decides not to update the nameservers. + DNSs="$DNS1" + # Only add a second nameserver to the list if it is defined. + if [ -n "$DNS2" ] + then + DNSs="$DNS1,$DNS2" + fi + + if yesno_box_no "Do you want to set your own nameservers?" + then + # Loop until user is happy with the nameserver 1 + echo + while : + do + # Ask for nameserver + NSIP1=$(input_box "Please enter the local nameserver address you want to set. +Just hit enter to choose the current NS1.\nYour current NS1 is: $DNS1") + if [ -z "$NSIP1" ] + then + NSIP1="$DNS1" + fi + if yesno_box_yes "Is this correct? $NSIP1" + then + break + fi + done + + # Nameserver 2 might be empty. As this will not be clear + # in prompts, 'none' is used in this case. + DISPLAY_DNS2="$DNS2" + if [ -z "$DISPLAY_DNS2" ] + then + DISPLAY_DNS2="'none'" + fi + + # Loop until user is happy with the nameserver 2 + echo + while : + do + # Ask for nameserver + NSIP2=$(input_box "Please enter the local nameserver address you want to set. The 3 options are: +- Hit enter to choose the current NS2.\n- Enter a new IP address for NS2. +- Enter the text 'none' if you only have one NS.\nYour current NS2 is: $DISPLAY_DNS2") + if [ -z "$NSIP2" ] + then + NSIP2="$DISPLAY_DNS2" + fi + if yesno_box_yes "Is this correct? $NSIP2" + then + break + fi + done + fi + + # Check if DNS is set manaully and set variables accordingly + if [ -n "$NSIP1" ] + then + DNSs="$NSIP1" + # Only add a second nameserver to the list if it is defined and not 'none'. + if [[ -n "$NSIP2" && ! ( "none" == "$NSIP2" || "'none'" == "$NSIP2" ) ]] + then + DNSs="$NSIP1,$NSIP2" + fi + fi + + # Check if IFACE is empty, if yes, try another method: + if [ -n "$IFACE" ] + then + cat <<-IPCONFIG > "$INTERFACES" +network: + version: 2 + ethernets: + $IFACE: #object name + dhcp4: false # dhcp v4 disable + dhcp6: false # dhcp v6 disable + addresses: [$LANIP] # client IP address + gateway4: $GATEWAYIP # gateway address + nameservers: + addresses: [$DNSs] #name servers +IPCONFIG + + msg_box "These are your settings, please make sure they are correct: + +$(cat /etc/netplan/01-netcfg.yaml)" + netplan try + set_systemd_resolved_dns "$IFACE" + else + cat <<-IPCONFIGnonvmware > "$INTERFACES" +network: + version: 2 + ethernets: + $IFACE2: #object name + dhcp4: false # dhcp v4 disable + dhcp6: false # dhcp v6 disable + addresses: [$LANIP] # client IP address + gateway4: $GATEWAY # gateway address + nameservers: + addresses: [$DNSs] #name servers +IPCONFIGnonvmware + + msg_box "These are your settings, please make sure they are correct: + +$(cat /etc/netplan/01-netcfg.yaml)" + netplan try + set_systemd_resolved_dns "$IFACE2" + fi + + if test_connection + then + sleep 1 + msg_box "Static IP sucessfully set!" + break + fi + + cat << BADNETWORKTEXT + +The network settings do not provide access to the Internet and/or the DNS +servers are not reachable. Unless Wi-Fi is required and still to be configured +proceeding will not succeed. + +BADNETWORKTEXT + if ! yesno_box_yes "Try new network settings?" + then + break + fi +done diff --git a/static/adduser.sh b/static/adduser.sh index 21217ae..cd06aee 100644 --- a/static/adduser.sh +++ b/static/adduser.sh @@ -1,10 +1,11 @@ #!/bin/bash # shellcheck disable=2034,2059 true +SCRIPT_NAME="Add CLI User" # shellcheck source=lib.sh -. <(curl -sL https://raw.githubusercontent.com/techandme/wordpress-vm/master/lib.sh) +source /var/scripts/fetch_lib.sh || source <(curl -sL https://raw.githubusercontent.com/techandme/wordpress-vm/master/lib.sh) -# T&M Hansson IT AB © - 2019, https://www.hanssonit.se/ +# T&M Hansson IT AB © - 2020, https://www.hanssonit.se/ # Check for errors + debug code and abort if something isn't right # 1 = ON @@ -14,13 +15,14 @@ debug_mode if [[ $UNIXUSER != "wordpress" ]] then -msg_box "Current user with sudo permissions is: $UNIXUSER. + msg_box "Current user with sudo permissions is: $UNIXUSER. This script will set up everything with that user. If the field after ':' is blank you are probably running as a pure root user. It's possible to install with root, but there will be minor errors. + Please create a user with sudo permissions if you want an optimal installation. -The preferred user is 'wordpress'." - if [[ "no" == $(ask_yes_or_no "Do you want to create a new user?") ]] +The preferred user is 'ncadmin'." + if ! yesno_box_yes "Do you want to create a new user?" then print_text_in_color "$ICyan" "Not adding another user..." sleep 1 @@ -29,7 +31,7 @@ The preferred user is 'wordpress'." adduser --disabled-password --gecos "" "$NEWUSER" sudo usermod -aG sudo "$NEWUSER" usermod -s /bin/bash "$NEWUSER" - while true + while : do sudo passwd "$NEWUSER" && break done diff --git a/static/change-root-profile.sh b/static/change-root-profile.sh index 2a43c42..9c2106a 100644 --- a/static/change-root-profile.sh +++ b/static/change-root-profile.sh @@ -5,7 +5,7 @@ # shellcheck disable=2034,2059 true # shellcheck source=lib.sh -. <(curl -sL https://raw.githubusercontent.com/techandme/wordpress-vm/master/lib.sh) +source /var/scripts/fetch_lib.sh || source <(curl -sL https://raw.githubusercontent.com/techandme/wordpress-vm/master/lib.sh) # Check for errors + debug code and abort if something isn't right # 1 = ON diff --git a/static/change-wordpress-profile.sh b/static/change-wordpress-profile.sh index 730f826..b6ff397 100644 --- a/static/change-wordpress-profile.sh +++ b/static/change-wordpress-profile.sh @@ -5,7 +5,7 @@ # shellcheck disable=2034,2059 true # shellcheck source=lib.sh -. <(curl -sL https://raw.githubusercontent.com/techandme/wordpress-vm/master/lib.sh) +source /var/scripts/fetch_lib.sh || source <(curl -sL https://raw.githubusercontent.com/techandme/wordpress-vm/master/lib.sh) # Check for errors + debug code and abort if something isn't right # 1 = ON @@ -13,7 +13,7 @@ true DEBUG=0 debug_mode -rm "/home/$UNIXUSER/.profile" +rm -f "/home/$UNIXUSER/.profile" cat <<-UNIXUSER-PROFILE > "$UNIXUSER_PROFILE" # ~/.profile: executed by the command interpreter for login shells. diff --git a/static/change_db_pass.sh b/static/change_db_pass.sh new file mode 100644 index 0000000..f6e083c --- /dev/null +++ b/static/change_db_pass.sh @@ -0,0 +1,30 @@ +#!/bin/bash +# shellcheck disable=2034,2059 +true +SCRIPT_NAME="Change Database Password" +# shellcheck source=lib.sh +source /var/scripts/fetch_lib.sh || source <(curl -sL https://raw.githubusercontent.com/techandme/wordpress-vm/master/lib.sh) + +# T&M Hansson IT AB © - 2020, https://www.hanssonit.se/ + +# Check for errors + debug code and abort if something isn't right +# 1 = ON +# 0 = OFF +DEBUG=0 +debug_mode + +# Change MARIADB Password +if mysqladmin -u root password "$NEWMARIADBPASS" > /dev/null 2>&1 +then + msg_box "Your new MARIADB root password is: $NEWMARIADBPASS +Please keep it somewhere safe. + +To login to MariaDB,, simply type 'mysql -u root' from your CLI. +Authentication happens with the UNIX socket. In other words, +no password is needed as long as you have access to the root account." + exit 0 +else + print_text_in_color "$IRed" "Changing MARIADB root password failed." + print_text_in_color "$ICyan" "Your old password is: $MARIADBMYCNFPASS" + exit 1 +fi diff --git a/static/change_mysql_pass.sh b/static/change_mysql_pass.sh deleted file mode 100644 index 829e5d8..0000000 --- a/static/change_mysql_pass.sh +++ /dev/null @@ -1,30 +0,0 @@ -#!/bin/bash -# shellcheck disable=2034,2059 -true -# shellcheck source=lib.sh -MYCNFPW=1 . <(curl -sL https://raw.githubusercontent.com/techandme/wordpress-vm/master/lib.sh) -unset MYCNFPW - -# T&M Hansson IT AB © - 2019, https://www.hanssonit.se/ - -# Check for errors + debug code and abort if something isn't right -# 1 = ON -# 0 = OFF -DEBUG=0 -debug_mode - -# Change MARIADB Password -if mysqladmin -u root -p"$MARIADBMYCNFPASS" password "$NEWMARIADBPASS" > /dev/null 2>&1 -then - print_text_in_color "$IGreen" "Your new MARIADB root password is: $NEWMARIADBPASS" - cat << LOGIN > "$MYCNF" -[client] -password='$NEWMARIADBPASS' -LOGIN - chmod 0600 $MYCNF - exit 0 -else - print_text_in_color "$IRed" "Changing MARIADB root password failed." - print_text_in_color "$ICyan" "Your old password is: $MARIADBMYCNFPASS" - exit 1 -fi diff --git a/static/fetch_lib.sh b/static/fetch_lib.sh new file mode 100644 index 0000000..d525984 --- /dev/null +++ b/static/fetch_lib.sh @@ -0,0 +1,37 @@ +#!/bin/bash +# shellcheck disable=2034,2059 +true +# see https://github.com/koalaman/shellcheck/wiki/Directive + +IRed='\e[0;91m' # Red +IGreen='\e[0;92m' # Green +ICyan='\e[0;96m' # Cyan +Color_Off='\e[0m' # Text Reset +print_text_in_color() { + printf "%b%s%b\n" "$1" "$2" "$Color_Off" +} + +if [[ "$EUID" -ne 0 ]] +then + print_text_in_color "$IRed" "You must run fetch_lib with sudo privileges, or directly as root!" + print_text_in_color "$ICyan" "Please report this to https://github.com/nextcloud/vm/issues if you think it's a bug." + exit 1 +fi + +mkdir -p /var/scripts +if ! [ -f /var/scripts/lib.sh ] +then + if ! curl -sfL https://raw.githubusercontent.com/techandme/wordpress-vm/master/lib.sh -o /var/scripts/lib.sh + then + print_text_in_color "$IRed" "You don't seem to have an internet \ +connection and the local lib isn't available. Hence you cannot run this script." + exit 1 + fi +elif ! [ -f /var/scripts/wordpress-startup-script.sh ] +then + print_text_in_color "$ICyan" "Updating lib..." + curl -sfL https://raw.githubusercontent.com/techandme/wordpress-vm/master/lib.sh -o /var/scripts/lib.sh +fi + +# shellcheck source=lib.sh +source /var/scripts/lib.sh diff --git a/static/instruction.sh b/static/instruction.sh index e14f8a7..3562fcf 100644 --- a/static/instruction.sh +++ b/static/instruction.sh @@ -7,7 +7,7 @@ cat << WELCOME +-----------------------------------------------------------------------+ |Thank you for downloading this Wordpress VM made by T&M Hansson IT AB! | | | -|This WordPress appliance comes with PHP 7.2, NGINX and Redis Cache for | +|This WordPress appliance comes with PHP 7.4, NGINX and Redis Cache for | |best performance. The site(s) load very fast! | | | |In order to configure everything you have to run the setup script | @@ -15,7 +15,7 @@ cat << WELCOME | | |Complete instructions can be found here: https://bit.ly/2E5fbUn | | | -|If you have any questions please email me: daniel@hanssonit.se | +|If you have any questions please email us: github@hanssonit.se | +-----------------------------------------------------------------------+ WELCOME diff --git a/static/new_etc_mycnf.sh b/static/new_etc_mycnf.sh index bd239c9..08fd356 100644 --- a/static/new_etc_mycnf.sh +++ b/static/new_etc_mycnf.sh @@ -2,7 +2,7 @@ # shellcheck disable=2034,2059 true # shellcheck source=lib.sh -. <(curl -sL https://raw.githubusercontent.com/techandme/wordpress-vm/master/lib.sh) +source /var/scripts/fetch_lib.sh || source <(curl -sL https://raw.githubusercontent.com/techandme/wordpress-vm/master/lib.sh) # Check for errors + debug code and abort if something isn't right # 1 = ON @@ -61,6 +61,7 @@ tmpdir = /tmp lc_messages_dir = /usr/share/mysql lc_messages = en_US skip-external-locking +skip-name-resolve # # Instead of skip-networking the default is now to listen only on # localhost which is more compatible and is not less secure. @@ -70,13 +71,13 @@ bind-address = 127.0.0.1 # max_connections = 100 connect_timeout = 5 -wait_timeout = 600 +wait_timeout = 300 max_allowed_packet = 16M thread_cache_size = 128 sort_buffer_size = 4M bulk_insert_buffer_size = 16M -tmp_table_size = 32M -max_heap_table_size = 32M +tmp_table_size = 64M +max_heap_table_size = 64M # # * MyISAM # @@ -94,8 +95,10 @@ read_rnd_buffer_size = 1M # * Query Cache Configuration # # Cache only tiny result sets, so we can fit more in the query cache. -query_cache_limit = 128K -query_cache_size = 64M +query_cache_type = 1 +query_cache_limit = 256K +query_cache_min_res_unit = 2k +query_cache_size = 80M # for more write intensive setups, set to DEMAND or OFF #query_cache_type = DEMAND # @@ -115,7 +118,7 @@ log_warnings = 2 # Enable the slow query log to see queries with especially long duration #slow_query_log[={0|1}] slow_query_log_file = /var/log/mysql/mariadb-slow.log -long_query_time = 10 +long_query_time = 10 #log_slow_rate_limit = 1000 log_slow_verbosity = query_plan #log-queries-not-using-indexes @@ -208,9 +211,7 @@ max_allowed_packet = 16M default-character-set = utf8mb4 #no-auto-rehash # faster start of mysql but no tab completion [mariadb] -innodb_use_fallocate = 1 innodb_use_atomic_writes = 1 -innodb_use_trim = 1 [isamchk] key_buffer = 16M # diff --git a/static/nginx.conf b/static/nginx.conf index 970d962..338dd94 100644 --- a/static/nginx.conf +++ b/static/nginx.conf @@ -12,37 +12,6 @@ events { } http { - -# GEO IP BLOCK DOMAIN -geoip_country /usr/share/GeoIP/GeoIP.dat; - map $geoip_country_code $allowed_country { - default yes; - CN no; #China -# RU no; #Russia -# HK no; #Hong Kong -# IN no; #India -# IR no; #Iran -# VN no; #Vietnam -# TR no; #Turkey -# EG no; #Egypt -# MX no; #Mexico -# JP no; #Japan -# KR no; #South Korea -# KP no; #North Korea :) -# PE no; #Peru -# BR no; #Brazil -# UA no; #Ukraine -# ID no; #Indonesia -# TH no; #Thailand - } - -# To activate GEO BLOCK, add this in the default conf: -# COUNTRY GEO BLOCK -# if ($allowed_country = no) { -# return 444; -# } - - ## # Basic Settings ## @@ -67,12 +36,10 @@ geoip_country /usr/share/GeoIP/GeoIP.dat; # SSL Settings ## - ssl_early_data on; + ssl_early_data off; ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384; ssl_prefer_server_ciphers on; - - ## # Logging Settings diff --git a/static/ntpdate.sh b/static/ntpdate.sh deleted file mode 100644 index aa27a2d..0000000 --- a/static/ntpdate.sh +++ /dev/null @@ -1,20 +0,0 @@ -#!/bin/bash - -# T&M Hansson IT AB © - 2019, https://www.hanssonit.se/ - -# shellcheck disable=2034,2059 -true -# shellcheck source=lib.sh -. <(curl -sL https://raw.githubusercontent.com/techandme/wordpress-vm/master/lib.sh) - -# Check for errors + debug code and abort if something isn't right -# 1 = ON -# 0 = OFF -DEBUG=0 -debug_mode - -if wget -q -T 10 -t 2 http://google.com > /dev/null -then - ntpdate -s 1.se.pool.ntp.org -fi -exit diff --git a/static/security.sh b/static/security.sh deleted file mode 100644 index 8ea0828..0000000 --- a/static/security.sh +++ /dev/null @@ -1,121 +0,0 @@ -#!/bin/bash - -# T&M Hansson IT AB © - 2019, https://www.hanssonit.se/ - -# REMOVE disable of SC2154 WHEN PUTTING SPAMHAUS IN PRODUCTION (it's just to fixing travis for now) -# shellcheck disable=2034,2059,SC2154 -true -# shellcheck source=lib.sh -. <(curl -sL https://raw.githubusercontent.com/techandme/wordpress-vm/master/lib.sh) - -# Check for errors + debug code and abort if something isn't right -# 1 = ON -# 0 = OFF -DEBUG=0 -debug_mode - -# Check if root -root_check - -print_text_in_color "$ICyan" "Installing Extra Security..." - -# Based on: http://www.techrepublic.com/blog/smb-technologist/secure-your-apache-server-from-ddos-slowloris-and-dns-injection-attacks/ - -# Protect against DDOS -apt update -q4 & spinner_loading -apt -y install libapache2-mod-evasive -mkdir -p /var/log/apache2/evasive -chown -R www-data:root /var/log/apache2/evasive -if [ ! -f "$ENVASIVE" ] -then - touch "$ENVASIVE" - cat << ENVASIVE > "$ENVASIVE" -DOSHashTableSize 2048 -DOSPageCount 20 # maximum number of requests for the same page -DOSSiteCount 300 # total number of requests for any object by the same client IP on the same listener -DOSPageInterval 1.0 # interval for the page count threshold -DOSSiteInterval 1.0 # interval for the site count threshold -DOSBlockingPeriod 10.0 # time that a client IP will be blocked for -DOSLogDir -ENVASIVE -fi - -# Protect against Slowloris -#apt -y install libapache2-mod-qos -a2enmod reqtimeout # http://httpd.apache.org/docs/2.4/mod/mod_reqtimeout.html - -# Don't enable SpamHaus now as it's now working anyway -# REMOVE disable of SC2154 WHEN PUTTING SPAMHAUS IN PRODUCTION (it's just to fixing travis for now) -exit - -# Protect against DNS Injection -# Insipired by: https://www.c-rieger.de/nextcloud-13-nginx-installation-guide-for-ubuntu-18-04-lts/#spamhausproject - -# shellcheck disable=SC2016 -DATE='$(date +%Y-%m-%d)' -cat << SPAMHAUS_ENABLE > "$SCRIPTS/spamhaus_cronjob.sh" -#!/bin/bash -# Thanks to @ank0m -EXEC_DATE='date +%Y-%m-%d' -SPAMHAUS_DROP="/usr/local/src/drop.txt" -SPAMHAUS_eDROP="/usr/local/src/edrop.txt" -URL="https://www.spamhaus.org/drop/drop.txt" -eURL="https://www.spamhaus.org/drop/edrop.txt" -DROP_ADD_TO_UFW="/usr/local/src/DROP2.txt" -eDROP_ADD_TO_UFW="/usr/local/src/eDROP2.txt" -DROP_ARCHIVE_FILE="/usr/local/src/DROP_{$EXEC_DATE}" -eDROP_ARCHIVE_FILE="/usr/local/src/eDROP_{$EXEC_DATE}" -# All credits for the following BLACKLISTS goes to "The Spamhaus Project" - https://www.spamhaus.org -echo "Start time: $(date)" -echo " " -echo "Download daily DROP file:" -wget -q -O - "$URL" > $SPAMHAUS_DROP -grep -v '^;' $SPAMHAUS_DROP | cut -d ' ' -f 1 > $DROP_ADD_TO_UFW -echo " " -echo "Extract DROP IP addresses and add to UFW:" -cat $DROP_ADD_TO_UFW | while read line -do -/usr/sbin/ufw insert 1 deny from "$line" comment 'DROP_Blacklisted_IPs' -done -echo " " -echo "Downloading eDROP list and import to UFW" -echo " " -echo "Download daily eDROP file:" -wget -q -O - "$eURL" > $SPAMHAUS_eDROP -grep -v '^;' $SPAMHAUS_eDROP | cut -d ' ' -f 1 > $eDROP_ADD_TO_UFW -echo " " -echo "Extract eDROP IP addresses and add to UFW:" -cat $eDROP_ADD_TO_UFW | while read line -do -/usr/sbin/ufw insert 1 deny from "$line" comment 'eDROP_Blacklisted_IPs' -done -echo " " -##### -## To remove or revert these rules, keep the list of IPs! -## Run a command like so to remove the rules: -# while read line; do ufw delete deny from $line; done < $ARCHIVE_FILE -##### -echo "Backup DROP IP address list:" -mv $DROP_ADD_TO_UFW $DROP_ARCHIVE_FILE -echo " " -echo "Backup eDROP IP address list:" -mv $eDROP_ADD_TO_UFW $eDROP_ARCHIVE_FILE -echo " " -echo End time: $(date) -SPAMHAUS_ENABLE - -# Make the file executable -chmod +x "$SCRIPTS"/spamhaus_cronjob.sh - -# Add it to crontab -(crontab -l ; echo "10 2 * * * $SCRIPTS/spamhaus_crontab.sh 2>&1") | crontab -u root - - -# Run it for the first time -check_command bash "$SCRIPTS"/spamhaus_cronjob.sh - -# Enable $SPAMHAUS -if sed -i "s|#MS_WhiteList /etc/spamhaus.wl|MS_WhiteList $SPAMHAUS|g" /etc/apache2/mods-enabled/spamhaus.conf -then - print_text_in_color "$IGreen" "Security added!" - restart_webserver -fi diff --git a/static/static_ip.sh b/static/static_ip.sh index 4549846..4d77ad7 100644 --- a/static/static_ip.sh +++ b/static/static_ip.sh @@ -5,7 +5,7 @@ # shellcheck disable=2034,2059 true # shellcheck source=lib.sh -FIRST_IFACE=1 . <(curl -sL https://raw.githubusercontent.com/techandme/wordpress-vm/master/lib.sh) +FIRST_IFACE=1 source /var/scripts/fetch_lib.sh || source <(curl -sL https://raw.githubusercontent.com/techandme/wordpress-vm/master/lib.sh) unset FIRST_IFACE # Check for errors + debug code and abort if something isn't right diff --git a/static/test_connection.sh b/static/test_connection.sh deleted file mode 100644 index 6b206e8..0000000 --- a/static/test_connection.sh +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/bash -# shellcheck disable=2034,2059 -true -# shellcheck source=lib.sh -. <(curl -sL https://raw.githubusercontent.com/techandme/wordpress-vm/master/lib.sh) - -# T&M Hansson IT AB © - 2019, https://www.hanssonit.se/ - -# Check for errors + debug code and abort if something isn't right -# 1 = ON -# 0 = OFF -DEBUG=0 -debug_mode - -$WGET -q --tries=20 --timeout=10 http://www.google.com -O /tmp/google.idx &> /dev/null -if [ ! -s /tmp/google.idx ] -then - printf "${Red}Not Connected!${Color_Off}\n" -else - printf "Connected!\n" -fi diff --git a/static/update.sh b/static/update.sh index f55303b..7cacb7a 100644 --- a/static/update.sh +++ b/static/update.sh @@ -5,7 +5,7 @@ # shellcheck disable=2034,2059 true # shellcheck source=lib.sh -. <(curl -sL https://raw.githubusercontent.com/techandme/wordpress-vm/master/lib.sh) +source <(curl -sL https://raw.githubusercontent.com/techandme/wordpress-vm/master/lib.sh) # Check for errors + debug code and abort if something isn't right # 1 = ON @@ -23,6 +23,6 @@ fi mkdir -p "$SCRIPTS" # Delete, download, run -run_static_script wordpress_update +run_script STATIC wordpress_update exit diff --git a/static/techandme.sh b/static/wordpress.sh similarity index 75% rename from static/techandme.sh rename to static/wordpress.sh index 4ceb20c..ef08c62 100644 --- a/static/techandme.sh +++ b/static/wordpress.sh @@ -19,9 +19,10 @@ echo "LAN IPv4: $ADDRESS" echo echo "Wordpress Login:" echo "$WPADMINUSER" -echo "WP PASS: 'grep WP PASS: /var/adminpass.txt'" +echo "Type this in your CLI to get the password:" +echo "grep 'WP PASS:' /var/adminpass.txt" echo echo "MySQL/MariaDB:" -echo "USER: root" -echo "PASS: 'cat /root/.my.cnf'" +echo "Login happens with the OS root account." +echo "Simply type 'mysql -u root' from your CLI" echo diff --git a/static/wordpress_update.sh b/static/wordpress_update.sh index 7e626b7..bc1bc70 100644 --- a/static/wordpress_update.sh +++ b/static/wordpress_update.sh @@ -5,7 +5,7 @@ # shellcheck disable=2034,2059 true # shellcheck source=lib.sh -. <(curl -sL https://raw.githubusercontent.com/techandme/wordpress-vm/master/lib.sh) +source <(curl -sL https://raw.githubusercontent.com/techandme/wordpress-vm/master/lib.sh) # Check for errors + debug code and abort if something isn't right # 1 = ON @@ -13,69 +13,96 @@ true DEBUG=0 debug_mode -# Check if root -if ! is_root -then - printf "\n${Red}Sorry, you are not root.\n${Color_Off}You must type: ${Cyan}sudo ${Color_Off}bash %s/wordpress_update.sh\n" "$SCRIPTS" - exit 1 -fi +# Must be root +root_check # Check if dpkg or apt is running is_process_running apt is_process_running dpkg -# System Upgrade -apt update -q2 -apt dist-upgrade -y - -# Update Redis PHP extension -print_text_in_color "$ICyan" "Trying to upgrade the Redis PECL extenstion..." -if ! pecl list | grep redis >/dev/null 2>&1 +# Check if /boot is filled more than 90% and exit the script if that's +# the case since we don't want to end up with a broken system +if [ -d /boot ] then - if is_this_installed php"$PHPVER" + if [[ "$(df -h | grep -m 1 /boot | awk '{print $5}' | cut -d "%" -f1)" -gt 90 ]] then - install_if_not php"$PHPVER"-dev - else - install_if_not php7.0-dev + msg_box "It seems like your boot drive is filled more than 90%. \ +You can't proceed to upgrade since it probably will break your system +To be able to proceed with the update you need to delete some old Linux kernels. If you need support, please visit: +https://shop.hanssonit.se/product/premium-support-per-30-minutes/" + exit fi - apt purge php-redis -y - apt autoremove -y - pecl channel-update pecl.php.net - yes no | pecl install redis - service redis-server restart - if nginx -v 2> /dev/null - then - service nginx restart - elif apache2 -v 2> /dev/null +fi + +# Ubuntu 16.04 is deprecated +check_distro_version + +send_mail \ +"Wordpress update started!" \ +"Please don't shutdown or reboot your server during the update! $(date +%T)" +wp_cli_cmd maintenance-mode activate + +# Hold PHP if Ondrejs PPA is used +print_text_in_color "$ICyan" "Fetching latest packages with apt..." +apt update -q4 & spinner_loading +if apt-cache policy | grep "ondrej" >/dev/null 2>&1 +then + print_text_in_color "$ICyan" "Ondrejs PPA is installed. \ +Holding PHP to avoid upgrading to a newer version without migration..." + apt-mark hold php* +fi + +# Make sure everyone gets access to menu.sh +download_script MENU menu + +# Make sure fetch_lib.sh is available +download_script STATIC fetch_lib + +export DEBIAN_FRONTEND=noninteractive ; apt dist-upgrade -y -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" + +# Update Netdata +if [ -d /etc/netdata ] +then + print_text_in_color "$ICyan" "Updating Netdata..." + NETDATA_UPDATER_PATH="$(find /usr -name 'netdata-updater.sh')" + if [ -n "$NETDATA_UPDATER_PATH" ] then - service apache2 restart + install_if_not cmake # Needed for Netdata in newer versions + bash "$NETDATA_UPDATER_PATH" fi -elif pecl list | grep redis >/dev/null 2>&1 +fi + +# Update Redis PHP extension (18.04 --> 20.04 since 16.04 already is deprecated in the top of this script) +print_text_in_color "$ICyan" "Trying to upgrade the Redis PECL extension..." + +# Check current PHP version +check_php + +# Do the upgrade +if pecl list | grep redis >/dev/null 2>&1 then - if is_this_installed php"$PHPVER" + if is_this_installed php"$PHPVER"-common then install_if_not php"$PHPVER"-dev - else - install_if_not php7.0-dev fi pecl channel-update pecl.php.net yes no | pecl upgrade redis - service redis-server restart - if nginx -v 2> /dev/null - then - service nginx restart - elif apache2 -v 2> /dev/null - then - service apache2 restart - fi + systemctl restart redis-server.service +fi + +# Double check if redis.so is enabled +if ! grep -qFx extension=redis.so "$PHP_INI" +then + echo "extension=redis.so" >> "$PHP_INI" fi +restart_webserver # Upgrade APCu and igbinary -if is_this_installed php"$PHPVER" +if is_this_installed php"$PHPVER"-dev then if [ -f "$PHP_INI" ] then - print_text_in_color "$ICyan" "Trying to upgrade igbinary and APCu..." + print_text_in_color "$ICyan" "Trying to upgrade igbinary, and APCu..." if pecl list | grep igbinary >/dev/null 2>&1 then yes no | pecl upgrade igbinary @@ -85,7 +112,7 @@ then echo "extension=igbinary.so" >> "$PHP_INI" fi fi - if pecl list | grep apcu >/dev/null 2>&1 + if pecl list | grep -q apcu then yes no | pecl upgrade apcu # Check if apcu.so is enabled @@ -94,6 +121,15 @@ then echo "extension=apcu.so" >> "$PHP_INI" fi fi + if pecl list | grep -q inotify + then + yes no | pecl upgrade inotify + # Check if inotify.so is enabled + if ! grep -qFx extension=inotify.so "$PHP_INI" + then + echo "extension=inotify.so" >> "$PHP_INI" + fi + fi fi fi @@ -102,56 +138,59 @@ if [ -d $ADMINERDIR ] then print_text_in_color "$ICyan" "Updating Adminer..." rm -f "$ADMINERDIR"/latest.php "$ADMINERDIR"/adminer.php - wget -q "http://www.adminer.org/latest.php" -O "$ADMINERDIR"/latest.php + curl_to_dir "http://www.adminer.org" "latest.php" "$ADMINERDIR" ln -s "$ADMINERDIR"/latest.php "$ADMINERDIR"/adminer.php fi -# Check if Wordpress is installed in the regular path or try to find it -if [ ! -d "$WPATH" ] +# Cleanup un-used packages +apt autoremove -y +apt autoclean + +# Update GRUB, just in case +update-grub + +# Remove update lists +rm /var/lib/apt/lists/* -r + +# Fix bug in nextcloud.sh +CURRUSR="$(getent group sudo | cut -d: -f4 | cut -d, -f1)" +if grep -q "6.ifcfg.me" $SCRIPTS/wordpress.sh &>/dev/null then - WPATH="/var/www/$(find /var/www/* -type d | grep wp | head -1 | cut -d "/" -f4)" - export WPATH - if [ ! -d "$WPATH"/wp-admin ] - then - WPATH="/var/www/$(find /var/www/* -type d | grep wp | tail -1 | cut -d "/" -f4)" - export WPATH - if [ ! -d "$WPATH"/wp-admin ] - then - WPATH="/var/www/html/$(find /var/www/html/* -type d | grep wp | head -1 | cut -d "/" -f5)" - export WPATH - if [ ! -d "$WPATH"/wp-admin ] - then - WPATH="/var/www/html/$(find /var/www/html/* -type d | grep wp | tail -1 | cut -d "/" -f5)" - export WPATH - if [ ! -d "$WPATH"/wp-admin ] - then -msg_box "Wordpress doesn't seem to be installed in the regular path. We tried to find it, but didn't succeed. - -The script will now exit." - exit 1 - fi - fi - fi - fi + rm -f "$SCRIPTS/wordpress.sh" + download_script STATIC wordpress + chown "$CURRUSR":"$CURRUSR" "$SCRIPTS/wordpress.sh" + chmod +x "$SCRIPTS/wordpress.sh" +elif [ -f $SCRIPTS/techandme.sh ] +then + rm -f "$SCRIPTS/techandme.sh" + download_script STATIC wordpress + chown "$CURRUSR":"$CURRUSR" "$SCRIPTS/wordpress.sh" + chmod +x "$SCRIPTS/wordpress.sh" + if [ -f /home/"$CURRUSR"/.bash_profile ] + then + sed -i "s|techandme|wordpress|g" /home/"$CURRUSR"/.bash_profile + elif [ -f /home/"$CURRUSR"/.profile ] + then + sed -i "s|techandme|wordpress|g" /home/"$CURRUSR"/.profile + fi fi # Set secure permissions if [ ! -f "$SECURE" ] then mkdir -p "$SCRIPTS" - download_static_script wp-permissions + download_script STATIC wp-permissions + chmod +x "$SECURE" +else + rm "$SECURE" + download_script STATIC wp-permissions chmod +x "$SECURE" - bash "$SECURE" -elif [ -f "$SECURE" ] -then - bash "$SECURE" fi # Upgrade WP-CLI wp cli update # Upgrade Wordpress and apps -cd "$WPATH" wp_cli_cmd db export mysql_backup.sql mv "$WPATH"/mysql_backup.sql /var/www/mysql_backup.sql chown root:root /var/www/mysql_backup.sql @@ -160,18 +199,20 @@ wp_cli_cmd plugin update --all wp_cli_cmd core update-db wp_cli_cmd db optimize print_text_in_color "$ICyan" "This is the current version installed:" -wp_cli_cmd core version --extra - -# Cleanup un-used packages -apt autoremove -y -apt autoclean - -# Update GRUB, just in case -update-grub - -# Write to log -touch /var/log/cronjobs_success.log -echo "WORDPRESS UPDATE success-$(date +%Y-%m-%d_%H:%M)" >> /var/log/cronjobs_success.log +if wp_cli_cmd core version --extra +then + # Write to log + touch "$VMLOGS"/cronjobs_success.log + echo "WORDPRESS UPDATE success-$(date +%Y-%m-%d_%H:%M)" >> "$VMLOGS"/cronjobs_success.log + # Send email + send_mail \ +"Wordpress update finished!" \ +"Wordpress update is now complete. Please visit your site to check that everything looks alright. $(date +%T)" + if wp_cli_cmd maintenance-mode status | grep -q "is active" + then + wp_cli_cmd maintenance-mode deactivate + fi +fi # Un-hash this if you want the system to reboot # reboot diff --git a/static/wp-permissions.sh b/static/wp-permissions.sh old mode 100755 new mode 100644 diff --git a/wordpress-startup-script.sh b/wordpress-startup-script.sh index 7749923..39b89fa 100644 --- a/wordpress-startup-script.sh +++ b/wordpress-startup-script.sh @@ -1,80 +1,46 @@ #!/bin/bash -# shellcheck disable=2034,2059 -true -# shellcheck source=lib.sh -WPDB=1 && MYCNFPW=1 && FIRST_IFACE=1 && CHECK_CURRENT_REPO=1 . <(curl -sL https://raw.githubusercontent.com/techandme/wordpress-vm/master/lib.sh) -unset FIRST_IFACE -unset CHECK_CURRENT_REPO -unset MYCNFPW -unset WPDB -# T&M Hansson IT AB © - 2019, https://www.hanssonit.se/ +# T&M Hansson IT AB © - 2020, https://www.hanssonit.se/ -## If you want debug mode, please activate it further down in the code at line ~132 +######### -# FUNCTIONS # - -msg_box() { -local PROMPT="$1" - whiptail --msgbox "${PROMPT}" "$WT_HEIGHT" "$WT_WIDTH" +IRed='\e[0;91m' # Red +IGreen='\e[0;92m' # Green +ICyan='\e[0;96m' # Cyan +Color_Off='\e[0m' # Text Reset +print_text_in_color() { + printf "%b%s%b\n" "$1" "$2" "$Color_Off" } -is_root() { - if [[ "$EUID" -ne 0 ]] - then - return 1 - else - return 0 - fi -} +print_text_in_color "$ICyan" "Fetching all the variables from lib.sh..." -root_check() { -if ! is_root -then -msg_box "Sorry, you are not root. You now have two options: -1. With SUDO directly: - a) :~$ sudo bash $SCRIPTS/name-of-script.sh -2. Become ROOT and then type your command: - a) :~$ sudo -i - b) :~# $SCRIPTS/name-of-script.sh -In both cases above you can leave out $SCRIPTS/ if the script -is directly in your PATH. -More information can be found here: https://unix.stackexchange.com/a/3064" - exit 1 -fi -} +is_process_running() { +PROCESS="$1" -network_ok() { - print_text_in_color "$ICyan" "Testing if network is OK..." - service network-manager restart - if wget -q -T 20 -t 2 http://github.com -O /dev/null - then - return 0 +while : +do + RESULT=$(pgrep "${PROCESS}") + + if [ "${RESULT:-null}" = null ]; then + break else - return 1 + print_text_in_color "$ICyan" "${PROCESS} is running, waiting for it to stop..." + sleep 10 fi +done } -check_command() { - if ! "$@"; - then - print_text_in_color "$IRed" "Sorry but something went wrong. Please report this issue to $ISSUES and include the output of the error message. Thank you!" - print_text_in_color "$IRed" "$* failed" - exit 1 - fi -} - -# Colors -Color_Off='\e[0m' -IRed='\e[0;91m' -IGreen='\e[0;92m' -ICyan='\e[0;96m' +######### -print_text_in_color() { - printf "%b%s%b\n" "$1" "$2" "$Color_Off" -} +# Check if dpkg or apt is running +is_process_running apt +is_process_running dpkg -# END OF FUNCTIONS # +# shellcheck disable=2034,2059,1091 +true +SCRIPT_NAME="Wordpress Startup Script" +# shellcheck source=lib.sh +source /var/scripts/fetch_lib.sh # Check if root root_check @@ -82,104 +48,55 @@ root_check # Check network if network_ok then - printf "${IGreen}Online!${Color_Off}\n" + print_text_in_color "$IGreen" "Online!" else print_text_in_color "$ICyan" "Setting correct interface..." [ -z "$IFACE" ] && IFACE=$(lshw -c network | grep "logical name" | awk '{print $3; exit}') # Set correct interface -cat <<-SETDHCP > "/etc/netplan/01-netcfg.yaml" + cat <<-SETDHCP > "/etc/netplan/01-netcfg.yaml" network: version: 2 renderer: networkd ethernets: $IFACE: - dhcp4: yes - dhcp6: yes + dhcp4: true + dhcp6: true SETDHCP check_command netplan apply - check_command service network-manager restart - ip link set "$IFACE" down - wait - ip link set "$IFACE" up - wait - check_command service network-manager restart print_text_in_color "$ICyan" "Checking connection..." sleep 1 + set_systemd_resolved_dns "$IFACE" if ! nslookup github.com then -msg_box "The script failed to get an address from DHCP. + msg_box "The script failed to get an address from DHCP. You must have a working network connection to run this script. -You will now be provided with the option to set a static IP manually instead." - # Copy old interfaces files -msg_box "Copying old netplan.io config files file to: -/tmp/netplan_io_backup/" - if [ -d /etc/netplan/ ] - then - mkdir -p /tmp/netplan_io_backup - check_command cp -vR /etc/netplan/* /tmp/netplan_io_backup/ - fi +You will now be provided with the option to set a static IP manually instead." - # Ask for IP address -cat << ENTERIP -+----------------------------------------------------------+ -| Please enter the static IP address you want to set, | -| including the subnet. Example: 192.168.1.100/24 | -+----------------------------------------------------------+ -ENTERIP - echo - read -r LANIP - echo - - # Ask for gateway address -cat << ENTERGATEWAY -+----------------------------------------------------------+ -| Please enter the gateway address you want to set, | -| Example: 192.168.1.1 | -+----------------------------------------------------------+ -ENTERGATEWAY - echo - read -r GATEWAYIP - echo - - # Create the Static IP file -cat <<-IPCONFIG > /etc/netplan/01-netcfg.yaml -network: - version: 2 - renderer: networkd - ethernets: - $IFACE: #object name - dhcp4: no # dhcp v4 disable - dhcp6: no # dhcp v6 disable - addresses: [$LANIP] # client IP address - gateway4: $GATEWAYIP # gateway address - nameservers: - addresses: [9.9.9.9,149.112.112.112] #name servers -IPCONFIG - -msg_box "These are your settings, please make sure they are correct: -$(cat /etc/netplan/01-netcfg.yaml)" - netplan try + # Run static_ip script + bash /var/scripts/static_ip.sh fi fi # Check network again if network_ok then - printf "${IGreen}Online!${Color_Off}\n" + print_text_in_color "$IGreen" "Online!" else -msg_box "Network NOT OK. You must have a working network connection to run this script. + msg_box "Network NOT OK. You must have a working network connection to run this script. + Please contact us for support: https://shop.hanssonit.se/product/premium-support-per-30-minutes/ -Please also post this issue on: $ISSUES" + +Please also post this issue on: https://github.com/techandme/wordpress-vm/issues" exit 1 fi + +# shellcheck disable=2034,2059,1091 +true +SCRIPT_NAME="Wordpress startup script" # shellcheck source=lib.sh -WPDB=1 && MYCNFPW=1 && FIRST_IFACE=1 && CHECK_CURRENT_REPO=1 . <(curl -sL https://raw.githubusercontent.com/techandme/wordpress-vm/master/lib.sh) -unset FIRST_IFACE -unset CHECK_CURRENT_REPO -unset MYCNFPW -unset WPDB +source /var/scripts/fetch_lib.sh # Check for errors + debug code and abort if something isn't right # 1 = ON @@ -187,23 +104,45 @@ unset WPDB DEBUG=0 debug_mode +# Run the startup menu +run_script MENU startup_configuration + +######## The first setup is OK to run to this point several times, but not any further ######## +if [ -f "$SCRIPTS/you-can-not-run-the-startup-script-several-times" ] +then + msg_box "The $SCRIPT_NAME that handles the first setup \ +(this one) is desinged to be run once, not several times in a row. + +If you feel uncertain about adding some extra features during this setup, \ +then it's best to wait until after the first setup is done. You can always add all the extra features later. + +[For the Wordpress VM:] +Please delete this VM from your host and reimport it once again, then run this setup like you did the first time. + +Full documentation can be found here: https://docs.hanssonit.se +Please report any bugs you find here: $ISSUES" + exit 1 +fi + +touch "$SCRIPTS/you-can-not-run-the-startup-script-several-times" + print_text_in_color "$ICyan" "Getting scripts from GitHub to be able to run the first setup..." -# All the shell scripts in static (.sh) -download_static_script security -download_static_script update -download_static_script test_connection -download_static_script wp-permissions -download_static_script change_mysql_pass -download_static_script techandme -download_static_script index -download_le_script activate-ssl +# Scripts in static (.sh, .php, .py) +download_script LETS_ENC activate-tls +download_script STATIC update +download_script STATIC wp-permissions +download_script STATIC change_db_pass +download_script STATIC wordpress +download_script MENU menu +download_script MENU server_configuration +download_script MENU additional_apps # Make $SCRIPTS excutable chmod +x -R $SCRIPTS chown root:root -R $SCRIPTS # Allow wordpress to run figlet script -chown wordpress:wordpress $SCRIPTS/techandme.sh +chown "$UNIXUSER":"$UNIXUSER" $SCRIPTS/wordpress.sh clear msg_box"This script will do the final setup for you @@ -212,186 +151,96 @@ msg_box"This script will do the final setup for you - Set static IP - Create a new WP user - Upgrade the system -- Activate SSL (Let's Encrypt) +- Activate TLS (Let's Encrypt) - Install Adminer -- Change keyboard setup (current is Swedish) - Change system timezone - Set new password to the Linux system (user: wordpress) ############### T&M Hansson IT AB - $(date +"%Y") ###############" clear -# Set keyboard layout -print_text_in_color "$ICyan" "Current keyboard layout is $(localectl status | grep "Layout" | awk '{print $3}')" -if [[ "no" == $(ask_yes_or_no "Do you want to change keyboard layout?") ]] -then - print_text_in_color "$ICyan" "Not changing keyboard layout..." - sleep 1 - clear -else - dpkg-reconfigure keyboard-configuration -clear -fi - -# Change Timezone -print_text_in_color "$ICyan" "Current timezone is $(cat /etc/timezone)" -if [[ "no" == $(ask_yes_or_no "Do you want to change timezone?") ]] -then - print_text_in_color "$ICyan" "Not changing timezone..." - sleep 1 - clear -else - dpkg-reconfigure tzdata -clear -fi - -# Check where the best mirrors are and update -msg_box "To make downloads as fast as possible when updating you should have mirrors that are as close to you as possible. -This VM comes with mirrors based on servers in that where used when the VM was released and packaged. -If you are located outside of Europe, we recomend you to change the mirrors so that downloads are faster." -print_text_in_color "$ICyan" "Checking current mirror..." -print_text_in_color "$ICyan" "Your current server repository is: $REPO" - -if [[ "no" == $(ask_yes_or_no "Do you want to try to find a better mirror?") ]] -then - print_text_in_color "$ICyan" "Keeping $REPO as mirror..." - sleep 1 -else - print_text_in_color "$ICyan" "Locating the best mirrors..." - apt update -q4 & spinner_loading - apt install python-pip -y - pip install \ - --upgrade pip \ - apt-select - check_command apt-select -m up-to-date -t 5 -c -C "$(localectl status | grep "Layout" | awk '{print $3}')" - sudo cp /etc/apt/sources.list /etc/apt/sources.list.backup && \ - if [ -f sources.list ] - then - sudo mv sources.list /etc/apt/ - fi -fi -clear +msg_box "PLEASE NOTE: +[#] Please finish the whole setup. The server will reboot once done. +[#] Please read the on-screen instructions carefully, they will guide you through the setup. +[#] When complete it will delete all the *.sh, *.html, *.tar, *.zip inside: + /root + /home/$UNIXUSER +[#] Please consider donating if you like the product: + https://shop.hanssonit.se/product-category/donate/ +[#] You can also ask for help here: + https://shop.hanssonit.se/product/premium-support-per-30-minutes/" + +msg_box "PLEASE NOTE: +The first setup is meant to be run once, and not aborted. +If you feel uncertain about the options during the setup, just choose the defaults by hitting [ENTER] at each question. +When the setup is done, the server will automatically reboot. +Please report any issues to: $ISSUES" + +# Change timezone in PHP +sed -i "s|;date.timezone.*|date.timezone = $(cat /etc/timezone)|g" "$PHP_INI" # Generate new SSH Keys printf "\nGenerating new SSH keys for the server...\n" rm -v /etc/ssh/ssh_host_* dpkg-reconfigure openssh-server -# Generate new MARIADB password -print_text_in_color "$ICyan" "Generating new MARIADB password..." -if bash "$SCRIPTS/change_mysql_pass.sh" && wait -then - rm "$SCRIPTS/change_mysql_pass.sh" -fi -clear +# Generate new MariaDB password +print_text_in_color "$ICyan" "Generating new MariaDB password..." +check_command bash "$SCRIPTS/change_db_pass.sh" +sleep 3 -whiptail --title "Which apps do you want to install?" --checklist --separate-output "Automatically configure and install selected apps\nSelect by pressing the spacebar" "$WT_HEIGHT" "$WT_WIDTH" 4 \ -"Fail2ban" "(Extra Bruteforce protection) " OFF \ -"Webmin" "(Server GUI) " OFF \ -"Adminer" "(*SQL GUI) " OFF 2>results -while read -r -u 9 choice -do - case $choice in - Fail2ban) - run_app_script fail2ban +# Server configurations +bash $SCRIPTS/server_configuration.sh - ;; +# Install apps +bash $SCRIPTS/additional_apps.sh - Webmin) - run_app_script webmin - ;; +### Change passwords +# CLI USER +msg_box "For better security, we will now change the password for the CLI user in Ubuntu." +UNIXUSER="$(getent group sudo | cut -d: -f4 | cut -d, -f1)" +while : +do + UNIX_PASSWORD=$(input_box_flow "Please type in the new password for the current CLI user in Ubuntu: $UNIXUSER.") + if [[ "$UNIX_PASSWORD" == *" "* ]] + then + msg_box "Please don't use spaces." + else + break + fi +done +if check_command echo "$UNIXUSER:$UNIX_PASSWORD" | sudo chpasswd +then + msg_box "The new password for the current CLI user in Ubuntu ($UNIXUSER) is now set to: $UNIX_PASSWORD - Adminer) - run_app_script adminer - ;; +This is used when you login to the Ubuntu CLI." +fi +unset UNIX_PASSWORD - *) - ;; - esac -done 9< results -rm -f results -clear +# WORDPRESS USER +while : +do +msg_box "Please define the FQDN and create a new user for Wordpress. -# Extra configurations -whiptail --title "Extra configurations" --checklist --separate-output "Choose what you want to configure\nSelect by pressing the spacebar" "$WT_HEIGHT" "$WT_WIDTH" 4 \ -"Security" "(Add extra security based on this http://goo.gl/gEJHi7)" OFF \ -"Static IP" "(Set static IP in Ubuntu with netplan.io)" OFF 2>results +Make sure your FQDN starts with either http:// or https://, +otherwise your installation will not work correctly!" -while read -r -u 9 choice -do - case $choice in - "Security") - clear - run_static_script security - ;; - - "Static IP") - clear - run_static_script static_ip - ;; - - *) - ;; - esac -done 9< results -rm -f results -clear +FQDN=$(input_box_flow "Please enter your domain name or IP address, e.g: https://www.example.com or http://192.168.1.100.") +USER=$(input_box_flow "Please enter your Wordpress username.") +NEWWPADMINPASS=$(input_box_flow "Please enter your Wordpress password.") +EMAIL=$(input_box_flow "Please enter your Wordpress admin email address.") -# Change password -printf "${Color_Off}\n" -print_text_in_color "$ICyan" "For better security, change the system user password for [$(getent group sudo | cut -d: -f4 | cut -d, -f1)]" -any_key "Press any key to change password for system user..." -while true -do - sudo passwd "$(getent group sudo | cut -d: -f4 | cut -d, -f1)" && break -done -clear +if yesno_box_yes "Is this correct? -cat << LETSENC -+-----------------------------------------------+ -| The following script will install a trusted | -| SSL certificate through Let's Encrypt. | -+-----------------------------------------------+ -LETSENC -# Let's Encrypt -if [[ "yes" == $(ask_yes_or_no "Do you want to install SSL?") ]] +Domain or IP address: $FQDN +Wordpress user: $USER +Wordpress password: $NEWWPADMINPASS +Wordpress admin email: $EMAIL" then - bash $SCRIPTS/activate-ssl.sh -else - print_text_in_color "$ICyan" "OK, but if you want to run it later, just type: sudo bash $SCRIPTS/activate-ssl.sh" - any_key "Press any key to continue..." + break fi - -# Define FQDN and create new WP user -MYANSWER="no" -while [ "$MYANSWER" == "no" ] -do - clear - cat << ENTERNEW -+-----------------------------------------------+ -| Please define the FQDN and create a new | -| user for Wordpress. | -| Make sure your FQDN starts with either | -| http:// or https://, otherwise your | -| installation will not work correctly! | -+-----------------------------------------------+ -ENTERNEW - print_text_in_color "$IGreen" "Enter FQDN (http(s)://yourdomain.com):" - read -r FQDN - echo - print_text_in_color "$IGreen" "Enter username:" - read -r USER - echo - print_text_in_color "$IGreen" "Enter password:" - read -r NEWWPADMINPASS - echo - print_text_in_color "$IGreen" "Enter email address:" - read -r EMAIL - echo - MYANSWER=$(ask_yes_or_no "Is this correct? FQDN: $FQDN User: $USER Password: $NEWWPADMINPASS Email: $EMAIL") done -clear echo "$FQDN" > fqdn.txt wp_cli_cmd option update siteurl < fqdn.txt --path="$WPATH" @@ -409,9 +258,9 @@ echo "WP PASS: $NEWWPADMINPASS" # Change servername in Nginx server_name=$(echo "$FQDN" | cut -d "/" -f3) -sed -i "s|# server_name .*|server_name $server_name;|g" /etc/nginx/sites-available/wordpress_port_80.conf -sed -i "s|# server_name .*|server_name $server_name;|g" /etc/nginx/sites-available/wordpress_port_443.conf -check_command service nginx restart +sed -i "s|# server_name .*|server_name $server_name;|g" "$SITES_ENABLED"/"$HTTP_CONF" +sed -i "s|# server_name .*|server_name $server_name;|g" "$SITES_ENABLED"/"$TLS_CONF" +restart_webserver # Show current administrators echo @@ -420,46 +269,48 @@ wp_cli_cmd user list --role=administrator --path="$WPATH" any_key "Press any key to continue..." clear -# Fixes https://github.com/techandme/wordpress-vm/issues/58 -a2dismod status -service apache2 reload - # Cleanup 1 -rm -f "$SCRIPTS/ip.sh" -rm -f "$SCRIPTS/test_connection.sh" +rm -f "$SCRIPTS/change_db_pass.sh" rm -f "$SCRIPTS/instruction.sh" -rm -f "$SCRIPTS/wordpress-startup-script.sh" -find /root "/home/$UNIXUSER" -type f \( -name '*.sh*' -o -name '*.html*' -o -name '*.tar*' -o -name '*.zip*' \) -delete -sed -i "s|instruction.sh|techandme.sh|g" "/home/$UNIXUSER/.bash_profile" +rm -f "$SCRIPTS/static_ip.sh" +rm -f "$SCRIPTS/lib.sh" +rm -f "$SCRIPTS/server_configuration.sh" +rm -f "$SCRIPTS/additional_apps.sh" +rm -f "$SCRIPTS/adduser.sh" +find /root /home/"$UNIXUSER" -type f \( -name '*.sh*' -o -name '*.html*' -o -name '*.tar*' -o -name 'results' -o -name '*.zip*' \) -delete +find "$WPATH" -type f \( -name 'results' -o -name '*.sh*' \) -delete +sed -i "s|instruction.sh|wordpress.sh|g" /home/"$UNIXUSER"/.bash_profile truncate -s 0 \ /root/.bash_history \ "/home/$UNIXUSER/.bash_history" \ /var/spool/mail/root \ "/var/spool/mail/$UNIXUSER" \ - /var/log/apache2/access.log \ - /var/log/apache2/error.log \ + /var/log/nginx/access.log \ + /var/log/nginx/error.log \ /var/log/cronjobs_success.log -sed -i "s|sudo -i||g" "/home/$UNIXUSER/.bash_profile" -cat << RCLOCAL > "/etc/rc.local" -#!/bin/sh -e -# -# rc.local -# -# This script is executed at the end of each multiuser runlevel. -# Make sure that the script will "exit 0" on success or any other -# value on error. -# -# In order to enable or disable this script just change the execution -# bits. -# -# By default this script does nothing. - -exit 0 - -RCLOCAL -clear +sed -i "s|sudo -i||g" "$UNIXUSER_PROFILE" + +cat << ROOTNEWPROFILE > "$ROOT_PROFILE" +# ~/.profile: executed by Bourne-compatible login shells. +if [ "/bin/bash" ] +then + if [ -f ~/.bashrc ] + then + . ~/.bashrc + fi +fi +if [ -x /var/scripts/wordpress-startup-script.sh ] +then + /var/scripts/wordpress-startup-script.sh +fi +if [ -x /var/scripts/history.sh ] +then + /var/scripts/history.sh +fi +mesg n +ROOTNEWPROFILE # Upgrade system print_text_in_color "$ICyan" "System will now upgrade..." @@ -469,33 +320,34 @@ bash $SCRIPTS/update.sh apt autoremove -y apt autoclean -ADDRESS2=$(grep "server_name" /etc/nginx/sites-available/wordpress_port_80.conf | awk '$1 == "server_name" { print $2 }' | cut -d ";" -f1) -# Success! -clear -# Success! -msg_box "Congratulations! You have successfully installed Wordpress! -Login to Wordpress in your browser: -- IP: $ADDRESS -- Hostname: $(hostname -f) +# Remove preference for IPv4 +rm -f /etc/apt/apt.conf.d/99force-ipv4 +apt update -SUPPORT: -Please ask for help in the forums, or visit our shop to buy support, -https://shop.hanssonit.se/product/premium-support-per-30-minutes/ - -BUGS: -Please report any bugs here: https://github.com/techandme/wordpress-vm +# Success! +msg_box "The installation process is *almost* done. +Please hit OK in all the following prompts and let the server reboot to complete the installation process." -TIPS & TRICKS: +msg_box "TIPS & TRICKS: 1. Publish your server online: https://goo.gl/iUGE2U -2. To update this VM just type: sudo bash /var/scripts/update.sh -3. Change IP to something outside DHCP: sudo nano /etc/netplan/01-netcfg.yaml -4. To allow access to wp-login.php, please edit your nginx virtual hosts file. +3. To update this server just type: sudo bash /var/scripts/update.sh +4. Install apps, configure Wordpress, and server: sudo bash $SCRIPTS/menu.sh +5. To allow access to wp-login.php, please edit your nginx virtual hosts file. You can find it here: $HTTP_CONF - ######################### T&M Hansson IT - $(date +"%Y") ######################### " +BUGS & SUPPORT: +- SUPPORT: https://shop.hanssonit.se/product/premium-support-per-30-minutes/ +- BUGS: Please report any bugs here: $ISSUES" -# Prefer IPv6 -sed -i "s|precedence ::ffff:0:0/96 100|#precedence ::ffff:0:0/96 100|g" /etc/gai.conf +msg_box "Congratulations! You have successfully installed Wordpress! +LOGIN: +Login to Wordpress in your browser: +- IP: $ADDRESS +- Hostname: $(hostname -f) +### PLEASE HIT OK TO REBOOT ###" # Reboot +print_text_in_color "$IGreen" "Installation done, system will now reboot..." +check_command rm -f "$SCRIPTS/you-can-not-run-the-startup-script-several-times" +check_command rm -f "$SCRIPTS/wordpress-startup-script.sh" reboot diff --git a/wordpress_install.sh b/wordpress_install.sh index e1f9425..707e346 100644 --- a/wordpress_install.sh +++ b/wordpress_install.sh @@ -1,16 +1,60 @@ #!/bin/bash -# T&M Hansson IT AB © - 2019, https://www.hanssonit.se/ +# T&M Hansson IT AB © - 2020, https://www.hanssonit.se/ -# Prefer IPv4 -sed -i "s|#precedence ::ffff:0:0/96 100|precedence ::ffff:0:0/96 100|g" /etc/gai.conf +# Prefer IPv4 for apt +echo 'Acquire::ForceIPv4 "true";' >> /etc/apt/apt.conf.d/99force-ipv4 + +# Install curl if not existing +if [ "$(dpkg-query -W -f='${Status}' "curl" 2>/dev/null | grep -c "ok installed")" == "1" ] +then + echo "curl OK" +else + apt update -q4 + apt install curl -y +fi # shellcheck disable=2034,2059 true +SCRIPT_NAME="Wordpress Install Script" # shellcheck source=lib.sh -FIRST_IFACE=1 && CHECK_CURRENT_REPO=1 . <(curl -sL https://raw.githubusercontent.com/techandme/wordpress-vm/master/lib.sh) -unset FIRST_IFACE -unset CHECK_CURRENT_REPO +source <(curl -sL https://raw.githubusercontent.com/techandme/wordpress-vm/master/lib.sh) + +# Check if dpkg or apt is running +is_process_running apt +is_process_running dpkg + +# Install lshw if not existing +if [ "$(dpkg-query -W -f='${Status}' "lshw" 2>/dev/null | grep -c "ok installed")" == "1" ] +then + print_text_in_color "$IGreen" "lshw OK" +else + apt update -q4 & spinner_loading + apt install lshw -y +fi + +# Install net-tools if not existing +if [ "$(dpkg-query -W -f='${Status}' "net-tools" 2>/dev/null | grep -c "ok installed")" == "1" ] +then + print_text_in_color "$IGreen" "net-tools OK" +else + apt update -q4 & spinner_loading + apt install net-tools -y +fi + +# Install whiptail if not existing +if [ "$(dpkg-query -W -f='${Status}' "whiptail" 2>/dev/null | grep -c "ok installed")" == "1" ] +then + print_text_in_color "$IGreen" "whiptail OK" +else + apt update -q4 & spinner_loading + apt install whiptail -y +fi + +# shellcheck disable=2034,2059 +true +# shellcheck source=lib.sh +source <(curl -sL https://raw.githubusercontent.com/techandme/wordpress-vm/master/lib.sh) # Check for errors + debug code and abort if something isn't right # 1 = ON @@ -19,38 +63,66 @@ DEBUG=0 debug_mode # Check if root -if ! is_root -then - printf "\n${Red}Sorry, you are not root.\n${Color_Off}You must type: ${Cyan}sudo ${Color_Off}bash %s/wordpress_install.sh\n" "$SCRIPTS" - exit 1 -fi +root_check # Test RAM size (2GB min) + CPUs (min 1) -ram_check 1 Wordpress +ram_check 2 Wordpress cpu_check 1 Wordpress +# Download needed libraries before execution of the first script +mkdir -p "$SCRIPTS" +download_script GITHUB_REPO lib +download_script STATIC fetch_lib + # Set locales -apt install language-pack-en-base -y -sudo locale-gen "sv_SE.UTF-8" && sudo dpkg-reconfigure --frontend=noninteractive locales +run_script ADDONS locales -# Show current user -download_static_script adduser +# Create new current user +download_script STATIC adduser bash $SCRIPTS/adduser.sh "wordpress_install.sh" -rm $SCRIPTS/adduser.sh +rm -f $SCRIPTS/adduser.sh -# Check Ubuntu version -print_text_in_color "$ICyan" "Checking server OS and version..." -if [ "$OS" != 1 ] +# Check distribution and version +if ! version 20.04 "$DISTRO" 20.04.6 then - print_text_in_color "$IRed" "Ubuntu Server is required to run this script." - print_text_in_color "$IRed" "Please install that distro and try again." + msg_box "This script can only be run on Ubuntu 20.04 (server)." exit 1 fi +# Use this when Ubuntu 18.04 is deprecated from the function: +#check_distro_version +check_universe +check_multiverse - -if ! version 18.04 "$DISTRO" 18.04.4; then - print_text_in_color "$IRed" "Ubuntu version $DISTRO must be between 18.04 - 18.04.4" - exit +# Fix LVM on BASE image +if grep -q "LVM" /etc/fstab +then + if yesno_box_yes "Do you want to make all free space available to your root partition?" + then + # Resize LVM (live installer is &%¤%/! + # VM + print_text_in_color "$ICyan" "Extending LVM, this may take a long time..." + lvextend -l +100%FREE /dev/ubuntu-vg/ubuntu-lv + + # Run it again manually just to be sure it's done + while : + do + lvdisplay | grep "Size" | awk '{print $3}' + if ! lvextend -L +10G /dev/ubuntu-vg/ubuntu-lv >/dev/null 2>&1 + then + if ! lvextend -L +1G /dev/ubuntu-vg/ubuntu-lv >/dev/null 2>&1 + then + if ! lvextend -L +100M /dev/ubuntu-vg/ubuntu-lv >/dev/null 2>&1 + then + if ! lvextend -L +1M /dev/ubuntu-vg/ubuntu-lv >/dev/null 2>&1 + then + resize2fs /dev/ubuntu-vg/ubuntu-lv + break + fi + fi + fi + fi + done + fi fi # Check if it's a clean server @@ -58,6 +130,12 @@ stop_if_installed postgresql stop_if_installed apache2 stop_if_installed nginx stop_if_installed php +stop_if_installed php-fpm +stop_if_installed php"$PHPVER"-fpm +stop_if_installed php7.0-fpm +stop_if_installed php7.1-fpm +stop_if_installed php7.2-fpm +stop_if_installed php7.3-fpm stop_if_installed mysql-common stop_if_installed mariadb-server @@ -67,86 +145,82 @@ then mkdir -p "$SCRIPTS" fi -# Change DNS -install_if_not resolvconf -yes | dpkg-reconfigure --frontend=noninteractive resolvconf -echo "nameserver 9.9.9.9" > /etc/resolvconf/resolv.conf.d/base -echo "nameserver 149.112.112.112" >> /etc/resolvconf/resolv.conf.d/base - -# Check network -test_connection - -# Check where the best mirrors are and update -print_text_in_color "$ICyan" "Your current server repository is: $REPO" -if [[ "no" == $(ask_yes_or_no "Do you want to try to find a better mirror?") ]] -then - print_text_in_color "$ICyan" "Keeping $REPO as mirror..." - sleep 1 -else - print_text_in_color "$ICyan" "Locating the best mirrors..." - apt update -q4 & spinner_loading - apt install python-pip -y - pip install \ - --upgrade pip \ - apt-select - apt-select -m up-to-date -t 5 -c - sudo cp /etc/apt/sources.list /etc/apt/sources.list.backup && \ - if [ -f sources.list ] - then - sudo mv sources.list /etc/apt/ - fi -fi -clear - -# Set keyboard layout -print_text_in_color "$ICyan" "Current keyboard layout is $(localectl status | grep "Layout" | awk '{print $3}')" -if [[ "no" == $(ask_yes_or_no "Do you want to change keyboard layout?") ]] +# Create $VMLOGS dir +if [ ! -d "$VMLOGS" ] then - print_text_in_color "$ICyan" "Not changing keyboard layout..." - sleep 1 - clear -else - dpkg-reconfigure keyboard-configuration - clear + mkdir -p "$VMLOGS" fi -# Update system -apt update -q4 & spinner_loading +# Install needed network +install_if_not netplan.io + +# Install build-essentials to get make +install_if_not build-essential + +# Set DNS resolver +# https://unix.stackexchange.com/questions/442598/how-to-configure-systemd-resolved-and-systemd-networkd-to-use-local-dns-server-f +while : +do +choice=$(whiptail --title "$TITLE - Set DNS Resolver" --menu \ +"Which DNS provider should this Wordpress server use? +$MENU_GUIDE" "$WT_HEIGHT" "$WT_WIDTH" 4 \ +"Quad9" "(https://www.quad9.net/)" \ +"Cloudflare" "(https://www.cloudflare.com/dns/)" \ +"Local" "($GATEWAY) - DNS on gateway" 3>&1 1>&2 2>&3) + + case "$choice" in + "Quad9") + sed -i "s|^#\?DNS=.*$|DNS=9.9.9.9 149.112.112.112 2620:fe::fe 2620:fe::9|g" /etc/systemd/resolved.conf + ;; + "Cloudflare") + sed -i "s|^#\?DNS=.*$|DNS=1.1.1.1 1.0.0.1 2606:4700:4700::1111 2606:4700:4700::1001|g" /etc/systemd/resolved.conf + ;; + "Local") + sed -i "s|^#\?DNS=.*$|DNS=$GATEWAY|g" /etc/systemd/resolved.conf + if network_ok + then + break + else + msg_box "Could not validate the local DNS server. Pick an Internet DNS server and try again." + continue + fi + ;; + *) + ;; + esac + if test_connection + then + break + else + msg_box "Could not validate the DNS server. Please try again." + fi +done # Install dependencies for GEO-block in Nginx -install_if_not geoip-database -install_if_not libgeoip1 - -# Write MARIADB pass to file and keep it safe -{ -echo "[client]" -echo "password='$MARIADB_PASS'" -} > "$MYCNF" -chmod 0600 $MYCNF -chown root:root $MYCNF - -# Install MARIADB -apt install software-properties-common -y -sudo apt-key adv --recv-keys --keyserver hkp://keyserver.ubuntu.com:80 0xF1656F24C74CD1D8 -sudo add-apt-repository 'deb [arch=amd64,i386,ppc64el] http://ftp.ddg.lth.se/mariadb/repo/10.2/ubuntu xenial main' -sudo debconf-set-selections <<< "mariadb-server-10.2 mysql-server/root_password password $MARIADB_PASS" -sudo debconf-set-selections <<< "mariadb-server-10.2 mysql-server/root_password_again password $MARIADB_PASS" +# TODO: https://linuxhint.com/nginx_block_geo_location/ +#install_if_not geoip-database +#install_if_not libgeoip1 + +# Install MariDB repos +install_if_not software-properties-common +curl -LsS https://downloads.mariadb.com/MariaDB/mariadb_repo_setup | sudo bash -s -- --mariadb-server-version="mariadb-10.5" --skip-maxscale +# Avoid i386 since we use x64 +sed -i "s|deb http|deb [arch=amd64] http|g" /etc/apt/sources.list.d/mariadb.list +# USed debconf to install it +sudo debconf-set-selections <<< "mariadb-server-10.5 mysql-server/root_password password $MARIADB_PASS" +sudo debconf-set-selections <<< "mariadb-server-10.5 mysql-server/root_password_again password $MARIADB_PASS" apt update -q4 & spinner_loading -check_command apt install mariadb-server-10.2 -y - -# Prepare for Wordpress installation -# https://blog.v-gar.de/2017/02/en-solved-error-1698-28000-in-mysqlmariadb/ -mysql -u root mysql -p"$MARIADB_PASS" -e "UPDATE user SET plugin='' WHERE user='root';" -mysql -u root mysql -p"$MARIADB_PASS" -e "UPDATE user SET password=PASSWORD('$MARIADB_PASS') WHERE user='root';" -mysql -u root -p"$MARIADB_PASS" -e "flush privileges;" +install_if_not mariadb-server-10.5 # mysql_secure_installation -apt -y install expect +install_if_not expect SECURE_MYSQL=$(expect -c " set timeout 10 spawn mysql_secure_installation expect \"Enter current password for root (enter for none):\" send \"$MARIADB_PASS\r\" +expect \"Switch to unix_socket authentication?\" +send \"y\r\" expect \"Change the root password?\" send \"n\r\" expect \"Remove anonymous users?\" @@ -163,10 +237,10 @@ echo "$SECURE_MYSQL" apt -y purge expect # Write a new MariaDB config -run_static_script new_etc_mycnf +run_script STATIC new_etc_mycnf # Install VM-tools -apt install open-vm-tools -y +install_if_not open-vm-tools # Install Nginx check_command yes | add-apt-repository ppa:nginx/stable @@ -178,9 +252,9 @@ sudo systemctl enable nginx.service # Download TLSv 1.3 modified nginx.conf rm -f /etc/nginx/nginx.conf -check_command wget -q $STATIC/nginx.conf -P /etc/nginx/ +curl_to_dir "$STATIC" nginx.conf /etc/nginx/ -# Install PHP 7.2 +# Install PHP 7.4 apt install -y \ php \ php"$PHPVER"-fpm \ @@ -193,24 +267,44 @@ apt install -y \ php"$PHPVER"-cli \ php"$PHPVER"-zip \ php"$PHPVER"-curl - + # Configure PHP -sed -i "s|allow_url_fopen =.*|allow_url_fopen = On|g" /etc/php/"$PHPVER"/fpm/php.ini -sed -i "s|max_execution_time =.*|max_execution_time = 360|g" /etc/php/"$PHPVER"/fpm/php.ini -sed -i "s|file_uploads =.*|file_uploads = On|g" /etc/php/"$PHPVER"/fpm/php.ini -sed -i "s|upload_max_filesize =.*|upload_max_filesize = 100M|g" /etc/php/"$PHPVER"/fpm/php.ini -sed -i "s|memory_limit =.*|memory_limit = 256M|g" /etc/php/"$PHPVER"/fpm/php.ini -sed -i "s|post_max_size =.*|post_max_size = 110M|g" /etc/php/"$PHPVER"/fpm/php.ini -sed -i "s|cgi.fix_pathinfo =.*|cgi.fix_pathinfo=0|g" /etc/php/"$PHPVER"/fpm/php.ini -sed -i "s|date.timezone =.*|date.timezone = Europe/Stockholm|g" /etc/php/"$PHPVER"/fpm/php.ini +sed -i "s|allow_url_fopen =.*|allow_url_fopen = On|g" "$PHP_INI" +sed -i "s|max_execution_time =.*|max_execution_time = 360|g" "$PHP_INI" +sed -i "s|file_uploads =.*|file_uploads = On|g" "$PHP_INI" +sed -i "s|upload_max_filesize =.*|upload_max_filesize = 100M|g" "$PHP_INI" +sed -i "s|memory_limit =.*|memory_limit = 256M|g" "$PHP_INI" +sed -i "s|post_max_size =.*|post_max_size = 110M|g" "$PHP_INI" +sed -i "s|cgi.fix_pathinfo =.*|cgi.fix_pathinfo=0|g" "$PHP_INI" +sed -i "s|date.timezone =.*|date.timezone = Europe/Stockholm|g" "$PHP_INI" + +# Enable OPCache for PHP +phpenmod opcache +{ +echo "# OPcache settings for Wordpress" +echo "opcache.enable=1" +echo "opcache.enable_cli=1" +echo "opcache.interned_strings_buffer=8" +echo "opcache.max_accelerated_files=10000" +echo "opcache.memory_consumption=256" +echo "opcache.save_comments=1" +echo "opcache.revalidate_freq=1" +echo "opcache.validate_timestamps=1" +} >> "$PHP_INI" + +# PHP-FPM optimization +# https://geekflare.com/php-fpm-optimization/ +sed -i "s|;emergency_restart_threshold.*|emergency_restart_threshold = 10|g" /etc/php/"$PHPVER"/fpm/php-fpm.conf +sed -i "s|;emergency_restart_interval.*|emergency_restart_interval = 1m|g" /etc/php/"$PHPVER"/fpm/php-fpm.conf +sed -i "s|;process_control_timeout.*|process_control_timeout = 10|g" /etc/php/"$PHPVER"/fpm/php-fpm.conf # Make sure the passwords are the same, this file will be deleted when redis is run. check_command echo "$REDIS_PASS" > $REDISPTXT -# Install Redis -run_static_script redis-server-ubuntu +# Install Redis (distrubuted cache) +run_script ADDONS redis-server-ubuntu -# Enable igbinary for PHP +# Enable igbinary for PHP # https://github.com/igbinary/igbinary if is_this_installed "php$PHPVER"-dev then @@ -226,7 +320,7 @@ echo "# igbinary for PHP" echo "extension=igbinary.so" echo "session.serialize_handler=igbinary" echo "igbinary.compact_strings=On" -} >> $PHP_INI +} >> "$PHP_INI" restart_webserver fi @@ -237,18 +331,19 @@ then then msg_box "APCu PHP module installation failed" exit - else + else print_text_in_color "$IGreen" "APCu PHP module installation OK!" fi { echo "# APCu settings for Wordpress" echo "extension=apcu.so" echo "apc.enabled=1" +echo "apc.max_file_size=5M" echo "apc.shm_segments=1" -echo "apc.shm_size=32M" +echo "apc.shm_size=128M" echo "apc.entries_hint=4096" -echo "apc.ttl=0" -echo "apc.gc_ttl=3600" +echo "apc.ttl=3600" +echo "apc.gc_ttl=7200" echo "apc.mmap_file_mask=NULL" echo "apc.slam_defense=1" echo "apc.enable_cli=1" @@ -256,7 +351,7 @@ echo "apc.use_request_time=1" echo "apc.serializer=igbinary" echo "apc.coredump_unmap=0" echo "apc.preload_path" -} >> $PHP_INI +} >> "$PHP_INI" restart_webserver fi @@ -268,21 +363,21 @@ mv wp-cli.phar /usr/local/bin/wp # Add www-data in sudoers { echo "# WP-CLI" -echo "$SUDO_USER ALL=(www-data) NOPASSWD: /usr/local/bin/wp" +echo "$UNIXUSER ALL=(www-data) NOPASSWD: /usr/local/bin/wp" echo "root ALL=(www-data) NOPASSWD: /usr/local/bin/wp" } >> /etc/sudoers # Create dir mkdir -p "$WPATH" chown -R www-data:www-data "$WPATH" -if [ ! -d /home/"$SUDO_USER"/.wp-cli ] +if [ ! -d /home/"$UNIXUSER"/.wp-cli ] then - mkdir -p /home/"$SUDO_USER"/.wp-cli/ - chown -R www-data:www-data /home/"$SUDO_USER"/.wp-cli/ + mkdir -p /home/"$UNIXUSER"/.wp-cli/ + chown -R www-data:www-data /home/"$UNIXUSER"/.wp-cli/ fi # Create wp-cli.yml -touch $WPATH/wp-cli.yml +touch "$WPATH/wp-cli.yml" cat << YML_CREATE > "$WPATH/wp-cli.yml" nginx_modules: - mod_rewrite @@ -292,8 +387,7 @@ YML_CREATE wp_cli_cmd --info # Download Wordpress -cd "$WPATH" -check_command wp_cli_cmd core download --force --debug --path="$WPATH" +check_command wp_cli_cmd core download --force --debug # Populate DB mysql -uroot -p"$MARIADB_PASS" < /var/adminpass.txt -chown wordpress:wordpress /var/adminpass.txt +chown "$UNIXUSER":"$UNIXUSER" /var/adminpass.txt # Create welcome post -check_command wget -q $STATIC/welcome.txt -sed -i "s|wordpress_user_login|$WPADMINUSER|g" welcome.txt -sed -i "s|wordpress_password_login|$WPADMINPASS|g" welcome.txt -wp_cli_cmd post create ./welcome.txt --post_title='T&M Hansson IT AB - Welcome' --post_status=publish --path=$WPATH -rm -f welcome.txt +curl_to_dir "$STATIC" welcome.txt "$SCRIPTS" +sed -i "s|wordpress_user_login|$WPADMINUSER|g" "$SCRIPTS"/welcome.txt +sed -i "s|wordpress_password_login|$WPADMINPASS|g" "$SCRIPTS"/welcome.txt +wp_cli_cmd post create "$SCRIPTS"/welcome.txt --post_title='T&M Hansson IT AB - Welcome' --post_status=publish +rm -f "$SCRIPTS"/welcome.txt wp_cli_cmd post delete 1 --force # Show version @@ -359,11 +453,11 @@ wp_cli_cmd plugin delete akismet wp_cli_cmd plugin delete hello # Secure permissions -run_static_script wp-permissions +run_script STATIC wp-permissions # Hardening security # create .htaccess to protect uploads directory -cat > $WPATH/wp-content/uploads/.htaccess <<'EOL' +cat > "$WPATH/wp-content/uploads/.htaccess" <<'EOL' # Protect this file Order Deny,Allow @@ -392,22 +486,22 @@ echo "RewriteRule ^wp-includes/js/tinymce/langs/.+\.php - [F,L]" echo "RewriteRule ^wp-includes/theme-compat/ - [F,L]" echo "# RewriteRule ^wp-includes/* - [F,L]" # Block EVERYTHING echo "" -} >> $WPATH/.htaccess +} >> "$WPATH/.htaccess" # Set up a php-fpm pool with a unixsocket -cat << POOL_CONF > "$PHP_POOL_DIR/Wordpress.conf" -[www_wordpress] +cat << POOL_CONF > "$PHP_POOL_DIR"/wordpress.conf +[Wordpress] user = www-data group = www-data listen = $PHP_FPM_SOCK listen.owner = www-data listen.group = www-data pm = dynamic -pm.max_children = 17 -pm.start_servers = 5 +; max_children is set dynamically with calculate_php_fpm() +pm.max_children = 22 +pm.start_servers = 9 pm.min_spare_servers = 2 -pm.max_spare_servers = 10 -pm.max_requests = 500 +pm.max_spare_servers = 11 env[HOSTNAME] = $(hostname -f) env[PATH] = /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin env[TMP] = /tmp @@ -415,32 +509,38 @@ env[TMPDIR] = /tmp env[TEMP] = /tmp security.limit_extensions = .php php_admin_value [cgi.fix_pathinfo] = 1 + +; Optional +; pm.max_requests = 2000 POOL_CONF -# Disable regular pool -mv $PHP_POOL_DIR/www.conf $PHP_POOL_DIR/default_www.config +# Disable the idling example pool. +mv "$PHP_POOL_DIR"/www.conf "$PHP_POOL_DIR"/www.conf.backup + +# Enable the new php-fpm config +restart_webserver # Force wp-cron.php (updates WooCommerce Services and run Scheluded Tasks) -if [ -f $WPATH/wp-cron.php ] +if [ -f "$WPATH/wp-cron.php" ] then - chmod +x $WPATH/wp-cron.php + chmod +x "$WPATH/wp-cron.php" crontab -u www-data -l | { cat; echo "14 */1 * * * php -f $WPATH/wp-cron.php > /dev/null 2>&1"; } | crontab -u www-data - fi # Install Figlet -apt install figlet -y +install_if_not figlet # Generate $SSL_CONF install_if_not ssl-cert systemctl stop nginx.service && wait -if [ ! -f $SSL_CONF ]; - then - touch $SSL_CONF - cat << SSL_CREATE > $SSL_CONF +if [ ! -f $SITES_AVAILABLE/$TLS_CONF ] +then + touch "$SITES_AVAILABLE/$TLS_CONF" + cat << TLS_CREATE > "$SITES_AVAILABLE/$TLS_CONF" server { listen 443 ssl http2; listen [::]:443 ssl http2; - + ## Your website name goes here. # server_name example.com; ## Your only path reference. @@ -449,14 +549,14 @@ server { index index.php; resolver $GATEWAY; - + ## Show real IP behind proxy (change to the proxy IP) # set_real_ip_from $GATEWAY/24; # set_real_ip_from $GATEWAY; # set_real_ip_from 2001:0db8::/32; # real_ip_header X-Forwarded-For; # real_ip_recursive on; - + # certs sent to the client in SERVER HELLO are concatenated in ssl_certificate ssl_certificate /etc/ssl/certs/ssl-cert-snakeoil.pem; ssl_certificate_key /etc/ssl/private/ssl-cert-snakeoil.key; @@ -483,14 +583,13 @@ server { ## verify chain of trust of OCSP response using Root CA and Intermediate certs # ssl_trusted_certificate /path/to/root_CA_cert_plus_intermediates; - location / { - try_files \$uri \$uri/ /index.php?\$args; + try_files \$uri \$uri/ /index.php?\$args; } - + location ~ /\\. { access_log off; - log_not_found off; + log_not_found off; deny all; } @@ -513,7 +612,7 @@ server { deny all; include fastcgi.conf; fastcgi_intercept_errors on; - fastcgi_pass unix:/var/run/php/php7.2-fpm-wordpress.sock; + fastcgi_pass unix:$PHP_FPM_SOCK; } fastcgi_split_path_info ^(.+\.php)(/.+)$; try_files \$uri =404; @@ -533,20 +632,20 @@ server { log_not_found off; } } -SSL_CREATE -print_text_in_color "$IGreen" "$SSL_CONF was successfully created" +TLS_CREATE +print_text_in_color "$IGreen" "$TLS_CONF was successfully created" sleep 1 fi # Generate $HTTP_CONF -if [ ! -f $HTTP_CONF ]; - then - touch $HTTP_CONF - cat << HTTP_CREATE > $HTTP_CONF +if [ ! -f $SITES_AVAILABLE/$HTTP_CONF ] +then + touch "$SITES_AVAILABLE/$HTTP_CONF" + cat << HTTP_CREATE > "$SITES_AVAILABLE/$HTTP_CONF" server { listen 80; listen [::]:80; - + ## Your website name goes here. # server_name example.com; ## Your only path reference. @@ -555,21 +654,21 @@ server { index index.php; resolver $GATEWAY; - + ## Show real IP behind proxy (change to the proxy IP) # set_real_ip_from $GATEWAY/24; # set_real_ip_from $GATEWAY; # set_real_ip_from 2001:0db8::/32; # real_ip_header X-Forwarded-For; # real_ip_recursive on; - + location / { - try_files \$uri \$uri/ /index.php?\$args; + try_files \$uri \$uri/ /index.php?\$args; } - + location ~ /\\. { access_log off; - log_not_found off; + log_not_found off; deny all; } @@ -583,7 +682,7 @@ server { log_not_found off; access_log off; } - + location ~* \.php$ { location ~ \wp-login.php$ { allow $GATEWAY/24; @@ -592,7 +691,7 @@ server { deny all; include fastcgi.conf; fastcgi_intercept_errors on; - fastcgi_pass unix:/var/run/php/php7.2-fpm-wordpress.sock; + fastcgi_pass unix:$PHP_FPM_SOCK; } fastcgi_split_path_info ^(.+\.php)(/.+)$; try_files \$uri =404; @@ -634,7 +733,7 @@ events { multi_accept on; use epoll; } - + http { ## @@ -682,7 +781,7 @@ http { # gzip_proxied any; # gzip_comp_level 6; gzip_buffers 16 4k; - # gzip_http_version 1.1; + # gzip_http_version 1.1; # gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript; ## @@ -700,17 +799,17 @@ http { #mail { # # See sample authentication script at: # # http://wiki.nginx.org/ImapAuthenticateWithApachePhpScript -# +# # # auth_http localhost/auth.php; # # pop3_capabilities "TOP" "USER"; # # imap_capabilities "IMAP4rev1" "UIDPLUS"; -# +# # server { # listen localhost:110; # protocol pop3; # proxy on; # } -# +# # server { # listen localhost:143; # protocol imap; @@ -726,7 +825,7 @@ fi if [ -f "$NGINX_DEF" ]; then rm -f $NGINX_DEF - rm -f /etc/nginx/sites-enabled/default + rm -f "$SITES_ENABLED"/default touch $NGINX_DEF cat << NGINX_DEFAULT > "$NGINX_DEF" ## @@ -791,10 +890,10 @@ sleep 1 fi # Enable new config -ln -s "$NGINX_DEF" /etc/nginx/sites-enabled/ -ln -s "$SSL_CONF" /etc/nginx/sites-enabled/ -ln -s "$HTTP_CONF" /etc/nginx/sites-enabled/ -systemctl restart nginx.service +ln -s "$NGINX_DEF" "$SITES_ENABLED"/default +ln -s "$SITES_AVAILABLE"/"$TLS_CONF" "$SITES_ENABLED"/"$TLS_CONF" +ln -s "$SITES_AVAILABLE"/"$HTTP_CONF" "$SITES_ENABLED"/"$HTTP_CONF" +restart_webserver # Enable UTF8mb4 (4-byte support) databases=$(mysql -u root -p"$MARIADB_PASS" -e "SHOW DATABASES;" | tr -d "| " | grep -v Database) @@ -806,67 +905,43 @@ for db in $databases; do fi done -# Enable OPCache for PHP -phpenmod opcache -{ -echo "# OPcache settings for Wordpress" -echo "opcache.enable=1" -echo "opcache.enable_cli=1" -echo "opcache.interned_strings_buffer=8" -echo "opcache.max_accelerated_files=10000" -echo "opcache.memory_consumption=128" -echo "opcache.save_comments=1" -echo "opcache.revalidate_freq=1" -echo "opcache.validate_timestamps=1" -} >> /etc/php/"$PHPVER"/fpm/php.ini - -# Set secure permissions final -run_static_script wp-permissions +# Put IP adress in /etc/issue (shown before the login) +if [ -f /etc/issue ] +then + echo "\4" >> /etc/issue +fi -# Prepare for first mount -download_static_script instruction -download_static_script history -run_static_script change-root-profile -run_static_script change-wordpress-profile -if [ ! -f "$SCRIPTS"/wordpress-startup-script.sh ] +# Force MOTD to show correct number of updates +if is_this_installed update-notifier-common then -check_command wget -q "$GITHUB_REPO"/wordpress-startup-script.sh -P "$SCRIPTS" + sudo /usr/lib/update-notifier/update-motd-updates-available --force fi +# It has to be this order: +# Download scripts +# chmod +x +# Set permissions for ncadmin in the change scripts + +# Get needed scripts for first bootup +download_script GITHUB_REPO wordpress-startup-script +download_script STATIC instruction +download_script STATIC history +download_script NETWORK static_ip + # Make $SCRIPTS excutable chmod +x -R "$SCRIPTS" chown root:root -R "$SCRIPTS" -# Allow wordpress to run theese scripts -chown wordpress:wordpress "$SCRIPTS/instruction.sh" -chown wordpress:wordpress "$SCRIPTS/history.sh" - -# Upgrade -apt dist-upgrade -y +# Prepare first bootup +run_script STATIC change-wordpress-profile +run_script STATIC change-root-profile -# Remove LXD (always shows up as failed during boot) -apt purge lxd -y - -# Cleanup -apt autoremove -y -apt autoclean -find /root "/home/$UNIXUSER" -type f \( -name '*.sh*' -o -name '*.html*' -o -name '*.tar*' -o -name '*.zip*' \) -delete - -# Install virtual kernels for Hyper-V -# Kernel 4.15 -apt install -y --install-recommends \ -linux-virtual \ -linux-tools-virtual \ -linux-cloud-tools-virtual \ -linux-image-virtual \ -linux-image-extra-virtual - -# Force MOTD to show correct number of updates -sudo /usr/lib/update-notifier/update-motd-updates-available --force - -# Prefer IPv6 -sed -i "s|precedence ::ffff:0:0/96 100|#precedence ::ffff:0:0/96 100|g" /etc/gai.conf +# Disable hibernation +print_text_in_color "$ICyan" "Disable hibernation..." +systemctl mask sleep.target suspend.target hibernate.target hybrid-sleep.target # Reboot -print_text_in_color "$IGreen" "Installation done, system will now reboot..." +msg_box "Installation almost done, system will reboot when you hit OK. + +Please log in again once rebooted to run the setup script." reboot