feat: add persistent ids to all users/groups

This commit is contained in:
Leon Schwarzäugl 2026-01-12 22:15:57 +01:00
parent 37a8e17cc9
commit 7f65f74fef
Signed by: swarsel
GPG key ID: 26A54C31F2A4FD84
62 changed files with 533 additions and 173 deletions

View file

@ -21,6 +21,27 @@ keys:
- &toto age16vzhcvz8tyxj8e0f47fy0z4p3dsg0ak4vl52ut3l07a0tz465cxslmhevl
- &twothreetunnel age1g7atkxdlt4ymeh7v7aa2yzr2hq2qkvzrc4r49ugttm3n582ymv9qrmpk8d
- &winters age1s0vssf9fey2l456hucppzx2x58xep279nsdcglvkqm30sr9ht37s8rvpza
- &summers-ankisync age1kyue7mfvzuxprjz2g6ulz2mxlr57rgzg6lfpnrqedkelehley5ls3enwsd
- &summers-atuin age1qpgj3ell93rzkpjq0ezs6t669ds3nyxx67pj50smx597pspz6fqs4jc6pt
- &summers-audio age1f63r2klnpfxmntswz5xydpa75ckgjqcs2yzkm0msqwqgz9aqgu0qwzr659
- &summers-firefly age17328xwk0z3znalpmma5rvp0lt5ghn5p8xfvnrtdxwsw80dqysacqj9j37q
- &summers-forgejo age1qdzkn6v3xhrfjwe8jxz3945dhyyhevwal0narjtr8whf9y7nh3wsn524u5
- &summers-freshrss age1etgfym5m8hn3hxs6cgg757zcv5zg5n22wq38fuq59n7qk7nef5uqyg6vvs
- &summers-homebox age17mugmkdw0y768a3huuf37r45eff9apyknxvwk3agg6xzsjmqp96q57tcty
- &summers-immich age16gf76uustmyyksm3t56zcq9g6j8avy0wrngh8laknfq733s5welqedeg4x
- &summers-jellyfin age1fnvlmhzju0yq908xtgags0sy85q3tacl2sc3w3vdd3yfp27xv5aq06v948
- &summers-kanidm age1s5gcxtatd9frwctzwg54fqycsx2sa73ll36k7qrpm9wwyknkldtst90gn4
- &summers-kavita age1d89878cvt7wsa07ydwtexspku5gppwstrpnpph4ufx5pcd4fadyqgf6lvl
- &summers-koillection age1ayupuxlrkepyvjk7xwgrd0pvcj3tfcha688mcuc8ees2hg3g2ersd0q3nc
- &summers-matrix age1cq7wxnugpfvjk6dgqpfmc8vemzhkg75drkgeaqjd9fuylz5qh40slazr4u
- &summers-monitoring age1vn6ya0japzpgc256jg57fldsqe4udmq50sj5hmkywn7rxfnskevsx2q96u
- &summers-nextcloud age1t7zagjfddns4yltupk7nx8xps4gh7mupyz85uuys0wd22cxj5qsq2hw0p7
- &summers-paperless age1rn0pxluh7m8dyeshek06d7scejqlrcewlk8xmyrwt5e5nev2dc2s3s78vq
- &summers-postgresql age12jh5836w3cmazec8ql652p9h3a3xn6quztztzqxg4n0kz7r96dnqqlhxxw
- &summers-radicale age1gxg2peektn8x36kk3nsgmeawl73e54kaadqd649ygwrv43kkvejq2cw64z
- &summers-storage age1kn34ny229gm0rg7wlcvxmcyjtz4gka6f2vd958fde6vmuzrxcvcsufra90
- &summers-transmission age1y69f2elvmq39lc3t3ucq9y7wt675520n7rvug88qg368qsmmk47qvwrtny
creation_rules:
- path_regex: secrets/repo/[^/]+\.(yaml|json|env|ini|enc)$
key_groups:
@ -42,6 +63,26 @@ creation_rules:
- *dgx
- *hintbooth-adguardhome
- *hintbooth-nginx
- *summers-ankisync
- *summers-atuin
- *summers-audio
- *summers-firefly
- *summers-forgejo
- *summers-freshrss
- *summers-homebox
- *summers-immich
- *summers-jellyfin
- *summers-kanidm
- *summers-kavita
- *summers-koillection
- *summers-matrix
- *summers-monitoring
- *summers-nextcloud
- *summers-paperless
- *summers-postgresql
- *summers-radicale
- *summers-storage
- *summers-transmission
- path_regex: secrets/work/[^/]+\.(yaml|json|env|ini)$
key_groups:
@ -159,6 +200,7 @@ creation_rules:
- *swarsel
age:
- *summers
- *summers-ankisync
- path_regex: hosts/nixos/x86_64-linux/summers/secrets/atuin/[^/]+\.(yaml|json|env|ini|enc)$
key_groups:
@ -166,6 +208,7 @@ creation_rules:
- *swarsel
age:
- *summers
- *summers-atuin
- path_regex: hosts/nixos/x86_64-linux/summers/secrets/audio/[^/]+\.(yaml|json|env|ini|enc)$
key_groups:
@ -173,6 +216,7 @@ creation_rules:
- *swarsel
age:
- *summers
- *summers-audio
- path_regex: hosts/nixos/x86_64-linux/summers/secrets/firefly/[^/]+\.(yaml|json|env|ini|enc)$
key_groups:
@ -180,6 +224,7 @@ creation_rules:
- *swarsel
age:
- *summers
- *summers-firefly
- path_regex: hosts/nixos/x86_64-linux/summers/secrets/forgejo/[^/]+\.(yaml|json|env|ini|enc)$
key_groups:
@ -187,6 +232,7 @@ creation_rules:
- *swarsel
age:
- *summers
- *summers-forgejo
- path_regex: hosts/nixos/x86_64-linux/summers/secrets/freshrss/[^/]+\.(yaml|json|env|ini|enc)$
key_groups:
@ -194,6 +240,7 @@ creation_rules:
- *swarsel
age:
- *summers
- *summers-freshrss
- path_regex: hosts/nixos/x86_64-linux/summers/secrets/homebox/[^/]+\.(yaml|json|env|ini|enc)$
key_groups:
@ -201,6 +248,7 @@ creation_rules:
- *swarsel
age:
- *summers
- *summers-homebox
- path_regex: hosts/nixos/x86_64-linux/summers/secrets/immich/[^/]+\.(yaml|json|env|ini|enc)$
key_groups:
@ -208,6 +256,7 @@ creation_rules:
- *swarsel
age:
- *summers
- *summers-immich
- path_regex: hosts/nixos/x86_64-linux/summers/secrets/jellyfin/[^/]+\.(yaml|json|env|ini|enc)$
key_groups:
@ -215,6 +264,7 @@ creation_rules:
- *swarsel
age:
- *summers
- *summers-jellyfin
- path_regex: hosts/nixos/x86_64-linux/summers/secrets/kanidm/[^/]+\.(yaml|json|env|ini|enc)$
key_groups:
@ -222,6 +272,7 @@ creation_rules:
- *swarsel
age:
- *summers
- *summers-kanidm
- path_regex: hosts/nixos/x86_64-linux/summers/secrets/kavita/[^/]+\.(yaml|json|env|ini|enc)$
key_groups:
@ -229,6 +280,7 @@ creation_rules:
- *swarsel
age:
- *summers
- *summers-kavita
- path_regex: hosts/nixos/x86_64-linux/summers/secrets/koillection/[^/]+\.(yaml|json|env|ini|enc)$
key_groups:
@ -236,6 +288,7 @@ creation_rules:
- *swarsel
age:
- *summers
- *summers-koillection
- path_regex: hosts/nixos/x86_64-linux/summers/secrets/matrix/[^/]+\.(yaml|json|env|ini|enc)$
key_groups:
@ -243,6 +296,7 @@ creation_rules:
- *swarsel
age:
- *summers
- *summers-matrix
- path_regex: hosts/nixos/x86_64-linux/summers/secrets/monitoring/[^/]+\.(yaml|json|env|ini|enc)$
key_groups:
@ -250,6 +304,7 @@ creation_rules:
- *swarsel
age:
- *summers
- *summers-monitoring
- path_regex: hosts/nixos/x86_64-linux/summers/secrets/nextcloud/[^/]+\.(yaml|json|env|ini|enc)$
key_groups:
@ -257,6 +312,7 @@ creation_rules:
- *swarsel
age:
- *summers
- *summers-nextcloud
- path_regex: hosts/nixos/x86_64-linux/summers/secrets/paperless/[^/]+\.(yaml|json|env|ini|enc)$
key_groups:
@ -264,6 +320,7 @@ creation_rules:
- *swarsel
age:
- *summers
- *summers-paperless
- path_regex: hosts/nixos/x86_64-linux/summers/secrets/postgresql/[^/]+\.(yaml|json|env|ini|enc)$
key_groups:
@ -271,6 +328,7 @@ creation_rules:
- *swarsel
age:
- *summers
- *summers-postgresql
- path_regex: hosts/nixos/x86_64-linux/summers/secrets/radicale/[^/]+\.(yaml|json|env|ini|enc)$
key_groups:
@ -278,6 +336,7 @@ creation_rules:
- *swarsel
age:
- *summers
- *summers-radicale
- path_regex: hosts/nixos/x86_64-linux/summers/secrets/storage/[^/]+\.(yaml|json|env|ini|enc)$
key_groups:
@ -285,6 +344,7 @@ creation_rules:
- *swarsel
age:
- *summers
- *summers-storage
- path_regex: hosts/nixos/x86_64-linux/summers/secrets/transmission/[^/]+\.(yaml|json|env|ini|enc)$
key_groups:
@ -292,6 +352,7 @@ creation_rules:
- *swarsel
age:
- *summers
- *summers-transmission
- path_regex: hosts/darwin/x86_64-darwin/nbm-imba-166/secrets/[^/]+\.(yaml|json|env|ini|enc)$
key_groups:

