diff --git a/flake.nix b/flake.nix index 576a6bc..7bb160d 100644 --- a/flake.nix +++ b/flake.nix @@ -41,8 +41,7 @@ flake-utils, stockholm, ... - }: let - in + }: { apps = nixinate.nixinate.x86_64-linux self; @@ -50,6 +49,7 @@ moodle-dl = import modules/moodle-dl.nix; networkmanager-declarative = import modules/networkmanager-declarative.nix; passport = import modules/passport.nix; + panoptikon = import modules/panoptikon.nix; system-dependent = import modules/system-dependent.nix; telegram-bot = import modules/telegram-bot.nix; traadfri = import modules/traadfri.nix; @@ -75,7 +75,9 @@ systems/ful/configuration.nix agenix.nixosModules.default inputs.self.nixosModules.passport + inputs.self.nixosModules.panoptikon retiolum.nixosModules.retiolum + nur.nixosModules.nur ]; }; zaatar = nixpkgs.lib.nixosSystem rec { diff --git a/modules/panoptikon.nix b/modules/panoptikon.nix new file mode 100644 index 0000000..ae82261 --- /dev/null +++ b/modules/panoptikon.nix @@ -0,0 +1,101 @@ +{ + config, + lib, + pkgs, + ... +}: { + options.services.panoptikon = { + enable = lib.mkEnableOption "Generic command output / website watcher"; + watchers = lib.mkOption { + type = lib.types.attrsOf (lib.types.submodule (watcher: { + options = { + script = lib.mkOption { + type = lib.types.path; + description = '' + A script whose stdout is to be watched. + ''; + example = '' + pkgs.writers.writeDash "github-meta" ''' + ''${pkgs.curl}/bin/curl -sSL https://api.github.com/meta | ''${pkgs.jq}/bin/jq + ''' + ''; + }; + frequency = lib.mkOption { + type = lib.types.str; + description = '' + How often to run the script. See systemd.time(7) for more information about the format. + ''; + example = "*:0/3"; + default = "daily"; + }; + reporters = lib.mkOption { + type = lib.types.listOf lib.types.path; + description = '' + A list of scripts that take the diff (if any) via stdin and report it (e.g. to IRC, Telegram or Prometheus). The name of the watcher will be in the $PANOPTIKON_WATCHER environment variable. + ''; + example = '' + [ + (pkgs.writers.writeDash "telegram-reporter" ''' + ''${pkgs.curl}/bin/curl -X POST https://api.telegram.org/bot''${TOKEN}/sendMessage \ + -d chat_id=123456 \ + -d text="$(cat)" + ''') + (pkgs.writers.writeDash "notify" ''' + ''${pkgs.libnotify}/bin/notify-send "$PANOPTIKON_WATCHER has changed." + ''') + ] + ''; + }; + }; + config = {}; + })); + }; + }; + + config = let + cfg = config.services.panoptikon; + in + lib.mkIf cfg.enable { + users.extraUsers.panoptikon = { + isSystemUser = true; + createHome = true; + home = "/var/lib/panoptikon"; + group = "panoptikon"; + }; + + users.extraGroups.panoptikon = {}; + + systemd.services = lib.attrsets.mapAttrs' (watcherName: watcherOptions: + lib.nameValuePair "panoptikon-${watcherName}" { + enable = true; + startAt = watcherOptions.frequency; + serviceConfig = { + Type = "oneshot"; + User = "panoptikon"; + Group = "panoptikon"; + WorkingDirectory = "/var/lib/panoptikon"; + }; + environment.PANOPTIKON_WATCHER = watcherName; + wants = ["network-online.target"]; + script = '' + set -efux + + ${pkgs.git}/bin/git init --quiet + ${pkgs.git}/bin/git config user.email "panoptikon@${config.networking.hostName}" + ${pkgs.git}/bin/git config user.name Panoptikon + + ${watcherOptions.script} > ${watcherName} + ${pkgs.git}/bin/git add ${watcherName} + ${pkgs.git}/bin/git commit --message "$(${pkgs.coreutils}/bin/date -Is)" || : + + if [ -n "$(${pkgs.git}/bin/git diff HEAD^ -- ${watcherName})" ]; then + ${lib.strings.concatMapStringsSep "\n" (reporter: '' + ${pkgs.git}/bin/git diff HEAD^ -- ${watcherName} | ${reporter} + '') + watcherOptions.reporters} + fi + ''; + }) + cfg.watchers; + }; +} diff --git a/systems/ful/configuration.nix b/systems/ful/configuration.nix index 91047f7..7cf9e17 100644 --- a/systems/ful/configuration.nix +++ b/systems/ful/configuration.nix @@ -10,6 +10,7 @@ in { ./hardware-configuration.nix ./matomo.nix ./radio.nix + ./panoptikon.nix ../../configs/monitoring.nix ../../configs/tor.nix ../../configs/save-space.nix diff --git a/systems/ful/panoptikon.nix b/systems/ful/panoptikon.nix new file mode 100644 index 0000000..d37b694 --- /dev/null +++ b/systems/ful/panoptikon.nix @@ -0,0 +1,41 @@ +{ + config, + pkgs, + lib, + ... +}: let + kpaste = pkgs.writers.writeDash "kpaste" '' + ${pkgs.curl}/bin/curl -sS -sS http://p.r --data-binary @"''${1:--}" | ${pkgs.gnused}/bin/sed '$ {p;s|http://p.r|https://p.krebsco.de|}' + ''; + + url = address: + pkgs.writers.writeDash "watch-url" '' + ${pkgs.w3m}/bin/w3m -dump ${lib.escapeShellArg address} + ''; + + urlJSON = address: + pkgs.writers.writeDash "watch-url-json" '' + ${pkgs.curl}/bin/curl -sSL ${lib.escapeShellArg address} | ${pkgs.jq}/bin/jq + ''; + + reporters.irc-xxx = pkgs.writers.writeDash "irc-xxx" '' + ${kpaste} \ + | ${pkgs.gnused}/bin/sed -n '2s/^/change detected: /p' \ + | ${config.nur.repos.mic92.ircsink}/bin/ircsink \ + --nick "$PANOPTIKON_WATCHER"-watcher \ + --server irc.r \ + --target '#xxx' + ''; +in { + services.panoptikon = { + enable = true; + watchers."github-meta" = { + script = urlJSON "https://api.github.com/meta"; + reporters = [reporters.irc-xxx]; + }; + watchers.spiegel = { + script = url "https://www.spiegel.de/"; + reporters = []; + }; + }; +}