services...
This commit is contained in:
parent
73d2f44d74
commit
8552656731
15 changed files with 918 additions and 490 deletions
|
|
@ -6,9 +6,18 @@ serviceName: {
|
|||
with lib; let
|
||||
cfg = config.homelab.services.${serviceName};
|
||||
homelabCfg = config.homelab;
|
||||
|
||||
shouldEnableLogging =
|
||||
cfg.logging.files
|
||||
!= []
|
||||
|| cfg.logging.extraSources != [];
|
||||
in {
|
||||
options.homelab.services.${serviceName}.logging = {
|
||||
enable = mkEnableOption "logging for ${serviceName}";
|
||||
enable = mkOption {
|
||||
type = types.bool;
|
||||
description = "Enable logging for ${serviceName}";
|
||||
default = shouldEnableLogging;
|
||||
};
|
||||
|
||||
files = mkOption {
|
||||
type = types.listOf types.str;
|
||||
|
|
@ -51,37 +60,33 @@ in {
|
|||
};
|
||||
};
|
||||
|
||||
config = mkIf (cfg.enable && cfg.logging.enable) {
|
||||
homelab.logging.sources =
|
||||
[
|
||||
{
|
||||
name = "${serviceName}-logs";
|
||||
type = "file";
|
||||
files = {
|
||||
paths = cfg.logging.files;
|
||||
multiline = cfg.logging.multiline;
|
||||
config = mkIf cfg.enable {
|
||||
homelab.logging.sources = mkIf cfg.logging.enable (
|
||||
# Only create file source if files are specified
|
||||
(optional (cfg.logging.files != []) {
|
||||
name = "${serviceName}-logs";
|
||||
type = "file";
|
||||
files = {
|
||||
paths = cfg.logging.files;
|
||||
multiline = cfg.logging.multiline;
|
||||
};
|
||||
labels =
|
||||
cfg.logging.extraLabels
|
||||
// {
|
||||
service = serviceName;
|
||||
node = homelabCfg.hostname;
|
||||
environment = homelabCfg.environment;
|
||||
};
|
||||
labels =
|
||||
cfg.logging.extraLabels
|
||||
// {
|
||||
service = serviceName;
|
||||
node = homelabCfg.hostname;
|
||||
environment = homelabCfg.environment;
|
||||
};
|
||||
pipelineStages =
|
||||
mkIf (cfg.logging.parsing.regex != null) [
|
||||
{
|
||||
regex.expression = cfg.logging.parsing.regex;
|
||||
}
|
||||
]
|
||||
++ [
|
||||
{
|
||||
labels = listToAttrs (map (field: nameValuePair field null) cfg.logging.parsing.extractFields);
|
||||
}
|
||||
];
|
||||
enabled = true;
|
||||
}
|
||||
]
|
||||
++ cfg.logging.extraSources;
|
||||
pipelineStages =
|
||||
(optional (cfg.logging.parsing.regex != null) {
|
||||
regex.expression = cfg.logging.parsing.regex;
|
||||
})
|
||||
++ (optional (cfg.logging.parsing.extractFields != []) {
|
||||
labels = listToAttrs (map (field: nameValuePair field null) cfg.logging.parsing.extractFields);
|
||||
});
|
||||
enabled = true;
|
||||
})
|
||||
++ cfg.logging.extraSources
|
||||
);
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,47 +6,69 @@ serviceName: {
|
|||
with lib; let
|
||||
cfg = config.homelab.services.${serviceName};
|
||||
homelabCfg = config.homelab;
|
||||
|
||||
hasMetricsConfig =
|
||||
cfg.monitoring.metrics.path
|
||||
!= null
|
||||
|| cfg.monitoring.metrics.extraEndpoints != [];
|
||||
|
||||
hasHealthCheckConfig =
|
||||
cfg.monitoring.healthCheck.path
|
||||
!= null
|
||||
|| cfg.monitoring.healthCheck.conditions != []
|
||||
|| cfg.monitoring.healthCheck.extraChecks != [];
|
||||
in {
|
||||
# Define the service-specific monitoring options
|
||||
options.homelab.services.${serviceName}.monitoring = {
|
||||
enable = mkEnableOption "monitoring for ${serviceName}";
|
||||
enable = mkOption {
|
||||
type = types.bool;
|
||||
description = "Enable monitoring for ${serviceName}";
|
||||
default = hasMetricsConfig || hasHealthCheckConfig;
|
||||
};
|
||||
|
||||
metrics = {
|
||||
enable = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
default = hasMetricsConfig;
|
||||
};
|
||||
|
||||
path = mkOption {
|
||||
type = types.str;
|
||||
default = "/metrics";
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
description = "Metrics endpoint path. Setting this enables metrics collection.";
|
||||
};
|
||||
|
||||
extraEndpoints = mkOption {
|
||||
type = types.listOf types.attrs;
|
||||
default = [];
|
||||
description = "Additional metrics endpoints. Adding endpoints enables metrics collection.";
|
||||
};
|
||||
};
|
||||
|
||||
healthCheck = {
|
||||
enable = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
default = hasHealthCheckConfig;
|
||||
};
|
||||
|
||||
path = mkOption {
|
||||
type = types.str;
|
||||
default = "/health";
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
description = "Health check endpoint path. Setting this enables health checks.";
|
||||
example = "/health";
|
||||
};
|
||||
|
||||
conditions = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = ["[STATUS] == 200"];
|
||||
description = "Health check conditions. Setting conditions enables health checks.";
|
||||
example = ["[STATUS] == 200"];
|
||||
};
|
||||
|
||||
extraChecks = mkOption {
|
||||
type = types.listOf types.attrs;
|
||||
default = [];
|
||||
description = "Additional health checks. Adding checks enables health monitoring.";
|
||||
};
|
||||
};
|
||||
|
||||
|
|
@ -57,52 +79,50 @@ in {
|
|||
};
|
||||
|
||||
# Generate the homelab config automatically when service is enabled
|
||||
config = mkIf (cfg.enable && cfg.monitoring.enable) {
|
||||
homelab.monitoring = {
|
||||
metrics =
|
||||
[
|
||||
{
|
||||
name = "${serviceName}-main";
|
||||
host = homelabCfg.hostname;
|
||||
port = cfg.port;
|
||||
path = cfg.monitoring.metrics.path;
|
||||
jobName = serviceName;
|
||||
scrapeInterval = "30s";
|
||||
labels =
|
||||
cfg.monitoring.extraLabels
|
||||
// {
|
||||
service = serviceName;
|
||||
node = homelabCfg.hostname;
|
||||
environment = homelabCfg.environment;
|
||||
};
|
||||
}
|
||||
]
|
||||
++ cfg.monitoring.metrics.extraEndpoints;
|
||||
config = mkIf cfg.enable {
|
||||
homelab.monitoring = mkIf cfg.monitoring.enable {
|
||||
metrics = mkIf hasMetricsConfig (
|
||||
(optional (cfg.monitoring.metrics.path != null) {
|
||||
name = "${serviceName}-main";
|
||||
host = homelabCfg.hostname;
|
||||
port = cfg.port;
|
||||
path = cfg.monitoring.metrics.path;
|
||||
jobName = serviceName;
|
||||
scrapeInterval = "30s";
|
||||
labels =
|
||||
cfg.monitoring.extraLabels
|
||||
// {
|
||||
service = serviceName;
|
||||
node = homelabCfg.hostname;
|
||||
environment = homelabCfg.environment;
|
||||
};
|
||||
})
|
||||
++ cfg.monitoring.metrics.extraEndpoints
|
||||
);
|
||||
|
||||
healthChecks =
|
||||
[
|
||||
{
|
||||
name = "${serviceName}-health";
|
||||
host = homelabCfg.hostname;
|
||||
port = cfg.port;
|
||||
path = cfg.monitoring.healthCheck.path;
|
||||
protocol = "http";
|
||||
method = "GET";
|
||||
interval = "30s";
|
||||
timeout = "10s";
|
||||
conditions = cfg.monitoring.healthCheck.conditions;
|
||||
group = "services";
|
||||
labels =
|
||||
cfg.monitoring.extraLabels
|
||||
// {
|
||||
service = serviceName;
|
||||
node = homelabCfg.hostname;
|
||||
environment = homelabCfg.environment;
|
||||
};
|
||||
enabled = true;
|
||||
}
|
||||
]
|
||||
++ cfg.monitoring.healthCheck.extraChecks;
|
||||
healthChecks = mkIf hasHealthCheckConfig (
|
||||
(optional (cfg.monitoring.healthCheck.path != null) {
|
||||
name = "${serviceName}-health";
|
||||
host = homelabCfg.hostname;
|
||||
port = cfg.port;
|
||||
path = cfg.monitoring.healthCheck.path;
|
||||
protocol = "http";
|
||||
method = "GET";
|
||||
interval = "30s";
|
||||
timeout = "10s";
|
||||
conditions = cfg.monitoring.healthCheck.conditions;
|
||||
group = "services";
|
||||
labels =
|
||||
cfg.monitoring.extraLabels
|
||||
// {
|
||||
service = serviceName;
|
||||
node = homelabCfg.hostname;
|
||||
environment = homelabCfg.environment;
|
||||
};
|
||||
enabled = true;
|
||||
})
|
||||
++ cfg.monitoring.healthCheck.extraChecks
|
||||
);
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,11 @@ with lib; let
|
|||
homelabCfg = config.homelab;
|
||||
in {
|
||||
options.homelab.services.${serviceName}.proxy = {
|
||||
enable = mkEnableOption "reverse proxy for ${serviceName}";
|
||||
enable = mkOption {
|
||||
type = types.bool;
|
||||
description = "Enable reverse proxy for ${serviceName}";
|
||||
default = true;
|
||||
};
|
||||
|
||||
subdomain = mkOption {
|
||||
type = types.str;
|
||||
|
|
@ -39,8 +43,8 @@ in {
|
|||
};
|
||||
};
|
||||
|
||||
config = mkIf (cfg.enable && cfg.proxy.enable) {
|
||||
homelab.reverseProxy.entries =
|
||||
config = mkIf cfg.enable {
|
||||
homelab.reverseProxy.entries = mkIf cfg.proxy.enable (
|
||||
[
|
||||
{
|
||||
subdomain = cfg.proxy.subdomain;
|
||||
|
|
@ -59,6 +63,7 @@ in {
|
|||
enableAuth = sub.enableAuth;
|
||||
enableSSL = true;
|
||||
})
|
||||
cfg.proxy.additionalSubdomains;
|
||||
cfg.proxy.additionalSubdomains
|
||||
);
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -219,8 +219,7 @@ in {
|
|||
homelab.services.${serviceName}.monitoring.enable = mkDefault true;
|
||||
}
|
||||
|
||||
# Smart defaults for Gatus
|
||||
(mkIf cfg.monitoring.enable {
|
||||
{
|
||||
homelab.services.${serviceName}.monitoring = mkDefault {
|
||||
metrics = {
|
||||
path = "/metrics";
|
||||
|
|
@ -240,9 +239,9 @@ in {
|
|||
tier = "monitoring";
|
||||
};
|
||||
};
|
||||
})
|
||||
}
|
||||
|
||||
(mkIf cfg.logging.enable {
|
||||
{
|
||||
homelab.services.${serviceName}.logging = mkDefault {
|
||||
files = ["/var/log/gatus/gatus.log"];
|
||||
parsing = {
|
||||
|
|
@ -255,13 +254,13 @@ in {
|
|||
application = "gatus";
|
||||
};
|
||||
};
|
||||
})
|
||||
}
|
||||
|
||||
(mkIf cfg.proxy.enable {
|
||||
{
|
||||
homelab.services.${serviceName}.proxy = mkDefault {
|
||||
subdomain = "status";
|
||||
enableAuth = false; # Status page should be public
|
||||
};
|
||||
})
|
||||
}
|
||||
]);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ in {
|
|||
}
|
||||
|
||||
# Smart defaults for Grafana
|
||||
(mkIf cfg.logging.enable {
|
||||
{
|
||||
# Grafana-specific log setup
|
||||
homelab.services.${serviceName}.logging = mkDefault {
|
||||
files = ["/var/log/grafana/grafana.log"];
|
||||
|
|
@ -59,9 +59,8 @@ in {
|
|||
component = "dashboard";
|
||||
};
|
||||
};
|
||||
})
|
||||
|
||||
(mkIf cfg.monitoring.enable {
|
||||
}
|
||||
{
|
||||
homelab.services.${serviceName}.monitoring = mkDefault {
|
||||
metrics.path = "/metrics";
|
||||
healthCheck = {
|
||||
|
|
@ -73,14 +72,13 @@ in {
|
|||
tier = "monitoring";
|
||||
};
|
||||
};
|
||||
})
|
||||
|
||||
(mkIf cfg.proxy.enable {
|
||||
}
|
||||
{
|
||||
# Grafana needs auth by default (admin interface)
|
||||
homelab.services.${serviceName}.proxy = mkDefault {
|
||||
subdomain = "grafana";
|
||||
# enableAuth = true;
|
||||
};
|
||||
})
|
||||
}
|
||||
]);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -168,7 +168,6 @@ in {
|
|||
|
||||
# Service configuration with smart defaults
|
||||
config = mkIf cfg.enable (mkMerge [
|
||||
# Core Prometheus service
|
||||
{
|
||||
services.prometheus = {
|
||||
enable = true;
|
||||
|
|
@ -203,39 +202,21 @@ in {
|
|||
};
|
||||
|
||||
networking.firewall.allowedTCPPorts = [cfg.port];
|
||||
|
||||
homelab.services.${serviceName}.monitoring.enable = mkDefault true;
|
||||
}
|
||||
{
|
||||
homelab.services.${serviceName}.monitoring = {
|
||||
metrics.path = "/metrics";
|
||||
healthCheck.path = "/-/healthy"; # ✅ Enables health checks
|
||||
healthCheck.conditions = ["[STATUS] == 200" "[RESPONSE_TIME] < 1000"];
|
||||
|
||||
# Smart defaults for Prometheus
|
||||
(mkIf cfg.monitoring.enable {
|
||||
homelab.services.${serviceName}.monitoring = mkDefault {
|
||||
metrics = {
|
||||
path = "/metrics";
|
||||
extraEndpoints = [];
|
||||
};
|
||||
healthCheck = {
|
||||
path = "/-/healthy";
|
||||
conditions = ["[STATUS] == 200" "[RESPONSE_TIME] < 1000"];
|
||||
extraChecks = [
|
||||
{
|
||||
name = "prometheus-ready";
|
||||
port = cfg.port;
|
||||
path = "/-/ready";
|
||||
conditions = ["[STATUS] == 200"];
|
||||
group = "monitoring";
|
||||
}
|
||||
];
|
||||
};
|
||||
extraLabels = {
|
||||
component = "monitoring-server";
|
||||
tier = "monitoring";
|
||||
};
|
||||
};
|
||||
})
|
||||
|
||||
(mkIf cfg.logging.enable {
|
||||
homelab.services.${serviceName}.logging = mkDefault {
|
||||
}
|
||||
{
|
||||
homelab.services.${serviceName}.logging = {
|
||||
files = ["/var/log/prometheus/prometheus.log"];
|
||||
parsing = {
|
||||
# Prometheus log format: ts=2024-01-01T12:00:00.000Z caller=main.go:123 level=info msg="message"
|
||||
|
|
@ -247,13 +228,11 @@ in {
|
|||
application = "prometheus";
|
||||
};
|
||||
};
|
||||
})
|
||||
|
||||
(mkIf cfg.proxy.enable {
|
||||
homelab.services.${serviceName}.proxy = mkDefault {
|
||||
subdomain = "prometheus";
|
||||
enableAuth = true; # Admin interface needs protection
|
||||
}
|
||||
{
|
||||
homelab.services.${serviceName}.proxy = {
|
||||
enableAuth = true;
|
||||
};
|
||||
})
|
||||
}
|
||||
]);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue