#!/bin/bash
#
# LAMP management script for Debian-based distributions.
# Script can be used to:
# 1) setup LAMP development environment (install and configure of all the necessery services);
# 2) install and configure additional PHP versions;
# 3) add or remove virtual hosts by creating or removing all the necessary directories and configuration;
# 4) change php version for an active virtual host;
# 5) restart web services (apache, php, mysql-server)
# More info:  https://xconfig.me/lamp-setup-and-management-script-for-ubuntu
# Author: https://xconfig.me/author/filex/
# Version: 0.1
#
if [ ! -x "$( command -v apt-get )" ];
    then
    printf "\nThe script has been written for Ubuntu 20.04 LTS. It required Debian-based system.\n" && exit;
fi
#
printf "\nYou are running LAMP management script for development environment.\n\nType in your sudo password.\n"
user="$(whoami)"
#
if [ "$user" == "root" ];
    then
    printf "\nScript should be executed by regular user account.\n" && exit;
fi
#
sudo printf "Password is correct.\n\n"
phpversions=(5.6 7.0 7.1 7.2 7.3 7.4)
#
# MENU
printf "\nChoose desired action.\n\n"
PS3="Select an option: "
options=("Setup LAMP development environment" "Add aditional PHP version to the LAMP environment" "Add or remove Virtual Host - website" "Change Virtual Host's PHP verson" "Restart web services" "Exit")
select i in "${options[@]}"
do
    case $i in
        "Setup LAMP development environment")
            #
            ## LAMP setup
            #
            printf "CAUTION: Any previously installed apache, mysql and php services (along with their configuration) will be removed.\nAll MySQL databases will be removed as well.\n\n To continue setup, type in \"proceed\"\n"
            read lamsetup
            #
            if [ "$lamsetup" == "proceed" ];
                then lampproceed=true
                else lampproceed=false
            fi
            #
            if ( $lampproceed );
                then
                # Remove all services
                sudo apt-get -y remove --purge apache2 mysql-common mysql-server mysql-client mysql* php php-*;
                sudo rm -rf /etc/apache2 && sudo rm -rf /etc/php && sudo rm -rf /etc/mysql && sudo rm -rf /var/lib/mysql;
                #
                # Install services
                sudo add-apt-repository -y ppa:ondrej/php && sudo apt-get update;
                sudo apt-get install -y apache2 mysql-common mysql-server mysql-client php7.4-fpm php7.4-common php7.4-mysql php7.4-xml php7.4-xmlrpc php7.4-curl php7.4-gd php7.4-imagick php7.4-cli php7.4-dev php7.4-imap php7.4-mbstring php7.4-soap php7.4-zip php7.4-bcmath;
                #
                # Configure services
                poolfpm="/etc/php/7.4/fpm/pool.d/${user}.conf";
                sudo a2enmod rewrite proxy proxy_fcgi setenvif && sudo a2enconf php7.4-fpm && sudo mysql -e "ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY '';";
                sudo bash -c "cat > ${poolfpm} << EOF
[${user}]

user = ${user}
group = ${user}

listen = /run/php/php7.4-fpm-${user}.sock

listen.owner = www-data
listen.group = www-data

pm = dynamic
pm.max_children = 5
pm.start_servers = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 3


EOF";
                sudo sed -i 's/post_max_size = 8M/post_max_size = 500M/g' /etc/php/7.4/fpm/php.ini && sudo sed -i 's/max_execution_time = 30/max_execution_time = 180/g' /etc/php/7.4/fpm/php.ini && sudo sed -i 's/memory_limit = 128M/memory_limit = 512M/g' /etc/php/7.4/fpm/php.ini && sudo sed -i 's/upload_max_filesize = 2M/upload_max_filesize = 500M/g' /etc/php/7.4/fpm/php.ini && sudo sed -i 's/max_file_uploads = 20/max_file_uploads = 100/g' /etc/php/7.4/fpm/php.ini;
                #
                # Remove phpMyAdmin
                sudo rm -rf /usr/share/phpmyadmin && sudo rm -rf /var/lib/phpmyadmin && sudo rm -f /etc/apache2/conf-available/phpmyadmin.conf && sudo rm -f /etc/apache2/conf-enabled/phpmyadmin.conf && sudo mkdir /usr/share/phpmyadmin;
                #
                # Install and configure phpMyAdmin
                sudo apt-get install unzip wget;
                sudo wget https://files.phpmyadmin.net/phpMyAdmin/5.0.2/phpMyAdmin-5.0.2-english.zip -O /usr/share/phpMyAdmin-5.0.2-english.zip;
                sudo unzip /usr/share/phpMyAdmin-5.0.2-english.zip -d /usr/share/;
                sudo mv /usr/share/phpMyAdmin-5.0.2-english/*  /usr/share/phpmyadmin/;
                sudo rm -rf /usr/share/phpMyAdmin-5.0.2-english && sudo rm -f  /usr/share/phpMyAdmin-5.0.2-english.zip;
                sudo chown -R www-data:  /usr/share/phpmyadmin && sudo chmod -R 744  /usr/share/phpmyadmin;
                sudo cp  /usr/share/phpmyadmin/config.sample.inc.php  /usr/share/phpmyadmin/config.inc.php;
                blowfish=$(date +%s | sha256sum | base64 | head -c 32 ; printf);
                replace="\$cfg['blowfish_secret'] = '$blowfish';";
                replace2="\$cfg['Servers'][\$i]['AllowNoPassword'] = 'true';";
                sudo sed -i "18s/.*/${replace}/"  /usr/share/phpmyadmin/config.inc.php;
                sudo sed -i "34s/.*/${replace2}/"  /usr/share/phpmyadmin/config.inc.php;
                sudo bash -c "cat > /etc/apache2/conf-available/phpmyadmin.conf << EOF
