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