{ config, pkgs, ... }: { # Systemd Journal Monitoring. # Alternative: # journal-biref # https://github.com/twaugh/journal-brief # https://opensource.com/article/20/7/systemd-journals-email # Write to Systemd Journal: # echo 'hello' | systemd-cat -p emerg # echo 'hello' | systemd-cat -t someapp -p emerg # View Systemd Journal. # Filter by app: # journalctl -b -t someapp # Filter by priority: # journalctl -b -p 5 # Manually execute journalwatch timer: # sudo systemctl start journalwatch.service # Find a message and view its details # journalctl -b -p5 -o json-pretty # Then press "/" and enter a pattern, then press "Enter". assertions = [{ assertion = config.services.opensmtpd.enable; message = "journalwatch requires a configured sendmail MTA, see sendmail-mta.nix."; }]; services.journalwatch = { enable = true; # TODO: Same as configured by sendmail MTA. mailFrom = "langbein@mail.de"; mailTo = "daniel+journalwatch@systemli.org"; #interval = "hourly"; # Lowest priority of message to be considered. A value between 7 (“debug”), and 0 (“emerg”). Defaults to 6 (“info”). If you don’t care about anything with “info” priority, you can reduce this to e.g. 5 (“notice”) to considerably reduce the amount of messages without needing many filterBlocks. priority = 5; # Default patterns: https://github.com/The-Compiler/journalwatch/blob/363725ac4b8aa841d87654fa8a63403a59ad1275/journalwatch.py#L71 # If the value of `match` starts and ends with a slash, it is interpreted as a regular expression, if not, it's an exact match. # `filters` are always regular expressions. # All regular expressions have to match the full string! filterBlocks = [ # # _SYSTEMD_UNIT # { # yodaTux filters = '' .* ''; match = "_SYSTEMD_UNIT = /(bluetooth\.service|cups\.service)/"; } { # yodaYoga filters = '' # Somebody evil trying to connect over SSH ^^ error: kex_exchange_identification: read: Connection reset by peer # Somebody evil connected with a non-SSH client to the SSH server. error: kex_exchange_identification: banner line contains invalid characters # Somebody evil ... error: kex_exchange_identification: client sent invalid protocol identifier "GET / HTTP/1.1" error: kex_exchange_identification: Connection closed by remote host ''; match = "_SYSTEMD_UNIT = sshd.service"; } { # yodaTux, yodaYoga filters = '' The system will suspend now! System is powering down\. ''; match = "_SYSTEMD_UNIT = systemd-logind.service"; } { # yodaTux filters = '' Reexecuting\. (finished )?switching to system configuration /nix/store/.+-nixos-system-.+-[0-9]+\.[0-9]+pre-git ''; match = "_SYSTEMD_UNIT = user@0.service"; } { # yodaTux filters = '' Reexecuting\. (finished )?switching to system configuration /nix/store/.+-nixos-system-.+-[0-9]+\.[0-9]+pre-git ''; match = "_SYSTEMD_UNIT = user@1000.service"; } { # yodaTux filters = '' Reloading rules Collecting garbage unconditionally\.\.\. Loading rules from directory /.+ Finished loading, compiling and executing [0-9]+ rules ''; match = "_SYSTEMD_UNIT = polkit.service"; } { # yodaTux filters = '' .+ error name="org\.bluez\.MediaEndpoint1\.Error\.NotImplemented" .+ # Open issue: https://github.com/NixOS/nixpkgs/issues/79220 Unknown username .+ in message bus configuration file ''; match = "_SYSTEMD_UNIT = dbus.service"; } { # yodaTux filters = '' Mounted /dev/\S+ at /\S+ on behalf of uid [0-9]+ Cleaning up mount point /\S+ \(device \S+ is not mounted\) Unmounted /dev/\S+ on behalf of uid [0-9]+ Successfully sent SCSI command SYNCHRONIZE CACHE to /dev/\S+ Successfully sent SCSI command START STOP UNIT to /dev/\S+ Powered off /dev/\S+ - successfully wrote to sysfs path /sys/devices/\S+ ''; match = "_SYSTEMD_UNIT = udisks2.service"; } # # SYSLOG_IDENTIFIER # { # yodaTux. If the user `yoda` runs a command with `sudo`. filters = '' \s+yoda : TTY=pts/1 ; PWD=/\S+ ; USER=root ; COMMAND=/.+ \s+yoda : TTY=pts/7 ; PWD=/\S+ ; USER=root ; COMMAND=/.+ ''; match = "SYSLOG_IDENTIFIER = sudo"; } { # yodaYoga filters = '' (finished )?switching to system configuration /nix/store/.+-nixos-system-.+-[0-9]+\.[0-9]+pre-git ''; match = "SYSLOG_IDENTIFIER = nixos"; } { # yodaYoga filters = '' docker\.service: Consumed [0-9]+h [0-9]+min [0-9]+\.[0-9]+s CPU time, read [0-9]+\.[0-9]+M from disk, written [0-9]+\.[0-9]+G to disk, received [0-9]+\.[0-9]+M IP traffic, sent [0-9]+\.[0-9]+M IP traffic\. # Shutting down\. ''; match = "SYSLOG_IDENTIFIER = systemd"; } { # yodaTux filters = '' .* ''; match = "SYSLOG_IDENTIFIER = //nix/store/.+/libexec/gdm-x-session/"; } { # yodaTux filters = '' # Bug. ACPI: FW issue: working around C-state latencies out of order # Kernel WiFi driver bug. #iwlwifi 0000:01:00.0: .* # Ignore. random: crng reseeded on system resumption # Ignore. sd 2:0:0:0: [sda] [0-9]+ 512-byte logical blocks: \([0-9]+ GB/[0-9]+ GiB\) sd 2:0:0:0: [sda] Write Protect is off sd 2:0:0:0: [sda] Write cache: enabled, read cache: enabled, doesn't support DPO or FUA sd 2:0:0:0: [sda] Optimal transfer size [0-9]+ bytes not a multiple of preferred minimum block size (4096 bytes) sd 2:0:0:0: [sda] Attached SCSI disk ''; match = "SYSLOG_IDENTIFIER = kernel"; } { # yodaTux filters = '' .* ''; match = "SYSLOG_IDENTIFIER = simple-scan"; } # # _SYSTEMD_USER_UNIT # { # yodaTux filters = '' .+ Setting AttentionNeeded to FALSE because EnsureCredentials\(\) succeded ''; match = "_SYSTEMD_USER_UNIT = dbus.service"; } { # yodaTux filters = '' .* ''; match = "_SYSTEMD_USER_UNIT = /(org\.gnome\..+\.service|pipewire\.service|wireplumber\.service)/"; } ]; }; }