be less verbose
[basic-https-conf] / apache-site
1 #!/bin/bash
2 # Copyright (C) 2016 Ian Kelling
3
4 # Licensed under the Apache License, Version 2.0 (the "License");
5 # you may not use this file except in compliance with the License.
6 # You may obtain a copy of the License at
7
8 # http://www.apache.org/licenses/LICENSE-2.0
9
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15
16 [[ $EUID == 0 ]] || exec sudo -E "$BASH_SOURCE" "$@"
17
18 set -eE -o pipefail
19 trap 'echo "$0:$LINENO:error: \"$BASH_COMMAND\" returned $?" >&2' ERR
20
21 usage() {
22 cat <<EOF
23 Usage: ${0##*/} [OPTIONS] [EXTRA_SETTINGS_FILE] DOMAIN
24 Setup apache virtualhost config with https using
25 ssl config provided by let's encrypt and my standard
26 location for storing certs.
27
28 EXTRA_SETTINGS_FILE can be - for stdin
29 -c CERT_DIR In priority: this arg, $ACME_TINY_WRAPPER_CERT_DIR,
30 $HOME/webservercerts, if the other options aren't set.
31 -i Insecure, no ssl
32 -p ADDR_PORT Main address and port to listen on, default *:443
33 -r DocumentRoot
34 -h|--help Print help and exit
35
36 Note: Uses GNU getopt options parsing style
37 EOF
38 exit $1
39 }
40
41 ##### begin command line parsing ########
42
43 cert_dir="$ACME_TINY_WRAPPER_CERT_DIR"
44 if [[ ! $cert_dir ]]; then
45 cert_dir=$HOME/webservercerts
46 fi
47 ssl=true
48 extra_settings=
49 addr_port="*:443"
50 temp=$(getopt -l help ic:p:r:h "$@") || usage 1
51 eval set -- "$temp"
52 while true; do
53 case $1 in
54 -i) ssl=false; shift ;;
55 -c) cert_dir="$2"; shift 2 ;;
56 -p) addr_port="$2"; shift 2 ;;
57 -r) root="$2"; shift 2 ;;
58 --) shift; break ;;
59 -h|--help) usage ;;
60 *) echo "$0: Internal error!" ; exit 1 ;;
61 esac
62 done
63
64 if (( ${#@} == 2 )); then
65 read -r extra_settings h <<<"${@}"
66 else
67 read -r h <<<"${@}"
68 fi
69
70 if [[ ! $h ]]; then
71 echo "$0: error: expected domain arg"
72 usage 1
73 fi
74
75 if [[ ! $root ]]; then
76 root=/var/www/$h/html
77 fi
78
79 port=${addr_port##*:}
80
81
82 ##### end command line parsing ########
83
84 # taken from the let's encrypt generated site, using
85 # ./certbot-auto --apache (should use the test mode to check if there are updates)
86 # on 5/29/2016
87
88 # I could have also used the mozilla generator this, but it had some open issues
89 # with no response
90 # so I figured I would check out let's encrypt.
91 # It's a little more liberal, but still get's an A in ssl labs,
92 # so, meh, I'll use it.
93 # https://mozilla.github.io/server-side-tls/ssl-config-generator/
94
95
96 rm -f /etc/apache2/sites-enabled/000-default.conf
97
98 mkdir -p $root
99 vhost_file=/etc/apache2/sites-enabled/$h.conf
100 redir_file=/etc/apache2/sites-enabled/httpsredir.conf
101
102 # note, we exepct ServerRoot of /etc/apache2
103 cd /etc/apache2
104 conf_files=(apache2.conf)
105
106 # apache requires exactly 1 listen directive per port (when no ip is also given),
107 # so we have to parse the config to do it programatically.
108 listen_80=false
109 listen_port=false
110 while (( i=0; i < ${#conf_files[@]}; i++ )); do
111 f="${conf_files[i]}"
112 # note: globs are expanded here:
113 conf_files+=( $(sed -rn "s,^\s*Include(Optional)?\s+(\S+).*,\2,p" "$f") )
114 case $(readlink -f "$f") in
115 $vhost_file|$redir_file) continue ;;
116 esac
117 for p in $(sed -rn "s,^\s*Listen\s+(\S+).*,\1,p" "$f"); do
118 case $p in
119 80) listen_80=true ;;
120 $port) listen_port=true ;;
121 esac
122 done
123 done
124
125 if $ssl; then
126 https_arg=" https"
127 fi
128
129
130 echo "$0: creating $vhost_file"
131 cat >$vhost_file <<EOF
132 <VirtualHost $addr_port>
133 ServerName $h
134 ServerAlias www.$h
135 DocumentRoot $root
136 EOF
137
138 if [[ $extra_settings ]]; then
139 cat -- $extra_settings >>$vhost_file
140 fi
141
142 # go faster!
143 if [[ -e /etc/apache2/mods-available/http2.load ]]; then
144 # https://httpd.apache.org/docs/2.4/mod/mod_http2.html
145 a2enmod http2
146 cat >>$vhost_file <<EOF
147 Protocols h2 http/1.1
148 EOF
149 fi
150
151 if $ssl; then
152 certbot_ssl_conf=/etc/letsencrypt/options-ssl-apache.conf
153 cat >>$vhost_file <<EOF
154 SSLCertificateFile $cert_dir/$h-chained.pem
155 SSLCertificateKeyFile $cert_dir/$h-domain.key
156 Include $certbot_ssl_conf
157 EOF
158
159 # if we are using a non-standard port, setup don't setup
160 # irrelevant 443 redirect.
161 if [[ $port == "443" ]]; then
162 echo "$0: creating $redir_file"
163 cat >$redir_file <<'EOF'
164 # vhost_combined with %D (request time in microseconds)
165 # this file is just a convenient place to drop it.
166 LogFormat "%v:%p %h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\" %D" vhost_time_combined
167 <VirtualHost *:80>
168 ServerAdmin webmaster@localhost
169 DocumentRoot /var/www/html
170
171 ErrorLog ${APACHE_LOG_DIR}/error.log
172 CustomLog ${APACHE_LOG_DIR}/httpsredir-access.log combined
173
174 RewriteEngine on
175 # ian: removed so it's for all sites
176 #RewriteCond %{SERVER_NAME} =certbot.iank.bid
177 RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,QSA,R=permanent]
178 </VirtualHost>
179 EOF
180 if ! $listen_80; then
181 cat >>$redir_file <<'EOF'
182 Listen 80
183 EOF
184 fi
185 fi
186
187 mkdir -p /etc/letsencrypt
188
189 # this is from cerbot, see below.
190 echo "$0: creating $certbot_ssl_conf"
191 cat >$certbot_ssl_conf <<'EOF'
192 # Baseline setting to Include for SSL sites
193
194 SSLEngine on
195
196 # Intermediate configuration, tweak to your needs
197 SSLProtocol all -SSLv2 -SSLv3
198 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
199 SSLHonorCipherOrder on
200 SSLCompression off
201
202 SSLOptions +StrictRequire
203
204 # Add vhost name to log entries:
205 LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-agent}i\"" vhost_combined
206 LogFormat "%v %h %l %u %t \"%r\" %>s %b" vhost_common
207
208 #CustomLog /var/log/apache2/access.log vhost_combined
209 #LogLevel warn
210 #ErrorLog /var/log/apache2/error.log
211
212 # Always ensure Cookies have "Secure" set (JAH 2012/1)
213 #Header edit Set-Cookie (?i)^(.*)(;\s*secure)??((\s*;)?(.*)) "$1; Secure$3$4"
214 EOF
215
216 upstream=https://github.com/certbot/certbot/raw/master/certbot-apache/certbot_apache/options-ssl-apache.conf
217 if ! diff -c <(wget -q -O - $upstream) $certbot_ssl_conf; then
218 cat <<EOF
219 WARNING!!!!!!!!!
220 WARNING!!!!!!!!!
221 WARNING!!!!!!!!!
222 WARNING!!!!!!!!!
223 WARNING!!!!!!!!!
224 upstream ssl settings differ from the snapshot we have taken!!!
225 We diffed with this command:
226 diff -c <(wget -q -O - $upstream) $certbot_ssl_conf
227 Update this script to take care this warning!!!!!
228 EOF
229 sleep 1
230 fi
231 fi
232 cat >>$vhost_file <<EOF
233 ErrorLog \${APACHE_LOG_DIR}/error.log
234 CustomLog \${APACHE_LOG_DIR}/access.log vhost_time_combined
235 </VirtualHost>
236 EOF
237
238 if ! $listen_port; then
239 # reference: https://httpd.apache.org/docs/2.4/mod/mpm_common.html#listen
240 cat >>$vhost_file <<EOF
241 listen ${port}${https_arg}
242 EOF
243 fi
244
245
246 a2enmod ssl rewrite # rewrite needed for httpredir
247 service apache2 restart
248
249 # I rarely look at how much traffic I get, so let's keep that info
250 # around for longer than the default of 2 weeks.
251 sed -ri --follow-symlinks 's/^(\s*rotate\s).*/\1 365/' /etc/logrotate.d/apache2