docs: complete NaxOS architectural specs, migration guides, API reference, and CI workflows
Validate Documentation / lint-docs (push) Successful in 9s
Validate Documentation / lint-docs (push) Successful in 9s
This commit is contained in:
@@ -0,0 +1,19 @@
|
||||
# App Engine & Workload Runtime Architecture
|
||||
|
||||
NaxOS features a tri-tier runtime engine that selects the best execution strategy for each application:
|
||||
|
||||
## 1. Native NixOS Systemd Services
|
||||
- **Best For**: High-throughput services requiring direct hardware device passthrough, minimal RAM overhead, and deep integration with OpenZFS.
|
||||
- **Example**: **Immich** Photo Hub.
|
||||
- Native Nixpkgs package running as an isolated systemd service.
|
||||
- Direct Intel QuickSync (`/dev/dri/renderD128`) access with `extraPackages = [ intel-media-driver intel-compute-runtime vpl-gpu-rt ]`.
|
||||
- Native systemd CPU quota: `CPUQuota = "200%"` to avoid choking the storage daemon during intensive facial recognition or CLIP embedding indexing.
|
||||
- Photos stored directly in OpenZFS dataset `/tank/media/photos`.
|
||||
|
||||
## 2. Rootless Docker / Compose Engine
|
||||
- **Best For**: General third-party containerized workloads.
|
||||
- **Backend**: Configured with Docker's native `zfs` storage driver (`virtualisation.docker.storageDriver = "zfs"`). Container image layers become native ZFS subvolumes with instant snapshots and copy-on-write deduplication.
|
||||
|
||||
## 3. Lightweight K3s
|
||||
- **Best For**: Cloud-native Helm charts and multi-service distributed workloads.
|
||||
- Can be activated on demand via `services.naxos.appEngine.k3s.enable = true`.
|
||||
@@ -0,0 +1,37 @@
|
||||
# Declarative Backend & GitOps Synchronization Engine
|
||||
|
||||
## Core Workflow
|
||||
|
||||
NaxOS eliminates drift between what the Web Dashboard displays and what the underlying operating system executes.
|
||||
|
||||
When an administrator performs an action in the UI (e.g. creating a share, setting a dataset quota, installing Immich):
|
||||
|
||||
1. **REST API Request**: The frontend sends a strongly typed JSON payload to the NaxOS Management Daemon (`naxos-api`).
|
||||
2. **In-Memory & JSON State Update**: The daemon validates the payload against its schemas and updates `/etc/naxos/repo/naxos-config.json`.
|
||||
3. **NixOS Code Generation**: The daemon's compiler generates `/etc/naxos/repo/generated-naxos-config.nix`.
|
||||
4. **Git Transaction**:
|
||||
- The daemon commits the modified files into the local Git repository at `/etc/naxos/repo`.
|
||||
- If a remote repository is configured (e.g. on Gitea), it pushes the commit automatically to `origin/main`.
|
||||
5. **Dry-Run Validation**:
|
||||
- Before any running service is altered, `naxos-rebuild-safe` performs a dry build:
|
||||
```bash
|
||||
nixos-rebuild build --flake .#naxos
|
||||
```
|
||||
- If evaluation or build fails (e.g. invalid option syntax or dependency conflict), the transaction is immediately aborted and the running system remains untouched.
|
||||
6. **Atomic Switch & Canary Verification**:
|
||||
- The new generation is activated using `nixos-rebuild switch`.
|
||||
- The canary runner tests daemon connectivity and storage accessibility.
|
||||
- If canary verification fails, the system automatically runs:
|
||||
```bash
|
||||
"$PREV_GEN/bin/switch-to-configuration" switch
|
||||
```
|
||||
- The user is alerted in the dashboard with full build logs.
|
||||
|
||||
---
|
||||
|
||||
## 1-Click Rollback Mechanism
|
||||
|
||||
Because every generation is tied to an explicit Git commit and NixOS system profile generation:
|
||||
- The user can browse the commit history in the Web UI.
|
||||
- Clicking **Rollback** checks out the selected commit and activates the previous generation in seconds.
|
||||
- No database dumps or manual backups are needed for appliance recovery.
|
||||
@@ -0,0 +1,49 @@
|
||||
# NaxOS Architecture Overview
|
||||
|
||||
## Design Philosophy
|
||||
|
||||
**NaxOS** is an appliance-like Network Attached Storage (NAS) operating system combining the mathematical immutability of **NixOS**, the enterprise data integrity of **OpenZFS**, and the modern observability of **CNCF Perses**.
|
||||
|
||||
Traditional NAS operating systems (like TrueNAS, Unraid, or Synology DSM) rely either on mutable root filesystems with hidden configuration databases, or proprietary management stacks that can be fragile to upgrade and difficult to replicate.
|
||||
|
||||
NaxOS introduces an opinionated, cloud-native paradigm:
|
||||
1. **The Entire OS is Code**: Kernel parameters, network tuning, storage datasets, shares, users, and installed applications are compiled from a single declarative definition.
|
||||
2. **GitOps-by-Default**: Every modification made via the modern web dashboard or API is recorded as an atomic Git commit and synchronized to a remote Gitea repository.
|
||||
3. **True Disaster Recovery**: If an update or bad configuration breaks a service, instant rollbacks return the running system to the exact previous working generation with a single command.
|
||||
4. **Data Safety First**: Existing OpenZFS pools from legacy systems (such as `nixos-lukas` or TrueNAS) are imported read-safe without formatting, preserving critical application storage such as Immich photo libraries.
|
||||
5. **Modern Native Observability**: Replaces heavy standalone Grafana instances with embedded CNCF **Perses** dashboards that render natively inside the web UI.
|
||||
|
||||
---
|
||||
|
||||
## Architectural Subsystems
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ NaxOS Modern Web UI │
|
||||
│ (React 18, Tailwind CSS, Embedded Perses) │
|
||||
└──────────────────────────────┬──────────────────────────────┘
|
||||
│ REST / SSE / WebSockets
|
||||
┌──────────────────────────────▼──────────────────────────────┐
|
||||
│ NaxOS Management Daemon │
|
||||
│ (Node.js / TypeScript, Fastify, ZFS Driver, GitOps) │
|
||||
├──────────────────────────────┬──────────────────────────────┤
|
||||
│ • Storage Controller │ • GitOps Synchronization │
|
||||
│ • NixOS Module Generator │ • App Engine Orchestrator │
|
||||
│ • Journald Log Streamer │ • Perses Metrics Coordinator│
|
||||
└──────────────┬───────────────┴───────────────┬──────────────┘
|
||||
│ │
|
||||
┌──────────────▼───────────────┐ ┌─────────────▼──────────────┐
|
||||
│ Declarative Engine │ │ OpenZFS Storage │
|
||||
│ /etc/naxos/repo (Git) │ │ • zpool / zfs Primitives │
|
||||
│ nixos-rebuild-safe │ │ • Native Encryption/Comp │
|
||||
│ System Generations │ │ • Auto-Scrub & Snapshots │
|
||||
└──────────────┬───────────────┘ └─────────────┬──────────────┘
|
||||
│ │
|
||||
┌──────────────▼───────────────────────────────▼──────────────┐
|
||||
│ Linux / NixOS Core │
|
||||
│ • BBR Congestion Control & 10G/25G Kernel Buffers │
|
||||
│ • Samba with Apple macOS Time Machine (vfs_fruit) │
|
||||
│ • App Runtimes: Native Systemd, Rootless Docker, K3s │
|
||||
│ • Intel QuickSync & OpenCL Hardware GPU Acceleration │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
@@ -0,0 +1,16 @@
|
||||
# CNCF Perses Native Analytics Architecture
|
||||
|
||||
## Why Perses over Standalone Grafana?
|
||||
|
||||
Traditional NAS appliances that provide telemetry either bundle a heavy standalone Grafana instance (which requires its own SQLite/PostgreSQL database, user accounts, and separate session cookies) or write rudimentary, un-configurable charts into their dashboard.
|
||||
|
||||
NaxOS takes a pioneering approach by integrating **Perses** (a Cloud Native Computing Foundation project):
|
||||
|
||||
1. **GitOps & Declarative Native**:
|
||||
- Perses dashboards and datasources are written in clean JSON/CUE manifests.
|
||||
- Dashboards are checked into `/var/lib/perses/projects/naxos/dashboards` as code.
|
||||
2. **Embedded Direct Visualization**:
|
||||
- The NaxOS Web Dashboard communicates with the internal Perses metrics API.
|
||||
- Eliminates Grafana's multi-megabyte bundle overhead, auth barriers, and database schema migrations.
|
||||
3. **Optimized for OpenZFS Metrics**:
|
||||
- Out-of-the-box panels monitor OpenZFS ARC hits, misses, ARC target sizing, IOPS, and disk latencies scraped from Prometheus and Node Exporter.
|
||||
@@ -0,0 +1,36 @@
|
||||
# OpenZFS Storage Engine & Migration Architecture
|
||||
|
||||
## OpenZFS Primitives in NaxOS
|
||||
|
||||
NaxOS leverages upstream OpenZFS on Linux with specific architectural choices optimized for mixed workloads (streaming media, small-file databases, photo indexing, and Apple Time Machine backups).
|
||||
|
||||
### 1. Default Pool Parameters
|
||||
When creating pools through NaxOS, the engine enforces optimal pool attributes:
|
||||
- `ashift=12`: 4096-byte sector alignment to eliminate write amplification on modern Advanced Format HDDs and NVMe SSDs.
|
||||
- `xattr=sa`: System-attribute storage for extended attributes, drastically improving Samba and POSIX ACL performance.
|
||||
- `acltype=posixacl`: POSIX Access Control Lists enabling granular multi-user permissions.
|
||||
- `compression=lz4`: Ultra-low overhead, transparent compression enabled globally on pools, with dataset-level overrides for `zstd` on cold backups and photo datasets.
|
||||
|
||||
### 2. Record Size Strategy
|
||||
NaxOS tunes dataset record sizes based on application type:
|
||||
- **Media Datasets** (`tank/media`): `recordsize=1M` (maximizing sequential read throughput and reducing metadata overhead).
|
||||
- **General Storage** (`tank/backup`): `recordsize=128K` (default ZFS balance).
|
||||
- **Databases & Containers** (`tank/container`): `recordsize=16K` or `128K`.
|
||||
|
||||
### 3. ZFS ARC Max Management
|
||||
To prevent OpenZFS from consuming all host RAM and starving machine learning workloads (such as Immich facial recognition models), NaxOS enforces a declarative ARC limit:
|
||||
```nix
|
||||
boot.kernelParams = [ "zfs.zfs_arc_max=4294967296" ]; # 4 GiB
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Safe Foreign Pool Import Architecture
|
||||
|
||||
A key tenet of NaxOS is **zero data loss**:
|
||||
|
||||
When importing pools from existing setups (e.g. TrueNAS or `nixos-lukas`):
|
||||
1. The pool is initially inspected with `zpool import -N -f <pool>` (`-N` instructs ZFS not to mount any datasets).
|
||||
2. The dataset tree is scanned and properties are parsed without modifying data.
|
||||
3. Datasets are adopted declaratively into `services.naxos.storage.importExistingPools`.
|
||||
4. Original permissions and POSIX ACLs are preserved.
|
||||
@@ -0,0 +1,95 @@
|
||||
# NaxOS Management Daemon REST & WebSocket API Reference
|
||||
|
||||
The NaxOS daemon listens on internal port `8088` (reverse-proxied via Nginx on port `80`/`443` at `/api/`).
|
||||
|
||||
---
|
||||
|
||||
## 1. System & Engine
|
||||
|
||||
### `GET /api/v1/system/status`
|
||||
Returns high-level appliance status, health metrics, and active generation.
|
||||
|
||||
**Response Example**:
|
||||
```json
|
||||
{
|
||||
"status": {
|
||||
"hostname": "naxos",
|
||||
"uptimeSeconds": 864200,
|
||||
"cpuUsagePercent": 12.4,
|
||||
"memoryTotalBytes": 33554432000,
|
||||
"memoryUsedBytes": 14200000000,
|
||||
"arcSizeBytes": 4294967296,
|
||||
"arcHitRatioPercent": 98.6,
|
||||
"zfsPoolsCount": 1,
|
||||
"activeSharesCount": 3,
|
||||
"runningAppsCount": 2,
|
||||
"osVersion": "NaxOS 24.11 (NixOS Vicuna)",
|
||||
"nixosGeneration": 42
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### `POST /api/v1/system/rebuild`
|
||||
Triggers `nixos-rebuild-safe` and streams stdout/stderr output in real-time as **Server-Sent Events (SSE)** (`text/event-stream`).
|
||||
|
||||
---
|
||||
|
||||
## 2. OpenZFS Storage
|
||||
|
||||
### `GET /api/v1/storage/pools`
|
||||
Lists all active OpenZFS pools, capacity, fragmentation, and health.
|
||||
|
||||
### `POST /api/v1/storage/pools`
|
||||
Creates a new OpenZFS pool.
|
||||
**Payload**:
|
||||
```json
|
||||
{
|
||||
"name": "tank",
|
||||
"layout": "mirror",
|
||||
"devices": ["/dev/sda", "/dev/sdb"],
|
||||
"ashift": 12
|
||||
}
|
||||
```
|
||||
|
||||
### `GET /api/v1/storage/unimported`
|
||||
Scans connected disks for foreign pools (TrueNAS / legacy NixOS) available for zero-data-loss import.
|
||||
|
||||
### `POST /api/v1/storage/import`
|
||||
Safely imports a pool.
|
||||
**Payload**:
|
||||
```json
|
||||
{
|
||||
"poolName": "tank",
|
||||
"force": true,
|
||||
"noMount": true
|
||||
}
|
||||
```
|
||||
|
||||
### `GET /api/v1/storage/datasets`
|
||||
Lists datasets, compression, mountpoint, and quotas.
|
||||
|
||||
---
|
||||
|
||||
## 3. GitOps Synchronization
|
||||
|
||||
### `GET /api/v1/gitops/status`
|
||||
Returns current branch, head commit SHA, and remote sync state.
|
||||
|
||||
### `GET /api/v1/gitops/commits`
|
||||
Returns generation commit history log.
|
||||
|
||||
### `POST /api/v1/gitops/rollback`
|
||||
Instantly rolls back the declarative appliance configuration to the specified Git commit hash.
|
||||
**Payload**:
|
||||
```json
|
||||
{
|
||||
"commitSha": "5da58ae0912f1"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. Real-Time Logs
|
||||
|
||||
### `GET /api/v1/logs/stream`
|
||||
SSE stream delivering journald logs in real time. Supports optional `?unit=<service>` query parameter.
|
||||
@@ -0,0 +1,46 @@
|
||||
# NaxOS Developer & Contribution Guide
|
||||
|
||||
## Repository Structure under `naxos` Organization
|
||||
|
||||
The NaxOS ecosystem is structured across dedicated repositories on Gitea (`git.lholz.de/naxos`):
|
||||
|
||||
1. **`naxos-os`**: The core NixOS distribution flake, modules, profiles, and bootable ISO installer.
|
||||
2. **`naxos-api`**: The TypeScript management daemon, ZFS driver, GitOps engine, and unit tests.
|
||||
3. **`naxos-ui`**: The React 18, Tailwind CSS, and CNCF Perses web dashboard.
|
||||
4. **`naxos-docs`**: Architectural blueprints, end-user tutorials, and migration guides.
|
||||
|
||||
---
|
||||
|
||||
## Local Development Workflow
|
||||
|
||||
### Developing `naxos-api`
|
||||
```bash
|
||||
cd naxos-api
|
||||
npm install
|
||||
npm test # Run Vitest test suite
|
||||
npm run dev # Watch mode on port 8088
|
||||
```
|
||||
|
||||
### Developing `naxos-ui`
|
||||
```bash
|
||||
cd naxos-ui
|
||||
npm install
|
||||
npm run dev # Vite development server on port 3000
|
||||
npm run build # Production compile
|
||||
```
|
||||
|
||||
### Testing NixOS Modules in `naxos-os`
|
||||
```bash
|
||||
cd naxos-os
|
||||
nix flake check
|
||||
nix eval .#nixosConfigurations.naxos.config.system.build.toplevel.drvPath
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Gitea Actions CI/CD Workflows
|
||||
Each repository includes automated Gitea Actions workflows in `.gitea/workflows/`:
|
||||
- **`naxos-os`**: Automated ISO build, flake check, and release artifact generation.
|
||||
- **`naxos-api`**: Automated lint, typecheck, and unit testing.
|
||||
- **`naxos-ui`**: Automated frontend build and artifact packaging.
|
||||
- **`naxos-docs`**: Documentation validation.
|
||||
@@ -0,0 +1,55 @@
|
||||
# NaxOS Installation & Distribution Guide
|
||||
|
||||
## 1. Building the Bootable ISO
|
||||
|
||||
To build the streamlined NaxOS installer image from source using Nix:
|
||||
|
||||
```bash
|
||||
cd naxos-os
|
||||
nix build .#iso
|
||||
```
|
||||
|
||||
The output will be located at `result/iso/naxos-installer-*.iso`.
|
||||
|
||||
Alternatively, download the latest pre-built ISO from the Gitea Releases page:
|
||||
`https://git.lholz.de/naxos/naxos-os/releases`
|
||||
|
||||
---
|
||||
|
||||
## 2. Writing to USB Flash Drive
|
||||
|
||||
Write the ISO image to a USB flash drive (replace `/dev/sdX` with your USB drive device):
|
||||
|
||||
```bash
|
||||
# macOS
|
||||
sudo dd if=result/iso/naxos-installer-*.iso of=/dev/rdiskX bs=4M status=progress; sync
|
||||
|
||||
# Linux
|
||||
sudo dd if=result/iso/naxos-installer-*.iso of=/dev/sdX bs=4M status=progress oflag=sync
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. Running the Installer Wizard
|
||||
|
||||
1. Insert the USB drive into your target hardware and boot in UEFI mode.
|
||||
2. The Live environment will automatically log in as `root` and start the interactive setup wizard:
|
||||
```bash
|
||||
naxos-installer
|
||||
```
|
||||
3. Follow the guided steps:
|
||||
- **Step 1**: System hardware inspection and disk discovery.
|
||||
- **Step 2**: Storage architecture choice (Create fresh ZFS pool vs. Safe foreign pool import).
|
||||
- **Step 3**: Target OS disk selection (installs bootloader and root system).
|
||||
- **Step 4**: Network configuration (hostname and DHCP/static IP).
|
||||
- **Step 5**: Administrator credentials and SSH public keys.
|
||||
- **Step 6**: Automated installation and reboot.
|
||||
|
||||
---
|
||||
|
||||
## 4. Post-Installation First Boot
|
||||
|
||||
After the system reboots:
|
||||
1. Access the web dashboard by navigating to `http://naxos.local` (or the IP displayed on console).
|
||||
2. Log in using your administrator credentials.
|
||||
3. Your NaxOS appliance is ready for service!
|
||||
@@ -0,0 +1,85 @@
|
||||
# Migration Guide: Migrating from `nixos-lukas` (Hulk NAS) to NaxOS
|
||||
|
||||
This guide details how to transition an existing custom NixOS NAS (specifically the `hulk` setup found in `nixos-lukas`) to a declarative NaxOS appliance **without data loss**, preserving existing OpenZFS pools and critical application data (such as your **Immich photo library**).
|
||||
|
||||
> **IMPORTANT: Data Safety Guarantee**
|
||||
> The `nixos-lukas` repository is strictly read-only reference material. Do not make changes to it. All new configuration is managed via NaxOS.
|
||||
|
||||
---
|
||||
|
||||
## 1. Inventory of the Existing `hulk` Setup
|
||||
|
||||
In `nixos-lukas/modules/system/hulk/nas.nix`, the storage topology is:
|
||||
- **Pool Name**: `tank`
|
||||
- **Key Datasets**:
|
||||
- `tank/media`: General media library
|
||||
- `tank/media/photos`: **Immich Photo Library** (critical data)
|
||||
- `tank/backup`: Backup share
|
||||
- `tank/time-machine`: macOS Time Machine backup target
|
||||
- `tank/scans` & `tank/paperless-incoming`: Paperless ingestion
|
||||
- `tank/container`: Docker container storage root
|
||||
- **Kernel Tuning**: ARC limited to 4GB (`zfs.zfs_arc_max=4294967296`).
|
||||
- **Services**: Immich with Intel GPU acceleration (`/dev/dri/renderD128`), Samba with `vfs_fruit`, NFS exports.
|
||||
|
||||
---
|
||||
|
||||
## 2. Pre-Migration Verification (On Legacy Host)
|
||||
|
||||
Before shutting down or booting the NaxOS installer on the NAS machine:
|
||||
|
||||
1. **Verify ZFS Pool Status**:
|
||||
```bash
|
||||
zpool status tank
|
||||
```
|
||||
Ensure the pool is in an `ONLINE` state with 0 errors.
|
||||
|
||||
2. **Ensure Clean Pool Export**:
|
||||
```bash
|
||||
# Stop write services
|
||||
systemctl stop immich docker smbd nfs-server
|
||||
|
||||
# Export pool cleanly
|
||||
sudo zpool export tank
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. Importing `tank` into NaxOS via the Web Dashboard
|
||||
|
||||
1. Boot into NaxOS.
|
||||
2. Open the Web Dashboard at `http://naxos.local` (or appliance IP).
|
||||
3. Navigate to **Storage & ZFS** -> **Pool Migration**.
|
||||
4. The NaxOS Migration Engine automatically detects the foreign `tank` pool:
|
||||
- Status will show `ONLINE`
|
||||
- Disks will list the member drive IDs
|
||||
5. Click **Safe Import & Adopt**:
|
||||
- NaxOS executes:
|
||||
```bash
|
||||
zpool import -N -f tank
|
||||
```
|
||||
- `-N` imports the pool **without mounting**, allowing NaxOS to audit and map dataset mountpoints safely.
|
||||
6. The pool and all sub-datasets (`tank/media/photos`, `tank/backup`, etc.) will appear under **Active Datasets**.
|
||||
|
||||
---
|
||||
|
||||
## 4. Automatic Declarative Configuration
|
||||
|
||||
When adopted, NaxOS automatically commits the following into your GitOps repository:
|
||||
|
||||
```nix
|
||||
services.naxos.storage = {
|
||||
enable = true;
|
||||
arcMaxBytes = 4294967296; # Preserves 4GB limit
|
||||
importExistingPools = [ "tank" ];
|
||||
};
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. Restoring Immich & Hardware Acceleration
|
||||
|
||||
1. Navigate to **App Store** -> **Immich Photo Hub**.
|
||||
2. Select **Native Systemd** runtime.
|
||||
3. Configure the media path: `/tank/media/photos`.
|
||||
4. Click **Deploy Workload**.
|
||||
5. NaxOS activates Immich, binds Intel QuickSync (`/dev/dri/renderD128`), starts Redis and PostgreSQL, and mounts your existing photo library intact!
|
||||
Reference in New Issue
Block a user