This commit is contained in:
Lucy Hochkamp 2025-07-29 03:02:25 +02:00
parent 9ca7a8d8f6
commit 414e830efa
No known key found for this signature in database
14 changed files with 376 additions and 62 deletions

53
flake.lock generated
View file

@ -208,6 +208,21 @@
"type": "github" "type": "github"
} }
}, },
"impermanence": {
"locked": {
"lastModified": 1737831083,
"narHash": "sha256-LJggUHbpyeDvNagTUrdhe/pRVp4pnS6wVKALS782gRI=",
"owner": "nix-community",
"repo": "impermanence",
"rev": "4b3e914cdf97a5b536a889e939fb2fd2b043a170",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "impermanence",
"type": "github"
}
},
"kmonad": { "kmonad": {
"inputs": { "inputs": {
"nixpkgs": [ "nixpkgs": [
@ -450,26 +465,12 @@
"type": "github" "type": "github"
} }
}, },
"quadlet": {
"locked": {
"lastModified": 1752618481,
"narHash": "sha256-8132xTqalZxJZbznHDNoia1UqjNdL/hIQD4IXnI9F58=",
"owner": "SEIAROTg",
"repo": "quadlet-nix",
"rev": "0c1d64f360c1a3c3534f6b592ca3ed5d46cf8429",
"type": "github"
},
"original": {
"owner": "SEIAROTg",
"repo": "quadlet-nix",
"type": "github"
}
},
"root": { "root": {
"inputs": { "inputs": {
"csharp-language-server": "csharp-language-server", "csharp-language-server": "csharp-language-server",
"helix": "helix", "helix": "helix",
"home-manager": "home-manager", "home-manager": "home-manager",
"impermanence": "impermanence",
"kmonad": "kmonad", "kmonad": "kmonad",
"lanzaboote": "lanzaboote", "lanzaboote": "lanzaboote",
"lix-module": "lix-module", "lix-module": "lix-module",
@ -479,7 +480,7 @@
"nixos-hardware": "nixos-hardware", "nixos-hardware": "nixos-hardware",
"nixpkgs": "nixpkgs_2", "nixpkgs": "nixpkgs_2",
"nixpkgs-master": "nixpkgs-master", "nixpkgs-master": "nixpkgs-master",
"quadlet": "quadlet", "sops-nix": "sops-nix",
"zen-browser": "zen-browser" "zen-browser": "zen-browser"
} }
}, },
@ -546,6 +547,26 @@
"type": "github" "type": "github"
} }
}, },
"sops-nix": {
"inputs": {
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1752544651,
"narHash": "sha256-GllP7cmQu7zLZTs9z0J2gIL42IZHa9CBEXwBY9szT0U=",
"owner": "Mic92",
"repo": "sops-nix",
"rev": "2c8def626f54708a9c38a5861866660395bb3461",
"type": "github"
},
"original": {
"owner": "Mic92",
"repo": "sops-nix",
"type": "github"
}
},
"systems": { "systems": {
"locked": { "locked": {
"lastModified": 1681028828, "lastModified": 1681028828,

View file

@ -10,7 +10,9 @@
home-manager.url = "github:nix-community/home-manager"; home-manager.url = "github:nix-community/home-manager";
home-manager.inputs.nixpkgs.follows = "nixpkgs"; home-manager.inputs.nixpkgs.follows = "nixpkgs";
nixos-hardware.url = "github:NixOS/nixos-hardware/master"; nixos-hardware.url = "github:NixOS/nixos-hardware/master";
quadlet.url = "github:SEIAROTg/quadlet-nix"; sops-nix.url = "github:Mic92/sops-nix";
sops-nix.inputs.nixpkgs.follows = "nixpkgs";
impermanence.url = "github:nix-community/impermanence";
# software # software
lanzaboote = { lanzaboote = {
@ -58,26 +60,30 @@
}; };
} }
); );
overlays = [ self.overlays.default overlays = [
# lix-module.overlays.default self.overlays.default
(final: prev: let # lix-module.overlays.default
versionSuffix = "-horribly-patched"; (
lix = final.applyPatches { final: prev:
name = "lix${versionSuffix}"; let
src = inputs.lix-module.inputs.lix; versionSuffix = "-horribly-patched";
patches = [ lix = final.applyPatches {
(final.fetchpatch { name = "lix${versionSuffix}";
name = "lix-2.93-structuredAttrs.patch"; src = inputs.lix-module.inputs.lix;
url = "https://gerrit.lix.systems/changes/lix~3668/revisions/2/patch?download&raw"; patches = [
hash = "sha256-JQlAU0texMa7DMrqk447SXJUEu1k4IP9z8mjCHyskVc="; (final.fetchpatch {
}) name = "lix-2.93-structuredAttrs.patch";
]; url = "https://gerrit.lix.systems/changes/lix~3668/revisions/2/patch?download&raw";
}; hash = "sha256-JQlAU0texMa7DMrqk447SXJUEu1k4IP9z8mjCHyskVc=";
patchedOverlay = import (inputs.lix-module + "/overlay.nix") { })
inherit versionSuffix lix; ];
}; };
in patchedOverlay = import (inputs.lix-module + "/overlay.nix") {
patchedOverlay final prev) inherit versionSuffix lix;
};
in
patchedOverlay final prev
)
]; ];
genPkgs = genPkgs =
system: system:
@ -99,7 +105,7 @@
inputs.kmonad.nixosModules.default inputs.kmonad.nixosModules.default
inputs.home-manager.nixosModules.default inputs.home-manager.nixosModules.default
inputs.lanzaboote.nixosModules.lanzaboote inputs.lanzaboote.nixosModules.lanzaboote
inputs.quadlet.nixosModules.quadlet inputs.sops-nix.nixosModules.sops
] ]
++ (import ./modules/module-list.nix) ++ (import ./modules/module-list.nix)
); );
@ -111,7 +117,10 @@
packages = [ packages = [
pkgs.nixfmt-rfc-style pkgs.nixfmt-rfc-style
pkgs.nil pkgs.nil
pkgs.sops
pkgs.ssh-to-age
]; ];
SOPS_AGE_KEY_CMD = "";
}; };
}; };
} }

