feat(core): initialize NaxOS declarative NixOS distribution, modules, and ISO installer
Test NaxOS Module Configurations / test-modules (push) Failing after 6m10s

This commit is contained in:
Lukas Holzner
2026-09-03 23:53:18 +02:00
parent 88a638955b
commit 5da58ae6d7
28 changed files with 2247 additions and 2 deletions
+11
View File
@@ -0,0 +1,11 @@
{ ... }:
{
imports = [
./immich.nix
./nextcloud.nix
./jellyfin.nix
./paperless.nix
./vaultwarden.nix
];
}
+84
View File
@@ -0,0 +1,84 @@
{ config, pkgs, lib, ... }:
with lib;
let
cfg = config.services.naxos.apps.immich;
in {
options.services.naxos.apps.immich = {
enable = mkEnableOption "Immich Self-Hosted Photo & Video Hub";
runtime = mkOption {
type = types.enum [ "systemd" "docker" ];
default = "systemd";
description = "Runtime to execute Immich (systemd for native bare-metal speed with NixOS package, docker for containerized).";
};
port = mkOption {
type = types.port;
default = 2283;
description = "Web interface and API port.";
};
host = mkOption {
type = types.str;
default = "0.0.0.0";
description = "Listen host.";
};
mediaLocation = mkOption {
type = types.str;
default = "/tank/media/photos";
description = "ZFS dataset or path where uploaded photos and videos are stored.";
};
accelerationDevices = mkOption {
type = types.listOf types.str;
default = [ "/dev/dri/renderD128" ];
description = "DRM render devices for hardware-accelerated transcoding.";
};
machineLearningCPUQuota = mkOption {
type = types.str;
default = "200%";
description = "CPU quota for machine learning service (200% = 2 full cores).";
};
openFirewall = mkOption {
type = types.bool;
default = true;
description = "Open port in firewall.";
};
};
config = mkIf cfg.enable {
# Systemd / Native NixOS Deployment
services.immich = mkIf (cfg.runtime == "systemd") {
enable = true;
host = cfg.host;
port = cfg.port;
mediaLocation = cfg.mediaLocation;
openFirewall = cfg.openFirewall;
accelerationDevices = cfg.accelerationDevices;
};
services.redis.servers.immich = mkIf (cfg.runtime == "systemd") {
logLevel = "warning";
};
systemd.services.immich-machine-learning = mkIf (cfg.runtime == "systemd") {
serviceConfig = {
CPUQuota = cfg.machineLearningCPUQuota;
Nice = 19;
};
};
users.users.immich = mkIf (cfg.runtime == "systemd") {
extraGroups = [ "video" "render" ];
};
systemd.tmpfiles.rules = [
"d ${cfg.mediaLocation} 0750 immich immich -"
];
};
}
+33
View File
@@ -0,0 +1,33 @@
{ config, pkgs, lib, ... }:
with lib;
let
cfg = config.services.naxos.apps.jellyfin;
in {
options.services.naxos.apps.jellyfin = {
enable = mkEnableOption "Jellyfin Open-Source Media Streaming Server";
openFirewall = mkOption {
type = types.bool;
default = true;
description = "Open port 8096 in firewall.";
};
user = mkOption {
type = types.str;
default = "jellyfin";
description = "Service user.";
};
};
config = mkIf cfg.enable {
services.jellyfin = {
enable = true;
openFirewall = cfg.openFirewall;
user = cfg.user;
};
users.users.${cfg.user}.extraGroups = [ "video" "render" ];
};
}
+43
View File
@@ -0,0 +1,43 @@
{ config, pkgs, lib, ... }:
with lib;
let
cfg = config.services.naxos.apps.nextcloud;
in {
options.services.naxos.apps.nextcloud = {
enable = mkEnableOption "Nextcloud Personal Cloud & Collaboration Platform";
hostName = mkOption {
type = types.str;
default = "cloud.local";
description = "Domain / hostname for Nextcloud.";
};
homeDir = mkOption {
type = types.str;
default = "/tank/data/nextcloud";
description = "Persistent data directory on ZFS storage.";
};
adminpassFile = mkOption {
type = types.nullOr types.str;
default = null;
description = "Path to file containing initial admin password.";
};
};
config = mkIf cfg.enable {
services.nextcloud = {
enable = true;
hostName = cfg.hostName;
home = cfg.homeDir;
config = {
adminuser = "admin";
adminpassFile = cfg.adminpassFile;
dbtype = "sqlite";
};
caching.redis = true;
};
};
}
+55
View File
@@ -0,0 +1,55 @@
{ config, pkgs, lib, ... }:
with lib;
let
cfg = config.services.naxos.apps.paperless;
in {
options.services.naxos.apps.paperless = {
enable = mkEnableOption "Paperless-ngx Document Archiving System";
port = mkOption {
type = types.port;
default = 28981;
description = "Web interface port.";
};
mediaDir = mkOption {
type = types.str;
default = "/tank/data/paperless/media";
description = "Directory where archived documents and OCR results are stored.";
};
consumptionDir = mkOption {
type = types.str;
default = "/tank/scans";
description = "Ingestion directory where scanner uploads incoming documents.";
};
openFirewall = mkOption {
type = types.bool;
default = true;
description = "Open port in firewall.";
};
};
config = mkIf cfg.enable {
services.paperless = {
enable = true;
port = cfg.port;
mediaDir = cfg.mediaDir;
consumptionDir = cfg.consumptionDir;
settings = {
PAPERLESS_OCR_LANGUAGE = "deu+eng";
PAPERLESS_CONSUMER_POLLING = 30;
};
};
networking.firewall.allowedTCPPorts = mkIf cfg.openFirewall [ cfg.port ];
systemd.tmpfiles.rules = [
"d ${cfg.mediaDir} 0750 paperless paperless -"
"d ${cfg.consumptionDir} 0775 paperless users -"
];
};
}
+35
View File
@@ -0,0 +1,35 @@
{ config, pkgs, lib, ... }:
with lib;
let
cfg = config.services.naxos.apps.vaultwarden;
in {
options.services.naxos.apps.vaultwarden = {
enable = mkEnableOption "Vaultwarden Password & Secret Vault";
port = mkOption {
type = types.port;
default = 8222;
description = "Web interface port.";
};
openFirewall = mkOption {
type = types.bool;
default = true;
description = "Open port in firewall.";
};
};
config = mkIf cfg.enable {
services.vaultwarden = {
enable = true;
config = {
ROCKET_PORT = cfg.port;
ROCKET_ADDRESS = "0.0.0.0";
};
};
networking.firewall.allowedTCPPorts = mkIf cfg.openFirewall [ cfg.port ];
};
}