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
Note: Uses GNU getopt options parsing style
EOF
- exit $1
+ exit $1
}
##### begin command line parsing ########
temp=$(getopt -l help e:if:p:r:sh "$@") || usage 1
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 ;;
- -s) symlinkarg=+; shift ;;
- --) shift; break ;;
- -h|--help) usage ;;
- *) echo "$0: Internal error!" ; exit 1 ;;
- esac
+ 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 ;;
+ -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 --fqdn)
+ email=root@$(hostname --fqdn)
fi
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
- 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
- rm $vhost_file
- fi
+
+ $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
+ rm $vhost_file
+ fi
+
+
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
- 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
+ done
- cat >$vhost_file <<EOF
+ cat >$vhost_file <<EOF
<VirtualHost *:$port>
ServerName $h
ServerAlias www.$h
</Directory>
EOF
- 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 -q http2
- cat >>$vhost_file <<EOF
+ # 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 -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
+ 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 -q headers
- https_arg=" https"
- common_ssl_conf=/etc/apache2/common-ssl.conf
- cat >>$vhost_file <<EOF
+ 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
Header always set Content-Security-Policy upgrade-insecure-requests
EOF
- echo "$0: creating $redir_file"
- cat >$redir_file <<EOF
+ echo "$0: creating $redir_file"
+ cat >$redir_file <<EOF
<VirtualHost *:80>
ServerName $h
ServerAdmin webmaster@localhost
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
- # this is a copy of a file certbot, see below.
- echo "$0: creating $common_ssl_conf"
- cat >$common_ssl_conf <<'EOF'
+ # 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
LogFormat "%v %h %l %u %t \"%r\" %>s %b" vhost_common
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
+ 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!!!!!!!!!
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'
+ 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
+ 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
+ fi
- a2enmod -q ssl rewrite # rewrite needed for httpredir
- service apache2 restart
+ a2enmod -q ssl rewrite # rewrite needed for httpredir
+ service apache2 restart
- # 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
# 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;
autoindex off;
}
EOF
- if $ssl; then
- cat >>$vhost_file <<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;
EOF
- cat >$redir_file <<EOF
+ cat >$redir_file <<EOF
server {
server_name $h www.$h;
listen 80 $http2_arg;
return 301 https://$server_name$request_uri;
}
EOF
- fi # end if $ssl
+ fi # end if $ssl
- if [[ $extra_settings ]]; then
- cat $extra_settings >>$vhost_file
- fi
+ if [[ $extra_settings ]]; then
+ cat $extra_settings >>$vhost_file
+ fi
- if [[ $proxy ]]; then
- cat >>$vhost_file <<EOF
+ if [[ $proxy ]]; then
+ cat >>$vhost_file <<EOF
location / {
proxy_set_header Host \$host;
proxy_set_header X-Real-IP \$remote_addr;
proxy_pass http://$proxy;
}
EOF
- fi
+ fi
- cat >>$vhost_file <<EOF
+ cat >>$vhost_file <<EOF
}
EOF
- service nginx restart
+ service nginx restart
fi ####### end if nginx