View file

@ -2,4 +2,7 @@
modules = [ ./configuration.nix ]; modules = [ ./configuration.nix ];
system = "x86_64-linux"; system = "x86_64-linux";
hostName = "ds9"; hostName = "ds9";
publicHostname = "ds9.hailsatan.eu";
wgPubKey = "";
wgServer = true;
} }

View file

@ -11,11 +11,12 @@ rec {
lib.mapAttrs (n: v: (import "${parentDir}/${n}")) ( lib.mapAttrs (n: v: (import "${parentDir}/${n}")) (
lib.filterAttrs (n: v: v == "directory") (builtins.readDir parentDir) lib.filterAttrs (n: v: v == "directory") (builtins.readDir parentDir)
); );
loadInstances = dir: extraModules: lib.mapAttrs (n: v: loadInstance extraModules v) (getDirs dir); loadInstances =
dir: extraModules: lib.mapAttrs (n: v: loadInstance extraModules v (getDirs dir)) (getDirs dir);
loadInstance = loadInstance =
extraModules: instance: extraModules: instance: instanceConfigs:
nixpkgs.lib.nixosSystem { nixpkgs.lib.nixosSystem {
specialArgs = { inherit inputs; }; specialArgs = { inherit inputs instanceConfigs; instanceConfig = instance; };
modules = modules =
instance.modules instance.modules
++ extraModules ++ extraModules

View file

@ -6,34 +6,71 @@
}: }:
let let
cfg = config.xyno.desktop.wpaperd; cfg = config.xyno.desktop.wpaperd;
wpaperdConf = pkgs.writeText "wpaperd.conf" '' # wpaperdConf = pkgs.writeText "wpaperd.conf" ''
[default] # [default]
path = "/home/${config.xyno.system.user.name}/Pictures/backgrounds" # path = "/home/${config.xyno.system.user.name}/Pictures/backgrounds"
duration = "10m" # duration = "10m"
sorting = "random" # sorting = "random"
mode = "center" # mode = "center"
''; # '';
in in
{ {
options.xyno.desktop.wpaperd.enable = lib.mkEnableOption "enable wpaperd notification daemon"; options.xyno.desktop.wpaperd.enable = lib.mkEnableOption "enable wpaperd wallpaper daemon";
options.xyno.desktop.wpaperd.wantedBy = lib.mkOption { options.xyno.desktop.wpaperd.wantedBy = lib.mkOption {
type = lib.types.str; type = lib.types.str;
default = "niri.service"; default = "niri.service";
}; };
options.xyno.desktop.wpaperd.package = lib.mkOption { options.xyno.desktop.wpaperd.package = lib.mkOption {
type = lib.types.package; type = lib.types.package;
default = pkgs.wpaperd; default = pkgs.swww;
}; };
config = lib.mkIf cfg.enable { config = lib.mkIf cfg.enable {
environment.systemPackages = [ cfg.package ]; environment.systemPackages = [ cfg.package ];
systemd.user.services.wpaperd = { systemd.user.services.swww-daemon = {
unitConfig.PartOf = "graphical-session.target"; unitConfig.PartOf = "graphical-session.target";
unitConfig.After = "graphical-session.target"; unitConfig.After = "graphical-session.target";
unitConfig.Requisite = "graphical-session.target"; unitConfig.Requisite = "graphical-session.target";
serviceConfig.Restart = "on-failure"; serviceConfig.Restart = "on-failure";
wantedBy = [ cfg.wantedBy ]; wantedBy = [ cfg.wantedBy ];
script = "exec ${cfg.package}/bin/wpaperd -c ${wpaperdConf}"; script = ''
restartTriggers = [wpaperdConf]; exec ${cfg.package}/bin/swww-daemon'';
};
systemd.user.services.swww-randomize = {
unitConfig.PartOf = "graphical-session.target";
unitConfig.After = "graphical-session.target";
unitConfig.Requisite = "graphical-session.target";
serviceConfig.Restart = "on-failure";
wantedBy = [ "swww-daemon.service" ];
script = ''
export DEFAULT_INTERVAL=300 # In seconds
export DIR=''$HOME/Pictures/backgrounds
# See swww-img(1)
RESIZE_TYPE="crop"
export SWWW_TRANSITION_FPS="120"
export SWWW_TRANSITION="fade"
export SWWW_TRANSITION_DURATION="1"
# export SWWW_TRANSITION_STEP="90"
while true; do
find "''$DIR" -type f \
| while read -r img; do
echo "''$(</dev/urandom tr -dc a-zA-Z0-9 | head -c 8):''$img"
done \
| sort -n | cut -d':' -f2- \
| while read -r img; do
for d in ''$(${cfg.package}/bin/swww query | grep -Po "^[^:]+"); do # see ${cfg.package}/bin/swww-query(1)
# Get next random image for this display, or re-shuffle images
# and pick again if no more unused images are remaining
[ -z "''$img" ] && if read -r img; then true; else break 2; fi
${cfg.package}/bin/swww img --resize "''$RESIZE_TYPE" --outputs "''$d" "''$img"
unset -v img # Each image should only be used once per loop
done
sleep "''${DEFAULT_INTERVAL}"
done
done
'';
# restartTriggers = [wpaperdConf];
}; };
}; };
} }

View file

@ -57,6 +57,7 @@ in
# # ipv6AcceptRAConfig.UsePREF64 = true; # # ipv6AcceptRAConfig.UsePREF64 = true;
# }; # };
networking.wireless.iwd.enable = cfg.enableWifi; networking.wireless.iwd.enable = cfg.enableWifi;
xyno.impermanence.extraDirectories = lib.mkOptionals cfg.enableWifi [ "/var/lib/iwd" ];
# services.clatd.enable = true; # services.clatd.enable = true;
}; };
} }

