diff --git a/docs/README.md b/docs/README.md index 9984a6d..17e36a8 100644 --- a/docs/README.md +++ b/docs/README.md @@ -20,7 +20,7 @@ This documentation is automatically generated from your colmena flake configurat ## 🚀 Quick Actions ### View Current Status -```bash +\`\`\`bash # Service status across fleet (if homelab CLI is available) homelab services --global @@ -29,22 +29,22 @@ homelab backups --global # Overall status homelab status -``` +\`\`\` ### Update Documentation -```bash +\`\`\`bash # Regenerate all documentation homelab-generate-docs ./docs # Generate in different directory homelab-generate-docs /path/to/output -``` +\`\`\` ## 📋 Quick Stats - **Total Nodes**: 2 - **Homelab-Enabled Nodes**: 2 -- **Generated**: ons 30 jul 00:20:46 CEST 2025 +- **Generated**: tir 29 jul 16:57:16 CEST 2025 ## 🛠️ Management Tools diff --git a/docs/current-deployment.md b/docs/current-deployment.md index c43eccf..2f1541c 100644 --- a/docs/current-deployment.md +++ b/docs/current-deployment.md @@ -11,15 +11,15 @@ |--------|-------| | Total Nodes | 2 | | Homelab-Enabled Nodes | 2 | -| Unique Services | 4 | -| Service Instances | 4 | +| Unique Services | 1 | +| Service Instances | 1 | ## Node Status | Node | Homelab | Environment | Services | Monitoring | Backups | Proxy | |------|---------|-------------|----------|------------|---------|-------| | `photos` | ✅ | production | 1 | ✅ | ❌ | ❌ | -| `sandbox` | ✅ | production | 3 | ✅ | ✅ | ❌ | +| `sandbox` | ✅ | production | 0 | ✅ | ✅ | ❌ | --- diff --git a/docs/fleet-overview.md b/docs/fleet-overview.md index 866c8bd..5982210 100644 --- a/docs/fleet-overview.md +++ b/docs/fleet-overview.md @@ -26,7 +26,7 @@ | Node | Service Count | Services | |------|---------------|----------| | `photos` | 1 | minio | -| `sandbox` | 3 | gatus, grafana, prometheus | +| `sandbox` | 0 | | --- diff --git a/docs/nodes.md b/docs/nodes.md index 90a635a..87cade4 100644 --- a/docs/nodes.md +++ b/docs/nodes.md @@ -61,10 +61,10 @@ | Service | Enabled | Port | Description | Tags | |---------|---------|------|-------------|------| -| `gatus` | ✅ | 8080 | Gatus Status Page | | -| `grafana` | ✅ | 3000 | Grafana Metrics Dashboard | | +| `gatus` | ❌ | 8080 | Gatus Status Page | | +| `grafana` | ❌ | 3000 | Grafana Metrics Dashboard | | | `minio` | ❌ | 9000 | minio | | -| `prometheus` | ✅ | 9090 | Prometheus Monitoring Server | | +| `prometheus` | ❌ | 9090 | Prometheus Monitoring Server | | --- diff --git a/docs/services.md b/docs/services.md index 7e3571b..a953b35 100644 --- a/docs/services.md +++ b/docs/services.md @@ -1,13 +1,10 @@ # Service Catalog -> Complete service documentation with core options, feature integrations, and smart defaults +> Available services and their configuration options > > Generated on: $(date) -This document provides comprehensive documentation for homelab services, organized by: -- **Core Service Options**: The main service configuration -- **Feature Integrations**: Available monitoring, logging, and proxy features -- **Service Defaults**: What this service configures by default for each feature +This document catalogs all available homelab services, their configuration options, and integration capabilities. ## Overview @@ -15,252 +12,142 @@ This document provides comprehensive documentation for homelab services, organiz ## Service Integration Matrix -| Service | Core Options | Monitoring | Logging | Proxy | Deployments | -|---------|--------------|------------|---------|-------|-------------| -| `gatus` | 11 | 📊 | 📝 | 🔀 | 1 | -| `grafana` | 3 | 📊 | 📝 | 🔀 | 1 | -| `minio` | 4 | ❌ | ❌ | ❌ | 1 | -| `prometheus` | 12 | 📊 | 📝 | 🔀 | 1 | +| Service | Monitoring | Logging | Proxy | Auth Default | +|---------|------------|---------|-------|--------------| +| `gatus` | ❌ | ❌ | ❌ | 🌐 | +| `grafana` | ❌ | ❌ | ❌ | 🌐 | +| `minio` | ❌ | ❌ | ❌ | 🌐 | +| `prometheus` | ❌ | ❌ | ❌ | 🌐 | -**Legend:** 📊📝🔀 = Feature available, ❌ = Feature not available +**Legend:** ✅ = Enabled by default, ❌ = Available but disabled, 🔒 = Auth required, 🌐 = Public access -## Service Documentation +## Service Reference ### gatus -**Deployment Status:** 1/2 nodes have this service enabled +**Description:** Gatus Status Page -#### Core Service Options +**Default Port:** `8080` -The main configuration options for gatus: +**Current Deployments:** 0 instance(s) on: + +#### Default Integration Status + +| Integration | Status | Default Configuration | +|-------------|--------|----------------------| +| 📊 Monitoring | ❌ Disabled | Available but requires `monitoring.enable = true` | +| 📝 Logging | ❌ Disabled | Available but requires `logging.enable = true` | +| 🔀 Proxy | ❌ Disabled | Available but requires `proxy.enable = true` | + +#### Core Configuration ```nix homelab.services.gatus = { - alerting = {}; # Gatus alerting configuration - description = Gatus Status Page; # No description - enable = false; # Whether to enable Gatus Status Page. - extraConfig = {}; # Additional Gatus configuration options - port = 8080; # No description - storage = { - "type": "memory" -}; # Gatus storage configuration - ui.buttons = [ - { - "link": "https://grafana.procopius.dk", - "name": "Grafana" - }, - { - "link": "https://prometheus.procopius.dk", - "name": "Prometheus" - } -]; # Navigation buttons in the Gatus interface - ui.header = Homelab Services Status; # Header text for the Gatus interface - ui.link = https://status.procopius.dk; # Link in the Gatus header - ui.title = Homelab Status; # Title for the Gatus web interface - web.address = 0.0.0.0; # Web interface bind address -}; -``` - -#### Feature Integrations - -##### 📊 Monitoring Integration - -Available monitoring options: - -```nix -homelab.services.gatus = { - # ... core options above ... - - monitoring.enable = true; # Enable monitoring for gatus - monitoring.extraLabels = {}; # No description - monitoring.healthCheck.conditions = [ - "[STATUS] == 200" -]; # Health check conditions. Setting conditions enables health checks. - monitoring.healthCheck.enable = true; # No description - monitoring.healthCheck.extraChecks = []; # Additional health checks. Adding checks enables health monitoring. - # monitoring.healthCheck.path = ; # Health check endpoint path. Setting this enables health checks. - monitoring.metrics.enable = false; # No description - monitoring.metrics.extraEndpoints = []; # Additional metrics endpoints. Adding endpoints enables metrics collection. - # monitoring.metrics.path = ; # Metrics endpoint path. Setting this enables metrics collection. -}; -``` - -**gatus sets these monitoring defaults:** -```nix enable = true; - extraLabels = {}; - healthCheck = {"conditions":["[STATUS] == 200"],"enable":true,"extraChecks":[],"path":null}; - metrics = {"enable":false,"extraEndpoints":[],"path":null}; + port = 8080; + description = "Gatus Status Page"; + + # Default integrations (adjust as needed) + # monitoring.enable = true; # ❌ Disabled by default + # logging.enable = true; # ❌ Disabled by default + # proxy.enable = true; # ❌ Disabled by default +}; ``` -##### 📝 Logging Integration +#### Service-Specific Options -Available logging options: +Available configuration options for gatus: ```nix homelab.services.gatus = { # ... core options above ... - logging.enable = false; # Enable logging for gatus - logging.extraLabels = {}; # No description - logging.extraSources = []; # No description - logging.files = []; # No description - # logging.multiline = ; # No description - logging.parsing.extractFields = []; # No description - # logging.parsing.regex = ; # No description + # Service-specific configuration + alerting = {}; + extraConfig = {}; + storage = {"type":"memory"}; + ui = {"buttons":[{"link":"https://grafana.procopius.dk","name":"Grafana"},{"link":"https://prometheus.procopius.dk","name":"Prometheus"}],"header":"Homelab Services Status","link":"https://status.procopius.dk","title":"Homelab Status"}; + web = {"address":"0.0.0.0"}; }; ``` -**gatus sets these logging defaults:** -```nix - enable = false; - extraLabels = {}; - extraSources = []; - files = []; - multiline = null; - parsing = {"extractFields":[],"regex":null}; -``` - -##### 🔀 Proxy Integration - -Available proxy options: - -```nix -homelab.services.gatus = { - # ... core options above ... - - proxy.additionalSubdomains = []; # No description - proxy.enable = true; # Enable reverse proxy for gatus - proxy.enableAuth = false; # No description - proxy.subdomain = gatus; # No description -}; -``` - -**gatus sets these proxy defaults:** -```nix - additionalSubdomains = []; - enable = true; - enableAuth = false; - subdomain = gatus; -``` - --- ### grafana -**Deployment Status:** 1/2 nodes have this service enabled +**Description:** Grafana Metrics Dashboard -#### Core Service Options +**Default Port:** `3000` -The main configuration options for grafana: +**Current Deployments:** 0 instance(s) on: + +#### Default Integration Status + +| Integration | Status | Default Configuration | +|-------------|--------|----------------------| +| 📊 Monitoring | ❌ Disabled | Available but requires `monitoring.enable = true` | +| 📝 Logging | ❌ Disabled | Available but requires `logging.enable = true` | +| 🔀 Proxy | ❌ Disabled | Available but requires `proxy.enable = true` | + +#### Core Configuration ```nix homelab.services.grafana = { - description = Grafana Metrics Dashboard; # No description - enable = false; # Whether to enable Grafana Dashboard. - port = 3000; # No description -}; -``` - -#### Feature Integrations - -##### 📊 Monitoring Integration - -Available monitoring options: - -```nix -homelab.services.grafana = { - # ... core options above ... - - monitoring.enable = true; # Enable monitoring for grafana - monitoring.extraLabels = {}; # No description - monitoring.healthCheck.conditions = [ - "[STATUS] == 200" -]; # Health check conditions. Setting conditions enables health checks. - monitoring.healthCheck.enable = true; # No description - monitoring.healthCheck.extraChecks = []; # Additional health checks. Adding checks enables health monitoring. - # monitoring.healthCheck.path = ; # Health check endpoint path. Setting this enables health checks. - monitoring.metrics.enable = false; # No description - monitoring.metrics.extraEndpoints = []; # Additional metrics endpoints. Adding endpoints enables metrics collection. - # monitoring.metrics.path = ; # Metrics endpoint path. Setting this enables metrics collection. -}; -``` - -**grafana sets these monitoring defaults:** -```nix enable = true; - extraLabels = {}; - healthCheck = {"conditions":["[STATUS] == 200"],"enable":true,"extraChecks":[],"path":null}; - metrics = {"enable":false,"extraEndpoints":[],"path":null}; -``` + port = 3000; + description = "Grafana Metrics Dashboard"; -##### 📝 Logging Integration - -Available logging options: - -```nix -homelab.services.grafana = { - # ... core options above ... - - logging.enable = false; # Enable logging for grafana - logging.extraLabels = {}; # No description - logging.extraSources = []; # No description - logging.files = []; # No description - # logging.multiline = ; # No description - logging.parsing.extractFields = []; # No description - # logging.parsing.regex = ; # No description + # Default integrations (adjust as needed) + # monitoring.enable = true; # ❌ Disabled by default + # logging.enable = true; # ❌ Disabled by default + # proxy.enable = true; # ❌ Disabled by default }; ``` -**grafana sets these logging defaults:** -```nix - enable = false; - extraLabels = {}; - extraSources = []; - files = []; - multiline = null; - parsing = {"extractFields":[],"regex":null}; -``` - -##### 🔀 Proxy Integration - -Available proxy options: - -```nix -homelab.services.grafana = { - # ... core options above ... - - proxy.additionalSubdomains = []; # No description - proxy.enable = true; # Enable reverse proxy for grafana - proxy.enableAuth = false; # No description - proxy.subdomain = grafana; # No description -}; -``` - -**grafana sets these proxy defaults:** -```nix - additionalSubdomains = []; - enable = true; - enableAuth = false; - subdomain = grafana; -``` - --- ### minio -**Deployment Status:** 1/2 nodes have this service enabled +**Description:** minio -#### Core Service Options +**Default Port:** `9000` -The main configuration options for minio: +**Current Deployments:** 1 instance(s) on: photos + +#### Default Integration Status + +| Integration | Status | Default Configuration | +|-------------|--------|----------------------| +| 📊 Monitoring | ❌ Disabled | Available but requires `monitoring.enable = true` | +| 📝 Logging | ❌ Disabled | Available but requires `logging.enable = true` | +| 🔀 Proxy | ❌ Disabled | Available but requires `proxy.enable = true` | + +#### Core Configuration ```nix homelab.services.minio = { - enable = false; # Whether to enable Minio Object Storage. - openFirewall = true; # Whether to open the ports specified in `port` and `webPort` in the firewall. - port = 9000; # Port of the server. - webPort = 9001; # Port of the web UI (console). + enable = true; + port = 9000; + description = "minio"; + + # Default integrations (adjust as needed) + # monitoring.enable = true; # ❌ Disabled by default + # logging.enable = true; # ❌ Disabled by default + # proxy.enable = true; # ❌ Disabled by default +}; +``` + +#### Service-Specific Options + +Available configuration options for minio: + +```nix +homelab.services.minio = { + # ... core options above ... + + # Service-specific configuration + openFirewall = true; + webPort = 9001; }; ``` @@ -268,132 +155,75 @@ homelab.services.minio = { ### prometheus -**Deployment Status:** 1/2 nodes have this service enabled +**Description:** Prometheus Monitoring Server -#### Core Service Options +**Default Port:** `9090` -The main configuration options for prometheus: +**Current Deployments:** 0 instance(s) on: + +#### Default Integration Status + +| Integration | Status | Default Configuration | +|-------------|--------|----------------------| +| 📊 Monitoring | ❌ Disabled | Available but requires `monitoring.enable = true` | +| 📝 Logging | ❌ Disabled | Available but requires `logging.enable = true` | +| 🔀 Proxy | ❌ Disabled | Available but requires `proxy.enable = true` | + +#### Core Configuration ```nix homelab.services.prometheus = { - alertmanager.enable = true; # Enable integration with Alertmanager - alertmanager.url = alertmanager.lab:9093; # Alertmanager URL - description = Prometheus Monitoring Server; # No description - enable = false; # Whether to enable Prometheus Monitoring Server. - extraAlertingRules = []; # Additional alerting rules - extraFlags = []; # Extra command line flags - extraScrapeConfigs = []; # Additional scrape configurations - globalConfig = { - "evaluation_interval": "15s", - "scrape_interval": "15s" -}; # Global Prometheus configuration - port = 9090; # No description - retention = 15d; # How long to retain metrics data - ruleFiles = []; # Additional rule files to load - systemdServices = [ - "prometheus.service", - "prometheus" -]; # Systemd services to monitor -}; -``` - -#### Feature Integrations - -##### 📊 Monitoring Integration - -Available monitoring options: - -```nix -homelab.services.prometheus = { - # ... core options above ... - - monitoring.enable = true; # Enable monitoring for prometheus - monitoring.extraLabels = {}; # No description - monitoring.healthCheck.conditions = [ - "[STATUS] == 200" -]; # Health check conditions. Setting conditions enables health checks. - monitoring.healthCheck.enable = true; # No description - monitoring.healthCheck.extraChecks = []; # Additional health checks. Adding checks enables health monitoring. - # monitoring.healthCheck.path = ; # Health check endpoint path. Setting this enables health checks. - monitoring.metrics.enable = false; # No description - monitoring.metrics.extraEndpoints = []; # Additional metrics endpoints. Adding endpoints enables metrics collection. - # monitoring.metrics.path = ; # Metrics endpoint path. Setting this enables metrics collection. -}; -``` - -**prometheus sets these monitoring defaults:** -```nix enable = true; - extraLabels = {}; - healthCheck = {"conditions":["[STATUS] == 200"],"enable":true,"extraChecks":[],"path":null}; - metrics = {"enable":false,"extraEndpoints":[],"path":null}; + port = 9090; + description = "Prometheus Monitoring Server"; + + # Default integrations (adjust as needed) + # monitoring.enable = true; # ❌ Disabled by default + # logging.enable = true; # ❌ Disabled by default + # proxy.enable = true; # ❌ Disabled by default +}; ``` -##### 📝 Logging Integration +#### Service-Specific Options -Available logging options: +Available configuration options for prometheus: ```nix homelab.services.prometheus = { # ... core options above ... - logging.enable = false; # Enable logging for prometheus - logging.extraLabels = {}; # No description - logging.extraSources = []; # No description - logging.files = []; # No description - # logging.multiline = ; # No description - logging.parsing.extractFields = []; # No description - # logging.parsing.regex = ; # No description + # Service-specific configuration + alertmanager = {"enable":true,"url":"alertmanager.lab:9093"}; + extraAlertingRules = []; + extraFlags = []; + extraScrapeConfigs = []; + globalConfig = {"evaluation_interval":"15s","scrape_interval":"15s"}; + retention = 15d; + ruleFiles = []; + systemdServices = ["prometheus.service","prometheus"]; }; ``` -**prometheus sets these logging defaults:** -```nix - enable = false; - extraLabels = {}; - extraSources = []; - files = []; - multiline = null; - parsing = {"extractFields":[],"regex":null}; -``` - -##### 🔀 Proxy Integration - -Available proxy options: - -```nix -homelab.services.prometheus = { - # ... core options above ... - - proxy.additionalSubdomains = []; # No description - proxy.enable = true; # Enable reverse proxy for prometheus - proxy.enableAuth = false; # No description - proxy.subdomain = prometheus; # No description -}; -``` - -**prometheus sets these proxy defaults:** -```nix - additionalSubdomains = []; - enable = true; - enableAuth = false; - subdomain = prometheus; -``` - --- -## Feature Reference +## Integration Summary -### Integration Features +### Available Integration Types -Homelab services can integrate with three main features: +| Integration | Purpose | Default Behavior | Configuration | +|-------------|---------|------------------|---------------| +| **📊 Monitoring** | Prometheus metrics + health checks | Service-dependent | `monitoring.enable = true` | +| **📝 Logging** | Centralized log collection | Service-dependent | `logging.enable = true` | +| **🔀 Proxy** | Reverse proxy with SSL + auth | Service-dependent | `proxy.enable = true` | -- **📊 Monitoring**: Prometheus metrics and health checks -- **📝 Logging**: Centralized log collection with Promtail/Loki -- **🔀 Proxy**: Reverse proxy with SSL and authentication +### Integration Benefits -Each service can import these features and set service-specific defaults. +- **🔄 Automatic Discovery:** Enabled integrations are automatically discovered by fleet-wide services +- **📊 Unified Monitoring:** All metrics and health checks appear in Prometheus/Grafana +- **📝 Centralized Logging:** All logs are collected and indexed in Loki +- **🌐 Consistent Access:** All services get consistent subdomain access with SSL +- **🎯 Smart Defaults:** Each service comes with sensible default configurations --- -*This documentation is generated from actual NixOS module evaluations.* +*This service catalog is generated from actual service configurations across your homelab fleet.* diff --git a/hosts/sandbox/default.nix b/hosts/sandbox/default.nix index ebf4475..70eb387 100644 --- a/hosts/sandbox/default.nix +++ b/hosts/sandbox/default.nix @@ -42,9 +42,9 @@ }; # services.loki.enable = true; - services.prometheus.enable = true; - services.grafana.enable = true; - services.gatus.enable = true; + # services.prometheus.enable = true; + # services.grafana.enable = true; + # services.gatus.enable = true; }; system.stateVersion = "25.05"; diff --git a/modules/homelab/lib/features/logging.nix b/modules/homelab/lib/features/logging.nix index 60f2cda..010b766 100644 --- a/modules/homelab/lib/features/logging.nix +++ b/modules/homelab/lib/features/logging.nix @@ -6,18 +6,9 @@ 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 = mkOption { - type = types.bool; - description = "Enable logging for ${serviceName}"; - default = shouldEnableLogging; - }; + enable = mkEnableOption "logging for ${serviceName}"; files = mkOption { type = types.listOf types.str; @@ -60,33 +51,37 @@ in { }; }; - 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; + config = mkIf (cfg.enable && cfg.logging.enable) { + homelab.logging.sources = + [ + { + name = "${serviceName}-logs"; + type = "file"; + files = { + paths = cfg.logging.files; + multiline = cfg.logging.multiline; }; - 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 - ); + 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; }; } diff --git a/modules/homelab/lib/features/monitoring.nix b/modules/homelab/lib/features/monitoring.nix index f25e3b8..90b36f9 100644 --- a/modules/homelab/lib/features/monitoring.nix +++ b/modules/homelab/lib/features/monitoring.nix @@ -6,69 +6,47 @@ 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 = mkOption { - type = types.bool; - description = "Enable monitoring for ${serviceName}"; - default = hasMetricsConfig || hasHealthCheckConfig; - }; + enable = mkEnableOption "monitoring for ${serviceName}"; metrics = { enable = mkOption { type = types.bool; - default = hasMetricsConfig; + default = true; }; path = mkOption { - type = types.nullOr types.str; - default = null; - description = "Metrics endpoint path. Setting this enables metrics collection."; + type = types.str; + default = "/metrics"; }; extraEndpoints = mkOption { type = types.listOf types.attrs; default = []; - description = "Additional metrics endpoints. Adding endpoints enables metrics collection."; }; }; healthCheck = { enable = mkOption { type = types.bool; - default = hasHealthCheckConfig; + default = true; }; path = mkOption { - type = types.nullOr types.str; - default = null; - description = "Health check endpoint path. Setting this enables health checks."; - example = "/health"; + type = types.str; + default = "/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."; }; }; @@ -79,50 +57,52 @@ in { }; # Generate the homelab config automatically when service is enabled - 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 - ); + 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; - 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 - ); + 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; }; }; } diff --git a/modules/homelab/lib/features/proxy.nix b/modules/homelab/lib/features/proxy.nix index 595f4c0..2658c7a 100644 --- a/modules/homelab/lib/features/proxy.nix +++ b/modules/homelab/lib/features/proxy.nix @@ -8,11 +8,7 @@ with lib; let homelabCfg = config.homelab; in { options.homelab.services.${serviceName}.proxy = { - enable = mkOption { - type = types.bool; - description = "Enable reverse proxy for ${serviceName}"; - default = true; - }; + enable = mkEnableOption "reverse proxy for ${serviceName}"; subdomain = mkOption { type = types.str; @@ -43,8 +39,8 @@ in { }; }; - config = mkIf cfg.enable { - homelab.reverseProxy.entries = mkIf cfg.proxy.enable ( + config = mkIf (cfg.enable && cfg.proxy.enable) { + homelab.reverseProxy.entries = [ { subdomain = cfg.proxy.subdomain; @@ -63,7 +59,6 @@ in { enableAuth = sub.enableAuth; enableSSL = true; }) - cfg.proxy.additionalSubdomains - ); + cfg.proxy.additionalSubdomains; }; } diff --git a/modules/homelab/services/gatus.nix b/modules/homelab/services/gatus.nix index 3bdd610..da907c4 100644 --- a/modules/homelab/services/gatus.nix +++ b/modules/homelab/services/gatus.nix @@ -219,7 +219,8 @@ in { homelab.services.${serviceName}.monitoring.enable = mkDefault true; } - { + # Smart defaults for Gatus + (mkIf cfg.monitoring.enable { homelab.services.${serviceName}.monitoring = mkDefault { metrics = { path = "/metrics"; @@ -239,9 +240,9 @@ in { tier = "monitoring"; }; }; - } + }) - { + (mkIf cfg.logging.enable { homelab.services.${serviceName}.logging = mkDefault { files = ["/var/log/gatus/gatus.log"]; parsing = { @@ -254,13 +255,13 @@ in { application = "gatus"; }; }; - } + }) - { + (mkIf cfg.proxy.enable { homelab.services.${serviceName}.proxy = mkDefault { subdomain = "status"; enableAuth = false; # Status page should be public }; - } + }) ]); } diff --git a/modules/homelab/services/grafana.nix b/modules/homelab/services/grafana.nix index 2663cc9..5f5aad9 100644 --- a/modules/homelab/services/grafana.nix +++ b/modules/homelab/services/grafana.nix @@ -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,8 +59,9 @@ in { component = "dashboard"; }; }; - } - { + }) + + (mkIf cfg.monitoring.enable { homelab.services.${serviceName}.monitoring = mkDefault { metrics.path = "/metrics"; healthCheck = { @@ -72,13 +73,14 @@ in { tier = "monitoring"; }; }; - } - { + }) + + (mkIf cfg.proxy.enable { # Grafana needs auth by default (admin interface) homelab.services.${serviceName}.proxy = mkDefault { subdomain = "grafana"; # enableAuth = true; }; - } + }) ]); } diff --git a/modules/homelab/services/prometheus.nix b/modules/homelab/services/prometheus.nix index dabc086..b3f398b 100644 --- a/modules/homelab/services/prometheus.nix +++ b/modules/homelab/services/prometheus.nix @@ -168,6 +168,7 @@ in { # Service configuration with smart defaults config = mkIf cfg.enable (mkMerge [ + # Core Prometheus service { services.prometheus = { enable = true; @@ -202,21 +203,39 @@ in { }; networking.firewall.allowedTCPPorts = [cfg.port]; - } - { - homelab.services.${serviceName}.monitoring = { - metrics.path = "/metrics"; - healthCheck.path = "/-/healthy"; # ✅ Enables health checks - healthCheck.conditions = ["[STATUS] == 200" "[RESPONSE_TIME] < 1000"]; + homelab.services.${serviceName}.monitoring.enable = mkDefault true; + } + + # 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"; }; }; - } - { - homelab.services.${serviceName}.logging = { + }) + + (mkIf cfg.logging.enable { + homelab.services.${serviceName}.logging = mkDefault { 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" @@ -228,11 +247,13 @@ in { application = "prometheus"; }; }; - } - { - homelab.services.${serviceName}.proxy = { - enableAuth = true; + }) + + (mkIf cfg.proxy.enable { + homelab.services.${serviceName}.proxy = mkDefault { + subdomain = "prometheus"; + enableAuth = true; # Admin interface needs protection }; - } + }) ]); } diff --git a/pkgs/homelab-docs/readme.nix b/pkgs/homelab-docs/readme.nix index 505d465..7a0891f 100644 --- a/pkgs/homelab-docs/readme.nix +++ b/pkgs/homelab-docs/readme.nix @@ -30,7 +30,7 @@ writeShellScriptBin "homelab-docs-readme" '' ## 🚀 Quick Actions ### View Current Status - ```bash + \`\`\`bash # Service status across fleet (if homelab CLI is available) homelab services --global @@ -39,16 +39,16 @@ writeShellScriptBin "homelab-docs-readme" '' # Overall status homelab status - ``` + \`\`\` ### Update Documentation - ```bash + \`\`\`bash # Regenerate all documentation homelab-generate-docs ./docs # Generate in different directory homelab-generate-docs /path/to/output - ``` + \`\`\` ## 📋 Quick Stats diff --git a/pkgs/homelab-docs/services.nix b/pkgs/homelab-docs/services.nix index 808c746..7e6c8a3 100644 --- a/pkgs/homelab-docs/services.nix +++ b/pkgs/homelab-docs/services.nix @@ -1,3 +1,4 @@ +# homelab-docs-services.nix - Service documentation generator CLI { writeShellScriptBin, jq, @@ -9,376 +10,261 @@ writeShellScriptBin "homelab-docs-services" '' cat << 'EOF' # Service Catalog - > Complete service documentation with core options, feature integrations, and smart defaults + > Available services and their configuration options > > Generated on: $(date) - This document provides comprehensive documentation for homelab services, organized by: - - **Core Service Options**: The main service configuration - - **Feature Integrations**: Available monitoring, logging, and proxy features - - **Service Defaults**: What this service configures by default for each feature + This document catalogs all available homelab services, their configuration options, and integration capabilities. EOF - # Extract comprehensive service information - echo "Extracting service information..." >&2 - services_catalog=$(colmena eval -E ' - { nodes, pkgs, lib, ... }: + # Get all services and their configurations + services_catalog=$(colmena eval -E '{ nodes, pkgs, lib, ... }: let - # Helper to extract option information - extractOptions = path: options: - lib.flatten (lib.mapAttrsToList (name: value: - let - currentPath = path ++ [name]; - pathStr = lib.concatStringsSep "." currentPath; - in - if (value._type or null) == "option" then - [{ - name = pathStr; - type = value.type.description or "unknown"; - default = value.default or null; - defaultText = if value ? defaultText then value.defaultText.text or null else null; - description = value.description or "No description"; - readOnly = value.readOnly or false; - }] - else if lib.isAttrs value && !(lib.hasAttr "_type" value) then - extractOptions currentPath value - else [] - ) options); + # Collect all services from all nodes to build a complete catalog + allServiceConfigs = lib.flatten (lib.mapAttrsToList (nodeName: node: + if (node.config.homelab.enable or false) then + lib.mapAttrsToList (serviceName: service: { + inherit serviceName; + config = { + # Core service options + enable = service.enable or false; + port = service.port or null; + description = service.description or serviceName; + tags = service.tags or []; - # Get first node for option definitions - firstNode = lib.head (lib.attrValues nodes); - homelabServices = firstNode.options.homelab.services or {}; + # Integration options + monitoring = { + enabled = service.monitoring.enable or false; + metricsPath = service.monitoring.metrics.path or "/metrics"; + healthPath = service.monitoring.healthCheck.path or "/health"; + extraLabels = service.monitoring.extraLabels or {}; + }; - # Process each service - serviceInfo = lib.mapAttrs (serviceName: serviceOptions: + logging = { + enabled = service.logging.enable or false; + files = service.logging.files or []; + extraLabels = service.logging.extraLabels or {}; + }; + + proxy = { + enabled = service.proxy.enable or false; + subdomain = service.proxy.subdomain or serviceName; + enableAuth = service.proxy.enableAuth or false; + }; + + # Service-specific options (everything else) + serviceSpecific = removeAttrs service [ + "enable" "port" "description" "tags" + "monitoring" "logging" "proxy" + ]; + }; + deployedOn = nodeName; + }) (node.config.homelab.services or {}) + else [] + ) nodes); + + # Group by service name and merge configurations + serviceGroups = lib.groupBy (svc: svc.serviceName) allServiceConfigs; + + # Get unique services with merged configuration examples + uniqueServices = lib.mapAttrs (serviceName: instances: let - allOptions = extractOptions [] serviceOptions; - - # Separate core options from feature options - coreOptions = lib.filter (opt: - !(lib.hasPrefix "monitoring." opt.name) && - !(lib.hasPrefix "logging." opt.name) && - !(lib.hasPrefix "proxy." opt.name) - ) allOptions; - - monitoringOptions = lib.filter (opt: lib.hasPrefix "monitoring." opt.name) allOptions; - loggingOptions = lib.filter (opt: lib.hasPrefix "logging." opt.name) allOptions; - proxyOptions = lib.filter (opt: lib.hasPrefix "proxy." opt.name) allOptions; - - # Get actual service configuration to see what defaults are set - serviceConfigs = lib.mapAttrs (nodeName: node: - let - serviceConfig = node.config.homelab.services.''${serviceName} or null; - in - if serviceConfig != null then { - exists = true; - enabled = serviceConfig.enable or false; - # Extract the computed configuration values - monitoring = serviceConfig.monitoring or {}; - logging = serviceConfig.logging or {}; - proxy = serviceConfig.proxy or {}; - # Get other core options - coreConfig = removeAttrs serviceConfig ["monitoring" "logging" "proxy"]; - } else { - exists = false; - } - ) nodes; - - # Find a node where this service exists to get default values - nodeWithService = lib.findFirst (nodeName: serviceConfigs.''${nodeName}.exists) null (lib.attrNames nodes); - exampleConfig = if nodeWithService != null then serviceConfigs.''${nodeWithService} else null; - + # Take the first enabled instance as the canonical example + enabledInstances = lib.filter (inst: inst.config.enable) instances; + canonicalConfig = if enabledInstances != [] then (lib.head enabledInstances).config else (lib.head instances).config; in { inherit serviceName; - coreOptions = coreOptions; - features = { - monitoring = { - available = monitoringOptions != []; - options = monitoringOptions; - defaults = if exampleConfig != null then exampleConfig.monitoring else {}; - }; - logging = { - available = loggingOptions != []; - options = loggingOptions; - defaults = if exampleConfig != null then exampleConfig.logging else {}; - }; - proxy = { - available = proxyOptions != []; - options = proxyOptions; - defaults = if exampleConfig != null then exampleConfig.proxy else {}; - }; - }; - deployment = { - totalNodes = lib.length (lib.filter (cfg: cfg.exists) (lib.attrValues serviceConfigs)); - enabledNodes = lib.length (lib.filter (cfg: cfg.exists && cfg.enabled) (lib.attrValues serviceConfigs)); - }; + config = canonicalConfig; + deploymentCount = lib.length (lib.filter (inst: inst.config.enable) instances); + deployedOn = lib.unique (map (inst: inst.deployedOn or "unknown") enabledInstances); } - ) homelabServices; + ) serviceGroups; in { - services = serviceInfo; - totalServices = lib.length (lib.attrNames serviceInfo); - } - ') + services = uniqueServices; + totalUniqueServices = lib.length (lib.attrNames uniqueServices); + }') - total_services=$(echo "$services_catalog" | ${jq}/bin/jq -r '.totalServices') + total_services=$(echo "$services_catalog" | ${jq}/bin/jq -r '.totalUniqueServices') echo "## Overview" echo echo "**Total Available Services:** $total_services" echo - # Service matrix + # Create a summary table of services and their default integrations echo "## Service Integration Matrix" echo - echo "| Service | Core Options | Monitoring | Logging | Proxy | Deployments |" - echo "|---------|--------------|------------|---------|-------|-------------|" + echo "| Service | Monitoring | Logging | Proxy | Auth Default |" + echo "|---------|------------|---------|-------|--------------|" - echo "$services_catalog" | ${jq}/bin/jq -r '.services | keys[]' | sort | while read -r service; do + echo "$services_catalog" | ${jq}/bin/jq -r '.services | to_entries[] | .key' | sort | while read -r service; do service_data=$(echo "$services_catalog" | ${jq}/bin/jq -r ".services[\"$service\"]") - core_count=$(echo "$service_data" | ${jq}/bin/jq -r '.coreOptions | length') - has_monitoring=$(echo "$service_data" | ${jq}/bin/jq -r '.features.monitoring.available') - has_logging=$(echo "$service_data" | ${jq}/bin/jq -r '.features.logging.available') - has_proxy=$(echo "$service_data" | ${jq}/bin/jq -r '.features.proxy.available') - enabled_deployments=$(echo "$service_data" | ${jq}/bin/jq -r '.deployment.enabledNodes') + monitoring_enabled=$(echo "$service_data" | ${jq}/bin/jq -r '.config.monitoring.enabled') + logging_enabled=$(echo "$service_data" | ${jq}/bin/jq -r '.config.logging.enabled') + proxy_enabled=$(echo "$service_data" | ${jq}/bin/jq -r '.config.proxy.enabled') + auth_default=$(echo "$service_data" | ${jq}/bin/jq -r '.config.proxy.enableAuth') - monitoring_icon=$(if [[ "$has_monitoring" == "true" ]]; then echo "📊"; else echo "❌"; fi) - logging_icon=$(if [[ "$has_logging" == "true" ]]; then echo "📝"; else echo "❌"; fi) - proxy_icon=$(if [[ "$has_proxy" == "true" ]]; then echo "🔀"; else echo "❌"; fi) + monitoring_icon=$(if [[ "$monitoring_enabled" == "true" ]]; then echo "✅"; else echo "❌"; fi) + logging_icon=$(if [[ "$logging_enabled" == "true" ]]; then echo "✅"; else echo "❌"; fi) + proxy_icon=$(if [[ "$proxy_enabled" == "true" ]]; then echo "✅"; else echo "❌"; fi) + auth_icon=$(if [[ "$auth_default" == "true" ]]; then echo "🔒"; else echo "🌐"; fi) - echo "| \`$service\` | $core_count | $monitoring_icon | $logging_icon | $proxy_icon | $enabled_deployments |" + echo "| \`$service\` | $monitoring_icon | $logging_icon | $proxy_icon | $auth_icon |" done echo - echo "**Legend:** 📊📝🔀 = Feature available, ❌ = Feature not available" + echo "**Legend:** ✅ = Enabled by default, ❌ = Available but disabled, 🔒 = Auth required, 🌐 = Public access" echo - echo "## Service Documentation" + echo "## Service Reference" echo # Process each service - echo "$services_catalog" | ${jq}/bin/jq -r '.services | keys[]' | sort | while read -r service; do + echo "$services_catalog" | ${jq}/bin/jq -r '.services | to_entries[] | .key' | sort | while read -r service; do echo "### $service" echo + # Get service details service_data=$(echo "$services_catalog" | ${jq}/bin/jq -r ".services[\"$service\"]") - enabled_deployments=$(echo "$service_data" | ${jq}/bin/jq -r '.deployment.enabledNodes') - total_deployments=$(echo "$service_data" | ${jq}/bin/jq -r '.deployment.totalNodes') - if [[ "$total_deployments" -gt 0 ]]; then - echo "**Deployment Status:** $enabled_deployments/$total_deployments nodes have this service enabled" + description=$(echo "$service_data" | ${jq}/bin/jq -r '.config.description // "No description available"') + port=$(echo "$service_data" | ${jq}/bin/jq -r '.config.port // "N/A"') + tags=$(echo "$service_data" | ${jq}/bin/jq -r '.config.tags | join(", ")') + deployment_count=$(echo "$service_data" | ${jq}/bin/jq -r '.deploymentCount') + deployed_on=$(echo "$service_data" | ${jq}/bin/jq -r '.deployedOn | join(", ")') + + echo "**Description:** $description" + echo + echo "**Default Port:** \`$port\`" + echo + if [[ -n "$tags" && "$tags" != "" ]]; then + echo "**Tags:** $tags" + echo + fi + echo "**Current Deployments:** $deployment_count instance(s) on: $deployed_on" + echo + + # Integration Status Overview + monitoring_enabled=$(echo "$service_data" | ${jq}/bin/jq -r '.config.monitoring.enabled') + logging_enabled=$(echo "$service_data" | ${jq}/bin/jq -r '.config.logging.enabled') + proxy_enabled=$(echo "$service_data" | ${jq}/bin/jq -r '.config.proxy.enabled') + + echo "#### Default Integration Status" + echo + echo "| Integration | Status | Default Configuration |" + echo "|-------------|--------|----------------------|" + + # Monitoring status + if [[ "$monitoring_enabled" == "true" ]]; then + metrics_path=$(echo "$service_data" | ${jq}/bin/jq -r '.config.monitoring.metricsPath') + health_path=$(echo "$service_data" | ${jq}/bin/jq -r '.config.monitoring.healthPath') + echo "| 📊 Monitoring | ✅ **Enabled** | Metrics: \`$metrics_path\`, Health: \`$health_path\` |" else - echo "**Deployment Status:** Available but not configured" + echo "| 📊 Monitoring | ❌ Disabled | Available but requires \`monitoring.enable = true\` |" + fi + + # Logging status + if [[ "$logging_enabled" == "true" ]]; then + log_files=$(echo "$service_data" | ${jq}/bin/jq -r '.config.logging.files | length') + if [[ "$log_files" -gt 0 ]]; then + echo "| 📝 Logging | ✅ **Enabled** | Collecting $log_files log file(s) |" + else + echo "| 📝 Logging | ✅ **Enabled** | Auto-configured log collection |" + fi + else + echo "| 📝 Logging | ❌ Disabled | Available but requires \`logging.enable = true\` |" + fi + + # Proxy status + if [[ "$proxy_enabled" == "true" ]]; then + subdomain=$(echo "$service_data" | ${jq}/bin/jq -r '.config.proxy.subdomain') + enable_auth=$(echo "$service_data" | ${jq}/bin/jq -r '.config.proxy.enableAuth') + auth_status=$(if [[ "$enable_auth" == "true" ]]; then echo "🔒 Auth required"; else echo "🌐 Public access"; fi) + echo "| 🔀 Proxy | ✅ **Enabled** | Subdomain: \`$subdomain\`, $auth_status |" + else + echo "| 🔀 Proxy | ❌ Disabled | Available but requires \`proxy.enable = true\` |" + fi + + echo + + # Core Configuration + echo "#### Core Configuration" + echo + echo "\`\`\`nix" + echo "homelab.services.$service = {" + echo " enable = true;" + if [[ "$port" != "N/A" ]]; then + echo " port = $port;" + fi + echo " description = \"$description\";" + if [[ -n "$tags" && "$tags" != "" ]]; then + echo " tags = [ $(echo "$tags" | sed 's/, /" "/g' | sed 's/^/"/; s/$/"/') ];" fi echo - - # Core Service Configuration - echo "#### Core Service Options" - echo - echo "The main configuration options for $service:" - echo - echo '```nix' - echo "homelab.services.$service = {" - - echo "$service_data" | ${jq}/bin/jq -r '.coreOptions[] | @base64' | while IFS= read -r option_b64; do - option=$(echo "$option_b64" | base64 -d) - - name=$(echo "$option" | ${jq}/bin/jq -r '.name') - type=$(echo "$option" | ${jq}/bin/jq -r '.type') - default_val=$(echo "$option" | ${jq}/bin/jq -r '.default') - description=$(echo "$option" | ${jq}/bin/jq -r '.description') - read_only=$(echo "$option" | ${jq}/bin/jq -r '.readOnly') - - if [[ "$read_only" == "true" ]]; then - continue - fi - - clean_description=$(echo "$description" | sed 's/"/\\"/g' | tr -d $'\n\r') - - if [[ "$default_val" == "null" ]]; then - echo " # $name = <$type>; # $clean_description" - else - echo " $name = $default_val; # $clean_description" - fi - done - + echo " # Default integrations (adjust as needed)" + if [[ "$monitoring_enabled" == "true" ]]; then + echo " monitoring.enable = true; # ✅ Enabled by default" + else + echo " # monitoring.enable = true; # ❌ Disabled by default" + fi + if [[ "$logging_enabled" == "true" ]]; then + echo " logging.enable = true; # ✅ Enabled by default" + else + echo " # logging.enable = true; # ❌ Disabled by default" + fi + if [[ "$proxy_enabled" == "true" ]]; then + echo " proxy.enable = true; # ✅ Enabled by default" + else + echo " # proxy.enable = true; # ❌ Disabled by default" + fi echo "};" - echo '```' + echo "\`\`\`" echo - # Feature Integrations - has_monitoring=$(echo "$service_data" | ${jq}/bin/jq -r '.features.monitoring.available') - has_logging=$(echo "$service_data" | ${jq}/bin/jq -r '.features.logging.available') - has_proxy=$(echo "$service_data" | ${jq}/bin/jq -r '.features.proxy.available') - - if [[ "$has_monitoring" == "true" || "$has_logging" == "true" || "$has_proxy" == "true" ]]; then - echo "#### Feature Integrations" + # Service-specific options + service_specific=$(echo "$service_data" | ${jq}/bin/jq -r '.config.serviceSpecific') + if [[ "$service_specific" != "{}" && "$service_specific" != "null" ]]; then + echo "#### Service-Specific Options" + echo + echo "Available configuration options for $service:" + echo + echo "\`\`\`nix" + echo "homelab.services.$service = {" + echo " # ... core options above ..." + echo + echo " # Service-specific configuration" + echo "$service_specific" | ${jq}/bin/jq -r 'to_entries[] | " \(.key) = \(.value | tostring);"' + echo "};" + echo "\`\`\`" echo - - # Monitoring Feature - if [[ "$has_monitoring" == "true" ]]; then - echo "##### 📊 Monitoring Integration" - echo - echo "Available monitoring options:" - echo - echo '```nix' - echo "homelab.services.$service = {" - echo " # ... core options above ..." - echo - - echo "$service_data" | ${jq}/bin/jq -r '.features.monitoring.options[] | @base64' | while IFS= read -r option_b64; do - option=$(echo "$option_b64" | base64 -d) - - name=$(echo "$option" | ${jq}/bin/jq -r '.name') - type=$(echo "$option" | ${jq}/bin/jq -r '.type') - default_val=$(echo "$option" | ${jq}/bin/jq -r '.default') - description=$(echo "$option" | ${jq}/bin/jq -r '.description') - read_only=$(echo "$option" | ${jq}/bin/jq -r '.readOnly') - - if [[ "$read_only" == "true" ]]; then - continue - fi - - clean_description=$(echo "$description" | sed 's/"/\\"/g' | tr -d $'\n\r') - - if [[ "$default_val" == "null" ]]; then - echo " # $name = <$type>; # $clean_description" - else - echo " $name = $default_val; # $clean_description" - fi - done - - echo "};" - echo '```' - - # Show service-specific monitoring defaults - monitoring_defaults=$(echo "$service_data" | ${jq}/bin/jq -r '.features.monitoring.defaults') - if [[ "$monitoring_defaults" != "{}" && "$monitoring_defaults" != "null" ]]; then - echo - echo "**$service sets these monitoring defaults:**" - echo '```nix' - echo "$monitoring_defaults" | ${jq}/bin/jq -r 'to_entries[] | " \(.key) = \(.value);"' - echo '```' - fi - echo - fi - - # Logging Feature - if [[ "$has_logging" == "true" ]]; then - echo "##### 📝 Logging Integration" - echo - echo "Available logging options:" - echo - echo '```nix' - echo "homelab.services.$service = {" - echo " # ... core options above ..." - echo - - echo "$service_data" | ${jq}/bin/jq -r '.features.logging.options[] | @base64' | while IFS= read -r option_b64; do - option=$(echo "$option_b64" | base64 -d) - - name=$(echo "$option" | ${jq}/bin/jq -r '.name') - type=$(echo "$option" | ${jq}/bin/jq -r '.type') - default_val=$(echo "$option" | ${jq}/bin/jq -r '.default') - description=$(echo "$option" | ${jq}/bin/jq -r '.description') - read_only=$(echo "$option" | ${jq}/bin/jq -r '.readOnly') - - if [[ "$read_only" == "true" ]]; then - continue - fi - - clean_description=$(echo "$description" | sed 's/"/\\"/g' | tr -d $'\n\r') - - if [[ "$default_val" == "null" ]]; then - echo " # $name = <$type>; # $clean_description" - else - echo " $name = $default_val; # $clean_description" - fi - done - - echo "};" - echo '```' - - # Show service-specific logging defaults - logging_defaults=$(echo "$service_data" | ${jq}/bin/jq -r '.features.logging.defaults') - if [[ "$logging_defaults" != "{}" && "$logging_defaults" != "null" ]]; then - echo - echo "**$service sets these logging defaults:**" - echo '```nix' - echo "$logging_defaults" | ${jq}/bin/jq -r 'to_entries[] | " \(.key) = \(.value);"' - echo '```' - fi - echo - fi - - # Proxy Feature - if [[ "$has_proxy" == "true" ]]; then - echo "##### 🔀 Proxy Integration" - echo - echo "Available proxy options:" - echo - echo '```nix' - echo "homelab.services.$service = {" - echo " # ... core options above ..." - echo - - echo "$service_data" | ${jq}/bin/jq -r '.features.proxy.options[] | @base64' | while IFS= read -r option_b64; do - option=$(echo "$option_b64" | base64 -d) - - name=$(echo "$option" | ${jq}/bin/jq -r '.name') - type=$(echo "$option" | ${jq}/bin/jq -r '.type') - default_val=$(echo "$option" | ${jq}/bin/jq -r '.default') - description=$(echo "$option" | ${jq}/bin/jq -r '.description') - read_only=$(echo "$option" | ${jq}/bin/jq -r '.readOnly') - - if [[ "$read_only" == "true" ]]; then - continue - fi - - clean_description=$(echo "$description" | sed 's/"/\\"/g' | tr -d $'\n\r') - - if [[ "$default_val" == "null" ]]; then - echo " # $name = <$type>; # $clean_description" - else - echo " $name = $default_val; # $clean_description" - fi - done - - echo "};" - echo '```' - - # Show service-specific proxy defaults - proxy_defaults=$(echo "$service_data" | ${jq}/bin/jq -r '.features.proxy.defaults') - if [[ "$proxy_defaults" != "{}" && "$proxy_defaults" != "null" ]]; then - echo - echo "**$service sets these proxy defaults:**" - echo '```nix' - echo "$proxy_defaults" | ${jq}/bin/jq -r 'to_entries[] | " \(.key) = \(.value);"' - echo '```' - fi - echo - fi fi echo "---" echo done - echo "## Feature Reference" + echo "## Integration Summary" echo - echo "### Integration Features" + echo "### Available Integration Types" echo - echo "Homelab services can integrate with three main features:" + echo "| Integration | Purpose | Default Behavior | Configuration |" + echo "|-------------|---------|------------------|---------------|" + echo "| **📊 Monitoring** | Prometheus metrics + health checks | Service-dependent | \`monitoring.enable = true\` |" + echo "| **📝 Logging** | Centralized log collection | Service-dependent | \`logging.enable = true\` |" + echo "| **🔀 Proxy** | Reverse proxy with SSL + auth | Service-dependent | \`proxy.enable = true\` |" echo - echo "- **📊 Monitoring**: Prometheus metrics and health checks" - echo "- **📝 Logging**: Centralized log collection with Promtail/Loki" - echo "- **🔀 Proxy**: Reverse proxy with SSL and authentication" + echo "### Integration Benefits" echo - echo "Each service can import these features and set service-specific defaults." + echo "- **🔄 Automatic Discovery:** Enabled integrations are automatically discovered by fleet-wide services" + echo "- **📊 Unified Monitoring:** All metrics and health checks appear in Prometheus/Grafana" + echo "- **📝 Centralized Logging:** All logs are collected and indexed in Loki" + echo "- **🌐 Consistent Access:** All services get consistent subdomain access with SSL" + echo "- **🎯 Smart Defaults:** Each service comes with sensible default configurations" echo echo "---" echo - echo "*This documentation is generated from actual NixOS module evaluations.*" + echo "*This service catalog is generated from actual service configurations across your homelab fleet.*" ''