Alias /phpmyadmin /usr/share/phpmyadmin

<Directory /usr/share/phpmyadmin>
    Options FollowSymLinks
    DirectoryIndex index.php
    AllowOverride all
</Directory>

# Disallow web access to directories that don't need it
<Directory /usr/share/phpmyadmin/setup>
    Require all denied
</Directory>

<Directory /usr/share/phpmyadmin/libraries>
    Require all denied
</Directory>
EOF";
                sudo a2enconf phpmyadmin;
                #
                # Restarting services
                sudo systemctl restart apache2;
                sudo systemctl restart php7.4-fpm;
                sudo systemctl restart mysql;
                #
                # LAMP setup output
                printf "==================\n\nLAMP (development environment) has been installed and configured\n";
                printf "phpMyAdmin URL: http://localhost/phpmyadmin\n";
                printf "Username: root\n";
                printf "Access without password\n";
                printf "\nRe-run the script for additional options.\n" && exit;
            #
            else printf "\nIncorrect input. Setup has been canceled. To setup LAMP development environment, re-run the script and follow the steps.\n" && exit;
            fi
            #
            ;;
        "Add aditional PHP version to the LAMP environment")
            #
            ## Additional PHP
            #
            if ! [ -x "$(command -v apache2)" ] && ! [ -x "$(command -v php-fpm7.4)" ] && ! [ -x "$(command -v mysql)" ];
                then
                printf "\nBefore you install additional PHP versions, run the script to install LAMP (development environment) first.\n" && exit;
            fi
            #
            # Checking available PHP versions for installation
            for i in "${phpversions[@]}";
                do
                [ ! -f "/etc/php/${i}/fpm/pool.d/${user}.conf" ] && phpavailable+=(${i});
            done
            if [ " ${#phpavailable[@]} " -eq 0 ]
            then
                unset phpavailable;
                printf "\nAll available PHP versions are installed.\nRe-run the script for additional options.\n" && exit;
            fi
            #
            # PHP installation and configuration
            printf "\nAvailable PHP versions for installation:\n"
            for i in "${phpavailable[@]}";
                do
                printf "${i}\n";
            done
            printf "\nEnter desired version for installation.\n"
            read php
            if [[ " ${phpavailable[@]} " == *" ${php} "* ]];
                then
                sudo apt-get install -y php${php}-fpm php${php}-common php${php}-mysql php${php}-xml php${php}-xmlrpc php${php}-curl php${php}-gd php${php}-imagick php${php}-cli php${php}-dev php${php}-imap php${php}-mbstring php${php}-soap php${php}-zip php${php}-bcmath;
                poolfpm="/etc/php/${php}/fpm/pool.d/${user}.conf";
                sudo bash -c "cat > ${poolfpm} << EOF
[${user}]

user = ${user}
group = ${user}

listen = /run/php/php${php}-fpm-${user}.sock

listen.owner = www-data
listen.group = www-data

pm = dynamic
pm.max_children = 5
pm.start_servers = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 3


