Skip to content

Instantly share code, notes, and snippets.

@othercodes
Last active November 12, 2019 09:36
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save othercodes/9deff8dd4c39376c2bbb5c8e43960b0d to your computer and use it in GitHub Desktop.
Save othercodes/9deff8dd4c39376c2bbb5c8e43960b0d to your computer and use it in GitHub Desktop.
Apache virtual host generator.
#!/usr/bin/env bash
#
# Virtual Host Generator
#
# Apache virtual host generator.
#
# Tested on:
# - CentOS Linux release 7.5.1804 (Core)
# - Ubuntu 16.04.3 LTS
#
# Execution:
# $ sudo bash vhost.sh [-s] [-f] [domain] [username]
#
# You can also move the script into the /usr/local/bin directory
# $ mv vhost.sh /usr/local/bin/vhost
# $ chmod +x /usr/local/bin/vhost
# $ sudo vhost [-s] [-f] [domain] [username]
#
# Options
# -s Deploy virtual host with SSL.
# -f Add domain entries to /etc/hosts file
# -v Display current version.
# -h Display help information.
#
# Changelog
# v1.0.0
# - Initial release.
#
# v1.1.0
# - Now the new users are creaded with /usr/sbin/nologin|/sbin/nologin as shell.
#
if [[ "$EUID" -ne 0 ]]; then
echo "PermissionError: Please run as root or with sudo."
exit 1
fi
if [[ ! -f /etc/os-release ]]; then
echo "UndefinedOSError: Unable to determine the OS version."
exit 2
fi
source /etc/os-release
case "$ID" in
centos)
APACHE_SERVICE_UNIT="httpd.service"
APACHE_SITES_AVAILABLE_DIR="/etc/httpd/conf.d"
APACHE_SITES_ENABLED_DIR="/etc/httpd/conf.d"
APACHE_GROUP_NAME="apache"
NOLOGIN_PATH="/sbin/nologin"
;;
ubuntu)
APACHE_SERVICE_UNIT="apache2.service"
APACHE_SITES_AVAILABLE_DIR="/etc/apache2/sites-available"
APACHE_SITES_ENABLED_DIR="/etc/apache2/sites-enabled"
APACHE_GROUP_NAME="www-data"
NOLOGIN_PATH="/usr/sbin/nologin"
;;
*) echo "Unsupported OS: $ID." ;;
esac
SITES_DIR="/var/www"
SITE_PUBLIC_DIR="public"
SITE_PRIVATE_DIR="private"
SITE_LOG_DIR="log"
SITE_CRT_DIR="crt"
SITE_CGI_DIR="cgi-bin"
VHOSTS_VERSION=1.1.0
VHOST_WITH_SSL="NO"
ADD_TO_HOSTS_FILE="NO"
CFG_CHANGED="NO"
VHOST_SSL_INSTALLED="NO"
C="US"
ST="California"
L="Los Angeles"
O="Tyrell Corporation"
OU="Development"
CN=$(hostname)
while getopts svfh options; do
case $options in
s) VHOST_WITH_SSL="YES" ;;
f) ADD_TO_HOSTS_FILE="YES" ;;
v)
echo "v${VHOSTS_VERSION}"
exit 0
;;
?)
printf "Create a new virtual host for the given domain.\n\n"
printf "Usage: %s: [-v] [-s] [domain] [username]\n $0"
printf " -s Deploy virtual host with SSL.\n"
printf " -f Add domain entries to /etc/hosts file.\n"
printf " -v Display current version.\n"
printf " -p Configure the vhost to work with "
printf " -h Display help information.\n\n"
exit 2
;;
esac
done
shift $((OPTIND - 1))
if [[ -n "$1" ]] && [[ $(echo "$1" | grep -cP '(?=^.{5,254}$)(^(?:(?!\d+\.)[a-zA-Z0-9_\-]{1,63}\.?)+(?:[a-zA-Z]{2,})$)') -gt 0 ]]; then
DOMAIN_NAME="$1"
else
echo "Name of the Virtual Host (domain: example.com) to create: "
read -r DOMAIN_NAME
echo "The following URL will be set: $DOMAIN_NAME and www.$DOMAIN_NAME (y/n): "
read -r CONFIRMATION
if [[ ! $CONFIRMATION =~ ^[Yy]$ ]]; then
echo "Installation aborted!"
exit 0
fi
fi
if [[ $(echo "$DOMAIN_NAME" | grep -ciE '\.') -eq 0 ]]; then
echo "TLD has not being specified in the domain name, please provide one without dot (es, com, net): "
read -r TLD
if [[ $(echo "$TLD" | grep -cP '[a-zA-Z]{2,}') -eq 0 ]]; then
echo "Invalid TLD, aborting."
exit 0
fi
DOMAIN_NAME="$DOMAIN_NAME.$TLD"
fi
if [[ -n "$2" ]] && [[ "$2" =~ ^[a-zA-Z][a-zA-Z0-9_]*$ ]]; then
USER_NAME="$2"
else
echo "Set a username to create for the new virtual host: "
read -r USER_NAME
if [[ ! "$USER_NAME" =~ ^[a-zA-Z][a-zA-Z0-9_]*$ ]]; then
echo "The $USER_NAME does not fit the standard way, and it may cause you problems in the future."
echo "Are you sure you want to create this user? (only if you know what you are doing) [y/n]: "
read -r CONFIRMATION
if [[ ! $CONFIRMATION =~ ^[Yy]$ ]]; then
echo "Installation aborted!"
exit 0
fi
fi
fi
if [[ $(getent group "$USER_NAME" | grep -c "$USER_NAME") -eq 0 ]]; then
echo "Adding new group $USER_NAME."
groupadd "$USER_NAME"
fi
if [[ $(getent passwd "$USER_NAME" | grep -c "$USER_NAME") -eq 0 ]]; then
echo "Adding new user $USER_NAME."
useradd -M -g "$USER_NAME" -s $NOLOGIN_PATH "$USER_NAME"
fi
if [[ $(getent group "$USER_NAME" | grep -c "$APACHE_GROUP_NAME") -eq 0 ]]; then
echo "Adding new user $USER_NAME to $APACHE_GROUP_NAME group."
usermod -a -G "$USER_NAME" $APACHE_GROUP_NAME
fi
VHOST_FILE="$APACHE_SITES_AVAILABLE_DIR/$DOMAIN_NAME.conf"
if [[ ! -f $VHOST_FILE ]]; then
echo "Creating directory structure."
mkdir -p "$SITES_DIR"/"$DOMAIN_NAME"/{$SITE_PUBLIC_DIR,$SITE_PRIVATE_DIR,$SITE_LOG_DIR,$SITE_CRT_DIR,$SITE_CGI_DIR}
chown -R "$USER_NAME":"$USER_NAME" "$SITES_DIR/$DOMAIN_NAME"
chmod 775 -R "$SITES_DIR/$DOMAIN_NAME"
echo "Generating apache virtual host configuration."
echo "
<VirtualHost *:80>
ServerAdmin webmaster@$DOMAIN_NAME
ServerName $DOMAIN_NAME
ServerAlias www.$DOMAIN_NAME
DocumentRoot $SITES_DIR/$DOMAIN_NAME/$SITE_PUBLIC_DIR
ErrorLog $SITES_DIR/$DOMAIN_NAME/$SITE_LOG_DIR/error.log
CustomLog $SITES_DIR/$DOMAIN_NAME/$SITE_LOG_DIR/access.log combined
<Directory $SITES_DIR/$DOMAIN_NAME/$SITE_PUBLIC_DIR>
Options Indexes FollowSymLinks
AllowOverRide All
IndexIgnore *
Require all granted
Order Allow,Deny
Allow from all
</Directory>
</VirtualHost>
" >>"$VHOST_FILE"
chown "$USER_NAME" "$VHOST_FILE"
CFG_CHANGED="YES"
else
echo "The virtual host $DOMAIN_NAME already exists."
fi
if [[ $(grep -c '443' "$VHOST_FILE") -gt 0 ]]; then
VHOST_SSL_INSTALLED="YES"
fi
if [[ $VHOST_SSL_INSTALLED == "NO" ]] && [[ $VHOST_WITH_SSL == "YES" ]]; then
echo "Generating SSL Certificates."
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
-subj "/C=$C/ST=$ST/L=$L/O=$O/OU=$OU/CN=$CN" \
-keyout "$SITES_DIR/$DOMAIN_NAME/$SITE_CRT_DIR/$DOMAIN_NAME.key" \
-out "$SITES_DIR/$DOMAIN_NAME/$SITE_CRT_DIR/$DOMAIN_NAME.crt" 2>/dev/null
echo "
<VirtualHost *:443>
ServerAdmin webmaster@$DOMAIN_NAME
ServerName $DOMAIN_NAME
ServerAlias www.$DOMAIN_NAME
DocumentRoot $SITES_DIR/$DOMAIN_NAME/$SITE_PUBLIC_DIR
ErrorLog $SITES_DIR/$DOMAIN_NAME/$SITE_LOG_DIR/ssl-error.log
CustomLog $SITES_DIR/$DOMAIN_NAME/$SITE_LOG_DIR/ssl-access.log combined
<Directory $SITES_DIR/$DOMAIN_NAME/$SITE_PUBLIC_DIR>
Options Indexes FollowSymLinks
AllowOverRide All
IndexIgnore *
Require all granted
Order Allow,Deny
Allow from all
</Directory>
SSLEngine on
SSLCertificateFile $SITES_DIR/$DOMAIN_NAME/$SITE_CRT_DIR/$DOMAIN_NAME.crt
SSLCertificateKeyFile $SITES_DIR/$DOMAIN_NAME/$SITE_CRT_DIR/$DOMAIN_NAME.key
</VirtualHost>
" >>"$VHOST_FILE"
VHOST_SSL_INSTALLED="YES"
CFG_CHANGED="YES"
fi
if [[ ! -f "$APACHE_SITES_ENABLED_DIR/$DOMAIN_NAME.conf" ]]; then
case "$ID" in
ubuntu)
echo "Activating virtual host."
a2ensite "$DOMAIN_NAME" 2>/dev/null
;;
esac
fi
if [[ $CFG_CHANGED == "YES" ]]; then
echo "Reloading $APACHE_SERVICE_UNIT."
systemctl reload $APACHE_SERVICE_UNIT
fi
if [[ $ADD_TO_HOSTS_FILE == "YES" ]] && [[ $(grep -c "$DOMAIN_NAME" "/etc/hosts") -eq 0 ]]; then
echo "Adding domain entries to /etc/hosts file."
for IP in $(hostname -I); do
echo -e "$IP\t$DOMAIN_NAME " >>/etc/hosts
done
echo -e "127.0.0.1\t$DOMAIN_NAME " >>/etc/hosts
fi
echo "============================ SUMMARY ============================"
echo "Domain: $DOMAIN_NAME"
echo "User: $USER_NAME"
echo "VHost File: $VHOST_FILE"
echo "VHost Directory: $SITES_DIR/$DOMAIN_NAME"
echo "SSL Support: $VHOST_SSL_INSTALLED"
if [[ $VHOST_SSL_INSTALLED == "YES" ]]; then
echo "SSL Key File: $SITES_DIR/$DOMAIN_NAME/$SITE_CRT_DIR/$DOMAIN_NAME.key"
echo "SSL Cert File: $SITES_DIR/$DOMAIN_NAME/$SITE_CRT_DIR/$DOMAIN_NAME.crt"
fi
echo "Server Name: $(hostname)"
echo "Server IP: $(hostname -I)"
echo "================================================================="
echo "Add following lines to /etc/hosts file if no DNS server available"
for IP in $(hostname -I); do
if [[ -n "$SSH_CONNECTION" ]]; then
if [[ $(echo "$SSH_CONNECTION" | cut -d " " -f 3) == "$IP" ]]; then
echo -e "$IP\t$DOMAIN_NAME"
fi
else
echo -e "$IP\t$DOMAIN_NAME"
fi
done
echo "================================================================="
echo "Have a nice day ;)"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment