@ -4,8 +4,11 @@ with lib;
let
cfg = config . services . prometheus ;
cfg2 = config . services . prometheus2 ;
promUser = " p r o m e t h e u s " ;
promGroup = " p r o m e t h e u s " ;
prom2User = " p r o m e t h e u s 2 " ;
prom2Group = " p r o m e t h e u s 2 " ;
# Get a submodule without any embedded metadata:
_filter = x : filterAttrs ( k : v : k != " _ m o d u l e " ) x ;
@ -17,13 +20,21 @@ let
promtool $ { what } $ out
'' ;
# a wrapper that verifies that the configuration is valid for
# prometheus 2
prom2toolCheck = what : name : file : pkgs . runCommand " ${ name } - ${ what } - c h e c k e d "
{ buildInputs = [ cfg2 . package ] ; } ''
ln - s $ { file } $ out
promtool $ { what } $ out
'' ;
# Pretty-print JSON to a file
writePrettyJSON = name : x :
pkgs . runCommand name { preferLocalBuild = true ; } ''
echo ' $ { builtins . toJSON x } ' | $ { pkgs . jq } /bin/jq . > $ out
'' ;
# This becomes the main config file
# This becomes the main config file for Prometheus 1
promConfig = {
global = cfg . globalConfig ;
rule_files = map ( promtoolCheck " c h e c k - r u l e s " " r u l e s " ) ( cfg . ruleFiles ++ [
@ -35,7 +46,7 @@ let
generatedPrometheusYml = writePrettyJSON " p r o m e t h e u s . y m l " promConfig ;
prometheusYml = let
yml = if cfg . configText != null then
yml = if cfg . configText != null then
pkgs . writeText " p r o m e t h e u s . y m l " cfg . configText
else generatedPrometheusYml ;
in promtoolCheck " c h e c k - c o n f i g " " p r o m e t h e u s . y m l " yml ;
@ -50,6 +61,39 @@ let
( optionalString ( cfg . webExternalUrl != null ) " - w e b . e x t e r n a l - u r l = ${ cfg . webExternalUrl } " )
] ;
# This becomes the main config file for Prometheus 2
promConfig2 = {
global = cfg2 . globalConfig ;
rule_files = map ( prom2toolCheck " c h e c k - r u l e s " " r u l e s " ) ( cfg2 . ruleFiles ++ [
( pkgs . writeText " p r o m e t h e u s . r u l e s " ( concatStringsSep " \n " cfg2 . rules ) )
] ) ;
scrape_configs = cfg2 . scrapeConfigs ;
alerting = optionalAttrs ( cfg2 . alertmanagerURL != [ ] ) {
alertmanagers = [ {
static_configs = [ {
targets = cfg2 . alertmanagerURL ;
} ] ;
} ] ;
} ;
} ;
generatedPrometheus2Yml = writePrettyJSON " p r o m e t h e u s . y m l " promConfig2 ;
prometheus2Yml = let
yml = if cfg2 . configText != null then
pkgs . writeText " p r o m e t h e u s . y m l " cfg2 . configText
else generatedPrometheus2Yml ;
in promtoo2lCheck " c h e c k - c o n f i g " " p r o m e t h e u s . y m l " yml ;
cmdlineArgs2 = cfg2 . extraFlags ++ [
" - - s t o r a g e . t s d b . p a t h = ${ cfg2 . dataDir } / d a t a / "
" - - c o n f i g . f i l e = ${ prometheus2Yml } "
" - - w e b . l i s t e n - a d d r e s s = ${ cfg2 . listenAddress } "
" - - a l e r t m a n a g e r . n o t i f i c a t i o n - q u e u e - c a p a c i t y = ${ toString cfg2 . alertmanagerNotificationQueueCapacity } "
" - - a l e r t m a n a g e r . t i m e o u t = ${ toString cfg2 . alertmanagerTimeout } s "
( optionalString ( cfg2 . webExternalUrl != null ) " - w e b . e x t e r n a l - u r l = ${ cfg2 . webExternalUrl } " )
] ;
promTypes . globalConfig = types . submodule {
options = {
scrape_interval = mkOption {
@ -497,30 +541,178 @@ in {
'' ;
} ;
} ;
} ;
services . prometheus2 = {
config = mkIf cfg . enable {
users . groups . ${ promGroup } . gid = config . ids . gids . prometheus ;
users . users . ${ promUser } = {
description = " P r o m e t h e u s d a e m o n u s e r " ;
uid = config . ids . uids . prometheus ;
group = promGroup ;
home = cfg . dataDir ;
createHome = true ;
} ;
systemd . services . prometheus = {
wantedBy = [ " m u l t i - u s e r . t a r g e t " ] ;
after = [ " n e t w o r k . t a r g e t " ] ;
script = ''
#!/bin/sh
exec $ { cfg . package } /bin/prometheus \
$ { concatStringsSep " \\ \n " cmdlineArgs }
'' ;
serviceConfig = {
User = promUser ;
Restart = " a l w a y s " ;
WorkingDirectory = cfg . dataDir ;
enable = mkOption {
type = types . bool ;
default = false ;
description = ''
Enable the Prometheus 2 monitoring daemon .
'' ;
} ;
package = mkOption {
type = types . package ;
default = pkgs . prometheus_2 ;
defaultText = " p k g s . p r o m e t h e u s _ 2 " ;
description = ''
The prometheus2 package that should be used .
'' ;
} ;
listenAddress = mkOption {
type = types . str ;
default = " 0 . 0 . 0 . 0 : 9 0 9 0 " ;
description = ''
Address to listen on for the web interface , API , and telemetry .
'' ;
} ;
dataDir = mkOption {
type = types . path ;
default = " / v a r / l i b / p r o m e t h e u s 2 " ;
description = ''
Directory to store Prometheus 2 metrics data .
'' ;
} ;
extraFlags = mkOption {
type = types . listOf types . str ;
default = [ ] ;
description = ''
Extra commandline options when launching Prometheus 2 .
'' ;
} ;
configText = mkOption {
type = types . nullOr types . lines ;
default = null ;
description = ''
If non-null , this option defines the text that is written to
prometheus . yml . If null , the contents of prometheus . yml is generated
from the structured config options .
'' ;
} ;
globalConfig = mkOption {
type = promTypes . globalConfig ;
default = { } ;
apply = _filter ;
description = ''
Parameters that are valid in all configuration contexts . They
also serve as defaults for other configuration sections
'' ;
} ;
rules = mkOption {
type = types . listOf types . str ;
default = [ ] ;
description = ''
Alerting and/or Recording rules to evaluate at runtime .
'' ;
} ;
ruleFiles = mkOption {
type = types . listOf types . path ;
default = [ ] ;
description = ''
Any additional rules files to include in this configuration .
'' ;
} ;
scrapeConfigs = mkOption {
type = types . listOf promTypes . scrape_config ;
default = [ ] ;
apply = x : map _filter x ;
description = ''
A list of scrape configurations .
'' ;
} ;
alertmanagerURL = mkOption {
type = types . listOf types . str ;
default = [ ] ;
description = ''
List of Alertmanager URLs to send notifications to .
'' ;
} ;
alertmanagerNotificationQueueCapacity = mkOption {
type = types . int ;
default = 10000 ;
description = ''
The capacity of the queue for pending alert manager notifications .
'' ;
} ;
alertmanagerTimeout = mkOption {
type = types . int ;
default = 10 ;
description = ''
Alert manager HTTP API timeout ( in seconds ) .
'' ;
} ;
webExternalUrl = mkOption {
type = types . nullOr types . str ;
default = null ;
example = " h t t p s : / / e x a m p l e . c o m / " ;
description = ''
The URL under which Prometheus is externally reachable ( for example ,
if Prometheus is served via a reverse proxy ) .
'' ;
} ;
} ;
} ;
} ;
config = mkMerge [
( mkIf cfg . enable {
users . groups . ${ promGroup } . gid = config . ids . gids . prometheus ;
users . users . ${ promUser } = {
description = " P r o m e t h e u s d a e m o n u s e r " ;
uid = config . ids . uids . prometheus ;
group = promGroup ;
home = cfg . dataDir ;
createHome = true ;
} ;
systemd . services . prometheus = {
wantedBy = [ " m u l t i - u s e r . t a r g e t " ] ;
after = [ " n e t w o r k . t a r g e t " ] ;
script = ''
#!/bin/sh
exec $ { cfg . package } /bin/prometheus \
$ { concatStringsSep " \\ \n " cmdlineArgs }
'' ;
serviceConfig = {
User = promUser ;
Restart = " a l w a y s " ;
WorkingDirectory = cfg . dataDir ;
} ;
} ;
} )
( mkIf cfg2 . enable {
users . groups . ${ prom2Group } . gid = config . ids . gids . prometheus2 ;
users . users . ${ prom2User } = {
description = " P r o m e t h e u s 2 d a e m o n u s e r " ;
uid = config . ids . uids . prometheus2 ;
group = prom2Group ;
home = cfg2 . dataDir ;
createHome = true ;
} ;
systemd . services . prometheus2 = {
wantedBy = [ " m u l t i - u s e r . t a r g e t " ] ;
after = [ " n e t w o r k . t a r g e t " ] ;
script = ''
#!/bin/sh
exec $ { cfg . package } /bin/prometheus \
$ { concatStringsSep " \\ \n " cmdlineArgs2 }
'' ;
serviceConfig = {
User = prom2User ;
Restart = " a l w a y s " ;
WorkingDirectory = cfg2 . dataDir ;
} ;
} ;
} )
] ;
}