View file

@ -1721,6 +1721,7 @@ A short overview over each input and what it does:
smallpkgs.url = "github:nixos/nixpkgs/08fcb0dcb59df0344652b38ea6326a2d8271baff?narHash=sha256-HXIQzULIG/MEUW2Q/Ss47oE3QrjxvpUX7gUl4Xp6lnc%3D&shallow=1";
nixpkgs-dev.url = "github:Swarsel/nixpkgs/main";
nixpkgs-debug.url = "github:nixos/nixpkgs/master";
nixpkgs-kernel.url = "github:NixOS/nixpkgs/063f43f2dbdef86376cc29ad646c45c46e93234c?narHash=sha256-6m1Y3/4pVw1RWTsrkAK2VMYSzG4MMIj7sqUy7o8th1o%3D"; #specifically pinned for kernel version
nixpkgs-stable.url = "github:NixOS/nixpkgs/nixos-25.11";
nixpkgs-stable24_05.url = "github:NixOS/nixpkgs/nixos-24.05";
@ -2620,7 +2621,7 @@ Another note concerning [[https://flake.parts/][flake-parts]]:
};
nswitch = mkDevice "Nintendo Switch" {
info = "Atmosphère 1.3.2 @ FW 19.0.1";
info = "Atmosphere 1.3.2 @ FW 19.0.1";
image = "${self}/files/topology-images/nintendo-switch.png";
interfaces.eth1 = { };
};
@ -4267,7 +4268,7 @@ This is my main server that I run at home. It handles most tasks that require bi
:CUSTOM_ID: h:0fdefb4f-ce53-4caf-89ed-5d79646f70f0
:END:
#+begin_src nix-ts :tangle hosts/nixos/x86_64-linux/winters/hardware-configuration.nix
{ lib, modulesPath, ... }:
{ lib, config, modulesPath, ... }:
{
imports =

29
flake.lock generated
View file

@ -1460,11 +1460,11 @@
"pre-commit-hooks": "pre-commit-hooks_2"
},
"locked": {
"lastModified": 1757854196,
"narHash": "sha256-RDr3/JTpRyXSR1OOg+wzdOUmDL1Ke05OLV/xctbuQOw=",
"lastModified": 1767971910,
"narHash": "sha256-j8vLAUaH8oAU5TSprSGa81wx+roo89iG98mUAutsjb8=",
"owner": "oddlama",
"repo": "nixos-extra-modules",
"rev": "a584a970a05d0410dcb00e0ade684a0c0ce00c4b",
"rev": "672abff4255796950924b284b1a2b3dd37113bd2",
"type": "github"
},
"original": {
@ -1598,6 +1598,22 @@
"type": "github"
}
},
"nixpkgs-bisect": {
"locked": {
"lastModified": 1768161245,
"narHash": "sha256-fSidazKIcZElti/a1SOmIwSXw6hXR2GLO/2XmkXgtX4=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "d2a6c7729bbe95f5770ccd4d15a38e5037984b04",
"type": "github"
},
"original": {
"owner": "nixos",
"ref": "master",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs-dev": {
"locked": {
"lastModified": 1767131767,
@ -1893,11 +1909,11 @@
},
"nixpkgs_14": {
"locked": {
"lastModified": 1763966396,
"narHash": "sha256-6eeL1YPcY1MV3DDStIDIdy/zZCDKgHdkCmsrLJFiZf0=",
"lastModified": 1737885589,
"narHash": "sha256-Zf0hSrtzaM1DEz8//+Xs51k/wdSajticVrATqDrfQjg=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "5ae3b07d8d6527c42f17c876e404993199144b6a",
"rev": "852ff1d9e153d8875a83602e03fdef8a63f0ecf8",
"type": "github"
},
"original": {
@ -2659,6 +2675,7 @@
"nixos-images": "nixos-images",
"nixos-nftables-firewall": "nixos-nftables-firewall",
"nixpkgs": "nixpkgs_18",
"nixpkgs-bisect": "nixpkgs-bisect",
"nixpkgs-dev": "nixpkgs-dev",
"nixpkgs-kernel": "nixpkgs-kernel",
"nixpkgs-stable": "nixpkgs-stable_3",

View file

@ -27,6 +27,7 @@
smallpkgs.url = "github:nixos/nixpkgs/08fcb0dcb59df0344652b38ea6326a2d8271baff?narHash=sha256-HXIQzULIG/MEUW2Q/Ss47oE3QrjxvpUX7gUl4Xp6lnc%3D&shallow=1";
nixpkgs-dev.url = "github:Swarsel/nixpkgs/main";
nixpkgs-bisect.url = "github:nixos/nixpkgs/master";
nixpkgs-kernel.url = "github:NixOS/nixpkgs/063f43f2dbdef86376cc29ad646c45c46e93234c?narHash=sha256-6m1Y3/4pVw1RWTsrkAK2VMYSzG4MMIj7sqUy7o8th1o%3D"; #specifically pinned for kernel version
nixpkgs-stable.url = "github:NixOS/nixpkgs/nixos-25.11";
nixpkgs-stable24_05.url = "github:NixOS/nixpkgs/nixos-24.05";

View file

@ -68,8 +68,8 @@
guests = lib.mkIf (!minimal && config.swarselsystems.withMicroVMs) (
{ }
// confLib.mkMicrovm "adguardhome"
// confLib.mkMicrovm "nginx"
// confLib.mkMicrovm "adguardhome" { }
// confLib.mkMicrovm "nginx" { }
);
}

View file

@ -3,6 +3,7 @@
imports = [
"${self}/profiles/nixos/microvm"
"${self}/modules/nixos"
"${self}/modules/nixos/optional/microvm-guest-shares.nix"
];
swarselsystems = {

View file

@ -6,6 +6,7 @@ in
imports = [
"${self}/profiles/nixos/microvm"
"${self}/modules/nixos"
"${self}/modules/nixos/optional/microvm-guest-shares.nix"
];
swarselsystems = {

View file

@ -1,4 +1,4 @@
{ self, inputs, lib, minimal, ... }:
{ self, config, inputs, lib, minimal, confLib, ... }:
{
imports = [
@ -39,7 +39,7 @@
writeGlobalNetworks = false;
networkKernelModules = [ "igb" ];
rootDisk = "/dev/disk/by-id/ata-TS120GMTS420S_J024880123";
withMicroVMs = false;
withMicroVMs = true;
localVLANs = [ "services" "home" ]; # devices is only provided on interface for bmc
initrdVLAN = "home";
server = {
@ -83,7 +83,7 @@
acme = false; # cert handled by proxy
nfs = true;
kavita = true;
# kavita = true;
restic = true;
jellyfin = true;
navidrome = true;
@ -109,29 +109,29 @@
opkssh = true;
};
# guests = lib.mkIf (!minimal && config.swarselsystems.withMicroVMs) (
# { }
# // confLib.mkMicrovm "kavita"
# // confLib.mkMicrovm "jellyfin"
# // confLib.mkMicrovm "audio"
# // confLib.mkMicrovm "postgresql"
# // confLib.mkMicrovm "matrix"
# // confLib.mkMicrovm "nextcloud"
# // confLib.mkMicrovm "immich"
# // confLib.mkMicrovm "paperless"
# // confLib.mkMicrovm "transmission"
# // confLib.mkMicrovm "storage"
# // confLib.mkMicrovm "monitoring"
# // confLib.mkMicrovm "freshrss"
# // confLib.mkMicrovm "kanidm"
# // confLib.mkMicrovm "firefly"
# // confLib.mkMicrovm "koillection"
# // confLib.mkMicrovm "radicale"
# // confLib.mkMicrovm "atuin"
# // confLib.mkMicrovm "forgejo"
# // confLib.mkMicrovm "ankisync"
# // confLib.mkMicrovm "homebox"
# );
guests = lib.mkIf (!minimal && config.swarselsystems.withMicroVMs) (
{ }
// confLib.mkMicrovm "kavita" { withZfs = true; }
// confLib.mkMicrovm "jellyfin" { withZfs = true; }
// confLib.mkMicrovm "audio" { withZfs = true; }
// confLib.mkMicrovm "postgresql" { withZfs = true; }
// confLib.mkMicrovm "matrix" { withZfs = true; }
// confLib.mkMicrovm "nextcloud" { withZfs = true; }
// confLib.mkMicrovm "immich" { withZfs = true; }
// confLib.mkMicrovm "paperless" { withZfs = true; }
// confLib.mkMicrovm "transmission" { withZfs = true; }
// confLib.mkMicrovm "storage" { withZfs = true; }
// confLib.mkMicrovm "monitoring" { withZfs = true; }
// confLib.mkMicrovm "freshrss" { withZfs = true; }
// confLib.mkMicrovm "kanidm" { withZfs = true; }
// confLib.mkMicrovm "firefly" { withZfs = true; }
// confLib.mkMicrovm "koillection" { withZfs = true; }
// confLib.mkMicrovm "radicale" { withZfs = true; }
// confLib.mkMicrovm "atuin" { withZfs = true; }
// confLib.mkMicrovm "forgejo" { withZfs = true; }
// confLib.mkMicrovm "ankisync" { withZfs = true; }
// confLib.mkMicrovm "homebox" { withZfs = true; }
);
networking.nftables.firewall.zones.untrusted.interfaces = [ "lan" "bmc" ];

View file

@ -27,7 +27,7 @@
} // lib.optionalAttrs (!minimal) {
microvm = {
mem = 1024 * 2;
mem = 1024 * 1;
vcpu = 1;
};
@ -36,7 +36,7 @@
};
swarselmodules.server = {
ankisync = true;
# ankisync = true;
};
}

View file

@ -36,7 +36,7 @@
};
swarselmodules.server = {
atuin = true;
# atuin = true;
};
}

View file

@ -36,9 +36,9 @@
};
swarselmodules.server = {
navidrome = true;
spotifyd = true;
mpd = true;
# navidrome = true;
# spotifyd = true;
# mpd = true;
};
}

