X-Git-Url: https://iankelling.org/git/?p=basic-https-conf;a=blobdiff_plain;f=web-conf;h=274f1eb91191274651dd6acacaec6a43a53ef74f;hp=4dc3974f38d4dc04f79593268c69562d8b2e8bf8;hb=HEAD;hpb=452c9b3203296546a1ae6c21fa4de5701a73f82a diff --git a/web-conf b/web-conf index 4dc3974..eb87f17 100755 --- a/web-conf +++ b/web-conf @@ -1,262 +1,331 @@ #!/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 . + +# 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 </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 < - ServerName $h - ServerAlias www.$h - DocumentRoot $root + done + + echo "$0: creating $vhost_file" + cat >$vhost_file < +ServerName $h +ServerAlias www.$h +DocumentRoot $root +EOF + if $do_root_settings; then + cat >>$vhost_file < + Options -Indexes ${symlinkarg}FollowSymlinks + 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 <>$vhost_file <>$vhost_file <>$vhost_file <>$vhost_file <>$vhost_file </etc/apache2/conf-enabled/local-custom.conf <<'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 -SSLStaplingCache shmcb:/var/run/apache2/stapling_cache(128000) + 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 + +Redirect permanent "/" "https://mydomain.ltd/" + +# 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 - echo "$0: creating $redir_file" - cat >$redir_file <$redir_file < - 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] 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 <>$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 EOF - if ! $listen_port; then - # reference: https://httpd.apache.org/docs/2.4/mod/mpm_common.html#listen - cat >>$vhost_file <>$vhost_file <&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 @@ -339,53 +415,78 @@ ssl_stapling_verify on; # ian: commented out, our local dns is expected to work fine. #resolver ; EOF - cat >$vhost_file <$vhost_file <>$vhost_file <>$vhost_file <>$vhost_file <>$vhost_file <$redir_file <$redir_file <>$vhost_file fi + fi # end if $ssl - if [[ $proxy ]]; then - cat >>$vhost_file <>$vhost_file + fi + if [[ $proxy ]]; then cat >>$vhost_file <>$vhost_file <&2 + fi + else service nginx restart + fi fi ####### end if nginx + +cat >/etc/apache2/conf-enabled/local-custom.conf <<'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 +SSLStaplingCache shmcb:/var/run/apache2/stapling_cache(128000) +EOF