1 { config, lib, pkgs, ... }:
3 cfg = config.services.datadog-agent;
6 skip_ssl_validation = false;
7 confd_path = "/etc/datadog-agent/conf.d";
8 additional_checksd = "/etc/datadog-agent/checks.d";
11 // lib.optionalAttrs (cfg.logLevel != null) { log_level = cfg.logLevel; }
12 // lib.optionalAttrs (cfg.hostname != null) { inherit (cfg) hostname; }
13 // lib.optionalAttrs (cfg.ddUrl != null) { dd_url = cfg.ddUrl; }
14 // lib.optionalAttrs (cfg.site != null) { site = cfg.site; }
15 // lib.optionalAttrs (cfg.tags != null ) { tags = lib.concatStringsSep ", " cfg.tags; }
16 // lib.optionalAttrs (cfg.enableLiveProcessCollection) {
18 dd_agent_bin = "${datadogPkg}/bin/agent";
19 process_collection.enabled = "true";
20 container_collection.enabled = "true";
23 // lib.optionalAttrs (cfg.enableTraceAgent) { apm_config = { enabled = true; }; }
26 # Generate Datadog configuration files for each configured checks.
27 # This works because check configurations have predictable paths,
28 # and because JSON is a valid subset of YAML.
29 makeCheckConfigs = entries: lib.mapAttrs' (name: conf: {
30 name = "datadog-agent/conf.d/${name}.d/conf.yaml";
31 value.source = pkgs.writeText "${name}-check-conf.yaml" (builtins.toJSON conf);
36 network = cfg.networkCheck;
39 # Assemble all check configurations and the top-level agent
41 etcfiles = with pkgs; with builtins;
42 { "datadog-agent/datadog.yaml" = {
43 source = writeText "datadog.yaml" (toJSON ddConf);
45 } // makeCheckConfigs (cfg.checks // defaultChecks);
47 # Apply the configured extraIntegrations to the provided agent
48 # package. See the documentation of `dd-agent/integrations-core.nix`
49 # for detailed information on this.
50 datadogPkg = cfg.package.override {
51 pythonPackages = pkgs.datadog-integrations-core cfg.extraIntegrations;
54 options.services.datadog-agent = {
55 enable = lib.mkEnableOption "Datadog-agent v7 monitoring service";
57 package = lib.mkPackageOption pkgs "datadog-agent" {
60 The provided package is expected to have an overridable `pythonPackages`-attribute
61 which configures the Python environment with the Datadog checks.
66 apiKeyFile = lib.mkOption {
68 Path to a file containing the Datadog API key to associate the
69 agent with your account.
71 example = "/run/keys/datadog_api_key";
72 type = lib.types.path;
75 ddUrl = lib.mkOption {
77 Custom dd_url to configure the agent with. Useful if traffic to datadog
78 needs to go through a proxy.
79 Don't use this to point to another datadog site (EU) - use site instead.
82 example = "http://haproxy.example.com:3834";
83 type = lib.types.nullOr lib.types.str;
88 The datadog site to point the agent towards.
89 Set to datadoghq.eu to point it to their EU site.
92 example = "datadoghq.eu";
93 type = lib.types.nullOr lib.types.str;
97 description = "The tags to mark this Datadog agent";
98 example = [ "test" "service" ];
100 type = lib.types.nullOr (lib.types.listOf lib.types.str);
103 hostname = lib.mkOption {
104 description = "The hostname to show in the Datadog dashboard (optional)";
106 example = "mymachine.mydomain";
107 type = lib.types.nullOr lib.types.str;
110 logLevel = lib.mkOption {
111 description = "Logging verbosity.";
113 type = lib.types.nullOr (lib.types.enum ["DEBUG" "INFO" "WARN" "ERROR"]);
116 extraIntegrations = lib.mkOption {
118 type = lib.types.attrs;
121 Extra integrations from the Datadog core-integrations
122 repository that should be built and included.
124 By default the included integrations are disk, mongo, network,
127 To include additional integrations the name of the derivation
128 and a function to filter its dependencies from the Python
129 package set must be provided.
132 example = lib.literalExpression ''
134 ntp = pythonPackages: [ pythonPackages.ntplib ];
139 extraConfig = lib.mkOption {
141 type = lib.types.attrs;
143 Extra configuration options that will be merged into the
144 main config file {file}`datadog.yaml`.
148 enableLiveProcessCollection = lib.mkOption {
150 Whether to enable the live process collection agent.
153 type = lib.types.bool;
156 processAgentPackage = lib.mkOption {
157 default = pkgs.datadog-process-agent;
158 defaultText = lib.literalExpression "pkgs.datadog-process-agent";
160 Which DataDog v7 agent package to use. Note that the provided
161 package is expected to have an overridable `pythonPackages`-attribute
162 which configures the Python environment with the Datadog
165 type = lib.types.package;
168 enableTraceAgent = lib.mkOption {
170 Whether to enable the trace agent.
173 type = lib.types.bool;
176 checks = lib.mkOption {
178 Configuration for all Datadog checks. Keys of this attribute
179 set will be used as the name of the check to create the
180 appropriate configuration in `conf.d/$check.d/conf.yaml`.
182 The configuration is converted into JSON from the plain Nix
183 language configuration, meaning that you should write
184 configuration adhering to Datadog's documentation - but in Nix
187 Refer to the implementation of this module (specifically the
188 definition of `defaultChecks`) for an example.
190 Note: The 'disk' and 'network' check are configured in
191 separate options because they exist by default. Attempting to
192 override their configuration here will have no effect.
197 init_config = null; # sic!
200 name = "some-service";
201 url = "http://localhost:1337/healthz";
202 tags = [ "some-service" ];
210 # sic! The structure of the values is up to the check, so we can
211 # not usefully constrain the type further.
212 type = with lib.types; attrsOf attrs;
215 diskCheck = lib.mkOption {
216 description = "Disk check config";
217 type = lib.types.attrs;
220 instances = [ { use_mount = "false"; } ];
224 networkCheck = lib.mkOption {
225 description = "Network check config";
226 type = lib.types.attrs;
229 # Network check only supports one configured instance
230 instances = [ { collect_connection_state = false;
231 excluded_interfaces = [ "lo" "lo0" ]; } ];
235 config = lib.mkIf cfg.enable {
236 environment.systemPackages = [ datadogPkg pkgs.sysstat pkgs.procps pkgs.iproute2 ];
238 users.users.datadog = {
239 description = "Datadog Agent User";
240 uid = config.ids.uids.datadog;
242 home = "/var/log/datadog/";
246 users.groups.datadog.gid = config.ids.gids.datadog;
248 systemd.services = let
249 makeService = attrs: lib.recursiveUpdate {
250 path = [ datadogPkg pkgs.sysstat pkgs.procps pkgs.iproute2 ];
251 wantedBy = [ "multi-user.target" ];
258 restartTriggers = [ datadogPkg ] ++ map (x: x.source) (lib.attrValues etcfiles);
261 datadog-agent = makeService {
262 description = "Datadog agent monitor";
264 chown -R datadog: /etc/datadog-agent
265 rm -f /etc/datadog-agent/auth_token
268 export DD_API_KEY=$(head -n 1 ${cfg.apiKeyFile})
269 exec ${datadogPkg}/bin/agent run -c /etc/datadog-agent/datadog.yaml
271 serviceConfig.PermissionsStartOnly = true;
274 dd-jmxfetch = lib.mkIf (lib.hasAttr "jmx" cfg.checks) (makeService {
275 description = "Datadog JMX Fetcher";
276 path = [ datadogPkg pkgs.python pkgs.sysstat pkgs.procps pkgs.jdk ];
277 serviceConfig.ExecStart = "${datadogPkg}/bin/dd-jmxfetch";
280 datadog-process-agent = lib.mkIf cfg.enableLiveProcessCollection (makeService {
281 description = "Datadog Live Process Agent";
284 export DD_API_KEY=$(head -n 1 ${cfg.apiKeyFile})
285 ${cfg.processAgentPackage}/bin/process-agent --config /etc/datadog-agent/datadog.yaml
289 datadog-trace-agent = lib.mkIf cfg.enableTraceAgent (makeService {
290 description = "Datadog Trace Agent";
293 export DD_API_KEY=$(head -n 1 ${cfg.apiKeyFile})
294 ${datadogPkg}/bin/trace-agent --config /etc/datadog-agent/datadog.yaml
300 environment.etc = etcfiles;