services...
This commit is contained in:
parent
73d2f44d74
commit
8552656731
15 changed files with 918 additions and 490 deletions
|
|
@ -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**: tir 29 jul 16:57:16 CEST 2025
|
||||
- **Generated**: ons 30 jul 00:20:46 CEST 2025
|
||||
|
||||
## 🛠️ Management Tools
|
||||
|
||||
|
|
|
|||
|
|
@ -11,15 +11,15 @@
|
|||
|--------|-------|
|
||||
| Total Nodes | 2 |
|
||||
| Homelab-Enabled Nodes | 2 |
|
||||
| Unique Services | 1 |
|
||||
| Service Instances | 1 |
|
||||
| Unique Services | 4 |
|
||||
| Service Instances | 4 |
|
||||
|
||||
## Node Status
|
||||
|
||||
| Node | Homelab | Environment | Services | Monitoring | Backups | Proxy |
|
||||
|------|---------|-------------|----------|------------|---------|-------|
|
||||
| `photos` | ✅ | production | 1 | ✅ | ❌ | ❌ |
|
||||
| `sandbox` | ✅ | production | 0 | ✅ | ✅ | ❌ |
|
||||
| `sandbox` | ✅ | production | 3 | ✅ | ✅ | ❌ |
|
||||
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@
|
|||
| Node | Service Count | Services |
|
||||
|------|---------------|----------|
|
||||
| `photos` | 1 | minio |
|
||||
| `sandbox` | 0 | |
|
||||
| `sandbox` | 3 | gatus, grafana, prometheus |
|
||||
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -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 | |
|
||||
|
||||
---
|
||||
|
||||
|
|
|
|||
452
docs/services.md
452
docs/services.md
|
|
@ -1,10 +1,13 @@
|
|||
# Service Catalog
|
||||
|
||||
> Available services and their configuration options
|
||||
> Complete service documentation with core options, feature integrations, and smart defaults
|
||||
>
|
||||
> Generated on: $(date)
|
||||
|
||||
This document catalogs all available homelab services, their configuration options, and integration capabilities.
|
||||
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
|
||||
|
||||
## Overview
|
||||
|
||||
|
|
@ -12,142 +15,252 @@ This document catalogs all available homelab services, their configuration optio
|
|||
|
||||
## Service Integration Matrix
|
||||
|
||||
| Service | Monitoring | Logging | Proxy | Auth Default |
|
||||
|---------|------------|---------|-------|--------------|
|
||||
| `gatus` | ❌ | ❌ | ❌ | 🌐 |
|
||||
| `grafana` | ❌ | ❌ | ❌ | 🌐 |
|
||||
| `minio` | ❌ | ❌ | ❌ | 🌐 |
|
||||
| `prometheus` | ❌ | ❌ | ❌ | 🌐 |
|
||||
| Service | Core Options | Monitoring | Logging | Proxy | Deployments |
|
||||
|---------|--------------|------------|---------|-------|-------------|
|
||||
| `gatus` | 11 | 📊 | 📝 | 🔀 | 1 |
|
||||
| `grafana` | 3 | 📊 | 📝 | 🔀 | 1 |
|
||||
| `minio` | 4 | ❌ | ❌ | ❌ | 1 |
|
||||
| `prometheus` | 12 | 📊 | 📝 | 🔀 | 1 |
|
||||
|
||||
**Legend:** ✅ = Enabled by default, ❌ = Available but disabled, 🔒 = Auth required, 🌐 = Public access
|
||||
**Legend:** 📊📝🔀 = Feature available, ❌ = Feature not available
|
||||
|
||||
## Service Reference
|
||||
## Service Documentation
|
||||
|
||||
### gatus
|
||||
|
||||
**Description:** Gatus Status Page
|
||||
**Deployment Status:** 1/2 nodes have this service enabled
|
||||
|
||||
**Default Port:** `8080`
|
||||
#### Core Service Options
|
||||
|
||||
**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
|
||||
The main configuration options for gatus:
|
||||
|
||||
```nix
|
||||
homelab.services.gatus = {
|
||||
enable = true;
|
||||
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
|
||||
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
|
||||
};
|
||||
```
|
||||
|
||||
#### Service-Specific Options
|
||||
#### Feature Integrations
|
||||
|
||||
Available configuration options for gatus:
|
||||
##### 📊 Monitoring Integration
|
||||
|
||||
Available monitoring options:
|
||||
|
||||
```nix
|
||||
homelab.services.gatus = {
|
||||
# ... core options above ...
|
||||
|
||||
# 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"};
|
||||
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 = <null or string>; # 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 = <null or string>; # 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};
|
||||
```
|
||||
|
||||
##### 📝 Logging Integration
|
||||
|
||||
Available logging options:
|
||||
|
||||
```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 = <null or (submodule)>; # No description
|
||||
logging.parsing.extractFields = []; # No description
|
||||
# logging.parsing.regex = <null or string>; # No description
|
||||
};
|
||||
```
|
||||
|
||||
**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
|
||||
|
||||
**Description:** Grafana Metrics Dashboard
|
||||
**Deployment Status:** 1/2 nodes have this service enabled
|
||||
|
||||
**Default Port:** `3000`
|
||||
#### Core Service Options
|
||||
|
||||
**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
|
||||
The main configuration options for grafana:
|
||||
|
||||
```nix
|
||||
homelab.services.grafana = {
|
||||
enable = true;
|
||||
port = 3000;
|
||||
description = "Grafana Metrics Dashboard";
|
||||
|
||||
# Default integrations (adjust as needed)
|
||||
# monitoring.enable = true; # ❌ Disabled by default
|
||||
# logging.enable = true; # ❌ Disabled by default
|
||||
# proxy.enable = true; # ❌ Disabled by default
|
||||
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 = <null or string>; # 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 = <null or string>; # 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};
|
||||
```
|
||||
|
||||
##### 📝 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 = <null or (submodule)>; # No description
|
||||
logging.parsing.extractFields = []; # No description
|
||||
# logging.parsing.regex = <null or string>; # No description
|
||||
};
|
||||
```
|
||||
|
||||
**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
|
||||
|
||||
**Description:** minio
|
||||
**Deployment Status:** 1/2 nodes have this service enabled
|
||||
|
||||
**Default Port:** `9000`
|
||||
#### Core Service Options
|
||||
|
||||
**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
|
||||
The main configuration options for minio:
|
||||
|
||||
```nix
|
||||
homelab.services.minio = {
|
||||
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;
|
||||
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).
|
||||
};
|
||||
```
|
||||
|
||||
|
|
@ -155,75 +268,132 @@ homelab.services.minio = {
|
|||
|
||||
### prometheus
|
||||
|
||||
**Description:** Prometheus Monitoring Server
|
||||
**Deployment Status:** 1/2 nodes have this service enabled
|
||||
|
||||
**Default Port:** `9090`
|
||||
#### Core Service Options
|
||||
|
||||
**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
|
||||
The main configuration options for prometheus:
|
||||
|
||||
```nix
|
||||
homelab.services.prometheus = {
|
||||
enable = true;
|
||||
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
|
||||
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
|
||||
};
|
||||
```
|
||||
|
||||
#### Service-Specific Options
|
||||
#### Feature Integrations
|
||||
|
||||
Available configuration options for prometheus:
|
||||
##### 📊 Monitoring Integration
|
||||
|
||||
Available monitoring options:
|
||||
|
||||
```nix
|
||||
homelab.services.prometheus = {
|
||||
# ... core options above ...
|
||||
|
||||
# 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"];
|
||||
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 = <null or string>; # 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 = <null or string>; # 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};
|
||||
```
|
||||
|
||||
##### 📝 Logging Integration
|
||||
|
||||
Available logging options:
|
||||
|
||||
```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 = <null or (submodule)>; # No description
|
||||
logging.parsing.extractFields = []; # No description
|
||||
# logging.parsing.regex = <null or string>; # No description
|
||||
};
|
||||
```
|
||||
|
||||
**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;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Integration Summary
|
||||
## Feature Reference
|
||||
|
||||
### Available Integration Types
|
||||
### Integration 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` |
|
||||
Homelab services can integrate with three main features:
|
||||
|
||||
### Integration Benefits
|
||||
- **📊 Monitoring**: Prometheus metrics and health checks
|
||||
- **📝 Logging**: Centralized log collection with Promtail/Loki
|
||||
- **🔀 Proxy**: Reverse proxy with SSL and authentication
|
||||
|
||||
- **🔄 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
|
||||
Each service can import these features and set service-specific defaults.
|
||||
|
||||
---
|
||||
|
||||
*This service catalog is generated from actual service configurations across your homelab fleet.*
|
||||
*This documentation is generated from actual NixOS module evaluations.*
|
||||
|
|
|
|||
|
|
@ -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";
|
||||
|
|
|
|||
|
|
@ -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,10 +60,10 @@ in {
|
|||
};
|
||||
};
|
||||
|
||||
config = mkIf (cfg.enable && cfg.logging.enable) {
|
||||
homelab.logging.sources =
|
||||
[
|
||||
{
|
||||
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 = {
|
||||
|
|
@ -69,19 +78,15 @@ in {
|
|||
environment = homelabCfg.environment;
|
||||
};
|
||||
pipelineStages =
|
||||
mkIf (cfg.logging.parsing.regex != null) [
|
||||
{
|
||||
(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;
|
||||
})
|
||||
++ 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,11 +79,10 @@ in {
|
|||
};
|
||||
|
||||
# Generate the homelab config automatically when service is enabled
|
||||
config = mkIf (cfg.enable && cfg.monitoring.enable) {
|
||||
homelab.monitoring = {
|
||||
metrics =
|
||||
[
|
||||
{
|
||||
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;
|
||||
|
|
@ -75,13 +96,12 @@ in {
|
|||
node = homelabCfg.hostname;
|
||||
environment = homelabCfg.environment;
|
||||
};
|
||||
}
|
||||
]
|
||||
++ cfg.monitoring.metrics.extraEndpoints;
|
||||
})
|
||||
++ cfg.monitoring.metrics.extraEndpoints
|
||||
);
|
||||
|
||||
healthChecks =
|
||||
[
|
||||
{
|
||||
healthChecks = mkIf hasHealthCheckConfig (
|
||||
(optional (cfg.monitoring.healthCheck.path != null) {
|
||||
name = "${serviceName}-health";
|
||||
host = homelabCfg.hostname;
|
||||
port = cfg.port;
|
||||
|
|
@ -100,9 +120,9 @@ in {
|
|||
environment = homelabCfg.environment;
|
||||
};
|
||||
enabled = true;
|
||||
}
|
||||
]
|
||||
++ cfg.monitoring.healthCheck.extraChecks;
|
||||
})
|
||||
++ 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;
|
||||
}
|
||||
|
||||
# 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";
|
||||
}
|
||||
];
|
||||
};
|
||||
homelab.services.${serviceName}.monitoring = {
|
||||
metrics.path = "/metrics";
|
||||
healthCheck.path = "/-/healthy"; # ✅ Enables health checks
|
||||
healthCheck.conditions = ["[STATUS] == 200" "[RESPONSE_TIME] < 1000"];
|
||||
|
||||
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;
|
||||
};
|
||||
})
|
||||
}
|
||||
]);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
138
pkgs/homelab-docs/service-evaluator.nix
Normal file
138
pkgs/homelab-docs/service-evaluator.nix
Normal file
|
|
@ -0,0 +1,138 @@
|
|||
# service-evaluator.nix - Pure Nix evaluation logic for service documentation
|
||||
{
|
||||
nodes,
|
||||
pkgs,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
# Helper to recursively extract option information
|
||||
extractOptions = path: options: let
|
||||
pathStr = lib.concatStringsSep "." path;
|
||||
in
|
||||
lib.flatten (lib.mapAttrsToList (
|
||||
name: value: let
|
||||
currentPath = path ++ [name];
|
||||
currentPathStr = lib.concatStringsSep "." currentPath;
|
||||
in
|
||||
if (value._type or null) == "option"
|
||||
then
|
||||
# This is an actual NixOS option
|
||||
[
|
||||
{
|
||||
name = currentPathStr;
|
||||
type = value.type.description or (builtins.typeOf (value.default or null));
|
||||
default = value.default or null;
|
||||
defaultText =
|
||||
if value ? defaultText
|
||||
then value.defaultText.text or null
|
||||
else null;
|
||||
description = value.description or "No description available";
|
||||
example = value.example or null;
|
||||
readOnly = value.readOnly or false;
|
||||
}
|
||||
]
|
||||
else if lib.isAttrs value && !(lib.hasAttr "_type" value)
|
||||
then
|
||||
# This is a nested attribute set, recurse
|
||||
extractOptions currentPath value
|
||||
else
|
||||
# Skip other types
|
||||
[]
|
||||
)
|
||||
options);
|
||||
|
||||
# Get service options from the first node (they should be the same across nodes)
|
||||
firstNode = lib.head (lib.attrValues nodes);
|
||||
homelabServices = firstNode.options.homelab.services or {};
|
||||
|
||||
# Extract all services and their options
|
||||
serviceDefinitions =
|
||||
lib.mapAttrs (serviceName: serviceOptions: {
|
||||
inherit serviceName;
|
||||
options = extractOptions [] serviceOptions;
|
||||
features = let
|
||||
optionNames = map (opt: opt.name) (extractOptions [] serviceOptions);
|
||||
in {
|
||||
hasMonitoring = lib.any (name: lib.hasPrefix "monitoring" name) optionNames;
|
||||
hasLogging = lib.any (name: lib.hasPrefix "logging" name) optionNames;
|
||||
hasProxy = lib.any (name: lib.hasPrefix "proxy" name) optionNames;
|
||||
};
|
||||
})
|
||||
homelabServices;
|
||||
|
||||
# Also get all services that exist in actual configurations (for deployment info)
|
||||
allConfiguredServices = lib.unique (lib.flatten (lib.mapAttrsToList (
|
||||
nodeName: node:
|
||||
if (node.config.homelab.enable or false)
|
||||
then lib.attrNames (node.config.homelab.services or {})
|
||||
else []
|
||||
)
|
||||
nodes));
|
||||
|
||||
# For each service, get deployment info
|
||||
serviceDeployments = lib.listToAttrs (map (serviceName: {
|
||||
name = serviceName;
|
||||
value =
|
||||
lib.foldl (
|
||||
acc: nodeName: let
|
||||
node = nodes.${nodeName};
|
||||
serviceConfig = node.config.homelab.services.${serviceName} or null;
|
||||
isEnabled =
|
||||
if serviceConfig != null
|
||||
then serviceConfig.enable or false
|
||||
else false;
|
||||
in
|
||||
if serviceConfig != null
|
||||
then
|
||||
acc
|
||||
// {
|
||||
totalNodes = acc.totalNodes + 1;
|
||||
enabledNodes =
|
||||
acc.enabledNodes
|
||||
+ (
|
||||
if isEnabled
|
||||
then 1
|
||||
else 0
|
||||
);
|
||||
nodeNames = acc.nodeNames ++ [nodeName];
|
||||
enabledNodeNames =
|
||||
acc.enabledNodeNames
|
||||
++ (
|
||||
if isEnabled
|
||||
then [nodeName]
|
||||
else []
|
||||
);
|
||||
}
|
||||
else acc
|
||||
) {
|
||||
totalNodes = 0;
|
||||
enabledNodes = 0;
|
||||
nodeNames = [];
|
||||
enabledNodeNames = [];
|
||||
} (lib.attrNames nodes);
|
||||
})
|
||||
allConfiguredServices);
|
||||
|
||||
# Combine service definitions with deployment info
|
||||
servicesWithDeployment =
|
||||
lib.mapAttrs (
|
||||
serviceName: serviceData:
|
||||
serviceData
|
||||
// {
|
||||
deployment =
|
||||
serviceDeployments.${
|
||||
serviceName
|
||||
} or {
|
||||
totalNodes = 0;
|
||||
enabledNodes = 0;
|
||||
nodeNames = [];
|
||||
enabledNodeNames = [];
|
||||
};
|
||||
}
|
||||
)
|
||||
serviceDefinitions;
|
||||
in {
|
||||
services = servicesWithDeployment;
|
||||
totalServices = lib.length (lib.attrNames servicesWithDeployment);
|
||||
allConfiguredServices = allConfiguredServices;
|
||||
}
|
||||
|
|
@ -1,4 +1,3 @@
|
|||
# homelab-docs-services.nix - Service documentation generator CLI
|
||||
{
|
||||
writeShellScriptBin,
|
||||
jq,
|
||||
|
|
@ -10,261 +9,376 @@ writeShellScriptBin "homelab-docs-services" ''
|
|||
cat << 'EOF'
|
||||
# Service Catalog
|
||||
|
||||
> Available services and their configuration options
|
||||
> Complete service documentation with core options, feature integrations, and smart defaults
|
||||
>
|
||||
> Generated on: $(date)
|
||||
|
||||
This document catalogs all available homelab services, their configuration options, and integration capabilities.
|
||||
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
|
||||
|
||||
EOF
|
||||
|
||||
# Get all services and their configurations
|
||||
services_catalog=$(colmena eval -E '{ nodes, pkgs, lib, ... }:
|
||||
# Extract comprehensive service information
|
||||
echo "Extracting service information..." >&2
|
||||
services_catalog=$(colmena eval -E '
|
||||
{ nodes, pkgs, lib, ... }:
|
||||
let
|
||||
# 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 [];
|
||||
|
||||
# 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 {};
|
||||
};
|
||||
|
||||
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 {})
|
||||
# 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 []
|
||||
) nodes);
|
||||
) options);
|
||||
|
||||
# Group by service name and merge configurations
|
||||
serviceGroups = lib.groupBy (svc: svc.serviceName) allServiceConfigs;
|
||||
# Get first node for option definitions
|
||||
firstNode = lib.head (lib.attrValues nodes);
|
||||
homelabServices = firstNode.options.homelab.services or {};
|
||||
|
||||
# Get unique services with merged configuration examples
|
||||
uniqueServices = lib.mapAttrs (serviceName: instances:
|
||||
# Process each service
|
||||
serviceInfo = lib.mapAttrs (serviceName: serviceOptions:
|
||||
let
|
||||
# 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;
|
||||
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;
|
||||
|
||||
in {
|
||||
inherit serviceName;
|
||||
config = canonicalConfig;
|
||||
deploymentCount = lib.length (lib.filter (inst: inst.config.enable) instances);
|
||||
deployedOn = lib.unique (map (inst: inst.deployedOn or "unknown") enabledInstances);
|
||||
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));
|
||||
};
|
||||
}
|
||||
) serviceGroups;
|
||||
) homelabServices;
|
||||
|
||||
in {
|
||||
services = uniqueServices;
|
||||
totalUniqueServices = lib.length (lib.attrNames uniqueServices);
|
||||
}')
|
||||
services = serviceInfo;
|
||||
totalServices = lib.length (lib.attrNames serviceInfo);
|
||||
}
|
||||
')
|
||||
|
||||
total_services=$(echo "$services_catalog" | ${jq}/bin/jq -r '.totalUniqueServices')
|
||||
total_services=$(echo "$services_catalog" | ${jq}/bin/jq -r '.totalServices')
|
||||
|
||||
echo "## Overview"
|
||||
echo
|
||||
echo "**Total Available Services:** $total_services"
|
||||
echo
|
||||
|
||||
# Create a summary table of services and their default integrations
|
||||
# Service matrix
|
||||
echo "## Service Integration Matrix"
|
||||
echo
|
||||
echo "| Service | Monitoring | Logging | Proxy | Auth Default |"
|
||||
echo "|---------|------------|---------|-------|--------------|"
|
||||
echo "| Service | Core Options | Monitoring | Logging | Proxy | Deployments |"
|
||||
echo "|---------|--------------|------------|---------|-------|-------------|"
|
||||
|
||||
echo "$services_catalog" | ${jq}/bin/jq -r '.services | to_entries[] | .key' | sort | while read -r service; do
|
||||
echo "$services_catalog" | ${jq}/bin/jq -r '.services | keys[]' | sort | while read -r service; do
|
||||
service_data=$(echo "$services_catalog" | ${jq}/bin/jq -r ".services[\"$service\"]")
|
||||
|
||||
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')
|
||||
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_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)
|
||||
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)
|
||||
|
||||
echo "| \`$service\` | $monitoring_icon | $logging_icon | $proxy_icon | $auth_icon |"
|
||||
echo "| \`$service\` | $core_count | $monitoring_icon | $logging_icon | $proxy_icon | $enabled_deployments |"
|
||||
done
|
||||
|
||||
echo
|
||||
echo "**Legend:** ✅ = Enabled by default, ❌ = Available but disabled, 🔒 = Auth required, 🌐 = Public access"
|
||||
echo "**Legend:** 📊📝🔀 = Feature available, ❌ = Feature not available"
|
||||
echo
|
||||
|
||||
echo "## Service Reference"
|
||||
echo "## Service Documentation"
|
||||
echo
|
||||
|
||||
# Process each service
|
||||
echo "$services_catalog" | ${jq}/bin/jq -r '.services | to_entries[] | .key' | sort | while read -r service; do
|
||||
echo "$services_catalog" | ${jq}/bin/jq -r '.services | keys[]' | 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')
|
||||
|
||||
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\` |"
|
||||
if [[ "$total_deployments" -gt 0 ]]; then
|
||||
echo "**Deployment Status:** $enabled_deployments/$total_deployments nodes have this service enabled"
|
||||
else
|
||||
echo "| 📊 Monitoring | ❌ Disabled | Available but requires \`monitoring.enable = true\` |"
|
||||
echo "**Deployment Status:** Available but not configured"
|
||||
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"
|
||||
# Core Service Configuration
|
||||
echo "#### Core Service Options"
|
||||
echo
|
||||
echo "\`\`\`nix"
|
||||
echo "The main configuration options for $service:"
|
||||
echo
|
||||
echo '```nix'
|
||||
echo "homelab.services.$service = {"
|
||||
echo " enable = true;"
|
||||
if [[ "$port" != "N/A" ]]; then
|
||||
echo " port = $port;"
|
||||
|
||||
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
|
||||
echo " description = \"$description\";"
|
||||
if [[ -n "$tags" && "$tags" != "" ]]; then
|
||||
echo " tags = [ $(echo "$tags" | sed 's/, /" "/g' | sed 's/^/"/; s/$/"/') ];"
|
||||
fi
|
||||
echo
|
||||
echo " # Default integrations (adjust as needed)"
|
||||
if [[ "$monitoring_enabled" == "true" ]]; then
|
||||
echo " monitoring.enable = true; # ✅ Enabled by default"
|
||||
|
||||
clean_description=$(echo "$description" | sed 's/"/\\"/g' | tr -d $'\n\r')
|
||||
|
||||
if [[ "$default_val" == "null" ]]; then
|
||||
echo " # $name = <$type>; # $clean_description"
|
||||
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"
|
||||
echo " $name = $default_val; # $clean_description"
|
||||
fi
|
||||
done
|
||||
|
||||
echo "};"
|
||||
echo "\`\`\`"
|
||||
echo '```'
|
||||
echo
|
||||
|
||||
# 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"
|
||||
# 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"
|
||||
echo
|
||||
echo "Available configuration options for $service:"
|
||||
|
||||
# Monitoring Feature
|
||||
if [[ "$has_monitoring" == "true" ]]; then
|
||||
echo "##### 📊 Monitoring Integration"
|
||||
echo
|
||||
echo "\`\`\`nix"
|
||||
echo "Available monitoring options:"
|
||||
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 "$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 "\`\`\`"
|
||||
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 "## Integration Summary"
|
||||
echo "## Feature Reference"
|
||||
echo
|
||||
echo "### Available Integration Types"
|
||||
echo "### Integration Features"
|
||||
echo
|
||||
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 "Homelab services can integrate with three main features:"
|
||||
echo
|
||||
echo "### Integration Benefits"
|
||||
echo "- **📊 Monitoring**: Prometheus metrics and health checks"
|
||||
echo "- **📝 Logging**: Centralized log collection with Promtail/Loki"
|
||||
echo "- **🔀 Proxy**: Reverse proxy with SSL and authentication"
|
||||
echo
|
||||
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 "Each service can import these features and set service-specific defaults."
|
||||
echo
|
||||
echo "---"
|
||||
echo
|
||||
echo "*This service catalog is generated from actual service configurations across your homelab fleet.*"
|
||||
echo "*This documentation is generated from actual NixOS module evaluations.*"
|
||||
''
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue