#!/usr/bin/env bash # # Author: Robert Brisita <[first-initial][last name] at gmail dot com> # # A non-interactive installation script for a Nginx Laravel application using MySQL. # # Tested on Ubuntu 16.04 LTS ##### # Project details # Used in creating project and MySQL schema and credentials. # The database credentials mirror the DotEnv file (.env) Laravel uses. ##### PROJECT_NAME=my_project DB_SCHEMA=homestead DB_USERNAME=homestead DB_PASSWORD=secret DB_ROOT_PASSWORD=secret # Turn off interactive prompt on server installs. DF_NI="DEBIAN_FRONTEND=noninteractive" ##### # Update and Upgrade ##### echo -e "\n*****\n* Updating Apt Package List.\n*****\n" sudo apt-get update echo -e "\n*****\n* Upgrade System Packages.\n*****\n" sudo "${DF_NI}" apt-get -y upgrade # Add the ability to add Personal Package Archive (PPA) (add-apt-repository) for more current software. sudo "${DF_NI}" apt-get -y install software-properties-common ##### # NGINX ##### echo -e "\n*****\n* Install Nginx.\n*****\n" sudo "${DF_NI}" apt-get -y install nginx ##### # PHP ##### echo -e "\n*****\n* Install PHP 7.1 and required packages.\n*****\n" # Add PPA to get PHP 7.1. sudo add-apt-repository -y ppa:ondrej/php sudo apt-get update # Install PHP # fpm - Installed first to satisfy PHP dependency request. # curl - This script and Composer needs curl to get some packages. # unzip/zip - Allows composer and Laravel to download and extract packages. # xml - Manipulate the dom. # mbstring - Handle multi-byte strings. sudo "${DF_NI}" apt-get -y install unzip php7.1-fpm php7.1 php7.1-curl php7.1-zip php7.1-xml php7.1-mbstring # Install Composer curl --silent --show-error https://getcomposer.org/installer | php sudo mv composer.phar /usr/local/bin/composer ##### # NGINX and PHP ##### # Modify Nginx default server block to use PHP for dynamic processing. # Copy file and create a new one. NGINX_PATH="/etc/nginx/sites-available/" DEFAULT_FILE="default" DATE=$(date +%Y-%m-%d:%H:%M:%S) sudo cp "${NGINX_PATH}${DEFAULT_FILE}" "${NGINX_PATH}backup_${DEFAULT_FILE}_${DATE}" # https://www.nginx.com/resources/wiki/start/topics/examples/phpfcgi/ HOST_NAME=$(hostname) sudo bash -c "cat > ${NGINX_PATH}${DEFAULT_FILE}" << EOF server { listen 80 default_server; listen [::]:80 default_server; root /var/www/html; index index.php index.html index.htm index.nginx-debian.html; server_name ${HOST_NAME}.eastus.cloudapp.azure.com; location / { try_files \$uri \$uri/ /index.php?\$query_string; } location ~ [^/]\.php(/|$) { # Secure path parsing. include snippets/fastcgi-php.conf; # Mitigate https://httpoxy.org/ vulnerabilities. fastcgi_param HTTP_PROXY ""; fastcgi_pass unix:/run/php/php7.1-fpm.sock; } location ~ /\.ht { deny all; } } EOF echo -e "\n*****\n* Restarting Nginx.\n*****\n" sudo systemctl restart nginx ##### # MYSQL ##### # Cleanly get script directory. # -f, --canonicalize - Follow every symlink, all but the last component must exist. SCRIPT_DIR=$(readlink --canonicalize "${BASH_SOURCE[0]}") SCRIPT_DIR=$(dirname "${SCRIPT_DIR}") echo -e "\n*****\n* Installing MySQL and PHP driver.\n*****\n" sudo "${DF_NI}" apt-get -y install mysql-server php7.1-mysql echo -e "\n*****\n* Setting Password Lifetime to forever.\n*****\n" MYSQL_CNF=/etc/mysql/mysql.conf.d/mysqld.cnf PASSWORD_LIFETIME='default_password_lifetime = 0' # Look for the above line in it's own line. # -F, --fixed-strings - Interpret patterns as a set of fixed strings. # -q, --quiet, --silent - Suppress normal output; search until a match is found. # -x, --line-regexp - Only input lines selected against an entire fixed string. grep --fixed-strings --silent --line-regexp "${PASSWORD_LIFETIME}" "${MYSQL_CNF}" if [ "$?" -eq "0" ] then echo -e "\n*****\n* Password Lifetime to forever already set.\n*****\n" else # Configure MySQL Password Lifetime to forever. sudo bash -c "cat >> ${MYSQL_CNF}" << EOF ${PASSWORD_LIFETIME} EOF fi # Securely setup MySQL. echo -e "\n*****\n* Securing MySQL.\n*****\n" sudo "${SCRIPT_DIR}/./ni-msi.sh" "${DB_ROOT_PASSWORD}" # Setup up database the Homestead way and mirror Laravel's .env file. echo -e "\n*****\n* Creating user and database schema.\n*****\n" sudo mysql --defaults-extra-file="${SCRIPT_DIR}/mysql_credentials.cnf" -e "CREATE USER IF NOT EXISTS '${DB_USERNAME}'@'0.0.0.0' IDENTIFIED BY '${DB_PASSWORD}';" sudo mysql --defaults-extra-file="${SCRIPT_DIR}/mysql_credentials.cnf" -e "GRANT ALL ON *.* TO '${DB_USERNAME}'@'0.0.0.0' IDENTIFIED BY '${DB_PASSWORD}' WITH GRANT OPTION;" sudo mysql --defaults-extra-file="${SCRIPT_DIR}/mysql_credentials.cnf" -e "GRANT ALL ON *.* TO '${DB_USERNAME}'@'%' IDENTIFIED BY '${DB_PASSWORD}' WITH GRANT OPTION;" sudo mysql --defaults-extra-file="${SCRIPT_DIR}/mysql_credentials.cnf" -e "FLUSH PRIVILEGES;" sudo mysql --defaults-extra-file="${SCRIPT_DIR}/mysql_credentials.cnf" -e "CREATE DATABASE IF NOT EXISTS ${DB_SCHEMA} character set UTF8mb4 collate utf8mb4_bin;" echo -e "\n*****\n* Restarting MySQL.\n*****\n" sudo systemctl restart mysql ##### # NODEJS ##### echo -e "\n*****\n* Install Node JS.\n*****\n" # Add PPA for NodeJS 6.x. curl --silent --location https://deb.nodesource.com/setup_6.x | sudo -E bash - # Install Node. sudo "${DF_NI}" apt-get -y install nodejs ##### # LARAVEL PROJECT SPECIFIC # At this point one can inject there own project here. # This script creates a new one for simplicity. ##### echo -e "\n*****\n* Creating Laravel Project.\n*****\n" composer create-project --prefer-dist laravel/laravel ${PROJECT_NAME} PROJECT_PATH="${HOME}/${PROJECT_NAME}" # Install PHP project dependencies. echo -e "\n*****\n* Install PHP Project Dependencies.\n*****\n" composer install --working-dir="${PROJECT_PATH}" # Install Node dependencies. echo -e "\n*****\n* Install Node Dependencies.\n*****\n" npm install --prefix "${PROJECT_PATH}/" # Create authentication tables and views. # Migrate tables. # Using --force to skip production warning echo -e "\n*****\n* Create MySQL Tables.\n*****\n" sudo php "${PROJECT_PATH}"/artisan make:auth --force sudo php "${PROJECT_PATH}"/artisan migrate --force # Change access permissions to Laravel's framework and log directories. STORAGE_PATH="${PROJECT_PATH}/storage" sudo chown -R www-data "${STORAGE_PATH}/framework" sudo chgrp -R www-data "${STORAGE_PATH}/framework" sudo chmod -R 0775 "${STORAGE_PATH}/framework" sudo chown -R www-data "${STORAGE_PATH}/logs" sudo chgrp -R www-data "${STORAGE_PATH}/logs" sudo chmod -R 0775 "${STORAGE_PATH}/logs" # Symlink project's public folder to /var/www/html. sudo rm -rf /var/www/html sudo ln -s "${HOME}/${PROJECT_NAME}/public" /var/www/html # You should see Laravel rendering on port 80. echo -e "\n*****\n* Open: http://${HOST_NAME}.eastus.cloudapp.azure.com in a broswer!\n*****\n" # EOF