{ config, lib, this, ... }: with lib; let cfg = config.nixfiles.modules.promtail; in { options.nixfiles.modules.promtail = { enable = mkEnableOption "Promtail"; port = mkOption { description = "Port."; type = with types; port; default = 30181; }; loki.url = mkOption { description = "Address of a listening Loki service."; type = with types; str; default = "https://${config.nixfiles.modules.loki.domain}"; }; filters = mkOption { description = ''Filters to use with "scrape_config.pipeline_stages".''; type = with types; listOf attrs; default = [ ]; }; }; config = mkIf cfg.enable { services.promtail = { enable = true; configuration = { server = rec { http_listen_address = this.wireguard.ipv4.address; http_listen_port = cfg.port; grpc_listen_address = this.wireguard.ipv4.address; grpc_listen_port = http_listen_port + 1; log_level = "warn"; }; clients = [ { url = "${cfg.loki.url}/loki/api/v1/push"; batchwait = "30s"; batchsize = 100000; external_labels.host_id = config.networking.hostId; } ]; positions = { filename = "/tmp/positions.yaml"; sync_period = "30s"; ignore_invalid_yaml = true; }; scrape_configs = [ { job_name = "journal"; journal.max_age = "24h"; relabel_configs = map ( n: let label = toLower n; in { source_labels = [ "__journal_${label}" ]; target_label = if hasPrefix "_" label then substring 1 (stringLength label - 1) label else label; } ) [ # Derived from systemd.journal fields[1]. # # [1]: https://github.com/coreos/go-systemd/blob/main/sdjournal/journal.go#L335 # [1]: https://www.freedesktop.org/software/systemd/man/systemd.journal-fields.html "MESSAGE" # "MESSAGE_ID" "PRIORITY" # "CODE_FILE" # "CODE_LINE" # "CODE_FUNC" # "ERRNO" "SYSLOG_FACILITY" "SYSLOG_IDENTIFIER" # "SYSLOG_PID" # "_PID" # "_UID" # "_GID" # "_COMM" # "_EXE" "_CMDLINE" # "_CAP_EFFECTIVE" # "_AUDIT_SESSION" # "_AUDIT_LOGINUID" # "_SYSTEMD_CGROUP" # "_SYSTEMD_SESSION" # "_SYSTEMD_UNIT" # "_SYSTEMD_USER_UNIT" # "_SYSTEMD_OWNER_UID" # "_SYSTEMD_SLICE" # "_SELINUX_CONTEXT" # "_SOURCE_REALTIME_TIMESTAMP" # "_BOOT_ID" # "_MACHINE_ID" "_HOSTNAME" # "_TRANSPORT" # "__CURSOR" # "__REALTIME_TIMESTAMP" # "__MONOTONIC_TIMESTAMP" ] ++ [ { # This is weird. I can't find where is this defined in the # source code but apparently it exists. source_labels = [ "__journal_priority_keyword" ]; target_label = "level"; } ]; pipeline_stages = cfg.filters; } ]; }; }; }; }