View file

@ -73,11 +73,12 @@ in
}; };
services.pcscd.enable = true; services.pcscd.enable = true;
programs.gnupg.agent = { programs.gnupg.agent = {
enable = true; enable = true;
# pinentrywlavor = "curses"; # pinentrywlavor = "curses";
# enableSSHSupport = true; # enableSSHSupport = true;
}; };
services.udev.packages = [ pkgs.yubikey-personalization ]; # needed for yubikeys to be used as smartcards
environment.systemPackages = with pkgs; [ environment.systemPackages = with pkgs; [
jq jq

View file

@ -13,5 +13,15 @@ in
boot.initrd.systemd.enable = true; boot.initrd.systemd.enable = true;
hardware.keyboard.zsa.enable = true; hardware.keyboard.zsa.enable = true;
programs.nh.enable = true; programs.nh.enable = true;
security.polkit.extraConfig = ''
polkit.addRule(function(action, subject) { // make run0 keep pw for some time (tm)
if (
subject.isInGroup("wheel")
&& action.id == "org.freedesktop.systemd1.manage-units"
) {
return polkit.Result.AUTH_ADMIN_KEEP;
}
});
'';
}; };
} }

View file

@ -14,6 +14,10 @@ in
default = "alacritty"; default = "alacritty";
}; };
config = lib.mkIf cfg.enable { config = lib.mkIf cfg.enable {
services.udev.packages = [
pkgs.openocd # fix permission errors with connecting things (especially esp32-c3)
pkgs.ptouch-print
];
xyno.desktop.niri.enable = true; xyno.desktop.niri.enable = true;
xyno.desktop.audio.enable = lib.mkDefault true; xyno.desktop.audio.enable = lib.mkDefault true;
security.soteria.enable = true; security.soteria.enable = true;
@ -116,6 +120,7 @@ in
source-sans source-sans
b612 b612
lxqt.lxqt-config lxqt.lxqt-config
ptouch-print
]; ];