View file

@ -36,8 +36,9 @@
};
swarselmodules.server = {
firefly-iii = true;
nginx = true;
# firefly-iii = true;
# nginx = true;
# acme = true;
};
}

View file

@ -27,7 +27,7 @@
} // lib.optionalAttrs (!minimal) {
microvm = {
mem = 1024 * 2;
mem = 1024 * 1;
vcpu = 1;
};
@ -36,7 +36,7 @@
};
swarselmodules.server = {
forgejo = true;
# forgejo = true;
};
}

View file

@ -36,8 +36,9 @@
};
swarselmodules.server = {
freshrss = true;
nginx = true;
# freshrss = true;
# nginx = true;
# acme = true;
};
}

View file

@ -27,7 +27,7 @@
} // lib.optionalAttrs (!minimal) {
microvm = {
mem = 1024 * 2;
mem = 1024 * 1;
vcpu = 1;
};
@ -36,7 +36,7 @@
};
swarselmodules.server = {
homebox = true;
# homebox = true;
};
}

View file

@ -36,7 +36,7 @@
};
swarselmodules.server = {
immich = true;
# immich = true;
};
}

View file

@ -27,7 +27,7 @@
} // lib.optionalAttrs (!minimal) {
microvm = {
mem = 1024 * 2;
mem = 1024 * 3;
vcpu = 1;
};
@ -36,7 +36,7 @@
};
swarselmodules.server = {
jellyfin = true;
# jellyfin = true;
};
}

