mostly a bunch of fixes
[distro-setup] / mail-setup
index c40c56c0b6eab97923f57686a5c617eaed7040ca..65682c2971f513a64b29c207633ca4888397725c 100755 (executable)
@@ -3,6 +3,31 @@
 # Copyright (C) 2019 Ian Kelling
 # SPDX-License-Identifier: AGPL-3.0-or-later
 
+# Things I tend to forget. on MAIL_HOST, daemon runs with /etc/exim4/my.conf,
+# due to /etc/default/exim4 containing:
+# COMMONOPTIONS='-C /etc/exim4/my.conf'
+# UPEX4OPTS='-o /etc/exim4/my.conf'
+#
+# The non-daemon config
+# gets generated from this script calling update-exim4.conf -d /etc/myexim4
+# which has log path
+# log_file_path = /var/log/exim4/my%s
+#
+# eximbackup folder is /bu/md
+# it is cleaned up by mail-backup-clean, which is run by btrbk-run
+
+# shellcheck disable=SC2254 # makes for a lot of unneeded quotes
+
+
+# perusing through /el/mainlog without test messages:
+# &!testignore|jtuttle|
+#
+#&! testignore|jtuttle|eximbackup|/usr/sbin/exim4 -bpu
+
+# todo: check new macro DKIM_TIMESTAMPS
+
+# todo: check if REMOTE_SMTP_INTERFACE or REMOTE_SMTP_TRANSPORTS_HEADERS_REMOVE can simplify my or fsfs config
+
 # todo: max line length macro changed in t11. look into it
 # todo: check that all macros we use are still valid in t11
 
@@ -131,7 +156,8 @@ if [[ -s /usr/local/lib/err ]]; then
 elif [[ -s /a/bin/errhandle/err ]]; then
   source /a/bin/errhandle/err
 else
-  err "no err tracing script found"
+  echo "no err tracing script found"
+  exit 1
 fi
 source /a/bin/distro-functions/src/identify-distros
 source /a/bin/distro-functions/src/package-manager-abstractions
@@ -277,7 +303,7 @@ fi
 
 # * functions & constants
 
-pre="${0##*/}:"
+pre="${0##*/}:${SSH_CLIENT:+ $HOSTNAME:}"
 m() { printf "$pre %s\n"  "$*"; "$@"; }
 e() { printf "$pre %s\n"  "$*"; }
 err() { printf "$pre %s\n"  "$*" >&2; exit 1; }
@@ -287,7 +313,7 @@ reload=false
 if [[ -e /var/local/mail-setup-reload ]]; then
   reload=true
 fi
