Personal Nix flake
nixos home-manager nix
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat: Server features

Add zfs pool, mergerfs configuration

Add default storage locations for application data, config and logs

Add gotify OCI service

Move hostId and network interface configs to host vars

+266 -14
+1
nix/home/modules/cli/essentials/default.nix
··· 43 43 rsync 44 44 sad 45 45 serpl 46 + smartmontools 46 47 tgpt 47 48 tig 48 49 yazi
+1 -6
nix/nixos/configs/desktop/default.nix
··· 10 10 ci.build = true; 11 11 gaming.enable = true; 12 12 networking.trusted = true; 13 + serving.enable = true; 13 14 users.emily.enable = true; 14 - virtualization.oci = { 15 - enable = true; 16 - externalInterface = "enp6s0"; 17 - }; 18 15 profiles = { 19 16 formfactor.desktop = true; 20 17 hardware.gpu.nvidia = true; ··· 24 21 graphical = true; 25 22 }; 26 23 }; 27 - 28 - networking.interfaces.enp6s0.wakeOnLan.enable = true; 29 24 30 25 system.stateVersion = "23.11"; 31 26 home-manager.users.${name.user}.home.stateVersion = "24.11";
+5
nix/nixos/modules/default.nix
··· 39 39 ./secureboot 40 40 ./security 41 41 ./services 42 + ./serving 42 43 ./ssh 43 44 ./storage 44 45 ./syncthing ··· 64 65 theming.enable = lib.mkDefault true; 65 66 users.enable = lib.mkDefault true; 66 67 users.lpchaim.enable = lib.mkDefault true; 68 + virtualization.oci.services = { 69 + cloudflare-ddns.enable = lib.mkDefault config.my.virtualization.oci.enable; 70 + gotify.enable = lib.mkDefault config.my.virtualization.oci.enable; 71 + }; 67 72 zram.enable = lib.mkDefault true; 68 73 }; 69 74
+7
nix/nixos/modules/networking/default.nix
··· 21 21 my.networking.tailscale.advertise.tags = lib.mkIf cfg.trusted ["trusted"]; 22 22 23 23 networking = { 24 + hostId = config.my.hostVars.hostId or null; 24 25 enableIPv6 = cfg.ipv6.enable; 25 26 firewall.enable = true; 27 + interfaces = lib.mkIf (config.my.hostVars.interface or {} ? "wired") { 28 + ${config.my.hostVars.interface.wired}.wakeOnLan = { 29 + enable = true; 30 + policy = ["magic"]; 31 + }; 32 + }; 26 33 networkmanager = { 27 34 enable = true; 28 35 settings = {
+19
nix/nixos/modules/serving/default.nix
··· 1 + { 2 + config, 3 + lib, 4 + ... 5 + }: let 6 + cfg = config.my.serving; 7 + in { 8 + options.my.serving.enable = lib.mkEnableOption "serving tweaks"; 9 + 10 + imports = [ 11 + ./storage.nix 12 + ]; 13 + 14 + config = lib.mkIf cfg.enable { 15 + my = { 16 + virtualization.oci.enable = true; 17 + }; 18 + }; 19 + }
+73
nix/nixos/modules/serving/storage.nix
··· 1 + { 2 + config, 3 + lib, 4 + ... 5 + }: let 6 + cfg = config.my.serving.storage; 7 + in { 8 + options.my.serving.storage.enable = 9 + lib.mkEnableOption "serving" 10 + // {default = config.my.serving.enable;}; 11 + 12 + config = lib.mkIf cfg.enable { 13 + my.storage = { 14 + mergerfs.enable = true; 15 + zfs.enable = true; 16 + configDir = "/srv/storage/AppData/config"; 17 + dataDir = "/srv/storage/AppData/data"; 18 + logDir = "/srv/storage/AppData/log"; 19 + }; 20 + 21 + fileSystems = { 22 + "/srv/tank" = { 23 + device = "tank"; 24 + fsType = "zfs"; 25 + options = [ 26 + "defaults" 27 + "nofail" 28 + "noatime" 29 + ]; 30 + }; 31 + "/srv/hdd1" = { 32 + device = "/dev/disk/by-id/ata-WDC_WD40EZRZ-00GXCB0_WD-WCC7K5FR9AZE-part1"; 33 + fsType = "ext4"; 34 + options = [ 35 + "defaults" 36 + "nofail" 37 + "noatime" 38 + ]; 39 + }; 40 + "/srv/storage" = rec { 41 + device = lib.concatStringsSep ":" depends; 42 + fsType = "mergerfs"; 43 + depends = [ 44 + "/srv/tank" 45 + "/srv/hdd1" 46 + ]; 47 + options = [ 48 + "defaults" 49 + "nofail" 50 + "cache.files=off" 51 + "category.create=eppfrd" 52 + "dropcacheonclose=false" 53 + "export-support=true" 54 + "fsname=mergerfs" 55 + "func.getattr=newest" 56 + "inodecalc=path-hash" 57 + "ignorepponrename=true" 58 + "minfreespace=50G" 59 + "nonempty" 60 + "passthrough.io=rw" 61 + "xattr=passthrough" 62 + ]; 63 + }; 64 + }; 65 + 66 + services.smartd = { 67 + enable = true; 68 + autodetect = true; 69 + notifications.wall.enable = true; 70 + notifications.x11.enable = true; 71 + }; 72 + }; 73 + }
+16 -1
nix/nixos/modules/storage/default.nix
··· 1 - { 1 + {lib, ...}: { 2 2 imports = [ 3 3 ./mergerfs.nix 4 4 ./zfs.nix 5 5 ]; 6 + 7 + options.my.storage = { 8 + configDir = lib.mkOption { 9 + description = "Centralized program configuration directory"; 10 + type = lib.types.str; 11 + }; 12 + dataDir = lib.mkOption { 13 + description = "Centralized program data directory"; 14 + type = lib.types.str; 15 + }; 16 + logDir = lib.mkOption { 17 + description = "Centralized program log directory"; 18 + type = lib.types.str; 19 + }; 20 + }; 6 21 }
+2 -1
nix/nixos/modules/virtualization/oci/compose.nix
··· 31 31 config = lib.mkIf cfg.enable { 32 32 my.virtualization.oci.compose = { 33 33 attrs = { 34 - inherit (config.my.virtualization.oci) networks services; 34 + inherit (config.my.virtualization.oci) networks; 35 35 name = cfg.project; 36 + services = config.my.virtualization.oci.services.contents; 36 37 }; 37 38 prettyAttrs = 38 39 cfg.attrs
+1 -1
nix/nixos/modules/virtualization/oci/default.nix
··· 30 30 31 31 config = lib.mkIf cfg.enable { 32 32 my.virtualization.oci = { 33 + externalInterface = config.my.hostVars.interfaces.wired or null; 33 34 networks = { 34 35 internal = { 35 36 internal = true; 36 37 ipam.config = [{subnet = oci.internal.routingPrefix;}]; 37 38 }; 38 39 external = { 39 - external = true; 40 40 ipam.config = [{subnet = oci.external.routingPrefix;}]; 41 41 }; 42 42 };
+4 -4
nix/nixos/modules/virtualization/oci/services/cloudflare-ddns.nix
··· 5 5 ... 6 6 }: let 7 7 inherit (config.my.secret.helpers) mkSecret; 8 - cfg = config.my.virtualization.oci.containers.cloudflare-ddns; 8 + cfg = config.my.virtualization.oci.services.cloudflare-ddns; 9 9 in { 10 - options.my.virtualization.oci.containers.cloudflare-ddns = { 10 + options.my.virtualization.oci.services.cloudflare-ddns = { 11 11 enable = lib.mkEnableOption "cloudflare-ddns container"; 12 12 }; 13 13 ··· 32 32 }; 33 33 }; 34 34 35 - my.virtualization.oci.services.cloudflare-ddns = { 36 - image = "oznu/cloudflare-ddns"; 35 + my.virtualization.oci.services.contents.cloudflare-ddns = { 36 + image = "docker.io/oznu/cloudflare-ddns"; 37 37 environment = { 38 38 ZONE = self.vars.domain.main; 39 39 INTERFACE = config.my.virtualization.oci.externalInterface;
+2 -1
nix/nixos/modules/virtualization/oci/services/default.nix
··· 8 8 in { 9 9 imports = [ 10 10 ./cloudflare-ddns.nix 11 + ./gotify.nix 11 12 ]; 12 13 13 - options.my.virtualization.oci.services = lib.mkOption { 14 + options.my.virtualization.oci.services.contents = lib.mkOption { 14 15 description = "freeform OCI compose services"; 15 16 type = lib.types.submodule { 16 17 freeformType = format.type;
+48
nix/nixos/modules/virtualization/oci/services/gotify.nix
··· 1 + { 2 + config, 3 + lib, 4 + ... 5 + }: let 6 + inherit (config.my.secret.helpers) mkSecret; 7 + cfg = config.my.virtualization.oci.services.gotify; 8 + in { 9 + options.my.virtualization.oci.services.gotify = { 10 + enable = lib.mkEnableOption "gotify container"; 11 + }; 12 + 13 + config = lib.mkIf cfg.enable { 14 + my.secret.definitions = { 15 + "gotify-password" = mkSecret "gotify-password" { 16 + generator.script = "password"; 17 + }; 18 + "gotify-env" = mkSecret "gotify-env" { 19 + owner = config.my.virtualization.oci.user; 20 + generator = { 21 + dependencies = {inherit (config.age.secrets) gotify-password;}; 22 + script = { 23 + lib, 24 + decrypt, 25 + deps, 26 + ... 27 + }: '' 28 + printf 'GOTIFY_DEFAULTUSER_PASS="%s"\n' $(${decrypt} ${lib.escapeShellArg deps.gotify-password.file}) 29 + ''; 30 + }; 31 + }; 32 + }; 33 + 34 + my.virtualization.oci.services.contents.gotify = { 35 + image = "docker.io/gotify/server"; 36 + env_file = config.my.secrets."gotify-env".path; 37 + environment = { 38 + GOTIFY_DEFAULTUSER_NAME = "lpchaim"; 39 + }; 40 + ports = [ 41 + "8090:80" 42 + ]; 43 + volumes = [ 44 + "${config.my.storage.dataDir}/gotify:/app/data" 45 + ]; 46 + }; 47 + }; 48 + }
+1
nix/shared/secrets.nix
··· 21 21 generators = let 22 22 getBaseName = file: lib.escapeShellArg (lib.removeSuffix ".age" file); 23 23 in { 24 + password = {pkgs, ...}: "${pkgs.xkcdpass}/bin/xkcdpass --numwords=6 --delimiter='-'"; 24 25 ssh-ed25519-keypair = { 25 26 pkgs, 26 27 file,
+40
nix/tests/_snapshots/filesystems-desktop.snap.json
··· 62 62 "x-gvfs-show" 63 63 ] 64 64 }, 65 + "/srv/hdd1": { 66 + "device": "/dev/disk/by-id/ata-WDC_WD40EZRZ-00GXCB0_WD-WCC7K5FR9AZE-part1", 67 + "fsType": "ext4", 68 + "options": [ 69 + "defaults", 70 + "nofail", 71 + "noatime" 72 + ] 73 + }, 74 + "/srv/storage": { 75 + "device": "/srv/tank:/srv/hdd1", 76 + "fsType": "mergerfs", 77 + "options": [ 78 + "x-systemd.requires-mounts-for=/srv/tank", 79 + "x-systemd.requires-mounts-for=/srv/hdd1", 80 + "defaults", 81 + "nofail", 82 + "cache.files=off", 83 + "category.create=eppfrd", 84 + "dropcacheonclose=false", 85 + "export-support=true", 86 + "fsname=mergerfs", 87 + "func.getattr=newest", 88 + "inodecalc=path-hash", 89 + "ignorepponrename=true", 90 + "minfreespace=50G", 91 + "nonempty", 92 + "passthrough.io=rw", 93 + "xattr=passthrough" 94 + ] 95 + }, 96 + "/srv/tank": { 97 + "device": "tank", 98 + "fsType": "zfs", 99 + "options": [ 100 + "defaults", 101 + "nofail", 102 + "noatime" 103 + ] 104 + }, 65 105 "/var/cache": { 66 106 "device": "/dev/disk/by-id/nvme-Corsair_MP600_PRO_XT_214279380001310131BD-part2", 67 107 "fsType": "btrfs",
+7
secrets/.rekeyed/desktop/33ba9852dc854eb9e2161157f4012b03-gotify-password.age
··· 1 + age-encryption.org/v1 2 + -> ssh-ed25519 NQ2aOg NKstOo4cHOwtB20xX3GbjFNYe9ot8OYW7qMqA6M55iI 3 + Fy+0XBSQeJ2RKNfeaSJLmiOWeaR1yphY++ik7DR3dbw 4 + -> 8`+7C26-grease bw;k 9 g0kSJ' 5 + jwI 6 + --- +GyQZ7d90MRMNT5l0xfuUgmR9n1BNYCuDv8d62guub0 7 + ��>,>w�̞�: ��92�:��d�ԏBS�x�+ǔOܠF�$ �l�!�*S���w�:���]��5���(*����'���#\�
secrets/.rekeyed/desktop/ec0f527009dc8bea9c08e6952700f6ca-gotify-env.age

This is a binary file and will not be displayed.

secrets/.rekeyed/laptop/4979b510caf7ac9b3f83bb4e118f2ce7-gotify-env.age

This is a binary file and will not be displayed.

+8
secrets/.rekeyed/laptop/564eea3779c0e5e023f5b1506835703f-cloudflare-ddns-env.age
··· 1 + age-encryption.org/v1 2 + -> ssh-ed25519 9M20hg 8mWilK1cbWG1FAr8evWyN3lfSLic79A/phDVGMGnCCU 3 + BXcO4gwt20MOVIv0B6owjKiza5QWaRYeoVUOAzJy91A 4 + -> $-grease |nwdzXs Y(j;=h{ GD.Sfn 5 + CsUYsJE0r2Olgw 6 + --- p+b8/JKpRhPpLjRmVTZGiz65RF2LU/22UtnK1JgAKNs 7 + �!2���U��ݒH��c���Ğup�kĬ"���j��T�9;�_쫱82�M���.R&�&��=! 8 + &�OiC����b�
+8
secrets/.rekeyed/laptop/80d54651c9428d07f8f853d746219c88-gotify-password.age
··· 1 + age-encryption.org/v1 2 + -> ssh-ed25519 9M20hg uQdOYWbeexeUj5thX3vtt4gxu7gA0yMKcNvYqZKr1hs 3 + Wbzq0gXwr5Yi0AA5yqucXxjgy8mqDnCqNs8ZFdTnQAw 4 + -> m-{fc0O<-grease U, pkW > R 5 + TFSe54H1gYaLQGiY3FSd7o8TCRpmF/qn+9UUnrfIeA/VAMpHFiIq3jp5Q9spOL4B 6 + DskNImGEGgLKXzQNmwG6HzU 7 + --- 6vWmaS5FQJXgeQGxwRm1/m7LMkF+jU8eqsjh7p3BNIE 8 + �m�����Mq���#�����H�_��)��qL���T�&�4X�/S��H�?Yn������C�ak�6��j���Y_B���
+9
secrets/gotify-env.age
··· 1 + age-encryption.org/v1 2 + -> piv-p256 0D9K1g A9H7+xNQONIpfZ1tuIZU+Tk5KW/HV9tj0oG4+iijjHYd 3 + JzFugoGJ9ukt5QMKQT2WZ4x1Jl2pJzN6XyCsf3252ak 4 + -> piv-p256 4lCx1w A8UIksajlA+y8UA7o3Zh6QrWIot6WBIyk2dFhvLIygUl 5 + C8sqzJ12P8902ZDSctLvMNpKFyi5OnyaA4YKVsG+0EY 6 + -> M0ylB1U.-grease % /Y%]%I 4+1or'9 7 + 0q1PtRAQDZoCiPUl 8 + --- n3/RrlsPO6AoAk9XVdhtAOgx4TaJljb3CGpddSsf1zQ 9 + a�M�����׮V0a���_�w@���M�)��Ir���5�5�} �x��qJ�*w��h\�X�� A��u_]\~��YTd��U���%o��ȔϿPeݶ"G����
+9
secrets/gotify-password.age
··· 1 + age-encryption.org/v1 2 + -> piv-p256 0D9K1g AyHN7f2Qbg4gVBdrdesqt/riVKJxYdFkQ3MiLIZTJW6Q 3 + 9OrClJY31mFRF1HdBYLTvT10NWfcrIUtBxV9R0tjcyM 4 + -> piv-p256 4lCx1w AnkSX3aOMlee8JF/TGRUxahxv4i900r4zrTSqccfvZl0 5 + S9DMR3MLHtBYslj3fc/RI0jF6XobxpQHQv66apZhZq0 6 + -> c{|%v-grease {RA$B>@8 oc\~EUFN m 4RG 7 + cMU 8 + --- 3pRpK7O56Ugx9OopfjVgtnXdJuuT9nZFDaR4R4LZEyI 9 + !|����Sr�؆�|>or����CdL>m����t�+���O�c)*����2�+���ӣ 0��Ϡ�-��C��70�߫�!�J��3
+5
vars/hosts.nix
··· 2 2 desktop = { 3 3 pubKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAVYoVIxGgrX+TCAbwZX6MwE/2wCOtyENOrMu/rTzlhs"; 4 4 system = "x86_64-linux"; 5 + hostId = "ee8f47f9"; 5 6 ip.v4 = "10.0.0.50"; 7 + interface.wired = "enp6s0"; 6 8 }; 7 9 laptop = { 8 10 pubKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHh5IZnZipti8mCt0NPCVrJ5XTU2z+nb7d2hgMG4/B3C"; 9 11 system = "x86_64-linux"; 12 + hostId = "a014571b"; 10 13 }; 11 14 raspberrypi = { 12 15 pubKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILr9pl4qaL/+DV//lhE5y6V7xJ2eh1BSlwNYD9L9a2sQ"; 13 16 system = "aarch64-linux"; 17 + hostId = "ee66c96c"; 14 18 ip.v4 = "10.0.0.2"; 19 + interface.wired = "enabcm6e4ei0"; 15 20 }; 16 21 }