View file

@ -36,7 +36,7 @@
};
swarselmodules.server = {
kanidm = true;
# kanidm = true;
};
}

View file

@ -29,6 +29,7 @@
microvm = {
mem = 1024 * 1;
vcpu = 1;
};
swarselprofiles = {
@ -36,7 +37,7 @@
};
swarselmodules.server = {
kavita = true;
# kavita = true;
};
}

View file

@ -27,7 +27,7 @@
} // lib.optionalAttrs (!minimal) {
microvm = {
mem = 1024 * 2;
mem = 1024 * 1;
vcpu = 1;
};
@ -36,7 +36,7 @@
};
swarselmodules.server = {
koillection = true;
# koillection = true;
};
}

View file

@ -36,7 +36,7 @@
};
swarselmodules.server = {
matrix = true;
# matrix = true;
};
}

View file

@ -27,7 +27,7 @@
} // lib.optionalAttrs (!minimal) {
microvm = {
mem = 1024 * 2;
mem = 1024 * 3;
vcpu = 2;
};
@ -36,7 +36,7 @@
};
swarselmodules.server = {
grafana = true;
# grafana = true;
};
}

View file

@ -36,8 +36,9 @@
};
swarselmodules.server = {
nextcloud = true;
nginx = true;
# nextcloud = true;
# nginx = true;
# acme = true;
};
}

View file

@ -36,7 +36,7 @@
};
swarselmodules.server = {
paperless = true;
# paperless = true;
};
}

View file

@ -27,7 +27,7 @@
} // lib.optionalAttrs (!minimal) {
microvm = {
mem = 1024 * 2;
mem = 1024 * 1;
vcpu = 1;
};
@ -36,7 +36,7 @@
};
swarselmodules.server = {
postgresql = true;
# postgresql = true;
};
}

View file

@ -27,7 +27,7 @@
} // lib.optionalAttrs (!minimal) {
microvm = {
mem = 1024 * 2;
mem = 1024 * 1;
vcpu = 1;
};
@ -36,7 +36,7 @@
};
swarselmodules.server = {
radicale = true;
# radicale = true;
};
}