EOF";
                sudo rm -f "/etc/php/${php}/fpm/pool.d/www.conf";
                phpini="/etc/php/${php}/fpm/php.ini";
                sudo sed -i 's/post_max_size = 8M/post_max_size = 500M/g' ${phpini} && sudo sed -i 's/max_execution_time = 30/max_execution_time = 180/g' ${phpini} && sudo sed -i 's/memory_limit = 128M/memory_limit = 512M/g' ${phpini} && sudo sed -i 's/upload_max_filesize = 2M/upload_max_filesize = 500M/g' ${phpini} && sudo sed -i 's/max_file_uploads = 20/max_file_uploads = 100/g' ${phpini};
                sudo systemctl restart php${php}-fpm;
                unset phpavailable;
                [ -f "/etc/php/${php}/fpm/pool.d/${user}.conf" ] && printf "==================\n\nPHP ${php} has been installed.\nRe-run the script to add additional PHP versions.\n" && exit;
                else
                unset phpavailable;
                printf "\nSelected PHP version is not available for installation.\nRe-run the script and try again.\n" && exit;
            fi
            #
            ;;
        "Add or remove Virtual Host - website")
            #
            ## Add / remove Virtual Host
            #
            if ! [ -x "$(command -v apache2)" ] && ! [ -x "$(command -v php-fpm7.4)" ] && ! [ -x "$(command -v mysql)" ];
                then
                printf "\nBefore you add Virtual Host, run the script to install LAMP (development environment) first.\n" && exit;
            fi
            #
            # Collecting input and generating needed data structure
            printf "\nEnter the FQDN of the website you want to add or remove.\n"
            read sitename
            loopip='127.0.0.1'
            hosts=/etc/hosts
            hostsentry="${loopip} ${sitename} "
            siteenabled="/etc/apache2/sites-enabled/${sitename}.conf"
            siteavailable="/etc/apache2/sites-available/${sitename}.conf"
            sitepath="/home/${user}/www/${sitename}"
            #
            # Checking whether the site has already been configured
            if grep -w -q "${sitename} " "${hosts}";
                then chkhosts=true
                else chkhosts=false
            fi
            if [ -e "${siteavailable}" ];
                then chksitea=true
                else chksitea=false
            fi
            if [ -e "${siteenabled}" ];
                then chksitee=true
                else chksitee=false
            fi
            if [ -d "${sitepath}" ];
                then chksitep=true
                else chksitep=false
            fi
            #
            # Removing the existing website
            if ( $chkhosts || $chksitea || $chksitee || $chksitep );
                then printf "\nThe ${sitename} website has been found on your system. To remove it, type in \"remove\".\nCAUTION: If you have any files in the ${sitepath} directory, please, backup.\n";
                read rmaction;
                if [ "$rmaction" == "remove" ];
                    then chkremove=true
                    else chkremove=false
                fi
                if ( $chkhosts && $chkremove );
                    then sudo sed -i "/${hostsentry}/d" "${hosts}";
                fi
                if ( $chksitee && $chkremove );
                    then sudo a2dissite -q "${sitename}" && sudo systemctl restart apache2;
                fi
                if ( $chksitea && $chkremove );
                    then sudo rm ${siteavailable};
                fi
                if ( $chksitep && $chkremove);
                then sudo rm -rf "${sitepath}";
                fi
                if ($chkremove);
                    then printf "==================\n\nThe website has been removed. Re-run the script to add new website.\n" && exit;
                    else printf "\nIncorrect input. The website has not been removed. To remove it, type 'remove'. Re-run the script to try again.\n" && exit;
                fi
            else
                #
                # Checking installed PHP versions
                for i in "${phpversions[@]}";
                    do
                    [ -f "/etc/php/${i}/fpm/pool.d/${user}.conf" ] && phpinstalled+=(${i});
                done
                printf "\nAvailable PHP versions for website:\n"
                for i in "${phpinstalled[@]}";
                    do
                    printf "${i}\n";
                done
                if [ "${#phpinstalled[@]}" -eq 1 ];
                    then
                        v=$(printf ${phpinstalled[@]});
                        php=$(printf $v | cut -d ' ' -f 2)
                    else
                        printf "\nEnter desired PHP version for the website.\n"
                        read php
                fi
                if [[ " ${phpinstalled[@]} " == *" ${php} "* ]];
                    then
                    # Adding the website
                    mkdir -p "${sitepath}";
                    sudo bash -c "cat > ${siteavailable} << EOF
<VirtualHost *:80>
    ServerName ${sitename}

    ServerAdmin webmaster@localhost
    DocumentRoot ${sitepath}

    ErrorLog /var/log/apache2/${sitename}-error.log
    CustomLog /var/log/apache2/${sitename}-access.log combined

    <Directory ${sitepath}/>
    Options FollowSymLinks MultiViews
    AllowOverride All
    Require all granted
    </Directory>

<IfModule proxy_fcgi_module>
    <IfModule setenvif_module>
    SetEnvIfNoCase ^Authorization$ \"(.+)\" HTTP_AUTHORIZATION=$1
    </IfModule>

    <FilesMatch \".+\.ph(ar|p|tml)$\">
        SetHandler \"proxy:unix:/run/php/php${php}-fpm-${user}.sock|fcgi://localhost\"
    </FilesMatch>
    <FilesMatch \".+\.phps$\">
        Require all denied
    </FilesMatch>
    <FilesMatch \"^\.ph(ar|p|ps|tml)$\">
        Require all denied
    </FilesMatch>
