{ flake.modules.nixos.mail = { pkgs, ... }: { services.postfix = { enable = true; setSendmail = true; settings.main = { myhostname = "sachiel.schererleander.de"; mydomain = "schererleander.de"; myorigin = "$myhostname"; mydestination = [ "localhost" ]; mynetworks = [ "127.0.0.0/8" "[::1]/128" ]; inet_interfaces = "loopback-only"; smtpd_banner = "$myhostname ESMTP"; smtp_tls_security_level = "may"; smtp_tls_loglevel = "1"; smtp_helo_name = "$myhostname"; # Restricted entirely to system and service accounts authorized_submit_users = "nextcloud, root"; smtpd_milters = "unix:/run/rspamd/worker-proxy.sock"; non_smtpd_milters = "unix:/run/rspamd/worker-proxy.sock"; milter_protocol = "6"; milter_default_action = "accept"; }; }; systemd.services."notify-backup-failure@" = { description = "Notify backup failure for %i"; serviceConfig.Type = "oneshot"; script = '' UNIT_NAME="%i" HOSTNAME=$(${pkgs.coreutils}/bin/cat /etc/hostname) TIMESTAMP=$(${pkgs.coreutils}/bin/date "+%Y-%m-%d %H:%M:%S %Z") # Get logs LOGS=$(${pkgs.systemd}/bin/journalctl -u "$UNIT_NAME" -n 50 --no-pager) ( ${pkgs.coreutils}/bin/echo "To: leander@schererleander.de" ${pkgs.coreutils}/bin/echo "From: root@sachiel.schererleander.de" ${pkgs.coreutils}/bin/echo "Subject: Backup Failure: $UNIT_NAME" ${pkgs.coreutils}/bin/echo "Content-Type: text/html; charset=UTF-8" ${pkgs.coreutils}/bin/echo "" ${pkgs.coreutils}/bin/cat <

Backup Failure Alert

Unit$UNIT_NAME
Host$HOSTNAME
Time$TIMESTAMP

Last 50 log lines:

$LOGS
EOF ) | /run/wrappers/bin/sendmail -f root@sachiel.schererleander.de leander@schererleander.de ''; }; systemd.services."weekly-report" = { description = "Generate and send weekly server report"; serviceConfig.Type = "oneshot"; script = '' HOSTNAME=$(${pkgs.coreutils}/bin/cat /etc/hostname) # 1. System Health UPTIME=$(${pkgs.procps}/bin/uptime -p) FAILED_SERVICES=$(${pkgs.systemd}/bin/systemctl --failed --no-legend --no-pager | ${pkgs.coreutils}/bin/head -n 5) [ -z "$FAILED_SERVICES" ] && FAILED_SERVICES="None" DISK_USAGE=$(${pkgs.coreutils}/bin/df -h) # 2. Security Overview BANNED_ROWS=$(${pkgs.systemd}/bin/journalctl _COMM=fail2ban --since "1 week ago" --no-pager | ${pkgs.gnugrep}/bin/grep " Ban " | ${pkgs.gawk}/bin/awk '{ # Log format: May 30 12:00:00 host fail2ban[123]: [jail] Ban IP date = $1 " " $2 match($0, /\[(.*)\] Ban (.*)/, m) jail = m[1] ip = m[2] print "" ip "" jail "" date "" }') [ -z "$BANNED_ROWS" ] && BANNED_ROWS="No new bans this week." LOGIN_ROWS=$(${pkgs.systemd}/bin/journalctl _SYSTEMD_UNIT=sshd.service --since "1 week ago" --no-pager | ${pkgs.gnugrep}/bin/grep -E "Accepted (publickey|password)" | ${pkgs.gawk}/bin/awk '{ # Log format: May 30 12:00:00 host sshd-session[123]: Accepted publickey for user from IP ... date = $1 " " $2 " " substr($3, 1, 5) user = $9 ip = $11 print "" user "" ip "" date "" }') [ -z "$LOGIN_ROWS" ] && LOGIN_ROWS="No logins recorded." # 3. Backup Status parse_backups() { ${pkgs.systemd}/bin/journalctl -u "$1" --since "1 week ago" --no-pager | ${pkgs.gawk}/bin/awk ' /Archive name:/ { d=$1" "$2; n=$NF } /Size \(compressed\):/ { s=$(NF-2)" "$(NF-1) } /Duration:/ { t=$NF; if (n != "") { if (n ~ /\.failed$/) { printf "%s%sFAILED%s\n", n, d, t } else { printf "%s%s%s%s\n", n, d, s, t } n="" } } ' | ${pkgs.coreutils}/bin/tail -n 5 } GIT_BACKUP_ROWS=$(parse_backups "borgbackup-job-git") [ -z "$GIT_BACKUP_ROWS" ] && GIT_BACKUP_ROWS="No recent logs." NC_BACKUP_ROWS=$(parse_backups "borgbackup-job-nextcloud") [ -z "$NC_BACKUP_ROWS" ] && NC_BACKUP_ROWS="No recent logs." # 4. Critical Events ERRORS=$(${pkgs.systemd}/bin/journalctl -p 0..3 --since "1 week ago" --no-pager | ${pkgs.coreutils}/bin/head -n 20) [ -z "$ERRORS" ] && ERRORS="No critical errors recorded." # Construct HTML ( ${pkgs.coreutils}/bin/echo "To: leander@schererleander.de" ${pkgs.coreutils}/bin/echo "From: root@sachiel.schererleander.de" ${pkgs.coreutils}/bin/echo "Subject: Weekly Report: $HOSTNAME" ${pkgs.coreutils}/bin/echo "Content-Type: text/html; charset=UTF-8" ${pkgs.coreutils}/bin/echo "" ${pkgs.coreutils}/bin/cat <

Weekly Report: $HOSTNAME

Server Health

Uptime: $UPTIME

Failed Services: $FAILED_SERVICES

Disk Usage:

$DISK_USAGE

Security Overview

Newly Banned IPs:

$BANNED_ROWS
IP AddressJailDate

Successful SSH Logins:

$LOGIN_ROWS
UserIP AddressDate

Backup Status

Git Repository

$GIT_BACKUP_ROWS
ArchiveDateSizeDuration

Nextcloud Repository

$NC_BACKUP_ROWS
ArchiveDateSizeDuration

Critical Events

$ERRORS
EOF ) | /run/wrappers/bin/sendmail -f root@sachiel.schererleander.de leander@schererleander.de ''; }; systemd.timers."weekly-report" = { description = "Timer for weekly server report"; wantedBy = [ "timers.target" ]; timerConfig = { OnCalendar = "Mon 08:00:00"; Persistent = true; }; }; services.rspamd = { enable = true; locals."dkim_signing.conf".text = '' selector = "mail"; path = "/var/lib/rspamd/dkim/mail.key"; allow_username_mismatch = true; use_domain = "header"; sign_authenticated = true; sign_local = true; use_esld = false; ''; }; }; }