From 411c11850056704e2e86973258bbac539954fbb1 Mon Sep 17 00:00:00 2001 From: oqyude Date: Tue, 11 Aug 2026 22:07:09 +0300 Subject: [PATCH] br v4 --- configurations/mini-laptop.nix | 15 +-- configurations/mini-pc.nix | 60 ++++-------- configurations/server.nix | 54 ++++------- flake.lock | 43 +++++++++ flake.nix | 9 ++ home/home.nix | 85 ++++++++-------- home/server.nix | 13 +-- home/wsl.nix | 17 +--- lib/xlib.nix | 153 +++++++++++++++++++++++++++++ modules/options.nix | 130 +++++++------------------ modules/pkgs/beets.nix | 9 +- modules/server/calibre-web.nix | 37 ++++--- modules/server/default.nix | 4 +- modules/server/gitea.nix | 10 +- modules/server/homebox.nix | 33 ++----- modules/server/immich.nix | 2 +- modules/server/memos.nix | 2 +- modules/server/n8n.nix | 25 ++--- modules/server/navidrome.nix | 13 +-- modules/server/nextcloud.nix | 2 +- modules/server/nfs.nix | 2 +- modules/server/nginx.nix | 171 +++++++++++++++------------------ modules/server/postgresql.nix | 26 ++--- modules/server/samba.nix | 25 ++--- modules/server/step-ca.nix | 23 +++-- modules/server/trilium.nix | 2 +- modules/server/uptime-kuma.nix | 12 +-- modules/users.nix | 78 ++++++++------- modules/vds/default.nix | 5 +- 29 files changed, 543 insertions(+), 517 deletions(-) create mode 100644 lib/xlib.nix diff --git a/configurations/mini-laptop.nix b/configurations/mini-laptop.nix index e2a1fed..847dc5a 100644 --- a/configurations/mini-laptop.nix +++ b/configurations/mini-laptop.nix @@ -25,17 +25,10 @@ }; }; - fileSystems."${xlib.dirs.lamet-drive}" = { - device = "/dev/disk/by-uuid/DC76BD3576BD116E"; - fsType = "ntfs3"; - options = [ - "defaults" - "uid=1000" - "gid=1000" - "fmask=0000" - "dmask=0000" - "nofail" - ]; + fileSystems = xlib.helpers.mkNtfsMount { + path = xlib.dirs.lamet-drive; + uuid = "DC76BD3576BD116E"; + mask = "0000"; }; xlib.ssh.enable = true; diff --git a/configurations/mini-pc.nix b/configurations/mini-pc.nix index d1625c7..ba535ba 100644 --- a/configurations/mini-pc.nix +++ b/configurations/mini-pc.nix @@ -18,47 +18,25 @@ self.nixosModules.default ]; - fileSystems = { - "${xlib.dirs.therima-drive}" = { - enable = false; - device = "/dev/disk/by-uuid/C0A2DDEFA2DDEA44"; - fsType = "ntfs3"; - options = [ - "defaults" - "uid=1000" - "gid=1000" - "fmask=0007" - "dmask=0007" - "nofail" - ]; - }; - "${xlib.dirs.vetymae-drive}" = { - enable = false; - device = "/dev/disk/by-uuid/6408433908430A0E"; - fsType = "ntfs3"; - options = [ - "defaults" - "uid=1000" - "gid=1000" - "fmask=0007" - "dmask=0007" - "nofail" - ]; - }; - "${xlib.dirs.soptur-drive}" = { - enable = false; - device = "/dev/disk/by-uuid/C00C56E40C56D54E"; - fsType = "ntfs3"; - options = [ - "defaults" - "uid=1000" - "gid=1000" - "fmask=0007" - "dmask=0007" - "nofail" - ]; - }; - }; + fileSystems = lib.listToAttrs ( + map (xlib.helpers.mkNtfsMount) [ + { + path = xlib.dirs.therima-drive; + uuid = "C0A2DDEFA2DDEA44"; + enable = false; + } + { + path = xlib.dirs.vetymae-drive; + uuid = "6408433908430A0E"; + enable = false; + } + { + path = xlib.dirs.soptur-drive; + uuid = "C00C56E40C56D54E"; + enable = false; + } + ] + ); boot = { kernelPackages = lib.mkDefault pkgs.linuxPackages_xanmod_stable; diff --git a/configurations/server.nix b/configurations/server.nix index b351973..330b2eb 100644 --- a/configurations/server.nix +++ b/configurations/server.nix @@ -38,42 +38,26 @@ intel-gpu-tools.enable = true; }; - fileSystems = { - # External drive - "${xlib.dirs.server-home}" = { - device = "/dev/disk/by-uuid/37e53ebc-5343-a94d-9fe2-0ca39e13a8de"; - fsType = "ext4"; + fileSystems = + (xlib.helpers.mkExfatMount { + path = xlib.dirs.archive-drive; + label = "archive"; + }) + // (xlib.helpers.mkExfatMount { + path = xlib.dirs.mobile-drive; + uuid = "7EB1-DC99"; + }) + // (xlib.helpers.mkBindMount { + what = xlib.dirs.services-folder; + where = xlib.dirs.services-mnt-folder; + }) + // { + # External drive + "${xlib.dirs.server-home}" = { + device = "/dev/disk/by-uuid/37e53ebc-5343-a94d-9fe2-0ca39e13a8de"; + fsType = "ext4"; + }; }; - # Archive drive - "${xlib.dirs.archive-drive}" = { - device = "/dev/disk/by-label/archive"; - fsType = "exfat"; - options = [ - "nofail" - "uid=1000" - "gid=1000" - ]; - }; - # Mobile SD-Card - "${xlib.dirs.mobile-drive}" = { - device = "/dev/disk/by-uuid/7EB1-DC99"; - fsType = "exfat"; - options = [ - "nofail" - "uid=1000" - "gid=1000" - ]; - }; - # Services in /mnt folder - "${xlib.dirs.services-mnt-folder}" = { - device = "${xlib.dirs.services-folder}"; - fsType = "none"; - options = [ - "bind" - "nofail" - ]; - }; - }; systemd.tmpfiles.rules = [ "z ${xlib.dirs.services-mnt-folder} 0777 root root -" diff --git a/flake.lock b/flake.lock index b30298d..9e26ae4 100644 --- a/flake.lock +++ b/flake.lock @@ -127,6 +127,32 @@ "type": "github" } }, + "nix-minecraft": { + "inputs": { + "flake-compat": [ + "flake-compat" + ], + "nixpkgs": [ + "nixpkgs" + ], + "systems": [ + "nix-systems" + ] + }, + "locked": { + "lastModified": 1786414302, + "narHash": "sha256-FNGnUYud1D3BqE1JU2Uef+puLB2Rml7gKSdIGQOb550=", + "owner": "Infinidoge", + "repo": "nix-minecraft", + "rev": "cacc8cd89550f0cbec7103f3db5e96d1a66c58e7", + "type": "github" + }, + "original": { + "owner": "Infinidoge", + "repo": "nix-minecraft", + "type": "github" + } + }, "nix-on-droid": { "inputs": { "home-manager": [ @@ -155,6 +181,21 @@ "type": "github" } }, + "nix-systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, "nixos-hardware": { "inputs": { "nixpkgs": "nixpkgs" @@ -348,7 +389,9 @@ "flake-compat": "flake-compat", "grub2-themes": "grub2-themes", "home-manager": "home-manager", + "nix-minecraft": "nix-minecraft", "nix-on-droid": "nix-on-droid", + "nix-systems": "nix-systems", "nixos-hardware": "nixos-hardware", "nixos-wsl": "nixos-wsl", "nixpkgs": "nixpkgs_2", diff --git a/flake.nix b/flake.nix index a22e1f0..76393fc 100644 --- a/flake.nix +++ b/flake.nix @@ -36,6 +36,7 @@ utils.url = "github:numtide/flake-utils"; flake-compat.url = "github:edolstra/flake-compat"; nixos-hardware.url = "github:NixOS/nixos-hardware/master"; + nix-systems.url = "github:nix-systems/default"; # nixos-facter-modules.url = "github:numtide/nixos-facter-modules"; # flake-utils.url = "github:numtide/flake-utils"; # flake-parts.url = "github:hercules-ci/flake-parts"; @@ -71,6 +72,14 @@ url = "github:vinceliuice/grub2-themes"; inputs.nixpkgs.follows = "nixpkgs"; }; + nix-minecraft = { + url = "github:Infinidoge/nix-minecraft"; + inputs = { + flake-compat.follows = "flake-compat"; + nixpkgs.follows = "nixpkgs"; + systems.follows = "nix-systems"; + }; + }; # nix-index-database = { # url = "github:nix-community/nix-index-database"; # inputs.nixpkgs.follows = "nixpkgs"; diff --git a/home/home.nix b/home/home.nix index 869c97c..87c01df 100644 --- a/home/home.nix +++ b/home/home.nix @@ -9,59 +9,56 @@ let ... }: let - mkHomeModule = username: { - imports = [ - (./. + "/${xlib.device.type}.nix") - ]; - home = { - username = username; - stateVersion = lib.mkDefault "26.05"; - homeDirectory = - if username == "root" then lib.mkDefault "/${username}" else lib.mkDefault "/home/${username}"; - enableNixpkgsReleaseCheck = false; - }; - # Headless hosts: no GUI user dirs - xdg = - lib.mkIf - (builtins.elem xlib.device.type [ - "server" - "vds" - "wsl" - ]) - { + mkUser = + username: + { + imports ? [ ], + headless ? false, + }: + { + inherit imports; + home = { + username = username; + stateVersion = lib.mkDefault "26.05"; + homeDirectory = + if username == "root" then lib.mkDefault "/${username}" else lib.mkDefault "/home/${username}"; + enableNixpkgsReleaseCheck = false; + }; + # Headless hosts: no GUI user dirs + xdg = lib.mkIf headless { + enable = true; + autostart.enable = true; + userDirs = { enable = true; - autostart.enable = true; - userDirs = { - enable = true; - createDirectories = false; - desktop = null; - documents = null; - download = null; - music = null; - pictures = null; - publicShare = null; - templates = null; - videos = null; - }; + createDirectories = false; + desktop = null; + documents = null; + download = null; + music = null; + pictures = null; + publicShare = null; + templates = null; + videos = null; }; - }; - mkRootModule = username: { - home = { - username = username; - stateVersion = lib.mkDefault "26.05"; - homeDirectory = - if username == "root" then lib.mkDefault "/${username}" else lib.mkDefault "/home/${username}"; - enableNixpkgsReleaseCheck = false; + }; }; - }; in { home-manager = { useGlobalPkgs = true; useUserPackages = true; users = { - root = mkRootModule "root"; - "${xlib.device.username}" = mkHomeModule xlib.device.username; + root = mkUser "root" { }; + "${xlib.device.username}" = mkUser xlib.device.username { + imports = [ + (./. + "/${xlib.device.type}.nix") + ]; + headless = builtins.elem xlib.device.type [ + "server" + "vds" + "wsl" + ]; + }; }; sharedModules = [ inputs.plasma-manager.homeModules.plasma-manager diff --git a/home/server.nix b/home/server.nix index f893366..3b9fe82 100644 --- a/home/server.nix +++ b/home/server.nix @@ -5,20 +5,13 @@ xlib, ... }: -let - symlinksPaths = { - "${config.home.homeDirectory}/External/Music" = "Music"; - }; - mkLinks = lib.mapAttrs' (sourcePath: targetPath: { - name = targetPath; - value.source = config.lib.file.mkOutOfStoreSymlink "${sourcePath}"; - }) symlinksPaths; -in { imports = [ ./minimal.nix ]; - home.file = mkLinks; + home.file = xlib.helpers.mkSymlinks config { + "${config.home.homeDirectory}/External/Music" = "Music"; + }; home.activation = { yaziSync = '' ${pkgs.rsync}/bin/rsync -Lrv --no-A --no-X "${config.home.homeDirectory}/.config/yazi/" "${xlib.dirs.storage}/yazi/" diff --git a/home/wsl.nix b/home/wsl.nix index f44e0be..c7144bc 100644 --- a/home/wsl.nix +++ b/home/wsl.nix @@ -5,23 +5,16 @@ xlib, ... }: -let - symlinksPaths = { - "${config.home.homeDirectory}/External/Music" = "Music"; - "${xlib.dirs.wsl-home}" = "External"; - "${xlib.dirs.wsl-storage}" = "Storage"; - }; - mkLinks = lib.mapAttrs' (sourcePath: targetPath: { - name = targetPath; - value.source = config.lib.file.mkOutOfStoreSymlink "${sourcePath}"; - }) symlinksPaths; -in { imports = [ ./apps ./minimal.nix ]; - home.file = mkLinks; + home.file = xlib.helpers.mkSymlinks config { + "${config.home.homeDirectory}/External/Music" = "Music"; + "${xlib.dirs.wsl-home}" = "External"; + "${xlib.dirs.wsl-storage}" = "Storage"; + }; home.activation = { yaziSync = '' ${pkgs.rsync}/bin/rsync -Lrv "${config.home.homeDirectory}/.config/yazi/" "${xlib.dirs.wsl-storage}/yazi/" diff --git a/lib/xlib.nix b/lib/xlib.nix new file mode 100644 index 0000000..99c3266 --- /dev/null +++ b/lib/xlib.nix @@ -0,0 +1,153 @@ +{ + lib, + ... +}: +# Shared pure helper functions for module definitions. +# Injected into every module via `xlib.helpers` (see options.nix). +let + # tmpfiles rule: "type dir mode user group -" + mkTmpfile = + type: dir: mode: user: group: + "${type} ${dir} ${mode} ${user} ${group} -"; + + # several tmpfiles types for the same dir, e.g. ["d" "z"] or ["d" "Z"] + mkTmpDirs = + { + dir, + mode, + user, + group, + types ? [ + "d" + "z" + ], + }: + map (type: mkTmpfile type dir mode user group) types; + + # fileSystems bind mount + mkBindMount = + { + what, + where, + }: + { + "${where}" = { + device = what; + fsType = "none"; + options = [ + "bind" + "nofail" + ]; + }; + }; + + # systemd.mounts bind mount (automount variant) + mkSystemdBind = + { + what, + where, + }: + { + enable = true; + options = "bind,x-systemd.automount,nofail"; + requires = [ "local-fs.target" ]; + type = "none"; + wantedBy = [ "multi-user.target" ]; + inherit what where; + }; + + # Full "service storage" block: services-mnt source dir + /var/lib target, + # tmpfiles d/z + automount bind. Used as: + # storage = xlib.helpers.mkServiceStorage { name = "x"; user = "x"; group = "x"; }; + # systemd = storage.systemd; + mkServiceStorage = + { + name, + user, + group, + mode ? "0755", + target ? "/var/lib/${name}", + base ? "/mnt/services", + }: + let + sourceDir = "${base}/${name}"; + in + { + inherit sourceDir target; + systemd = { + tmpfiles.rules = mkTmpDirs { + dir = sourceDir; + inherit mode user group; + }; + mounts = [ + (mkSystemdBind { + what = sourceDir; + where = target; + }) + ]; + }; + }; + + # ntfs3 mount, e.g. fileSystems = mkNtfsMount { path = ...; uuid = ...; } + mkNtfsMount = + { + path, + uuid, + mask ? "0007", + enable ? null, + }: + { + "${path}" = { + device = "/dev/disk/by-uuid/${uuid}"; + fsType = "ntfs3"; + options = [ + "defaults" + "uid=1000" + "gid=1000" + "fmask=${mask}" + "dmask=${mask}" + "nofail" + ]; + } + // lib.optionalAttrs (enable != null) { inherit enable; }; + }; + + # exfat mount, e.g. fileSystems = mkExfatMount { path = ...; uuid = ...; } + mkExfatMount = + { + path, + uuid ? null, + label ? null, + }: + { + "${path}" = { + device = if uuid != null then "/dev/disk/by-uuid/${uuid}" else "/dev/disk/by-label/${label}"; + fsType = "exfat"; + options = [ + "nofail" + "uid=1000" + "gid=1000" + ]; + }; + }; + + # home-manager out-of-store symlinks: path = source (target name = attr name) + mkSymlinks = + config: paths: + lib.mapAttrs' (sourcePath: targetPath: { + name = targetPath; + value.source = config.lib.file.mkOutOfStoreSymlink "${sourcePath}"; + }) paths; +in +{ + inherit + mkTmpfile + mkTmpDirs + mkBindMount + mkSystemdBind + mkServiceStorage + mkNtfsMount + mkExfatMount + mkSymlinks + ; +} diff --git a/modules/options.nix b/modules/options.nix index 66ff180..100735f 100644 --- a/modules/options.nix +++ b/modules/options.nix @@ -3,6 +3,17 @@ lib, ... }: +let + # Option factory for the xlib.dirs namespace + mkDir = + default: description: + lib.mkOption { + type = lib.types.str; + inherit default description; + }; + + helpers = import ../lib/xlib.nix { inherit lib; }; +in { options = { xlib = { @@ -39,101 +50,30 @@ }; }; dirs = { - user-home = lib.mkOption { - type = lib.types.str; - default = "/home/${config.xlib.device.username}"; - description = "User home directory."; - }; - user-storage = lib.mkOption { - type = lib.types.str; - default = "${config.xlib.dirs.user-home}/Storage"; - description = "User storage directory."; - }; - archive-drive = lib.mkOption { - type = lib.types.str; - default = "/mnt/archive"; - description = "Archive drive mount point."; - }; - lamet-drive = lib.mkOption { - type = lib.types.str; - default = "/mnt/lamet"; - description = "Lamet drive mount point."; - }; - mobile-drive = lib.mkOption { - type = lib.types.str; - default = "/mnt/mobile"; - description = "Mobile drive mount point."; - }; - therima-drive = lib.mkOption { - type = lib.types.str; - default = "/mnt/therima"; - description = "Therima drive mount point."; - }; - vetymae-drive = lib.mkOption { - type = lib.types.str; - default = "/mnt/vetymae"; - description = "Vetymae drive mount point."; - }; - soptur-drive = lib.mkOption { - type = lib.types.str; - default = "/mnt/soptur"; - description = "Soptur drive mount point."; - }; - wsl-home = lib.mkOption { - type = lib.types.str; - default = "/mnt/c/Users/${config.xlib.device.username}"; - description = "WSL home directory."; - }; - wsl-storage = lib.mkOption { - type = lib.types.str; - default = "${config.xlib.dirs.wsl-home}/Storage"; - description = "WSL storage directory."; - }; - server-home = lib.mkOption { - type = lib.types.str; - default = "/home/${config.xlib.device.username}/External"; - description = "Server home directory."; - }; - server-credentials = lib.mkOption { - type = lib.types.str; - default = "${config.xlib.dirs.server-home}/Credentials/server"; - description = "Server credentials directory."; - }; - storage = lib.mkOption { - type = lib.types.str; - default = "${config.xlib.dirs.server-home}/Storage"; - description = "General storage directory."; - }; - calibre-library = lib.mkOption { - type = lib.types.str; - default = "${config.xlib.dirs.server-home}/Books-Library"; - description = "Calibre library directory."; - }; - music-library = lib.mkOption { - type = lib.types.str; - default = "${config.xlib.dirs.user-home}/Music"; - description = "Music library directory."; - }; - services-folder = lib.mkOption { - type = lib.types.str; - default = "${config.xlib.dirs.server-home}/Services"; - description = "All services folder."; - }; - services-mnt-folder = lib.mkOption { - type = lib.types.str; - default = "/mnt/services"; - description = "All services folder."; - }; - services-nodes-folder = lib.mkOption { - type = lib.types.str; - default = "${config.xlib.dirs.services-mnt-folder}/nodes"; - description = "All nodes folder."; - }; - postgresql-folder = lib.mkOption { - type = lib.types.str; - default = "${config.xlib.dirs.services-mnt-folder}/postgresql"; - description = "PostgreSQL service folder."; - }; + user-home = mkDir "/home/${config.xlib.device.username}" "User home directory."; + user-storage = mkDir "${config.xlib.dirs.user-home}/Storage" "User storage directory."; + archive-drive = mkDir "/mnt/archive" "Archive drive mount point."; + lamet-drive = mkDir "/mnt/lamet" "Lamet drive mount point."; + mobile-drive = mkDir "/mnt/mobile" "Mobile drive mount point."; + therima-drive = mkDir "/mnt/therima" "Therima drive mount point."; + vetymae-drive = mkDir "/mnt/vetymae" "Vetymae drive mount point."; + soptur-drive = mkDir "/mnt/soptur" "Soptur drive mount point."; + wsl-home = mkDir "/mnt/c/Users/${config.xlib.device.username}" "WSL home directory."; + wsl-storage = mkDir "${config.xlib.dirs.wsl-home}/Storage" "WSL storage directory."; + server-home = mkDir "/home/${config.xlib.device.username}/External" "Server home directory."; + server-credentials = mkDir "${config.xlib.dirs.server-home}/Credentials/server" "Server credentials directory."; + storage = mkDir "${config.xlib.dirs.server-home}/Storage" "General storage directory."; + calibre-library = mkDir "${config.xlib.dirs.server-home}/Books-Library" "Calibre library directory."; + music-library = mkDir "${config.xlib.dirs.user-home}/Music" "Music library directory."; + services-folder = mkDir "${config.xlib.dirs.server-home}/Services" "All services folder."; + services-mnt-folder = mkDir "/mnt/services" "All services folder."; + services-nodes-folder = mkDir "${config.xlib.dirs.services-mnt-folder}/nodes" "All nodes folder."; + postgresql-folder = mkDir "${config.xlib.dirs.services-mnt-folder}/postgresql" "PostgreSQL service folder."; + }; + helpers = lib.mkOption { + type = lib.types.anything; + default = helpers; + description = "Shared helper functions (see lib/xlib.nix)."; }; }; }; diff --git a/modules/pkgs/beets.nix b/modules/pkgs/beets.nix index 758eb21..bd97c31 100644 --- a/modules/pkgs/beets.nix +++ b/modules/pkgs/beets.nix @@ -68,14 +68,9 @@ in }; }; systemd.mounts = [ - { - enable = true; - options = "bind,x-systemd.automount,nofail"; - requires = [ "local-fs.target" ]; - type = "none"; - wantedBy = [ "multi-user.target" ]; + (xlib.helpers.mkSystemdBind { what = "/home/${xlib.device.username}/Music"; where = "/home/${xlib.device.username}/.config/beets"; - } + }) ]; } diff --git a/modules/server/calibre-web.nix b/modules/server/calibre-web.nix index 0581c72..0d00c92 100644 --- a/modules/server/calibre-web.nix +++ b/modules/server/calibre-web.nix @@ -42,21 +42,30 @@ in # }; }; - systemd.tmpfiles.rules = [ - "d ${libraryDir} 0755 calibre-web calibre-web -" - "d ${sourceDir} 0755 calibre-web calibre-web -" - "Z ${libraryDir} 0755 calibre-web calibre-web -" - "Z ${sourceDir} 0755 calibre-web calibre-web -" - ]; - - fileSystems = { - "${targetDir}" = { - device = "${sourceDir}"; - fsType = "none"; - options = [ - "bind" - "nofail" + systemd.tmpfiles.rules = + xlib.helpers.mkTmpDirs { + dir = libraryDir; + mode = "0755"; + user = "calibre-web"; + group = "calibre-web"; + types = [ + "d" + "Z" + ]; + } + ++ xlib.helpers.mkTmpDirs { + dir = sourceDir; + mode = "0755"; + user = "calibre-web"; + group = "calibre-web"; + types = [ + "d" + "Z" ]; }; + + fileSystems = xlib.helpers.mkBindMount { + what = sourceDir; + where = targetDir; }; } diff --git a/modules/server/default.nix b/modules/server/default.nix index f5c52f4..12e6817 100644 --- a/modules/server/default.nix +++ b/modules/server/default.nix @@ -44,7 +44,7 @@ # ./zerotier.nix ]; systemd.tmpfiles.rules = [ - "d /mnt 0755 root root -" - "d ${xlib.dirs.services-mnt-folder} 0755 root root -" + (xlib.helpers.mkTmpfile "d" "/mnt" "0755" "root" "root") + (xlib.helpers.mkTmpfile "d" xlib.dirs.services-mnt-folder "0755" "root" "root") ]; } diff --git a/modules/server/gitea.nix b/modules/server/gitea.nix index 6ec7a48..520bd7c 100644 --- a/modules/server/gitea.nix +++ b/modules/server/gitea.nix @@ -22,8 +22,10 @@ }; }; - systemd.tmpfiles.rules = [ - "d ${config.services.gitea.stateDir} 0755 gitea gitea -" - "z ${config.services.gitea.stateDir} 0755 gitea gitea -" - ]; + systemd.tmpfiles.rules = xlib.helpers.mkTmpDirs { + dir = config.services.gitea.stateDir; + mode = "0755"; + user = "gitea"; + group = "gitea"; + }; } diff --git a/modules/server/homebox.nix b/modules/server/homebox.nix index 9d2cd7f..28711ce 100644 --- a/modules/server/homebox.nix +++ b/modules/server/homebox.nix @@ -5,8 +5,11 @@ ... }: let - sourceDir = "${xlib.dirs.services-mnt-folder}/homebox"; - targetDir = "/var/lib/homebox"; + storage = xlib.helpers.mkServiceStorage { + name = "homebox"; + user = "homebox"; + group = "homebox"; + }; in { services.homebox = { @@ -14,33 +17,17 @@ in settings = { HBOX_WEB_HOST = "0.0.0.0"; HBOX_WEB_PORT = "7745"; - HBOX_STORAGE_CONN_STRING = "file://${targetDir}"; + HBOX_STORAGE_CONN_STRING = "file://${storage.target}"; HBOX_STORAGE_PREFIX_PATH = "data"; HBOX_DATABASE_DRIVER = "sqlite3"; - HBOX_DATABASE_SQLITE_PATH = "${targetDir}/data/homebox.db?_pragma=busy_timeout=999&_pragma=journal_mode=WAL&_fk=1"; + HBOX_DATABASE_SQLITE_PATH = "${storage.target}/data/homebox.db?_pragma=busy_timeout=999&_pragma=journal_mode=WAL&_fk=1"; HBOX_OPTIONS_ALLOW_REGISTRATION = "true"; HBOX_OPTIONS_GITHUB_RELEASE_CHECK = "false"; HBOX_MODE = "production"; - HOME = "${targetDir}"; - TMPDIR = "${targetDir}/tmp"; + HOME = "${storage.target}"; + TMPDIR = "${storage.target}/tmp"; }; }; - systemd = { - tmpfiles.rules = [ - "d ${sourceDir} 0755 homebox homebox -" - "z ${sourceDir} 0755 homebox homebox -" - ]; - mounts = [ - { - enable = true; - options = "bind,x-systemd.automount,nofail"; - requires = [ "local-fs.target" ]; - type = "none"; - wantedBy = [ "multi-user.target" ]; - what = "${sourceDir}"; - where = "${targetDir}"; - } - ]; - }; + systemd = storage.systemd; } diff --git a/modules/server/immich.nix b/modules/server/immich.nix index 54174df..98c4897 100644 --- a/modules/server/immich.nix +++ b/modules/server/immich.nix @@ -20,7 +20,7 @@ }; systemd.tmpfiles.rules = [ - "z ${config.services.immich.mediaLocation} 0755 immich immich -" + (xlib.helpers.mkTmpfile "z" config.services.immich.mediaLocation "0755" "immich" "immich") ]; users.users.immich.extraGroups = [ diff --git a/modules/server/memos.nix b/modules/server/memos.nix index 4a27f45..9331bbf 100644 --- a/modules/server/memos.nix +++ b/modules/server/memos.nix @@ -21,6 +21,6 @@ }; systemd.tmpfiles.rules = [ - "z /mnt/services/memos 0750 memos memos -" + (xlib.helpers.mkTmpfile "z" "${xlib.dirs.services-mnt-folder}/memos" "0750" "memos" "memos") ]; } diff --git a/modules/server/n8n.nix b/modules/server/n8n.nix index 757d5eb..47c2f0b 100644 --- a/modules/server/n8n.nix +++ b/modules/server/n8n.nix @@ -7,8 +7,11 @@ ... }: let - sourceDir = "${xlib.dirs.services-mnt-folder}/n8n"; - targetDir = "/var/lib/n8n"; + storage = xlib.helpers.mkServiceStorage { + name = "n8n"; + user = "nobody"; + group = "nogroup"; + }; in { services.n8n = { @@ -21,21 +24,5 @@ in openFirewall = true; }; - systemd = { - tmpfiles.rules = [ - "d ${sourceDir} 0755 nobody nogroup -" - "z ${sourceDir} 0755 nobody nogroup -" - ]; - mounts = [ - { - enable = true; - options = "bind,x-systemd.automount,nofail"; - requires = [ "local-fs.target" ]; - type = "none"; - wantedBy = [ "multi-user.target" ]; - what = "${sourceDir}"; - where = "${targetDir}"; - } - ]; - }; + systemd = storage.systemd; } diff --git a/modules/server/navidrome.nix b/modules/server/navidrome.nix index e72f933..f68e9f3 100644 --- a/modules/server/navidrome.nix +++ b/modules/server/navidrome.nix @@ -24,14 +24,9 @@ in }; }; systemd.mounts = [ - { - enable = true; - options = "bind,x-systemd.automount,nofail"; - requires = [ "local-fs.target" ]; - type = "none"; - wantedBy = [ "multi-user.target" ]; - what = "${libraryDir}"; - where = "${pointDir}"; - } + (xlib.helpers.mkSystemdBind { + what = libraryDir; + where = pointDir; + }) ]; } diff --git a/modules/server/nextcloud.nix b/modules/server/nextcloud.nix index 3d4a392..671d5cf 100644 --- a/modules/server/nextcloud.nix +++ b/modules/server/nextcloud.nix @@ -201,7 +201,7 @@ # }; systemd.tmpfiles.rules = [ - "z ${config.services.nextcloud.home} 0750 nextcloud nextcloud -" + (xlib.helpers.mkTmpfile "z" config.services.nextcloud.home "0750" "nextcloud" "nextcloud") ]; environment.systemPackages = [ diff --git a/modules/server/nfs.nix b/modules/server/nfs.nix index b3ae98c..23034e9 100644 --- a/modules/server/nfs.nix +++ b/modules/server/nfs.nix @@ -6,7 +6,7 @@ }: { systemd.tmpfiles.rules = [ - "z /export 0755 nobody nogroup -" + (xlib.helpers.mkTmpfile "z" "/export" "0755" "nobody" "nogroup") ]; services.nfs = { server = { diff --git a/modules/server/nginx.nix b/modules/server/nginx.nix index 6f1644a..ffa9d99 100644 --- a/modules/server/nginx.nix +++ b/modules/server/nginx.nix @@ -7,6 +7,83 @@ }: let server = "192.168.1.20"; + + # Standard TLS proxy vhost: "/" -> http://server:port + # Returns { name = domain; value = vhost; } for builtins.listToAttrs + mkProxy = + { + domain, + port, + addSSL ? false, + body ? false, + }: + { + name = domain; + value = { + enableACME = true; + locations."/" = { + proxyPass = "http://${server}:${toString port}"; + proxyWebsockets = true; + }; + } + // lib.optionalAttrs (!addSSL) { forceSSL = true; } + // lib.optionalAttrs addSSL { addSSL = true; } + // lib.optionalAttrs body { + extraConfig = '' + client_max_body_size 5G; + ''; + }; + }; + + # Simple proxy sites + sites = [ + { + domain = "immich.zeroq.su"; + port = 2283; + addSSL = true; + body = true; + } + { + domain = "kuma.zeroq.su"; + port = 4001; + } + { + domain = "health.zeroq.su"; + port = 19999; + } + { + domain = "git.zeroq.su"; + port = 3000; + } + { + domain = "homebox.zeroq.su"; + port = 7745; + } + { + domain = "flux.zeroq.su"; + port = 6061; + } + { + domain = "navidrome.zeroq.su"; + port = 4533; + addSSL = true; + } + { + domain = "calibre.zeroq.su"; + port = 8083; + body = true; + } + { + domain = "nix-cache.zeroq.su"; + port = 5000; + body = true; + } + { + domain = "pdf.zeroq.su"; + port = 8446; + body = true; + } + ]; in { services = { @@ -16,7 +93,7 @@ in recommendedOptimisation = true; recommendedProxySettings = true; recommendedTlsSettings = true; - virtualHosts = { + virtualHosts = (builtins.listToAttrs (map mkProxy sites)) // { "nextcloud.private" = { forceSSL = false; enableACME = false; @@ -169,49 +246,6 @@ in # client_max_body_size 5G; # ''; # }; - "immich.zeroq.su" = { - addSSL = true; - enableACME = true; - locations."/" = { - proxyPass = "http://${server}:2283"; - proxyWebsockets = true; - }; - extraConfig = '' - client_max_body_size 5G; - ''; - }; - "kuma.zeroq.su" = { - forceSSL = true; - enableACME = true; - locations."/" = { - proxyPass = "http://${server}:4001"; - proxyWebsockets = true; - }; - }; - "health.zeroq.su" = { - forceSSL = true; - enableACME = true; - locations."/" = { - proxyPass = "http://${server}:19999"; - proxyWebsockets = true; - }; - }; - "git.zeroq.su" = { - forceSSL = true; - enableACME = true; - locations."/" = { - proxyPass = "http://${server}:3000"; - proxyWebsockets = true; - }; - }; - "homebox.zeroq.su" = { - forceSSL = true; - enableACME = true; - locations."/" = { - proxyPass = "http://${server}:7745"; - proxyWebsockets = true; - }; - }; # "agent.zeroq.su" = { # forceSSL = true; # enableACME = true; @@ -256,22 +290,6 @@ in # }; }; }; - "flux.zeroq.su" = { - forceSSL = true; - enableACME = true; - locations."/" = { - proxyPass = "http://${server}:6061"; - proxyWebsockets = true; - }; - }; - "navidrome.zeroq.su" = { - addSSL = true; - enableACME = true; - locations."/" = { - proxyPass = "http://${server}:4533"; - proxyWebsockets = true; - }; - }; "vetymae.opencodes.zeroq.su" = { forceSSL = true; enableACME = true; @@ -323,39 +341,6 @@ in client_max_body_size 5G; ''; }; - "calibre.zeroq.su" = { - forceSSL = true; - enableACME = true; - locations."/" = { - proxyPass = "http://${server}:8083"; - proxyWebsockets = true; - }; - extraConfig = '' - client_max_body_size 5G; - ''; - }; - "nix-cache.zeroq.su" = { - forceSSL = true; - enableACME = true; - locations."/" = { - proxyPass = "http://${server}:5000"; - proxyWebsockets = true; - }; - extraConfig = '' - client_max_body_size 5G; - ''; - }; - "pdf.zeroq.su" = { - forceSSL = true; - enableACME = true; - locations."/" = { - proxyPass = "http://${server}:8446"; - proxyWebsockets = true; - }; - extraConfig = '' - client_max_body_size 5G; - ''; - }; # "calibre.home.arpa" = { # forceSSL = true; # enableACME = true; diff --git a/modules/server/postgresql.nix b/modules/server/postgresql.nix index 303c3c9..1b8e1d7 100644 --- a/modules/server/postgresql.nix +++ b/modules/server/postgresql.nix @@ -7,8 +7,12 @@ ... }: let - sourceDir = "${xlib.dirs.services-mnt-folder}/postgresql"; - targetDir = "/var/lib/postgresql"; + storage = xlib.helpers.mkServiceStorage { + name = "postgresql"; + user = "postgres"; + group = "postgres"; + mode = "0760"; + }; in { services = { @@ -19,21 +23,5 @@ in # postgresqlBackup.enable = true; }; - systemd = { - tmpfiles.rules = [ - "d ${sourceDir} 0760 postgres postgres -" - "z ${sourceDir} 0760 postgres postgres -" - ]; - mounts = [ - { - enable = true; - options = "bind,x-systemd.automount,nofail"; - requires = [ "local-fs.target" ]; - type = "none"; - wantedBy = [ "multi-user.target" ]; - what = "${sourceDir}"; - where = "${targetDir}"; - } - ]; - }; + systemd = storage.systemd; } diff --git a/modules/server/samba.nix b/modules/server/samba.nix index 6490769..49cb6f1 100644 --- a/modules/server/samba.nix +++ b/modules/server/samba.nix @@ -6,8 +6,11 @@ ... }: let - sourceDir = "${xlib.dirs.services-mnt-folder}/samba"; - targetDir = "/var/lib/samba"; + storage = xlib.helpers.mkServiceStorage { + name = "samba"; + user = "root"; + group = "root"; + }; in { services = { @@ -69,21 +72,5 @@ in }; }; - systemd = { - tmpfiles.rules = [ - "d ${sourceDir} 0755 root root -" - "z ${sourceDir} 0755 root root -" - ]; - mounts = [ - { - enable = true; - options = "bind,x-systemd.automount,nofail"; - requires = [ "local-fs.target" ]; - type = "none"; - wantedBy = [ "multi-user.target" ]; - what = "${sourceDir}"; - where = "${targetDir}"; - } - ]; - }; + systemd = storage.systemd; } diff --git a/modules/server/step-ca.nix b/modules/server/step-ca.nix index 32fa68a..c175c5d 100644 --- a/modules/server/step-ca.nix +++ b/modules/server/step-ca.nix @@ -69,13 +69,9 @@ in }; }; - fileSystems."${targetDir}" = { - device = "${sourceDir}"; - fsType = "none"; - options = [ - "bind" - "nofail" - ]; + fileSystems = xlib.helpers.mkBindMount { + what = sourceDir; + where = targetDir; }; environment = { @@ -84,11 +80,14 @@ in ]; }; - systemd.tmpfiles.rules = [ - "d ${sourceDir} 0755 nobody nogroup -" - "z ${sourceDir} 0755 nobody nogroup -" - "Z ${sourceDir}/ 0700 nobody nogroup -" - ]; + systemd.tmpfiles.rules = + xlib.helpers.mkTmpDirs { + dir = sourceDir; + mode = "0755"; + user = "nobody"; + group = "nogroup"; + } + ++ [ (xlib.helpers.mkTmpfile "Z" "${sourceDir}/" "0700" "nobody" "nogroup") ]; sops.secrets = { intermediate-password = { diff --git a/modules/server/trilium.nix b/modules/server/trilium.nix index 0e7fdfc..c890073 100644 --- a/modules/server/trilium.nix +++ b/modules/server/trilium.nix @@ -18,6 +18,6 @@ in }; systemd.tmpfiles.rules = [ - "z ${sourceDir} 0750 trilium trilium -" + (xlib.helpers.mkTmpfile "z" sourceDir "0750" "trilium" "trilium") ]; } diff --git a/modules/server/uptime-kuma.nix b/modules/server/uptime-kuma.nix index 2d2ec4d..14cf89b 100644 --- a/modules/server/uptime-kuma.nix +++ b/modules/server/uptime-kuma.nix @@ -20,15 +20,11 @@ in }; systemd.tmpfiles.rules = [ - "z ${xlib.dirs.services-mnt-folder}/uptime-kuma 0755 nobody nogroup -" + (xlib.helpers.mkTmpfile "z" sourceDir "0755" "nobody" "nogroup") ]; - fileSystems."${targetDir}" = { - device = "${xlib.dirs.services-mnt-folder}/uptime-kuma"; - fsType = "none"; - options = [ - "bind" - "nofail" - ]; + fileSystems = xlib.helpers.mkBindMount { + what = sourceDir; + where = targetDir; }; } diff --git a/modules/users.nix b/modules/users.nix index 0bca5e4..28981a0 100644 --- a/modules/users.nix +++ b/modules/users.nix @@ -2,23 +2,54 @@ config, xlib, lib, - pkgs, ... }: +let + user = "${xlib.device.username}"; + userGroup = config.users.users."${user}".group; + + # sops secret factory: name == key by default, owner/group default to root + mkSecret = + { + path, + mode, + key ? null, + owner ? null, + group ? null, + }: + { + format = "yaml"; + inherit path mode; + } + // lib.optionalAttrs (key != null) { inherit key; } + // lib.optionalAttrs (owner != null) { inherit owner; } + // lib.optionalAttrs (group != null) { inherit group; }; + + # default owner = device user + mkUserSecret = + args: + mkSecret ( + args + // { + owner = user; + group = userGroup; + } + ); +in { xlib.device.username = "oqyude"; users = { mutableUsers = false; users = { - "${xlib.device.username}" = { - name = "${xlib.device.username}"; + "${user}" = { + name = "${user}"; isNormalUser = true; group = "users"; description = "Jor Oqyude"; hashedPasswordFile = config.sops.secrets.hashed_password.path; # hashed_password homeMode = "700"; - home = "/home/${xlib.device.username}"; + home = "/home/${user}"; extraGroups = [ "audio" "disk" @@ -46,51 +77,32 @@ secrets = { hashed_password = { neededForUsers = true; + format = "yaml"; key = "hashed_password"; - format = "yaml"; }; - age_key_private = { - format = "yaml"; - key = "age_key_private"; - path = "/home/${xlib.device.username}/.config/sops/age/keys.txt"; - owner = config.users.users."${xlib.device.username}".name; - group = config.users.users."${xlib.device.username}".group; + age_key_private = mkUserSecret { + path = "${xlib.dirs.user-home}/.config/sops/age/keys.txt"; mode = "0600"; }; - ssh_key_private = { - format = "yaml"; - key = "ssh_key_private"; - path = "/home/${xlib.device.username}/.ssh/id_ed25519"; - owner = config.users.users."${xlib.device.username}".name; - group = config.users.users."${xlib.device.username}".group; + ssh_key_private = mkUserSecret { + path = "${xlib.dirs.user-home}/.ssh/id_ed25519"; mode = "0600"; }; - ssh_key_public = { - format = "yaml"; - key = "ssh_key_public"; - path = "/home/${xlib.device.username}/.ssh/id_ed25519.pub"; - owner = config.users.users."${xlib.device.username}".name; - group = config.users.users."${xlib.device.username}".group; + ssh_key_public = mkUserSecret { + path = "${xlib.dirs.user-home}/.ssh/id_ed25519.pub"; mode = "0655"; }; - ssh_key_private_root = { - format = "yaml"; + ssh_key_private_root = mkSecret { key = "ssh_key_private"; path = "/root/.ssh/id_ed25519"; - owner = "root"; - group = "root"; mode = "0600"; }; - ssh_key_public_root = { - format = "yaml"; + ssh_key_public_root = mkSecret { key = "ssh_key_public"; path = "/root/.ssh/id_ed25519.pub"; - owner = "root"; - group = "root"; mode = "0655"; }; - ssh_key_public_host = { - format = "yaml"; + ssh_key_public_host = mkSecret { key = "ssh_key_public"; path = "/etc/ssh/id_ed25519.pub"; mode = "0655"; diff --git a/modules/vds/default.nix b/modules/vds/default.nix index f2bf66e..b3f5c3b 100644 --- a/modules/vds/default.nix +++ b/modules/vds/default.nix @@ -1,5 +1,6 @@ { lib, + xlib, ... }: { @@ -13,7 +14,7 @@ # ./xray.nix ]; systemd.tmpfiles.rules = [ - "d /mnt 0755 root root -" - "d ${xlib.dirs.services-mnt-folder} 0755 root root -" + (xlib.helpers.mkTmpfile "d" "/mnt" "0755" "root" "root") + (xlib.helpers.mkTmpfile "d" xlib.dirs.services-mnt-folder "0755" "root" "root") ]; }