add new option
[basic-https-conf] / web-conf
index 61b735be95269f415e84e152d4ae86df49120e22..eb87f17d93670d7b8903495dfebb5eff99c58531 100755 (executable)
--- a/web-conf
+++ b/web-conf
 #!/bin/bash
-# Copyright (C) 2016 Ian Kelling
+# This file is part of web-conf which configures web servers
+# Copyright (C) 2024  Ian Kelling
 
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
 
-#     http://www.apache.org/licenses/LICENSE-2.0
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
 
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the 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/>.
+
+# SPDX-License-Identifier: GPL-3.0-or-later
 
 [[ $EUID == 0 ]] || exec sudo -E "$BASH_SOURCE" "$@"
 
 set -eE -o pipefail
 trap 'echo "$0:$LINENO:error: \"$BASH_COMMAND\" returned $?" >&2' ERR
 
+readonly this_file="$(readlink -f -- "${BASH_SOURCE[0]}")"
+readonly this_dir="${this_file%/*}"
+
 shopt -s nullglob # used in apache config file expansion
 
 usage() {
-    cat <<EOF
+  cat <<EOF
 Usage: ${0##*/} [OPTIONS] [EXTRA_SETTINGS_FILE] apache2|nginx DOMAIN
 apache/nginx config & let's encrypt
 
 If using tls then it expects certbot to be installed and in PATH.  Also,
 certbot cronjob should be taken care of outside this script. In the
-debian package, it installs a systemd timer, which I (Ian Kelling) use
-and modify to email me on failure. You can see how I do this in my git
-repo distro-setup, and log-quiet.
+debian package, it installs a systemd timer. If a script exists (I
+expect it only on my , Ian Kelling's sytem) we install a systemd timer
+to on failure. You can see the relevant script in my git repo
+distro-setup, and log-quiet.
+
+
+/a/bin/distro-setup/certbot-renew-hook
+
 
 
 EXTRA_SETTINGS_FILE can be - for stdin
+-a IPv4_ADDR      IP address to listen on. Default all addresses.
+                  ipv6 address support could be added to this script.
+-c CERT_FOLDER    No letsencrypt. use fullchain.pem and privkey.pem in this folder.
 -e EMAIL          Contact address for let's encrypt. Default is
-                  root@\$(hostname -A|awk '{print $1}')
-                  which is root@$(hostname -A|awk '{print $1}') on this host.
+                  root@\$(hostname --fqdn')
+                  which is root@$(hostname --fqdn) on this host.
 -f [ADDR:]PORT    Enable proxy to [ADDR:]PORT. ADDR default is 127.0.0.1
 -i                Insecure, no ssl.
+-l                Allow failure of restarting apache/nginx. Useful for scripts where
+                  we want to do the configuration, but don't mind if the web
+                  server has some preexisting problem or other problem to fix later.
 -p PORT           Main port to listen on, default 443. 80 implies -i.
 -r DIR            DocumentRoot
+-s                Allow symlinks from the doucment root
+-t                No settings on documentroot.
 -h|--help         Print help and exit
 
 Note: Uses GNU getopt options parsing style
 EOF
-    exit $1
+  exit $1
 }
 
 ##### begin command line parsing ########
 
+symlinkarg=-
 ssl=true
 extra_settings=
 port=443
-temp=$(getopt -l help e:if:p:r:h "$@") || usage 1
+do_root_settings=true
+temp=$(getopt -l help a:c:e:if:lp:r:sth "$@") || usage 1
+vhostip='*'
+allow_server_fail=false
 eval set -- "$temp"
 while true; do
-    case $1 in
-        -e) email="$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 ;;
-        *) echo "$0: Internal error!" ; exit 1 ;;
-    esac
+  case $1 in
+    -a)
+      listenip="$2:"
+      vhostip="$2"
+      shift 2 ;;
+    -c) oob_cert_dir="$2"; shift 2 ;;
+    -e) email="$2"; shift 2 ;;
+    -f) proxy="$2"; shift 2 ;;
+    -i) ssl=false; shift ;;
+    -l) allow_server_fail=true; shift ;;
+    -p) port="$2"; shift 2 ;;
+    -r) root="$2"; shift 2 ;;
+    -t) do_root_settings=false; shift ;;
+    -s) symlinkarg=+; shift ;;
+    --) shift; break ;;
+    -h|--help) usage ;;
+    *) echo "$0: Internal error!" ; exit 1 ;;
+  esac
 done
 
 # t = type, h = host
 if (( ${#@} == 3 )); then
-    read -r extra_settings t h <<<"${@}"
+  read -r extra_settings t h <<<"${@}"
 else
-    read -r t h <<<"${@}"
+  read -r t h <<<"${@}"
 fi
 
 case $t in
-    apache2|nginx) : ;;
-    *) echo "$0: error: expected apache2 or nginx arg"; usage 1 ;;
+  apache2|nginx) : ;;
+  *) echo "$0: error: expected apache2 or nginx arg"; usage 1 ;;
 esac
 
 if [[ ! $h ]]; then
