project-nomad/docs/homelab/architecture.md
2026-03-13 17:41:23 +00:00

8.3 KiB

Project N.O.M.A.D. — Homelab Edition: Architecture

System Overview

Project N.O.M.A.D. Homelab Edition is a container-native knowledge platform designed for NAS and homelab environments. The architecture prioritizes reliability, minimal resource usage, and compatibility with storage-backed systems.

Container Stack

┌─────────────────────────────────────────────────────────────────┐
│                        Docker Host / NAS                        │
│                                                                 │
│  ┌────────────────────────────────────────────────────────────┐ │
│  │                   nomad-internal network                   │ │
│  │                                                            │ │
│  │  ┌──────────────┐    ┌──────────────┐    ┌─────────────┐  │ │
│  │  │  nomad-nginx  │    │  nomad-app   │    │nomad-worker │  │ │
│  │  │  (Nginx)      ├───►│  (AdonisJS)  │    │ (Queue Jobs)│  │ │
│  │  │  :80/:443     │    │  :8080       │    │             │  │ │
│  │  └──────────────┘    └──────┬───────┘    └──────┬──────┘  │ │
│  │                             │                   │          │ │
│  │                      ┌──────▼───────┐    ┌──────▼──────┐  │ │
│  │                      │nomad-database│    │ nomad-cache  │  │ │
│  │                      │  (MySQL 8.0) │    │ (Redis 7)   │  │ │
│  │                      │  :3306       │    │ :6379       │  │ │
│  │                      └──────────────┘    └─────────────┘  │ │
│  └────────────────────────────────────────────────────────────┘ │
│                                                                 │
│  Volumes:                                                       │
│  ├── nomad-db-data (Docker volume - local SSD)                  │
│  ├── NOMAD_DATA_DIR/storage (bind mount - NAS share)            │
│  ├── NOMAD_DATA_DIR/redis (bind mount)                          │
│  └── NOMAD_DATA_DIR/logs/nginx (bind mount)                     │
└─────────────────────────────────────────────────────────────────┘

Service Roles

nomad-app (Application Server)

  • Technology: Node.js 22 + AdonisJS 6
  • Role: Serves the web UI (React/Inertia), handles API requests, manages content
  • Port: 8080
  • Dependencies: nomad-database, nomad-cache

nomad-worker (Background Worker)

  • Technology: Same image as nomad-app
  • Role: Processes background jobs — content downloads, AI model downloads, embeddings, benchmarks
  • Queues: downloads, model-downloads, benchmarks, embeddings
  • Dependencies: nomad-database, nomad-cache

nomad-database (Database)

  • Technology: MySQL 8.0
  • Role: Persistent storage for services, content metadata, chat sessions, benchmarks, settings
  • Storage: Docker named volume (optimized for I/O)

nomad-cache (Cache / Queue Broker)

  • Technology: Redis 7 Alpine
  • Role: BullMQ job queues, session cache, real-time event transport
  • Config: AOF persistence, 256MB max memory with LRU eviction

nomad-nginx (Reverse Proxy)

  • Technology: Nginx Alpine
  • Role: TLS termination, request routing, static asset caching, WebSocket proxy
  • Ports: 80 (HTTP), 443 (HTTPS)

Data Flow

Content Download Pipeline

User Request
    │
    ▼
nomad-app (API) ──► nomad-cache (Redis Queue)
                         │
                         ▼
                    nomad-worker
                         │
                    Downloads content
                         │
                         ▼
                    /app/storage/
                    (NAS bind mount)

AI Chat Pipeline

User Message
    │
    ▼
nomad-app ──► Ollama (AI Model)
    │              │
    │              ▼
    │         Response + RAG context
    │              │
    ▼              ▼
nomad-database (Chat History)

Real-Time Updates

nomad-worker ──► nomad-cache (Redis Pub/Sub)
                      │
                      ▼
                 nomad-app (Transmit SSE)
                      │
                      ▼
                 Browser (EventSource)

Storage Architecture

Design Principles

  1. Database on local volume — Docker named volume for high-IOPS MySQL operations
  2. Content on NAS share — Bind mount to NAS storage for large files (ZIM, maps, PDFs)
  3. Logs rotated automatically — Nginx logs on bind mount, easily accessible

Storage Tiers

Tier Type Use Case I/O Profile
Hot Docker named volume MySQL database High IOPS, small writes
Warm Bind mount (SSD/cache) Redis, temp files Medium IOPS
Cold Bind mount (NAS array) Content library, backups Sequential reads, large files

NAS Compatibility

Platform Storage Path Notes
Unraid /mnt/user/appdata/project-nomad Uses cache drive for DB
TrueNAS SCALE /mnt/pool/apps/project-nomad ZFS dataset recommended
Linux /opt/project-nomad Standard filesystem
Synology /volume1/docker/project-nomad Btrfs volume

Network Architecture

Internal Network

All services communicate over the nomad-internal bridge network. Only the following ports are exposed to the host:

Port Service Purpose
80 nomad-nginx HTTP (configurable)
443 nomad-nginx HTTPS (configurable)
8080 nomad-app Direct app access (optional)

Reverse Proxy Compatibility

The stack works behind external reverse proxies:

Internet/LAN
    │
    ▼
┌───────────────────┐
│ External Proxy     │   Nginx Proxy Manager / Traefik / Caddy
│ (TLS termination)  │
└─────────┬─────────┘
          │
          ▼
┌─────────────────────┐
│ nomad-nginx (:80)   │   OR directly to nomad-app (:8080)
└─────────┬───────────┘
          │
          ▼
┌─────────────────────┐
│ nomad-app (:8080)   │
└─────────────────────┘

When using an external reverse proxy, you can disable nomad-nginx:

# In docker-compose.yml override
services:
  nomad-nginx:
    profiles: ["proxy"]  # Only starts with --profile proxy

Resource Requirements

Minimum (8 GB RAM system)

Service RAM CPU
nomad-app 256 MB 0.25 cores
nomad-worker 256 MB 0.1 cores
nomad-database 256 MB 0.25 cores
nomad-cache 64 MB 0.05 cores
nomad-nginx 16 MB 0.01 cores
Total ~850 MB ~0.66 cores
Service RAM CPU
nomad-app 1 GB 1 core
nomad-worker 2 GB 1 core
nomad-database 1 GB 0.5 cores
nomad-cache 256 MB 0.1 cores
nomad-nginx 32 MB 0.05 cores
Total ~3.3 GB ~2.65 cores

Security Model

  • No authentication by default (network-level access control recommended)
  • All inter-service communication on private Docker network
  • Database and Redis not exposed to host by default
  • Docker socket mounted read-only where possible
  • Agent communication via shared secret (Bearer token)