diff options
Diffstat (limited to 'nixpkgs/nixos/modules/services/monitoring')
5 files changed, 350 insertions, 5 deletions
diff --git a/nixpkgs/nixos/modules/services/monitoring/certspotter.md b/nixpkgs/nixos/modules/services/monitoring/certspotter.md new file mode 100644 index 000000000000..9bf6e1d946a0 --- /dev/null +++ b/nixpkgs/nixos/modules/services/monitoring/certspotter.md @@ -0,0 +1,74 @@ +# Cert Spotter {#module-services-certspotter} + +Cert Spotter is a tool for monitoring [Certificate Transparency](https://en.wikipedia.org/wiki/Certificate_Transparency) +logs. + +## Service Configuration {#modules-services-certspotter-service-configuration} + +A basic config that notifies you of all certificate changes for your +domain would look as follows: + +```nix +services.certspotter = { + enable = true; + # replace example.org with your domain name + watchlist = [ ".example.org" ]; + emailRecipients = [ "webmaster@example.org" ]; +}; + +# Configure an SMTP client +programs.msmtp.enable = true; +# Or you can use any other module that provides sendmail, like +# services.nullmailer, services.opensmtpd, services.postfix +``` + +In this case, the leading dot in `".example.org"` means that Cert +Spotter should monitor not only `example.org`, but also all of its +subdomains. + +## Operation {#modules-services-certspotter-operation} + +**By default, NixOS configures Cert Spotter to skip all certificates +issued before its first launch**, because checking the entire +Certificate Transparency logs requires downloading tens of terabytes of +data. If you want to check the *entire* logs for previously issued +certificates, you have to set `services.certspotter.startAtEnd` to +`false` and remove all previously saved log state in +`/var/lib/certspotter/logs`. The downloaded logs aren't saved, so if you +add a new domain to the watchlist and want Cert Spotter to go through +the logs again, you will have to remove `/var/lib/certspotter/logs` +again. + +After catching up with the logs, Cert Spotter will start monitoring live +logs. As of October 2023, it uses around **20 Mbps** of traffic on +average. + +## Hooks {#modules-services-certspotter-hooks} + +Cert Spotter supports running custom hooks instead of (or in addition +to) sending emails. Hooks are shell scripts that will be passed certain +environment variables. + +To see hook documentation, see Cert Spotter's man pages: + +```ShellSession +nix-shell -p certspotter --run 'man 8 certspotter-script' +``` + +For example, you can remove `emailRecipients` and send email +notifications manually using the following hook: + +```nix +services.certspotter.hooks = [ + (pkgs.writeShellScript "certspotter-hook" '' + function print_email() { + echo "Subject: [certspotter] $SUMMARY" + echo "Mime-Version: 1.0" + echo "Content-Type: text/plain; charset=US-ASCII" + echo + cat "$TEXT_FILENAME" + } + print_email | ${config.services.certspotter.sendmailPath} -i webmaster@example.org + '') +]; +``` diff --git a/nixpkgs/nixos/modules/services/monitoring/certspotter.nix b/nixpkgs/nixos/modules/services/monitoring/certspotter.nix new file mode 100644 index 000000000000..aafa29daa872 --- /dev/null +++ b/nixpkgs/nixos/modules/services/monitoring/certspotter.nix @@ -0,0 +1,143 @@ +{ config +, lib +, pkgs +, ... }: + +let + cfg = config.services.certspotter; + + configDir = pkgs.linkFarm "certspotter-config" ( + lib.toList { + name = "watchlist"; + path = pkgs.writeText "certspotter-watchlist" (builtins.concatStringsSep "\n" cfg.watchlist); + } + ++ lib.optional (cfg.emailRecipients != [ ]) { + name = "email_recipients"; + path = pkgs.writeText "certspotter-email_recipients" (builtins.concatStringsSep "\n" cfg.emailRecipients); + } + # always generate hooks dir when no emails are provided to allow running cert spotter with no hooks/emails + ++ lib.optional (cfg.emailRecipients == [ ] || cfg.hooks != [ ]) { + name = "hooks.d"; + path = pkgs.linkFarm "certspotter-hooks" (lib.imap1 (i: path: { + inherit path; + name = "hook${toString i}"; + }) cfg.hooks); + }); +in +{ + options.services.certspotter = { + enable = lib.mkEnableOption "Cert Spotter, a Certificate Transparency log monitor"; + + package = lib.mkPackageOptionMD pkgs "certspotter" { }; + + startAtEnd = lib.mkOption { + type = lib.types.bool; + description = '' + Whether to skip certificates issued before the first launch of Cert Spotter. + Setting this to `false` will cause Cert Spotter to download tens of terabytes of data. + ''; + default = true; + }; + + sendmailPath = lib.mkOption { + type = with lib.types; nullOr path; + description = '' + Path to the `sendmail` binary. By default, the local sendmail wrapper is used + (see {option}`services.mail.sendmailSetuidWrapper`}). + ''; + example = lib.literalExpression ''"''${pkgs.system-sendmail}/bin/sendmail"''; + }; + + watchlist = lib.mkOption { + type = with lib.types; listOf str; + description = "Domain names to watch. To monitor a domain with all subdomains, prefix its name with `.` (e.g. `.example.org`)."; + default = [ ]; + example = [ ".example.org" "another.example.com" ]; + }; + + emailRecipients = lib.mkOption { + type = with lib.types; listOf str; + description = "A list of email addresses to send certificate updates to."; + default = [ ]; + }; + + hooks = lib.mkOption { + type = with lib.types; listOf path; + description = '' + Scripts to run upon the detection of a new certificate. See `man 8 certspotter-script` or + [the GitHub page](https://github.com/SSLMate/certspotter/blob/${pkgs.certspotter.src.rev or "master"}/man/certspotter-script.md) + for more info. + ''; + default = [ ]; + example = lib.literalExpression '' + [ + (pkgs.writeShellScript "certspotter-hook" ''' + echo "Event summary: $SUMMARY." + ''') + ] + ''; + }; + + extraFlags = lib.mkOption { + type = with lib.types; listOf str; + description = "Extra command-line arguments to pass to Cert Spotter"; + example = [ "-no_save" ]; + default = [ ]; + }; + }; + + config = lib.mkIf cfg.enable { + assertions = [ + { + assertion = (cfg.emailRecipients != [ ]) -> (cfg.sendmailPath != null); + message = '' + You must configure the sendmail setuid wrapper (services.mail.sendmailSetuidWrapper) + or services.certspotter.sendmailPath + ''; + } + ]; + + services.certspotter.sendmailPath = let + inherit (config.security) wrapperDir; + inherit (config.services.mail) sendmailSetuidWrapper; + in lib.mkMerge [ + (lib.mkIf (sendmailSetuidWrapper != null) (lib.mkOptionDefault "${wrapperDir}/${sendmailSetuidWrapper.program}")) + (lib.mkIf (sendmailSetuidWrapper == null) (lib.mkOptionDefault null)) + ]; + + users.users.certspotter = { + description = "Cert Spotter user"; + group = "certspotter"; + home = "/var/lib/certspotter"; + isSystemUser = true; + }; + users.groups.certspotter = { }; + + systemd.services.certspotter = { + description = "Cert Spotter - Certificate Transparency Monitor"; + after = [ "network.target" ]; + wantedBy = [ "multi-user.target" ]; + environment.CERTSPOTTER_CONFIG_DIR = configDir; + environment.SENDMAIL_PATH = if cfg.sendmailPath != null then cfg.sendmailPath else "/run/current-system/sw/bin/false"; + script = '' + export CERTSPOTTER_STATE_DIR="$STATE_DIRECTORY" + cd "$CERTSPOTTER_STATE_DIR" + ${lib.optionalString cfg.startAtEnd '' + if [[ ! -d logs ]]; then + # Don't download certificates issued before the first launch + exec ${cfg.package}/bin/certspotter -start_at_end ${lib.escapeShellArgs cfg.extraFlags} + fi + ''} + exec ${cfg.package}/bin/certspotter ${lib.escapeShellArgs cfg.extraFlags} + ''; + serviceConfig = { + User = "certspotter"; + Group = "certspotter"; + StateDirectory = "certspotter"; + }; + }; + }; + + meta.maintainers = with lib.maintainers; [ chayleaf ]; + meta.doc = ./certspotter.md; +} diff --git a/nixpkgs/nixos/modules/services/monitoring/goss.md b/nixpkgs/nixos/modules/services/monitoring/goss.md new file mode 100644 index 000000000000..1e636aa3bdf3 --- /dev/null +++ b/nixpkgs/nixos/modules/services/monitoring/goss.md @@ -0,0 +1,44 @@ +# Goss {#module-services-goss} + +[goss](https://goss.rocks/) is a YAML based serverspec alternative tool +for validating a server's configuration. + +## Basic Usage {#module-services-goss-basic-usage} + +A minimal configuration looks like this: + +``` +{ + services.goss = { + enable = true; + + environment = { + GOSS_FMT = "json"; + GOSS_LOGLEVEL = "TRACE"; + }; + + settings = { + addr."tcp://localhost:8080" = { + reachable = true; + local-address = "127.0.0.1"; + }; + command."check-goss-version" = { + exec = "${lib.getExe pkgs.goss} --version"; + exit-status = 0; + }; + dns.localhost.resolvable = true; + file."/nix" = { + filetype = "directory"; + exists = true; + }; + group.root.exists = true; + kernel-param."kernel.ostype".value = "Linux"; + service.goss = { + enabled = true; + running = true; + }; + user.root.exists = true; + }; + }; +} +``` diff --git a/nixpkgs/nixos/modules/services/monitoring/goss.nix b/nixpkgs/nixos/modules/services/monitoring/goss.nix new file mode 100644 index 000000000000..64a8dad0703e --- /dev/null +++ b/nixpkgs/nixos/modules/services/monitoring/goss.nix @@ -0,0 +1,86 @@ +{ config, lib, pkgs, ... }: + +let + cfg = config.services.goss; + + settingsFormat = pkgs.formats.yaml { }; + configFile = settingsFormat.generate "goss.yaml" cfg.settings; + +in { + meta = { + doc = ./goss.md; + maintainers = [ lib.maintainers.anthonyroussel ]; + }; + + options = { + services.goss = { + enable = lib.mkEnableOption (lib.mdDoc "Goss daemon"); + + package = lib.mkPackageOptionMD pkgs "goss" { }; + + environment = lib.mkOption { + type = lib.types.attrsOf lib.types.str; + default = { }; + example = { + GOSS_FMT = "json"; + GOSS_LOGLEVEL = "FATAL"; + GOSS_LISTEN = ":8080"; + }; + description = lib.mdDoc '' + Environment variables to set for the goss service. + + See <https://github.com/goss-org/goss/blob/master/docs/manual.md> + ''; + }; + + settings = lib.mkOption { + type = lib.types.submodule { freeformType = settingsFormat.type; }; + default = { }; + example = { + addr."tcp://localhost:8080" = { + reachable = true; + local-address = "127.0.0.1"; + }; + service.goss = { + enabled = true; + running = true; + }; + }; + description = lib.mdDoc '' + The global options in `config` file in yaml format. + + Refer to <https://github.com/goss-org/goss/blob/master/docs/goss-json-schema.yaml> for schema. + ''; + }; + }; + }; + + config = lib.mkIf cfg.enable { + environment.systemPackages = [ cfg.package ]; + + systemd.services.goss = { + description = "Goss - Quick and Easy server validation"; + unitConfig.Documentation = "https://github.com/goss-org/goss/blob/master/docs/manual.md"; + + after = [ "network-online.target" ]; + wantedBy = [ "multi-user.target" ]; + wants = [ "network-online.target" ]; + + environment = { + GOSS_FILE = configFile; + } // cfg.environment; + + reloadTriggers = [ configFile ]; + + serviceConfig = { + DynamicUser = true; + ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID"; + ExecStart = "${cfg.package}/bin/goss serve"; + Group = "goss"; + Restart = "on-failure"; + RestartSec = 5; + User = "goss"; + }; + }; + }; +} diff --git a/nixpkgs/nixos/modules/services/monitoring/ups.nix b/nixpkgs/nixos/modules/services/monitoring/ups.nix index bb11b6a1c1d0..efef2d777acd 100644 --- a/nixpkgs/nixos/modules/services/monitoring/ups.nix +++ b/nixpkgs/nixos/modules/services/monitoring/ups.nix @@ -239,11 +239,9 @@ in power.ups.schedulerRules = mkDefault "${pkgs.nut}/etc/upssched.conf.sample"; - system.activationScripts.upsSetup = stringAfter [ "users" "groups" ] - '' - # Used to store pid files of drivers. - mkdir -p /var/state/ups - ''; + systemd.tmpfiles.rules = [ + "d /var/state/ups -" + ]; /* |