homelab framework module init (everything is a mess)
This commit is contained in:
parent
0347f4d325
commit
bcbcc8b17b
94 changed files with 7289 additions and 436 deletions
304
modules/nixos/motd/default.nix
Normal file
304
modules/nixos/motd/default.nix
Normal file
|
|
@ -0,0 +1,304 @@
|
|||
# modules/motd/default.nix
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
with lib; let
|
||||
cfg = config.homelab.motd;
|
||||
globalCfg = config.homelab.global;
|
||||
enabledServices = filterAttrs (name: service: service.enable) globalCfg.services;
|
||||
|
||||
homelab-motd = pkgs.writeShellScriptBin "homelab-motd" ''
|
||||
#! /usr/bin/env bash
|
||||
source /etc/os-release
|
||||
|
||||
# Colors for output
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
PURPLE='\033[0;35m'
|
||||
CYAN='\033[0;36m'
|
||||
WHITE='\033[1;37m'
|
||||
NC='\033[0m' # No Color
|
||||
BOLD='\033[1m'
|
||||
|
||||
# Helper functions
|
||||
print_header() {
|
||||
echo -e "''${BOLD}''${BLUE}╔══════════════════════════════════════════════════════════════╗''${NC}"
|
||||
echo -e "''${BOLD}''${BLUE}║''${NC}''${WHITE} 🏠 HOMELAB STATUS ''${NC}''${BOLD}''${BLUE}║''${NC}"
|
||||
echo -e "''${BOLD}''${BLUE}╚══════════════════════════════════════════════════════════════╝''${NC}"
|
||||
}
|
||||
|
||||
print_section() {
|
||||
echo -e "\n''${BOLD}''${CYAN}▶ $1''${NC}"
|
||||
echo -e "''${CYAN}─────────────────────────────────────────────────────────────''${NC}"
|
||||
}
|
||||
|
||||
get_service_status() {
|
||||
local service="$1"
|
||||
if ${pkgs.systemd}/bin/systemctl is-active --quiet "$service" 2>/dev/null; then
|
||||
echo -e "''${GREEN}●''${NC} Active"
|
||||
elif ${pkgs.systemd}/bin/systemctl is-enabled --quiet "$service" 2>/dev/null; then
|
||||
echo -e "''${YELLOW}●''${NC} Inactive"
|
||||
else
|
||||
echo -e "''${RED}●''${NC} Disabled"
|
||||
fi
|
||||
}
|
||||
|
||||
get_timer_status() {
|
||||
local timer="$1"
|
||||
if ${pkgs.systemd}/bin/systemctl is-active --quiet "$timer" 2>/dev/null; then
|
||||
local next_run=$(${pkgs.systemd}/bin/systemctl show "$timer" --property=NextElapseUSecRealtime --value 2>/dev/null || echo "0")
|
||||
if [[ "$next_run" != "0" && "$next_run" != "n/a" ]]; then
|
||||
local next_readable=$(${pkgs.systemd}/bin/systemctl list-timers --no-pager "$timer" 2>/dev/null | tail -n +2 | head -n 1 | awk '{print $1, $2}' || echo "Unknown")
|
||||
echo -e "''${GREEN}●''${NC} Next: ''${next_readable}"
|
||||
else
|
||||
echo -e "''${GREEN}●''${NC} Active"
|
||||
fi
|
||||
else
|
||||
echo -e "''${RED}●''${NC} Inactive"
|
||||
fi
|
||||
}
|
||||
|
||||
# Main script
|
||||
${optionalString cfg.clearScreen "clear"}
|
||||
print_header
|
||||
|
||||
# Check if global config exists
|
||||
CONFIG_FILE="/etc/homelab/config.json"
|
||||
if [[ ! -f "$CONFIG_FILE" ]]; then
|
||||
echo -e "''${RED}❌ Global homelab configuration not found at $CONFIG_FILE''${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Parse global configuration
|
||||
HOSTNAME=$(${pkgs.jq}/bin/jq -r '.hostname' "$CONFIG_FILE" 2>/dev/null || hostname)
|
||||
DOMAIN=$(${pkgs.jq}/bin/jq -r '.domain' "$CONFIG_FILE" 2>/dev/null || echo "unknown")
|
||||
ENVIRONMENT=$(${pkgs.jq}/bin/jq -r '.environment' "$CONFIG_FILE" 2>/dev/null || echo "unknown")
|
||||
LOCATION=$(${pkgs.jq}/bin/jq -r '.location' "$CONFIG_FILE" 2>/dev/null || echo "unknown")
|
||||
TAGS=$(${pkgs.jq}/bin/jq -r '.tags[]?' "$CONFIG_FILE" 2>/dev/null | tr '\n' ' ' || echo "none")
|
||||
|
||||
print_section "SYSTEM INFO"
|
||||
echo -e " ''${BOLD}Hostname:''${NC} $HOSTNAME"
|
||||
echo -e " ''${BOLD}Domain:''${NC} $DOMAIN"
|
||||
echo -e " ''${BOLD}Environment:''${NC} $ENVIRONMENT"
|
||||
echo -e " ''${BOLD}Location:''${NC} $LOCATION"
|
||||
echo -e " ''${BOLD}Tags:''${NC} ''${TAGS:-none}"
|
||||
echo -e " ''${BOLD}Uptime:''${NC} $(${pkgs.procps}/bin/uptime -p)"
|
||||
echo -e " ''${BOLD}Load:''${NC} $(${pkgs.procps}/bin/uptime | awk -F'load average:' '{print $2}' | xargs)"
|
||||
|
||||
${optionalString cfg.showServices ''
|
||||
# Enabled services from homelab config
|
||||
print_section "HOMELAB SERVICES"
|
||||
${concatStringsSep "\n" (mapAttrsToList (name: service: ''
|
||||
status=$(get_service_status "${service.systemdService}")
|
||||
printf " %-25s %s\n" "${name}" "$status"
|
||||
'')
|
||||
cfg.services)}
|
||||
''}
|
||||
|
||||
${optionalString cfg.showMonitoring ''
|
||||
# Monitoring endpoints
|
||||
print_section "MONITORING ENDPOINTS"
|
||||
ENDPOINTS=$(${pkgs.jq}/bin/jq -c '.monitoring.endpoints[]?' "$CONFIG_FILE" 2>/dev/null || echo "")
|
||||
if [[ -n "$ENDPOINTS" ]]; then
|
||||
while IFS= read -r endpoint; do
|
||||
name=$(echo "$endpoint" | ${pkgs.jq}/bin/jq -r '.name')
|
||||
port=$(echo "$endpoint" | ${pkgs.jq}/bin/jq -r '.port')
|
||||
path=$(echo "$endpoint" | ${pkgs.jq}/bin/jq -r '.path')
|
||||
job=$(echo "$endpoint" | ${pkgs.jq}/bin/jq -r '.jobName')
|
||||
|
||||
# Check if port is accessible
|
||||
if ${pkgs.netcat}/bin/nc -z localhost "$port" 2>/dev/null; then
|
||||
status="''${GREEN}●''${NC}"
|
||||
else
|
||||
status="''${RED}●''${NC}"
|
||||
fi
|
||||
|
||||
printf " %-20s %s %s:%s%s (job: %s)\n" "$name" "$status" "$HOSTNAME" "$port" "$path" "$job"
|
||||
done <<< "$ENDPOINTS"
|
||||
else
|
||||
echo -e " ''${YELLOW}No monitoring endpoints configured''${NC}"
|
||||
fi
|
||||
''}
|
||||
|
||||
${optionalString cfg.showBackups ''
|
||||
# Backup jobs status
|
||||
print_section "BACKUP JOBS"
|
||||
BACKUP_JOBS=$(${pkgs.jq}/bin/jq -c '.backups.jobs[]?' "$CONFIG_FILE" 2>/dev/null || echo "")
|
||||
if [[ -n "$BACKUP_JOBS" ]]; then
|
||||
while IFS= read -r job; do
|
||||
name=$(echo "$job" | ${pkgs.jq}/bin/jq -r '.name')
|
||||
backend=$(echo "$job" | ${pkgs.jq}/bin/jq -r '.backend')
|
||||
schedule=$(echo "$job" | ${pkgs.jq}/bin/jq -r '.schedule')
|
||||
|
||||
service_name="backup-''${name}"
|
||||
timer_name="''${service_name}.timer"
|
||||
|
||||
timer_status=$(get_timer_status "$timer_name")
|
||||
|
||||
# Get last backup info
|
||||
last_run="Unknown"
|
||||
if ${pkgs.systemd}/bin/systemctl show "$service_name" --property=ExecMainStartTimestamp --value 2>/dev/null | grep -q "^[^n]"; then
|
||||
last_run=$(${pkgs.systemd}/bin/systemctl show "$service_name" --property=ExecMainStartTimestamp --value 2>/dev/null | head -1)
|
||||
if [[ "$last_run" != "n/a" && -n "$last_run" ]]; then
|
||||
last_run=$(${pkgs.coreutils}/bin/date -d "$last_run" "+%Y-%m-%d %H:%M" 2>/dev/null || echo "Unknown")
|
||||
fi
|
||||
fi
|
||||
|
||||
printf " %-20s %s (%s, %s) Last: %s\n" "$name" "$timer_status" "$backend" "$schedule" "$last_run"
|
||||
done <<< "$BACKUP_JOBS"
|
||||
|
||||
# Show backup-status command output if available
|
||||
if command -v backup-status >/dev/null 2>&1; then
|
||||
echo -e "\n ''${BOLD}Quick Status:''${NC}"
|
||||
backup-status 2>/dev/null | tail -n +3 | head -10 | sed 's/^/ /'
|
||||
fi
|
||||
else
|
||||
echo -e " ''${YELLOW}No backup jobs configured''${NC}"
|
||||
fi
|
||||
''}
|
||||
|
||||
${optionalString cfg.showReverseProxy ''
|
||||
# Reverse proxy entries
|
||||
print_section "REVERSE PROXY ENTRIES"
|
||||
PROXY_ENTRIES=$(${pkgs.jq}/bin/jq -c '.reverseProxy.entries[]?' "$CONFIG_FILE" 2>/dev/null || echo "")
|
||||
if [[ -n "$PROXY_ENTRIES" ]]; then
|
||||
while IFS= read -r entry; do
|
||||
subdomain=$(echo "$entry" | ${pkgs.jq}/bin/jq -r '.subdomain')
|
||||
port=$(echo "$entry" | ${pkgs.jq}/bin/jq -r '.port')
|
||||
domain=$(echo "$entry" | ${pkgs.jq}/bin/jq -r '.domain')
|
||||
auth=$(echo "$entry" | ${pkgs.jq}/bin/jq -r '.enableAuth')
|
||||
ssl=$(echo "$entry" | ${pkgs.jq}/bin/jq -r '.enableSSL')
|
||||
|
||||
# Check if service is running on the port
|
||||
if ${pkgs.netcat}/bin/nc -z localhost "$port" 2>/dev/null; then
|
||||
status="''${GREEN}●''${NC}"
|
||||
else
|
||||
status="''${RED}●''${NC}"
|
||||
fi
|
||||
|
||||
auth_indicator=""
|
||||
[[ "$auth" == "true" ]] && auth_indicator=" 🔐"
|
||||
|
||||
ssl_indicator=""
|
||||
[[ "$ssl" == "true" ]] && ssl_indicator=" 🔒"
|
||||
|
||||
printf " %-25s %s :%s → %s%s%s\n" "''${domain}" "$status" "$port" "$domain" "$auth_indicator" "$ssl_indicator"
|
||||
done <<< "$PROXY_ENTRIES"
|
||||
else
|
||||
echo -e " ''${YELLOW}No reverse proxy entries configured''${NC}"
|
||||
fi
|
||||
''}
|
||||
|
||||
${optionalString cfg.showResources ''
|
||||
# Resource usage
|
||||
print_section "RESOURCE USAGE"
|
||||
echo -e " ''${BOLD}Memory:''${NC} $(${pkgs.procps}/bin/free -h | awk '/^Mem:/ {printf "%s/%s (%.1f%%)", $3, $2, ($3/$2)*100}')"
|
||||
echo -e " ''${BOLD}Disk (root):''${NC} $(${pkgs.coreutils}/bin/df -h / | awk 'NR==2 {printf "%s/%s (%s)", $3, $2, $5}')"
|
||||
echo -e " ''${BOLD}CPU Usage:''${NC} $(${pkgs.procps}/bin/top -bn1 | grep "Cpu(s)" | awk '{printf "%.1f%%", $2+$4}' | sed 's/%us,//')%"
|
||||
''}
|
||||
|
||||
${optionalString cfg.showRecentIssues ''
|
||||
# Recent logs (errors only)
|
||||
print_section "RECENT ISSUES"
|
||||
error_count=$(${pkgs.systemd}/bin/journalctl --since "24 hours ago" --priority=err --no-pager -q | wc -l)
|
||||
if [[ "$error_count" -gt 0 ]]; then
|
||||
echo -e " ''${RED}⚠ $error_count errors in last 24h''${NC}"
|
||||
${pkgs.systemd}/bin/journalctl --since "24 hours ago" --priority=err --no-pager -q | tail -3 | sed 's/^/ /'
|
||||
else
|
||||
echo -e " ''${GREEN}✓ No critical errors in last 24h''${NC}"
|
||||
fi
|
||||
''}
|
||||
|
||||
echo -e "\n''${BOLD}''${BLUE}╔══════════════════════════════════════════════════════════════╗''${NC}"
|
||||
echo -e "''${BOLD}''${BLUE}║''${NC} ''${WHITE}Run 'backup-status' for detailed backup info ''${NC}''${BOLD}''${BLUE}║''${NC}"
|
||||
echo -e "''${BOLD}''${BLUE}║''${NC} ''${WHITE}Config: /etc/homelab/config.json ''${NC}''${BOLD}''${BLUE}║''${NC}"
|
||||
echo -e "''${BOLD}''${BLUE}╚══════════════════════════════════════════════════════════════╝''${NC}"
|
||||
echo
|
||||
'';
|
||||
in {
|
||||
options.homelab.motd = {
|
||||
enable = mkEnableOption "Dynamic homelab MOTD";
|
||||
|
||||
clearScreen = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = "Clear screen before showing MOTD";
|
||||
};
|
||||
|
||||
showServices = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = "Show enabled homelab services";
|
||||
};
|
||||
|
||||
showMonitoring = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = "Show monitoring endpoints";
|
||||
};
|
||||
|
||||
showBackups = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = "Show backup jobs status";
|
||||
};
|
||||
|
||||
showReverseProxy = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = "Show reverse proxy entries";
|
||||
};
|
||||
|
||||
showResources = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = "Show system resource usage";
|
||||
};
|
||||
|
||||
showRecentIssues = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = "Show recent system issues";
|
||||
};
|
||||
|
||||
services = mkOption {
|
||||
type = types.attrsOf (types.submodule {
|
||||
options = {
|
||||
systemdService = mkOption {
|
||||
type = types.str;
|
||||
description = "Name of the systemd service to monitor";
|
||||
};
|
||||
description = mkOption {
|
||||
type = types.str;
|
||||
default = "";
|
||||
description = "Human-readable description of the service";
|
||||
};
|
||||
};
|
||||
});
|
||||
default = {};
|
||||
description = "Homelab services to monitor in MOTD";
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf (cfg.enable && globalCfg.enable) {
|
||||
# Register services with MOTD
|
||||
homelab.motd.services =
|
||||
mapAttrs (name: service: {
|
||||
systemdService = name;
|
||||
description = service.description;
|
||||
})
|
||||
enabledServices;
|
||||
|
||||
# Create a command to manually run the MOTD
|
||||
environment.systemPackages = with pkgs; [
|
||||
jq
|
||||
netcat
|
||||
homelab-motd
|
||||
];
|
||||
};
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue