move apache ssl file to avoid certbot owned dir
[basic-https-conf] / apache-site
index 9a22d2aad73a308d4bffc0b4fd6c6e2a85e2dcf7..8ff08b8d63594bdffd2dbb19dea991d31cf41a3f 100755 (executable)
 set -eE -o pipefail
 trap 'echo "$0:$LINENO:error: \"$BASH_COMMAND\" returned $?" >&2' ERR
 
 set -eE -o pipefail
 trap 'echo "$0:$LINENO:error: \"$BASH_COMMAND\" returned $?" >&2' ERR
 
+shopt -s nullglob # used in apache config file expansion
+
 usage() {
     cat <<EOF
 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.
 Setup apache virtualhost config with https using
 ssl config provided by let's encrypt and my standard
 location for storing certs.
@@ -28,9 +30,10 @@ location for storing certs.
 EXTRA_SETTINGS_FILE can be - for stdin
 -c CERT_DIR       In priority: this arg, $ACME_TINY_WRAPPER_CERT_DIR,
                   $HOME/webservercerts, if the other options aren't set.
 EXTRA_SETTINGS_FILE can be - for stdin
 -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
 -i                Insecure, no ssl
--p PORT           Main port to listen on, default 443
--r                DocumentRoot
+-p PORT           Main port to listen on, default 443. 80 implies -i.
+-r DIR            DocumentRoot
 -h|--help         Print help and exit
 
 Note: Uses GNU getopt options parsing style
 -h|--help         Print help and exit
 
 Note: Uses GNU getopt options parsing style
@@ -46,13 +49,14 @@ if [[ ! $cert_dir ]]; then
 fi
 ssl=true
 extra_settings=
 fi
 ssl=true
 extra_settings=
-port="*:443"
-temp=$(getopt -l help ic:p:r:h "$@") || usage 1
+port=443
+temp=$(getopt -l help ic:f:p:r:h "$@") || usage 1
 eval set -- "$temp"
 while true; do
     case $1 in
 eval set -- "$temp"
 while true; do
     case $1 in
-        -i) ssl=false; shift ;;
         -c) cert_dir="$2"; shift 2 ;;
         -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 ;;
         -p) port="$2"; shift 2 ;;
         -r) root="$2"; shift 2 ;;
         --) shift; break ;;
@@ -76,6 +80,10 @@ if [[ ! $root ]]; then
     root=/var/www/$h/html
 fi
 
     root=/var/www/$h/html
 fi
 
+if [[ $proxy ]]; then
+    [[ $proxy == *:* ]] || proxy=127.0.0.1:$proxy
+fi
+
 
 ##### end command line parsing ########
 
 
 ##### end command line parsing ########
 
@@ -95,35 +103,89 @@ rm -f /etc/apache2/sites-enabled/000-default.conf
 
 mkdir -p $root
 vhost_file=/etc/apache2/sites-enabled/$h.conf
 
 mkdir -p $root
 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)
+
+
+if [[ $port == 80 ]]; then
+    ssl=false
+    # remove any thats hanging around
+    rm -f $redir_file
+fi
+
+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
 cat >$vhost_file <<EOF
-<VirtualHost $port>
+<VirtualHost *:$port>
         ServerName $h
         ServerAlias www.$h
         DocumentRoot $root
 EOF
 
 if [[ $extra_settings ]]; then
         ServerName $h
         ServerAlias www.$h
         DocumentRoot $root
 EOF
 
 if [[ $extra_settings ]]; then
-    cat -- $extra_settings | tee -a $vhost_file
+    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
 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
-tee -a $vhost_file <<EOF
+    cat >>$vhost_file <<EOF
         Protocols h2 http/1.1
 EOF
 fi
 
         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
 if $ssl; then
-    certbot_ssl_conf=/etc/letsencrypt/options-ssl-apache.conf
-    tee -a $vhost_file <<EOF
+    certbot_ssl_conf=/etc/apache2/apache-site-ssl.conf
+    cat >>$vhost_file <<EOF
         SSLCertificateFile $cert_dir/$h-chained.pem
         SSLCertificateKeyFile $cert_dir/$h-domain.key
         Include $certbot_ssl_conf
 EOF
 
         SSLCertificateFile $cert_dir/$h-chained.pem
         SSLCertificateKeyFile $cert_dir/$h-domain.key
         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
 # 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
@@ -140,11 +202,18 @@ RewriteEngine on
 RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,QSA,R=permanent]
 </VirtualHost>
 EOF
 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
 
     # this is from cerbot, see below.
 
     mkdir -p /etc/letsencrypt
 
     # this is from cerbot, see below.
-     cat >$certbot_ssl_conf <<'EOF'
+    echo "$0: creating $certbot_ssl_conf"
+    cat >$certbot_ssl_conf <<'EOF'
 # Baseline setting to Include for SSL sites
 
 SSLEngine on
 # Baseline setting to Include for SSL sites
 
 SSLEngine on
@@ -184,14 +253,21 @@ Update this script to take care this warning!!!!!
 EOF
         sleep 1
     fi
 EOF
         sleep 1
     fi
-fi
-tee -a $vhost_file <<EOF
+fi # end if $ssl
+
+cat >>$vhost_file <<EOF
         ErrorLog \${APACHE_LOG_DIR}/error.log
         CustomLog \${APACHE_LOG_DIR}/access.log vhost_time_combined
 </VirtualHost>
         ErrorLog \${APACHE_LOG_DIR}/error.log
         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
 EOF
+fi
+
 
 a2enmod ssl rewrite # rewrite needed for httpredir
 service apache2 restart
 
 a2enmod ssl rewrite # rewrite needed for httpredir
 service apache2 restart