diff --git a/services/crowdsec.nix b/services/crowdsec.nix index 9f3f6d8..4223c5c 100644 --- a/services/crowdsec.nix +++ b/services/crowdsec.nix @@ -1,4 +1,4 @@ -{ pkgs, config, ... }: { +{ pkgs, config, lib, ... }: { services = { crowdsec = { enable = true; @@ -46,6 +46,40 @@ users.users."${config.services.crowdsec.user}".extraGroups = [ "adm" ]; - systemd.tmpfiles.rules = let cfg = config.services.crowdsec; - in [ "d /var/lib/crowdsec 0755 ${cfg.user} ${cfg.group}" ]; + # Workaround generated by Claude Opus 4.8 - seems reasonable + # --- Workarounds for the immature nixpkgs 26.05 crowdsec modules --- + # Tracking issue: https://github.com/NixOS/nixpkgs/issues/469519 + + # (1) The raw `cscli` used by the firewall-bouncer register service (and by + # manual invocations) reads /etc/crowdsec/config.yaml, which the module + # otherwise never writes. Materialize the same generated config there. + environment.etc."crowdsec/config.yaml".source = + (pkgs.formats.yaml { }).generate "crowdsec.yaml" + config.services.crowdsec.settings.general; + + # (2) The modules mix `DynamicUser = true` with a `StateDirectory` named + # "crowdsec" shared across several units. Dynamic UIDs differ per unit, and + # the firewall-bouncer register service declares `StateDirectory=crowdsec` + # while the agent does not, so systemd relocates /var/lib/crowdsec into the + # root-only /var/lib/private, after which the agent can no longer reach it + # ("mkdir /var/lib/crowdsec: Permission denied"), the LAPI never starts, and + # the bouncer gets connection refused. Pin every unit that touches the state + # to the static `crowdsec` user and give the agent + hub updater a matching + # StateDirectory, so /var/lib/crowdsec is a normal directory owned by + # `crowdsec`. systemd migrates the existing data out of /var/lib/private. + systemd.services.crowdsec.serviceConfig = { + DynamicUser = lib.mkForce false; + StateDirectory = "crowdsec"; + }; + systemd.services.crowdsec-update-hub.serviceConfig = { + DynamicUser = lib.mkForce false; + StateDirectory = "crowdsec"; + }; + systemd.services.crowdsec-firewall-bouncer-register.serviceConfig.DynamicUser = + lib.mkForce false; + + # (3) The bouncer `requires` the register service but is not ordered after it, + # so it can try to load the API-key credential before it has been written. + systemd.services.crowdsec-firewall-bouncer.after = + [ "crowdsec-firewall-bouncer-register.service" ]; } diff --git a/systems/linux/hardware-configuration/bosephus-external-drives.nix b/systems/linux/hardware-configuration/bosephus-external-drives.nix index d870389..a68646a 100644 --- a/systems/linux/hardware-configuration/bosephus-external-drives.nix +++ b/systems/linux/hardware-configuration/bosephus-external-drives.nix @@ -1,37 +1,22 @@ -{ pkgs, ... }: - -{ +{ ... }: +let + disks = [ + { + uuid = "f719549e-fe01-4367-a37b-eeb4bdda4138"; + mountPoint = "/media/my-book-duo"; + } + { + uuid = "1915dcd7-7daa-40bf-82be-e808e313becd"; + mountPoint = "/media/g-drive"; + } + ]; +in map (x: { fileSystems = { - "/media/my-book-duo" = { - device = "/dev/disk/by-uuid/f719549e-fe01-4367-a37b-eeb4bdda4138"; - fsType = "btrfs"; - options = [ "defaults" "compress=zstd" ]; - }; - - "/media/g-drive" = { - device = "/dev/disk/by-uuid/1915dcd7-7daa-40bf-82be-e808e313becd"; + ${x.mountPoint} = { + device = "/dev/disk/by-uuid/${x.uuid}"; fsType = "btrfs"; options = [ "defaults" "compress=zstd" ]; }; }; - - systemd.services."fix-mount-permissions" = { - wantedBy = [ "local-fs.target" ]; - after = [ "local-fs.target" ]; - path = [ pkgs.coreutils ]; - serviceConfig = { - Type = "oneshot"; - ExecStart = '' - ${pkgs.coreutils}/bin/chown root:mixstudios /media/my-book-duo - ${pkgs.coreutils}/bin/chown root:mixstudios /media/g-drive - - ${pkgs.coreutils}/bin/chmod 2775 /media/my-book-duo - ${pkgs.coreutils}/bin/chmod 2775 /media/g-drive - - ${pkgs.coreutils}/bin/chgrp -R mixstudios /media/my-book-duo - ${pkgs.coreutils}/bin/chgrp -P mixstudios /media/g-drive - ''; - }; - }; - -} + systemd.tmpfiles.rules = [ "z ${x.mountPoint} 2775 root mixstudios -" ]; +}) disks