homelab/pkgs/homelab-docs/services.nix
plasmagoat 73d2f44d74
Some checks failed
Test / tests (push) Failing after 2m27s
/ OpenTofu (push) Successful in 9s
updated docs
2025-07-29 16:58:09 +02:00

270 lines
11 KiB
Nix

# homelab-docs-services.nix - Service documentation generator CLI
{
writeShellScriptBin,
jq,
}:
writeShellScriptBin "homelab-docs-services" ''
#!/usr/bin/env bash
set -euo pipefail
cat << 'EOF'
# Service Catalog
> Available services and their configuration options
>
> Generated on: $(date)
This document catalogs all available homelab services, their configuration options, and integration capabilities.
EOF
# Get all services and their configurations
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 {})
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
# 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;
config = canonicalConfig;
deploymentCount = lib.length (lib.filter (inst: inst.config.enable) instances);
deployedOn = lib.unique (map (inst: inst.deployedOn or "unknown") enabledInstances);
}
) serviceGroups;
in {
services = uniqueServices;
totalUniqueServices = lib.length (lib.attrNames uniqueServices);
}')
total_services=$(echo "$services_catalog" | ${jq}/bin/jq -r '.totalUniqueServices')
echo "## Overview"
echo
echo "**Total Available Services:** $total_services"
echo
# Create a summary table of services and their default integrations
echo "## Service Integration Matrix"
echo
echo "| Service | Monitoring | Logging | Proxy | Auth Default |"
echo "|---------|------------|---------|-------|--------------|"
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\"]")
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 [[ "$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\` | $monitoring_icon | $logging_icon | $proxy_icon | $auth_icon |"
done
echo
echo "**Legend:** = Enabled by default, = Available but disabled, 🔒 = Auth required, 🌐 = Public access"
echo
echo "## Service Reference"
echo
# Process each service
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\"]")
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 "| 📊 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
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
# 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
fi
echo "---"
echo
done
echo "## Integration Summary"
echo
echo "### Available Integration Types"
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
echo "### Integration Benefits"
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
echo "---"
echo
echo "*This service catalog is generated from actual service configurations across your homelab fleet.*"
''