1{ config, lib, pkgs, ... }:
2
3with lib;
4
5let
6 cfg = config.services.mackerel-agent;
7 settingsFmt = pkgs.formats.toml {};
8in {
9 options.services.mackerel-agent = {
10 enable = mkEnableOption (lib.mdDoc "mackerel.io agent");
11
12 # the upstream package runs as root, but doesn't seem to be strictly
13 # necessary for basic functionality
14 runAsRoot = mkEnableOption (lib.mdDoc "Whether to run as root");
15
16 autoRetirement = mkEnableOption (lib.mdDoc ''
17 Whether to automatically retire the host upon OS shutdown.
18 '');
19
20 apiKeyFile = mkOption {
21 type = types.path;
22 example = "/run/keys/mackerel-api-key";
23 description = lib.mdDoc ''
24 Path to file containing the Mackerel API key. The file should contain a
25 single line of the following form:
26
27 `apikey = "EXAMPLE_API_KEY"`
28 '';
29 };
30
31 settings = mkOption {
32 description = lib.mdDoc ''
33 Options for mackerel-agent.conf.
34
35 Documentation:
36 <https://mackerel.io/docs/entry/spec/agent>
37 '';
38
39 default = {};
40 example = {
41 verbose = false;
42 silent = false;
43 };
44
45 type = types.submodule {
46 freeformType = settingsFmt.type;
47
48 options.host_status = {
49 on_start = mkOption {
50 type = types.enum [ "working" "standby" "maintenance" "poweroff" ];
51 description = lib.mdDoc "Host status after agent startup.";
52 default = "working";
53 };
54 on_stop = mkOption {
55 type = types.enum [ "working" "standby" "maintenance" "poweroff" ];
56 description = lib.mdDoc "Host status after agent shutdown.";
57 default = "poweroff";
58 };
59 };
60
61 options.diagnostic =
62 mkEnableOption (lib.mdDoc "Collect memory usage for the agent itself");
63 };
64 };
65 };
66
67 config = mkIf cfg.enable {
68 environment.systemPackages = with pkgs; [ mackerel-agent ];
69
70 environment.etc = {
71 "mackerel-agent/mackerel-agent.conf".source =
72 settingsFmt.generate "mackerel-agent.conf" cfg.settings;
73 "mackerel-agent/conf.d/api-key.conf".source = cfg.apiKeyFile;
74 };
75
76 services.mackerel-agent.settings = {
77 root = mkDefault "/var/lib/mackerel-agent";
78 pidfile = mkDefault "/run/mackerel-agent/mackerel-agent.pid";
79
80 # conf.d stores the symlink to cfg.apiKeyFile
81 include = mkDefault "/etc/mackerel-agent/conf.d/*.conf";
82 };
83
84 # upstream service file in https://git.io/JUt4Q
85 systemd.services.mackerel-agent = {
86 description = "mackerel.io agent";
87 after = [ "network-online.target" "nss-lookup.target" ];
88 wantedBy = [ "multi-user.target" ];
89 environment = {
90 MACKEREL_PLUGIN_WORKDIR = mkDefault "%C/mackerel-agent";
91 };
92 serviceConfig = {
93 DynamicUser = !cfg.runAsRoot;
94 PrivateTmp = mkDefault true;
95 CacheDirectory = "mackerel-agent";
96 ConfigurationDirectory = "mackerel-agent";
97 RuntimeDirectory = "mackerel-agent";
98 StateDirectory = "mackerel-agent";
99 ExecStart = "${pkgs.mackerel-agent}/bin/mackerel-agent supervise";
100 ExecStopPost = mkIf cfg.autoRetirement "${pkg.mackerel-agent}/bin/mackerel-agent retire -force";
101 ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
102 LimitNOFILE = mkDefault 65536;
103 LimitNPROC = mkDefault 65536;
104 };
105 restartTriggers = [
106 config.environment.etc."mackerel-agent/mackerel-agent.conf".source
107 ];
108 };
109 };
110}