-    echo "$0: error: expected domain and type arg"
-    usage 1
+  echo "$0: error: expected domain and type arg"
+  usage 1
 fi
 
 if [[ ! $root ]]; then
-    root=/var/www/$h/html
+  root=/var/www/$h/html
 fi
 
 if [[ $proxy ]]; then
-    [[ $proxy == *:* ]] || proxy=127.0.0.1:$proxy
+  [[ $proxy == *:* ]] || proxy=127.0.0.1:$proxy
 fi
 
 if [[ ! $email ]]; then
-    email=root@$(hostname -A|awk '{print $1}')
+  email=root@$(hostname --fqdn)
 fi
 
 
 ##### end command line parsing ########
 
 se=/etc/$t/sites-enabled
-cert_dir=/etc/letsencrypt/live/$h
+if [[ $oob_cert_dir ]]; then
+  cert_dir="$oob_cert_dir"
+else
+  cert_dir=/etc/letsencrypt/live/$h
+fi
 
 mkdir -p $root
-vhost_file=$se/$h.conf
+case $port in
+  80|443)
+    vhost_file=$se/$h.conf
+    ;;
+  *)
+    vhost_file=$se/$h-$port.conf
+    ;;
+esac
 redir_file=$se/$h-redir.conf
 
 if [[ $port == 80 ]]; then
-    ssl=false
-    # remove any thats hanging around
-    rm -f $redir_file
+  ssl=false
+  # remove any thats hanging around
+  rm -f $redir_file
 fi
 
 
