Created
November 30, 2016 10:27
-
-
Save rmpel/dda9f0286e1de426dfde62921570d081 to your computer and use it in GitHub Desktop.
Apache Config File builder - generates an Apache2 config file based on a Development directory with virtual hosts with custom TLD.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# this file is related to a series of posts on my website, see | |
# https://remonpel.nl/2012/10/semi-automatically-rebuild-apache-vhost-configuration/ | |
# this script is ANYTHING BUT optimal | |
# it works as it is very well on macOS, Ubuntu and "Bash on Ubuntu on Windows with WSL" | |
# WSL is a seriously crippled way to use anything linux related, but if you are brave enough, you should try it. | |
# If you have better ways of doing things, send me a note :) | |
# USE AT YOUR OWN RISK | |
# Although this script writes just ONE file (development.conf) and does not alter your Apache config file, you should still | |
# keep backup copies just to be sure. | |
# INSTALLATION | |
# place this file in a PATH directory and make it executable. | |
# If your development sites are not in /Development, change the path accordingly | |
# this file will be placed in the other folder of apache config. In case it's not loaded, check httpd.conf to make sure | |
# the other/* conf files are included | |
# SUPPORT | |
# You can ask, but I cannot promise anything. | |
while [ "$1" != "" ]; do | |
[ "--php-version" == "$1" ] && shift && PHPVERSION="$1" && shift | |
[ "--dpath" == "$1" ] && shift && DEVELOPMENTPATH="$1" && shift | |
[ "-v" == "$1" ] && shift && PHPVERSION="$1" && shift | |
[ "-p" == "$1" ] && shift && DEVELOPMENTPATH="$1" && shift | |
shift | |
done | |
# Working directory | |
# CHANGE THIS IF YOU USE A DIFFERENT LOCATION | |
# You can export the variable DEVELOPMENTPATH in your .bashrc or .bash_profile if you want and set it to | |
# the correct folder | |
export DPATH="$DEVELOPMENTPATH" | |
if [ "" == "$DPATH" ]; then | |
DPATH=/Development | |
[ -d /Volumes/Development/Websites ] && DPATH=/Volumes/Development/Websites | |
fi | |
# To avoid working with symlinks, do not edit. | |
DPATH=$(cd "$DPATH" && pwd -P) | |
# verify PHP version | |
if [ "$PHPVERSION" == "" ]; then | |
PHPVERSION=$(ls -la $(which php) | egrep -o 'php[57][450]') | |
[ "" = "$PHPVERSION" ] && [ -f "/usr/bin/php" ] && PHPVERSION=php$(php --version | egrep -o 'PHP [57]\.[0-9]' | egrep -o '[57]\.[0-9]' | sed 's/\.//') | |
echo 'php:' $(which php) '-> version' $PHPVERSION | |
fi | |
# root cannot brew, so do this before elevation | |
if [ "$(id -u)" != "0" ]; then | |
if [ "" != "$(which brew)" ]; then | |
V=$(echo $PHPVERSION | sed 's/php//') | |
[ "$V" != "" ] && [ ! -d /usr/local/Cellar/php$V ] && echo "PHP $V not installed" && brew install homebrew/php/php$V homebrew/php/php$V-mongo homebrew/php/php$V-xdebug | |
CURRENTPHPVERSION=$(ls -la $(which php) | egrep -o 'php[57][450]' | egrep -o '[57][450]') | |
if [ "$PHPVERSION" != "" ]; then | |
if [ "$CURRENTPHPVERSION" != "$V" ]; then | |
echo "Switching from PHP $CURRENTPHPVERSION to PHP $V" | |
for V in 53 54 55 56 70; do | |
[ -d /usr/local/Cellar/php$V ] && brew unlink php$V | |
done | |
shift; | |
brew link php$PHPVERSION | |
fi | |
fi | |
fi | |
fi | |
# Make sure only root can run this script | |
if [ "$(id -u)" != "0" ]; then | |
sudo "$0" --php-version $PHPVERSION --dpath "$DPATH" "$@" | |
exit 0 | |
fi | |
# from here, we are root. | |
# make sure PHPVERSION is just the number 54, 55, 56 or 70 | |
PHPVERSION=php$(echo $PHPVERSION | egrep -o '[57][450]') | |
# Set to no if you don't want to use SSL, set to auto to auto detect, set to yes to force | |
USE_SSL=auto | |
SSL_LOG_SUFFIX=_ssl | |
SSL_LOG_SUFFIX= | |
# FORCENEWCERTS=YES | |
PERDOMAINCERTS=NO | |
# TLDs | |
# CHANGE THESE IF YOU USE A TLD OTHER THAN .local | |
# You can enter more, using a space-separated list. | |
# Eample: TLDS="local dev dv" | |
TLDS="dev dv home cs" | |
# Your details | |
SSLC=NL ; # country | |
SSLST=Utrecht ; # state | |
SSLL=Nieuwegein ; # locality | |
SSLO="Clearsite Webdesigners" ; # organisation | |
SSLOU=Development ; # organisational unit | |
MYEMAIL=ik@remonpel.nl | |
# LOG path | |
LPATH="$DPATH/logs" | |
# APACHE SSL CERTIFICATE PATH | |
SPATH=/etc/apache2/ssl.crt | |
# Virtual host config file or directory, for example: /etc/apache2/extra/httpd-vhost.conf or /etc/apache2/other/ | |
# /etc/apache2/conf-enabled is for ubuntu/debian based distsributions | |
# /etc/apache2/other is the usual place on OS X/macOS | |
[ -d /etc/apache2/conf-enabled ] && VHOST=/etc/apache2/conf-enabled/ || VHOST=/etc/apache2/other/ | |
# subdirectory for the web-files | |
PHDIR=public_html | |
# Evaluate the actual path (following symlinks all the way)? YES or NO | |
PHDIR_EVAL=YES | |
# can be IPv4, IPv6, BOTH or NONE. if NONE, hosts file will not be touched | |
# when using a local DNS server for serving your TLD's, set this to NONE. | |
NETMODE=IPv4 | |
# CGI-BIN for FastCGI PHP - in case a different version of PHP is needed. | |
# example structure | |
# /Development/cgi-bin/ base folder. this is ofcourse your own choice and is a subfolder of $DPATH | |
CGI_SUB=cgi-bin | |
# /Development/cgi-bin/5.3.8 version folder. you download the package, so you know which version it is. | |
# /Development/cgi-bin/5.3.8/PHP5 the downloaded package. in this folder you find bin lib etc and include | |
# copy lib/php.ini to ../ see below | |
# /Development/cgi-bin/5.3.8/php-cgi cgi-bin alias script. contains: #!/bin/bash | |
# D=` dirname "$0" `; [ "$D" == "." ] && D=` pwd -P ` | |
# exec "$D"/PHP5/bin/php-cgi \"$@\" | |
# /Development/cgi-bin/5.3.8/php.ini this is the ini file copied from the package/lib/ folder | |
# no more configuration after this | |
# editing below this line is for advanced users only | |
# make sure log path exists | |
[ ! -d "$LPATH" ] && mkdir $LPATH | |
# migrate the path we created ourselves to the path ubuntu/debian uses, but only if the path is in use | |
[ "$SPATH" = "/etc/apache2/ssl.crt" ] && [ -d /etc/apache2/ssl.key ] && [ ! -d /etc/apache2/ssl.crt ] && mv /etc/apache2/ssl.{key,crt} | |
# module path | |
[ -d /usr/lib/apache2/modules ] && MODPATH=/usr/lib/apache2/modules || MODPATH=libexec/apache2 | |
#autodetect SSL | |
[ -f "$SPATH"/server.crt ] && [ "$USE_SSL" != "no" ] && USE_SSL=yes | |
# function for easy stderr | |
a_message () { | |
echo $1 >&2 | |
} | |
RBATOKEN="#rba_line_do_not_edit" | |
# for the domain list in hosts file | |
a_host () { | |
LOCAL=YES | |
IP="127.0.0.1" | |
IP6="::1" | |
NM=$NETMODE | |
# a bit redundant here, but it's readable | |
while [ "$1" != "" ]; do | |
[ "--ip" == "$1" ] && shift && IP="$1" && shift && LOCAL=NO | |
[ "--ip6" == "$1" ] && shift && IP6="$1" && shift && LOCAL=NO | |
[ "$LOCAL" == "NO" ] && [ "$IP6" == "::1" ] && [ "$NETMODE" == "BOTH" ] && NETMODE=IPv4 | |
[ "$NETMODE" == "IPv4" ] && echo "$IP $1 $RBATOKEN" >> /tmp/hosts$$ | |
[ "$NETMODE" == "IPv6" ] && echo "$IP6 $1 $RBATOKEN" >> /tmp/hosts$$ | |
[ "$NETMODE" == "BOTH" ] && echo "$IP $1 $RBATOKEN" >> /tmp/hosts$$ | |
[ "$NETMODE" == "BOTH" ] && echo "$IP6 $1 $RBATOKEN" >> /tmp/hosts$$ | |
shift | |
done | |
NETMODE=$NM | |
} | |
read_hosts () { | |
[ "$NETMODE" != "NONE" ] && cat /etc/hosts | grep -v "$RBATOKEN" > /tmp/hosts$$ | |
} | |
write_hosts () { | |
[ "$NETMODE" != "NONE" ] && cat /tmp/hosts$$ > /etc/hosts | |
[ "$NETMODE" != "NONE" ] && rm /tmp/hosts$$ | |
} | |
getVagrantIp () { | |
cat "$1" | grep 'private_network' | egrep -o '([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)' | |
} | |
generate_openssl_ca_config () { | |
echo '[ ca ]' | |
echo 'default_ca = CA_own' | |
echo '[ CA_own ]' | |
echo 'dir = '$SPATH | |
echo 'certs = $dir' | |
echo 'new_certs_dir = $dir/ca.db.certs' | |
echo 'database = $dir/ca.db.index' | |
echo 'serial = $dir/ca.db.serial' | |
echo 'RANDFILE = $dir/ca.db.rand' | |
echo 'certificate = $dir/ca.crt' | |
echo 'private_key = $dir/ca.key' | |
echo 'default_days = 3650' | |
echo 'default_crl_days = 30' | |
echo 'default_md = md5' | |
echo 'preserve = no' | |
echo 'policy = policy_anything' | |
echo 'unique_subject = no' | |
echo '[ policy_anything ]' | |
echo 'countryName = optional' | |
echo 'stateOrProvinceName = optional' | |
echo 'localityName = optional' | |
echo 'organizationName = optional' | |
echo 'organizationalUnitName = optional' | |
echo 'commonName = supplied' | |
echo 'emailAddress = optional' | |
} | |
generate_openssl_req_config () { | |
echo '[ req ]' | |
echo 'default_bits = 2048' | |
echo 'default_keyfile = privkey.pem' | |
echo 'distinguished_name = req_distinguished_name' | |
echo 'req_extensions = req_ext # The extentions to add to the self signed cert' | |
echo '' | |
echo '[ req_distinguished_name ]' | |
echo 'countryName = Country Name (2 letter code)' | |
echo 'countryName_default = US' | |
echo 'stateOrProvinceName = State or Province Name (full name)' | |
echo 'stateOrProvinceName_default = Illinois' | |
echo 'localityName = Locality Name (eg, city)' | |
echo 'localityName_default = Chicago' | |
echo 'organizationName = Organization Name (eg, company)' | |
echo 'organizationName_default = Example, Co.' | |
echo 'commonName = Common Name (eg, YOUR name)' | |
echo 'commonName_max = 64' | |
echo '' | |
echo '[ req_ext ]' | |
echo 'subjectAltName = @alt_names' | |
echo '' | |
echo '[alt_names]' | |
generate_openssl_req_config_j=0; | |
for generate_openssl_req_config_i in $aliases; do | |
generate_openssl_req_config_j=` expr $generate_openssl_req_config_j + 1 ` | |
echo 'DNS.'$generate_openssl_req_config_j' = '$generate_openssl_req_config_i | |
done; | |
} | |
# VirtualHost Template. Change this if you must | |
a_virtual_host () { | |
CGI=no; | |
aCGI=` ls -1 "$DPATH/$1"/*.cgi 2>/dev/null | head -n 1 ` | |
[ "$aCGI" != "" ] && CGI=yes && VER=` basename $aCGI | sed 's/.cgi//' `; | |
[ "$CGI" == "yes" ] && [ ! -d "$DPATH/$CGI_SUB/$VER/" ] && CGI=no; | |
a_message "Writing VHOST config for domain $1 on $2 with aliases $3" | |
[ "$CGI" == "yes" ] && a_message " Use FastCGI version $VER" | |
echo " " | |
echo "# $1 " | |
echo " " | |
echo "<VirtualHost *:80>" | |
echo " SetEnv APP_ENV \"development\" " | |
if [ "$CGI" == "yes" ]; then | |
echo "ScriptAlias /cgi-bin/ $DPATH/$CGI_SUB/$VER/" | |
echo "AddHandler php-fcgi .php" | |
echo "Action php-fcgi /cgi-bin/php-cgi" | |
fi | |
echo " ServerAdmin $MYEMAIL" | |
echo " ServerName $1" | |
echo " ServerAlias $3" | |
echo " DocumentRoot \"$2\"" | |
echo " Options +FollowSymlinks" | |
echo " ErrorLog \"$LPATH/` echo $i | sed 's/\./_/g' `_error_log\"" | |
echo " CustomLog \"$LPATH/` echo $i | sed 's/\./_/g' `_access_log\" common" | |
echo " php_value html_errors On" | |
echo " KeepAlive On" | |
echo " KeepAliveTimeout 5" | |
echo " php_value error_reporting 22517" | |
echo " php_value display_errors On" | |
[ -f "$DPATH/global.php" ] && [ ! -f "$DPATH/$i/noglobal" ] && echo " php_value auto_prepend_file $DPATH/global.php" | |
echo "</VirtualHost>" | |
if [ "$USE_SSL" == "yes" ]; then | |
# individual certificates | |
if [ "$PERDOMAINCERTS" == "YES" ]; then | |
if [ -d "$DPATH"/"$1" ]; then | |
[ "$FORCENEWCERTS" == "YES" ] && [ -f "$DPATH"/"$1"/ssl.key ] && rm "$DPATH"/"$1"/ssl.key | |
[ "$FORCENEWCERTS" == "YES" ] && [ -f "$DPATH"/"$1"/ssl.cnf ] && rm "$DPATH"/"$1"/ssl.cnf | |
[ ! -f "$SPATH"/openssl.cnf ] && generate_openssl_ca_config > "$SPATH"/openssl.cnf | |
[ ! -f "$DPATH"/"$1"/ssl.cnf ] && generate_openssl_req_config > "$DPATH"/"$1"/ssl.cnf | |
pushd "$SPATH" >/dev/null 2>&1 | |
if [ ! -f "$DPATH"/"$1"/ssl.key ]; then | |
# generate key | |
openssl genrsa -des3 -passout pass:nopasswordhere -out "$DPATH"/"$1"/ssl.key 2048 -noout | |
# Remove passphrase from the key. Comment the line out to keep the passphrase | |
openssl rsa -in "$DPATH"/"$1"/ssl.key -passin pass:nopasswordhere -out "$DPATH"/"$1"/ssl.key | |
# remove the csr, it's no longer valid | |
[ -f "$DPATH"/"$1"/ssl.csr ] && rm "$DPATH"/"$1"/ssl.csr | |
fi | |
# generate CSR | |
if [ ! -f "$DPATH"/"$1"/ssl.csr ]; then | |
openssl req -new -key "$DPATH"/"$1"/ssl.key -out "$DPATH"/"$1"/ssl.csr -config "$DPATH"/"$1"/ssl.cnf \ | |
-subj "/C=$SSLC/ST=$SSLST/L=SSSLL/O=$SSLO/OU=$SSLOU/CN=$1/emailAddress=$MYEMAIL" | |
# openssl req -new -key $domain.key -out $domain.csr -passin pass:$password \ | |
# -subj "/C=$country/ST=$state/L=$locality/O=$organization/OU=$organizationalunit/CN=$commonname/emailAddress=$email" | |
# remove the certificate, it's no longer valid | |
[ -f "$DPATH"/"$1"/ssl.crt ] && rm "$DPATH"/"$1"/ssl.crt | |
fi | |
# sign the certificate | |
if [ ! -f "$DPATH"/"$1"/ssl.crt ]; then | |
openssl ca -batch -config "$SPATH"/openssl.cnf -out "$DPATH"/"$1"/ssl.crt -infiles "$DPATH"/"$1"/ssl.csr | |
fi | |
chown `logname` "$DPATH"/"$1"/ssl.* | |
popd >/dev/null 2>&1 | |
fi | |
else | |
[ -f "$DPATH"/"$1"/ssl.crt ] && rm "$DPATH"/"$1"/ssl.* | |
fi | |
echo "<VirtualHost *:443>" | |
echo " SetEnv APP_ENV \"development\" " | |
if [ "$CGI" == "yes" ]; then | |
echo "ScriptAlias /cgi-bin/ $DPATH/$CGI_SUB/$VER/" | |
echo "AddHandler php-fcgi .php" | |
echo "Action php-fcgi /cgi-bin/php-cgi" | |
fi | |
echo " ServerAdmin $MYEMAIL" | |
echo " ServerName $1" | |
echo " ServerAlias $3" | |
echo " DocumentRoot \"$2\"" | |
echo " Options +FollowSymlinks" | |
echo " ErrorLog \"$LPATH/` echo $i | sed 's/\./_/g' `${SSL_LOG_SUFFIX}_error_log\"" | |
echo " CustomLog \"$LPATH/` echo $i | sed 's/\./_/g' `${SSL_LOG_SUFFIX}_access_log\" common" | |
echo " php_value html_errors On" | |
echo " KeepAlive On" | |
echo " KeepAliveTimeout 5" | |
echo " php_value error_reporting 22517" | |
echo " php_value display_errors On" | |
[ -f "$DPATH/global.php" ] && [ ! -f "$DPATH/$i/noglobal" ] && echo " php_value auto_prepend_file $DPATH/global.php" | |
echo " SSLEngine On" | |
# site key or server key | |
[ -f "$DPATH"/"$1"/ssl.key ] && echo " SSLCertificateKeyFile $DPATH/$1/ssl.key" | |
[ ! -f "$DPATH"/"$1"/ssl.key ] && echo " SSLCertificateKeyFile $SPATH/server.key" | |
# site sert or server cert | |
[ -f "$DPATH"/"$1"/ssl.crt ] && echo " SSLCertificateFile $DPATH/$1/ssl.crt" | |
[ ! -f "$DPATH"/"$1"/ssl.crt ] && echo " SSLCertificateFile $SPATH/server.crt" | |
echo "</VirtualHost>" | |
else | |
[ -f "$DPATH"/"$1"/ssl.crt ] && rm "$DPATH"/"$1"/ssl.* | |
fi | |
} | |
a_message "Rebuilding Apache2 VirtualHost list" | |
[ -d "$VHOST" ] && VHOSTFILE="$VHOST/development.conf" | |
[ -f "$VHOST" ] && VHOSTFILE="$VHOST" | |
# TODO: Switch from single config file to multiple config files; | |
# ONLY in case the VHOST variable holds a FOLDER | |
# | |
# outside TLD loop: | |
# write a development.conf for the directory configuration | |
# | |
# inside TLD loop: | |
# write a development.$tld.conf for every tld with the fallback | |
# write a development.$tld.$projectFolderBasename.conf for every project. | |
# list all development.$tld.*.conf and check if conf is still needed. remove if not | |
touch /tmp/conf$$ | |
read_hosts | |
echo "" > /tmp/conf$$ | |
echo "LoadModule ${PHPVERSION:0:4}_module /usr/local/opt/${PHPVERSION}/${MODPATH}/lib${PHPVERSION:0:4}.so" >> /tmp/conf$$ | |
echo "AddType application/x-httpd-php .php" >> /tmp/conf$$ | |
echo "DirectoryIndex index.php" >> /tmp/conf$$ | |
echo "LoadModule rewrite_module ${MODPATH}/mod_rewrite.so" >> /tmp/conf$$ | |
echo "LoadModule socache_shmcb_module ${MODPATH}/mod_socache_shmcb.so" >> /tmp/conf$$ | |
echo "<IfVersion >= 2.4>" >> /tmp/conf$$ | |
echo "LoadModule access_compat_module ${MODPATH}/mod_access_compat.so" >> /tmp/conf$$ | |
echo "</IfVersion>" >> /tmp/conf$$ | |
[ "$USE_SSL" == "yes" ] && echo "LoadModule ssl_module ${MODPATH}/mod_ssl.so" >> /tmp/conf$$ | |
[ "$USE_SSL" == "yes" ] && echo "Include /private/etc/apache2/extra/httpd-ssl.conf" >> /tmp/conf$$ | |
[ "$USE_SSL" == "yes" ] && echo "SSLVerifyClient none" >> /tmp/conf$$ | |
echo "<Directory \"$DPATH\">" >> /tmp/conf$$ | |
echo " Options Indexes FollowSymLinks MultiViews" >> /tmp/conf$$ | |
echo " AllowOverride All" >> /tmp/conf$$ | |
echo " <IfVersion >= 2.4>" >> /tmp/conf$$ | |
echo " Require all granted" >> /tmp/conf$$ | |
echo " </IfVersion>" >> /tmp/conf$$ | |
echo " <IfVersion < 2.4>" >> /tmp/conf$$ | |
echo " Order allow,deny" >> /tmp/conf$$ | |
echo " Allow from all" >> /tmp/conf$$ | |
echo " </IfVersion>" >> /tmp/conf$$ | |
echo "</Directory>" >> /tmp/conf$$ | |
echo "" >> /tmp/conf$$ | |
echo " <IfVersion < 2.4>" >> /tmp/conf$$ | |
echo "NameVirtualHost *:80" >> /tmp/conf$$ | |
echo "NameVirtualHost *:443" >> /tmp/conf$$ | |
echo "</IfVersion>" >> /tmp/conf$$ | |
DEFPATH=no | |
[ -d "$DPATH/default" ] && DEFPATH=$DPATH/default | |
for tld in $TLDS; do | |
if [ "no" != "$DEFPATH" ]; then | |
a_message "Writing fallback for $tld to $DEFPATH" | |
a_virtual_host "development.$tld" "$DEFPATH" "www.development.$tld" >> /tmp/conf$$ | |
a_host "development.$tld" | |
fi | |
for i in ` ls -1 "$DPATH" | egrep "\.$tld$" `; do | |
aliases="www.$i" | |
[ -f "$DPATH/$i/aliases" ] && aliases=` cat "$DPATH/$i/aliases" ` | |
if [ -f "$DPATH/$i/Vagrantfile" ]; then | |
VAGRIP=` getVagrantIp "$DPATH/$i/Vagrantfile"` | |
a_message "Writing Vagrant VM IP to host file for domain $i on $VAGRIP with aliases $aliases" | |
a_host --ip $VAGRIP $i $aliases | |
elif [ -f "$DPATH/$i/remoteip" ]; then | |
a_message "Writing Remote IP to host file for domain $i on $(cat "$DPATH/$i/remoteip") with aliases $aliases" | |
a_host --ip $(cat "$DPATH/$i/remoteip") $i $aliases | |
else | |
if [ "$PHDIR_EVAL" == "YES" ] && [ -L "$DPATH/$i/$PHDIR" ]; then | |
ABSPATH=` cd "$DPATH/$i/$PHDIR" && pwd -P ` | |
a_virtual_host "$i" "$ABSPATH" "$aliases" >> /tmp/conf$$ | |
elif [ -d "$DPATH/$i/$PHDIR" ]; then | |
a_virtual_host "$i" "$DPATH/$i/$PHDIR" "$aliases" >> /tmp/conf$$ | |
else | |
a_virtual_host "$i" "$DPATH/$i" "$aliases" >> /tmp/conf$$ | |
fi | |
a_host $i $aliases | |
fi | |
done | |
done | |
cat /tmp/conf$$ > $VHOSTFILE | |
rm /tmp/conf$$ | |
write_hosts | |
echo Restarting Apache && apachectl restart | |
[ ` apachectl configtest 2>&1 | grep 'Syntax OK' | wc -l ` -gt 0 ] && echo "All ok. Get crackin'!" && exit 0 | |
[ ` apachectl configtest 2>&1 | grep 'Syntax OK' | wc -l ` -eq 0 ] && echo "HELP! Something went wrong. Please review the config files" && apachectl configtest && exit 1 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment