From 50798ac330c741d342037a5e00636c0d4b205395 Mon Sep 17 00:00:00 2001 From: Brian Porter Date: Sun, 24 Oct 2021 16:39:57 -0500 Subject: [PATCH] Overhaul Vagrantfile and bootstrap.sh provisioner. --- .gitignore | 6 +- .vagrant/bootstrap.sh.example | 56 --------- README.md | 34 ++++- Vagrantfile | 75 +++++++++-- cgi-bin/.gitignore | 217 -------------------------------- cgi-bin/db_end.php | 3 +- cgi-bin/db_start.php.example | 9 +- provision/bootstrap.sh | 230 ++++++++++++++++++++++++++++++++++ provision/schema.sql | 1 + 9 files changed, 334 insertions(+), 297 deletions(-) delete mode 100644 .vagrant/bootstrap.sh.example delete mode 100644 cgi-bin/.gitignore create mode 100644 provision/bootstrap.sh create mode 100644 provision/schema.sql diff --git a/.gitignore b/.gitignore index db66051..8e31a4c 100644 --- a/.gitignore +++ b/.gitignore @@ -10,8 +10,8 @@ tiles/ tiles/**/* google*.html *.sql -.vagrant/bootstrap.sh -.vagrant/machines/ +cgi-bin/db_start.php +.vagrant/ .well-known/brave-payment-verification.txt 9A4F12FD1854F031824A5EE0E710E4F0.txt @@ -231,4 +231,4 @@ pip-log.txt #Mr Developer .mr.developer.cfg -*.code-workspace \ No newline at end of file +*.code-workspace diff --git a/.vagrant/bootstrap.sh.example b/.vagrant/bootstrap.sh.example deleted file mode 100644 index 35538b4..0000000 --- a/.vagrant/bootstrap.sh.example +++ /dev/null @@ -1,56 +0,0 @@ -#!/usr/bin/env bash - -echo "Provisioning virtual machine..." -export DEBIAN_FRONTEND=noninteractive - -echo "Updating apt" -apt-get update > /dev/null - -echo "Installing vim" -apt-get install -y vim > /dev/null - -echo "Installing Apache and linking /vagrant to /var/www" -apt-get install -y apache2 > /dev/null -if ! [ -L /var/www ]; then - rm -rf /var/www - ln -fs /vagrant /var/www -fi - -echo "Installing PHP" -apt-get install -y php7.2 php7.2-dev libapache2-mod-php7.2 libsodium23 php-common php7.2-cli php7.2-common php7.2-json php7.2-opcache php7.2-readline > /dev/null - -echo "Installing PHP extensions" -apt-get install -y curl php-curl php7.2-gd php-gd mcrypt php-mysql php7.2-mysql > /dev/null -sed -i "s|;extension=pdo_mysql|extension=pdo_mysql|g" /etc/php/7.2/apache2/php.ini - -echo "Making PHP and Apache work together" -sudo a2enmod php7.2 # > /dev/null -service apache2 stop # > /dev/null -echo "listen 4069" | sudo tee --append /etc/apache2/httpd.conf -echo "ServerName localhost" | sudo tee --append /etc/apache2/httpd.conf -sudo ln -s /etc/apache2/mods-available/rewrite.load /etc/apache2/mods-enabled/rewrite.load -sudo rm /etc/apache2/sites-enabled/000-default.conf -sudo cp /vagrant/.vagrant/default.conf /etc/apache2/sites-enabled/000-default.conf -service apache2 restart # > /dev/null - -echo "Preparing MySQL" -apt-get install debconf-utils -y > /dev/null -debconf-set-selections <<< "mysql-server mysql-server/root_password password 1234" -debconf-set-selections <<< "mysql-server mysql-server/root_password_again password 1234" - -echo "Installing MySQL" -apt-get install mysql-server -y > /dev/null - -echo "Setup database" -mysql -uroot -p1234 -e "DROP DATABASE IF EXISTS ---your-db-name-here---"; -mysql -uroot -p1234 -e "CREATE DATABASE ---your-db-name-here---;" - -echo "Make MySQL external accessible" -mysql -uroot -p1234 -e "GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY '1234';" -mysql -uroot -p1234 -e "GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' IDENTIFIED BY '1234';" -mysql -uroot -p1234 -e "GRANT ALL PRIVILEGES ON *.* TO 'cartographer'@'localhost' IDENTIFIED BY '1234';" - -echo "Import bootstrap SQL" -mysql -uroot -p1234 ---your-db-name-here--- < /vagrant/---your-db-name-here---.sql - -sudo service mysql restart diff --git a/README.md b/README.md index f868068..11464cc 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,32 @@ -Dave's Mapper -============= +# Dave's Mapper + This is the code behind [Dave's Mapper](https://davesmapper.com). It's based on the Morph Mapper by Rob Lang, but vastly larger in scope and ambition. -License -------- + +## Development + +This project includes a Vagrantfile to bundle all necessary dependencies. Locally you will need: + +* git v2.0+ +* [Vagrant](https://www.vagrantup.com/downloads) + * [Virtualbox](https://www.virtualbox.org/wiki/Downloads) + +The included `provision/boostrap.sh` script defines all other system-level dependencies including PHP, Apache and MySQL. + +### Setup + +1. Clone the repo. +2. Run `vagrant up` to download, provision and launch the development box. + * This will take some time during the first execution as the base VM image needs to be downloaded from the internet. +3. This local folder is mapped into the VM's `/app` folder. Changes to files in the project will be updated inside the VM nearly instantaneously. +4. Visit http://localhost:4069 +5. When you are done, run `vagrant down` to halt the configured VM. (Subsequent `vagrant up` commands will boot this already-provisioned VM.) + +Database credentials will be automatically configured in `cgi-bin/db_start.php` to work with Vagrant. This file is gitignore'd to prevent it from being committed back to the repo with sensitive credentials. + +## License + Dave's Mapper Copyright © 2010-2018 David Millar @@ -22,7 +44,7 @@ License You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/. -Contact -------- +## Contact + I can be reached at dave@davegoesthedistance.com or dave@davesmapper.com diff --git a/Vagrantfile b/Vagrantfile index 100519d..eb07b72 100644 --- a/Vagrantfile +++ b/Vagrantfile @@ -1,13 +1,70 @@ -project_name = "mapper" - -Vagrant.configure("2") do |config| - config.vm.box = "hashicorp/bionic64" - config.vm.box_version = "1.0.282" - config.vm.synced_folder ".", "/vagrant" - config.vm.provision :shell, path: ".vagrant/bootstrap.sh" - config.vm.network :forwarded_port, host: 4069, guest: 80 - config.vm.provider "virtualbox" do |v| +conf = { + PROJECT_NAME: 'daves-mapper', + PROJECT_ROOT: '/var/www/daves-mapper', + PROJECT_PORT: 4069, +} + +Vagrant.require_version '>= 2.0.0' + +Vagrant.configure('2') do |config| + config.vm.box = 'bento/ubuntu-20.04' + + config.vm.network :forwarded_port, + host: conf[:PROJECT_PORT], + guest: 80 + config.vm.network :forwarded_port, + host: 3307, + guest: 3306, + auto_correct: true + + config.vm.synced_folder '.', conf[:PROJECT_ROOT] + + config.vm.provider 'virtualbox' do |v| v.name = "Dave's Mapper Vagrant" v.gui = false end + + config.vm.provision :shell, + name: 'bootstrap', + path: 'provision/bootstrap.sh', + args: [ + conf[:PROJECT_ROOT], + "#{conf[:PROJECT_NAME]}.test", + 'vagrant' + ] + + config.vm.provision :shell, + name: 'vagrant specific', + privileged: false, + inline: <<~VAGRANTONLYSCRIPT + cd #{conf[:PROJECT_ROOT]} + + echo '## Creating a limited vagrant-only DB user.' + cat <> ~/.profile + fi + + VAGRANTONLYSCRIPT + + # TODO: Define a safety trigger to export MySQL data before destroying the VM. + + config.vm.post_up_message = "VM is up! Visit http://localhost:#{conf[:PROJECT_PORT]}" end diff --git a/cgi-bin/.gitignore b/cgi-bin/.gitignore deleted file mode 100644 index 49f0df5..0000000 --- a/cgi-bin/.gitignore +++ /dev/null @@ -1,217 +0,0 @@ -db_start.php - -################# -## Eclipse -################# - -*.pydevproject -.project -.metadata -bin/ -tmp/ -*.tmp -*.bak -*.swp -*~.nib -local.properties -.classpath -.settings/ -.loadpath - -# External tool builders -.externalToolBuilders/ - -# Locally stored "Eclipse launch configurations" -*.launch - -# CDT-specific -.cproject - -# PDT-specific -.buildpath - - -################# -## Visual Studio -################# - -## Ignore Visual Studio temporary files, build results, and -## files generated by popular Visual Studio add-ons. - -# User-specific files -*.suo -*.user -*.sln.docstates - -# Build results - -[Dd]ebug/ -[Rr]elease/ -x64/ -build/ -[Bb]in/ -[Oo]bj/ - -# MSTest test Results -[Tt]est[Rr]esult*/ -[Bb]uild[Ll]og.* - -*_i.c -*_p.c -*.ilk -*.meta -*.obj -*.pch -*.pdb -*.pgc -*.pgd -*.rsp -*.sbr -*.tlb -*.tli -*.tlh -*.tmp -*.tmp_proj -*.log -*.vspscc -*.vssscc -.builds -*.pidb -*.log -*.scc - -# Visual C++ cache files -ipch/ -*.aps -*.ncb -*.opensdf -*.sdf -*.cachefile - -# Visual Studio profiler -*.psess -*.vsp -*.vspx - -# Guidance Automation Toolkit -*.gpState - -# ReSharper is a .NET coding add-in -_ReSharper*/ -*.[Rr]e[Ss]harper - -# TeamCity is a build add-in -_TeamCity* - -# DotCover is a Code Coverage Tool -*.dotCover - -# NCrunch -*.ncrunch* -.*crunch*.local.xml - -# Installshield output folder -[Ee]xpress/ - -# DocProject is a documentation generator add-in -DocProject/buildhelp/ -DocProject/Help/*.HxT -DocProject/Help/*.HxC -DocProject/Help/*.hhc -DocProject/Help/*.hhk -DocProject/Help/*.hhp -DocProject/Help/Html2 -DocProject/Help/html - -# Click-Once directory -publish/ - -# Publish Web Output -*.Publish.xml -*.pubxml - -# NuGet Packages Directory -## TODO: If you have NuGet Package Restore enabled, uncomment the next line -#packages/ - -# Windows Azure Build Output -csx -*.build.csdef - -# Windows Store app package directory -AppPackages/ - -# Others -sql/ -*.Cache -ClientBin/ -[Ss]tyle[Cc]op.* -~$* -*~ -*.dbmdl -*.[Pp]ublish.xml -*.pfx -*.publishsettings - -# RIA/Silverlight projects -Generated_Code/ - -# Backup & report files from converting an old project file to a newer -# Visual Studio version. Backup files are not needed, because we have git ;-) -_UpgradeReport_Files/ -Backup*/ -UpgradeLog*.XML -UpgradeLog*.htm - -# SQL Server files -App_Data/*.mdf -App_Data/*.ldf - -############# -## Windows detritus -############# - -# Windows image file caches -Thumbs.db -ehthumbs.db - -# Folder config file -Desktop.ini - -# Recycle Bin used on file shares -$RECYCLE.BIN/ - -# Mac crap -.DS_Store - - -############# -## Python -############# - -*.py[co] - -# Packages -*.egg -*.egg-info -dist/ -build/ -eggs/ -parts/ -var/ -sdist/ -develop-eggs/ -.installed.cfg - -# Installer logs -pip-log.txt - -# Unit test / coverage reports -.coverage -.tox - -#Translations -*.mo - -#Mr Developer -.mr.developer.cfg diff --git a/cgi-bin/db_end.php b/cgi-bin/db_end.php index f76d4fd..5b3017f 100644 --- a/cgi-bin/db_end.php +++ b/cgi-bin/db_end.php @@ -1 +1,2 @@ - + +$user = 'vagrant'; +$password = 'vagrant'; +$database = 'daves_mapper'; +$pdo = new PDO("mysql:host=localhost;dbname=$database", $user, $password); diff --git a/provision/bootstrap.sh b/provision/bootstrap.sh new file mode 100644 index 0000000..c0b3397 --- /dev/null +++ b/provision/bootstrap.sh @@ -0,0 +1,230 @@ +#!/usr/bin/env bash +# +# Provisioning script. Intended to configure an Ubuntu 20 server with all +# necessary system-level dependencies. This script is written to be used +# in both development (Vagrant) and potentially in production against a +# standard Ubuntu cloud server or VPS. +# +# This script is also written to be idempotent (safe to re-run) to make for +# easier testing/tweaking. +# +# This script must be run as root. To use this script on a new +# production server: +# +# 1. SCP or clone this repo to `/var/www/daves_mapper` on the server. +# 2. SSH into the server: `ssh ubuntu@$YOUR_SERVER` +# 3. Move to the project dir: `cd /var/www/daves_mapper` +# 4. Switch to root: `sudo su -` +# 5. Run `provision/bootstrap.sh "$PWD" 'davesmapper.com' $USER` + + +# Config vars. + +export MYSQL_PASS=$(date +%s|sha256sum|base64|head -c 32) +export MYSQL_DATABASE_NAME=daves_mapper +export PROJECT_NAME=daves-mapper +export PROJECT_ROOT="${1:-/var/www/$PROJECT_NAME}" +export PROJECT_DOMAIN="${2:-daves-mapper.test}" +export PROJECT_USER="${3:-vagrant}" +export PROJECT_GROUP="${4:-www-data}" + +PHP_VERSION='7.4' +PHP_REQ_EXT=( 'cli' 'curl' 'fpm' 'gd' 'json' 'mysql' 'opcache' 'readline' 'xml' 'zip' ) + + +# Users. +# Adding the login user to the web server's group makes editing files easier. +echo '## Setting up user groups for convenience.' + +if ! id -g ${PROJECT_GROUP} &>/dev/null; then + groupadd ${PROJECT_GROUP} +fi +if ! id -u ${PROJECT_GROUP} &>/dev/null; then + useradd ${PROJECT_USER} -g ${PROJECT_GROUP} +fi +# Login user can manage files owned by Apache. +usermod -a -G ${PROJECT_USER} ${PROJECT_GROUP} +# Apache can manage files owned by user. +usermod -a -G ${PROJECT_USER} ${PROJECT_GROUP} + + +# Locales +echo '## Configuring locale and apt.' + +export LANGUAGE=en_US.UTF-8 +export TERM=xterm +export DEBIAN_FRONTEND=noninteractive + +locale-gen en_US.UTF-8 +dpkg --configure -a + + +# Low-level system dependencies. +echo '## Installing and configuring system dependencies.' + +apt-get -qqq update +apt-get -yqq install \ + software-properties-common \ + build-essential \ + debconf-utils \ + zip \ + unzip \ + git \ + libsodium23 \ + mcrypt + + +# PHP and Apache. +echo '## Installing and configuring Apache and PHP.' + +add-apt-repository -y ppa:ondrej/php +add-apt-repository -y ppa:ondrej/apache2 +apt-get -qqq update + +EXT_LIST="" +for EXT in "${PHP_REQ_EXT[@]}"; do + EXT_LIST+=" php${PHP_VERSION}-${EXT}" +done +apt-get -yqq install \ + apache2 \ + libapache2-mod-fcgid \ + php$PHP_VERSION \ + $EXT_LIST + +cat < /etc/php/7.4/fpm/conf.d/99-logging.ini +error_log /var/log/php_error.log + +PHPINI + +if [ -f "/etc/php/$PHP_VERSION/fpm/pool.d/www.conf" ]; then + rm /etc/php/$PHP_VERSION/fpm/pool.d/www.conf +fi +cat < /etc/php/$PHP_VERSION/fpm/pool.d/$PROJECT_NAME.conf +[$PROJECT_NAME] + +user = $PROJECT_USER +group = $PROJECT_GROUP + +listen = /var/run/php/php$PHP_VERSION-fpm.sock; + +listen.owner = www-data +listen.group = www-data +listen.mode = 0660 + +pm = dynamic +pm.max_children = 5 +pm.start_servers = 2 +pm.min_spare_servers = 1 +pm.max_spare_servers = 3 +pm.process_idle_timeout = 10s +pm.max_requests = 500 + +chdir = / +FPMCONF + +systemctl enable php$PHP_VERSION-fpm +systemctl restart php$PHP_VERSION-fpm + +a2enconf php7.4-fpm +a2enmod \ + actions \ + alias \ + fcgid \ + proxy_fcgi \ + rewrite \ + setenvif + +mkdir -p /var/log/apache2/${PROJECT_DOMAIN} +touch /var/log/apache2/${PROJECT_DOMAIN}/{access,error}.log +chown root:www-data /var/log/apache2/${PROJECT_DOMAIN}/{access,error}.log +chmod ug=rw,o=r /var/log/apache2/${PROJECT_DOMAIN}/{access,error}.log +if [ -f '/etc/apache2/sites-enabled/000-default.conf' ]; then + rm /etc/apache2/sites-enabled/000-default.conf +fi +cat < "/etc/apache2/sites-available/${PROJECT_NAME}.conf" + + ServerAdmin admin@${PROJECT_DOMAIN} + ServerName ${PROJECT_DOMAIN} + DocumentRoot "${PROJECT_ROOT}" + DirectoryIndex index.php + + + Options Indexes FollowSymLinks MultiViews + AllowOverride All + Order allow,deny + Allow from all + + + + # For Apache version 2.4.10 and above, use SetHandler to run PHP as a fastCGI process server + SetHandler "proxy:unix:/var/run/php/php$PHP_VERSION-fpm.sock|fcgi://localhost" + + + ErrorLog \${APACHE_LOG_DIR}/${PROJECT_DOMAIN}/error.log + CustomLog \${APACHE_LOG_DIR}/${PROJECT_DOMAIN}/access.log combined + + +APACHECONF + +a2ensite $PROJECT_NAME + +apachectl configtest +systemctl enable apache2 +systemctl restart apache2 + +# Install composer. + +curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer + + +# MySQL. +echo '## Installing and configuring MySQL server.' + +if [ ! -f '/home/$PROJECT_USER/.my.cnf' ]; then + echo "mysql-server mysql-server/root_password password $MYSQL_PASS" | debconf-set-selections + echo "mysql-server mysql-server/root_password_again password $MYSQL_PASS" | debconf-set-selections +fi + +apt-get -yqq install mysql-server +mysqld --initialize +systemctl enable mysql +systemctl restart mysql + +# Save local credentials for streamlined command-line usage. +# Example: `ssh ubuntu@your-server.com mysql` will work by reading +# the root credentials directly from the ~/.my.cnf file on the server. +# This SSH-styled approach also means you don't have to open 3306 to +# the world, nor do you need to allow external TCP connections to the +# MySQL service directly. +if [ ! -f '/home/$PROJECT_USER/.my.cnf' ]; then + # This heredoc MUST be indented with TABS. + cat <<-MYCNF > /home/$PROJECT_USER/.my.cnf + [client] + user=root + password="$MYSQL_PASS" + + [mysql] + user=root + password="$MYSQL_PASS" + + [mysqldump] + user=root + password="$MYSQL_PASS" + + [mysqldiff] + user=root + password="$MYSQL_PASS" + + [mysqladmin] + user=root + password="$MYSQL_PASS" + MYCNF +fi + +if [ ! -f '/root/.my.cnf' ]; then + ln -s /home/$PROJECT_USER/.my.cnf /root/.my.cnf +fi +chown $PROJECT_USER:$PROJECT_GROUP /home/$PROJECT_USER/.my.cnf +chmod u=r,go= /home/$PROJECT_USER/.my.cnf + +mysql -e "CREATE DATABASE IF NOT EXISTS $MYSQL_DATABASE_NAME;" diff --git a/provision/schema.sql b/provision/schema.sql new file mode 100644 index 0000000..7ed610d --- /dev/null +++ b/provision/schema.sql @@ -0,0 +1 @@ +-- TODO: Commit schema-only table structure to this file for first-run setup.