-if $ssl; then
-    f=$cert_dir/fullchain.pem
-    if [[ ! -e $f ]] || openssl x509 -checkend 86400 -noout -in $f; then
-        # cerbot needs an existing virtualhost.
-        $0 -p 80 $t $h
-        # when generating an example config, add all relevant security options:
-        # --hsts --staple-ocsp --uir
-        certbot certonly -n --must-staple --email $email --no-self-upgrade \
-                --agree-tos --${t%2} -d $h
-        rm $vhost_file
+if [[ ! $oob_cert_dir ]] && $ssl; then
+
+  $this_dir/certbot-setup $t
+
+  f=$cert_dir/fullchain.pem
+  threedays=259200 # in seconds
+  if [[ ! -e $f ]] || ! openssl x509 -checkend $threedays -noout -in $f >/dev/null; then
+    # cerbot needs an existing virtualhost.
+    $0 -p 80 $t $h
+    # when generating an example config, add all relevant security options:
+    # --hsts --staple-ocsp --uir --must-staple
+    certbot certonly -n --email $email --no-self-upgrade \
+            --agree-tos --${t%2} -d $h
+    # cleanup the call to ourselves a short bit ago
+    rm $se/$h.conf
+  fi
+  # these scripts only run on renew, that is kinda dumb.
+  export RENEWED_LINEAGE=/etc/letsencrypt/live/$h
+  for script in /etc/letsencrypt/renewal-hooks/deploy/*; do
+    if [[ -x $script ]]; then
+      "$script"
     fi
+  done
 fi
 
 
 if [[ $t == apache2 ]]; then
-    rm -f $se/000-default.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
-        echo "$f"
-        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
+  rm -f $se/000-default.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
-
-
-    cat >$vhost_file <<EOF
-<VirtualHost *:$port>
-        ServerName $h
-        ServerAlias www.$h
-        DocumentRoot $root
+  done
+
+  echo "$0: creating $vhost_file"
+  cat >$vhost_file <<EOF
+<VirtualHost $vhostip:$port>
+ServerName $h
+ServerAlias www.$h
+DocumentRoot $root
 EOF
+  if $do_root_settings; then
+    cat >>$vhost_file <<EOF
+<Directory $root>
+  Options -Indexes ${symlinkarg}FollowSymlinks
+</Directory>
+EOF
+  fi
 
-    if [[ $extra_settings ]]; then
-        cat -- $extra_settings >>$vhost_file
-    fi
+  if [[ $extra_settings ]]; then
+    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
+  # go faster!
+  if [[ -e /etc/apache2/mods-available/http2.load ]]; then
+    # https://httpd.apache.org/docs/2.4/mod/mod_http2.html
+    a2enmod -q http2
+    cat >>$vhost_file <<EOF
+Protocols h2 http/1.1
 EOF
-    fi
+  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
-        # retry=0: https://stackoverflow.com/questions/683052/why-am-i-getting-an-apache-proxy-503-error
-        cat >>$vhost_file <<EOF
-        ProxyPass "/"  "http://$proxy/" retry=0
-        ProxyPassReverse "/"  "http://$proxy/"
+  if [[ $proxy ]]; then
+    a2enmod -q proxy proxy_http
+    # fyi: trailing slash is important
+    # reference: https://httpd.apache.org/docs/2.4/howto/reverse_proxy.html
+    # retry=0: https://stackoverflow.com/questions/683052/why-am-i-getting-an-apache-proxy-503-error
+    cat >>$vhost_file <<EOF
+ProxyPass "/"  "http://$proxy/" retry=0
+ProxyPassReverse "/"  "http://$proxy/"
 EOF
-    fi
+  fi
 
 
-    if $ssl; then
-        a2enmod headers
-        https_arg=" https"
-        common_ssl_conf=/etc/apache2/common-ssl.conf
-        cat >>$vhost_file <<EOF
-        SSLCertificateFile $cert_dir/fullchain.pem
-        SSLCertificateKeyFile $cert_dir/privkey.pem
-        Include $common_ssl_conf
-        # From cerbot generated config example, taken 4/2017,
-        # should be rechecked once a year or so.
-        Header always set Strict-Transport-Security "max-age=31536000"
-        SSLUseStapling on
-        Header always set Content-Security-Policy upgrade-insecure-requests
+  if $ssl; then
+    a2enmod -q headers
+    https_arg=" https"
+    common_ssl_conf=/etc/apache2/common-ssl.conf
+    cat >>$vhost_file <<EOF
+SSLCertificateFile $cert_dir/fullchain.pem
+SSLCertificateKeyFile $cert_dir/privkey.pem
+Include $common_ssl_conf
+# From cerbot generated config example, taken 4/2017,
+# should be rechecked once a year or so.
+Header always set Strict-Transport-Security "max-age=31536000"
+SSLUseStapling on
+Header always set Content-Security-Policy upgrade-insecure-requests
 EOF
 
-        echo "$0: creating $redir_file"
-        cat >$redir_file <<EOF
+    if (( port == 443 )); then
+      echo "$0: creating $redir_file"
+
+      # note, alternatively:
+      cat >/dev/null <<'EOF'
+#https://webmasters.stackexchange.com/questions/124635/apache-redirect-http-to-https-without-preventing-http
+<If "%{req:Upgrade-Insecure-Requests} == '1'">
+Redirect permanent "/" "https://mydomain.ltd/"
+</If>
+# or, with generic rewrite, we use this on gnu.org
+RewriteEngine on
+RewriteCond %{HTTP:Upgrade-Insecure-Requests} "^1$"
+RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,QSA,R=307]
+EOF
+
+      cat >$redir_file <<EOF
 <VirtualHost *:80>
-        ServerName $h
-        ServerAdmin webmaster@localhost
-        DocumentRoot /var/www/html
+ServerName $h
+ServerAdmin webmaster@localhost
+DocumentRoot /var/www/html
 
-        ErrorLog \${APACHE_LOG_DIR}/error.log
-        CustomLog \${APACHE_LOG_DIR}/access.log vhost_time_combined
+ErrorLog \${APACHE_LOG_DIR}/error.log
+CustomLog \${APACHE_LOG_DIR}/access.log vhost_time_combined
 
-        RewriteEngine on
-        RewriteCond %{SERVER_NAME} =$h
-        RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,QSA,R=permanent]
+RewriteEngine on
+RewriteCond %{SERVER_NAME} =$h
+RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,QSA,R=permanent]
 </VirtualHost>
 EOF
-        if ! $listen_80; then
-            cat >>$redir_file <<'EOF'
+      if ! $listen_80; then
+        cat >>$redir_file <<'EOF'
 Listen 80
 EOF
-        fi
+      fi
+    fi
 
-        # this is a copy of a file certbot, see below.
-        echo "$0: creating $common_ssl_conf"
-        cat >$common_ssl_conf <<'EOF'
-# Baseline setting to Include for SSL sites
+    # this is a copy of a file certbot, see below.
+    echo "$0: creating $common_ssl_conf"
+    cat >$common_ssl_conf <<'EOF'
+# This file contains important security parameters. If you modify this file
+# manually, Certbot will be unable to automatically provide future security
+# updates. Instead, Certbot will print and log an error message with a path to
+# the up-to-date file that you will need to refer to when manually updating
+# this file. Contents are based on https://ssl-config.mozilla.org
 
 SSLEngine on
 
 # Intermediate configuration, tweak to your needs
-SSLProtocol             all -SSLv2 -SSLv3
-SSLCipherSuite          ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA
-SSLHonorCipherOrder     on
-SSLCompression          off
+SSLProtocol             all -SSLv2 -SSLv3 -TLSv1 -TLSv1.1
+SSLCipherSuite          ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384
+SSLHonorCipherOrder     off
+SSLSessionTickets       off
 
 SSLOptions +StrictRequire
 
 # Add vhost name to log entries:
 LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-agent}i\"" vhost_combined
 LogFormat "%v %h %l %u %t \"%r\" %>s %b" vhost_common
-
-#CustomLog /var/log/apache2/access.log vhost_combined
-#LogLevel warn
-#ErrorLog /var/log/apache2/error.log
-
-# Always ensure Cookies have "Secure" set (JAH 2012/1)
-#Header edit Set-Cookie (?i)^(.*)(;\s*secure)??((\s*;)?(.*)) "$1; Secure$3$4"
 EOF
 
-        upstream=https://github.com/certbot/certbot/raw/master/certbot-apache/certbot_apache/options-ssl-apache.conf
-        if ! diff -c <(wget -q -O - $upstream) $common_ssl_conf; then
-            cat <<EOF
+    upstream=https://raw.githubusercontent.com/certbot/certbot/master/certbot-apache/certbot_apache/_internal/tls_configs/current-options-ssl-apache.conf
+    if ! diff -u <(wget -q -O - $upstream) $common_ssl_conf; then
+      cat <<EOF
 WARNING!!!!!!!!!
 WARNING!!!!!!!!!
 WARNING!!!!!!!!!
@@ -263,48 +336,55 @@ We diffed with this command:
 diff -c <(wget -q -O - $upstream) $common_ssl_conf
 Update this script to take care this warning!!!!!
 EOF
-            sleep 1
-        fi
-    fi # end if $ssl
+      sleep 1
+    fi
+  fi # end if $ssl
 
-    cat >>$vhost_file <<'EOF'
-        ErrorLog ${APACHE_LOG_DIR}/error.log
-        CustomLog ${APACHE_LOG_DIR}/access.log vhost_time_combined
+  cat >>$vhost_file <<'EOF'
+ErrorLog ${APACHE_LOG_DIR}/error.log
+CustomLog ${APACHE_LOG_DIR}/access.log vhost_time_combined
 </VirtualHost>
 EOF
 
-    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}
+  if ! $listen_port; then
+    # reference: https://httpd.apache.org/docs/2.4/mod/mpm_common.html#listen
+    cat >>$vhost_file <<EOF
+listen ${listenip}${port}${https_arg}
 EOF
-    fi
+  fi
 
 
-    a2enmod ssl rewrite # rewrite needed for httpredir
+  a2enmod -q ssl rewrite # rewrite needed for httpredir
+
+  if $allow_server_fail; then
+    if ! service apache2 restart; then
+      echo "$0: warning: apache2 restart failed. ignoring due to -l flag" >&2
+    fi
+  else
     service apache2 restart
+  fi
 
-    # I rarely look at how much traffic I get, so let's keep that info
-    # around for longer than the default of 2 weeks.
-    sed -ri --follow-symlinks 's/^(\s*rotate\s).*/\1 365/' /etc/logrotate.d/apache2
+  # I rarely look at how much traffic I get, so let's keep that info
+  # around for longer than the default of 2 weeks.
+  sed -ri --follow-symlinks 's/^(\s*rotate\s).*/\1 365/' /etc/logrotate.d/apache2
 fi  ###### end if apache
 
 if [[ $t == nginx ]]; then
