# See the License for the specific language governing permissions and
# limitations under the License.
-# run as root.
[[ $EUID == 0 ]] || exec sudo -E "$BASH_SOURCE" "$@"
set -eE -o pipefail
usage() {
cat <<EOF
-Usage: ${0##*/} [EXTRA_SETTINGS_FILE] DOMAIN
+Usage: ${0##*/} [OPTIONS] [EXTRA_SETTINGS_FILE] DOMAIN
Setup apache virtualhost config with https using
ssl config provided by let's encrypt and my standard
location for storing certs.
EXTRA_SETTINGS_FILE can be - for stdin
--p PORT
--i Insecure, no ssl
--c CERT_DIR Default is /p/c/machine_specific/\$HOSTNAME/webservercerts
--h|--help Print help and exit
--r DocumentRoot
--- Subsequent arguments are never treated as options
-
-Note: options and non-options can be in any order.
+-c CERT_DIR In priority: this arg, $ACME_TINY_WRAPPER_CERT_DIR,
+ $HOME/webservercerts, if the other options aren't set.
+-f [ADDR:]PORT Enable proxy to [ADDR:]PORT. ADDR default is 127.0.0.1
+-i Insecure, no ssl
+-p PORT Main port to listen on, default 443
+-r DocumentRoot
+-h|--help Print help and exit
+
+Note: Uses GNU getopt options parsing style
EOF
exit $1
}
##### begin command line parsing ########
-cert_dir=/p/c/machine_specific/$HOSTNAME/webservercerts
+cert_dir="$ACME_TINY_WRAPPER_CERT_DIR"
+if [[ ! $cert_dir ]]; then
+ cert_dir=$HOME/webservercerts
+fi
ssl=true
extra_settings=
-args=()
-port="*:443"
-while [[ $1 ]]; do
+port=443
+temp=$(getopt -l help ic:f:p:r:h "$@") || usage 1
+eval set -- "$temp"
+while true; do
case $1 in
- -i) ssl=false; shift ;; # i for insecure
-c) cert_dir="$2"; shift 2 ;;
+ -f) proxy="$2"; shift 2 ;;
+ -i) ssl=false; shift ;;
-p) port="$2"; shift 2 ;;
-r) root="$2"; shift 2 ;;
--) shift; break ;;
- -?*|-h|--help) usage ;;
- *) args+=("$1"); shift ;;
+ -h|--help) usage ;;
+ *) echo "$0: Internal error!" ; exit 1 ;;
esac
done
-args+=("$@")
-if (( ${#args[@]} == 2 )); then
- read extra_settings h <<<"${args[@]}"
+if (( ${#@} == 2 )); then
+ read -r extra_settings h <<<"${@}"
else
- read h <<<"${args[@]}"
+ read -r h <<<"${@}"
fi
if [[ ! $h ]]; then
root=/var/www/$h/html
fi
+if [[ $proxy ]]; then
+ [[ $proxy == *:* ]] || proxy=127.0.0.1:$proxy
+fi
+
##### end command line parsing ########
rm -f /etc/apache2/sites-enabled/000-default.conf
mkdir -p $root
-dd of=/etc/apache2/sites-enabled/$h.conf <<EOF
-<VirtualHost $port>
+vhost_file=/etc/apache2/sites-enabled/$h.conf
+redir_file=/etc/apache2/sites-enabled/httpsredir.conf
+
+# note, we exepct ServerRoot of /etc/apache2
+# apache requires exactly 1 listen directive per port (when no ip is also given),
+# so we have to parse the config to do it programatically.
+listen_80=false
+listen_port=false
+cd /etc/apache2
+conf_files=(apache2.conf)
+for (( i=0; i < ${#conf_files[@]}; i++ )); do
+ f="${conf_files[i]}"
+ # note: globs are expanded here:
+ conf_files+=( $(sed -rn "s,^\s*Include(Optional)?\s+(\S+).*,\2,p" "$f") )
+ case $(readlink -f "$f") in
+ $vhost_file|$redir_file) continue ;;
+ esac
+ for p in $(sed -rn "s,^\s*listen\s+(\S+).*,\1,Ip" "$f"); do
+ case $p in
+ 80) listen_80=true ;;
+ $port) listen_port=true ;;
+ esac
+ done
+done
+
+if $ssl; then
+ https_arg=" https"
+fi
+
+
+echo "$0: creating $vhost_file"
+cat >$vhost_file <<EOF
+<VirtualHost *:$port>
ServerName $h
ServerAlias www.$h
DocumentRoot $root
EOF
if [[ $extra_settings ]]; then
- cat -- $extra_settings | tee -a /etc/apache2/sites-enabled/$h.conf
+ cat -- $extra_settings >>$vhost_file
+fi
+
+# go faster!
+if [[ -e /etc/apache2/mods-available/http2.load ]]; then
+ # https://httpd.apache.org/docs/2.4/mod/mod_http2.html
+ a2enmod http2
+ cat >>$vhost_file <<EOF
+ Protocols h2 http/1.1
+EOF
+fi
+
+if [[ $proxy ]]; then
+ a2enmod proxy proxy_http
+ # fyi: trailing slash is important
+ # reference: https://httpd.apache.org/docs/2.4/howto/reverse_proxy.html
+ cat >>$vhost_file <<EOF
+ ProxyPass "/" "http://$proxy/"
+ ProxyPassReverse "/" "http://$proxy/"
+EOF
fi
if $ssl; then
- tee -a /etc/apache2/sites-enabled/$h.conf <<EOF
+ certbot_ssl_conf=/etc/letsencrypt/options-ssl-apache.conf
+ cat >>$vhost_file <<EOF
SSLCertificateFile $cert_dir/$h-chained.pem
SSLCertificateKeyFile $cert_dir/$h-domain.key
- Include /etc/letsencrypt/options-ssl-apache.conf
+ Include $certbot_ssl_conf
EOF
- dd of=/etc/apache2/sites-enabled/httpsredir.conf <<'EOF'
+ # if we are using a non-standard port, setup don't setup
+ # irrelevant 443 redirect.
+ if [[ $port == "443" ]]; then
+ echo "$0: creating $redir_file"
+ cat >$redir_file <<'EOF'
+# vhost_combined with %D (request time in microseconds)
+# this file is just a convenient place to drop it.
+LogFormat "%v:%p %h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\" %D" vhost_time_combined
<VirtualHost *:80>
ServerAdmin webmaster@localhost
DocumentRoot /var/www/html
RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,QSA,R=permanent]
</VirtualHost>
EOF
+ if ! $listen_80; then
+ cat >>$redir_file <<'EOF'
+Listen 80
+EOF
+ fi
+ fi
mkdir -p /etc/letsencrypt
- base_file=/etc/letsencrypt/options-ssl-apache.conf
# this is from cerbot, see below.
- dd of=$base_file <<'EOF'
+ echo "$0: creating $certbot_ssl_conf"
+ cat >$certbot_ssl_conf <<'EOF'
# Baseline setting to Include for SSL sites
SSLEngine on
EOF
upstream=https://github.com/certbot/certbot/raw/master/certbot-apache/certbot_apache/options-ssl-apache.conf
- if ! diff -c <(wget -q -O - $upstream) $base_file; then
+ if ! diff -c <(wget -q -O - $upstream) $certbot_ssl_conf; then
cat <<EOF
WARNING!!!!!!!!!
WARNING!!!!!!!!!
WARNING!!!!!!!!!
upstream ssl settings differ from the snapshot we have taken!!!
We diffed with this command:
-diff -c <(wget -q -O - $upstream) $base_file
+diff -c <(wget -q -O - $upstream) $certbot_ssl_conf
Update this script to take care this warning!!!!!
EOF
sleep 1
fi
fi
-tee -a /etc/apache2/sites-enabled/$h.conf <<EOF
+cat >>$vhost_file <<EOF
ErrorLog \${APACHE_LOG_DIR}/error.log
- CustomLog \${APACHE_LOG_DIR}/access.log vhost_combined
+ CustomLog \${APACHE_LOG_DIR}/access.log vhost_time_combined
</VirtualHost>
+EOF
-# vim: syntax=apache ts=4 sw=4 sts=4 sr noet
+if ! $listen_port; then
+ # reference: https://httpd.apache.org/docs/2.4/mod/mpm_common.html#listen
+ cat >>$vhost_file <<EOF
+listen ${port}${https_arg}
EOF
+fi
+
a2enmod ssl rewrite # rewrite needed for httpredir
service apache2 restart