View file

@ -0,0 +1,22 @@
{
pkgs,
lib,
config,
...
}:
let
cfg = config.xyno.services.monitoring;
in
{
options.xyno.services.monitoring.enable =
lib.mkEnableOption "enables monitoring (prometheus exporters and stuff)";
options.xyno.services.monitoring.ip = lib.mkOption {
type = lib.types.str;
default = "::1";
description = "the ip prometheus exporters should listen to";
};
config = lib.mkIf cfg.enable {
};
}

View file

@ -0,0 +1,39 @@
{
pkgs,
lib,
config,
...
}:
let
cfg = config.xyno.services.postgres;
in
{
options.xyno.services.postgres.enable = lib.mkEnableOption "enables postgres";
config = lib.mkIf cfg.enable {
services.postgresql = {
enable = true;
package = pkgs.postgresql_17_jit;
identMap = ''
# ArbitraryMapName systemUser DBUser
superuser_map root postgres
superuser_map postgres postgres
# Let other names login as themselves
superuser_map /^(.*)$ \1
'';
};
services.prometheus.exporters.postgres = lib.mkIf config.xyno.services.monitoring.enable {
enable = true;
listenAddress = config.xyno.services.monitoring.ip;
port = 9187;
};
xyno.impermanence.extraDirectories = [ "/var/lib/postgresql" ];
services.borgmatic.settings.postgresql_databases = [
{
name = "all"; # gets run as root anyways so can log in
}
];
};
}

View file

@ -0,0 +1,88 @@
{
pkgs,
lib,
config,
instanceConfigs,
instanceConfig,
...
}:
let
cfg = config.xyno.services.wireguard;
ula = "fd68:b6a4:36e4";
ulaPrefix = "${ula}:1337"; # /64 for normal vpn
monitoringUlaPrefix = "${ula}:2337"; # /64 for monitoring
# uses a hash digest as the host identifier
genUlaForHost =
prefix: hostName:
let
hostHash = builtins.hashString "sha512" hostName;
localParts = map (n: builtins.substring (n * 4) 4 hostHash) hostHash;
localPart = lib.concatStringsSep ":" localParts;
in
"${prefix}:${localPart}";
# peers list for networkd
wgPeers = map (
c:
(
(lib.optionals (lib.hasAttr c "publicHostname") {
# if peer is publicly on the internet
AllowedIPs =
(lib.optionals (c.wgServer) [
"${ulaPrefix}::/48" # all traffic in the ula shall be sent to the server
])
++ (lib.optionals (!c.wgServer) [
"${genUlaForHost ulaPrefix c.hostName}/128" # if a host is reachable but shouldn't play server, send only to the hosts ip
]);
Endpoint = "${c.publicHostname}:51820";
PersistentKeepalive = 25;
PublicKey = c.wgPubKey;
})
++ (lib.optionals (!(lib.hasAttr c "publicHostname") && instanceConfig.wgServer && (lib.hasAttr c "wgPubKey")) {
# if this is the server and the peer isn't reachable on the internet
AllowedIPs = [
"${genUlaForHost ulaPrefix c.hostName}/128"
"${genUlaForHost monitoringUlaPrefix c.hostName}/128"
];
PublicKey = c.wgPubKey;
# TODO: preshared keys
})
)
) instanceConfigs;
in
{
options.xyno.services.wireguard.enable = lib.mkEnableOption "enables wireguard";
options.xyno.services.wireguard.hostsDomain = lib.mkOpion { type = lib.types.str; default = "wg.hailsatan.eu"; };
config = lib.mkIf cfg.enable {
xyno.services.monitoring.ip = genUlaForHost monitoringUlaPrefix config.networking.hostName;
networking.hosts = lib.mapAttrs' (
n: v: {
name = "${v.hostName}.${cfg.hostsDomain}";
value = [ (genUlaForHost ulaPrefix v.hostName) ];
}
);
networking.firewall.allowedUDPPorts = lib.mkIf instanceConfig.wgServer [ 51820 ];
systemd.network.netdevs."wg0" = {
wireguardConfig = {
ListenPort = lib.mkIf instanceConfig.wgServer 51820;
PrivateKeyFile = config.sops.secrets.wg_privkey.path; # TODO
};
wireguardPeers = wgPeers;
};
systemd.network.networks."wg0" = {
matchConfig.Name = "wg0";
networkConfig = {
Description = "xyno wireguard";
};
address = [
"${(genUlaForHost ulaPrefix config.networking.hostName)}/128"
"${(genUlaForHost monitoringUlaPrefix config.networking.hostName)}/128"
];
};
sops.secrets.wg_privkey = {
reloadUnits = [ "systemd-networkd.service" ];
};
};
}