-    common_ssl_conf=/etc/nginx/common-ssl.conf
-
-    rm -f $se/default
-    cd /etc/nginx
-    [[ -e dh2048.pem ]] || openssl dhparam -out dh2048.pem 2048
-
-    if $ssl; then
-        ssl_arg=ssl
-        if nginx -V |& grep -- '--with-http_v2_module\b' &>/dev/null; then
-            # fun fact: nginx can be configured to do http2 without ssl.
-            ssl_arg+=" http2"
-        fi
+  common_ssl_conf=/etc/nginx/common-ssl.conf
+
+  rm -f $se/default
+  cd /etc/nginx
+  [[ -e dh2048.pem ]] || openssl dhparam -out dh2048.pem 2048
+
+  if $ssl; then
+    ssl_arg=ssl
+    if nginx -V |& grep -- '--with-http_v2_module\b' &>/dev/null; then
+      # fun fact: nginx can be configured to do http2 without ssl.
+      ssl_arg+=" http2"
     fi
+  fi
 
-    cat >$common_ssl_conf <<'EOF'
+  cat >$common_ssl_conf <<'EOF'
 # let's encrypt gives us a bad nginx config, so use this:
 # https://mozilla.github.io/server-side-tls/ssl-config-generator/
 # using modern config. last checked 2017/4/22