-i() { # install file
+u() { # update file. note: duplicated in brc
   local tmp tmpdir dest="$1"
   local base="${dest##*/}"
   local dir="${dest%/*}"
@@ -295,13 +321,13 @@ i() { # install file
     # dest has a directory component
     mkdir -p "$dir"
   fi
-  ir=false # i result
+  ur=false # u result
   tmpdir=$(mktemp -d)
   cat >$tmpdir/"$base"
   tmp=$(rsync -ic $tmpdir/"$base" "$dest")
   if [[ $tmp ]]; then
     printf "%s\n" "$tmp"
-    ir=true
+    ur=true
     if [[ $dest == /etc/systemd/system/* ]]; then
       touch /var/local/mail-setup-reload
       reload=true
@@ -323,9 +349,19 @@ soff () {
   done
 }
 sre() {
+  local enabled
   for service; do
     m systemctl restart $service
-    m systemctl enable $service;
+    # Optimization for exim,
+    # is-enabled: 0m0.015s
+    # enable: 0m0.748s
+    # It is related to this message:
+    # exim4.service is not a native service, redirecting to systemd-sysv-install.
+    # Executing: /lib/systemd/systemd-sysv-install enable exim4
+    enabled=$(systemctl is-enabled $service 2>/dev/null ||:)
+    if [[ $enabled != enabled ]]; then
+      m systemctl enable $service
+    fi
   done
 }
 mailhost() {
@@ -427,7 +463,7 @@ fi
 
 # * Mail clean cronjob
 
-i /etc/systemd/system/mailclean.timer <<'EOF'
+u /etc/systemd/system/mailclean.timer <<'EOF'
 [Unit]
 Description=Run mailclean daily
 
@@ -438,7 +474,7 @@ OnCalendar=monthly
 WantedBy=timers.target
 EOF
 
-i /etc/systemd/system/mailclean.service <<EOF
+u /etc/systemd/system/mailclean.service <<EOF
 [Unit]
 Description=Delete and archive old mail files
 After=multi-user.target
@@ -452,7 +488,7 @@ EOF
 # * postgrey
 
 
-i /etc/default/postgrey <<'EOF'
+u /etc/default/postgrey <<'EOF'
 POSTGREY_OPTS="--exim --unix=/var/run/postgrey/postgrey.sock --retry-window=4 --max-age=60"
 EOF
 
@@ -460,7 +496,7 @@ EOF
 
 m usermod -a -G Debian-exim clamav
 
-i /etc/systemd/system/clamav-daemon.service.d/fix.conf <<EOF
+u /etc/systemd/system/clamav-daemon.service.d/fix.conf <<EOF
 [Service]
 ExecStartPre=-/bin/mkdir -p /var/run/clamav
 ExecStartPre=/bin/chown clamav /var/run/clamav
@@ -500,7 +536,7 @@ EOF
 # Aug 02 21:59:27 sy systemd[1]: wg-quick@wgmail.service: Failed with result 'exit-code'.
 # Aug 02 21:59:27 sy systemd[1]: Failed to start WireGuard via wg-quick(8) for wgmail.
 # Aug 02 21:59:47 sy systemd[1]: wg-quick@wgmail.service: Scheduled restart job, restart counter is at 1.
-# Aug 02 21:59:47 sy systemd[1]: Stopped WireGuard via wg-quick(8) for wgmail.
+# Aug 02 21:95:47 sy systemd[1]: Stopped WireGuard via wg-quick(8) for wgmail.
 # Aug 02 21:59:47 sy systemd[1]: Starting WireGuard via wg-quick(8) for wgmail...
 # Aug 02 21:59:47 sy wg-quick[3424]: wg-quick: `wgmail' already exists
 # Aug 02 21:59:47 sy systemd[1]: wg-quick@wgmail.service: Main process exited, code=exited, status=1/FAILURE
@@ -533,7 +569,7 @@ esac
 case $HOSTNAME in
   li) : ;;
   *)
-    i /etc/systemd/system/wg-quick@wgmail.service.d/override.conf <<EOF
+    u /etc/systemd/system/wg-quick@wgmail.service.d/override.conf <<EOF
 [Unit]
 Requires=mailnn.service
 JoinsNamespaceOf=mailnn.service
@@ -553,7 +589,7 @@ esac
 
 
 # https://selivan.github.io/2017/12/30/systemd-serice-always-restart.html
-i /etc/systemd/system/mailvpn.service <<EOF
+u /etc/systemd/system/mailvpn.service <<EOF
 [Unit]
 Description=OpenVPN tunnel for mail
 After=syslog.target network-online.target mailnn.service
@@ -597,7 +633,7 @@ RestartSec=20
 WantedBy=multi-user.target
 EOF
 
-i /etc/systemd/system/mailnnroute.service <<'EOF'
+u /etc/systemd/system/mailnnroute.service <<'EOF'
 [Unit]
 Description=Network routing for mailnn
 After=syslog.target network-online.target mailnn.service
@@ -621,7 +657,7 @@ WantedBy=multi-user.target
 EOF
 
 #
-i /etc/systemd/system/mailnn.service <<'EOF'
+u /etc/systemd/system/mailnn.service <<'EOF'
 [Unit]
 Description=Network Namespace for mail vpn service that will live forever and cant fail
 After=syslog.target network-online.target
@@ -636,7 +672,7 @@ ExecStart=/bin/sleep infinity
 WantedBy=multi-user.target
 EOF
 
-i /etc/systemd/system/mailbindwatchdog.service <<EOF
+u /etc/systemd/system/mailbindwatchdog.service <<EOF
 [Unit]
 Description=Watchdog to restart services relying on systemd-resolved dir
 After=syslog.target network-online.target
@@ -670,18 +706,18 @@ rm -fv /etc/systemd/system/openvpn-client-mail@.service
 # If we ever notice this change, chattr +i on it
 # trust-ad is used in t10+, glibc 2.31
 
-i /etc/127.0.0.1-resolv/stub-resolv.conf <<'EOF'
+u /etc/127.0.0.1-resolv/stub-resolv.conf <<'EOF'
 nameserver 127.0.0.1
 options edns0 trust-ad
 EOF
 
-i /etc/127.0.0.53-resolv/stub-resolv.conf <<'EOF'
+u /etc/127.0.0.53-resolv/stub-resolv.conf <<'EOF'
 nameserver 127.0.0.53
 options edns0 trust-ad
 EOF
 
 
-i /etc/10.173.8.1-resolv/stub-resolv.conf <<'EOF'
+u /etc/10.173.8.1-resolv/stub-resolv.conf <<'EOF'
 nameserver 10.173.8.1
 options edns0 trust-ad
 EOF
@@ -712,7 +748,7 @@ fi
 case $HOSTNAME in
   $MAIL_HOST)
     # todo, should this be after vpn service
-    i /etc/systemd/system/unbound.service.d/nn.conf <<EOF
+    u /etc/systemd/system/unbound.service.d/nn.conf <<EOF
 [Unit]
 After=mailnn.service
 JoinsNamespaceOf=mailnn.service
@@ -761,7 +797,7 @@ EOF
     ;;&
   $MAIL_HOST|bk)
     for unit in ${nn_progs[@]}; do
-      i /etc/systemd/system/$unit.service.d/nn.conf <<EOF
+      u /etc/systemd/system/$unit.service.d/nn.conf <<EOF
 [Unit]
 
 # Wants appears better than requires because with requires,
@@ -799,7 +835,7 @@ esac
 # * wghole (another mail vpn)
 
 if $bhost_t; then
-  i /etc/systemd/system/wg-quick@wghole.service.d/override.conf <<'EOF'
+  u /etc/systemd/system/wg-quick@wghole.service.d/override.conf <<'EOF'
 [Unit]
 StartLimitIntervalSec=0
 
@@ -810,17 +846,18 @@ EOF
 fi
 
 # * spamassassin config
-i /etc/sysctl.d/80-iank-mail.conf <<'EOF'
+u /etc/sysctl.d/80-iank-mail.conf <<'EOF'
 # see exim spec
 net.netfilter.nf_conntrack_tcp_timeout_close_wait = 120
 EOF
-if $ir; then
+if $ur; then
   m sysctl -p
 fi
 
-i /etc/spamassassin/mylocal.cf <<'EOF'
+u /etc/spamassassin/mylocal.cf <<'EOF'
 # this is mylocal.cf because the normal local.cf has a bunch of upstream stuff i dont want to mess with
 
+
 # /usr/share/doc/exim4-base/README.Debian.gz:
 #   SpamAssassin's default report should not be used in a add_header
 #   statement since it contains empty lines. (This triggers e.g. Amavis'
@@ -837,7 +874,7 @@ EOF
 # 2020-10-19 remove old file. remove this when all hosts updated
 rm -fv /etc/systemd/system/spamddnsfix.{timer,service}
 
-i /etc/default/spamassassin <<'EOF'
+u /etc/default/spamassassin <<'EOF'
 # defaults plus debugging flags for an issue im having
 OPTIONS="--create-prefs --max-children 5 --helper-home-dir"
 PIDFILE="/var/run/spamd.pid"
@@ -845,6 +882,35 @@ PIDFILE="/var/run/spamd.pid"
 NICE="--nicelevel 15"
 CRON=1
 EOF
+
+case $HOSTNAME in
+  bk)
+u /etc/spamassassin/my_thishost.cf <<'EOF'
+# note: these are duplicated in exim config
+# veth0/1 # bk bk_ip6
+internal_networks 10.173.8.1/32 10.173.8.2/32 85.119.83.50/32 2001:ba8:1f1:f0c9::2
+trusted_networks 10.173.8.1/32 10.173.8.2/32 85.119.83.50/32 2001:ba8:1f1:f0c9::2
+EOF
+
+    ;;
+  je)
+    u /etc/spamassassin/my_thishost.cf <<'EOF'
+# note: these are duplicated in exim config
+# veth0/1 # je je_ipv6
+internal_networks 10.173.8.1/32 10.173.8.2/32 85.119.82.128/32 2001:ba8:1f1:f09d::2/128
+trusted_networks 10.173.8.1/32 10.173.8.2/32 85.119.82.128/32 2001:ba8:1f1:f09d::2/128
+EOF
+    ;;
+  *)
+    u /etc/spamassassin/my_thishost.cf <<'EOF'
+# note: these are duplicated in exim config
+# veth0/1 # li li_ip6
+internal_networks 10.173.8.1/32 10.173.8.2/32 72.14.176.105/32 2600:3c00::f03c:91ff:fe6d:baf8/128
+trusted_networks 10.173.8.1/32 10.173.8.2/32 72.14.176.105/32 2600:3c00::f03c:91ff:fe6d:baf8/128
+EOF
+;;
+  esac
+
 #####   end spamassassin config
 
 
@@ -876,7 +942,7 @@ EOF
 
 m rsync -aiSAX --chown=root:root --chmod=g-s /a/bin/ds/mail-cert-cron /usr/local/bin
 
-i /etc/systemd/system/mailcert.service <<'EOF'
+u /etc/systemd/system/mailcert.service <<'EOF'
 [Unit]
 Description=Mail cert rsync
 After=multi-user.target
@@ -885,7 +951,7 @@ After=multi-user.target
 Type=oneshot
 ExecStart=/usr/local/bin/sysd-mail-once mailcert /usr/local/bin/mail-cert-cron
 EOF
-i /etc/systemd/system/mailcert.timer <<'EOF'
+u /etc/systemd/system/mailcert.timer <<'EOF'
 [Unit]
 Description=Run mail-cert once a day
 
@@ -913,8 +979,8 @@ fi
 # and see someone is banned.
 
 sed 's/^ *before *= *iptables-common.conf/before = iptables-common-exim.conf/' \
-    /etc/fail2ban/action.d/iptables-multiport.conf| i /etc/fail2ban/action.d/iptables-exim.conf
-i /etc/fail2ban/action.d/iptables-common-exim.conf <<'EOF'
+    /etc/fail2ban/action.d/iptables-multiport.conf| u /etc/fail2ban/action.d/iptables-exim.conf
+u /etc/fail2ban/action.d/iptables-common-exim.conf <<'EOF'
 # iank: same as iptables-common, except iptables is iptables-exim, ip6tables is ip6tables-exim
 
 # Fail2Ban configuration file
@@ -1010,7 +1076,7 @@ blocktype = REJECT --reject-with icmp6-port-unreachable
 iptables = /usr/local/bin/ip6tables-exim <lockingopt>
 EOF
 
-i /etc/fail2ban/jail.d/exim.local <<'EOF'
+u /etc/fail2ban/jail.d/exim.local <<'EOF'
 [exim]
 enabled  = true
 port    = 25,587
@@ -1025,7 +1091,7 @@ banaction = iptables-exim
 # 10.173.8.1 = non-nn net
 ignoreip = 209.51.188.13 2001:470:142::13 209.51.188.92 2001:470:142:3::10 72.14.176.105 2600:3c00:e000:280::2 10.173.8.1
 EOF
-if $ir; then
+if $ur; then
   m systemctl restart fail2ban
 fi
 
@@ -1131,26 +1197,26 @@ rm -fv /etc/exim4/conf.d/retry/37_retry
 
 cat >/etc/exim4/conf.d/retry/17_retry <<'EOF'
 # Retry fast for my own domains
-iankelling.org * F,1d,4m;F,14d,1h
-amnimal.ninja * F,1d,4m;F,14d,1h
-expertpathologyreview.com * F,1d,4m;F,14d,1h
-je.b8.nz * F,1d,4m;F,14d,1h
-zroe.org * F,1d,4m;F,14d,1h
-eximbackup.b8.nz * F,1d,4m;F,14d,1h
+iankelling.org * F,1d,1m;F,14d,1h
+amnimal.ninja * F,1d,1m;F,14d,1h
+expertpathologyreview.com * F,1d,1m;F,14d,1h
+je.b8.nz * F,1d,1m;F,14d,1h
+zroe.org * F,1d,1m;F,14d,1h
+eximbackup.b8.nz * F,1d,1m;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
-fencepost.gnu.org * F,1d,4m;F,14d,1h
+nn.b8.nz * F,1d,1m;F,14d,1h
+defaultnn.b8.nz * F,1d,1m;F,14d,1h
+mx.iankelling.org * F,1d,1m;F,14d,1h
+bk.b8.nz * F,1d,1m;F,14d,1h
+eggs.gnu.org * F,1d,1m;F,14d,1h
+fencepost.gnu.org * F,1d,1m;F,14d,1h
 
 # afaik our retry doesnt need this, but just using everything
-mx.amnimal.ninja * F,1d,4m;F,14d,1h
-mx.expertpathologyreview.com * F,1d,4m;F,14d,1h
+mx.amnimal.ninja * F,1d,1m;F,14d,1h
+mx.expertpathologyreview.com * F,1d,1m;F,14d,1h
 
 
 mail.fsf.org * F,1d,15m;F,14d,1h
@@ -1172,27 +1238,16 @@ cd /etc/exim4
   for f in *-private.pem; do
     echo ${f%-private.pem}
   done
-} | i /etc/exim4/conf.d/my-dkim-domains
-
-if grep -Fq REMOTE_SMTP_SMARTHOST_TLS_VERIFY_HOSTS \
-        /etc/exim4/conf.d/transport/10_exim4-config_transport-macros; then
-  cat >/etc/exim4/conf.d/transport/11_iank <<'EOF'
-# This unsets the default macro defined in on t11 in
-# /etc/exim4/conf.d/transport/10_exim4-config_transport-macros
-# It seems like a very odd choice that this has become
-# the default in t11. Normal smarthost clients use username/password
-# auth. Oh well.
-REMOTE_SMTP_SMARTHOST_TLS_VERIFY_HOSTS ==
-EOF
-else
-  rm -f /etc/exim4/conf.d/transport/11_iank
-fi
+} | u /etc/exim4/conf.d/my-dkim-domains
+
+rm -f /etc/exim4/conf.d/transport/11_iank
 
 cat >/etc/exim4/conf.d/main/000_local <<'EOF'
 MAIN_TLS_ENABLE = true
 
 # require tls connections for all smarthosts
-REMOTE_SMTP_SMARTHOST_HOSTS_REQUIRE_TLS = *
+REMOTE_SMTP_SMARTHOST_HOSTS_REQUIRE_TLS = ! nn.b8.nz
+REMOTE_SMTP_SMARTHOST_HOSTS_AVOID_TLS = nn.b8.nz
 
 # debian exim config added this in 2016 or so?
 # it's part of the smtp spec, to limit lines to 998 chars
@@ -1204,8 +1259,8 @@ REMOTE_SMTP_SMARTHOST_HOSTS_REQUIRE_TLS = *
 # other says gmail does not reject. figure out and open a new bug.
 IGNORE_SMTP_LINE_LENGTH_LIMIT = true
 
-# more verbose logs
-MAIN_LOG_SELECTOR = +all
+# more verbose logs. used to use +all, but made it less for more efficiency.
+MAIN_LOG_SELECTOR = -skip_delivery -tls_cipher -tls_certificate_verified +all_parents +address_rewrite +arguments +deliver_time +pid +queue_time +queue_time_overall +received_recipients +received_sender +return_path_on_delivery +sender_on_delivery +smtp_confirmation +subject
 
 # Based on spec, seems like a good idea to be nice.
 smtp_return_error_details = true
@@ -1236,6 +1291,7 @@ DKIM_SIGN_HEADERS = mime-version:in-reply-to:references:from:date:subject:to
 
 domainlist local_hostnames = ! je.b8.nz : ! bk.b8.nz : *.b8.nz : b8.nz
 
+# note: most of these are duplicated in spamassassin config
 hostlist iank_trusted = <; \
 # veth0
 10.173.8.1 ; \
@@ -1264,7 +1320,7 @@ delay_warning_condition = ${if or {\
 
 # enable 587 in addition to the default 25, so that
 # i can send mail where port 25 is firewalled by isp
-daemon_smtp_ports = 25 : 587
+daemon_smtp_ports = 25 : 587 : 10025
 # default of 25, can get stuck when catching up on mail
 smtp_accept_max = 400
 smtp_accept_reserve = 100
@@ -1295,7 +1351,7 @@ fi
 
 rm -fv /etc/exim4/rcpt_local_acl # old path
 
-i /etc/exim4/conf.d/local_deny_exceptions_acl <<'EOF'
+u /etc/exim4/conf.d/local_deny_exceptions_acl <<'EOF'
 # This acl already exists in rcpt, this just makes it more widespread.
 # See the comment there for its rationale. The reason it needs to be
 # more widespread is that I've turned on sender verification, but cron
@@ -1312,7 +1368,7 @@ EOF
 
 rm -fv /etc/exim4/data_local_acl # old path
 
-i /etc/exim4/conf.d/data_local_acl <<'EOF'
+u /etc/exim4/conf.d/data_local_acl <<'EOF'
 # Except for the "condition =", this was
 # a comment in the check_data acl. The comment about this not
 # being suitable has been changed in newer exim versions. The only thing
@@ -1348,18 +1404,21 @@ warn
 
 EOF
 
-# It is important for this to exist universally, instead of
-# just on the mail host because if we change mail host and
-# still have something in the queue which was destined for
-# this router, but hosts were unreachable, the routers will
-# be reevaluated on the next retry.
-i /etc/exim4/conf.d/router/890_backup_copy <<EOF
+
+# old file
+rm -fv /etc/exim4/conf.d/router/8{8,9}0_backup_copy \
+   /etc/exim4/conf.d/router/865_backup_redir \
+   /etc/exim4/conf.d/router/870_backup_local
+
+# It is important for this to exist everywhere except in MAIL_HOST
+# non-nn config. Previously, just had it in the nn-config on MAIL_HOST,
+# but that is a problem if we change mail host and still have something
+# in the queue which was destined for this router, but hosts were
+# unreachable, the routers will be reevaluated on the next retry.
+u /etc/exim4/conf.d/router/170_backup_copy <<EOF
 ### router/900_exim4-config_local_user
 #################################
 
-# todo, it would be nice backup sent email too,
-# but its not so important, they still exist in my head
-
 backup_copy:
 driver = manualroute
 domains = eximbackup.b8.nz
@@ -1372,13 +1431,14 @@ errors_to = alerts@iankelling.org
 no_more
 EOF
 
+
 # exim4-config transports are the same as default except for
 # message_linelength_limit = 2097152
 #
 # TODO: copy the defaults into their own file, and setup a cronjob so
 # that if file.dpkg-dist shows up, and it is different, we get an alert.
 
-i /etc/exim4/conf.d/transport/30_exim4-config_remote_smtp_smarthost <<'EOF'
+u /etc/exim4/conf.d/transport/30_exim4-config_remote_smtp_smarthost <<'EOF'
 ### transport/30_exim4-config_remote_smtp_smarthost
 #################################
 
@@ -1435,7 +1495,7 @@ tls_privatekey = REMOTE_SMTP_SMARTHOST_PRIVATEKEY
 .endif
 EOF
 
-i /etc/exim4/conf.d/transport/30_exim4-config_remote_smtp <<'EOF'
+u /etc/exim4/conf.d/transport/30_exim4-config_remote_smtp <<'EOF'
 ### transport/30_exim4-config_remote_smtp
 #################################
 # This transport is used for delivering messages over SMTP connections.
@@ -1501,7 +1561,7 @@ tls_privatekey = REMOTE_SMTP_PRIVATEKEY
 
 EOF
 
-i /etc/exim4/conf.d/transport/30_backup_remote <<'EOF'
+u /etc/exim4/conf.d/transport/30_backup_remote <<'EOF'
 backup_remote:
   driver = smtp
   multi_domain
@@ -1544,7 +1604,7 @@ tls_privatekey = REMOTE_SMTP_SMARTHOST_PRIVATEKEY
 .endif
 EOF
 
-i /etc/exim4/conf.d/router/900_exim4-config_local_user <<'EOF'
+u /etc/exim4/conf.d/router/900_exim4-config_local_user <<'EOF'
 ### router/900_exim4-config_local_user
 #################################
 
@@ -1565,7 +1625,7 @@ local_user:
   local_part_suffix = +*
   local_part_suffix_optional
 EOF
-i /etc/exim4/conf.d/transport/30_exim4-config_dovecot_lmtp <<'EOF'
+u /etc/exim4/conf.d/transport/30_exim4-config_dovecot_lmtp <<'EOF'
 dovecot_lmtp:
   driver = lmtp
   socket = /var/run/dovecot/lmtp
@@ -1574,7 +1634,7 @@ dovecot_lmtp:
   envelope_to_add
 EOF
 
-i /etc/exim4/conf.d/transport/30_remote_smtp_vpn <<'EOF'
+u /etc/exim4/conf.d/transport/30_remote_smtp_vpn <<'EOF'
 # same as debians 30_exim4-config_remote_smtp, but
 # with interface added at the end.
 
@@ -1630,7 +1690,7 @@ tls_privatekey = REMOTE_SMTP_PRIVATEKEY
   interface = <; 10.8.0.4 ; 2600:3c00:e002:3800::4
 EOF
 
-i /etc/exim4/conf.d/transport/30_smarthost_dkim <<'EOF'
+u /etc/exim4/conf.d/transport/30_smarthost_dkim <<'EOF'
 # ian: this is remote_smtp_smarthost plus the dkim parts from remote_smtp
 
 smarthost_dkim:
@@ -1701,7 +1761,6 @@ EOF
 cat >/etc/exim4/update-exim4.conf.conf  <<'EOF'
 # default stuff, i havent checked if its needed
 dc_minimaldns='false'
-dc_relay_nets=''
 CFILEMODE='644'
 dc_use_split_config='true'
 dc_mailname_in_oh='true'
@@ -1725,7 +1784,7 @@ if mailhost; then
   # in the log it just says "Starting Radicale". If you run
   # it in the foreground, it will give more info. Background
   # plus debug does not help.
-  # sudo -u radicale radicale -D -f
+  # sudo -u radicale radicale -D
 
   # created password file with:
   # htpasswd -c /p/c/machine_specific/li/filesystem/etc/caldav-htpasswd
@@ -1733,8 +1792,9 @@ if mailhost; then
   # # setup chgrp www-data in ./conflink
 
   pi-nostart radicale
+  m usermod -a -G radicale iank
 
-  i /etc/systemd/system/radicale.service.d/override.conf <<EOF
+  u /etc/systemd/system/radicale.service.d/override.conf <<EOF
 [Unit]
 
 After=network.target network-online.target mailnn.service $vpnser
@@ -1866,7 +1926,7 @@ case $HOSTNAME in
     done
 
     # https://wiki.dovecot.org/SSL/DovecotConfiguration
-    i /etc/dovecot/dhparam <<'EOF'
+    u /etc/dovecot/dhparam <<'EOF'
 -----BEGIN DH PARAMETERS-----
 MIIBCAKCAQEAoleil6SBxGqQKk7j0y2vV3Oklv6XupZKn7PkPv485QuFeFagifeS
 A+Jz6Wquqk5zhGyCu63Hp4wzGs4TyQqoLjkaWL6Ra/Bw3g3ofPEzMGEsV1Qdqde4
@@ -2053,7 +2113,7 @@ namespace inbox {
 auth_mechanisms = plain login
 EOF
 
-    i /etc/dovecot/sieve-spam.sieve <<'EOF'
+    u /etc/dovecot/sieve-spam.sieve <<'EOF'
 require ["regex", "fileinto", "imap4flags"];
 
 if allof (header :regex "X-Spam-Status" "^Yes") {
@@ -2062,7 +2122,7 @@ if allof (header :regex "X-Spam-Status" "^Yes") {
 }
 EOF
 
-    i /etc/dovecot/local.conf.ext <<'EOF'
+    u /etc/dovecot/local.conf.ext <<'EOF'
 passdb {
   driver = sql
   args = /etc/dovecot/dovecot-sql.conf.ext
@@ -2074,7 +2134,7 @@ userdb {
 
 EOF
 
-    i /etc/dovecot/dovecot-sql.conf.ext <<'EOF'
+    u /etc/dovecot/dovecot-sql.conf.ext <<'EOF'
 # from mailinabox
 driver = sqlite
 # for je and bk, populated the testignore users for the relevant domains
@@ -2129,7 +2189,7 @@ if [[ $HOSTNAME == bk ]]; then
     dir=/var/www/autoconfig.$domain/html/mail
     m mkdir -p $dir
     # taken from mailinabox
-    i $dir/config-v1.1.xml <<EOF
+    u $dir/config-v1.1.xml <<EOF
 <?xml version="1.0" encoding="UTF-8"?>
 <clientConfig version="1.1">
     <emailProvider id="$domain">
@@ -2187,27 +2247,28 @@ if [[ $HOSTNAME == bk ]]; then
 
   ### begin composer install
   # https://getcomposer.org/doc/faqs/how-to-install-composer-programmatically.md
-  # cd $(mktemp -d)
-  # sum="$(wget -q -O - https://composer.github.io/installer.sig)"
-  # m php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
-  # if [[ $sum != $(php -r "echo hash_file('sha384', 'composer-setup.php');") ]]; then
-  #   echo 'ERROR: Invalid composer installer checksum' >&2
-  #   rm -fv composer-setup.php
-  #   exit 1
-  # fi
-  # m php composer-setup.php --quiet
-  # rm -fv composer-setup.php
-  # m mv composer.phar /usr/local/bin
-
-  # the above method gets composer2, carddav plugin at least doesnt work with that
-  # yet, it was just released 10-24-2020.
-  m cd /usr/local/bin
-  m wget -nv -N https://getcomposer.org/composer-1.phar
-  chmod +x composer-1.phar
+  cd /usr/local/bin
+  EXPECTED_CHECKSUM="$(php -r 'copy("https://composer.github.io/installer.sig", "php://stdout");')"
+  php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
+  ACTUAL_CHECKSUM="$(php -r "echo hash_file('sha384', 'composer-setup.php');")"
+
+  if [ "$EXPECTED_CHECKSUM" != "$ACTUAL_CHECKSUM" ]
+  then
+    >&2 echo 'ERROR: Invalid installer checksum'
+    rm composer-setup.php
+    exit 1
+  fi
+
+  php composer-setup.php --quiet
+  rm composer-setup.php
+
+  # based on error when running composer
+  mkdir -p /var/www/.composer
+  chown www-data:www-data /var/www/.composer
+
   ### 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
 
@@ -2239,11 +2300,9 @@ if [[ $HOSTNAME == bk ]]; then
     rcdir=${rcdirs[i]}
     rcbase=${rcdir##*/}
     ncdir=${ncdirs[i]}
-    myncdir=/root/${ncdir##*/}
-    mkdir -p $myncdir
 
     # copied from debians cronjob
-    i /etc/cron.d/$rcbase <<EOF
+    u /etc/cron.d/$rcbase <<EOF
 #  Roundcube database cleaning: finally removes all records that are
 #  marked as deleted.
 0   5  *   *   *   www-data $rcdir/bin/cleandb.sh >/dev/null
@@ -2303,7 +2362,7 @@ EOF
     rctmpdir=/var/tmp/$rcbase
     rcdb=/m/rc/$rcbase.sqlite
     # config from mailinabox
-    i $rcdir/config/config.inc.php <<EOF
+    u $rcdir/config/config.inc.php <<EOF
 <?php
 \$config = array();
 # debian creates this for us
@@ -2362,7 +2421,7 @@ EOF
     verf=$rcdir/plugins/carddav/myversion
     upgrade=false
     install=false
-    v=4.0.0
+    v=5.0.1
     if [[ -e $verf ]]; then
       if [[ $(cat $verf) != "$v" ]]; then
         install=true
@@ -2374,16 +2433,16 @@ EOF
     if $install; then
       m rm -rf $rcdir/plugins/carddav
       tmpd=$(mktemp -d)
-      m wget -nv -O $tmpd/t.tgz https://github.com/blind-coder/rcmcarddav/releases/download/v$v/carddav-v$v.tgz
+      m wget -nv -O $tmpd/t.tgz https://github.com/blind-coder/rcmcarddav/releases/download/v$v/carddav-v$v.tar.gz
       cd $rcdir/plugins
       tar xzf $tmpd/t.tgz
       rm -rf $tmpd
       m chown -R www-data:www-data $rcdir/plugins/carddav
       m cd $rcdir/plugins/carddav
       if $upgrade; then
-        m sudo -u www-data composer-1.phar update --no-dev
+        m sudo -u www-data composer.phar update --no-dev
       else
-        m sudo -u www-data composer-1.phar install --no-dev
+        m sudo -u www-data composer.phar install --no-dev
       fi
       m chown -R root:root $rcdir/plugins/carddav
       echo $v >$verf
@@ -2398,7 +2457,7 @@ EOF
 
     # About categories, see https://www.davx5.com/tested-with/nextcloud
     # https://github.com/blind-coder/rcmcarddav/blob/master/doc/GROUPS.md
-    i $rcdir/plugins/carddav/config.inc.php <<EOF;
+    u $rcdir/plugins/carddav/config.inc.php <<EOF;
 <?php
 \$prefs['_GLOBAL']['hide_preferences'] = false;
 \$prefs['davserver'] = array(
@@ -2468,11 +2527,11 @@ EOF
   # $rclogdir/errors.log
   # todo: consider other settings in
   # /a/opt/mailinabox/setup/nextcloud.sh
-  i /etc/php/$phpver/cli/conf.d/30-local.ini <<'EOF'
+  u /etc/php/$phpver/cli/conf.d/30-local.ini <<'EOF'
 apc.enable_cli = 1
 EOF
 
-  i /etc/php/$phpver/fpm/conf.d/30-local.ini <<'EOF'
+  u /etc/php/$phpver/fpm/conf.d/30-local.ini <<'EOF'
 date.timezone = "America/New_York"
 # for nextcloud
 upload_max_filesize = 2000M
@@ -2507,7 +2566,9 @@ EOF
   for ((i=0; i < ${#bkdomains[@]}; i++)); do
     domain=${bkdomains[i]}
     ncdir=${ncdirs[i]}
+    myncdir=/var/local/${ncdir##*/}
     ncbase=${ncdir##*/}
+    mkdir -p $myncdir
     m cd /var/www
     if [[ ! -e $ncdir/index.php ]]; then
       # if we wanted to only install a specific version, use something like
@@ -2527,13 +2588,16 @@ EOF
       m touch $myncdir/done-install
     fi
 
-    # note, strange this happend where updater did not increment the version var,
-    # mine was stuck on 20. I manually updated it.
     m cd $ncdir/config
-    if [[ ! -e $myncdir/config.php-orig ]]; then
-      m cp -a config.php $myncdir/config.php-orig
-    fi
-    cat $myncdir/config.php-orig - >$myncdir/tmp.php <<EOF
+    # if we did this more than once, it would revert the
+    # version number to the original.
+    if [[ ! -e $myncdir/config.php-orig || ! -s config.php ]]; then
+      if [[ -s config.php ]]; then
+        m cp -a config.php $myncdir/config.php-orig
+        # keep the file so it keeps the same permissions.
+        truncate -s0 config.php
+      fi
+      cat $myncdir/config.php-orig - >$myncdir/tmp.php <<EOF
 # https://docs.nextcloud.com/server/19/admin_manual/configuration_server/email_configuration.html
 \$CONFIG["mail_smtpmode"] = "sendmail";
 \$CONFIG["mail_smtphost"] = "127.0.0.1";
@@ -2565,9 +2629,11 @@ fwrite(STDOUT, "<?php\n\\\$CONFIG = ");
 var_export(\$CONFIG);
 fwrite(STDOUT, ";\n");
 EOF
-    e running php $myncdir/tmp.php
-    # note: we leave it around place for debugging
-    php $myncdir/tmp.php >config.php
+      e running php $myncdir/tmp.php
+      # note: we leave it around place for debugging
+      # shellcheck disable=SC2024 # intended
+      sudo -u www-data php $myncdir/tmp.php >config.php
+    fi
     cd $ncdir
     m sudo -u www-data php occ maintenance:update:htaccess
     list=$(sudo -u www-data php $ncdir/occ --output=json_pretty app:list)
@@ -2578,7 +2644,7 @@ EOF
         m sudo -u www-data php occ app:install $app
       fi
     done
-    i /etc/systemd/system/$ncbase.service <<EOF
+    u /etc/systemd/system/$ncbase.service <<EOF
 [Unit]
 Description=ncup $ncbase
 After=multi-user.target
@@ -2590,7 +2656,7 @@ User=www-data
 IOSchedulingClass=idle
 CPUSchedulingPolicy=idle
 EOF
-    i /etc/systemd/system/$ncbase.timer <<EOF
+    u /etc/systemd/system/$ncbase.timer <<EOF
 [Unit]
 Description=ncup $ncbase timer
 
@@ -2601,7 +2667,7 @@ OnCalendar=Daily
 WantedBy=timers.target
 EOF
     systemctl enable --now $ncbase.timer
-    i /usr/local/bin/ncup <<'EOFOUTER'
+    u /usr/local/bin/ncup <<'EOFOUTER'
 #!/bin/bash
 
 source /usr/local/lib/err
@@ -2633,13 +2699,19 @@ fi
 ncbase=$1
 cd /var/www/$ncbase
 # https://docs.nextcloud.com/server/22/admin_manual/maintenance/update.html?highlight=updater+phar
+# the docs claim this is all you need, which is not true.
+# You will go to the web ui and it will say that you need to click a button to update,
+# or that you can run occ upgrade
 m php /var/www/$ncbase/updater/updater.phar -n
+# throw a sleep in just because who knows what else is undocumented
+sleep 5
+m php occ upgrade
 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
+    u /etc/cron.d/$ncbase <<EOF
 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
@@ -2687,7 +2759,7 @@ deny
   domains = +local_domains
   !verify = recipient/callout=no_cache
 EOF
-    i /etc/exim4/conf.d/auth/29_exim4-config_auth <<'EOF'
+    u /etc/exim4/conf.d/auth/29_exim4-config_auth <<'EOF'
 dovecot_plain:
   driver = dovecot
   public_name = PLAIN
@@ -2697,7 +2769,7 @@ EOF
     ;;
 esac
 if $bhost_t; then
-  i /etc/exim4/conf.d/auth/29_exim4-config_auth <<'EOF'
+  u /etc/exim4/conf.d/auth/29_exim4-config_auth <<'EOF'
 # from 30_exim4-config_examples
 plain_server:
 driver = plaintext
@@ -2717,7 +2789,7 @@ case $HOSTNAME in
     # to see the default comments in /etc/default/exim4:
     # s update-exim4defaults --force --init
     # which will overwrite any existing file
-    i /etc/default/exim4 <<'EOF'
+    u /etc/default/exim4 <<'EOF'
 QUEUERUNNER='combined'
 QUEUEINTERVAL='30m'
 COMMONOPTIONS='-C /etc/exim4/my.conf'
@@ -2736,13 +2808,13 @@ EOF
     # note: the daemon gives up and dies after retrying those 9 times.
     # I came upon this by guessing and trial and error.
     setcap CAP_NET_BIND_SERVICE+ei /usr/sbin/exim4
-    i /etc/exim4/trusted_configs <<'EOF'
+    u /etc/exim4/trusted_configs <<'EOF'
 /etc/exim4/my.conf
 EOF
     ;;
   *)
     # default file
-    i /etc/default/exim4 <<'EOF'
+    u /etc/default/exim4 <<'EOF'
 QUEUERUNNER='combined'
 QUEUEINTERVAL='30m'
 EOF
@@ -2763,7 +2835,7 @@ case $HOSTNAME in
         dirs+=($d)
       fi
     done
-    i /etc/systemd/system/exim4.service.d/nonroot.conf <<EOF
+    u /etc/systemd/system/exim4.service.d/nonroot.conf <<EOF
 [Service]
 # see 56.2 Root privilege in exim spec
 AmbientCapabilities=CAP_NET_BIND_SERVICE
@@ -2784,7 +2856,7 @@ ProtectSystem=yes
 # when we get newer systemd
 #ProtectDevices=yes
 EOF
-    i /etc/exim4/conf.d/main/000_local-noroot <<'EOF'
+    u /etc/exim4/conf.d/main/000_local-noroot <<'EOF'
 # see 56.2 Root privilege in exim spec
 deliver_drop_privilege = true
 EOF
@@ -2796,7 +2868,7 @@ EOF
       mmm_mail4root
     )
     for f in ${files[@]}; do
-      echo "# iank: removed due to running nonroot"|i /etc/exim4/conf.d/router/$f
+      echo "# iank: removed due to running nonroot"|u /etc/exim4/conf.d/router/$f
     done
     ;;
 esac
@@ -2806,7 +2878,7 @@ case $HOSTNAME in
   # ** $MAIL_HOST|bk|je)
   $MAIL_HOST|bk|je)
 
-    echo|i /etc/exim4/conf.d/router/870_backup_local
+    echo|u /etc/exim4/conf.d/router/165_backup_local
 
     cat >>/etc/exim4/update-exim4.conf.conf <<EOF
 # note: some things we don't set that are here by default because they are unused.
@@ -2836,9 +2908,12 @@ EOF
   # ** $MAIL_HOST|bk)
   $MAIL_HOST|bk)
 
+    cat >>/etc/exim4/update-exim4.conf.conf <<EOF
+dc_relay_nets='defaultnn.b8.nz'
+EOF
 
     # no clamav on je, it has 1.5g memory and clamav uses most of it
-    i /etc/exim4/conf.d/clamav_data_acl <<'EOF'
+    u /etc/exim4/conf.d/clamav_data_acl <<'EOF'
 warn
 !hosts = +iank_trusted
 !authenticated = plain_server:login_server
@@ -2882,12 +2957,12 @@ MAIN_TLS_CERTIFICATE = /etc/exim4/fullchain.pem
 MAIN_TLS_PRIVATEKEY = /etc/exim4/privkey.pem
 EOF
 
-    i /etc/exim4/conf.d/router/190_exim4-config_fsfsmarthost <<'EOF'
+    u /etc/exim4/conf.d/router/190_exim4-config_fsfsmarthost <<'EOF'
 gnusmarthost:
   debug_print = "R: smarthost for $local_part@$domain"
   driver = manualroute
   domains = ! +local_domains
-# send most mail through eggs, helps fsfs sender reputation.
+# comment senders to send most mail through eggs, helps fsfs sender reputation.
 # uncomment and optionally move to 188 file to send through my own servers again
   senders = *@gnu.org
   transport = smarthost_dkim
@@ -2904,7 +2979,7 @@ EOF
   # ** $MAIL_HOST)
   $MAIL_HOST)
 
-    i /etc/exim4/conf.d/router/195_dnslookup_vpn <<'EOF'
+    u /etc/exim4/conf.d/router/195_dnslookup_vpn <<'EOF'
 # copied from /etc/exim4/conf.d/router/200_exim4-config_primary, but
 # use vpn transport. lower priority so it overrides the default route.
 # Use this in case our vpn fails, we dont send anything without it.
@@ -2926,12 +3001,12 @@ EOF
     # which required using a dedicated user, but realized smtp will be
     # more reliable and less fuss. If I ever need that again, see the
     # history of this file, and bum in brc2.
-    i /etc/exim4/conf.d/router/890_backup_copy <<EOF
-backup_redir:
+    u /etc/exim4/conf.d/router/161_backup_redir_nn <<'EOF'
+backup_redir_nn:
 driver = redirect
-domains = +local_domains
 # b is just an arbirary short string
 data = b@eximbackup.b8.nz
+condition = ${if !bool{${lookup{$local_part@$domain}lsearch{/etc/exim4/ignore-sent}{true}}}}
 # note, to test this, i could temporarily allow testignore.
 # alerts avoids potential mail loop. root is already
 # redirected earlier, so that is just being overly cautious.
@@ -2944,7 +3019,7 @@ EOF
 
     # This allows for forwarded mail to not get most rcpt checks, especially SPF,
     # which would incorrectly get denied.
-    i /etc/exim4/host_local_deny_exceptions <<'EOF'
+    u /etc/exim4/host_local_deny_exceptions <<'EOF'
 mail.fsf.org
 *.posteo.de
 EOF
@@ -2954,36 +3029,45 @@ EOF
     # case that doesn't work, we still want to accept that mail, but not
     # from any host except the smarthosts. local_hostnames and this rule
     # is for that purpose.
-    i /etc/exim4/conf.d/rcpt_local_acl <<'EOF'
+    u /etc/exim4/conf.d/rcpt_local_acl <<'EOF'
 deny
   !authenticated = *
   domains = +local_hostnames
   message = no relay
+
+# for testing bounce behavior
+#deny
+#  senders = testlist-bounces+test=zroe.org@fsf.org
+#  message = iank-bounce
 EOF
-    echo|i /etc/exim4/conf.d/router/880_universal_forward
+    echo|u /etc/exim4/conf.d/router/880_universal_forward
 
 
     cat >>/etc/exim4/conf.d/main/000_local <<EOF
 MAILDIR_HOME_MAILDIR_LOCATION = /m/md/Sent
 EOF
 
-    # for iank@fsf.org, i have mail.fsf.org forward it to fsf@iankelling.org.
-    # and also have mail.iankelling.org whitelisted as a relay domain.
-    # I could avoid that if I changed this to submit to 587 with a
-    # password like a standard mua.
-    i /etc/exim4/conf.d/router/188_exim4-config_smarthost <<'EOF'
+
+    u /etc/exim4/conf.d/router/186_sentarchive_nn <<'EOF'
 # ian: save a copy of sent mail. i thought of other ways to
 # do this, for example, to only save sent mail that is not sent
 # from my mail client which saves a copy by default, but in the
 # end, it seems simplest to turn that off. We want to save
 # external mail sent by smarthosts.
-sentarchive:
+sentarchive_nn:
   driver = redirect
   domains = ! +local_domains
   condition = ${if !bool{${lookup{$local_part@$domain}lsearch{/etc/exim4/ignore-sent}{true}}}}
   data    = vojdedIdNejyebni@b8.nz
   unseen
+EOF
+
 
+    # for iank@fsf.org, i have mail.fsf.org forward it to fsf@iankelling.org.
+    # and also have mail.iankelling.org whitelisted as a relay domain.
+    # I could avoid that if I changed this to submit to 587 with a
+    # password like a standard mua.
+    u /etc/exim4/conf.d/router/188_exim4-config_smarthost <<'EOF'
 # ian: copied from /etc/exim4/conf.d/router/200_exim4-config_primary, and added senders = and
 # replaced DCsmarthost with hostname
 fsfsmarthost:
@@ -3069,21 +3153,19 @@ EOF
   ## we use this host to monitor MAIL_HOST and host a mail server for someone
   bk)
 
-    echo|i /etc/exim4/conf.d/rcpt_local_acl
-    echo|i /etc/exim4/conf.d/router/880_universal_forward
 
     /a/exe/cedit nn /etc/hosts <<'EOF' || [[ $? == 1 ]]
 10.173.8.2 nn.b8.nz
 EOF
 
-    sed -r -f - /etc/init.d/exim4  <<'EOF' | i /etc/init.d/exim4in
+    sed -r -f - /etc/init.d/exim4  <<'EOF' |u /etc/init.d/exim4in
 s,/etc/default/exim4,/etc/default/exim4in,g
 s,/run/exim4/exim.pid,/run/exim4/eximin.pid,g
 s,(^[ #]*Provides:).*,\1 exim4in,
 s,(^[ #]*NAME=).*,\1"exim4in",
 EOF
     chmod +x /etc/init.d/exim4in
-    i /etc/systemd/system/exim4in.service.d/alwaysrestart.conf <<'EOF'
+    u /etc/systemd/system/exim4in.service.d/alwaysrestart.conf <<'EOF'
 [Unit]
 # needed to continually restart
 StartLimitIntervalSec=0
@@ -3094,7 +3176,7 @@ Restart=always
 RestartSec=20
 EOF
 
-    i /etc/default/exim4in <<'EOF'
+    u /etc/default/exim4in <<'EOF'
 # defaults but no queue runner and alternate config dir
 QUEUERUNNER='no'
 COMMONOPTIONS='-oP /run/exim4/eximin.pid'
@@ -3114,23 +3196,21 @@ EOF
     cat >>/etc/exim4/update-exim4.conf.conf <<EOF
 dc_other_hostnames='je.b8.nz'
 EOF
-    echo|i /etc/exim4/conf.d/router/188_exim4-config_smarthost
-    echo|i /etc/exim4/conf.d/router/190_exim4-config_fsfsmarthost
-    echo|i /etc/exim4/conf.d/rcpt_local_acl
-    echo|i /etc/exim4/conf.d/router/880_universal_forward
     ;;
   # ** not MAIL_HOST|bk|je
   *)
     # this one should be removed for all non mail hosts, but
     # bk and je never become mail_host
-    echo|i /etc/exim4/conf.d/router/195_dnslookup_vpn
-
-    echo|i /etc/exim4/conf.d/router/188_exim4-config_smarthost
-    echo|i /etc/exim4/conf.d/router/190_exim4-config_fsfsmarthost
-    echo|i /etc/exim4/conf.d/rcpt_local_acl
-    echo|i /etc/exim4/conf.d/router/890_backup_copy
-    echo|i /etc/exim4/conf.d/main/000_local-nn
-    echo|i /etc/exim4/conf.d/clamav_data_acl
+    echo|u /etc/exim4/conf.d/router/195_dnslookup_vpn
+    echo|u /etc/exim4/conf.d/router/160_backup_redir
+    echo|u /etc/exim4/conf.d/router/161_backup_redir_nn
+    echo|u /etc/exim4/conf.d/router/185_sentarchive
+    echo|u /etc/exim4/conf.d/router/186_sentarchive_nn
+    echo|u /etc/exim4/conf.d/router/188_exim4-config_smarthost
+    echo|u /etc/exim4/conf.d/router/190_exim4-config_fsfsmarthost
+    echo|u /etc/exim4/conf.d/rcpt_local_acl
+    echo|u /etc/exim4/conf.d/main/000_local-nn
+    echo|u /etc/exim4/conf.d/clamav_data_acl
 
 
     if $bhost_t; then
@@ -3147,7 +3227,7 @@ EOF
     fi
 
     # catches things like cronjob email
-    i /etc/exim4/conf.d/router/880_universal_forward <<'EOF'
+    u /etc/exim4/conf.d/router/880_universal_forward <<'EOF'
 universal_forward:
   driver = redirect
   domains = +local_domains
@@ -3172,7 +3252,7 @@ EOF
       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
+      u /etc/exim4/conf.d/transport/30_backup_maildir <<EOF
 # modified debian maildir transport
 backup_maildir:
   driver = appendfile
@@ -3185,7 +3265,7 @@ backup_maildir:
   mode_fail_narrower = false
 EOF
 
-      i /etc/exim4/conf.d/router/870_backup_local <<'EOF'
+      u /etc/exim4/conf.d/router/165_backup_local <<'EOF'
 ### router/900_exim4-config_local_user
 #################################
 
@@ -3204,7 +3284,7 @@ dc_local_interfaces='127.0.0.1;::1;$wgholeip'
 EOF
 
       # wghole & thus exim will fail to start without internet connectivity.
-      i /etc/systemd/system/exim4.service.d/backup.conf <<'EOF'
+      u /etc/systemd/system/exim4.service.d/backup.conf <<'EOF'
 [Unit]
 StartLimitIntervalSec=0
 
@@ -3227,7 +3307,7 @@ dc_eximconfig_configtype='smarthost'
 dc_smarthost='$smarthost'
 EOF
 
-    hostname -f |i /etc/mailname
+    hostname -f |u /etc/mailname
     cat >>/etc/exim4/update-exim4.conf.conf <<EOF
 # The manpage incorrectly states this will do header rewriting, but
 # that only happens if we have dc_hide_mailname is set.
@@ -3244,8 +3324,12 @@ esac
 # ** $MAILHOST|bk, things that belong at the end
 case $HOSTNAME in
   $MAIL_HOST|bk)
-    # config for the non-nn exim
-    m rsync -ra --delete --delete-excluded --exclude=/conf.d/main/000_local-nn /etc/exim4/ /etc/myexim4
+    # config for the non-nn exim. note, it uses not default dir, but we
+    # generate that into the default config file
+    m rsync -ra --delete --delete-excluded \
+      --exclude=/conf.d/router/161_backup_redir_nn \
+      --exclude=/conf.d/router/186_sentarchive_nn \
+      --exclude=/conf.d/main/000_local-nn /etc/exim4/ /etc/myexim4
     cat >>/etc/myexim4/conf.d/main/000_local <<'EOF'
 # this makes it easier to see which exim is doing what
 log_file_path = /var/log/exim4/my%s
@@ -3286,11 +3370,39 @@ EOF
   bk)
 
     # config for the non-nn exim
-    cat >/etc/myexim4/conf.d/main/000_local-nn <<'EOF'
+    cat >>/etc/myexim4/conf.d/main/000_local <<'EOF'
 MAIN_HARDCODE_PRIMARY_HOSTNAME = mail2.iankelling.org
 EOF
     ;;
   $MAIL_HOST)
+
+
+    u /etc/myexim4/conf.d/router/185_sentarchive <<'EOF'
+sentarchive:
+  driver = redirect
+  domains = ! +local_domains
+  senders = <; *@fsf.org ; *@posteo.net
+  condition = ${if !bool{${lookup{$local_part@$domain}lsearch{/etc/exim4/ignore-sent}{true}}}}
+  data    = vojdedIdNejyebni@b8.nz
+  unseen
+EOF
+
+    u /etc/myexim4/conf.d/router/160_backup_redir <<'EOF'
+backup_redir:
+driver = redirect
+# i dont email myself from my own machine much, so lets ignore that.
+domains = ! +local_domains
+senders = <; *@fsf.org ; *@posteo.net
+condition = ${if !bool{${lookup{$local_part@$domain}lsearch{/etc/exim4/ignore-sent}{true}}}}
+# b is just an arbirary short string
+data = b@eximbackup.b8.nz
+# note, to test this, i could temporarily allow testignore.
+# alerts avoids potential mail loop.
+local_parts = ! root : ! testignore : ! alerts : ! daylert
+unseen = true
+errors_to = alerts@iankelling.org
+EOF
+
     # for bk, we have a exim4in.service that will do this for us.
     m update-exim4.conf -d /etc/myexim4
     ;;
@@ -3314,7 +3426,7 @@ if [[ -e /nocow ]]; then
   if ! grep -Fx "/nocow/exim4  /var/spool/exim4  none  bind  0 0" /etc/fstab; then
     echo "/nocow/exim4  /var/spool/exim4  none  bind  0 0" >>/etc/fstab
   fi
-  i /etc/systemd/system/exim4.service.d/override.conf <<'EOF'
+  u /etc/systemd/system/exim4.service.d/override.conf <<'EOF'
 [Unit]
 # 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
@@ -3368,14 +3480,20 @@ if $reload; then
   m systemctl daemon-reload
 fi
 
-# checking bhost_t is redundant, but could help us catch errors.
-if $bhost_t || [[ -e /etc/wireguard/wghole.conf ]]; then
-  # todo: in mail-setup, we have a static list of backup hosts, not *y
-  m systemctl --now enable wg-quick@wghole
+# optimization, this only needs to run once.
+if [[ ! -e /sys/class/net/wghole ]]; then
+  # checking bhost_t is redundant, but could help us catch errors.
+  if $bhost_t || [[ -e /etc/wireguard/wghole.conf ]]; then
+    # todo: in mail-setup, we have a static list of backup hosts, not *y
+    m systemctl --now enable wg-quick@wghole
+  fi
 fi
 
-sysd-prom-fail-install epanicclean
-m systemctl --now enable epanicclean
+# optimization, this only needs to be run once
+if [[ ! -e /var/lib/prometheus/node-exporter/exim_paniclog.prom ]]; then
+  sysd-prom-fail-install epanicclean
+  m systemctl --now enable epanicclean
+fi
 
 case $HOSTNAME in
   je)
@@ -3386,8 +3504,11 @@ case $HOSTNAME in
     ;;
 esac
 
-m /a/bin/ds/mail-cert-cron -1
-sre mailcert.timer
+# optimization, this only needs to run once.
+if [[ ! -e /etc/exim4/fullchain.pem ]]; then
+  m /a/bin/ds/mail-cert-cron -1
+  m systemctl --now enable mailcert.timer
+fi
 
 case $HOSTNAME in
   $MAIL_HOST|bk)
@@ -3424,9 +3545,11 @@ case $HOSTNAME in
   $MAIL_HOST|bk|je)
     # start spamassassin/dovecot before exim.
     sre dovecot spamassassin
-    # need to wait a bit before restarting exim, else I
-    # get a paniclog entry like: spam acl condition: all spamd servers failed
-    sleep 3
+    # Wait a bit before restarting exim, else I get a paniclog entry
+    # like: spam acl condition: all spamd servers failed. But I'm tired
+    # of waiting. I'll deal with this some other way.
+    #
+    # sleep 3
     m systemctl --now enable mailclean.timer
     ;;&
   $MAIL_HOST)
@@ -3485,7 +3608,7 @@ case $HOSTNAME in
     # note: cronjob "ian" also does some important monitoring
     # todo: this will sometimes cause an alert because mailtest-check will run
     # before we have setup network namespace and spamassassin
-    i /etc/cron.d/mailtest <<EOF
+    u /etc/cron.d/mailtest <<EOF
 SHELL=/bin/bash
 PATH=/usr/bin:/bin:/usr/local/bin
 MAILTO=daylert@iankelling.org
@@ -3498,7 +3621,7 @@ EOF
 
     m sudo rsync -ahhi --chown=root:root --chmod=0755 \
       /b/ds/mailtest-check /b/ds/check-remote-mailqs /usr/local/bin/
-    i /etc/systemd/system/mailtest-check.service <<'EOF'
+    u /etc/systemd/system/mailtest-check.service <<'EOF'
 [Unit]
 Description=mailtest-check
 After=local-fs.target
@@ -3546,10 +3669,12 @@ EOF
 
     # Dont put these test messages into the sent folder or else it will
     # overwhelm it, plus i dont want to save a copy at all.
-    rm -f /etc/exim4/ignore-sent
-    for t in ${test_tos[@]}; do
-      echo $t >> /etc/exim4/ignore-sent
-    done
+    # Plus addresses we generally want to ignore.
+    u /etc/exim4/ignore-sent <<EOF
+$(printf "%s\n" ${test_tos[@]})
+vojdedIdNejyebni@b8.nz
+b@eximbackup.b8.nz
+EOF
 
     cat >/usr/local/bin/send-test-forward <<'EOF'
 #!/bin/bash