View file

@ -2,21 +2,97 @@
pkgs, pkgs,
lib, lib,
config, config,
inputs,
... ...
}: }:
let let
cfg = config.xyno.impermanence; cfg = config.xyno.impermanence;
genImpermanenceCfg = cfg: {
hideMounts = true;
directories = [
"/var/log"
"/var/lib/systemd/coredump"
]
++ cfg.extraDirectories;
files = [
"/etc/machine-id"
]
++ cfg.extraFiles;
users.${config.xyno.system.user.name} = {
directories = [
"Downloads"
"Music"
"Pictures"
"Documents"
"Videos"
"docs"
"proj"
"git"
{
directory = ".gnupg";
mode = "0700";
}
{
directory = ".ssh";
mode = "0700";
}
{
directory = ".local/share/keyrings";
mode = "0700";
}
".local/share/direnv"
]
++ cfg.user.extraDirectories;
files = cfg.user.extraFiles;
};
};
in in
{ {
options.xyno.impermanence = { options.xyno.impermanence = {
enable = lib.mkEnableOption "erase all your darlings (they hate you anyways)"; enable = lib.mkEnableOption "erase all your darlings (they hate you anyways)";
extraFiles = lib.mkOption { type = lib.types.listOf lib.types.str; }; extraFiles = lib.mkOption { type = lib.types.listOf lib.types.str; };
extraDirectories = lib.mkOption { type = lib.types.listOf lib.types.str; }; extraDirectories = lib.mkOption { type = lib.types.listOf lib.types.str; };
user = {
extraFiles = lib.mkOption { type = lib.types.listOf lib.types.str; };
extraDirectories = lib.mkOption { type = lib.types.listOf lib.types.str; };
};
# have a seperate impermanence tree for "cache" files that can just be deleted if wanted
cache = {
extraFiles = lib.mkOption { type = lib.types.listOf lib.types.str; };
extraDirectories = lib.mkOption { type = lib.types.listOf lib.types.str; };
user = {
extraFiles = lib.mkOption { type = lib.types.listOf lib.types.str; };
extraDirectories = lib.mkOption { type = lib.types.listOf lib.types.str; };
};
};
}; };
config = lib.mkIf cfg.enable { config = lib.mkIf cfg.enable {
imports = [ ]; # TODO imports = [
inputs.impermanence.nixosModules.impermanence
impermanence.extraFiles = cfg.extraFiles; ];
impermanence.extraDirectories = cfg.extraDirectories; xyno.impermanence.cache.extraDirectories = [ "/var/cache" ];
xyno.impermanence.cache.user.extraDirectories = [ ".cache" ];
environment.persistence."/persistent" = genImpermanenceCfg cfg;
environment.persistence."/persistent/cache" = genImpermanenceCfg cfg.cache;
system.activationScripts."createPersistentStorageDirs".deps = [
"var-lib-private-permissions"
"users"
"groups"
];
# https://github.com/nix-community/impermanence/issues/254#issuecomment-2683859091
system.activationScripts = {
"var-lib-private-permissions" = {
deps = [ "specialfs" ];
text = ''
mkdir -p /persistent/var/lib/private
chmod 0700 /persistent/var/lib/private
'';
};
};
}; };
} }

View file

@ -30,6 +30,7 @@ in
"tape" "tape"
"uucp" "uucp"
"wireshark" "wireshark"
"lock"
]; ];