# Architecture

**Analysis Date:** 2026-02-04

## Pattern Overview

**Overall:** Hub-and-spoke service orchestration with API-driven infrastructure management.

**Key Characteristics:**
- Centralized management container (VMID 102 - mgmt) coordinating all infrastructure
- Layered abstraction: CLI helpers → REST APIs → external services
- Event-driven notifications (Telegram bot bridges management layer to user)
- Credential-based authentication for all service integrations

## Layers

**Management Layer:**
- Purpose: Orchestration and automation entry point for the homelab
- Location: `/home/mikkel/homelab` (git repository in mgmt container)
- Contains: CLI helper scripts (`~/bin/*`), Telegram bot, documentation
- Depends on: Remote SSH access to container/VM IP addresses, Proxmox API, service REST APIs
- Used by: Claude Code automation, Telegram bot commands, cron jobs

**API Integration Layer:**
- Purpose: Abstracts service APIs into simple CLI interfaces
- Location: `~/bin/` (pve, npm-api, dns, pbs, beszel, kuma, updates, telegram)
- Contains: Python and Bash wrappers around external service APIs
- Depends on: Proxmox API, Nginx Proxy Manager API, Technitium DNS API, PBS REST API, Beszel PocketBase, Uptime Kuma REST API, Telegram Bot API
- Used by: Telegram bot, CI/CD automation, interactive CLI usage

**Service Layer:**
- Purpose: Individual hosted services providing infrastructure capabilities
- Location: Distributed across containers (NPM, DNS, PBS, Dockge, Forgejo, etc.)
- Contains: Docker containers, LXC services, backup systems
- Depends on: PVE host networking, shared storage, external integrations
- Used by: API layer, end-user access via web UI or CLI

**Data & Communication Layer:**
- Purpose: State persistence and inter-service communication
- Location: Shared storage (`~/stuff` - ZFS bind mount), credential files (`~/.config/*/credentials`)
- Contains: Backup data, configuration files, Telegram inbox/images/files
- Depends on: PVE ZFS dataset, filesystem access
- Used by: All services, backup/restore operations

## Data Flow

**Infrastructure Query Flow (e.g., `pve list`):**

1. User invokes CLI helper: `~/bin/pve list`
2. Helper loads credentials from `~/.config/pve/credentials`
3. Helper authenticates to Proxmox API at `core.georgsen.dk:8006` using token auth
4. Proxmox returns cluster resource state (VMs/containers)
5. Helper formats and displays output to user

**Service Management Flow (e.g., `dns add myhost 10.5.0.50`):**

1. User invokes: `~/bin/dns add myhost 10.5.0.50`
2. DNS helper loads credentials and authenticates to Technitium at `10.5.0.2:5380`
3. Helper makes HTTP API call to add A record
4. Technitium stores in zone file and updates DNS records
5. Helper confirms success to user

**Backup Status Flow (e.g., `/pbs` command in Telegram):**

1. Telegram user sends `/pbs` command
2. Bot handler in `telegram/bot.py` executes `~/bin/pbs status`
3. PBS helper SSH's to `10.5.0.6` as root
4. SSH command reads backup logs and GC status from PBS container
5. Helper formats human-readable output
6. Bot sends result back to Telegram chat (truncated to 4000 chars for Telegram API limit)

**State Management:**
- Credentials: Stored in `~/.config/*/credentials` files (sourced at runtime)
- Telegram messages: Appended to `telegram/inbox` file for Claude to read
- Media uploads: Saved to `telegram/images/` and `telegram/files/` with timestamps
- Authorization: `telegram/authorized_users` file maintains allowlist of chat IDs

## Key Abstractions

**Helper Scripts (API Adapters):**
- Purpose: Translate user intent into remote service API calls
- Examples: `~/bin/pve`, `~/bin/dns`, `~/bin/pbs`, `~/bin/beszel`, `~/bin/kuma`
- Pattern: Load credentials → authenticate → execute command → format output
- Language: Mix of Python (pve, updates, telegram) and Bash (dns, pbs, beszel, kuma)

**Telegram Bot:**
- Purpose: Provides two-way interactive access to management functions
- Implementation: `telegram/bot.py` using python-telegram-bot library
- Pattern: Command handlers dispatch to helper scripts, results sent back to user
- Channels: Commands (e.g., `/pbs`), free-text messages saved to inbox, photos/files downloaded

**Service Registry (Documentation):**
- Purpose: Centralized reference for service locations and access patterns
- Implementation: `homelab-documentation.md` and `CLAUDE.md`
- Contents: IP addresses, ports, authentication methods, SSH targets, network topology

## Entry Points

**CLI Usage (Direct):**
- Location: `~/bin/{helper}` scripts
- Triggers: Manual invocation by user or cron jobs
- Responsibilities: Execute service operations, format output, validate inputs

**Telegram Bot:**
- Location: `telegram/bot.py` (systemd service: `telegram-bot.service`)
- Triggers: Telegram message or command from authorized user
- Responsibilities: Authenticate user, route command/message, execute via helper scripts, send response

**Automation Scripts:**
- Location: Potential cron jobs or scheduled tasks
- Triggers: Time-based scheduling
- Responsibilities: Execute periodic management tasks (e.g., backup checks, updates)

**Manual Execution:**
- Location: Interactive shell in mgmt container
- Triggers: User SSH session
- Responsibilities: Run helpers for ad-hoc infrastructure management

## Error Handling

**Strategy:** Graceful degradation with informative messaging.

**Patterns:**
- CLI helpers return non-zero exit codes on failure (exception handling in Python, `set -e` in Bash)
- Timeout protection: Telegram bot commands have 30-second timeout (configurable per command)
- Service unavailability: Caught in try/except blocks, fall back to next option (e.g., `pve` tries LXC first, then QEMU)
- Credential failures: Load-time validation, clear error message if credentials file missing
- Network errors: SSH timeouts, API connection failures logged to stdout/stderr

## Cross-Cutting Concerns

**Logging:**
- Telegram bot uses Python stdlib logging (INFO level, writes to systemd journal)
- CLI helpers write directly to stdout/stderr
- PBS helper uses SSH error output for remote command failures

**Validation:**
- Telegram bot validates hostnames (alphanumeric + dots + hyphens only) before ping
- DNS helper validates that name and IP are provided before API call
- PVE helper validates VMID is integer before API call

**Authentication:**
- Credentials stored in `~/.config/{service}/credentials` as simple key=value files
- Sourced at runtime (Bash) or read at startup (Python)
- Token-based auth for Proxmox (no password in memory)
- Basic auth for DNS and other REST APIs (credentials URL-encoded if needed)
- Bearer token for Uptime Kuma (API key-based)

---

*Architecture analysis: 2026-02-04*