View file

@ -27,7 +27,7 @@
} // lib.optionalAttrs (!minimal) {
microvm = {
mem = 1024 * 2;
mem = 1024 * 4;
vcpu = 2;
};
@ -36,8 +36,8 @@
};
swarselmodules.server = {
nfs = true;
syncthing = true;
# nfs = true;
# syncthing = true;
};
}

View file

@ -27,7 +27,7 @@
} // lib.optionalAttrs (!minimal) {
microvm = {
mem = 1024 * 2;
mem = 1024 * 4;
vcpu = 2;
};
@ -36,7 +36,7 @@
};
swarselmodules.server = {
transmission = true;
# transmission = true;
};
}

View file

@ -1,4 +1,4 @@
{ lib, modulesPath, ... }:
{ lib, config, modulesPath, ... }:
{
imports =

View file

@ -1,5 +1,5 @@
# largely based on https://github.com/oddlama/nix-config/blob/main/modules/secrets.nix
{ config, inputs, lib, nodes, ... }:
{ config, inputs, lib, nodes, globals, ... }:
let
# If the given expression is a bare set, it will be wrapped in a function,
# so that the imported file can always be applied to the inputs, similar to
@ -53,7 +53,7 @@ in
secrets = lib.mkOption {
readOnly = true;
default = lib.mapAttrs (_: x: importEncrypted x { inherit lib nodes inputs; inherit (inputs.topologyPrivate) topologyPrivate; }) config.repo.secretFiles;
default = lib.mapAttrs (_: x: importEncrypted x { inherit lib nodes globals inputs; inherit (inputs.topologyPrivate) topologyPrivate; }) config.repo.secretFiles;
type = lib.types.unspecified;
description = "Exposes the loaded repo secrets. This option is read-only.";
};

View file

@ -13,6 +13,8 @@
};
"${config.swarselsystems.mainUser}" = {
isNormalUser = true;
uid = 1000;
autoSubUidGidRange = false;
description = "Leon S";
password = lib.mkIf (minimal || config.swarselsystems.isPublic) "setup";
hashedPasswordFile = lib.mkIf (!minimal && !config.swarselsystems.isPublic) config.sops.secrets.main-user-hashed-pw.path;

View file

@ -0,0 +1,15 @@
{ self, lib, config, inputs, microVMParent, nodes, ... }:
{
config = {
microvm = {
shares = [
{
tag = "persist";
source = "${lib.optionalString nodes.${microVMParent}.config.swarselsystems.isImpermanence "/persist"}/microvms/${config.networking.hostName}";
mountPoint = "/persist";
proto = "virtiofs";
}
];
};
};
}

View file

@ -1,4 +1,4 @@
{ self, lib, config, inputs, microVMParent, nodes, ... }:
{ self, lib, config, inputs, microVMParent, nodes, globals, confLib, ... }:
{
imports = [
inputs.disko.nixosModules.disko
@ -49,24 +49,16 @@
};
};
microvm = {
shares = [
{
tag = "persist";
source = "${lib.optionalString nodes.${microVMParent}.config.swarselsystems.isImpermanence "/persist"}/microvms/${config.networking.hostName}";
mountPoint = "/persist";
proto = "virtiofs";
}
];
# mount the writeable overlay so that we can use nix shells inside the microvm
volumes = [
{
image = "/tmp/nix-store-overlay-${config.networking.hostName}.img";
autoCreate = true;
mountPoint = config.microvm.writableStoreOverlay;
size = 1024;
}
];
};
# microvm = {
# mount the writeable overlay so that we can use nix shells inside the microvm
# volumes = [
# {
# image = "/tmp/nix-store-overlay-${config.networking.hostName}.img";
# autoCreate = true;
# mountPoint = config.microvm.writableStoreOverlay;
# size = 1024;
# }
# ];
# };
};
}

View file

@ -1,4 +1,4 @@
{ config, lib, ... }:
{ config, lib, confLib, ... }:
{
config = lib.mkIf (config.guests != { }) {
@ -17,5 +17,7 @@
(builtins.attrNames config.guests)
);
users.persistentIds.microvm = confLib.mkIds 999;
};
}

View file

