jupiter had a leftover docker-compose Immich on the RAID (/mnt/data/Immich, 9.9G) that survived the NixOS install. Native module now, media at /mnt/data/AppData/immich, caddy vhost on 2283 with a 50GB body limit (caddy's default rejects video uploads). The package comes from nixpkgs-unstable, the module from the 26.05 pin: 26.05 ships immich 2.7.5, but that database was last written by 3.0.0 and migrations only run forward -- corrupted migrations: previously executed migration 1776217577402-DropAuditTable is missing Safe because the two module files are byte-identical at these revisions; services/media/immich.nix carries the diff command to re-check on a bump. Drop the input once the stable pin ships >= 3.0.0. immich needs group "users" only to traverse /mnt/data/AppData (drwx--x---); its own dir stays 0700 immich:immich. mediaLocation is outside /var/lib, so the module's tmpfiles entry only ADJUSTS it -- add a rule that creates it. scripts/immich-import-legacy-db does the database half: boots a copy of the legacy PGDATA under the matching image (PG14 + vchord 0.3.0 + pgvector 0.8.1), dumps it with the local pg_dump 17, restores into a scratch DB, fixes ownership, and only swaps after confirmation. Never touches the original. The old cluster ran VectorChord, not pgvecto.rs, so the smart search and face embeddings survive -- no ML re-run. Imported: 666 assets, 25 people, 647 clip + 359 face embeddings, 2 users.
87 lines
3.8 KiB
Nix
87 lines
3.8 KiB
Nix
{ config, pkgs, lib, ... }:
|
|
|
|
# ZimaBlade NAS host: hardware + disk + the services it runs.
|
|
{
|
|
imports = [
|
|
./hardware-configuration.nix
|
|
./disk-config.nix # disko: OS-disk partitions + filesystems
|
|
./secrets.nix # sops-nix: samba password, tailscale key, ...
|
|
../../common.nix # shared base: user / ssh / nix / firewall
|
|
../../services/network/samba.nix
|
|
../../services/network/avahi.nix
|
|
../../services/media/audiobookshelf.nix
|
|
../../services/containers.nix
|
|
../../services/network/caddy.nix
|
|
../../services/vpn/tailscale.nix
|
|
../../services/media/jellyfin.nix
|
|
../../services/media/sabnzbd.nix
|
|
../../services/media/prowlarr.nix
|
|
../../services/media/sonarr.nix
|
|
../../services/media/radarr.nix
|
|
../../services/media/clonarr.nix
|
|
../../services/media/seerr.nix
|
|
../../services/media/immich.nix
|
|
../../services/dev/gitea.nix
|
|
];
|
|
|
|
# sabnzbd's unrar dependency is unfree; scope the allowance to just that
|
|
# package rather than blanket-allowing unfree across the host.
|
|
nixpkgs.config.allowUnfreePredicate = pkg: builtins.elem (lib.getName pkg) [ "unrar" ];
|
|
|
|
# ---- Host identity ----
|
|
networking.hostName = "jupiter";
|
|
networking.networkmanager.enable = true;
|
|
users.users.darman.extraGroups = [ "docker" ]; # merges with common.nix
|
|
|
|
# ---- Boot ----
|
|
# systemd-boot for UEFI. If ZimaBlade boots legacy/BIOS, switch to grub.
|
|
boot.loader.systemd-boot.enable = true;
|
|
boot.loader.efi.canTouchEfiVariables = true;
|
|
|
|
# Root lives on the ZimaBlade eMMC (mmcblk0). nixos-generate-config runs in
|
|
# the RAM installer and does NOT detect these, so pin them here (merged with
|
|
# hardware-configuration.nix) or stage-1 can't mount root and the box panics.
|
|
boot.initrd.availableKernelModules = [ "mmc_block" "sdhci_pci" "sdhci_acpi" ];
|
|
|
|
# Warm reboot hangs at firmware reset on this board (cold power-cycle works).
|
|
# Force the PCI-chipset reset method. If a warm `reboot` still hangs, try the
|
|
# next value: acpi -> bios -> cold -> efi.
|
|
boot.kernelParams = [ "reboot=pci" ];
|
|
|
|
# ---- NAS data array ----
|
|
# Existing ext4 on the mdadm RAID0 over sda+sdb (md0, 29.1T).
|
|
# Mounted, NOT formatted; kept out of disko so it is never wiped.
|
|
# ⚠️ RAID0 = no redundancy: either 16TB disk failing loses ALL data.
|
|
boot.swraid.enable = true; # assemble the mdadm array at boot
|
|
fileSystems."/mnt/data" = {
|
|
# fs UUID (stable) — the array may enumerate as /dev/md127, so avoid /dev/md0.
|
|
device = "/dev/disk/by-uuid/dadbff6f-652e-49b2-bfed-eb1308ab8b78";
|
|
fsType = "ext4";
|
|
options = [ "nofail" ]; # don't block boot if the array is degraded/absent
|
|
};
|
|
|
|
# ---- Caddy vhosts (LAN) ----
|
|
# Reached via pihole local-DNS names -> jupiter IP.
|
|
services.caddy.virtualHosts = {
|
|
"http://audiobookshelf.jupiter.sol".extraConfig = "reverse_proxy localhost:8000";
|
|
"http://jellyfin.jupiter.sol".extraConfig = "reverse_proxy localhost:8096";
|
|
"http://sabnzbd.jupiter.sol".extraConfig = "reverse_proxy localhost:8085";
|
|
"http://prowlarr.jupiter.sol".extraConfig = "reverse_proxy localhost:9696";
|
|
"http://sonarr.jupiter.sol".extraConfig = "reverse_proxy localhost:8989";
|
|
"http://radarr.jupiter.sol".extraConfig = "reverse_proxy localhost:7878";
|
|
"http://clonarr.jupiter.sol".extraConfig = "reverse_proxy localhost:6060";
|
|
"http://seerr.jupiter.sol".extraConfig = "reverse_proxy localhost:5055";
|
|
"http://gitea.jupiter.sol".extraConfig = "reverse_proxy localhost:3000";
|
|
# Immich uploads are large: raise the body limit off caddy's default and
|
|
# give slow phone uploads room before the proxy gives up.
|
|
"http://immich.jupiter.sol".extraConfig = ''
|
|
request_body {
|
|
max_size 50GB
|
|
}
|
|
reverse_proxy localhost:2283
|
|
'';
|
|
};
|
|
|
|
system.stateVersion = "26.05";
|
|
}
|