· 9 years ago · Dec 01, 2016, 02:04 AM
1# The perfect rootserver
2# by zypr
3# https://github.com/zypr/perfectrootserver
4# Big thanks to https://github.com/andryyy/mailcow
5# Compatible with Debian 8.x (jessie)
6
7#################################
8## DO NOT MODIFY, JUST DON'T! ##
9#################################
10
11generatepw() {
12 while [[ $pw == "" ]]; do
13 pw=$(openssl rand -base64 30 | tr -d / | cut -c -24 | grep -P '(?=^.{8,255}$)(?=^[^\s]*$)(?=.*\d)(?=.*[A-Z])(?=.*[a-z])')
14 done
15 echo "$pw" && unset pw
16}
17
18checksystem() {
19 echo "$(date +"[%T]") | ${info} Checking your system..."
20
21 if [ $(dpkg-query -l | grep gawk | wc -l) -ne 1 ]; then
22 apt-get update -y >/dev/null 2>&1 && apt-get -y --force-yes install gawk >/dev/null 2>&1
23 fi
24
25 if [ $USER != 'root' ]; then
26 echo "${error} Please run the script as root" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
27 exit 1
28 fi
29
30 if [[ -z $(which nc) ]]; then
31 echo "${error} Please install $(textb netcat) before running this script" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
32 exit 1
33 fi
34
35 if [ $(dpkg-query -l | grep lsb-release | wc -l) -ne 1 ]; then
36 apt-get update -y >/dev/null 2>&1 && apt-get -y --force-yes install lsb-release >/dev/null 2>&1
37 fi
38
39 if [ $(lsb_release -cs) != 'jessie' ] || [ $(lsb_release -is) != 'Debian' ]; then
40 echo "${error} The script for now works only on $(textb Debian) $(textb 8.x)" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
41 exit 1
42 fi
43
44 if [ $(grep MemTotal /proc/meminfo | awk '{print $2}') -lt 1000000 ]; then
45 echo "${warn} At least ~1000MB of memory is highly recommended" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
46 echo "${info} Press $(textb ENTER) to skip this warning or $(textb CTRL-C) to cancel the process" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
47 read -s -n 1 i
48 fi
49
50 if [ $(dpkg-query -l | grep dmidecode | wc -l) -ne 1 ]; then
51 echo "${error} This script does not support the virtualization technology!" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
52 exit 1
53 fi
54
55 if [ "$(dmidecode -s system-product-name)" == 'Bochs' ] || [ "$(dmidecode -s system-product-name)" == 'KVM' ] || [ "$(dmidecode -s system-product-name)" == 'All Series' ] || [ "$(dmidecode -s system-product-name)" == 'OpenStack Nova' ] || [ "$(dmidecode -s system-product-name)" == 'Standard' ]; then
56 echo >> /dev/null
57 else
58 if [ $(dpkg-query -l | grep facter | wc -l) -ne 1 ]; then
59 apt-get update -y >/dev/null 2>&1 && apt-get -y --force-yes install facter >/dev/null 2>&1
60 fi
61
62 if [ "$(facter virtual)" == 'physical' ] || [ "$(facter virtual)" == 'kvm' ]; then
63 echo >> /dev/null
64 else
65 echo "${warn} This script does not support the virtualization technology ($(dmidecode -s system-product-name))" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
66 echo "${info} Press $(textb ENTER) to skip this warning and proceed at your own risk or $(textb CTRL-C) to cancel the process" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
67 read -s -n 1 i
68 fi
69 fi
70
71 if [ ${CLOUDFLARE} != '1' ]; then
72 if [[ $FQDNIP != $IPADR ]]; then
73 echo "${error} The domain (${MYDOMAIN} - ${FQDNIP}) does not resolve to the IP address of your server (${IPADR})" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
74 echo "${error} Please check the userconfig and/or your DNS-Records." | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
75 exit 1
76 else
77 if [ ${USE_VALID_SSL} == '1' ]; then
78 if [[ $(echo ${SSLMAIL} | egrep "^(([-a-zA-Z0-9\!#\$%\&\'*+/=?^_\`{\|}~])+\.)*[-a-zA-Z0-9\!#\$%\&\'*+/=?^_\`{\|}~]+@\w((-|\w)*\w)*\.(\w((-|\w)*\w)*\.)*\w{2,4}$") != ${SSLMAIL} ]]; then
79 echo "${error} Please chose a valid e-mail adress for your letsencrypt ssl certificate!" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
80 exit 1
81 fi
82 if [ ${USE_MAILSERVER} == '1' ]; then
83 while true; do
84 p=0
85 if [[ $MAILIP != $IPADR ]]; then
86 echo "${error} mail.${MYDOMAIN} does not resolve to the IP address of your server (${IPADR})" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
87 else
88 p=$((p + 1))
89 fi
90 sleep 1
91 if [[ $ACIP != $IPADR ]]; then
92 echo "${error} autoconfig.${MYDOMAIN} does not resolve to the IP address of your server (${IPADR})" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
93 else
94 p=$((p + 1))
95 fi
96 sleep 1
97 if [[ $ADIP != $IPADR ]]; then
98 echo "${error} autodiscover.${MYDOMAIN} does not resolve to the IP address of your server (${IPADR})" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
99 else
100 p=$((p + 1))
101 fi
102 sleep 1
103 if [[ $DAVIP != $IPADR ]]; then
104 echo "${error} dav.${MYDOMAIN} does not resolve to the IP address of your server (${IPADR})" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
105 else
106 p=$((p + 1))
107 fi
108 sleep 1
109 if [[ $WWWIP != $IPADR ]]; then
110 echo "${error} www.${MYDOMAIN} does not resolve to the IP address of your server (${IPADR})" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
111 else
112 p=$((p + 1))
113 fi
114 if [ ${p} -eq 5 ]; then
115 break
116 else
117 echo
118 echo "${warn} Please check your DNS-Records." | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
119 echo "${info} Press $(textb ENTER) to repeat this check or $(textb CTRL-C) to cancel the process" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
120 read -s -n 1 i
121 fi
122 done
123 else
124 while true; do
125 if [[ $WWWIP != $IPADR ]]; then
126 echo "${error} www.${MYDOMAIN} does not resolve to the IP address of your server (${IPADR})" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
127 echo
128 echo "${warn} Please check your DNS-Records." | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
129 echo "${info} Press $(textb ENTER) to repeat this check or $(textb CTRL-C) to cancel the process" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
130 read -s -n 1 i
131 else
132 break
133 fi
134 done
135 fi
136 fi
137 fi
138 fi
139 echo "${ok} The system meets the minimum requirements." | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
140}
141
142checkconfig() {
143 echo "${info} Checking your configuration..." | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
144 for var in NGINX_VERSION OPENSSL_VERSION OPENSSH_VERSION NPS_VERSION TIMEZONE MYDOMAIN SSH USE_MAILSERVER MAILCOW_ADMIN_USER USE_WEBMAIL USE_PMA PMA_HTTPAUTH_USER PMA_RESTRICT MYSQL_MCDB_NAME MYSQL_MCDB_USER MYSQL_RCDB_NAME MYSQL_RCDB_USER MYSQL_PMADB_NAME MYSQL_PMADB_USER MYSQL_HOSTNAME CLOUDFLARE
145 do
146 if [[ -z ${!var} ]]; then
147 echo "${error} Parameter $(textb ${var}) must not be empty." | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
148 exit 1
149 fi
150 done
151
152 if [ "$CONFIG_COMPLETED" != '1' ]; then
153 echo "${error} Please check the userconfig and set a valid value for the variable \"$(textb CONFIG_COMPLETED)\" to continue." | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
154 exit 1
155 fi
156
157 if [ $(dpkg-query -l | grep libcrack2 | wc -l) -ne 1 ]; then
158 apt-get update -y >/dev/null 2>&1 && apt-get -y --force-yes install libcrack2 >/dev/null 2>&1
159 fi
160
161 for var in ${MAILCOW_ADMIN_PASS} ${PMA_HTTPAUTH_PASS} ${PMA_BFSECURE_PASS} ${SSH_PASS} ${MYSQL_ROOT_PASS} ${MYSQL_MCDB_PASS} ${MYSQL_RCDB_PASS} ${MYSQL_RCDB_PASS} ${MYSQL_PMADB_PASS}
162 do
163 if echo "${var}" | grep -P '(?=^.{8,255}$)(?=^[^\s]*$)(?=.*\d)(?=.*[A-Z])(?=.*[a-z])' > /dev/null; then
164 if [[ "$(awk -F': ' '{ print $2}' <<<"$(cracklib-check <<<"${var}")")" == "OK" ]]; then
165 echo >> /dev/null
166 else
167 echo "${error} One of your passwords was rejected!" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
168 echo "${info} Your password must be a minimum of 8 characters and must include at least 1 number, 1 uppercase and 1 lowercase letter." | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
169 echo "${info} Recommended password settings: Leave \`generatepw\` to generate a strong password." | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
170 echo
171 while true; do
172 echo "${info} Press $(textb ENTER) to show the weak password or $(textb CTRL-C) to cancel the process" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
173 read -s -n 1 i
174 case $i in
175 * ) echo;echo "-----------------------" | awk '{ print strftime("[%H:%M:%S] |"), $0 }';echo "$(cracklib-check <<<\"${var}\")" | awk '{ print strftime("[%H:%M:%S] |"), $0 }';echo "-----------------------" | awk '{ print strftime("[%H:%M:%S] |"), $0 }';echo;break;;
176 esac
177 done
178 exit 1
179 fi
180 else
181 echo "${error} One of your passwords is too weak." | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
182 echo "${info} Your password must be a minimum of 8 characters and must include at least 1 number, 1 uppercase and 1 lowercase letter." | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
183 echo "${info} Recommended password settings: Leave \`generatepw\` to generate a strong password." | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
184 echo
185 while true; do
186 echo "${info} Press $(textb ENTER) to show the weak password or $(textb CTRL-C) to cancel the process" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
187 read -s -n 1 i
188 case $i in
189 * ) echo;echo "-----------------------" | awk '{ print strftime("[%H:%M:%S] |"), $0 }';echo "$(textb ${var})" | awk '{ print strftime("[%H:%M:%S] |"), $0 }';echo "-----------------------" | awk '{ print strftime("[%H:%M:%S] |"), $0 }';echo;break;;
190 esac
191 done
192 exit 1
193 fi
194 done
195
196 if [ ${SSH} == '21' ] || [ ${SSH} == '25' ] || [ ${SSH} == '53' ] || [ ${SSH} == '80' ] || [ ${SSH} == '143' ] || [ ${SSH} == '443' ] || [ ${SSH} == '587' ] || [ ${SSH} == '990' ] || [ ${SSH} == '993' ] || [ ${SSH} -gt 1024 ] || [ ${SSH} -le 0 ]; then
197 echo "${error} You are using an unsupportet SSH port, please chose another one!" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
198 exit 1
199 else
200 if [ ${SSH} == '22' ]; then
201 echo "${warn} Do you really want to use the standard SSH port? -> $(textb 22)" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
202 echo "${info} Press $(textb ENTER) to skip this warning and proceed or $(textb CTRL-C) to cancel the process" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
203 read -s -n 1 i
204 else
205 if [[ $SSH =~ ^-?[0-9]+$ ]]; then
206 echo >> /dev/null
207 else
208 echo "${error} SSH Port is not an integer, chose another one!" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
209 exit 1
210 fi
211 fi
212 fi
213 echo "${ok} Userconfig is correct." | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
214 echo
215}
216
217installation() {
218echo "${info} Starting installation!" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
219
220cat > /etc/hosts <<END
221127.0.0.1 localhost
222::1 localhost ip6-localhost ip6-loopback
223ff02::1 ip6-allnodes
224ff02::2 ip6-allrouters
225END
226
227if [[ -z $(dpkg --get-selections | grep -E "^dbus.*install$") ]]; then
228 apt-get update -y >/dev/null 2>&1 && apt-get -y --force-yes install dbus >/dev/null 2>&1
229fi
230
231if [ ${USE_MAILSERVER} == '1' ]; then
232 echo -e "${IPADR} mail.${MYDOMAIN} mail" >> /etc/hosts
233 hostnamectl set-hostname mail
234else
235 echo -e "${IPADR} ${MYDOMAIN} $(echo ${MYDOMAIN} | cut -f 1 -d '.')" >> /etc/hosts
236 hostnamectl set-hostname $(echo ${MYDOMAIN} | cut -f 1 -d '.')
237fi
238
239if [ ${USE_MAILSERVER} == '1' ]; then
240 echo "mail.${MYDOMAIN}" > /etc/mailname
241else
242 echo "${MYDOMAIN}" > /etc/mailname
243fi
244
245echo "${info} Setting your hostname & timezone..." | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
246if [[ -f /usr/share/zoneinfo/${TIMEZONE} ]] ; then
247 echo ${TIMEZONE} > /etc/timezone
248 dpkg-reconfigure -f noninteractive tzdata >/dev/null 2>&1
249 if [ "$?" -ne "0" ]; then
250 echo "${error} Timezone configuration failed: dpkg returned exit code != 0" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
251 exit 1
252 fi
253 else
254 echo "${error} Cannot set your timezone: timezone is unknown" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
255 exit 1
256fi
257echo "${info} Installing prerequisites..." | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
258echo "${warn} Some of the tasks could take a long time, please be patient!" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
259
260rm /etc/apt/sources.list
261cat > /etc/apt/sources.list <<END
262# Dotdeb
263deb http://packages.dotdeb.org jessie all
264deb-src http://packages.dotdeb.org jessie all
265
266# Doveocot
267deb http://xi.rename-it.nl/debian/ stable-auto/dovecot-2.3 main
268END
269
270cat > /etc/apt/sources.list.d/security.list <<END
271deb http://security.debian.org/ stable/updates main contrib non-free
272deb http://security.debian.org/ testing/updates main contrib non-free
273END
274
275cat > /etc/apt/sources.list.d/stable.list <<END
276deb http://ftp.debian.org/debian/ stable main contrib non-free
277deb-src http://ftp.debian.org/debian/ stable main contrib non-free
278END
279
280cat > /etc/apt/sources.list.d/testing.list <<END
281deb http://ftp.debian.org/debian/ testing main contrib non-free
282deb-src http://ftp.debian.org/debian/ testing main contrib non-free
283END
284
285cat > /etc/apt/sources.list.d/unstable.list <<END
286deb http://ftp.debian.org/debian/ unstable main contrib non-free
287deb-src http://ftp.debian.org/debian/ unstable main contrib non-free
288END
289
290cat > /etc/apt/sources.list.d/experimental.list <<END
291deb http://ftp.debian.org/debian/ experimental main contrib non-free
292deb-src http://ftp.debian.org/debian/ experimental main contrib non-free
293END
294
295cat > /etc/apt/preferences.d/security.pref <<END
296Package: *
297Pin: release l=Debian-Security
298Pin-Priority: 1000
299END
300
301cat > /etc/apt/preferences.d/stable.pref <<END
302Package: *
303Pin: release a=stable
304Pin-Priority: 900
305END
306
307cat > /etc/apt/preferences.d/testing.pref <<END
308Package: *
309Pin: release a=testing
310Pin-Priority: 750
311END
312
313cat > /etc/apt/preferences.d/unstable.pref <<END
314Package: *
315Pin: release a=unstable
316Pin-Priority: 50
317END
318
319cat > /etc/apt/preferences.d/experimental.pref <<END
320Package: *
321Pin: release a=experimental
322Pin-Priority: 1
323END
324
325wget -O ~/sources/dovecot.key http://xi.rename-it.nl/debian/archive.key >/dev/null 2>&1 && apt-key add ~/sources/dovecot.key >/dev/null 2>&1
326wget -O ~/sources/dotdeb.gpg http://www.dotdeb.org/dotdeb.gpg >/dev/null 2>&1 && apt-key add ~/sources/dotdeb.gpg >/dev/null 2>&1
327apt-get update -y >/dev/null 2>&1 && apt-get -y upgrade >/dev/null 2>&1
328apt-get -y --force-yes install aptitude ssl-cert whiptail apt-utils jq libc6-dev/stable >/dev/null 2>&1
329DEBIAN_FRONTEND=noninteractive aptitude -y install apache2-threaded-dev apache2-utils apt-listchanges arj autoconf automake bison bsd-mailx build-essential bzip2 ca-certificates cabextract checkinstall curl dnsutils file flex git htop libapr1-dev libaprutil1 libaprutil1-dev libauthen-sasl-perl-Daemon libawl-php libcrypt-ssleay-perl libcurl4-openssl-dev libdbi-perl libgeoip-dev libio-socket-ssl-perl libio-string-perl liblockfile-simple-perl liblogger-syslog-perl libmail-dkim-perl libmail-spf-perl libmime-base64-urlsafe-perl libnet-dns-perl libnet-ident-perl libnet-LDAP-perl libnet1 libnet1-dev libpam-dev libpcre-ocaml-dev libpcre3 libpcre3-dev libreadline6-dev libtest-tempdir-perl libtool libwww-perl libxml2 libxml2-dev libxml2-utils libxslt1-dev libyaml-dev lzop mariadb-server memcached mlocate nomarch php-auth-sasl php-auth-sasl php-http-request php-http-request php-mail php-mail-mime php-mail-mimedecode php-net-dime php-net-smtp php-net-url php-pear php-soap php5 php5-apcu php5-cli php5-common php5-common php5-curl php5-dev php5-fpm php5-geoip php5-gd php5-igbinary php5-imap php5-intl php5-mcrypt php5-mysql php5-sqlite php5-xmlrpc php5-xsl python-setuptools python-software-properties rkhunter software-properties-common subversion sudo unzip vim-nox zip zlib1g zlib1g-dbg zlib1g-de zoo >/dev/null 2>&1
330
331if [ "$?" -ne "0" ]; then
332 echo "${error} Package installation failed!" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
333 exit 1
334fi
335
336mysqladmin -u root password ${MYSQL_ROOT_PASS}
337
338sed -i 's/.*max_allowed_packet.*/max_allowed_packet = 128M/g' /etc/mysql/my.cnf
339sed -i '32s/.*/innodb_file_per_table = 1\n&/' /etc/mysql/my.cnf
340sed -i '33s/.*/innodb_additional_mem_pool_size = 50M\n&/' /etc/mysql/my.cnf
341sed -i '34s/.*/innodb_thread_concurrency = 4\n&/' /etc/mysql/my.cnf
342sed -i '35s/.*/innodb_flush_method = O_DSYNC\n&/' /etc/mysql/my.cnf
343sed -i '36s/.*/innodb_flush_log_at_trx_commit = 0\n&/' /etc/mysql/my.cnf
344sed -i '37s/.*/#innodb_buffer_pool_size = 2G #reserved RAM, reduce i\/o\n&/' /etc/mysql/my.cnf
345sed -i '38s/.*/innodb_log_files_in_group = 2\n&/' /etc/mysql/my.cnf
346sed -i '39s/.*/innodb_log_file_size = 32M\n&/' /etc/mysql/my.cnf
347sed -i '40s/.*/innodb_log_buffer_size = 16M\n&/' /etc/mysql/my.cnf
348sed -i '41s/.*/#innodb_table_locks = 0 #disable table lock, uncomment if you do not want to crash all applications, if one does\n&/' /etc/mysql/my.cnf
349
350# Automated mysql_secure_installation
351mysql -u root -p${MYSQL_ROOT_PASS} -e "DELETE FROM mysql.user WHERE User=''; DELETE FROM mysql.user WHERE User='root' AND Host NOT IN ('localhost', '127.0.0.1', '::1'); DROP DATABASE IF EXISTS test; FLUSH PRIVILEGES; DELETE FROM mysql.db WHERE Db='test' OR Db='test\\_%'; FLUSH PRIVILEGES;" >/dev/null 2>&1
352
353# Bash
354cd ~/sources
355mkdir bash && cd $_
356echo "${info} Downloading GNU bash & latest security patches..." | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
357wget https://ftp.gnu.org/gnu/bash/bash-4.3.tar.gz >/dev/null 2>&1
358for i in $(seq -f "%03g" 1 42); do wget http://ftp.gnu.org/gnu/bash/bash-4.3-patches/bash43-$i; done >/dev/null 2>&1
359tar zxf bash-4.3.tar.gz && cd bash-4.3 >/dev/null 2>&1
360echo "${info} Patching sourcefiles..." | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
361for i in ../bash43-[0-9][0-9][0-9]; do patch -p0 -s < $i; done
362echo "${info} Compiling GNU bash..." | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
363./configure --prefix=/usr/local >/dev/null 2>&1 && make >/dev/null 2>&1 && make install >/dev/null 2>&1
364cp -f /usr/local/bin/bash /bin/bash
365
366# OpenSSL
367echo "${info} Installing OpenSSL libs & headers..." | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
368DEBIAN_FRONTEND=noninteractive apt-get -y --force-yes install openssl/unstable libssl-dev/unstable >/dev/null 2>&1
369cd ~/sources
370wget http://www.openssl.org/source/openssl-${OPENSSL_VERSION}.tar.gz >/dev/null 2>&1
371tar -xzf openssl-${OPENSSL_VERSION}.tar.gz >/dev/null 2>&1
372echo "${info} Downloading OpenSSH..." | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
373wget http://ftp.hostserver.de/pub/OpenBSD/OpenSSH/portable/openssh-${OPENSSH_VERSION}.tar.gz >/dev/null 2>&1
374tar -xzf openssh-${OPENSSH_VERSION}.tar.gz >/dev/null 2>&1
375cd openssh-${OPENSSH_VERSION}
376echo "${info} Compiling OpenSSH..." | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
377./configure --prefix=/usr --with-pam --with-zlib --with-ssl-engine --with-ssl-dir=/etc/ssl --sysconfdir=/etc/ssh >/dev/null 2>&1
378make >/dev/null 2>&1 && mv /etc/ssh{,.bak} && make install >/dev/null 2>&1
379sed -i 's/^#Port 22/Port 22/g' /etc/ssh/sshd_config
380sed -i 's/^#AddressFamily any/AddressFamily inet/g' /etc/ssh/sshd_config
381sed -i 's/^#Protocol 2/Protocol 2/g' /etc/ssh/sshd_config
382sed -i 's/^#HostKey \/etc\/ssh\/ssh_host_rsa_key/HostKey \/etc\/ssh\/ssh_host_rsa_key/g' /etc/ssh/sshd_config
383sed -i 's/^#HostKey \/etc\/ssh\/ssh_host_ecdsa_key/HostKey \/etc\/ssh\/ssh_host_ecdsa_key/g' /etc/ssh/sshd_config
384sed -i 's/^#HostKey \/etc\/ssh\/ssh_host_ed25519_key/HostKey \/etc\/ssh\/ssh_host_ed25519_key/g' /etc/ssh/sshd_config
385sed -i 's/^#ServerKeyBits 1024/ServerKeyBits 2048/' /etc/ssh/sshd_config
386sed -i 's/^#RekeyLimit default none/RekeyLimit 256M/' /etc/ssh/sshd_config
387sed -i 's/^#LogLevel INFO/LogLevel VERBOSE/' /etc/ssh/sshd_config
388sed -i 's/^#KeyRegenerationInterval 1h/KeyRegenerationInterval 1800/g' /etc/ssh/sshd_config
389sed -i 's/^#SyslogFacility AUTH/SyslogFacility AUTH/g' /etc/ssh/sshd_config
390sed -i 's/^#LoginGraceTime 2m/LoginGraceTime 30/g' /etc/ssh/sshd_config
391sed -i 's/^#MaxAuthTries 6/MaxAuthTries 20/g' /etc/ssh/sshd_config
392sed -i 's/^#PermitRootLogin yes/PermitRootLogin yes/g' /etc/ssh/sshd_config
393sed -i 's/^#StrictModes yes/StrictModes yes/g' /etc/ssh/sshd_config
394sed -i 's/^#RSAAuthentication yes/RSAAuthentication yes/g' /etc/ssh/sshd_config
395sed -i 's/^#PubkeyAuthentication yes/PubkeyAuthentication yes/g' /etc/ssh/sshd_config
396sed -i 's/^AuthorizedKeysFile .ssh\/authorized_keys/#AuthorizedKeysFile .ssh\/authorized_keys/g' /etc/ssh/sshd_config
397sed -i 's/^#RhostsRSAAuthentication no/RhostsRSAAuthentication no/g' /etc/ssh/sshd_config
398sed -i 's/^#HostbasedAuthentication no/HostbasedAuthentication no/g' /etc/ssh/sshd_config
399sed -i 's/^#PermitEmptyPasswords no/PermitEmptyPasswords no/g' /etc/ssh/sshd_config
400sed -i 's/^#ChallengeResponseAuthentication yes/ChallengeResponseAuthentication no/g' /etc/ssh/sshd_config
401sed -i 's/^#AllowTcpForwarding yes/AllowTcpForwarding yes/g' /etc/ssh/sshd_config
402sed -i 's/^#X11Forwarding no/X11Forwarding yes/g' /etc/ssh/sshd_config
403sed -i 's/^#X11DisplayOffset 10/X11DisplayOffset 10/g' /etc/ssh/sshd_config
404sed -i 's/^#PrintMotd yes/PrintMotd no/g' /etc/ssh/sshd_config
405sed -i 's/^#PrintLastLog yes/PrintLastLog yes/g' /etc/ssh/sshd_config
406sed -i 's/^#TCPKeepAlive yes/TCPKeepAlive yes/g' /etc/ssh/sshd_config
407sed -i 's/^#UsePAM no/UsePAM yes/g' /etc/ssh/sshd_config
408sed -i 's/^#Banner none/Banner \/etc\/issue/g' /etc/ssh/sshd_config
409sed -i 's/^#MaxStartups 10:30:100/MaxStartups 2/g' /etc/ssh/sshd_config
410sed -i 's/^#MaxSessions 10/MaxSessions 3/g' /etc/ssh/sshd_config
411sed -i 's/^Subsystem sftp \/usr\/libexec\/sftp-server/Subsystem sftp \/usr\/lib\/openssh\/sftp-server/g' /etc/ssh/sshd_config
412echo -e "" >> /etc/ssh/sshd_config
413echo -e "# Allow client to pass locale environment variables" >> /etc/ssh/sshd_config
414echo -e "AcceptEnv LANG LC_* TZ" >> /etc/ssh/sshd_config
415echo -e "" >> /etc/ssh/sshd_config
416echo -e "# KEX algorithms">> /etc/ssh/sshd_config
417echo -e "KexAlgorithms curve25519-sha256@libssh.org,diffie-hellman-group-exchange-sha256">> /etc/ssh/sshd_config
418echo -e "" >> /etc/ssh/sshd_config
419echo -e "# Ciphers">> /etc/ssh/sshd_config
420echo -e "Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr">> /etc/ssh/sshd_config
421echo -e "" >> /etc/ssh/sshd_config
422echo -e "# MAC algorithms">> /etc/ssh/sshd_config
423echo -e "MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,hmac-ripemd160-etm@openssh.com,umac-128-etm@openssh.com,hmac-sha2-512,hmac-sha2-256,hmac-ripemd160,umac-128@openssh.com">> /etc/ssh/sshd_config
424
425rm /etc/issue
426cat > $_ <<END
427
428####################################################################
429# Unauthorized access to this system is forbidden and will be #
430# prosecuted by law. By accessing this system, you agree that your #
431# actions may be monitored if unauthorized usage is suspected. #
432####################################################################
433
434END
435systemctl -q restart ssh.service
436
437# Nginx
438cd ~/sources
439echo "${info} Downloading Nginx Pagespeed..." | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
440wget https://github.com/pagespeed/ngx_pagespeed/archive/release-${NPS_VERSION}-beta.zip >/dev/null 2>&1
441unzip -qq release-${NPS_VERSION}-beta.zip
442cd ngx_pagespeed-release-${NPS_VERSION}-beta/
443wget https://dl.google.com/dl/page-speed/psol/${NPS_VERSION}.tar.gz >/dev/null 2>&1
444tar -xzf ${NPS_VERSION}.tar.gz
445cd ~/sources
446echo "${info} Downloading Nginx..." | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
447wget http://nginx.org/download/nginx-${NGINX_VERSION}.tar.gz >/dev/null 2>&1
448tar -xzf nginx-${NGINX_VERSION}.tar.gz
449cd nginx-${NGINX_VERSION}
450
451echo "${info} Compiling Nginx..." | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
452
453./configure --prefix=/etc/nginx \
454--sbin-path=/usr/sbin/nginx \
455--conf-path=/etc/nginx/nginx.conf \
456--error-log-path=/var/log/nginx/error.log \
457--http-log-path=/var/log/nginx/access.log \
458--pid-path=/var/run/nginx.pid \
459--lock-path=/var/run/nginx.lock \
460--http-client-body-temp-path=/var/lib/nginx/body \
461--http-proxy-temp-path=/var/lib/nginx/proxy \
462--http-fastcgi-temp-path=/var/lib/nginx/fastcgi \
463--http-uwsgi-temp-path=/var/lib/nginx/uwsgi \
464--http-scgi-temp-path=/var/lib/nginx/scgi \
465--user=www-data \
466--group=www-data \
467--without-http_autoindex_module \
468--without-http_browser_module \
469--without-http_empty_gif_module \
470--without-http_userid_module \
471--without-http_split_clients_module \
472--with-http_ssl_module \
473--with-http_v2_module \
474--with-http_realip_module \
475--with-http_geoip_module \
476--with-http_addition_module \
477--with-http_sub_module \
478--with-http_dav_module \
479--with-http_flv_module \
480--with-http_mp4_module \
481--with-http_gunzip_module \
482--with-http_gzip_static_module \
483--with-http_random_index_module \
484--with-http_secure_link_module \
485--with-http_stub_status_module \
486--with-http_auth_request_module \
487--with-mail \
488--with-mail_ssl_module \
489--with-file-aio \
490--with-ipv6 \
491--with-debug \
492--with-pcre \
493--with-cc-opt='-O2 -g -pipe -Wall -Wformat -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -m64 -mtune=generic' \
494--with-openssl=$HOME/sources/openssl-${OPENSSL_VERSION} \
495--add-module=$HOME/sources/ngx_pagespeed-release-${NPS_VERSION}-beta >/dev/null 2>&1
496
497# make the package
498make >/dev/null 2>&1
499
500# Create a .deb package
501checkinstall --install=no -y >/dev/null 2>&1
502
503# Install the package
504echo "${info} Installing Nginx..." | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
505dpkg -i nginx_${NGINX_VERSION}-1_amd64.deb >/dev/null 2>&1
506mv nginx_${NGINX_VERSION}-1_amd64.deb ../
507
508# Create directories
509mkdir -p /var/lib/nginx/body && cd $_
510mkdir ../proxy
511mkdir ../fastcgi
512mkdir ../uwsgi
513mkdir ../cgi
514mkdir ../nps_cache
515mkdir /var/log/nginx
516mkdir /etc/nginx/sites-available && cd $_
517mkdir ../sites-enabled
518mkdir ../sites-custom
519mkdir ../htpasswd
520touch ../htpasswd/.htpasswd
521mkdir ../logs
522mkdir ../ssl
523chown -R www-data:www-data /var/lib/nginx
524chown www-data:www-data /etc/nginx/logs
525
526# Install the Nginx service script
527wget -O /etc/init.d/nginx --no-check-certificate https://raw.githubusercontent.com/Fleshgrinder/nginx-sysvinit-script/master/init >/dev/null 2>&1
528chmod 0755 /etc/init.d/nginx
529chown root:root /etc/init.d/nginx
530update-rc.d nginx defaults
531
532# Edit/create Nginx config files
533echo "${info} Configuring Nginx..." | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
534
535rm -rf /etc/nginx/nginx.conf
536cat > /etc/nginx/nginx.conf <<END
537user www-data;
538worker_processes auto;
539pid /var/run/nginx.pid;
540
541events {
542 worker_connections 4024;
543 multi_accept on;
544 use epoll;
545}
546
547http {
548 include /etc/nginx/mime.types;
549 default_type application/octet-stream;
550 server_tokens off;
551 keepalive_timeout 70;
552 sendfile on;
553 send_timeout 60;
554 tcp_nopush on;
555 tcp_nodelay on;
556 client_max_body_size 50m;
557 client_body_timeout 15;
558 client_header_timeout 15;
559 client_body_buffer_size 1K;
560 client_header_buffer_size 1k;
561 large_client_header_buffers 4 8k;
562 reset_timedout_connection on;
563 server_names_hash_bucket_size 100;
564 types_hash_max_size 2048;
565
566 open_file_cache max=2000 inactive=20s;
567 open_file_cache_valid 60s;
568 open_file_cache_min_uses 5;
569 open_file_cache_errors off;
570
571 gzip on;
572 gzip_static on;
573 gzip_disable "msie6";
574 gzip_vary on;
575 gzip_proxied any;
576 gzip_comp_level 6;
577 gzip_min_length 1100;
578 gzip_buffers 16 8k;
579 gzip_http_version 1.1;
580 gzip_types text/css text/javascript text/xml text/plain text/x-component application/javascript application/x-javascript application/json application/xml application/rss+xml font/truetype application/x-font-ttf font/opentype application/vnd.ms-fontobject image/svg+xml;
581
582 log_format main '\$remote_addr - \$remote_user [\$time_local] "\$request" '
583 '\$status \$body_bytes_sent "\$http_referer" '
584 '"\$http_user_agent" "\$http_x_forwarded_for"';
585
586 access_log logs/access.log main buffer=16k;
587 error_log logs/error.log;
588
589 map \$http_referer \$bad_referer {
590 default 0;
591 ~(?i)(adult|babes|click|diamond|forsale|girl|jewelry|love|nudit|organic|poker|porn|poweroversoftware|sex|teen|webcam|zippo|casino|replica) 1;
592 }
593
594 map \$http_cookie \$cache_uid {
595 default nil;
596 ~SESS[[:alnum:]]+=(?<session_id>[[:alnum:]]+) \$session_id;
597 }
598
599 map \$request_method \$no_cache {
600 default 1;
601 HEAD 0;
602 }
603
604 include /etc/nginx/sites-enabled/*.conf;
605}
606END
607
608# SSL certificate
609if [ ${CLOUDFLARE} == '0' ] && [ ${USE_VALID_SSL} == '1' ]; then
610 echo "${info} Creating valid SSL certificates..." | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
611 git clone https://github.com/letsencrypt/letsencrypt ~/sources/letsencrypt -q
612 cd ~/sources/letsencrypt
613 if [ ${USE_MAILSERVER} == '1' ]; then
614 ./letsencrypt-auto --agree-tos --renew-by-default --non-interactive --standalone --email ${SSLMAIL} --rsa-key-size 2048 -d ${MYDOMAIN} -d www.${MYDOMAIN} -d mail.${MYDOMAIN} -d autodiscover.${MYDOMAIN} -d autoconfig.${MYDOMAIN} -d dav.${MYDOMAIN} certonly >/dev/null 2>&1
615 else
616 ./letsencrypt-auto --agree-tos --renew-by-default --non-interactive --standalone --email ${SSLMAIL} --rsa-key-size 2048 -d ${MYDOMAIN} -d www.${MYDOMAIN} certonly >/dev/null 2>&1
617 fi
618 ln -s /etc/letsencrypt/live/${MYDOMAIN}/fullchain.pem /etc/nginx/ssl/${MYDOMAIN}.pem
619 ln -s /etc/letsencrypt/live/${MYDOMAIN}/privkey.pem /etc/nginx/ssl/${MYDOMAIN}.key.pem
620else
621 echo "${info} Creating self-signed SSL certificates..." | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
622 openssl ecparam -genkey -name secp384r1 -out /etc/nginx/ssl/${MYDOMAIN}.key.pem >/dev/null 2>&1
623 openssl req -new -sha256 -key /etc/nginx/ssl/${MYDOMAIN}.key.pem -out /etc/nginx/ssl/csr.pem -subj "/C=/ST=/L=/O=/OU=/CN=*.${MYDOMAIN}" >/dev/null 2>&1
624 openssl req -x509 -days 365 -key /etc/nginx/ssl/${MYDOMAIN}.key.pem -in /etc/nginx/ssl/csr.pem -out /etc/nginx/ssl/${MYDOMAIN}.pem >/dev/null 2>&1
625fi
626
627HPKP1=$(openssl x509 -pubkey < /etc/nginx/ssl/${MYDOMAIN}.pem | openssl pkey -pubin -outform der | openssl dgst -sha256 -binary | base64)
628HPKP2=$(openssl rand -base64 32)
629
630echo "${info} Creating strong Diffie-Hellman parameters, please wait..." | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
631openssl dhparam -out /etc/nginx/ssl/dh.pem 2048 >/dev/null 2>&1
632
633# Create server config
634rm -rf /etc/nginx/sites-available/${MYDOMAIN}.conf
635cat > /etc/nginx/sites-available/${MYDOMAIN}.conf <<END
636server {
637 listen 80 default_server;
638 server_name ${IPADR} ${MYDOMAIN};
639 return 301 https://${MYDOMAIN}\$request_uri;
640}
641
642server {
643 listen 443;
644 server_name ${IPADR} www.${MYDOMAIN} mail.${MYDOMAIN};
645 return 301 https://${MYDOMAIN}\$request_uri;
646}
647
648server {
649 listen 443 ssl http2 default deferred;
650 server_name ${MYDOMAIN};
651
652 root /etc/nginx/html;
653 index index.php index.html index.htm;
654
655 charset utf-8;
656
657 error_page 404 /index.php;
658
659 ssl_certificate ssl/${MYDOMAIN}.pem;
660 ssl_certificate_key ssl/${MYDOMAIN}.key.pem;
661 #ssl_trusted_certificate ssl/${MYDOMAIN}.pem;
662 ssl_dhparam ssl/dh.pem;
663 ssl_ecdh_curve secp384r1;
664 ssl_session_cache shared:SSL:10m;
665 ssl_session_timeout 10m;
666 ssl_session_tickets off;
667 ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
668 ssl_prefer_server_ciphers on;
669 ssl_buffer_size 1400;
670
671 #ssl_stapling on;
672 #ssl_stapling_verify on;
673 #resolver 8.8.8.8 8.8.4.4 208.67.222.222 208.67.220.220 valid=60s;
674 #resolver_timeout 2s;
675
676 ssl_ciphers "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:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!3DES:!MD5:!PSK";
677
678 #add_header Strict-Transport-Security "max-age=63072000; includeSubdomains; preload";
679 ##add_header Public-Key-Pins 'pin-sha256="PIN1"; pin-sha256="PIN2"; max-age=5184000; includeSubDomains';
680 add_header Cache-Control "public";
681 add_header X-Frame-Options SAMEORIGIN;
682 add_header Alternate-Protocol 443:npn-http/2;
683 add_header X-Content-Type-Options nosniff;
684 add_header X-XSS-Protection "1; mode=block";
685 add_header X-Permitted-Cross-Domain-Policies "master-only";
686 add_header "X-UA-Compatible" "IE=Edge";
687 add_header "Access-Control-Allow-Origin" "*";
688 add_header Content-Security-Policy "script-src 'self' 'unsafe-inline' 'unsafe-eval' *.youtube.com maps.gstatic.com *.googleapis.com *.google-analytics.com cdnjs.cloudflare.com assets.zendesk.com connect.facebook.net; frame-src 'self' *.youtube.com assets.zendesk.com *.facebook.com s-static.ak.facebook.com tautt.zendesk.com; object-src 'self'";
689
690 pagespeed on;
691 pagespeed EnableFilters collapse_whitespace;
692 pagespeed EnableFilters canonicalize_javascript_libraries;
693 pagespeed EnableFilters combine_css;
694 pagespeed EnableFilters combine_javascript;
695 pagespeed EnableFilters elide_attributes;
696 pagespeed EnableFilters extend_cache;
697 pagespeed EnableFilters flatten_css_imports;
698 pagespeed EnableFilters lazyload_images;
699 pagespeed EnableFilters rewrite_javascript;
700 pagespeed EnableFilters rewrite_images;
701 pagespeed EnableFilters insert_dns_prefetch;
702 pagespeed EnableFilters prioritize_critical_css;
703
704 pagespeed FetchHttps enable,allow_self_signed;
705 pagespeed FileCachePath /var/lib/nginx/nps_cache;
706 pagespeed RewriteLevel CoreFilters;
707 pagespeed CssFlattenMaxBytes 5120;
708 pagespeed LogDir /var/log/pagespeed;
709 pagespeed EnableCachePurge on;
710 pagespeed PurgeMethod PURGE;
711 pagespeed DownstreamCachePurgeMethod PURGE;
712 pagespeed DownstreamCachePurgeLocationPrefix http://127.0.0.1:80/;
713 pagespeed DownstreamCacheRewrittenPercentageThreshold 95;
714 pagespeed LazyloadImagesAfterOnload on;
715 pagespeed LazyloadImagesBlankUrl "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7";
716
717 pagespeed MemcachedThreads 1;
718 pagespeed MemcachedServers "localhost:11211";
719 pagespeed MemcachedTimeoutUs 100000;
720 pagespeed RespectVary on;
721
722 pagespeed Disallow "*/pma/*";
723
724 # This will correctly rewrite your subresources with https:// URLs and thus avoid mixed content warnings.
725 # Note, that you should only enable this option if you are behind a load-balancer that will set this header,
726 # otherwise your users will be able to set the protocol PageSpeed uses to interpret the request.
727 #
728 #pagespeed RespectXForwardedProto on;
729
730 auth_basic_user_file htpasswd/.htpasswd;
731
732 location ~ \.php\$ {
733 fastcgi_split_path_info ^(.+\.php)(/.+)\$;
734 if (!-e \$document_root\$fastcgi_script_name) {
735 return 404;
736 }
737 try_files \$fastcgi_script_name =404;
738 fastcgi_param PATH_INFO \$fastcgi_path_info;
739 fastcgi_param PATH_TRANSLATED \$document_root\$fastcgi_path_info;
740 fastcgi_param APP_ENV production;
741 fastcgi_pass unix:/var/run/php5-fpm.sock;
742 fastcgi_index index.php;
743 include fastcgi.conf;
744 fastcgi_intercept_errors off;
745 fastcgi_ignore_client_abort off;
746 fastcgi_buffers 256 16k;
747 fastcgi_buffer_size 128k;
748 fastcgi_connect_timeout 3s;
749 fastcgi_send_timeout 120s;
750 fastcgi_read_timeout 120s;
751 fastcgi_busy_buffers_size 256k;
752 fastcgi_temp_file_write_size 256k;
753 }
754
755 include /etc/nginx/sites-custom/*.conf;
756
757 location / {
758 # Uncomment, if you need to remove index.php from the
759 # URL. Usefull if you use Codeigniter, Zendframework, etc.
760 # or just need to remove the index.php
761 #
762 #try_files \$uri \$uri/ /index.php?\$args;
763 }
764
765 location ~* /\.(?!well-known\/) {
766 deny all;
767 access_log off;
768 log_not_found off;
769 }
770
771 location ~* (?:\.(?:bak|conf|dist|fla|in[ci]|log|psd|sh|sql|sw[op])|~)$ {
772 deny all;
773 access_log off;
774 log_not_found off;
775 }
776
777 location = /favicon.ico {
778 access_log off;
779 log_not_found off;
780 }
781
782 location = /robots.txt {
783 allow all;
784 access_log off;
785 log_not_found off;
786 }
787
788 location ~* ^.+\.(css|js)\$ {
789 rewrite ^(.+)\.(\d+)\.(css|js)\$ \$1.\$3 last;
790 expires 30d;
791 access_log off;
792 log_not_found off;
793 add_header Pragma public;
794 add_header Cache-Control "max-age=2592000, public";
795 }
796
797 location ~* \.(asf|asx|wax|wmv|wmx|avi|bmp|class|divx|doc|docx|eot|exe|gif|gz|gzip|ico|jpg|jpeg|jpe|mdb|mid|midi|mov|qt|mp3|m4a|mp4|m4v|mpeg|mpg|mpe|mpp|odb|odc|odf|odg|odp|ods|odt|ogg|ogv|otf|pdf|png|pot|pps|ppt|pptx|ra|ram|svg|svgz|swf|tar|t?gz|tif|tiff|ttf|wav|webm|wma|woff|wri|xla|xls|xlsx|xlt|xlw|zip)\$ {
798 expires 30d;
799 access_log off;
800 log_not_found off;
801 add_header Pragma public;
802 add_header Cache-Control "max-age=2592000, public";
803 }
804
805 if (\$http_user_agent ~* "FeedDemon|JikeSpider|Indy Library|Alexa Toolbar|AskTbFXTV|AhrefsBot|CrawlDaddy|CoolpadWebkit|Java|Feedly|UniversalFeedParser|ApacheBench|Microsoft URL Control|Swiftbot|ZmEu|oBot|jaunty|Python-urllib|lightDeckReports Bot|YYSpider|DigExt|YisouSpider|HttpClient|MJ12bot|heritrix|EasouSpider|Ezooms|Scrapy") {
806 return 403;
807 }
808}
809END
810
811ln -s /etc/nginx/sites-available/${MYDOMAIN}.conf /etc/nginx/sites-enabled/${MYDOMAIN}.conf
812
813if [ ${CLOUDFLARE} == '0' ] && [ ${USE_VALID_SSL} == '1' ]; then
814 sed -i 's/#ssl/ssl/g' /etc/nginx/sites-available/${MYDOMAIN}.conf
815 sed -i 's/#resolver/resolver/g' /etc/nginx/sites-available/${MYDOMAIN}.conf
816 sed -i 's/#add/add/g' /etc/nginx/sites-available/${MYDOMAIN}.conf
817fi
818
819# Configure PHP
820echo "${info} Configuring PHP..." | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
821sed -i 's/.*disable_functions =.*/disable_functions = pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,escapeshellarg,passthru,proc_close,proc_get_status,proc_nice,proc_open,proc_terminate,/' /etc/php5/fpm/php.ini
822sed -i 's/.*ignore_user_abort =.*/ignore_user_abort = Off/' /etc/php5/fpm/php.ini
823sed -i 's/.*expose_php =.*/expose_php = Off/' /etc/php5/fpm/php.ini
824sed -i 's/.*post_max_size =.*/post_max_size = 15M/' /etc/php5/fpm/php.ini
825sed -i 's/.*default_charset =.*/default_charset = "UTF-8"/' /etc/php5/fpm/php.ini
826sed -i 's/.*cgi.fix_pathinfo=.*/cgi.fix_pathinfo=1/' /etc/php5/fpm/php.ini
827sed -i 's/.*upload_max_filesize =.*/upload_max_filesize = 15M/' /etc/php5/fpm/php.ini
828sed -i 's/.*default_socket_timeout =.*/default_socket_timeout = 30/' /etc/php5/fpm/php.ini
829sed -i 's/.*date.timezone =.*/date.timezone = Europe\/Berlin/' /etc/php5/fpm/php.ini
830sed -i 's/.*mysql.allow_persistent =.*/mysql.allow_persistent = Off/' /etc/php5/fpm/php.ini
831sed -i 's/.*session.cookie_httponly =.*/session.cookie_httponly = 1/' /etc/php5/fpm/php.ini
832
833# Configure PHP-FPM
834sed -i 's/.*emergency_restart_threshold =.*/emergency_restart_threshold = 10/' /etc/php5/fpm/php-fpm.conf
835sed -i 's/.*emergency_restart_interval =.*/emergency_restart_interval = 1m/' /etc/php5/fpm/php-fpm.conf
836sed -i 's/.*process_control_timeout =.*/process_control_timeout = 10/' /etc/php5/fpm/php-fpm.conf
837sed -i 's/.*events.mechanism =.*/events.mechanism = epoll/' /etc/php5/fpm/php-fpm.conf
838sed -i 's/.*listen.mode =.*/listen.mode = 0666/' /etc/php5/fpm/pool.d/www.conf
839sed -i 's/.*listen.allowed_clients =.*/listen.allowed_clients = 127.0.0.1/' /etc/php5/fpm/pool.d/www.conf
840sed -i 's/.*pm.max_children =.*/pm.max_children = 50/' /etc/php5/fpm/pool.d/www.conf
841sed -i 's/.*pm.start_servers =.*/pm.start_servers = 15/' /etc/php5/fpm/pool.d/www.conf
842sed -i 's/.*pm.min_spare_servers =.*/pm.min_spare_servers = 5/' /etc/php5/fpm/pool.d/www.conf
843sed -i 's/.*pm.max_spare_servers =.*/pm.max_spare_servers = 25/' /etc/php5/fpm/pool.d/www.conf
844sed -i 's/.*pm.process_idle_timeout =.*/pm.process_idle_timeout = 60s;/' /etc/php5/fpm/pool.d/www.conf
845sed -i 's/.*request_terminate_timeout =.*/request_terminate_timeout = 30/' /etc/php5/fpm/pool.d/www.conf
846sed -i 's/.*security.limit_extensions =.*/security.limit_extensions = .php/' /etc/php5/fpm/pool.d/www.conf
847sed -i 's/.*php_flag[display_errors] =.*/php_flag[display_errors] = off/' /etc/php5/fpm/pool.d/www.conf
848sed -i 's/.*php_admin_value[error_log] =.*/php_admin_value[error_log] = \/var\/log\/fpm5-php.www.log/' /etc/php5/fpm/pool.d/www.conf
849sed -i 's/.*php_admin_flag[log_errors] =.*/php_admin_flag[log_errors] = on/' /etc/php5/fpm/pool.d/www.conf
850sed -i 's/.*php_admin_value[memory_limit] =.*/php_admin_value[memory_limit] = 128M/' /etc/php5/fpm/pool.d/www.conf
851echo -e "php_flag[display_errors] = off" >> /etc/php5/fpm/pool.d/www.conf
852
853# Configure APCu
854rm -rf /etc/php5/mods-available/apcu.ini
855rm -rf /etc/php5/mods-available/20-apcu.ini
856
857cat > /etc/php5/mods-available/apcu.ini <<END
858extension=apcu.so
859apc.enabled=1
860apc.stat = "0"
861apc.max_file_size = "1M"
862apc.localcache = "1"
863apc.localcache.size = "256"
864apc.shm_segments = "1"
865apc.ttl = "3600"
866apc.user_ttl = "7200"
867apc.enable_cli=0
868apc.gc_ttl = "3600"
869apc.cache_by_default = "1"
870apc.filters = ""
871apc.write_lock = "1"
872apc.num_files_hint= "512"
873apc.user_entries_hint="4096"
874apc.shm_size = "256M"
875apc.mmap_file_mask=/tmp/apc.XXXXXX
876apc.include_once_override = "0"
877apc.file_update_protection="2"
878apc.canonicalize = "1"
879apc.report_autofilter="0"
880apc.stat_ctime="0"
881END
882
883ln -s /etc/php5/mods-available/apcu.ini /etc/php5/mods-available/20-apcu.ini
884
885
886# Restart FPM & Nginx
887systemctl -q start nginx.service
888systemctl -q restart php5-fpm.service
889
890if [ ${USE_MAILSERVER} == '1' ]; then
891 echo "${info} Installing mailserver..." | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
892
893 # Mailcow binaries
894 install -m 755 ~/sources/mailcow/misc/mc_clean_spam_aliases /etc/cron.daily/mc_clean_spam_aliases
895 install -m 755 ~/sources/mailcow/misc/mc_pfset /usr/local/sbin/mc_pfset
896 install -m 755 ~/sources/mailcow/misc/mc_pflog_renew /usr/local/sbin/mc_pflog_renew
897 install -m 755 ~/sources/mailcow/misc/mc_msg_size /usr/local/sbin/mc_msg_size
898 install -m 755 ~/sources/mailcow/misc/mc_dkim_ctrl /usr/local/sbin/mc_dkim_ctrl
899 install -m 755 ~/sources/mailcow/misc/mc_setup_backup /usr/local/sbin/mc_setup_backup
900 install -m 700 ~/sources/mailcow/misc/mc_resetadmin /usr/local/sbin/mc_resetadmin
901
902 # Prerequisites
903 update-alternatives --set mailx /usr/bin/bsd-mailx --quiet >/dev/null 2>&1
904 DEBIAN_FRONTEND=noninteractive aptitude -y install clamav-daemon dovecot-common dovecot-core dovecot-imapd dovecot-lmtpd dovecot-managesieved dovecot-mysql dovecot-pop3d dovecot-sieve dovecot-solr fcgiwrap fetchmail imagemagick mailutils mailgraph/unstable mpack opendkim opendkim-tools pflogsumm postfix postfix-mysql postfix-pcre postgrey pyzor razor rrdtool/unstable spamassassin spamc spawn-fcgi wkhtmltopdf >/dev/null 2>&1
905
906 # Create SSL
907 mkdir -p /etc/ssl/mail >/dev/null 2>&1
908 rm /etc/ssl/mail/* >/dev/null 2>&1
909 cp /etc/nginx/ssl/dh.pem /etc/ssl/mail/dhparams.pem
910 if [ ${USE_VALID_SSL} == '1' ]; then
911 ln -s /etc/letsencrypt/live/${MYDOMAIN}/fullchain.pem /etc/ssl/mail/mail.crt
912 ln -s /etc/letsencrypt/live/${MYDOMAIN}/privkey.pem /etc/ssl/mail/mail.key
913 else
914 openssl req -new -newkey rsa:4096 -sha256 -days 1095 -nodes -x509 -subj "/C=/ST=/L=/O=/OU=/CN=mail.${MYDOMAIN}" -keyout /etc/ssl/mail/mail.key -out /etc/ssl/mail/mail.crt >/dev/null 2>&1
915 chmod 600 /etc/ssl/mail/mail.key
916 cp /etc/ssl/mail/mail.crt /usr/local/share/ca-certificates/
917 update-ca-certificates >/dev/null 2>&1
918 fi
919
920 # Create MySQL databases
921 echo "${info} Creating MySQL databases..." | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
922 mysql -uroot -p${MYSQL_ROOT_PASS} -h${MYSQL_HOSTNAME} -e "CREATE DATABASE ${MYSQL_MCDB_NAME}; GRANT SELECT, INSERT, UPDATE, DELETE ON ${MYSQL_MCDB_NAME}.* TO '${MYSQL_MCDB_USER}'@'%' IDENTIFIED BY '${MYSQL_MCDB_PASS}';"
923 mysql -uroot -p${MYSQL_ROOT_PASS} -h${MYSQL_HOSTNAME} -e "CREATE DATABASE ${MYSQL_RCDB_NAME}; GRANT ALL PRIVILEGES ON ${MYSQL_RCDB_NAME}.* TO '${MYSQL_RCDB_USER}'@'%' IDENTIFIED BY '${MYSQL_RCDB_PASS}';"
924 mysql -uroot -p${MYSQL_ROOT_PASS} -h${MYSQL_HOSTNAME} -e "GRANT SELECT ON ${MYSQL_MCDB_NAME}.* TO 'vmail'@'%'; FLUSH PRIVILEGES;"
925
926 # Postfix
927 echo "${info} Installing Postfix..." | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
928 cp -R ~/sources/mailcow/postfix/conf/* /etc/postfix/
929 chown root:postfix "/etc/postfix/sql"; chmod 750 "/etc/postfix/sql"
930 chown root:postfix "/etc/postfix/sql/mysql_virtual_alias_domain_catchall_maps.cf"; chmod 640 "/etc/postfix/sql/mysql_virtual_alias_domain_catchall_maps.cf"
931 chown root:postfix "/etc/postfix/sql/mysql_virtual_alias_maps.cf"; chmod 640 "/etc/postfix/sql/mysql_virtual_alias_maps.cf"
932 chown root:postfix "/etc/postfix/sql/mysql_virtual_alias_domain_mailbox_maps.cf"; chmod 640 "/etc/postfix/sql/mysql_virtual_alias_domain_mailbox_maps.cf"
933 chown root:postfix "/etc/postfix/sql/mysql_virtual_mailbox_limit_maps.cf"; chmod 640 "/etc/postfix/sql/mysql_virtual_mailbox_limit_maps.cf"
934 chown root:postfix "/etc/postfix/sql/mysql_virtual_mailbox_maps.cf"; chmod 640 "/etc/postfix/sql/mysql_virtual_mailbox_maps.cf"
935 chown root:postfix "/etc/postfix/sql/mysql_virtual_mxdomain_maps.cf"; chmod 640 "/etc/postfix/sql/mysql_virtual_mxdomain_maps.cf"
936 chown root:postfix "/etc/postfix/sql/mysql_virtual_alias_domain_maps.cf"; chmod 640 "/etc/postfix/sql/mysql_virtual_alias_domain_maps.cf"
937 chown root:postfix "/etc/postfix/sql/mysql_virtual_spamalias_maps.cf"; chmod 640 "/etc/postfix/sql/mysql_virtual_spamalias_maps.cf"
938 chown root:postfix "/etc/postfix/sql/mysql_virtual_sender_acl.cf"; chmod 640 "/etc/postfix/sql/mysql_virtual_sender_acl.cf"
939 chown root:postfix "/etc/postfix/sql/mysql_virtual_domains_maps.cf"; chmod 640 "/etc/postfix/sql/mysql_virtual_domains_maps.cf"
940 chown root:root "/etc/postfix/master.cf"; chmod 644 "/etc/postfix/master.cf"
941 chown root:root "/etc/postfix/main.cf"; chmod 644 "/etc/postfix/main.cf"
942 sed -i "s/MAILCOW_HOST.MAILCOW_DOMAIN/mail.${MYDOMAIN}/g" /etc/postfix/main.cf
943 sed -i "s/MAILCOW_DOMAIN/${MYDOMAIN}/g" /etc/postfix/main.cf
944 chmod +x /usr/local/sbin/mc_pfset /usr/local/sbin/mc_pflog_renew
945 chmod 700 /etc/cron.daily/mc_clean_spam_aliases
946 sed -i "s/my_mailcowpass/${MYSQL_MCDB_PASS}/g" /etc/postfix/sql/* /etc/cron.daily/mc_clean_spam_aliases
947 sed -i "s/my_mailcowuser/${MYSQL_MCDB_USER}/g" /etc/postfix/sql/* /etc/cron.daily/mc_clean_spam_aliases
948 sed -i "s/my_mailcowdb/${MYSQL_MCDB_NAME}/g" /etc/postfix/sql/* /etc/cron.daily/mc_clean_spam_aliases
949 sed -i "s/my_dbhost/${MYSQL_HOSTNAME}/g" /etc/postfix/sql/* /etc/cron.daily/mc_clean_spam_aliases
950 sed -i '/^POSTGREY_OPTS=/s/=.*/="--inet=127.0.0.1:10023"/' /etc/default/postgrey
951 chown www-data: /etc/postfix/mailcow_*
952 chmod 755 /var/spool/
953 sed -i "/%www-data/d" /etc/sudoers >/dev/null 2>&1
954 sed -i "/%vmail/d" /etc/sudoers >/dev/null 2>&1
955 echo '%www-data ALL=(ALL) NOPASSWD: /usr/bin/doveadm * sync *, /usr/local/sbin/mc_pfset *, /usr/bin/doveadm quota recalc -A, /usr/sbin/dovecot reload, /usr/sbin/postfix reload, /usr/local/sbin/mc_dkim_ctrl, /usr/local/sbin/mc_msg_size, /usr/local/sbin/mc_pflog_renew, /usr/local/sbin/mc_setup_backup' >> /etc/sudoers
956 if [ ${USE_VALID_SSL} == '1' ]; then
957 sed -i 's/smtp_tls_CAfile/# smtp_tls_CAfile/g' /etc/postfix/main.cf
958 fi
959
960 # Fuglu
961 if [[ -z $(grep fuglu /etc/passwd) ]]; then
962 userdel fuglu >/dev/null 2>&1
963 groupadd fuglu >/dev/null 2>&1
964 useradd -g fuglu -s /bin/false fuglu
965 usermod -a -G debian-spamd fuglu
966 usermod -a -G clamav fuglu
967 fi
968 rm /tmp/fuglu_control.sock >/dev/null 2>&1
969 mkdir /var/log/fuglu >/dev/null 2>&1
970 chown fuglu:fuglu /var/log/fuglu
971 tar xf ~/sources/mailcow/fuglu/inst/0.6.5.tar -C ~/sources/mailcow/fuglu/inst/ >/dev/null 2>&1
972 (cd ~/sources/mailcow/fuglu/inst/0.6.5 ; python setup.py -q install)
973 cp -R ~/sources/mailcow/fuglu/conf/* /etc/fuglu/
974 cp ~/sources/mailcow/fuglu/inst/0.6.5/scripts/startscripts/debian/8/fuglu.service /etc/systemd/system/fuglu.service
975 systemctl -q disable fuglu
976 [[ -f /lib/systemd/system/fuglu.service ]] && rm /lib/systemd/system/fuglu.service
977 systemctl -q daemon-reload
978 systemctl -q enable fuglu
979 rm -rf ~/sources/mailcow/fuglu/inst/0.6.5
980
981 # Dovecot
982 echo "${info} Installing Dovecot..." | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
983 systemctl -q disable dovecot.socket
984 if [[ -z $(grep '/var/vmail:' /etc/passwd | grep '5000:5000') ]]; then
985 userdel vmail >/dev/null 2>&1
986 groupdel vmail >/dev/null 2>&1
987 groupadd -g 5000 vmail
988 useradd -g vmail -u 5000 vmail -d /var/vmail
989 fi
990 chmod 755 "/etc/dovecot/"
991 install -o root -g dovecot -m 640 ~/sources/mailcow/dovecot/conf/dovecot-dict-sql.conf /etc/dovecot/dovecot-dict-sql.conf
992 install -o root -g vmail -m 640 ~/sources/mailcow/dovecot/conf/dovecot-mysql.conf /etc/dovecot/dovecot-mysql.conf
993 install -m 644 ~/sources/mailcow/dovecot/conf/dovecot.conf /etc/dovecot/dovecot.conf
994 touch /etc/dovecot/mailcow_public_folder.conf
995 chmod 664 "/etc/dovecot/mailcow_public_folder.conf"; chown root:www-data "/etc/dovecot/mailcow_public_folder.conf"
996 DOVEFILES=$(find /etc/dovecot -maxdepth 1 -type f -printf '/etc/dovecot/%f ')
997 sed -i "s/MAILCOW_HOST.MAILCOW_DOMAIN/mail.${MYDOMAIN}/g" ${DOVEFILES}
998 sed -i "s/MAILCOW_DOMAIN/${MYDOMAIN}/g" ${DOVEFILES}
999 sed -i "s/my_mailcowpass/${MYSQL_MCDB_PASS}/g" ${DOVEFILES}
1000 sed -i "s/my_mailcowuser/${MYSQL_MCDB_USER}/g" ${DOVEFILES}
1001 sed -i "s/my_mailcowdb/${MYSQL_MCDB_NAME}/g" ${DOVEFILES}
1002 sed -i "s/my_dbhost/${MYSQL_HOSTNAME}/g" ${DOVEFILES}
1003 mkdir /etc/dovecot/conf.d >/dev/null 2>&1
1004 mkdir -p /var/vmail/sieve >/dev/null 2>&1
1005 mkdir -p /var/vmail/public >/dev/null 2>&1
1006 if [ ! -f /var/vmail/public/dovecot-acl ]; then
1007 echo "anyone lrwstipekxa" > /var/vmail/public/dovecot-acl
1008 fi
1009 install -m 644 ~/sources/mailcow/dovecot/conf/global.sieve /var/vmail/sieve/global.sieve
1010 touch /var/vmail/sieve/default.sieve
1011 install -m 755 ~/sources/mailcow/misc/mc_msg_size /usr/local/sbin/mc_msg_size
1012 sievec /var/vmail/sieve/global.sieve
1013 chown -R vmail:vmail /var/vmail
1014 [[ -f /etc/cron.daily/doverecalcq ]] && rm /etc/cron.daily/doverecalcq
1015 install -m 755 ~/sources/mailcow/dovecot/conf/dovemaint /etc/cron.daily/
1016 install -m 644 ~/sources/mailcow/dovecot/conf/solrmaint /etc/cron.d/
1017
1018 # clamav
1019 echo "${info} Installing ClamaV..." | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
1020 usermod -a -G vmail clamav >/dev/null 2>&1
1021 service clamav-freshclam stop >/dev/null 2>&1
1022 killall freshclam >/dev/null 2>&1
1023 rm -f /var/lib/clamav/* >/dev/null 2>&1 >/dev/null 2>&1
1024 sed -i '/DatabaseMirror/d' /etc/clamav/freshclam.conf
1025 sed -i '/MaxFileSize/c\MaxFileSize 10240M' /etc/clamav/clamd.conf
1026 sed -i '/StreamMaxLength/c\StreamMaxLength 10240M' /etc/clamav/clamd.conf
1027 echo "DatabaseMirror clamav.netcologne.de
1028DatabaseMirror clamav.internet24.eu
1029DatabaseMirror clamav.inode.at" >> /etc/clamav/freshclam.conf
1030 if [[ -f /etc/apparmor.d/usr.sbin.clamd || -f /etc/apparmor.d/local/usr.sbin.clamd ]]; then
1031 rm /etc/apparmor.d/usr.sbin.clamd >/dev/null 2>&1
1032 rm /etc/apparmor.d/local/usr.sbin.clamd >/dev/null 2>&1
1033 service apparmor restart >/dev/null 2>&1
1034 fi
1035 cp -f ~/sources/mailcow/clamav/clamav-unofficial-sigs.sh /usr/local/bin/clamav-unofficial-sigs.sh
1036 chmod +x /usr/local/bin/clamav-unofficial-sigs.sh
1037 cp -f ~/sources/mailcow/clamav/clamav-unofficial-sigs.conf /etc/clamav-unofficial-sigs.conf
1038 cp -f ~/sources/mailcow/clamav/clamav-unofficial-sigs.8 /usr/share/man/man8/clamav-unofficial-sigs.8
1039 cp -f ~/sources/mailcow/clamav/clamav-unofficial-sigs-cron /etc/cron.d/clamav-unofficial-sigs-cron
1040 cp -f ~/sources/mailcow/clamav/clamav-unofficial-sigs-logrotate /etc/logrotate.d/clamav-unofficial-sigs-logrotate
1041 mkdir -p /var/log/clamav-unofficial-sigs >/dev/null 2>&1
1042 sed -i '/MaxFileSize/c\MaxFileSize 10M' /etc/clamav/clamd.conf
1043 sed -i '/StreamMaxLength/c\StreamMaxLength 10M' /etc/clamav/clamd.conf
1044 freshclam >/dev/null 2>&1
1045
1046 # OpenDKIM
1047 echo "${info} Installing OpenDKIM..." | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
1048 echo 'SOCKET="inet:10040@localhost"' > /etc/default/opendkim
1049 mkdir -p /etc/opendkim/{keyfiles,dnstxt} >/dev/null 2>&1
1050 touch /etc/opendkim/{KeyTable,SigningTable}
1051 install -m 644 ~/sources/mailcow/opendkim/conf/opendkim.conf /etc/opendkim.conf
1052
1053 # SpamAssassin
1054 echo "${info} Installing SpamAssassin..." | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
1055 cp ~/sources/mailcow/spamassassin/conf/local.cf /etc/spamassassin/local.cf
1056 sed -i '/^OPTIONS=/s/=.*/="--create-prefs --max-children 5 --helper-home-dir --username debian-spamd --socketpath \/var\/run\/spamd.sock --socketowner debian-spamd --socketgroup debian-spamd"/' /etc/default/spamassassin
1057 sed -i '/^CRON=/s/=.*/="1"/' /etc/default/spamassassin
1058 sed -i '/^ENABLED=/s/=.*/="1"/' /etc/default/spamassassin
1059 # Thanks to mf3hd@GitHub
1060 [[ -z $(grep RANDOM_DELAY /etc/crontab) ]] && sed -i '/SHELL/a RANDOM_DELAY=30' /etc/crontab
1061 install -m 755 ~/sources/mailcow/spamassassin/conf/spamlearn /etc/cron.daily/spamlearn
1062 install -m 755 ~/sources/mailcow/spamassassin/conf/spamassassin_heinlein /etc/cron.daily/spamassassin_heinlein
1063 # Thanks to mf3hd@GitHub, again!
1064 chmod g+s /etc/spamassassin
1065 chown -R debian-spamd: /etc/spamassassin
1066 razor-admin -create -home /etc/razor -conf=/etc/razor/razor-agent.conf >/dev/null 2>&1
1067 razor-admin -discover -home /etc/razor >/dev/null 2>&1
1068 razor-admin -register -home /etc/razor >/dev/null 2>&1
1069 su debian-spamd -c "pyzor --homedir /etc/mail/spamassassin/.pyzor discover >/dev/null 2>&1"
1070 su debian-spamd -c "sa-update >/dev/null 2>&1"
1071 systemctl enable spamassassin >/dev/null 2>&1
1072
1073 # Mailcow
1074 echo "${info} Installing Mailcow..." | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
1075 mkdir -p /var/mailcow/log
1076 mkdir -p /var/www/ >/dev/null 2>&1
1077 cp ~/sources/mailcow/webserver/php5-fpm/conf/pool/mail.conf /etc/php5/fpm/pool.d/mail.conf
1078 sed -i "/date.timezone/c\php_admin_value[date.timezone] = ${TIMEZONE}" /etc/php5/fpm/pool.d/mail.conf
1079 mkdir /var/lib/php5/sessions >/dev/null 2>&1
1080 chown -R www-data:www-data /var/lib/php5/sessions
1081 install -m 755 ~/sources/mailcow/misc/mc_setup_backup /usr/local/sbin/mc_setup_backup
1082 cp -R ~/sources/mailcow/webserver/htdocs/{mail,dav,zpush} /var/www/
1083 tar xf /var/www/dav/vendor.tar -C /var/www/dav/ ; rm /var/www/dav/vendor.tar
1084 tar xf /var/www/zpush/vendor.tar -C /var/www/zpush/ ; rm /var/www/zpush/vendor.tar
1085 find /var/www/{dav,mail,zpush} -type d -exec chmod 755 {} \;
1086 find /var/www/{dav,mail,zpush} -type f -exec chmod 644 {} \;
1087 sed -i "/date_default_timezone_set/c\date_default_timezone_set('${TIMEZONE}');" /var/www/dav/server.php
1088 touch /var/mailcow/mailbox_backup_env
1089 echo none > /var/mailcow/log/pflogsumm.log
1090 cp ~/sources/mailcow/misc/mc_resetadmin /usr/local/sbin/mc_resetadmin ; chmod 700 /usr/local/sbin/mc_resetadmin
1091 sed -i "s/mailcow_sub/mail/g" /var/www/mail/autoconfig.xml
1092 sed -i "s/my_dbhost/${MYSQL_HOSTNAME}/g" /var/www/mail/inc/vars.inc.php /var/www/dav/server.php /usr/local/sbin/mc_resetadmin /var/www/zpush/config.php /var/www/zpush/backend/imap/config.php
1093 sed -i "s/my_mailcowpass/${MYSQL_MCDB_PASS}/g" /var/www/mail/inc/vars.inc.php /var/www/dav/server.php /usr/local/sbin/mc_resetadmin /var/www/zpush/config.php /var/www/zpush/backend/imap/config.php
1094 sed -i "s/my_mailcowuser/${MYSQL_MCDB_USER}/g" /var/www/mail/inc/vars.inc.php /var/www/dav/server.php /usr/local/sbin/mc_resetadmin /var/www/zpush/config.php /var/www/zpush/backend/imap/config.php
1095 sed -i "s/my_mailcowdb/${MYSQL_MCDB_NAME}/g" /var/www/mail/inc/vars.inc.php /var/www/dav/server.php /usr/local/sbin/mc_resetadmin /var/www/zpush/config.php /var/www/zpush/backend/imap/config.php
1096 sed -i "s/httpd_dav_subdomain/dav/g" /var/www/mail/inc/vars.inc.php
1097 chown -R www-data: /var/www/{.,mail,dav} /var/lib/php5/sessions /var/mailcow/mailbox_backup_env
1098 mysql -uroot -p${MYSQL_ROOT_PASS} -h${MYSQL_HOSTNAME} ${MYSQL_MCDB_NAME} < ~/sources/mailcow/webserver/htdocs/init.sql
1099 if [[ -z $(mysql -uroot -p${MYSQL_ROOT_PASS} -h${MYSQL_HOSTNAME} ${MYSQL_MCDB_NAME} -e "SHOW INDEX FROM propertystorage WHERE KEY_NAME = 'path_property';" -N -B) ]]; then
1100 mysql -uroot -p${MYSQL_ROOT_PASS} -h${MYSQL_HOSTNAME} ${MYSQL_MCDB_NAME} -e "CREATE UNIQUE INDEX path_property ON propertystorage (path(600), name(100));" -N -B
1101 fi
1102 if [[ -z $(mysql -uroot -p${MYSQL_ROOT_PASS} -h${MYSQL_HOSTNAME} ${MYSQL_MCDB_NAME} -e "SHOW INDEX FROM zpush_states WHERE KEY_NAME = 'idx_zpush_states_unique';" -N -B) ]]; then
1103 mysql -uroot -p${MYSQL_ROOT_PASS} -h${MYSQL_HOSTNAME} ${MYSQL_MCDB_NAME} -e "CREATE unique index idx_zpush_states_unique on zpush_states (device_id, uuid, state_type, counter);" -N -B
1104 fi
1105 if [[ -z $(mysql -uroot -p${MYSQL_ROOT_PASS} -h${MYSQL_HOSTNAME} ${MYSQL_MCDB_NAME} -e "SHOW INDEX FROM zpush_preauth_users WHERE KEY_NAME = 'index_zpush_preauth_users_on_username_and_device_id';" -N -B) ]]; then
1106 mysql -uroot -p${MYSQL_ROOT_PASS} -h${MYSQL_HOSTNAME} ${MYSQL_MCDB_NAME} -e "CREATE unique index index_zpush_preauth_users_on_username_and_device_id on zpush_preauth_users (username, device_id);" -N -B
1107 fi
1108 if [[ -z $(mysql -uroot -p${MYSQL_ROOT_PASS} -h${MYSQL_HOSTNAME} ${MYSQL_MCDB_NAME} -e "SHOW COLUMNS FROM domain LIKE 'relay_all_recipients';" -N -B) ]]; then
1109 mysql -uroot -p${MYSQL_ROOT_PASS} -h${MYSQL_HOSTNAME} ${MYSQL_MCDB_NAME} -e "ALTER TABLE domain ADD relay_all_recipients tinyint(1) NOT NULL DEFAULT '0';" -N -B
1110 fi
1111 if [[ $(mysql -uroot -p${MYSQL_ROOT_PASS} -h${MYSQL_HOSTNAME} ${MYSQL_MCDB_NAME} -s -N -e "SELECT * FROM admin;" | wc -l) -lt 1 ]]; then
1112 mailcow_admin_pass_hashed=$(doveadm pw -s SHA512-CRYPT -p ${MAILCOW_ADMIN_PASS})
1113 mysql -uroot -p${MYSQL_ROOT_PASS} -h${MYSQL_HOSTNAME} ${MYSQL_MCDB_NAME} -e "INSERT INTO admin VALUES ('${MAILCOW_ADMIN_USER}','$mailcow_admin_pass_hashed',1,now(),now(),1);"
1114 mysql -uroot -p${MYSQL_ROOT_PASS} -h${MYSQL_HOSTNAME} ${MYSQL_MCDB_NAME} -e "INSERT INTO domain_admins (username, domain, created, active) VALUES ('${MAILCOW_ADMIN_USER}', 'ALL', now(), '1');"
1115 else
1116 echo "${info} At least one administrator exists, will not create another mailcow administrator" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
1117 fi
1118
1119 # zpush
1120 echo "${info} Installing Z-Push..." | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
1121 sed -i "s#MAILCOW_TIMEZONE#${TIMEZONE}#g" /var/www/zpush/config.php
1122 sed -i "s/MAILCOW_HOST.MAILCOW_DOMAIN/mail.${MYDOMAIN}/g" /var/www/zpush/backend/imap/config.php
1123 sed -i "s/MAILCOW_DAV_HOST.MAILCOW_DOMAIN/dav.${MYDOMAIN}/g" /var/www/zpush/backend/caldav/config.php
1124 sed -i "s/MAILCOW_DAV_HOST.MAILCOW_DOMAIN/dav.${MYDOMAIN}/g" /var/www/zpush/backend/carddav/config.php
1125 mkdir /var/{lib,log}/z-push 2>/dev/null
1126 chown -R www-data: /var/{lib,log}/z-push
1127 mkdir /var/www/zpush/mail
1128 cat > /var/www/zpush/mail/config-v1.1.xml <<END
1129<?xml version="1.0" encoding="UTF-8"?>
1130
1131<clientConfig version="1.1">
1132 <emailProvider id="${MYDOMAIN}">
1133 <domain>${MYDOMAIN}</domain>
1134 <displayName>${MYDOMAIN} Mail</displayName>
1135 <displayShortName>${MYDOMAIN}</displayShortName>
1136 <incomingServer type="imap">
1137 <hostname>mail.${MYDOMAIN}</hostname>
1138 <port>993</port>
1139 <socketType>SSL</socketType>
1140 <authentication>password-cleartext</authentication>
1141 <username>%EMAILADDRESS%</username>
1142 </incomingServer>
1143 <incomingServer type="imap">
1144 <hostname>mail.${MYDOMAIN}</hostname>
1145 <port>143</port>
1146 <socketType>STARTTLS</socketType>
1147 <authentication>password-cleartext</authentication>
1148 <username>%EMAILADDRESS%</username>
1149 </incomingServer>
1150 <incomingServer type="pop3">
1151 <hostname>mail.${MYDOMAIN}</hostname>
1152 <port>995</port>
1153 <socketType>SSL</socketType>
1154 <authentication>password-cleartext</authentication>
1155 <username>%EMAILADDRESS%</username>
1156 </incomingServer>
1157 <incomingServer type="pop3">
1158 <hostname>mail.${MYDOMAIN}</hostname>
1159 <port>110</port>
1160 <socketType>STARTTLS</socketType>
1161 <authentication>password-cleartext</authentication>
1162 <username>%EMAILADDRESS%</username>
1163 </incomingServer>
1164 <outgoingServer type="smtp">
1165 <hostname>mail.${MYDOMAIN}</hostname>
1166 <port>587</port>
1167 <socketType>STARTTLS</socketType>
1168 <authentication>password-cleartext</authentication>
1169 <username>%EMAILADDRESS%</username>
1170 </outgoingServer>
1171 <documentation url="https://${MYDOMAIN}/admin">
1172 <descr lang="de">Allgemeine Beschreibung der Einstellungen</descr>
1173 <descr lang="en">Generic settings page</descr>
1174 </documentation>
1175 <documentation url="https://${MYDOMAIN}/admin">
1176 <descr lang="de">TB 2.0 IMAP-Einstellungen</descr>
1177 <descr lang="en">TB 2.0 IMAP settings</descr>
1178 </documentation>
1179 </emailProvider>
1180</clientConfig>
1181END
1182 chown -R www-data: /var/www/zpush/mail/
1183
1184 # Cleaning up old files
1185 sed -i '/test -d /var/run/fetchmail/d' /etc/rc.local >/dev/null 2>&1
1186 rm /etc/cron.d/pfadminfetchmail >/dev/null 2>&1
1187 rm /etc/mail/postfixadmin/fetchmail.conf >/dev/null 2>&1
1188 rm /usr/local/bin/fetchmail.pl >/dev/null 2>&1
1189
1190 # Create Nginx Config
1191 cat > /etc/nginx/sites-custom/mailcow.conf <<END
1192location /admin {
1193 alias /var/www/mail;
1194 index index.php;
1195
1196 location ~ ^/admin/(.+\.php)$ {
1197 alias /var/www/mail/\$1;
1198 fastcgi_split_path_info ^(.+\.php)(/.+)$;
1199 include fastcgi_params;
1200 fastcgi_index index.php;
1201 fastcgi_param SCRIPT_FILENAME /var/www/mail/\$1;
1202 fastcgi_pass unix:/var/run/php5-fpm-mail.sock;
1203 }
1204
1205 location ~* ^/admin/(.+\.(jpg|jpeg|gif|css|png|js|ico|html|xml|txt))$ {
1206 alias /var/www/mail/\$1;
1207 }
1208}
1209
1210location ~ ^/(admin/rc)/ {
1211 deny all;
1212 return 301 /admin;
1213}
1214
1215location ~ \.cgi\$ {
1216 allow 127.0.0.1;
1217 deny all;
1218 alias /usr/lib/cgi-bin;
1219 include fastcgi_params;
1220 fastcgi_param SCRIPT_FILENAME /usr/lib/cgi-bin/\$1;
1221 fastcgi_pass unix:/var/run/fcgiwrap.socket;
1222}
1223END
1224
1225 cat > /etc/nginx/sites-available/mailgraph.conf <<END
1226server {
1227 listen 127.0.0.1:81;
1228 location ~ \.cgi\$ {
1229 alias /usr/lib/cgi-bin/\$1;
1230 include /etc/nginx/fastcgi_params;
1231 fastcgi_pass unix:/var/run/fcgiwrap.socket;
1232 }
1233}
1234END
1235
1236 cat > /etc/nginx/sites-available/autodiscover.${MYDOMAIN}.conf <<END
1237server {
1238 listen 80;
1239 server_name autodiscover.${MYDOMAIN} autoconfig.${MYDOMAIN};
1240 return 301 https://autodiscover.${MYDOMAIN}\$request_uri;
1241}
1242
1243server {
1244 listen 443 ssl http2;
1245 server_name autodiscover.${MYDOMAIN} autoconfig.${MYDOMAIN};
1246
1247 root /var/www/zpush;
1248 index index.php;
1249 charset utf-8;
1250
1251 error_page 404 /index.php;
1252
1253 ssl_certificate ssl/${MYDOMAIN}.pem;
1254 ssl_certificate_key ssl/${MYDOMAIN}.key.pem;
1255 #ssl_trusted_certificate ssl/${MYDOMAIN}.pem;
1256 ssl_dhparam ssl/dh.pem;
1257 #ssl_ecdh_curve secp384r1;
1258 ssl_session_cache shared:SSL:10m;
1259 ssl_session_timeout 10m;
1260 ssl_session_tickets off;
1261 ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
1262 ssl_prefer_server_ciphers on;
1263 ssl_buffer_size 1400;
1264
1265 #ssl_stapling on;
1266 #ssl_stapling_verify on;
1267 #resolver 8.8.8.8 8.8.4.4 208.67.222.222 208.67.220.220 valid=60s;
1268 #resolver_timeout 2s;
1269
1270 ssl_ciphers "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:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!3DES:!MD5:!PSK";
1271
1272 #add_header Strict-Transport-Security "max-age=63072000; includeSubdomains; preload";
1273 ##add_header Public-Key-Pins 'pin-sha256="PIN1"; pin-sha256="PIN2"; max-age=5184000; includeSubDomains';
1274 add_header Cache-Control "public";
1275 add_header X-Frame-Options SAMEORIGIN;
1276 add_header Alternate-Protocol 443:npn-http/2;
1277 add_header X-Content-Type-Options nosniff;
1278 add_header X-XSS-Protection "1; mode=block";
1279 add_header X-Permitted-Cross-Domain-Policies "master-only";
1280 add_header "X-UA-Compatible" "IE=Edge";
1281 add_header "Access-Control-Allow-Origin" "*";
1282 add_header Content-Security-Policy "script-src 'self' 'unsafe-inline' 'unsafe-eval' *.youtube.com maps.gstatic.com *.googleapis.com *.google-analytics.com cdnjs.cloudflare.com assets.zendesk.com connect.facebook.net; frame-src 'self' *.youtube.com assets.zendesk.com *.facebook.com s-static.ak.facebook.com tautt.zendesk.com; object-src 'self'";
1283
1284 auth_basic_user_file htpasswd/.htpasswd;
1285
1286 location ~ ^(.+\.php)(.*)\$ {
1287 fastcgi_split_path_info ^(.+\.php)(/.+)\$;
1288 try_files \$fastcgi_script_name =404;
1289 set \$path_info \$fastcgi_path_info;
1290 fastcgi_param PATH_INFO \$path_info;
1291 fastcgi_param APP_ENV production;
1292 fastcgi_pass unix:/var/run/php5-fpm.sock;
1293 fastcgi_index index.php;
1294 include fastcgi.conf;
1295 fastcgi_intercept_errors on;
1296 fastcgi_ignore_client_abort off;
1297 fastcgi_buffers 256 16k;
1298 fastcgi_buffer_size 128k;
1299 fastcgi_connect_timeout 3s;
1300 fastcgi_send_timeout 120s;
1301 fastcgi_read_timeout 120s;
1302 fastcgi_busy_buffers_size 256k;
1303 fastcgi_temp_file_write_size 256k;
1304 }
1305
1306 rewrite (?i)^/autodiscover/autodiscover\.xml\$ /autodiscover/autodiscover.php;
1307
1308 location / {
1309 try_files \$uri \$uri/ /index.php;
1310 }
1311
1312 location /Microsoft-Server-ActiveSync {
1313 rewrite ^(.*)\$ /index.php last;
1314 }
1315
1316 location ~ /(\.ht|Core|Specific) {
1317 deny all;
1318 return 404;
1319 }
1320
1321 location = /favicon.ico {
1322 access_log off;
1323 log_not_found off;
1324 }
1325
1326 location = /robots.txt {
1327 allow all;
1328 access_log off;
1329 log_not_found off;
1330 }
1331
1332 location ~* ^.+\.(css|js)\$ {
1333 rewrite ^(.+)\.(\d+)\.(css|js)\$ \$1.\$3 last;
1334 expires 30d;
1335 access_log off;
1336 log_not_found off;
1337 add_header Pragma public;
1338 add_header Cache-Control "max-age=2592000, public";
1339 }
1340
1341 location ~* \.(asf|asx|wax|wmv|wmx|avi|bmp|class|divx|doc|docx|eot|exe|gif|gz|gzip|ico|jpg|jpeg|jpe|mdb|mid|midi|mov|qt|mp3|m4a|mp4|m4v|mpeg|mpg|mpe|mpp|odb|odc|odf|odg|odp|ods|odt|ogg|ogv|otf|pdf|png|pot|pps|ppt|pptx|ra|ram|svg|svgz|swf|tar|t?gz|tif|tiff|ttf|wav|webm|wma|woff|wri|xla|xls|xlsx|xlt|xlw|zip)\$ {
1342 expires 30d;
1343 access_log off;
1344 log_not_found off;
1345 add_header Pragma public;
1346 add_header Cache-Control "max-age=2592000, public";
1347 }
1348
1349 if (\$http_user_agent ~* "FeedDemon|JikeSpider|Indy Library|Alexa Toolbar|AskTbFXTV|AhrefsBot|CrawlDaddy|CoolpadWebkit|Java|Feedly|UniversalFeedParser|ApacheBench|Microsoft URL Control|Swiftbot|ZmEu|oBot|jaunty|Python-urllib|lightDeckReports Bot|YYSpider|DigExt|YisouSpider|HttpClient|MJ12bot|heritrix|EasouSpider|Ezooms|Scrapy") {
1350 return 403;
1351 }
1352
1353}
1354END
1355
1356 cat > /etc/nginx/sites-available/dav.${MYDOMAIN}.conf <<END
1357server {
1358 listen 80;
1359 server_name dav.${MYDOMAIN};
1360 return 301 https://dav.${MYDOMAIN}\$request_uri;
1361}
1362
1363server {
1364 listen 443 ssl http2;
1365 server_name dav.${MYDOMAIN};
1366
1367 root /var/www/dav;
1368 index server.php;
1369 charset utf-8;
1370
1371 error_page 404 /index.php;
1372
1373 ssl_certificate ssl/${MYDOMAIN}.pem;
1374 ssl_certificate_key ssl/${MYDOMAIN}.key.pem;
1375 #ssl_trusted_certificate ssl/${MYDOMAIN}.pem;
1376 ssl_dhparam ssl/dh.pem;
1377 #ssl_ecdh_curve secp384r1;
1378 ssl_session_cache shared:SSL:10m;
1379 ssl_session_timeout 10m;
1380 ssl_session_tickets off;
1381 ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
1382 ssl_prefer_server_ciphers on;
1383 ssl_buffer_size 1400;
1384
1385 #ssl_stapling on;
1386 #ssl_stapling_verify on;
1387 #resolver 8.8.8.8 8.8.4.4 208.67.222.222 208.67.220.220 valid=60s;
1388 #resolver_timeout 2s;
1389
1390 ssl_ciphers "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:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!3DES:!MD5:!PSK";
1391
1392 #add_header Strict-Transport-Security "max-age=63072000; includeSubdomains; preload";
1393 ##add_header Public-Key-Pins 'pin-sha256="PIN1"; pin-sha256="PIN2"; max-age=5184000; includeSubDomains';
1394 add_header Cache-Control "public";
1395 add_header X-Frame-Options SAMEORIGIN;
1396 add_header Alternate-Protocol 443:npn-http/2;
1397 add_header X-Content-Type-Options nosniff;
1398 add_header X-XSS-Protection "1; mode=block";
1399 add_header X-Permitted-Cross-Domain-Policies "master-only";
1400 add_header "X-UA-Compatible" "IE=Edge";
1401 add_header "Access-Control-Allow-Origin" "*";
1402 add_header Content-Security-Policy "script-src 'self' 'unsafe-inline' 'unsafe-eval' *.youtube.com maps.gstatic.com *.googleapis.com *.google-analytics.com cdnjs.cloudflare.com assets.zendesk.com connect.facebook.net; frame-src 'self' *.youtube.com assets.zendesk.com *.facebook.com s-static.ak.facebook.com tautt.zendesk.com; object-src 'self'";
1403
1404 auth_basic_user_file htpasswd/.htpasswd;
1405
1406 location ~ ^(.+\.php)(.*)\$ {
1407 fastcgi_split_path_info ^(.+\.php)(/.+)\$;
1408 try_files \$fastcgi_script_name =404;
1409 set \$path_info \$fastcgi_path_info;
1410 fastcgi_param PATH_INFO \$path_info;
1411 fastcgi_param APP_ENV production;
1412 fastcgi_pass unix:/var/run/php5-fpm.sock;
1413 fastcgi_index index.php;
1414 include fastcgi.conf;
1415 fastcgi_intercept_errors on;
1416 fastcgi_ignore_client_abort off;
1417 fastcgi_buffers 256 16k;
1418 fastcgi_buffer_size 128k;
1419 fastcgi_connect_timeout 3s;
1420 fastcgi_send_timeout 120s;
1421 fastcgi_read_timeout 120s;
1422 fastcgi_busy_buffers_size 256k;
1423 fastcgi_temp_file_write_size 256k;
1424 }
1425
1426 rewrite ^/.well-known/caldav /server.php redirect;
1427 rewrite ^/.well-known/carddav /server.php redirect;
1428
1429 location / {
1430 try_files \$uri \$uri/ /server.php?\$args;
1431 }
1432
1433 location ~ /(\.ht|Core|Specific) {
1434 deny all;
1435 return 404;
1436 }
1437
1438 location = /favicon.ico {
1439 access_log off;
1440 log_not_found off;
1441 }
1442
1443 location = /robots.txt {
1444 allow all;
1445 access_log off;
1446 log_not_found off;
1447 }
1448
1449 location ~* ^.+\.(css|js)\$ {
1450 rewrite ^(.+)\.(\d+)\.(css|js)\$ \$1.\$3 last;
1451 expires 30d;
1452 access_log off;
1453 log_not_found off;
1454 add_header Pragma public;
1455 add_header Cache-Control "max-age=2592000, public";
1456 }
1457
1458 location ~* \.(asf|asx|wax|wmv|wmx|avi|bmp|class|divx|doc|docx|eot|exe|gif|gz|gzip|ico|jpg|jpeg|jpe|mdb|mid|midi|mov|qt|mp3|m4a|mp4|m4v|mpeg|mpg|mpe|mpp|odb|odc|odf|odg|odp|ods|odt|ogg|ogv|otf|pdf|png|pot|pps|ppt|pptx|ra|ram|svg|svgz|swf|tar|t?gz|tif|tiff|ttf|wav|webm|wma|woff|wri|xla|xls|xlsx|xlt|xlw|zip)\$ {
1459 expires 30d;
1460 access_log off;
1461 log_not_found off;
1462 add_header Pragma public;
1463 add_header Cache-Control "max-age=2592000, public";
1464 }
1465
1466 if (\$http_user_agent ~* "FeedDemon|JikeSpider|Indy Library|Alexa Toolbar|AskTbFXTV|AhrefsBot|CrawlDaddy|CoolpadWebkit|Java|Feedly|UniversalFeedParser|ApacheBench|Microsoft URL Control|Swiftbot|ZmEu|oBot|jaunty|Python-urllib|lightDeckReports Bot|YYSpider|DigExt|YisouSpider|HttpClient|MJ12bot|heritrix|EasouSpider|Ezooms|Scrapy") {
1467 return 403;
1468 }
1469}
1470END
1471
1472 if [ ${CLOUDFLARE} == '0' ] && [ ${USE_VALID_SSL} == '1' ]; then
1473 sed -i 's/#ssl/ssl/g' /etc/nginx/sites-available/autodiscover.${MYDOMAIN}.conf /etc/nginx/sites-available/dav.${MYDOMAIN}.conf
1474 sed -i 's/#resolver/resolver/g' /etc/nginx/sites-available/autodiscover.${MYDOMAIN}.conf /etc/nginx/sites-available/dav.${MYDOMAIN}.conf
1475 sed -i 's/#add/add/g' /etc/nginx/sites-available/autodiscover.${MYDOMAIN}.conf /etc/nginx/sites-available/dav.${MYDOMAIN}.conf
1476 fi
1477
1478 ln -s /etc/nginx/sites-available/mailgraph.conf /etc/nginx/sites-enabled/mailgraph.conf
1479 ln -s /etc/nginx/sites-available/autodiscover.${MYDOMAIN}.conf /etc/nginx/sites-enabled/autodiscover.${MYDOMAIN}.conf
1480 ln -s /etc/nginx/sites-available/dav.${MYDOMAIN}.conf /etc/nginx/sites-enabled/dav.${MYDOMAIN}.conf
1481
1482 # RoundCube
1483 echo "${info} Installing RoundCube..." | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
1484 if [ ${USE_WEBMAIL} == '1' ]; then
1485 mkdir -p /var/www/mail/rc
1486 tar xf ~/sources/mailcow/roundcube/inst/1.1.3.tar -C ~/sources/mailcow/roundcube/inst/
1487 cp -R ~/sources/mailcow/roundcube/inst/1.1.3/* /var/www/mail/rc/
1488 cp -R ~/sources/mailcow/roundcube/conf/* /var/www/mail/rc/
1489 sed -i "s/my_mailcowuser/${MYSQL_MCDB_USER}/g" /var/www/mail/rc/plugins/password/config.inc.php
1490 sed -i "s/my_mailcowpass/${MYSQL_MCDB_PASS}/g" /var/www/mail/rc/plugins/password/config.inc.php
1491 sed -i "s/my_mailcowdb/${MYSQL_MCDB_NAME}/g" /var/www/mail/rc/plugins/password/config.inc.php
1492 sed -i "s/my_dbhost/${MYSQL_HOSTNAME}/g" /var/www/mail/rc/plugins/password/config.inc.php
1493 sed -i "s/my_dbhost/${MYSQL_HOSTNAME}/g" /var/www/mail/rc/config/config.inc.php
1494 sed -i "s/my_rcuser/${MYSQL_RCDB_USER}/g" /var/www/mail/rc/config/config.inc.php
1495 sed -i "s/my_rcpass/${MYSQL_RCDB_PASS}/g" /var/www/mail/rc/config/config.inc.php
1496 sed -i "s/my_rcdb/${MYSQL_RCDB_NAME}/g" /var/www/mail/rc/config/config.inc.php
1497 sed -i "s/conf_rcdeskey/$(generatepw)/g" /var/www/mail/rc/config/config.inc.php
1498 sed -i "s/MAILCOW_HOST.MAILCOW_DOMAIN/mail.${MYDOMAIN}/g" /var/www/mail/rc/config/config.inc.php
1499 mysql -u${MYSQL_RCDB_USER} -p${MYSQL_RCDB_PASS} -h${MYSQL_HOSTNAME} ${MYSQL_RCDB_NAME} < /var/www/mail/rc/SQL/mysql.initial.sql
1500 chown -R www-data: /var/www/mail/rc
1501 rm -rf ~/sources/mailcow/roundcube/inst/1.1.3
1502 rm -rf /var/www/mail/rc/installer/
1503
1504 # Create Nginx Config
1505 cat > /etc/nginx/sites-custom/roundcube.conf <<END
1506location /mail {
1507 alias /var/www/mail/rc;
1508 index index.php;
1509
1510 location ~ ^/mail/(.+\.php)$ {
1511 alias /var/www/mail/rc/\$1;
1512 fastcgi_split_path_info ^(.+\.php)(/.+)$;
1513 include fastcgi_params;
1514 fastcgi_index index.php;
1515 fastcgi_param SCRIPT_FILENAME /var/www/mail/rc/\$1;
1516 fastcgi_pass unix:/var/run/php5-fpm-mail.sock;
1517 }
1518
1519 location ~* ^/mail/(.+\.(jpg|jpeg|gif|css|png|js|ico|html|xml|txt))$ {
1520 alias /var/www/mail/rc/\$1;
1521 }
1522}
1523
1524location ~ ^/(mail/temp|mail/SQL|mail/config|mail/logs)/ {
1525 deny all;
1526 return 301 /mail;
1527}
1528END
1529 fi
1530
1531 # Rsyslogd
1532 if [[ -d /etc/rsyslog.d ]]; then
1533 rm /etc/rsyslog.d/10-fufix >/dev/null 2>&1
1534 cp ~/sources/mailcow/rsyslog/conf/10-mailcow /etc/rsyslog.d/
1535 service rsyslog restart >/dev/null 2>&1
1536 postlog -p warn dummy >/dev/null 2>&1
1537 postlog -p info dummy >/dev/null 2>&1
1538 postlog -p err dummy >/dev/null 2>&1
1539 fi
1540fi
1541
1542# phpMyAdmin
1543if [ $USE_PMA == '1' ]; then
1544 echo "${info} Installing phpMyAdmin..." | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
1545 htpasswd -b /etc/nginx/htpasswd/.htpasswd ${PMA_HTTPAUTH_USER} ${PMA_HTTPAUTH_PASS} >/dev/null 2>&1
1546 cd /usr/local
1547 git clone -b STABLE https://github.com/phpmyadmin/phpmyadmin.git -q
1548 mkdir phpmyadmin/save
1549 mkdir phpmyadmin/upload
1550 chmod 0700 phpmyadmin/save
1551 chmod g-s phpmyadmin/save
1552 chmod 0700 phpmyadmin/upload
1553 chmod g-s phpmyadmin/upload
1554 mysql -u root -p${MYSQL_ROOT_PASS} mysql < phpmyadmin/sql/create_tables.sql >/dev/null 2>&1
1555 mysql -u root -p${MYSQL_ROOT_PASS} -e "GRANT USAGE ON mysql.* TO '${MYSQL_PMADB_USER}'@'${MYSQL_HOSTNAME}' IDENTIFIED BY '${MYSQL_PMADB_PASS}'; GRANT SELECT ( Host, User, Select_priv, Insert_priv, Update_priv, Delete_priv, Create_priv, Drop_priv, Reload_priv, Shutdown_priv, Process_priv, File_priv, Grant_priv, References_priv, Index_priv, Alter_priv, Show_db_priv, Super_priv, Create_tmp_table_priv, Lock_tables_priv, Execute_priv, Repl_slave_priv, Repl_client_priv ) ON mysql.user TO '${MYSQL_PMADB_USER}'@'${MYSQL_HOSTNAME}'; GRANT SELECT ON mysql.db TO '${MYSQL_PMADB_USER}'@'${MYSQL_HOSTNAME}'; GRANT SELECT (Host, Db, User, Table_name, Table_priv, Column_priv) ON mysql.tables_priv TO '${MYSQL_PMADB_USER}'@'${MYSQL_HOSTNAME}'; GRANT SELECT, INSERT, DELETE, UPDATE, ALTER ON ${MYSQL_PMADB_NAME}.* TO '${MYSQL_PMADB_USER}'@'${MYSQL_HOSTNAME}'; FLUSH PRIVILEGES;" >/dev/null 2>&1
1556 cat > phpmyadmin/config.inc.php <<END
1557<?php
1558\$cfg['blowfish_secret'] = '$PMA_BFSECURE_PASS';
1559\$i = 0;
1560\$i++;
1561\$cfg['UploadDir'] = 'upload';
1562\$cfg['SaveDir'] = 'save';
1563\$cfg['ForceSSL'] = true;
1564\$cfg['ExecTimeLimit'] = 300;
1565\$cfg['VersionCheck'] = false;
1566\$cfg['NavigationTreeEnableGrouping'] = false;
1567\$cfg['AllowArbitraryServer'] = true;
1568\$cfg['AllowThirdPartyFraming'] = true;
1569\$cfg['ShowServerInfo'] = false;
1570\$cfg['ShowDbStructureCreation'] = true;
1571\$cfg['ShowDbStructureLastUpdate'] = true;
1572\$cfg['ShowDbStructureLastCheck'] = true;
1573\$cfg['UserprefsDisallow'] = array(
1574 'ShowServerInfo',
1575 'ShowDbStructureCreation',
1576 'ShowDbStructureLastUpdate',
1577 'ShowDbStructureLastCheck',
1578 'Export/quick_export_onserver',
1579 'Export/quick_export_onserver_overwrite',
1580 'Export/onserver');
1581\$cfg['Import']['charset'] = 'utf-8';
1582\$cfg['Export']['quick_export_onserver'] = true;
1583\$cfg['Export']['quick_export_onserver_overwrite'] = true;
1584\$cfg['Export']['compression'] = 'gzip';
1585\$cfg['Export']['charset'] = 'utf-8';
1586\$cfg['Export']['onserver'] = true;
1587\$cfg['Export']['sql_drop_database'] = true;
1588\$cfg['DefaultLang'] = 'en';
1589\$cfg['ServerDefault'] = 1;
1590\$cfg['Servers'][\$i]['auth_type'] = 'cookie';
1591\$cfg['Servers'][\$i]['auth_http_realm'] = 'phpMyAdmin Login';
1592\$cfg['Servers'][\$i]['host'] = '${MYSQL_HOSTNAME}';
1593\$cfg['Servers'][\$i]['connect_type'] = 'tcp';
1594\$cfg['Servers'][\$i]['compress'] = false;
1595\$cfg['Servers'][\$i]['extension'] = 'mysqli';
1596\$cfg['Servers'][\$i]['AllowNoPassword'] = false;
1597\$cfg['Servers'][\$i]['controluser'] = '$MYSQL_PMADB_USER';
1598\$cfg['Servers'][\$i]['controlpass'] = '$MYSQL_PMADB_PASS';
1599\$cfg['Servers'][\$i]['pmadb'] = '$MYSQL_PMADB_NAME';
1600\$cfg['Servers'][\$i]['bookmarktable'] = 'pma__bookmark';
1601\$cfg['Servers'][\$i]['relation'] = 'pma__relation';
1602\$cfg['Servers'][\$i]['table_info'] = 'pma__table_info';
1603\$cfg['Servers'][\$i]['table_coords'] = 'pma__table_coords';
1604\$cfg['Servers'][\$i]['pdf_pages'] = 'pma__pdf_pages';
1605\$cfg['Servers'][\$i]['column_info'] = 'pma__column_info';
1606\$cfg['Servers'][\$i]['history'] = 'pma__history';
1607\$cfg['Servers'][\$i]['table_uiprefs'] = 'pma__table_uiprefs';
1608\$cfg['Servers'][\$i]['tracking'] = 'pma__tracking';
1609\$cfg['Servers'][\$i]['userconfig'] = 'pma__userconfig';
1610\$cfg['Servers'][\$i]['recent'] = 'pma__recent';
1611\$cfg['Servers'][\$i]['favorite'] = 'pma__favorite';
1612\$cfg['Servers'][\$i]['users'] = 'pma__users';
1613\$cfg['Servers'][\$i]['usergroups'] = 'pma__usergroups';
1614\$cfg['Servers'][\$i]['navigationhiding'] = 'pma__navigationhiding';
1615\$cfg['Servers'][\$i]['savedsearches'] = 'pma__savedsearches';
1616\$cfg['Servers'][\$i]['central_columns'] = 'pma__central_columns';
1617\$cfg['Servers'][\$i]['designer_settings'] = 'pma__designer_settings';
1618\$cfg['Servers'][\$i]['export_templates'] = 'pma__export_templates';
1619\$cfg['Servers'][\$i]['hide_db'] = 'information_schema';
1620?>
1621END
1622 if [ ${PMA_RESTRICT} == '1' ]; then
1623 sed -i "64s/.*/\$cfg['Servers'][\$i]['AllowDeny']['order'] = 'deny,allow';\n&/" /usr/local/phpmyadmin/config.inc.php
1624 sed -i "65s/.*/\$cfg['Servers'][\$i]['AllowDeny']['rules'] = array(\n&/" /usr/local/phpmyadmin/config.inc.php
1625 sed -i "66s/.*/ 'deny % from all',\n&/" /usr/local/phpmyadmin/config.inc.php
1626 sed -i "67s/.*/ 'allow % from localhost',\n&/" /usr/local/phpmyadmin/config.inc.php
1627 sed -i "68s/.*/ 'allow % from 127.0.0.1',\n&/" /usr/local/phpmyadmin/config.inc.php
1628 sed -i "69s/.*/ 'allow % from ::1',\n&/" /usr/local/phpmyadmin/config.inc.php
1629 sed -i "70s/.*/ 'allow root from localhost',\n&/" /usr/local/phpmyadmin/config.inc.php
1630 sed -i "71s/.*/ 'allow root from 127.0.0.1',\n&/" /usr/local/phpmyadmin/config.inc.php
1631 sed -i "72s/.*/ 'allow root from ::1',\n&/" /usr/local/phpmyadmin/config.inc.php
1632 sed -i "73s/.*/);\n&/" /usr/local/phpmyadmin/config.inc.php
1633 sed -i "74s/.*/?>/" /usr/local/phpmyadmin/config.inc.php
1634
1635 cat > /etc/nginx/sites-custom/phpmyadmin.conf <<END
1636location /pma {
1637 allow 127.0.0.1;
1638 deny all;
1639 auth_basic "Restricted";
1640 alias /usr/local/phpmyadmin;
1641 index index.php;
1642
1643 location ~ ^/pma/(.+\.php)$ {
1644 alias /usr/local/phpmyadmin/\$1;
1645 fastcgi_split_path_info ^(.+\.php)(/.+)$;
1646 include fastcgi_params;
1647 fastcgi_index index.php;
1648 fastcgi_param SCRIPT_FILENAME /usr/local/phpmyadmin/\$1;
1649 fastcgi_pass unix:/var/run/php5-fpm.sock;
1650 }
1651
1652 location ~* ^/pma/(.+\.(jpg|jpeg|gif|css|png|js|ico|html|xml|txt))$ {
1653 alias /usr/local/phpmyadmin/\$1;
1654 }
1655
1656 location ~ ^/pma/save/ {
1657 deny all;
1658 }
1659
1660 location ~ ^/pma/upload/ {
1661 deny all;
1662 }
1663}
1664END
1665
1666 else
1667 cat > /etc/nginx/sites-custom/phpmyadmin.conf <<END
1668location /pma {
1669 auth_basic "Restricted";
1670 alias /usr/local/phpmyadmin;
1671 index index.php;
1672
1673 location ~ ^/pma/(.+\.php)$ {
1674 alias /usr/local/phpmyadmin/\$1;
1675 fastcgi_split_path_info ^(.+\.php)(/.+)$;
1676 include fastcgi_params;
1677 fastcgi_index index.php;
1678 fastcgi_param SCRIPT_FILENAME /usr/local/phpmyadmin/\$1;
1679 fastcgi_pass unix:/var/run/php5-fpm.sock;
1680 }
1681
1682 location ~* ^/pma/(.+\.(jpg|jpeg|gif|css|png|js|ico|html|xml|txt))$ {
1683 alias /usr/local/phpmyadmin/\$1;
1684 }
1685
1686 location ~ ^/pma/save/ {
1687 deny all;
1688 }
1689
1690 location ~ ^/pma/upload/ {
1691 deny all;
1692 }
1693}
1694END
1695 fi
1696
1697 chown -R www-data:www-data phpmyadmin/
1698 systemctl -q reload nginx.service
1699
1700fi
1701
1702# FIREWALL & SYSTEM TUNING
1703#
1704# Arno-Iptables-Firewall
1705# Fail2Ban
1706# System Tuning
1707#
1708
1709#
1710# Arno-Iptable-Firewall
1711#
1712
1713# Get the latest version
1714echo "${info} Installing Arno-Iptables-Firewall..." | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
1715git clone https://github.com/arno-iptables-firewall/aif.git ~/sources/aif -q
1716
1717# Create folders and copy files
1718cd ~/sources/aif
1719echo "${info} Configuring Arno-Iptables-Firewall..." | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
1720mkdir -p /usr/local/share/arno-iptables-firewall/plugins
1721mkdir -p /usr/local/share/man/man1
1722mkdir -p /usr/local/share/man/man8
1723mkdir -p /usr/local/share/doc/arno-iptables-firewall
1724mkdir -p /etc/arno-iptables-firewall/plugins
1725mkdir -p /etc/arno-iptables-firewall/conf.d
1726cp bin/arno-iptables-firewall /usr/local/sbin/
1727cp bin/arno-fwfilter /usr/local/bin/
1728cp -R share/arno-iptables-firewall/* /usr/local/share/arno-iptables-firewall/
1729ln -s /usr/local/share/arno-iptables-firewall/plugins/traffic-accounting-show /usr/local/sbin/traffic-accounting-show
1730gzip -c share/man/man1/arno-fwfilter.1 >/usr/local/share/man/man1/arno-fwfilter.1.gz >/dev/null 2>&1
1731gzip -c share/man/man8/arno-iptables-firewall.8 >/usr/local/share/man/man8/arno-iptables-firewall.8.gz >/dev/null 2>&1
1732cp README /usr/local/share/doc/arno-iptables-firewall/
1733cp etc/init.d/arno-iptables-firewall /etc/init.d/
1734if [ -d "/usr/lib/systemd/system/" ]; then
1735 cp lib/systemd/system/arno-iptables-firewall.service /usr/lib/systemd/system/
1736fi
1737cp etc/arno-iptables-firewall/firewall.conf /etc/arno-iptables-firewall/
1738cp etc/arno-iptables-firewall/custom-rules /etc/arno-iptables-firewall/
1739cp -R etc/arno-iptables-firewall/plugins/ /etc/arno-iptables-firewall/
1740cp share/arno-iptables-firewall/environment /usr/local/share/
1741
1742chmod +x /usr/local/sbin/arno-iptables-firewall
1743chown 0:0 /etc/arno-iptables-firewall/firewall.conf
1744chown 0:0 /etc/arno-iptables-firewall/custom-rules
1745chmod +x /usr/local/share/environment
1746
1747# Start Arno-Iptables-Firewall at boot
1748update-rc.d -f arno-iptables-firewall start 11 S . stop 10 0 6 >/dev/null 2>&1
1749
1750# Configure firewall.conf
1751bash /usr/local/share/environment >/dev/null 2>&1
1752sed -i "s/^Port 22/Port ${SSH}/g" /etc/ssh/sshd_config
1753sed -i "s/^EXT_IF=.*/EXT_IF="${INTERFACE}"/g" /etc/arno-iptables-firewall/firewall.conf
1754sed -i 's/^EXT_IF_DHCP_IP=.*/EXT_IF_DHCP_IP="0"/g' /etc/arno-iptables-firewall/firewall.conf
1755sed -i 's/^#FIREWALL_LOG=.*/FIREWALL_LOG="\/var\/log\/firewall.log"/g' /etc/arno-iptables-firewall/firewall.conf
1756sed -i 's/^DRDOS_PROTECT=.*/DRDOS_PROTECT="1"/g' /etc/arno-iptables-firewall/firewall.conf
1757sed -i 's/^OPEN_ICMP=.*/OPEN_ICMP="1"/g' /etc/arno-iptables-firewall/firewall.conf
1758sed -i 's/^#BLOCK_HOSTS_FILE=.*/BLOCK_HOSTS_FILE="\/etc\/arno-iptables-firewall\/blocked-hosts"/g' /etc/arno-iptables-firewall/firewall.conf
1759if [ ${USE_MAILSERVER} == '1' ]; then
1760 sed -i "s/^OPEN_TCP=.*/OPEN_TCP=\"${SSH}, 25, 80, 110, 143, 443, 465, 587, 993, 995\"/" /etc/arno-iptables-firewall/firewall.conf
1761else
1762 sed -i "s/^OPEN_TCP=.*/OPEN_TCP=\"${SSH}, 80, 443\"/" /etc/arno-iptables-firewall/firewall.conf
1763fi
1764sed -i 's/^OPEN_UDP=.*/OPEN_UDP=""/' /etc/arno-iptables-firewall/firewall.conf
1765sed -i 's/^VERBOSE=.*/VERBOSE=1/' /etc/init.d/arno-iptables-firewall
1766
1767# Start the firewall
1768systemctl -q daemon-reload
1769systemctl -q start arno-iptables-firewall.service
1770
1771# Blacklist some bad guys
1772mkdir ~/sources/blacklist
1773sed -i 's/.*BLOCK_HOSTS_FILE=.*/BLOCK_HOSTS_FILE="\/etc\/arno-iptables-firewall\/blocked-hosts"/' /etc/arno-iptables-firewall/firewall.conf
1774cat > /etc/cron.daily/blocked-hosts <<END
1775#!/bin/bash
1776BLACKLIST_DIR="/root/sources/blacklist"
1777BLACKLIST="/etc/arno-iptables-firewall/blocked-hosts"
1778BLACKLIST_TEMP="\$BLACKLIST_DIR/blacklist"
1779
1780LIST=(
1781"http://www.projecthoneypot.org/list_of_ips.php?t=d&rss=1"
1782"http://check.torproject.org/cgi-bin/TorBulkExitList.py?ip=1.1.1.1"
1783"http://www.maxmind.com/en/anonymous_proxies"
1784"http://danger.rulez.sk/projects/bruteforceblocker/blist.php"
1785"http://rules.emergingthreats.net/blockrules/compromised-ips.txt"
1786"http://www.spamhaus.org/drop/drop.lasso"
1787"http://cinsscore.com/list/ci-badguys.txt"
1788"http://www.openbl.org/lists/base.txt"
1789"http://www.autoshun.org/files/shunlist.csv"
1790"http://lists.blocklist.de/lists/all.txt"
1791)
1792
1793for i in "\${LIST[@]}"
1794do
1795 wget -T 10 -t 2 -O - \$i | grep -Po '(?:\d{1,3}\.){3}\d{1,3}(?:/\d{1,2})?' >> \$BLACKLIST_TEMP
1796done
1797
1798sort \$BLACKLIST_TEMP -n | uniq > \$BLACKLIST
1799cp \$BLACKLIST_TEMP \${BLACKLIST_DIR}/blacklist\_\$(date '+%d.%m.%Y_%T' | tr -d :) && rm \$BLACKLIST_TEMP
1800systemctl force-reload arno-iptables-firewall.service
1801END
1802chmod +x /etc/cron.daily/blocked-hosts
1803
1804# Fail2Ban
1805tar xf ~/sources/mailcow/fail2ban/inst/0.9.3.tar -C ~/sources/mailcow/fail2ban/inst/
1806rm -rf /etc/fail2ban/ >/dev/null 2>&1
1807(cd ~/sources/mailcow/fail2ban/inst/0.9.3 ; python setup.py -q install >/dev/null 2>&1)
1808mkdir -p /var/run/fail2ban
1809cp ~/sources/mailcow/fail2ban/conf/fail2ban.service /etc/systemd/system/fail2ban.service
1810[[ -f /lib/systemd/system/fail2ban.service ]] && rm /lib/systemd/system/fail2ban.service
1811systemctl -q daemon-reload
1812systemctl -q enable fail2ban
1813if [[ ! -f /var/log/mail.warn ]]; then
1814 touch /var/log/mail.warn
1815fi
1816if [[ ! -f /etc/fail2ban/jail.local ]]; then
1817 cp ~/sources/mailcow/fail2ban/conf/jail.local /etc/fail2ban/jail.local
1818fi
1819cp ~/sources/mailcow/fail2ban/conf/jail.d/*.conf /etc/fail2ban/jail.d/
1820rm -rf ~/sources/mailcow/fail2ban/inst/0.9.3
1821[[ -z $(grep fail2ban /etc/rc.local) ]] && sed -i '/^exit 0/i\test -d /var/run/fail2ban || install -m 755 -d /var/run/fail2ban/' /etc/rc.local
1822mkdir /var/run/fail2ban/ >/dev/null 2>&1
1823
1824# System Tuning
1825echo "${info} Kernel hardening & system tuning..." | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
1826cat > /etc/sysctl.conf <<END
1827kernel.randomize_va_space=1
1828net.ipv4.conf.all.rp_filter=1
1829net.ipv4.conf.all.accept_source_route=0
1830net.ipv4.icmp_echo_ignore_broadcasts=1
1831net.ipv4.conf.all.log_martians = 1
1832net.ipv4.tcp_fin_timeout = 1
1833net.ipv4.tcp_tw_recycle = 1
1834kernel.shmmax = 1073741824
1835net.ipv4.tcp_rmem = 4096 25165824 25165824
1836net.core.rmem_max = 25165824
1837net.core.rmem_default = 25165824
1838net.ipv4.tcp_wmem = 4096 65536 25165824
1839net.core.wmem_max = 25165824
1840net.core.wmem_default = 65536
1841net.core.optmem_max = 25165824
1842net.ipv4.tcp_syncookies = 1
1843net.ipv4.tcp_max_orphans = 262144
1844net.ipv4.tcp_max_syn_backlog = 262144
1845net.ipv4.tcp_synack_retries = 2
1846net.ipv4.tcp_syn_retries = 2
1847net.core.default_qdisc=fq_codel
1848fs.inotify.max_user_instances=2048
1849
1850# Disable IPV6
1851net.ipv6.conf.all.disable_ipv6 = 1
1852net.ipv6.conf.default.disable_ipv6 = 1
1853net.ipv6.conf.lo.disable_ipv6 = 1
1854net.ipv6.conf.${INTERFACE}.disable_ipv6 = 1
1855END
1856
1857# Enable changes
1858sysctl -p >/dev/null 2>&1
1859
1860
1861# Public Key Authentication
1862echo "${info} Generating key for public key authentication..." | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
1863ssh-keygen -f ~/ssh.key -b 3072 -t rsa -N ${SSH_PASS} >/dev/null 2>&1
1864mkdir -p ~/.ssh && chmod 700 ~/.ssh
1865cat ~/ssh.key.pub > ~/.ssh/authorized_keys2 && rm ~/ssh.key.pub
1866chmod 600 ~/.ssh/authorized_keys2
1867mv ~/ssh.key ~/ssh_privatekey.txt
1868
1869sed -i 's/^#PasswordAuthentication yes/PasswordAuthentication no/g' /etc/ssh/sshd_config
1870sed -i 's/^UsePAM yes/UsePAM no/g' /etc/ssh/sshd_config
1871echo -e "" >> /etc/ssh/sshd_config
1872echo -e "# Disable password based logins" >> /etc/ssh/sshd_config
1873echo -e "AuthenticationMethods publickey" >> /etc/ssh/sshd_config
1874systemctl -q restart ssh.service
1875
1876truncate -s 0 /var/log/daemon.log
1877truncate -s 0 /var/log/syslog
1878
1879# Restart all services
1880if [ ${USE_MAILSERVER} == '1' ]; then
1881 systemctl -q restart {fail2ban,rsyslog,nginx,php5-fpm,spamassassin,dovecot,postfix,opendkim,clamav-daemon,fuglu,mailgraph}
1882else
1883 systemctl -q restart {fail2ban,nginx,php5-fpm}
1884fi
1885
1886}
1887
1888logininformation() {
1889touch ~/credentials.txt
1890echo "///////////////////////////////////////////////////////////////////////////" >> ~/credentials.txt
1891echo "// Passwords, Usernames, Databases" >> ~/credentials.txt
1892echo "///////////////////////////////////////////////////////////////////////////" >> ~/credentials.txt
1893echo "" >> ~/credentials.txt
1894echo "_______________________________________________________________________________________" >> ~/credentials.txt
1895echo "### MYSQL & WEB" >> ~/credentials.txt
1896echo "" >> ~/credentials.txt
1897echo "--------------------------------------------" >> ~/credentials.txt
1898echo "MySQL root" >> ~/credentials.txt
1899echo "--------------------------------------------" >> ~/credentials.txt
1900echo "hostname = ${MYSQL_HOSTNAME}" >> ~/credentials.txt
1901echo "username = root" >> ~/credentials.txt
1902echo "password = ${MYSQL_ROOT_PASS}" >> ~/credentials.txt
1903echo "" >> ~/credentials.txt
1904echo "" >> ~/credentials.txt
1905if [ ${USE_MAILSERVER} == '1' ]; then
1906 echo "--------------------------------------------" >> ~/credentials.txt
1907 echo "mailcow admin" >> ~/credentials.txt
1908 echo "--------------------------------------------" >> ~/credentials.txt
1909 echo "username = ${MAILCOW_ADMIN_USER}" >> ~/credentials.txt
1910 echo "password = ${MAILCOW_ADMIN_PASS}" >> ~/credentials.txt
1911 echo "" >> ~/credentials.txt
1912 echo "" >> ~/credentials.txt
1913 echo "--------------------------------------------" >> ~/credentials.txt
1914 echo "mailcow database" >> ~/credentials.txt
1915 echo "--------------------------------------------" >> ~/credentials.txt
1916 echo "database = ${MYSQL_MCDB_NAME}" >> ~/credentials.txt
1917 echo "username = ${MYSQL_MCDB_USER}" >> ~/credentials.txt
1918 echo "password = ${MYSQL_MCDB_PASS}" >> ~/credentials.txt
1919 echo "" >> ~/credentials.txt
1920 echo "" >> ~/credentials.txt
1921 if [ ${USE_WEBMAIL} == '1' ]; then
1922 echo "--------------------------------------------" >> ~/credentials.txt
1923 echo "roundcube database" >> ~/credentials.txt
1924 echo "--------------------------------------------" >> ~/credentials.txt
1925 echo "database = ${MYSQL_RCDB_NAME}" >> ~/credentials.txt
1926 echo "username = ${MYSQL_RCDB_USER}" >> ~/credentials.txt
1927 echo "password = ${MYSQL_RCDB_PASS}" >> ~/credentials.txt
1928 echo "" >> ~/credentials.txt
1929 echo "" >> ~/credentials.txt
1930 fi
1931fi
1932if [ ${USE_PMA} == '1' ]; then
1933 echo "--------------------------------------------" >> ~/credentials.txt
1934 echo "phpMyAdmin database" >> ~/credentials.txt
1935 echo "--------------------------------------------" >> ~/credentials.txt
1936 echo "database = ${MYSQL_PMADB_NAME}" >> ~/credentials.txt
1937 echo "username = ${MYSQL_PMADB_USER}" >> ~/credentials.txt
1938 echo "password = ${MYSQL_PMADB_PASS}" >> ~/credentials.txt
1939 echo "" >> ~/credentials.txt
1940 echo "" >> ~/credentials.txt
1941 echo "--------------------------------------------" >> ~/credentials.txt
1942 echo "phpMyAdmin web" >> ~/credentials.txt
1943 echo "--------------------------------------------" >> ~/credentials.txt
1944 echo "username = ${PMA_HTTPAUTH_USER}" >> ~/credentials.txt
1945 echo "password = ${PMA_HTTPAUTH_PASS}" >> ~/credentials.txt
1946 echo "" >> ~/credentials.txt
1947 echo "blowfish = ${PMA_BFSECURE_PASS}" >> ~/credentials.txt
1948 echo "" >> ~/credentials.txt
1949 echo "" >> ~/credentials.txt
1950fi
1951echo "_______________________________________________________________________________________" >> ~/credentials.txt
1952echo "## SSH" >> ~/credentials.txt
1953echo "" >> ~/credentials.txt
1954echo "port = ${SSH}" >> ~/credentials.txt
1955echo "password = ${SSH_PASS}" >> ~/credentials.txt
1956echo "privatekey = check /root/ssh_privatekey.txt" >> ~/credentials.txt
1957echo "" >> ~/credentials.txt
1958echo "_______________________________________________________________________________________" >> ~/credentials.txt
1959echo "## URLs" >> ~/credentials.txt
1960echo "" >> ~/credentials.txt
1961echo "--------------------------------------------" >> ~/credentials.txt
1962echo "your domain" >> ~/credentials.txt
1963echo "--------------------------------------------" >> ~/credentials.txt
1964echo "https://${MYDOMAIN}" >> ~/credentials.txt
1965echo "" >> ~/credentials.txt
1966echo "" >> ~/credentials.txt
1967if [ ${USE_MAILSERVER} == '1' ]; then
1968 echo "--------------------------------------------" >> ~/credentials.txt
1969 echo "mailcow (mailserver admin)" >> ~/credentials.txt
1970 echo "--------------------------------------------" >> ~/credentials.txt
1971 echo "https://${MYDOMAIN}/admin" >> ~/credentials.txt
1972 echo "" >> ~/credentials.txt
1973 echo "" >> ~/credentials.txt
1974 if [ ${USE_WEBMAIL} == '1' ]; then
1975 echo "--------------------------------------------" >> ~/credentials.txt
1976 echo "roundcube (webmail)" >> ~/credentials.txt
1977 echo "--------------------------------------------" >> ~/credentials.txt
1978 echo "https://${MYDOMAIN}/mail" >> ~/credentials.txt
1979 echo "" >> ~/credentials.txt
1980 echo "" >> ~/credentials.txt
1981 fi
1982 echo "--------------------------------------------" >> ~/credentials.txt
1983 echo "caldav" >> ~/credentials.txt
1984 echo "--------------------------------------------" >> ~/credentials.txt
1985 echo "https://dav.${MYDOMAIN}" >> ~/credentials.txt
1986 echo "" >> ~/credentials.txt
1987 echo "" >> ~/credentials.txt
1988 echo "--------------------------------------------" >> ~/credentials.txt
1989 echo "autoconfigure" >> ~/credentials.txt
1990 echo "--------------------------------------------" >> ~/credentials.txt
1991 echo "https://autodiscover.${MYDOMAIN}" >> ~/credentials.txt
1992 echo "" >> ~/credentials.txt
1993 echo "" >> ~/credentials.txt
1994fi
1995if [ ${USE_PMA} == '1' ]; then
1996 echo "--------------------------------------------" >> ~/credentials.txt
1997 echo "phpMyAdmin" >> ~/credentials.txt
1998 echo "--------------------------------------------" >> ~/credentials.txt
1999 echo "https://${MYDOMAIN}/pma" >> ~/credentials.txt
2000 echo "" >> ~/credentials.txt
2001 echo "" >> ~/credentials.txt
2002fi
2003echo "_______________________________________________________________________________________" >> ~/credentials.txt
2004echo "## SYSTEM INFORMATION" >> ~/credentials.txt
2005echo "" >> ~/credentials.txt
2006echo "--------------------------------------------" >> ~/credentials.txt
2007echo "open ports" >> ~/credentials.txt
2008echo "--------------------------------------------" >> ~/credentials.txt
2009if [ ${USE_MAILSERVER} == '1' ]; then
2010 echo "TCP = 25 (SMTP), 80 (HTTP), 110 (POP3), 143(IMAP), 443 (HTTPS), 465 (SMPTS)" >> ~/credentials.txt
2011 echo "TCP = 587 (Submission), 993 (IMAPS), 995 (POP3S), ${SSH} (SSH)" >> ~/credentials.txt
2012 echo "UDP = All ports are closed" >> ~/credentials.txt
2013 echo "" >> ~/credentials.txt
2014 echo "" >> ~/credentials.txt
2015else
2016 echo "TCP = 80 (HTTP), 443 (HTTPS), ${SSH} (SSH)" >> ~/credentials.txt
2017 echo "UDP = All ports are closed" >> ~/credentials.txt
2018 echo "" >> ~/credentials.txt
2019 echo "" >> ~/credentials.txt
2020fi
2021echo "You can add additional ports, just edit \"/etc/arno-iptables-firewall/firewall.conf\" (lines 1164 & 1165)" >> ~/credentials.txt
2022echo "and restart your firewall -> \"systemctl force-reload arno-iptables-firewall\"" >> ~/credentials.txt
2023echo "" >> ~/credentials.txt
2024echo "" >> ~/credentials.txt
2025echo "_______________________________________________________________________________________" >> ~/credentials.txt
2026echo "${ok} Done! The credentials are located in the file $(textb /root/credentials.txt)!" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
2027}
2028
2029instructions() {
2030 SSH_PASSWD=$(sed -n '/^## SSH$/{n;n;n;p}' ~/credentials.txt | awk '{print $3}')
2031 echo
2032 echo "${info} Your server is ready to go! Do you want to start the configuration assistant?" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
2033 echo "${info} Press $(textb ENTER) to proceed or $(textb CTRL-C) to cancel the process" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
2034 read -s -n 1 i
2035 echo
2036 echo "${warn} You have to set up your SSH client, otherwise you will not be able to connect to your system!" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
2037 echo "${info} Press $(textb ENTER) to show your SSH private key" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
2038 echo
2039 echo "$(textb \###########################################################)" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
2040 echo "$(textb \#) This is your private key. Copy the entire key $(textb \#)" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
2041 echo "$(textb \#) including the -----BEGIN and -----END line and $(textb \#)" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
2042 echo "$(textb \#) save it on your Desktop. The file name does not matter! $(textb \#)" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
2043 echo "$(textb \###########################################################)" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
2044 yellow "Import the file by using Putty key generator and save your" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
2045 yellow "private key as *.ppk file. Now you can use the key to" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
2046 yellow "authenticate with your server using Putty." | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
2047 echo
2048 echo "Password for your ssh key = ${SSH_PASSWD}" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
2049 echo
2050 echo
2051 cat ~/ssh_privatekey.txt
2052 echo
2053 echo
2054 echo "${info} Press $(textb ENTER) to continue" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
2055 read -s -n 1 i
2056 echo
2057 if [ ${USE_MAILSERVER} == '1' ]; then
2058 MCAU=$(sed -n '/^mailcow admin$/{n;n;p}' ~/credentials.txt | awk '{print $3}')
2059 MCAP=$(sed -n '/^mailcow admin$/{n;n;n;p}' ~/credentials.txt | awk '{print $3}')
2060 echo "${info} Before the mailserver can be used, the following requirements must be met:" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
2061 echo
2062 echo "The subomains mail.${MYDOMAIN}, dav.${MYDOMAIN}, autodiscover.${MYDOMAIN} and autoconfig.${MYDOMAIN}" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
2063 echo "must have an \"A\" record that resolves to your IP adress: ${IPADR}" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
2064 while true; do
2065 echo
2066 echo
2067 if [ ${CLOUDFLARE} == '0' ]; then
2068 if [[ $FQDNIP != $IPADR ]]; then
2069 echo "${error} ${MYDOMAIN} does not resolve to the IP address of your server (${IPADR})" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
2070 else
2071 echo "${ok} ${MYDOMAIN} resolve to the IP adress of your server (${IPADR})" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
2072 fi
2073 fi
2074 sleep 1
2075 if [[ $MAILIP != $IPADR ]]; then
2076 echo "${warn} mail.${MYDOMAIN} does not resolve to the IP address of your server (${IPADR})" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
2077 else
2078 echo "${ok} mail.${MYDOMAIN} resolve to the IP adress of your server (${IPADR})" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
2079 fi
2080 sleep 1
2081 if [[ $ADIP != $IPADR ]]; then
2082 echo "${warn} autodiscover.${MYDOMAIN} does not resolve to the IP address of your server (${IPADR})" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
2083 else
2084 echo "${ok} autodiscover.${MYDOMAIN} resolve to the IP adress of your server (${IPADR})" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
2085 fi
2086 sleep 1
2087 if [[ $ACIP != $IPADR ]]; then
2088 echo "${warn} autoconfig.${MYDOMAIN} does not resolve to the IP address of your server (${IPADR})" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
2089 else
2090 echo "${ok} autoconfig.${MYDOMAIN} resolve to the IP adress of your server (${IPADR})" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
2091 fi
2092 sleep 1
2093 if [[ $DAVIP != $IPADR ]]; then
2094 echo "${warn} dav.${MYDOMAIN} does not resolve to the IP address of your server (${IPADR})" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
2095 else
2096 echo "${ok} dav.${MYDOMAIN} resolve to the IP adress of your server (${IPADR})" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
2097 fi
2098 sleep 1
2099 if [[ $CHECKRDNS != mail.${MYDOMAIN}. ]]; then
2100 echo "${warn} Your reverse DNS does not match the SMTP Banner. Please set your Reverse DNS to $(textb mail.${MYDOMAIN})" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
2101 else
2102 echo "${ok} Your reverse DNS is a valid Hostname ($(textb ${CHECKRDNS}))" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
2103 fi
2104 echo
2105 echo "${info} Repeat this check? Press $(textb ENTER) for yes or $(textb [N]) to skip" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
2106 read -s -n 1 i
2107 if [[ $i == "" ]]; then
2108 echo >> /dev/null
2109 else
2110 if [[ $i == "n" ]] || [[ $i == "N" ]]; then
2111 break
2112 fi
2113 fi
2114 done
2115
2116 echo
2117 echo
2118 echo "${info} Verify that the following MX record is set:" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
2119 echo "" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
2120 echo "NAME TYPE VALUE" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
2121 echo "-----------------------------------------" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
2122 echo "${MYDOMAIN} MX 10:mail.${MYDOMAIN}" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
2123 while true; do
2124 if [[ -z $CHECKMX ]]; then
2125 echo
2126 echo
2127 echo "${warn} MX record for ${MYDOMAIN} was not found!" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
2128 else
2129 echo
2130 echo
2131 echo "${ok} MX record for ${MYDOMAIN} was found!" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
2132 fi
2133 echo
2134 echo "${info} Repeat this check? Press $(textb ENTER) for yes or $(textb [N]) to skip" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
2135 read -s -n 1 i
2136 if [[ $i == "" ]]; then
2137 echo >> /dev/null
2138 else
2139 if [[ $i == "n" ]] || [[ $i == "N" ]]; then
2140 break
2141 fi
2142 fi
2143 done
2144 echo
2145 echo
2146 echo "${info} In the next step you have to set three DNS TXT records for your domain." | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
2147 echo
2148 yellow "The first record sould look like this:" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
2149 echo
2150 echo "NAME TYPE VALUE" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
2151 echo "----------------------------------------------------------" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
2152 echo " @ TXT \"mailconf=https://autoconfig.${MYDOMAIN}/mail/config-v1.1.xml\"" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
2153 echo
2154 echo
2155 yellow "The second record should look like this:" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
2156 echo
2157 echo "NAME TYPE VALUE" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
2158 echo "-----------------------------------------" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
2159 if [ $CLOUDFLARE == '1' ]; then
2160 echo " @ TXT \"v=spf1 ip4:${IPADR} -all\"" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
2161 else
2162 echo " @ TXT \"v=spf1 mx -all\"" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
2163 fi
2164 echo
2165 echo
2166 yellow "The third record sould look like this:" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
2167 echo
2168 echo " NAME TYPE VALUE" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
2169 echo "----------------------------------------------------------" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
2170 echo " mail._domainkey TXT \"v=DKIM1; k=rsa; t=s; s=email; p=DKIMPUBLICKEY\"" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
2171 echo
2172 echo "Visit https://${MYDOMAIN}/admin and login with username = ${MCAU} and password = ${MCAP}" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
2173 echo "Generate your DKIMPUBLICKEY (mailcow admin -> DKMIM signing)" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
2174 echo "Domain: ${MYDOMAIN}" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
2175 echo "Selector: mail" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
2176 while true; do
2177 echo
2178 echo
2179 if [[ -z $CHECKAC ]]; then
2180 echo "${warn} TXT record for autoconfig was not found!" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
2181 else
2182 echo "${ok} TXT record for autoconfig was found!" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
2183 fi
2184 sleep 1
2185 if [[ -z $CHECKSPF ]]; then
2186 echo "${warn} TXT record for SPF was not found!" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
2187 else
2188 echo "${ok} TXT record for SPF was found!" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
2189 fi
2190 sleep 1
2191 if [[ -z $CHECKDKIM ]]; then
2192 echo "${warn} TXT record for DKIM was not found!" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
2193 else
2194 echo "${ok} TXT record for DKIM was found!" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
2195 fi
2196 echo
2197 echo "${info} Repeat this check? Press $(textb ENTER) for yes or $(textb [N]) to skip" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
2198 read -s -n 1 i
2199 if [[ $i == "" ]]; then
2200 echo >> /dev/null
2201 else
2202 if [[ $i == "n" ]] || [[ $i == "N" ]]; then
2203 break
2204 fi
2205 fi
2206 done
2207 echo
2208 echo
2209 echo "${info} Your server supports ActiveSync. To make it work you have to enable autodiscovery." | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
2210 echo "${info} It is the ability for Outlook (and ofc other software) to automatically configure itself." | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
2211 echo "${info} You had to set specific DNS _SRV records to bring it up:" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
2212 echo
2213 echo " NAME TYPE VALUE" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
2214 echo "----------------------------------------------------------" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
2215 echo " _autodiscover._tcp SRV \"SRV 0 0 443 autodiscover.${MYDOMAIN}.\"" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
2216 echo
2217 echo
2218 echo " NAME TYPE VALUE" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
2219 echo "----------------------------------------------------------" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
2220 echo " _carddavs._tcp SRV \"SRV 0 0 443 dav.${MYDOMAIN}.\"" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
2221 echo
2222 echo
2223 echo " NAME TYPE VALUE" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
2224 echo "----------------------------------------------------------" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
2225 echo " _caldavs._tcp SRV \"SRV 0 0 443 dav.${MYDOMAIN}.\"" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
2226 echo
2227 echo
2228 echo " NAME TYPE VALUE" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
2229 echo "----------------------------------------------------------" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
2230 echo " _pop3._tcp SRV \"SRV 0 1 110 mail.${MYDOMAIN}.\"" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
2231 echo
2232 echo
2233 echo " NAME TYPE VALUE" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
2234 echo "----------------------------------------------------------" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
2235 echo " _imap._tcp SRV \"SRV 0 1 143 mail.${MYDOMAIN}.\"" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
2236 echo
2237 echo
2238 echo " NAME TYPE VALUE" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
2239 echo "----------------------------------------------------------" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
2240 echo " _submission._tcp SRV \"SRV 0 1 587 mail.${MYDOMAIN}.\"" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
2241 echo
2242 echo
2243 echo " NAME TYPE VALUE" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
2244 echo "----------------------------------------------------------" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
2245 echo " _imaps._tcp SRV \"SRV 0 1 993 mail.${MYDOMAIN}.\"" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
2246 echo
2247 echo
2248 echo " NAME TYPE VALUE" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
2249 echo "----------------------------------------------------------" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
2250 echo " _pop3s._tcp SRV \"SRV 0 1 995 mail.${MYDOMAIN}.\"" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
2251 echo
2252 echo "${info} Please read http://wki.pe/SRV_record for more information" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
2253 echo "${info} Press $(textb ENTER) to continue.." | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
2254 read -s -n 1 i
2255 while true; do
2256 echo
2257 echo
2258 for srv in _autodiscover _carddavs _caldavs _imap _imaps _submission _pop3 _pop3s
2259 do
2260 sleep 1.5
2261 if [[ -z $(dig srv ${srv}._tcp.${MYDOMAIN} @64.6.64.6 +short) ]]; then
2262 echo "${warn} SRV record not found: $(textb ${srv}._tcp.${MYDOMAIN})" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
2263 else
2264 echo "${ok} Valid SRV record found: $(textb ${srv}._tcp.${MYDOMAIN})" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
2265 fi
2266 done
2267 echo
2268 echo "${info} Repeat this check? Press $(textb ENTER) for yes or $(textb [N]) to skip" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
2269 read -s -n 1 i
2270 if [[ $i == "" ]]; then
2271 echo >> /dev/null
2272 else
2273 if [[ $i == "n" ]] || [[ $i == "N" ]]; then
2274 break
2275 fi
2276 fi
2277 done
2278 fi
2279 echo
2280 echo "${ok} You are done. You can run the assistant again, just write \"$(textb bash) $(textb ~/assistant.sh)\"" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
2281 echo "The credentials are located in the file $(textb ~/credentials.txt)!" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
2282}
2283
2284source ~/userconfig.cfg
2285
2286# Some nice colors
2287red() { echo "$(tput setaf 1)$*$(tput setaf 9)"; }
2288green() { echo "$(tput setaf 2)$*$(tput setaf 9)"; }
2289yellow() { echo "$(tput setaf 3)$*$(tput setaf 9)"; }
2290magenta() { echo "$(tput setaf 5)$*$(tput setaf 9)"; }
2291cyan() { echo "$(tput setaf 6)$*$(tput setaf 9)"; }
2292textb() { echo $(tput bold)${1}$(tput sgr0); }
2293greenb() { echo $(tput bold)$(tput setaf 2)${1}$(tput sgr0); }
2294redb() { echo $(tput bold)$(tput setaf 1)${1}$(tput sgr0); }
2295yellowb() { echo $(tput bold)$(tput setaf 3)${1}$(tput sgr0); }
2296pinkb() { echo $(tput bold)$(tput setaf 5)${1}$(tput sgr0); }
2297
2298# Some nice variables
2299info="$(textb [INFO] -)"
2300warn="$(yellowb [WARN] -)"
2301error="$(redb [ERROR] -)"
2302fyi="$(pinkb [INFO] -)"
2303ok="$(greenb [OKAY] -)"
2304
2305echo
2306echo
2307echo "$(date +"[%T]") | $(textb +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+)"
2308echo "$(date +"[%T]") | $(textb P) $(textb e) $(textb r) $(textb f) $(textb e) $(textb c) $(textb t) $(textb R) $(textb o) $(textb o) $(textb t) $(textb s) $(textb e) $(textb r) $(textb v) $(textb e) $(textb r) "
2309echo "$(date +"[%T]") | $(textb +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+)"
2310echo
2311echo "$(date +"[%T]") | ${info} Welcome to the Perfect Rootserver installation!"
2312echo "$(date +"[%T]") | ${info} Please wait while the installer is preparing for the first use..."
2313
2314if [ $(dpkg-query -l | grep dnsutils | wc -l) -ne 1 ]; then
2315 apt-get update -y >/dev/null 2>&1 && apt-get -y --force-yes install dnsutils >/dev/null 2>&1
2316fi
2317
2318if [ $(dpkg-query -l | grep openssl | wc -l) -ne 1 ]; then
2319 apt-get update -y >/dev/null 2>&1 && apt-get -y --force-yes install openssl >/dev/null 2>&1
2320fi
2321
2322IPADR=$(ip route get 64.6.64.6 | head -1 | cut -d' ' -f8)
2323INTERFACE=$(ip route get 64.6.64.6 | head -1 | cut -d' ' -f5)
2324FQDNIP=$(source ~/userconfig.cfg; dig @64.6.64.6 +short ${MYDOMAIN})
2325WWWIP=$(source ~/userconfig.cfg; dig @64.6.64.6 +short www.${MYDOMAIN})
2326ACIP=$(source ~/userconfig.cfg; dig @64.6.64.6 +short autoconfig.${MYDOMAIN})
2327ADIP=$(source ~/userconfig.cfg; dig @64.6.64.6 +short autodiscover.${MYDOMAIN})
2328DAVIP=$(source ~/userconfig.cfg; dig @64.6.64.6 +short dav.${MYDOMAIN})
2329MAILIP=$(source ~/userconfig.cfg; dig @64.6.64.6 +short mail.${MYDOMAIN})
2330CHECKAC=$(source ~/userconfig.cfg; dig @64.6.64.6 ${MYDOMAIN} txt | grep -i mailconf=)
2331CHECKMX=$(source ~/userconfig.cfg; dig @64.6.64.6 mx ${MYDOMAIN} +short)
2332CHECKSPF=$(source ~/userconfig.cfg; dig @64.6.64.6 ${MYDOMAIN} txt | grep -i spf)
2333CHECKDKIM=$(source ~/userconfig.cfg; dig @64.6.64.6 mail._domainkey.${MYDOMAIN} txt | grep -i DKIM1)
2334CHECKRDNS=$(dig @64.6.64.6 -x ${IPADR} +short)