</IfModule>

</VirtualHost>
EOF";
                    #
                    # Enabling the website
                    sudo a2ensite -q "$sitename";
                    sudo systemctl restart apache2;
                    sudo bash -c "printf \"${hostsentry}\n\" >> ${hosts}";
                    #
                    # Adding phpinfo() index
                    bash -c "cat > "${sitepath}/index.php" << EOF
<?php
phpinfo();
?>
EOF";
                    unset phpinstalled;
                    #
                    # Added website output
                    printf "==================\n\n${sitename} has been added.\n";
                    printf "URL: http://${sitename}\n";
                    printf "Local directory: ${sitepath}\n";
                    printf "\n\nRe-run the script to add new website.\n" && exit;
                    #
                    else
                    unset phpinstalled;
                    printf "\nSelected PHP version is not available for installation.\nRe-run the script and try again.\n" && exit;
                    fi
            fi
            #
            ;;
        "Change Virtual Host's PHP verson")
            #
            ## Change VHost's PHP verson
            #
            if ! [ -x "$(command -v apache2)" ] && ! [ -x "$(command -v php-fpm7.4)" ] && ! [ -x "$(command -v mysql)" ];
                then
                printf "\nBefore reconfiguring Virtual Host PHP version, run the script to install LAMP (development environment) first.\n" && exit;
            fi
            #
            # Collecting input
            printf "\nEnter the FQDN of the website you want to switch to another PHP verion.\n"
            read sitename
            loopip='127.0.0.1'
            hosts=/etc/hosts
            hostsentry="${loopip} ${sitename} "
            siteenabled="/etc/apache2/sites-enabled/${sitename}.conf"
            siteavailable="/etc/apache2/sites-available/${sitename}.conf"
            sitepath="/home/${user}/www/${sitename}"
            #
            # Checking whether the site exists
            if grep -w -q "${sitename} " "${hosts}";
                then chkhosts=true
                else chkhosts=false
            fi
            if [ -e "${siteavailable}" ];
                then chksitea=true
                else chksitea=false
            fi
            if [ -e "${siteenabled}" ];
                then chksitee=true
                else chksitee=false
            fi
            if [ -d "${sitepath}" ];
                then chksitep=true
                else chksitep=false
            fi
            #
            # Changing PHP on Virtual Host
            if ( $chkhosts && $chksitea && $chksitee && $chksitep );
                then
                    curphp="$(grep "proxy:unix:\/run\/php\/php" ${siteavailable} | grep -Eo '[0-9]+.+[0-9]')";
                    #
                    # Checking installed PHP versions
                    for i in "${phpversions[@]}";
                        do
                        [ -f "/etc/php/${i}/fpm/pool.d/${user}.conf" ] && phpinstalled+=(${i});
                    done;
                    #
                    # Remove currently used PHP on the website
                    for set in "$curphp"; do
                        for i in "${!phpinstalled[@]}"; do
                            if [[ ${phpinstalled[i]} = $set ]]; then
                            unset 'phpinstalled[i]'
                            fi
                        done
                    done
                    #
                    if ! (( ${#phpinstalled[@]} ));
                        then
                            unset phpinstalled;
                            printf "\nBefore reconfiguring Virtual Host PHP version, run the script to install aditional php versions first.\n" && exit;
                    fi
                    #
                    # Listing available PHP versions
                    printf "\nAvailable PHP versions for website:\n"
                    for i in "${phpinstalled[@]}";
                        do
                        printf "${i}\n";
                    done;
                    printf "\nEnter desired PHP version you want to switch the website to.\n";
                    read php;
                    #
                    if [[ " ${phpinstalled[@]} " =~ " ${php} " ]];
                        then
                            sudo sed -i 's,'.*proxy:unix:\/run\/php\/php.*',        SetHandler \"proxy:unix:/run/php/php'${php}'-fpm-'${user}'.sock|fcgi://localhost\",' ${siteavailable};
                            sudo systemctl restart apache2;
                            unset phpinstalled;
                            printf "\n${sitename} has been switched to PHP ${php}\n" && exit;
                        else
                            unset phpinstalled;
                            printf "\nSelected PHP version is not available.\nRe-run the script and try again.\n" && exit;
                    fi
                    unset phpinstalled;
                else printf "\nBefore reconfiguring Virtual Host PHP version, run the script to add Virtual Host first.\n" && exit;
            fi
            #
            ;;
        "Restart web services")
            #
            ## Restart apache, php, mysql services
            #
            sudo systemctl restart php*-fpm.service && sudo systemctl restart apache2.service && sudo systemctl restart mysql.service;
            #
            ;;
        "Exit")
            break
            ;;
        *) echo "$REPLY is not available";;
    esac
done
#