@ -1,4 +1,4 @@
{ self, pkgs, lib, config, globals, ... }:
{ self, pkgs, lib, config, globals, confLib, ... }:
let
inherit (config.repo.secrets.common) dnsProvider dnsBase dnsMail;
@ -21,7 +21,10 @@ in
'';
};
users.groups.acme.members = lib.mkIf config.swarselmodules.server.nginx [ "nginx" ];
users = {
persistentIds.acme = confLib.mkIds 967;
groups.acme.members = lib.mkIf config.swarselmodules.server.nginx [ "nginx" ];
};
security.acme = {
acceptTerms = true;

View file

@ -45,9 +45,9 @@ in
};
boot = lib.mkIf (!config.swarselsystems.isClient) {
kernelParams = lib.mkIf (!config.swarselsystems.isCloud && ((config.swarselsystems.localVLANs == [ ]) || isRouter)) [
"ip=${localIp}::${gatewayIp}:${subnetMask}:${config.networking.hostName}::none"
];
# kernelParams = lib.mkIf (!config.swarselsystems.isCloud && ((config.swarselsystems.localVLANs == []) || isRouter)) [
# "ip=${localIp}::${gatewayIp}:${subnetMask}:${config.networking.hostName}::none"
# ];
initrd = {
secrets."/tmp${hostKeyPathBase}" = if minimal then (lib.mkForce generatedHostKey) else (lib.mkForce hostKeyPath); # need to mkForce this or it behaves stateful
availableKernelModules = config.swarselsystems.networkKernelModules;

View file

@ -13,6 +13,9 @@ in
config = lib.mkIf config.swarselmodules.server.${serviceName} {
users = {
persistentIds = {
firefly-iii = confLib.mkIds 983;
};
groups.${serviceGroup} = { };
users.${serviceUser} = {
group = lib.mkForce serviceGroup;

View file

@ -12,9 +12,14 @@ in
# networking.firewall.allowedTCPPorts = [ servicePort ];
users.users.${serviceUser} = {
group = serviceGroup;
isSystemUser = true;
users = {
persistentIds = {
forgejo = confLib.mkIds 985;
};
users.${serviceUser} = {
group = serviceGroup;
isSystemUser = true;
};
};
users.groups.${serviceGroup} = { };

View file

@ -9,10 +9,15 @@ in
options.swarselmodules.server.${serviceName} = lib.mkEnableOption "enable ${serviceName} on server";
config = lib.mkIf config.swarselmodules.server.${serviceName} {
users.users.${serviceUser} = {
extraGroups = [ "users" ];
group = serviceGroup;
isSystemUser = true;
users = {
persistentIds = {
freshrss = confLib.mkIds 986;
};
users.${serviceUser} = {
extraGroups = [ "users" ];
group = serviceGroup;
isSystemUser = true;
};
};
users.groups.${serviceGroup} = { };

View file

@ -13,6 +13,10 @@ in
icon = "${self}/files/topology-images/${serviceName}.png";
};
users.persistentIds = {
homebox = confLib.mkIds 981;
};
globals = {
networks = {
${webProxyIf}.hosts = lib.mkIf isProxied {
@ -29,14 +33,25 @@ in
};
};
systemd.services.homebox = {
environment = {
TMPDIR = "/var/lib/homebox/.tmp";
};
serviceConfig = {
# ReadWritePaths = "/var/lib/homebox";
RuntimeDirectory = "homebox";
BindPaths = "/run/homebox:/var/lib/homebox/.tmp";
};
};
services.${serviceName} = {
enable = true;
package = pkgs.dev.homebox;
package = pkgs.bisect.homebox;
database.createLocally = true;
settings = {
HBOX_WEB_PORT = builtins.toString servicePort;
HBOX_OPTIONS_ALLOW_REGISTRATION = "false";
HBOX_STORAGE_CONN_STRING = "file:///Vault/data/homebox";
HBOX_STORAGE_CONN_STRING = "file:///var/lib/homebox";
HBOX_STORAGE_PREFIX_PATH = ".data";
};
};

103
modules/nixos/server/id.nix Normal file
View file

@ -0,0 +1,103 @@
{ lib, config, confLib, ... }:
let
inherit (lib)
concatLists
flip
mapAttrsToList
mkDefault
mkIf
mkOption
types
;
cfg = config.users.persistentIds;
in
{
options = {
swarselmodules.server.ids = lib.mkEnableOption "enable persistent ids on server";
users.persistentIds = mkOption {
default = { };
description = ''
Maps a user or group name to its expected uid/gid values. If a user/group is
used on the system without specifying a uid/gid, this module will assign the
corresponding ids defined here, or show an error if the definition is missing.
'';
type = types.attrsOf (
types.submodule {
options = {
uid = mkOption {
type = types.nullOr types.int;
default = null;
description = "The uid to assign if it is missing in `users.users.<name>`.";
};
gid = mkOption {
type = types.nullOr types.int;
default = null;
description = "The gid to assign if it is missing in `users.groups.<name>`.";
};
};
}
);
};
users.users = mkOption {
type = types.attrsOf (
types.submodule (
{ name, ... }:
{
config.uid =
let
persistentUid = cfg.${name}.uid or null;
in
mkIf (persistentUid != null) (mkDefault persistentUid);
}
)
);
};
users.groups = mkOption {
type = types.attrsOf (
types.submodule (
{ name, ... }:
{
config.gid =
let
persistentGid = cfg.${name}.gid or null;
in
mkIf (persistentGid != null) (mkDefault persistentGid);
}
)
);
};
};
config = lib.mkIf config.swarselmodules.server.ids {
assertions =
concatLists
(
flip mapAttrsToList config.users.users (
name: user: [
{
assertion = user.uid != null;
message = "non-persistent uid detected for '${name}', please assign one via `users.persistentIds`";
}
{
assertion = !user.autoSubUidGidRange;
message = "non-persistent subUids/subGids detected for: ${name}";
}
]
)
)
++ flip mapAttrsToList config.users.groups (
name: group: {
assertion = group.gid != null;
message = "non-persistent gid detected for '${name}', please assign one via `users.persistentIds`";
}
);
users.persistentIds = {
systemd-coredump = confLib.mkIds 998;
systemd-oom = confLib.mkIds 997;
polkituser = confLib.mkIds 973;
nscd = confLib.mkIds 972;
};
};
}

View file

@ -7,8 +7,14 @@ in
options.swarselmodules.server.${serviceName} = lib.mkEnableOption "enable ${serviceName} on server";
config = lib.mkIf config.swarselmodules.server.${serviceName} {
users.users.${serviceUser} = {
extraGroups = [ "video" "render" "users" ];
users = {
persistentIds = {
immich = confLib.mkIds 989;
redis-immich = confLib.mkIds 977;
};
users.${serviceUser} = {
extraGroups = [ "video" "render" "users" ];
};
};
topology.self.services.${serviceName}.info = "https://${serviceDomain}";

View file

@ -7,10 +7,12 @@ in
options.swarselmodules.server.${serviceName} = lib.mkEnableOption "enable ${serviceName} on server";
config = lib.mkIf config.swarselmodules.server.${serviceName} {
users.users.${serviceUser} = {
extraGroups = [ "video" "render" "users" ];
users = {
persistentIds.jellyfin = confLib.mkIds 994;
users.${serviceUser} = {
extraGroups = [ "video" "render" "users" ];
};
};
# nixpkgs.config.packageOverrides = pkgs: {
# intel-vaapi-driver = pkgs.intel-vaapi-driver.override { enableHybridCodec = true; };
# };

View file

@ -34,6 +34,9 @@ in
users = {
persistentIds = {
kanidm = confLib.mkIds 984;
};
users.${serviceUser} = {
group = serviceGroup;
isSystemUser = true;

View file

@ -12,11 +12,14 @@ in
calibre
];
users.users.${serviceUser} = {
extraGroups = [ "users" ];
users = {
persistentIds.kavita = confLib.mkIds 995;
users.${serviceUser} = {
extraGroups = [ "users" ];
};
};
sops.secrets.kavita-token = { inherit sopsFile; owner = serviceUser; };
# networking.firewall.allowedTCPPorts = [ servicePort ];

View file

@ -82,6 +82,8 @@ in
{ directory = serviceDir; mode = "0700"; }
];
users.persistentIds.kea = confLib.mkIds 968;
topology = {
extractors.kea.enable = false;
self.services.${serviceName} = {

View file

@ -314,6 +314,11 @@ in
# restart the bridges daily. this is done for the signal bridge mainly which stops carrying
# messages out after a while.
users.persistentIds = {
mautrix-signal = confLib.mkIds 993;
mautrix-whatsapp = confLib.mkIds 992;
mautrix-telegram = confLib.mkIds 991;
};
nodes =
let

View file

@ -42,6 +42,11 @@ in
};
users = {
persistentIds = {
nextcloud-exporter = confLib.mkIds 988;
node-exporter = confLib.mkIds 987;
grafana = confLib.mkIds 974;
};
users = {
nextcloud-exporter = {
extraGroups = [ "nextcloud" ];

View file

@ -16,6 +16,11 @@ in
kanidm-nextcloud-client = { inherit sopsFile; owner = serviceUser; group = serviceGroup; mode = "0440"; };
};
users.persistentIds = {
nextcloud = confLib.mkIds 990;
redis-nextcloud = confLib.mkIds 976;
};
globals.services.${serviceName} = {
domain = serviceDomain;
inherit proxyAddress4 proxyAddress6 isHome serviceAddress;

View file

@ -1,10 +1,15 @@
{ lib, config, pkgs, globals, ... }:
{ lib, config, pkgs, globals, confLib, ... }:
let
nfsUser = globals.user.name;
in
{
options.swarselmodules.server.nfs = lib.mkEnableOption "enable nfs on server";
config = lib.mkIf config.swarselmodules.server.nfs {
users.persistentIds = {
avahi = confLib.mkIds 978;
};
services = {
# add a user with sudo smbpasswd -a <user>
samba = {

View file

@ -11,6 +11,9 @@ in
options.swarselmodules.server.${serviceName} = lib.mkEnableOption "enable ${serviceName} on server";
config = lib.mkIf config.swarselmodules.server.${serviceName} {
users.persistentIds = {
opksshuser = confLib.mkIds 980;
};
services.${serviceName} = {
enable = true;

View file

@ -12,8 +12,13 @@ in
options.swarselmodules.server.${serviceName} = lib.mkEnableOption "enable ${serviceName} on server";
config = lib.mkIf config.swarselmodules.server.${serviceName} {
users.users.${serviceUser} = {
extraGroups = [ "users" ];
users = {
persistentIds = {
redis-paperless = confLib.mkIds 975;
};
users.${serviceUser} = {
extraGroups = [ "users" ];
};
};
sops.secrets = {

View file

@ -1,9 +1,11 @@
{ lib, config, ... }:
{ lib, config, confLib, ... }:
{
config = lib.mkIf (config?swarselmodules.server.mpd || config?swarselmodules.server.navidrome) {
config = lib.mkIf (config.swarselmodules.server.mpd || config.swarselmodules.server.navidrome) {
security.rtkit.enable = true; # this is required for pipewire real-time access
users.persistentIds.rtkit = confLib.mkIds 996;
services.pipewire = {
enable = true;
pulse.enable = true;

View file

@ -1,4 +1,4 @@
{ config, lib, ... }:
{ config, lib, confLib, ... }:
let
serviceName = "podman";
in
@ -6,6 +6,10 @@ in
options.swarselmodules.server.${serviceName} = lib.mkEnableOption "enable ${serviceName} on server";
config = lib.mkIf config.swarselmodules.server.${serviceName} {
users.persistentIds = {
podman = confLib.mkIds 969;
};
virtualisation = {
podman.enable = true;
oci-containers.backend = "podman";

View file

@ -29,6 +29,10 @@ in
};
};
users.persistentIds = {
radicale = confLib.mkIds 982;
};
topology.self.services.${serviceName}.info = "https://${serviceDomain}";
globals = {

View file

@ -11,6 +11,10 @@ in
paths = lib.mkOption {
type = lib.types.listOf lib.types.str;
};
withPostgres = lib.mkOption {
type = lib.types.bool;
default = false;
};
};
config = lib.mkIf config.swarselmodules.server.restic {

View file

@ -1,4 +1,4 @@
{ self, lib, config, withHomeManager, ... }:
{ self, lib, config, withHomeManager, confLib, ... }:
{
options.swarselmodules.server.ssh = lib.mkEnableOption "enable ssh on server";
config = lib.mkIf config.swarselmodules.server.ssh {
@ -21,17 +21,22 @@
}
];
};
users.users = {
"${config.swarselsystems.mainUser}".openssh.authorizedKeys.keyFiles = lib.mkIf withHomeManager [
(self + /secrets/public/ssh/yubikey.pub)
(self + /secrets/public/ssh/magicant.pub)
# (lib.mkIf config.swarselsystems.isBastionTarget (self + /secrets/public/ssh/jump.pub))
];
root.openssh.authorizedKeys.keyFiles = [
(self + /secrets/public/ssh/yubikey.pub)
(self + /secrets/public/ssh/magicant.pub)
# (lib.mkIf config.swarselsystems.isBastionTarget (self + /secrets/public/ssh/jump.pub))
];
users = {
persistentIds = {
sshd = lib.mkIf config.swarselmodules.server.ids (confLib.mkIds 979);
};
users = {
"${config.swarselsystems.mainUser}".openssh.authorizedKeys.keyFiles = lib.mkIf withHomeManager [
(self + /secrets/public/ssh/yubikey.pub)
(self + /secrets/public/ssh/magicant.pub)
# (lib.mkIf config.swarselsystems.isBastionTarget (self + /secrets/public/ssh/jump.pub))
];
root.openssh.authorizedKeys.keyFiles = [
(self + /secrets/public/ssh/yubikey.pub)
(self + /secrets/public/ssh/magicant.pub)
# (lib.mkIf config.swarselsystems.isBastionTarget (self + /secrets/public/ssh/jump.pub))
];
};
};
security.sudo.extraConfig = ''
Defaults env_keep+=SSH_AUTH_SOCK

View file

@ -25,6 +25,10 @@ in
# this user/group section is probably unneeded
users = {
persistentIds = {
prowlarr = confLib.mkIds 971;
readarr = confLib.mkIds 970;
};
groups = {
dockeruser = {
gid = 1155;

View file

@ -53,44 +53,104 @@ in
homeServiceAddress = lib.optionalString (config.swarselsystems.server.wireguard.interfaces ? wgHome) globals.networks."${config.swarselsystems.server.wireguard.interfaces.wgHome.serverNetConfigPrefix}-wgHome".hosts.${config.node.name}.ipv4;
};
mkIds = id: {
uid = id;
gid = id;
};
mkDeviceMac = id:
let
mod = n: d: n - (n / d) * d;
toHexByte = n:
let
hex = "0123456789abcdef";
hi = n / 16;
lo = mod n 16;
in
builtins.substring hi 1 hex
+ builtins.substring lo 1 hex;
max = 16777215; # 256^3 - 1
b1 = id / (256 * 256);
r1 = mod id (256 * 256);
b2 = r1 / 256;
b3 = mod r1 256;
in
if
(id <= max)
then
(builtins.concatStringsSep ":"
(map toHexByte [ b1 b2 b3 ]))
else
(throw "Device MAC ID too large (max is 16777215)");
mkMicrovm =
if config.swarselsystems.withMicroVMs then
(guestName: {
${guestName} = {
backend = "microvm";
autostart = true;
modules = [
(config.node.configDir + /guests/${guestName}/default.nix)
{
node.secretsDir = config.node.configDir + /secrets/${guestName};
node.configDir = config.node.configDir + /guests/${guestName};
networking.nftables.firewall = {
zones.untrusted.interfaces = lib.mkIf
(
lib.length config.guests.${guestName}.networking.links == 1
)
config.guests.${guestName}.networking.links;
(guestName:
{ enableStorage ? false
, withZfs ? false
, ...
}:
{
${guestName} = {
backend = "microvm";
autostart = true;
zfs = lib.mkIf withZfs {
# stateful config that should be backed up
"/state" = {
pool = "Vault";
dataset = "guests/${guestName}/state";
};
}
"${self}/modules/nixos/optional/microvm-guest.nix"
"${self}/modules/nixos/optional/systemd-networkd-base.nix"
];
microvm = {
system = config.node.arch;
baseMac = config.repo.secrets.local.networking.networks.lan.mac;
interfaces.vlan-services = { };
# data that should be backed up
"/storage" = lib.mkIf enableStorage {
pool = "Vault";
dataset = "guests/${guestName}/storage";
};
# other stuff that should only reside on disk, not backed up
"/persist" = {
pool = "Vault";
dataset = "guests/${guestName}/persist";
};
};
modules = [
(config.node.configDir + /guests/${guestName}/default.nix)
{
node.secretsDir = config.node.configDir + /secrets/${guestName};
node.configDir = config.node.configDir + /guests/${guestName};
networking.nftables.firewall = {
zones.untrusted.interfaces = lib.mkIf
(
lib.length config.guests.${guestName}.networking.links == 1
)
config.guests.${guestName}.networking.links;
};
}
"${self}/modules/nixos/optional/microvm-guest.nix"
"${self}/modules/nixos/optional/systemd-networkd-base.nix"
];
microvm = {
system = config.node.arch;
baseMac = config.repo.secrets.local.networking.networks.lan.mac;
interfaces.vlan-services = {
mac = lib.mkForce "02:${lib.substring 3 5 config.guests.${guestName}.microvm.baseMac}:${mkDeviceMac globals.networks.home-lan.vlans.services.hosts."${config.node.name}-${guestName}".id}";
};
};
extraSpecialArgs = {
inherit (inputs.self) nodes;
inherit (inputs.self.pkgs.${config.node.arch}) lib;
inherit inputs outputs minimal;
inherit (inputs) self;
withHomeManager = false;
microVMParent = config.node.name;
globals = inputs.self.globals.${config.node.arch};
};
};
extraSpecialArgs = {
inherit (inputs.self) nodes;
inherit (inputs.self.pkgs.${config.node.arch}) lib;
inherit inputs outputs minimal;
inherit (inputs) self;
withHomeManager = false;
microVMParent = config.node.name;
globals = inputs.self.globals.${config.node.arch};
};
};
}) else (_: { _ = { }; });
}) else
(_: {
_ = { };
});
genNginx =
{ serviceAddress

View file

@ -17,6 +17,7 @@
nftables = lib.mkDefault true;
server = {
general = lib.mkDefault true;
ids = lib.mkDefault true;
network = lib.mkDefault true;
diskEncryption = lib.mkDefault true;
packages = lib.mkDefault true;

View file

@ -18,6 +18,7 @@
nftables = lib.mkDefault true;
server = {
general = lib.mkDefault true;
ids = lib.mkDefault true;
packages = lib.mkDefault true;
ssh = lib.mkDefault true;
wireguard = lib.mkDefault true;

File diff suppressed because one or more lines are too long