grafana-alloy: don't build the frontend twice
[NixPkgs.git] / nixos / modules / services / monitoring / loki.nix
blob307119ecbf8ba96df60974e47b201817235f4ad9
1 { config, lib, pkgs, ... }:
3 let
4   inherit (lib) escapeShellArgs mkEnableOption mkIf mkOption types;
6   cfg = config.services.loki;
8   prettyJSON = conf:
9     pkgs.runCommand "loki-config.json" { } ''
10       echo '${builtins.toJSON conf}' | ${pkgs.jq}/bin/jq 'del(._module)' > $out
11     '';
13 in {
14   options.services.loki = {
15     enable = mkEnableOption "loki";
17     user = mkOption {
18       type = types.str;
19       default = "loki";
20       description = ''
21         User under which the Loki service runs.
22       '';
23     };
25     package = lib.mkPackageOption pkgs "grafana-loki" { };
27     group = mkOption {
28       type = types.str;
29       default = "loki";
30       description = ''
31         Group under which the Loki service runs.
32       '';
33     };
35     dataDir = mkOption {
36       type = types.path;
37       default = "/var/lib/loki";
38       description = ''
39         Specify the directory for Loki.
40       '';
41     };
43     configuration = mkOption {
44       type = (pkgs.formats.json {}).type;
45       default = {};
46       description = ''
47         Specify the configuration for Loki in Nix.
48       '';
49     };
51     configFile = mkOption {
52       type = types.nullOr types.path;
53       default = null;
54       description = ''
55         Specify a configuration file that Loki should use.
56       '';
57     };
59     extraFlags = mkOption {
60       type = types.listOf types.str;
61       default = [];
62       example = [ "--server.http-listen-port=3101" ];
63       description = ''
64         Specify a list of additional command line flags,
65         which get escaped and are then passed to Loki.
66       '';
67     };
68   };
70   config = mkIf cfg.enable {
71     assertions = [{
72       assertion = (
73         (cfg.configuration == {} -> cfg.configFile != null) &&
74         (cfg.configFile != null -> cfg.configuration == {})
75       );
76       message  = ''
77         Please specify either
78         'services.loki.configuration' or
79         'services.loki.configFile'.
80       '';
81     }];
83     environment.systemPackages = [ cfg.package ]; # logcli
85     users.groups.${cfg.group} = { };
86     users.users.${cfg.user} = {
87       description = "Loki Service User";
88       group = cfg.group;
89       home = cfg.dataDir;
90       createHome = true;
91       isSystemUser = true;
92     };
94     systemd.services.loki = {
95       description = "Loki Service Daemon";
96       wantedBy = [ "multi-user.target" ];
97       after = [ "network.target" ];
99       serviceConfig = let
100         conf = if cfg.configFile == null
101                then
102                  # Config validation may fail when using extraFlags = [ "-config.expand-env=true" ].
103                  # To work around this, we simply skip it when extraFlags is not empty.
104                  if cfg.extraFlags == []
105                  then validateConfig (prettyJSON cfg.configuration)
106                  else prettyJSON cfg.configuration
107                else cfg.configFile;
108         validateConfig = file:
109         pkgs.runCommand "validate-loki-conf" {
110           nativeBuildInputs = [ cfg.package ];
111         } ''
112             loki -verify-config -config.file "${file}"
113             ln -s "${file}" "$out"
114           '';
115       in
116       {
117         ExecStart = "${cfg.package}/bin/loki --config.file=${conf} ${escapeShellArgs cfg.extraFlags}";
118         User = cfg.user;
119         Restart = "always";
120         PrivateTmp = true;
121         ProtectHome = true;
122         ProtectSystem = "full";
123         DevicePolicy = "closed";
124         NoNewPrivileges = true;
125         WorkingDirectory = cfg.dataDir;
126       };
127     };
128   };