# Copyright (C) 2019 Ian Kelling
# SPDX-License-Identifier: AGPL-3.0-or-later
+
+# todo: add a prometheus alert for dovecot.
+
+# todo: handle errors like this:
+# Mar 02 12:44:26 kw systemd[1]: exim4.service: Found left-over process 68210 (exim4) in control group while starting unit. Ignoring.
+# Mar 02 12:44:26 kw systemd[1]: This usually indicates unclean termination of a previous run, or service implementation deficiencies.
+
# todo: harden dovecot. need to do some research. one way is for it to only listen on a wireguard vpn interface, so only clients that are on the vpn can access it.
# todo: consider hardening cups listening on 0.0.0.0
# todo: stop/disable local apache, and rpc.mountd, and kdeconnect when not in use.
# todo: run mailping test after running, or otherwise
# clear out terminal alert
-# todo: reinstall bk with bigger filesystem
-
# todo: on bk, dont send email if mailvpn is not up
# todo: mailtest-check should check on bk too
[[ $EUID == 0 ]] || exec sudo -E "${BASH_SOURCE[0]}" "$@"
-
+# note, this is hardcoded in /etc/exim4/conf.d/main/000_local
u=$(id -nu 1000)
# background: dovecot does not yet have ocsp stapling support
# reference: https://community.letsencrypt.org/t/simple-guide-using-lets-encrypt-ssl-certs-with-dovecot/2921
#
-# for phone, k9mail, same thing but username alerts, pass in ivy-pass.
+# for phone, k9mail, fdroid, same thing but username alerts, pass in ivy-pass.
# also, bk.b8.nz for secondary alerts, username is iank. same alerts pass.
-# fetching mail settings: folder poll frequency 10 minutes
+# fetching mail settings: folder poll frequency 10 minutes.
+# account settings, fetching mail, push folders: All. Then disable the persistent notification.
#######
i() { # install file
local tmp tmpdir dest="$1"
local base="${dest##*/}"
- mkdir -p ${dest%/*}
+ local dir="${dest%/*}"
+ if [[ $dir != "$base" ]]; then
+ mkdir -p ${dest%/*}
+ fi
ir=false # i result
tmpdir=$(mktemp -d)
cat >$tmpdir/"$base"
fi
# light version of exim does not have sasl auth support.
-pi-nostart exim4 exim4-daemon-heavy spamassassin openvpn unbound clamav-daemon wireguard
+pi-nostart exim4 exim4-daemon-heavy spamassassin unbound clamav-daemon wireguard
# note: pyzor debian readme says you need to run some initialization command
# but its outdated.
pi spf-tools-perl p0f postgrey pyzor razor jq moreutils certbot fail2ban
+case $HOSTNAME in
+ je) : ;;
+ # not included due to using wireguard: openvpn
+ *) pi wget git unzip iptables ;;
+esac
# bad packages that sometimes get automatically installed
pu openresolv resolvconf
i /etc/systemd/system/wg-quick@wgmail.service.d/override.conf <<EOF
[Unit]
Requires=mailnn.service
-After=network.target mailnn.service
JoinsNamespaceOf=mailnn.service
BindsTo=mailnn.service
StartLimitIntervalSec=0
case $HOSTNAME in
$MAIL_HOST)
+ # todo, should this be after vpn service
i /etc/systemd/system/unbound.service.d/nn.conf <<EOF
[Unit]
After=mailnn.service
for unit in ${nn_progs[@]}; do
i /etc/systemd/system/$unit.service.d/nn.conf <<EOF
[Unit]
-# commented for old openvpn
-Requires=$vpnser
+
+# Wants appears better than requires because with requires,
+# if the vpnser fails to start, this service won't get run at
+# all, even if the vpnser starts on an automatic restart.
+
+Wants=$vpnser
After=network.target mailnn.service $vpnser
JoinsNamespaceOf=mailnn.service
BindsTo=mailnn.service
# NOTE: Pulled options changed on restart, will need to close and reopen TUN/TAP device.
m /a/exe/vpn-mk-client-cert -b mailclient -n mail li.iankelling.org
fi
-case $HOSTNAME in
- bk)
- if [[ ! -e /etc/openvpn/client/mail.conf ]]; then
- echo "$0: error: first, on a system with /p/c/filesystem, run mail-setup, or the vpn-mk-client-cert line above this err" 2>&2
- exit 1
- fi
- ;;
-esac
+
+# With openvpn, I didn't get around to persisting the openvpn
+# cert/configs into /p/c/machine_specific/bk, so I had this case to
+# manually get the cert. However, we aren't using openvpn anymore, so it
+# is commented out.
+#
+# case $HOSTNAME in
+# bk)
+# if [[ ! -e /etc/openvpn/client/mail.conf ]]; then
+# echo "$0: error: first, on a system with /p/c/filesystem, run mail-setup, or the vpn-mk-client-cert line above this err" 2>&2
+# exit 1
+# fi
+# ;;
+# esac
m rsync -aiSAX --chown=root:root --chmod=g-s /a/bin/ds/mail-cert-cron /usr/local/bin
${files[@]} /etc/exim4
fi
-# by default, only 10 days of logs are kept. increase that.
-m sed -ri 's/^(\s*rotate\s).*/\11000/' /etc/logrotate.d/exim4-base
-
+# By default, only 10 days of logs are kept. increase that.
+# And dont compress, I look back at logs too often and
+# dont need the annoyance of decompressing them all the time.
+m sed -ri '/^\s*compress\s*$/d;s/^(\s*rotate\s).*/\11000/' /etc/logrotate.d/exim4-base
+files=(/var/log/exim4/*.gz)
+if (( ${#files[@]} )); then
+ gunzip ${files[@]}
+fi
## disabled. not using .forward files, but this is still interesting
## for reference.
# b=userforward_higher_priority
# # replace the router name so it is unique
# sed -r s/^\\S+:/$b:/ 600_exim4-config_userforward >175_$b
+rm -fv /etc/exim4/conf.d/router/175_userforward_higher_priority
# todo, consider 'separate' in etc/exim4.conf, could it help on busy systems?
je.b8.nz * F,1d,10m;F,14d,1h
zroe.org * F,1d,10m;F,14d,1h
eximbackup.b8.nz * F,1d,4m;F,14d,1h
+
+# The spec says the target domain will be used for temporary host errors,
+# but i've found that isn't correct, the hostname is required
+# at least sometimes.
+nn.b8.nz * F,1d,4m;F,14d,1h
+defaultnn.b8.nz * F,1d,4m;F,14d,1h
+mx.iankelling.org * F,1d,4m;F,14d,1h
+bk.b8.nz * F,1d,4m;F,14d,1h
+eggs.gnu.org * F,1d,4m;F,14d,1h
+mail.fsf.org * F,1d,15m;F,14d,1h
EOF
rm -vf /etc/exim4/conf.d/main/000_localmacros # old filename
-cat >/etc/exim4/conf.d/main/000_local <<EOF
+
+# separate file so without quoted EOF for convenience
+cat >/etc/exim4/conf.d/main/000_local2 <<EOF
+# normally empty, I set this so I can set the envelope address
+# when doing mail redelivery to invoke filters. Also allows
+# me exiqgrep and stuff.
+MAIN_TRUSTED_GROUPS = $u
+EOF
+
+cat >/etc/exim4/conf.d/main/000_local <<'EOF'
MAIN_TLS_ENABLE = true
# require tls connections for all smarthosts
# Based on spec, seems like a good idea to be nice.
smtp_return_error_details = true
-# normally empty, I set this so I can set the envelope address
-# when doing mail redelivery to invoke filters. Also allows
-# me exiqgrep and stuff.
-MAIN_TRUSTED_GROUPS = $u
-
# default is 10. when exim has been down for a bit, fsf mailserver
# will do a big send in one connection, then exim decides to put
# the messages in the queue instead of delivering them, to avoid
# There could be some circumstance when the
# from: isnt our domain, but the envelope sender is
# and so still want to sign, but I cant think of any case.
-DKIM_DOMAIN = \${lc:\${domain:\$rh_from:}}
+DKIM_DOMAIN = ${lc:${domain:$rh_from:}}
# The file is based on the outgoing domain-name in the from-header.
# sign if key exists
-DKIM_PRIVATE_KEY = \${if exists{/etc/exim4/\${dkim_domain}-private.pem} {/etc/exim4/\${dkim_domain}-private.pem}}
+DKIM_PRIVATE_KEY = ${if exists{/etc/exim4/${dkim_domain}-private.pem} {/etc/exim4/${dkim_domain}-private.pem}}
# most of the ones that gmail seems to use.
# Exim has horrible default of signing unincluded
85.119.82.128 ; 2001:ba8:1f1:f09d::2 ; \\
# fsf_mit_net fsf_mit_net_ip6 fsf_net fsf_net_ip6 fsf_office_net
18.4.89.0/24 ; 2603:3005:71a:2e00::/64 ; 209.51.188.0/24 ; 2001:470:142::/48 ; 74.94.156.208/28
+
+
+# this is the default delay_warning_condition, plus matching on local_domains.
+# If I have some problem with my local system that causes delayed delivery,
+# I dont want to send warnings out to non-local domains.
+delay_warning_condition = ${if or {\
+ { !eq{$h_list-id:$h_list-post:$h_list-subscribe:}{} }\
+ { match{$h_precedence:}{(?i)bulk|list|junk} }\
+ { match{$h_auto-submitted:}{(?i)auto-generated|auto-replied} }\
+ { match_domain{$domain}{+local_domains} }\
+ } {no}{yes}}
+
+
EOF
rm -fv /etc/exim4/rcpt_local_acl # old path
EOF
-i /etc/exim4/conf.d/router/900_exim4-config_local_user <<EOF
+i /etc/exim4/conf.d/router/900_exim4-config_local_user <<'EOF'
### router/900_exim4-config_local_user
#################################
# This router matches local user mailboxes. If the router fails, the error
# message is "Unknown user".
local_user:
- debug_print = "R: local_user for \$local_part@\$domain"
+ debug_print = "R: local_user for $local_part@$domain"
driver = accept
domains = +local_domains
# ian: default file except where mentioned.
i /etc/systemd/system/radicale.service.d/override.conf <<EOF
[Unit]
-# this unit is configured to start and stop whenever
-# $vpnser does
After=network.target network-online.target mailnn.service $vpnser
-BindsTo=$vpnser
-Wants=network-online.target
+Wants=$vpnser
JoinsNamespaceOf=mailnn.service
StartLimitIntervalSec=0
# sieve has the benefit of being supported in postfix and
# proprietary/weird environments, so there is more examples on the
# internet.
- pi dovecot-core dovecot-imapd dovecot-sieve dovecot-lmtpd dovecot-sqlite sqlite3
+ pi-nostart dovecot-core dovecot-imapd dovecot-sieve dovecot-lmtpd dovecot-sqlite sqlite3
for f in /p/c{/machine_specific/$HOSTNAME,}/filesystem/etc/dovecot/users; do
if [[ -e $f ]]; then
-----END DH PARAMETERS-----
EOF
{
+
if [[ $HOSTNAME == "$MAIL_HOST" ]]; then
cat <<'EOF'
ssl_cert = </etc/exim4/fullchain.pem
ssl_key = </etc/exim4/privkey.pem
EOF
else
+ # We have a lets encrypt hooks that puts things here.
+ # This is just for bk, which uses the vpn cert in exim
+ # for sending mail, but the local hostname cert for
+ # dovecot.
cat <<'EOF'
ssl_cert = </etc/exim4/exim.crt
ssl_key = </etc/exim4/exim.key
EOF
fi
- cat <<EOF
+
+ cat <<'EOF'
# https://ssl-config.mozilla.org
ssl = required
# this is the same as the certbot list, in my cert cronjob, I check if that has changed upstream.
protocol lmtp {
#per https://wiki2.dovecot.org/Pigeonhole/Sieve/Configuration
-# default is just \$mail_plugins
- mail_plugins = \$mail_plugins sieve
+# default is just $mail_plugins
+ mail_plugins = $mail_plugins sieve
}
EOF
if dpkg --compare-versions $(dpkg-query -f='${Version}\n' --show dovecot-core) ge 1:2.3; then
i /etc/dovecot/dovecot-sql.conf.ext <<'EOF'
# from mailinabox
driver = sqlite
+# for je and bk, populated the testignore users for the relevant domains
connect = /m/rc/users.sqlite
default_pass_scheme = SHA512-CRYPT
password_query = SELECT email as user, password FROM users WHERE email='%u';
privileges TEXT NOT NULL DEFAULT '');
EOF
fi
+ # users.sqlite is saved into /p/c/machine_specific, so update it there!.
+ #
# example of adding a user:
# hash: doveadm pw -s SHA512-CRYPT -p passhere
# sqlite3 /m/rc/users.sqlite <<'EOF'
### end composer install
rcdirs=(/usr/local/lib/rcexpertpath /usr/local/lib/rcninja)
+ ncdirs=(/var/www/ncninja)
ncdirs=(/var/www/ncexpertpath /var/www/ncninja)
# point debian cronjob to our local install, preventing daily cron error
#### begin dl roundcube
# note, im r2e subbed to https://github.com/roundcube/roundcubemail/releases.atom
v=1.4.13; f=roundcubemail-$v-complete.tar.gz
- cd /a/opt
+ cd /root
if [[ -e $f ]]; then
timestamp=$(stat -c %Y $f)
else
fwrite(STDOUT, ";\n");
EOF
m php tmp.php >config.php
- m rm tmp.php
+ m rm -f tmp.php
m sudo -u www-data php $ncdir/occ maintenance:update:htaccess
list=$(sudo -u www-data php $ncdir/occ --output=json_pretty app:list)
# user_external not compaible with nc 23
EOF
fi
EOFOUTER
+ chmod +x /usr/local/bin/ncup
mkdir -p /var/www/cron-errors
chown www-data.www-data /var/www/cron-errors
i /etc/cron.d/$ncbase <<EOF
-PATH=/sbin:/usr/sbin:/usr/bin:/bin:/usr/local/bin
+PATH=/usr/sbin:/sbin:/usr/bin:/bin:/usr/local/bin
SHELL=/bin/bash
# https://docs.nextcloud.com/server/20/admin_manual/configuration_server/background_jobs_configuration.html
*/5 * * * * www-data php -f $ncdir/cron.php --define apc.enable_cli=1 |& log-once nccron
rm -fv /etc/systemd/system/exim4.service.d/nonroot.conf
;;
*)
- i /etc/systemd/system/exim4.service.d/nonroot.conf <<'EOF'
+ dirs=()
+ for d in /a /d /m /media /mnt /nocow /o /p /q; do
+ if [[ -d $d ]]; then
+ dirs+=($d)
+ fi
+ done
+ i /etc/systemd/system/exim4.service.d/nonroot.conf <<EOF
[Service]
# see 56.2 Root privilege in exim spec
AmbientCapabilities=CAP_NET_BIND_SERVICE
# note, in t10 systemd, if one of these is an sshfs mountpoint,
# this whole setting doesnt work. tried it with a newer systemd 250 though
# an nspawn, and it worked there.
-InaccessiblePaths=d m media mnt nocow o p q
+InaccessiblePaths=${dirs[@]}
NoNewPrivileges=yes
ProtectSystem=yes
# see 56.2 Root privilege in exim spec
deliver_drop_privilege = true
EOF
- # Note: there are other routers that would also fail due to not running as root,
- # but afaik, the main router will catch all mail. If not, we will see
- # something in the queue.
- rm -fv /etc/exim4/conf.d/router/600_exim4-config_userforward
+ files=(
+ 300_exim4-config_real_local
+ 600_exim4-config_userforward
+ 700_exim4-config_procmail
+ 800_exim4-config_maildrop
+ mmm_mail4root
+ )
+ for f in ${files[@]}; do
+ echo "# iank: removed due to running nonroot"|i /etc/exim4/conf.d/router/$f
+ done
;;
esac
echo|i /etc/exim4/conf.d/rcpt_local_acl
echo|i /etc/exim4/conf.d/router/880_universal_forward
- echo amnimal.ninja > /etc/mailname
-
/a/exe/cedit nn /etc/hosts <<'EOF' || [[ $? == 1 ]]
10.173.8.2 nn.b8.nz
EOF
UPEX4OPTS='-d /etc/myexim4'
EOF
+ echo bk.b8.nz > /etc/mailname
cat >>/etc/exim4/update-exim4.conf.conf <<EOF
# man page: is used to build the local_domains list, together with "localhost"
-dc_other_hostnames='amnimal.ninja;expertpathologyreview.com'
+dc_other_hostnames='amnimal.ninja;expertpathologyreview.com;bk.b8.nz'
EOF
;;
if $bhost_t; then
install -d /bu
- install -d -g $u -o $u -m 771 /bu/md
+ install -d -g Debian-exim -o Debian-exim -m 771 /bu/md
+ if [[ -e /bu/md/cur && $(stat -c %u /bu/md/cur) == 1000 ]]; then
+ chown -R Debian-exim:Debian-exim /bu/md
+ fi
i /etc/exim4/conf.d/transport/30_backup_maildir <<EOF
# modified debian maildir transport
backup_maildir:
directory_mode = 0700
mode = 0644
mode_fail_narrower = false
- user = $u
EOF
- i /etc/exim4/conf.d/router/870_backup_local <<EOF
+ i /etc/exim4/conf.d/router/870_backup_local <<'EOF'
### router/900_exim4-config_local_user
#################################
backup_local:
- debug_print = "R: local_user for \$local_part@\$domain"
+ debug_print = "R: local_user for $local_part@$domain"
driver = accept
domains = eximbackup.b8.nz
transport = backup_maildir
# without local-fs on exim, we get these kind of errors in paniclog on shutdown:
# Failed to create spool file /var/spool/exim4//input//1jCLxz-0008V4-V9-D: Permission denied
After=local-fs.target
+
+[Service]
+ExecStartPre=/usr/local/bin/exim-nn-iptables
EOF
if ! mountpoint -q $sdir; then
stopifactive exim4 exim4in
m usermod -u 608 Debian-exim
m groupmod -g 608 Debian-exim
m usermod -g 608 Debian-exim
- m find / /nocow -path ./var/tmp -prune -o -xdev -uid $uid -execdir chown -h 608 {} +
- m find / /nocow -path ./var/tmp -prune -o -xdev -gid $gid -execdir chgrp -h 608 {} +
+ m find / /nocow -xdev -path ./var/tmp -prune -o -uid $uid -execdir chown -h 608 {} +
+ m find / /nocow -xdev -path ./var/tmp -prune -o -gid $gid -execdir chgrp -h 608 {} +
fi
# * start / stop services
m systemctl daemon-reload
fi
-m systemctl --now enable epanicclean.timer
+sysd-prom-fail-install epanicclean
+m systemctl --now enable epanicclean
case $HOSTNAME in
je)
sre mailcert.timer
case $HOSTNAME in
- bk)
- # todo, this should be done in distro-begin
- soff systemd-resolved
- ln -sf 127.0.0.1-resolv/stub-resolv.conf /etc/resolv.conf
- ;;&
$MAIL_HOST|bk)
m systemctl --now enable mailnn mailnnroute
;;&
fi
if ! systemctl is-active clamav-daemon >/dev/null; then
m systemctl --now enable clamav-daemon
- out=$(rsync -aiSAX --chown=root:root --chmod=g-s /a/bin/ds/filesystem/etc/systemd/system/epanicclean.{timer,service} /etc/systemd/system)
+ out=$(rsync -aiSAX --chown=root:root --chmod=g-s /a/bin/ds/filesystem/etc/systemd/system/epanicclean.service /etc/systemd/system)
if [[ $out ]]; then
reload=true
fi
case $HOSTNAME in
- $MAIL_HOST|bk|je) : ;;
+ $MAIL_HOST|bk|je|li)
+ # on li, these are never started, except $vpnser
+ :
+ ;;
*)
soff radicale mailclean.timer dovecot spamassassin $vpnser mailnn clamav-daemon
;;
cat >/etc/cron.d/mailtest <<EOF
SHELL=/bin/bash
PATH=/usr/bin:/bin:/usr/local/bin
-MAILTO=alerts@iankelling.org
-*/5 * * * * $u send-test-forward |& log-once send-test-forward
+MAILTO=daylert@iankelling.org
+*/5 * * * * $u send-test-forward |& log-once send-test-forward
*/10 * * * * root chmod -R g+rw /m/md/bounces |& log-once -1 bounces-chmod
-# im seeing some intermittent failures on the slow check, do it all the time
-# for now. It looks like a dns failure.
-#5-59/5 * * * * root mailtest-check |& log-once -1 mailtest-check
-#0 * * * * root mailtest-check slow |& log-once -1 mailtest-slow
-*/5 * * * * root timeout 290 mailtest-check slow |& log-once -12 mailtest-check
+*/5 * * * * root timeout 290 mailtest-check slow |& log-once -4 mailtest-check
+# if a bounce happened yesterday, dont let it slip through the cracks
+8 1 * * * root export MAILTO=alerts@iankelling.org; [[ -s /var/log/exim4/mainlog.1 ]] && awk '\$5 == "**"' /var/log/exim4/mainlog.1
EOF
m sudo rsync -ahhi --chown=root:root --chmod=0755 \
/b/ds/mailtest-check /b/ds/check-remote-mailqs /usr/local/bin/
test_to="testignore@expertpathologyreview.com, testignore@je.b8.nz, testignore@amnimal.ninja, jtuttle@gnu.org"
cat >>/etc/cron.d/mailtest <<EOF
+0 13 * * * root echo "1pm alert. You are not in the matrix."
2 * * * * root check-remote-mailqs |& log-once check-remote-mailqs
EOF
;;&
cat >/usr/local/bin/send-test-forward <<'EOF'
#!/bin/bash
olds=(
-$(/sbin/exiqgrep -o 260 -i -r '^(testignore@(iankelling\.org|zroe\.org|expertpathologyreview\.com|amnimal\.ninja|je\.b8\.nz)|jtuttle@gnu\.org)$')
+$(/usr/sbin/exiqgrep -o 260 -i -r '^(testignore@(iankelling\.org|zroe\.org|expertpathologyreview\.com|amnimal\.ninja|je\.b8\.nz)|jtuttle@gnu\.org)$')
)
if (( ${#olds[@]} )); then
- /sbin/exim -Mrm "${olds[@]}" >/dev/null
+ /usr/sbin/exim -Mrm "${olds[@]}" >/dev/null
fi
EOF
for test_from in ${test_froms[@]}; do