# homelab-docs.nix - Standalone documentation generator package { lib, stdenv, writeShellScriptBin, jq, nixfmt, }: let # Main documentation generator script docsGenerator = writeShellScriptBin "homelab-generate-docs" '' #!/usr/bin/env bash set -euo pipefail # Colors BLUE='\033[0;34m' GREEN='\033[0;32m' YELLOW='\033[1;33m' RED='\033[0;31m' NC='\033[0m' info() { echo -e "''${BLUE}$1''${NC}"; } success() { echo -e "''${GREEN}$1''${NC}"; } warn() { echo -e "''${YELLOW}$1''${NC}"; } error() { echo -e "''${RED}$1''${NC}"; } # Configuration DOCS_DIR="''${1:-./docs}" info "📚 Generating homelab documentation..." echo " Output directory: $DOCS_DIR" echo # Check if we're in a directory with a flake if [[ ! -f flake.nix ]]; then error "No flake.nix found in current directory" echo "Please run this command from your homelab flake directory" exit 1 fi # Check if colmena is available if ! command -v colmena >/dev/null 2>&1; then error "colmena command not found." echo "Please ensure colmena is available in your environment" echo "Add it to your devShell or install it globally" exit 1 fi # Create docs directory mkdir -p "$DOCS_DIR" # Generate fleet overview info " 🌐 Generating fleet overview..." homelab-docs-fleet > "$DOCS_DIR/fleet-overview.md" # Generate node documentation info " 🖥️ Generating node configurations..." homelab-docs-nodes > "$DOCS_DIR/nodes.md" # Generate service documentation info " ⚙️ Generating service configurations..." homelab-docs-services > "$DOCS_DIR/services.md" # Generate current deployment info " 🏠 Generating current deployment..." homelab-docs-deployment > "$DOCS_DIR/current-deployment.md" # Generate README info " 📋 Generating README..." homelab-docs-readme > "$DOCS_DIR/README.md" success "✅ Documentation generated successfully!" echo echo "Generated files:" echo " 🌐 fleet-overview.md - Fleet statistics and overview" echo " 🖥️ nodes.md - Per-node configurations" echo " ⚙️ services.md - Service configurations" echo " 🏠 current-deployment.md - Current deployment state" echo " 📋 README.md - Documentation index" echo echo "💡 Tip: Add these files to your repository and set up GitHub Actions" echo " to automatically regenerate documentation on changes!" ''; # Fleet overview generator fleetDocsGenerator = writeShellScriptBin "homelab-docs-fleet" '' #!/usr/bin/env bash set -euo pipefail cat << EOF # Homelab Fleet Overview > Auto-generated fleet overview > > Generated on: $(date) > Source: $(pwd) ## Fleet Statistics EOF # Get basic fleet stats echo "### Basic Information" echo fleet_stats=$(colmena eval -E '{ nodes, pkgs, lib, ... }: { totalNodes = lib.length (lib.attrNames nodes); nodeNames = lib.attrNames nodes; }') total_nodes=$(echo "$fleet_stats" | ${jq}/bin/jq -r '.totalNodes') node_names=$(echo "$fleet_stats" | ${jq}/bin/jq -r '.nodeNames[]' | tr '\n' ' ') echo "| Metric | Value |" echo "|--------|-------|" echo "| Total Nodes | $total_nodes |" echo "| Node Names | $node_names |" echo # Get homelab-enabled nodes echo "### Homelab Configuration" echo homelab_info=$(colmena eval -E '{ nodes, pkgs, lib, ... }: { homelabNodes = lib.mapAttrs (name: node: { enabled = node.config.homelab.enable or false; hostname = node.config.homelab.hostname or null; environment = node.config.homelab.environment or null; }) nodes; }') echo "| Node | Homelab Enabled | Hostname | Environment |" echo "|------|----------------|----------|-------------|" echo "$homelab_info" | ${jq}/bin/jq -r '.homelabNodes | to_entries[] | [.key, (.value.enabled | tostring), (.value.hostname // "N/A"), (.value.environment // "N/A")] | @tsv' | while IFS=$'\t' read -r node enabled hostname environment; do enabled_icon=$(if [[ "$enabled" == "true" ]]; then echo "✅"; else echo "❌"; fi) echo "| \`$node\` | $enabled_icon | $hostname | $environment |" done echo # Get service distribution echo "### Service Distribution" echo service_info=$(colmena eval -E '{ nodes, pkgs, lib, ... }: lib.mapAttrs (name: node: if (node.config.homelab.enable or false) then { serviceCount = lib.length (lib.attrNames (lib.filterAttrs (n: v: v.enable or false) (node.config.homelab.services or {}))); serviceNames = lib.attrNames (lib.filterAttrs (n: v: v.enable or false) (node.config.homelab.services or {})); } else { serviceCount = 0; serviceNames = []; } ) nodes') echo "| Node | Service Count | Services |" echo "|------|---------------|----------|" echo "$service_info" | ${jq}/bin/jq -r 'to_entries[] | [.key, (.value.serviceCount | tostring), (.value.serviceNames | join(", "))] | @tsv' | while IFS=$'\t' read -r node count services; do echo "| \`$node\` | $count | $services |" done echo # Environment distribution echo "### Environment Distribution" echo env_distribution=$(echo "$homelab_info" | ${jq}/bin/jq -r ' [.homelabNodes | to_entries[] | select(.value.enabled == true) | .value.environment // "unknown"] | group_by(.) | map({environment: .[0], count: length}) | .[]') if [[ -n "$env_distribution" ]]; then echo "| Environment | Node Count |" echo "|-------------|------------|" echo "$env_distribution" | ${jq}/bin/jq -r '[.environment, (.count | tostring)] | @tsv' | \ while IFS=$'\t' read -r env count; do echo "| $env | $count |" done else echo "No homelab-enabled nodes found." fi echo echo "---" echo echo "*Fleet overview generated from colmena evaluation*" ''; # Node documentation generator nodeDocsGenerator = writeShellScriptBin "homelab-docs-nodes" '' #!/usr/bin/env bash set -euo pipefail cat << EOF # Node Configurations > Detailed per-node configuration > > Generated on: $(date) EOF # Get all node information node_info=$(colmena eval -E '{ nodes, pkgs, lib, ... }: lib.mapAttrs (name: node: { # Basic system info nixosVersion = node.config.system.nixos.version; hostName = node.config.networking.hostName; system = node.config.nixpkgs.system; # Homelab config (safe extraction) homelab = if (node.config.homelab.enable or false) then { enabled = true; hostname = node.config.homelab.hostname or null; domain = node.config.homelab.domain or null; externalDomain = node.config.homelab.externalDomain or null; environment = node.config.homelab.environment or null; location = node.config.homelab.location or null; tags = node.config.homelab.tags or []; } else { enabled = false; }; # Services (safe extraction) services = if (node.config.homelab.enable or false) then lib.mapAttrs (svcName: svc: { enabled = svc.enable or false; port = svc.port or null; description = svc.description or svcName; tags = svc.tags or []; }) (node.config.homelab.services or {}) else {}; }) nodes') echo "$node_info" | ${jq}/bin/jq -r 'to_entries[] | .key' | while read -r node; do echo "## Node: $node" echo # Basic system information echo "### System Information" echo nixos_version=$(echo "$node_info" | ${jq}/bin/jq -r ".[\"$node\"].nixosVersion") hostname=$(echo "$node_info" | ${jq}/bin/jq -r ".[\"$node\"].hostName") system=$(echo "$node_info" | ${jq}/bin/jq -r ".[\"$node\"].system") echo "| Property | Value |" echo "|----------|-------|" echo "| NixOS Version | \`$nixos_version\` |" echo "| Hostname | \`$hostname\` |" echo "| System | \`$system\` |" echo # Homelab configuration homelab_enabled=$(echo "$node_info" | ${jq}/bin/jq -r ".[\"$node\"].homelab.enabled") if [[ "$homelab_enabled" == "true" ]]; then echo "### Homelab Configuration" echo hl_hostname=$(echo "$node_info" | ${jq}/bin/jq -r ".[\"$node\"].homelab.hostname // \"N/A\"") hl_domain=$(echo "$node_info" | ${jq}/bin/jq -r ".[\"$node\"].homelab.domain // \"N/A\"") hl_external=$(echo "$node_info" | ${jq}/bin/jq -r ".[\"$node\"].homelab.externalDomain // \"N/A\"") hl_env=$(echo "$node_info" | ${jq}/bin/jq -r ".[\"$node\"].homelab.environment // \"N/A\"") hl_location=$(echo "$node_info" | ${jq}/bin/jq -r ".[\"$node\"].homelab.location // \"N/A\"") hl_tags=$(echo "$node_info" | ${jq}/bin/jq -r ".[\"$node\"].homelab.tags | join(\", \")") echo "| Property | Value |" echo "|----------|-------|" echo "| Homelab Hostname | \`$hl_hostname\` |" echo "| Domain | \`$hl_domain\` |" echo "| External Domain | \`$hl_external\` |" echo "| Environment | \`$hl_env\` |" echo "| Location | \`$hl_location\` |" echo "| Tags | $hl_tags |" echo # Services echo "### Services" echo services_data=$(echo "$node_info" | ${jq}/bin/jq -r ".[\"$node\"].services") service_count=$(echo "$services_data" | ${jq}/bin/jq 'length') if [[ "$service_count" -gt 0 ]]; then echo "| Service | Enabled | Port | Description | Tags |" echo "|---------|---------|------|-------------|------|" echo "$services_data" | ${jq}/bin/jq -r 'to_entries[] | [.key, (.value.enabled | tostring), (.value.port // "N/A" | tostring), (.value.description // "N/A"), (.value.tags | join(", "))] | @tsv' | while IFS=$'\t' read -r service enabled port description tags; do enabled_icon=$(if [[ "$enabled" == "true" ]]; then echo "✅"; else echo "❌"; fi) echo "| \`$service\` | $enabled_icon | $port | $description | $tags |" done else echo "No services configured." fi else echo "### Homelab Configuration" echo echo "❌ Homelab is not enabled on this node." fi echo echo "---" echo done ''; # Service documentation generator - refocused on service capabilities serviceDocsGenerator = 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; additionalSubdomains = service.proxy.additionalSubdomains or []; }; # Service-specific options (everything else) serviceSpecific = removeAttrs service [ "enable" "port" "description" "tags" "monitoring" "logging" "proxy" ]; }; }) (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); availableOn = lib.unique (map (inst: inst.nodeName 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 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') 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)" 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 "\`\`\`" 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 # Integration Options 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') if [[ "$monitoring_enabled" == "true" || "$logging_enabled" == "true" || "$proxy_enabled" == "true" ]]; then echo "#### Available Integrations" echo fi # Monitoring Integration 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') extra_labels=$(echo "$service_data" | ${jq}/bin/jq -r '.config.monitoring.extraLabels') echo "##### 📊 Monitoring" echo echo "- **Metrics Endpoint:** \`$metrics_path\`" echo "- **Health Check:** \`$health_path\`" if [[ "$extra_labels" != "{}" ]]; then echo "- **Default Labels:** $(echo "$extra_labels" | ${jq}/bin/jq -r 'to_entries[] | "\(.key)=\(.value)"' | paste -sd, -)" fi echo echo "\`\`\`nix" echo "homelab.services.$service.monitoring = {" echo " enable = true;" echo " metrics.path = \"$metrics_path\";" echo " healthCheck.path = \"$health_path\";" if [[ "$extra_labels" != "{}" ]]; then echo " extraLabels = $extra_labels;" fi echo "};" echo "\`\`\`" echo fi # Logging Integration if [[ "$logging_enabled" == "true" ]]; then log_files=$(echo "$service_data" | ${jq}/bin/jq -r '.config.logging.files[]?') log_labels=$(echo "$service_data" | ${jq}/bin/jq -r '.config.logging.extraLabels') echo "##### 📝 Logging" echo if [[ -n "$log_files" ]]; then echo "- **Log Files:**" echo "$log_files" | while read -r file; do echo " - \`$file\`" done fi if [[ "$log_labels" != "{}" ]]; then echo "- **Default Labels:** $(echo "$log_labels" | ${jq}/bin/jq -r 'to_entries[] | "\(.key)=\(.value)"' | paste -sd, -)" fi echo echo "\`\`\`nix" echo "homelab.services.$service.logging = {" echo " enable = true;" if [[ -n "$log_files" ]]; then echo " files = [" echo "$log_files" | while read -r file; do echo " \"$file\"" done echo " ];" fi if [[ "$log_labels" != "{}" ]]; then echo " extraLabels = $log_labels;" fi echo "};" echo "\`\`\`" echo fi # Proxy Integration 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') additional_subdomains=$(echo "$service_data" | ${jq}/bin/jq -r '.config.proxy.additionalSubdomains') echo "##### 🔀 Reverse Proxy" echo echo "- **Primary Subdomain:** \`$subdomain\`" echo "- **Authentication Required:** $(if [[ "$enable_auth" == "true" ]]; then echo "✅ Yes"; else echo "❌ No"; fi)" if [[ "$additional_subdomains" != "[]" && "$additional_subdomains" != "null" ]]; then echo "- **Additional Subdomains:** Available" fi echo echo "\`\`\`nix" echo "homelab.services.$service.proxy = {" echo " enable = true;" echo " subdomain = \"$subdomain\";" echo " enableAuth = $enable_auth;" if [[ "$additional_subdomains" != "[]" && "$additional_subdomains" != "null" ]]; then echo " additionalSubdomains = [" echo " # Configure additional proxy entries as needed" echo " ];" fi echo "};" echo "\`\`\`" echo fi # Usage Examples echo "#### Complete Example" echo echo "\`\`\`nix" echo "# Full configuration example for $service" echo "homelab.services.$service = {" echo " enable = true;" if [[ "$port" != "N/A" ]]; then echo " port = $port;" fi echo " description = \"$description\";" # Add integration examples if [[ "$monitoring_enabled" == "true" ]]; then echo " " echo " # Monitoring integration" echo " monitoring.enable = true;" fi if [[ "$logging_enabled" == "true" ]]; then echo " " echo " # Logging integration" echo " logging.enable = true;" fi if [[ "$proxy_enabled" == "true" ]]; then echo " " echo " # Reverse proxy integration" echo " proxy = {" echo " enable = true;" echo " subdomain = \"$subdomain\";" echo " enableAuth = $enable_auth;" echo " };" fi echo "};" echo "\`\`\`" echo echo "---" echo done echo "## Integration Summary" echo echo "### Available Integration Types" echo echo "| Integration | Purpose | Configuration |" echo "|-------------|---------|---------------|" echo "| **Monitoring** | Prometheus metrics + health checks | \`monitoring.enable = true\` |" echo "| **Logging** | Centralized log collection | \`logging.enable = true\` |" echo "| **Proxy** | Reverse proxy with SSL + auth | \`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 echo "---" echo echo "*This service catalog is generated from actual service configurations across your homelab fleet.*" ''; # Current deployment generator deploymentDocsGenerator = writeShellScriptBin "homelab-docs-deployment" '' #!/usr/bin/env bash set -euo pipefail cat << EOF # Current Deployment State > Current homelab deployment configuration > > Generated on: $(date) > Working directory: $(pwd) ## Deployment Summary EOF # Get deployment summary deployment_summary=$(colmena eval -E '{ nodes, pkgs, lib, ... }: let homelabNodes = lib.filterAttrs (name: node: node.config.homelab.enable or false) nodes; allServices = lib.flatten (lib.mapAttrsToList (nodeName: node: lib.attrNames (lib.filterAttrs (n: v: v.enable or false) (node.config.homelab.services or {})) ) homelabNodes); in { totalNodes = lib.length (lib.attrNames nodes); homelabEnabledNodes = lib.length (lib.attrNames homelabNodes); uniqueServices = lib.length (lib.unique allServices); totalServiceInstances = lib.length allServices; nodeNames = lib.attrNames nodes; homelabNodeNames = lib.attrNames homelabNodes; }') total_nodes=$(echo "$deployment_summary" | ${jq}/bin/jq -r '.totalNodes') homelab_nodes=$(echo "$deployment_summary" | ${jq}/bin/jq -r '.homelabEnabledNodes') unique_services=$(echo "$deployment_summary" | ${jq}/bin/jq -r '.uniqueServices') service_instances=$(echo "$deployment_summary" | ${jq}/bin/jq -r '.totalServiceInstances') echo "| Metric | Count |" echo "|--------|-------|" echo "| Total Nodes | $total_nodes |" echo "| Homelab-Enabled Nodes | $homelab_nodes |" echo "| Unique Services | $unique_services |" echo "| Service Instances | $service_instances |" echo echo "## Node Status" echo # Get detailed node status node_status=$(colmena eval -E '{ nodes, pkgs, lib, ... }: lib.mapAttrs (name: node: { homelabEnabled = node.config.homelab.enable or false; environment = node.config.homelab.environment or "unknown"; serviceCount = if (node.config.homelab.enable or false) then lib.length (lib.attrNames (lib.filterAttrs (n: v: v.enable or false) (node.config.homelab.services or {}))) else 0; monitoringEnabled = if (node.config.homelab.enable or false) then node.config.homelab.monitoring.enable or false else false; backupsEnabled = if (node.config.homelab.enable or false) then node.config.homelab.backups.enable or false else false; proxyEnabled = if (node.config.homelab.enable or false) then node.config.homelab.reverseProxy.enable or false else false; }) nodes') echo "| Node | Homelab | Environment | Services | Monitoring | Backups | Proxy |" echo "|------|---------|-------------|----------|------------|---------|-------|" echo "$node_status" | ${jq}/bin/jq -r 'to_entries[] | [.key, (.value.homelabEnabled | if . then "✅" else "❌" end), .value.environment, (.value.serviceCount | tostring), (.value.monitoringEnabled | if . then "✅" else "❌" end), (.value.backupsEnabled | if . then "✅" else "❌" end), (.value.proxyEnabled | if . then "✅" else "❌" end)] | @tsv' | while IFS=$'\t' read -r node homelab env services monitoring backups proxy; do echo "| \`$node\` | $homelab | $env | $services | $monitoring | $backups | $proxy |" done echo echo "---" echo echo "*Deployment state extracted from live colmena configuration*" ''; # README generator readmeGenerator = writeShellScriptBin "homelab-docs-readme" '' #!/usr/bin/env bash set -euo pipefail cat << EOF # Homelab Documentation > Auto-generated documentation for the homelab deployment > > Generated on: $(date) > Source: $(pwd) ## 📚 Documentation Files This documentation is automatically generated from your colmena flake configuration. ### 📊 Overview Documents - **[Fleet Overview](fleet-overview.md)** - High-level fleet statistics and service distribution - **[Current Deployment](current-deployment.md)** - Current deployment state and node status ### 📖 Detailed Configuration - **[Node Configurations](nodes.md)** - Per-node detailed configuration and services - **[Service Configurations](services.md)** - Service configurations across the fleet ## 🚀 Quick Actions ### View Current Status \`\`\`bash # Service status across fleet (if homelab CLI is available) homelab services --global # Backup status homelab backups --global # Overall status homelab status \`\`\` ### Update Documentation \`\`\`bash # Regenerate all documentation homelab-generate-docs ./docs # Generate in different directory homelab-generate-docs /path/to/output \`\`\` ## 📋 Quick Stats EOF # Add live stats quick_stats=$(colmena eval -E '{ nodes, pkgs, lib, ... }: let homelabNodes = lib.filterAttrs (name: node: node.config.homelab.enable or false) nodes; in { totalNodes = lib.length (lib.attrNames nodes); homelabNodes = lib.length (lib.attrNames homelabNodes); }') total_nodes=$(echo "$quick_stats" | ${jq}/bin/jq -r '.totalNodes') homelab_nodes=$(echo "$quick_stats" | ${jq}/bin/jq -r '.homelabNodes') echo "- **Total Nodes**: $total_nodes" echo "- **Homelab-Enabled Nodes**: $homelab_nodes" echo "- **Generated**: $(date)" echo echo "## 🛠️ Management Tools" echo echo "### Documentation Commands" echo "- \`homelab-generate-docs\` - Regenerate this documentation" echo "- \`homelab-docs-fleet\` - Generate fleet overview only" echo "- \`homelab-docs-nodes\` - Generate node configurations only" echo "- \`homelab-docs-services\` - Generate service configurations only" echo "- \`homelab-docs-deployment\` - Generate deployment state only" echo echo "### Colmena Commands" echo "- \`colmena eval\` - Evaluate flake expressions" echo "- \`colmena apply\` - Deploy configuration changes" echo "- \`colmena build\` - Build configurations without deploying" echo echo "---" echo echo "*This documentation reflects the live state of your homelab deployment as evaluated by colmena.*" ''; in stdenv.mkDerivation { pname = "homelab-docs"; version = "1.0.0"; dontUnpack = true; dontBuild = true; installPhase = '' mkdir -p $out/bin # Install all the generators cp ${docsGenerator}/bin/homelab-generate-docs $out/bin/ cp ${fleetDocsGenerator}/bin/homelab-docs-fleet $out/bin/ cp ${nodeDocsGenerator}/bin/homelab-docs-nodes $out/bin/ cp ${serviceDocsGenerator}/bin/homelab-docs-services $out/bin/ cp ${deploymentDocsGenerator}/bin/homelab-docs-deployment $out/bin/ cp ${readmeGenerator}/bin/homelab-docs-readme $out/bin/ # Make sure they're executable chmod +x $out/bin/* ''; meta = with lib; { description = "Documentation generator for homelab colmena deployments"; longDescription = '' A collection of tools to generate comprehensive documentation for homelab deployments managed with colmena. Extracts configuration from flakes and generates markdown documentation. ''; license = licenses.mit; maintainers = []; platforms = platforms.all; }; }