@@ -335,54 +415,72 @@ ssl_stapling_verify on;
 # ian: commented out, our local dns is expected to work fine.
 #resolver <IP DNS resolver>;
 EOF
-    cat >$vhost_file <<EOF
+  cat >$vhost_file <<EOF
 server {
-    server_name $h www.$h;
-    root $root;
-    listen $port $ssl_arg;
-    listen [::]:$port $ssl_arg;
-
+  server_name $h www.$h;
+  root $root;
+  listen $listenip$port $ssl_arg;
 EOF
-    if $ssl; then
-        cat >>$vhost_file <<EOF
-    ssl_certificate $cert_dir/fullchain.pem;
-    ssl_certificate_key $cert_dir/privkey.pem;
-    include $common_ssl_conf;
+  if [[ ! $listenip ]]; then
+    cat >>$vhost_file <<EOF
+  listen [::]:$port $ssl_arg;
+EOF
+  fi
+  if $do_root_settings; then
+    cat >>$vhost_file <<EOF
+  location $root {
+    autoindex off;
+  }
+EOF
+  fi
+  if $ssl; then
+    cat >>$vhost_file <<EOF
+  ssl_certificate $cert_dir/fullchain.pem;
+  ssl_certificate_key $cert_dir/privkey.pem;
+  include $common_ssl_conf;
 EOF
 
-        cat >$redir_file <<EOF
+    if (( port == 443 )); then
+      cat >$redir_file <<EOF
 server {
-    server_name $h www.$h;
-    listen 80 $http2_arg;
-    listen [::]:80 $http2_arg;
-    return 301 https://$server_name$request_uri;
+  server_name $h www.$h;
+  listen 80 $http2_arg;
+  listen [::]:80 $http2_arg;
+  return 301 https://\$server_name\$request_uri;
 }
 EOF
-    fi # end if $ssl
-
-    if [[ $extra_settings ]]; then
-        cat $extra_settings >>$vhost_file
     fi
+  fi # end if $ssl
 
-    if [[ $proxy ]]; then
-        cat >>$vhost_file <<EOF
-    location / {
-        proxy_set_header Host \$host;
-        proxy_set_header X-Real-IP \$remote_addr;
-        proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
-        proxy_set_header X-Forwarded-Ssl on;
-        proxy_set_header X-Forwarded-Port $port;
-        proxy_pass http://$proxy;
-    }
-EOF
-    fi
+  if [[ $extra_settings ]]; then
+    cat $extra_settings >>$vhost_file
+  fi
 
+  if [[ $proxy ]]; then
     cat >>$vhost_file <<EOF
+  location / {
+    proxy_set_header Host \$host;
+    proxy_set_header X-Real-IP \$remote_addr;
+    proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
+    proxy_set_header X-Forwarded-Ssl on;
+    proxy_set_header X-Forwarded-Port $port;
+    proxy_pass http://$proxy;
+  }
+EOF
+  fi
+
+  cat >>$vhost_file <<EOF
 }
 EOF
 
 
+  if $allow_server_fail; then
+    if ! service nginx restart; then
+      echo "$0: warning: nginx restart failed. ignoring due to -l flag" >&2
+    fi
+  else
     service nginx restart
+  fi
 
 fi ####### end if nginx