{ flake-inputs, pkgs, lib, config, ... }: let crowdsecCfg = config.security.crowdsec; cfg = crowdsecCfg.remediationComponents.firewallBouncer; settingsFormat = pkgs.formats.yaml { }; crowdsec-firewall-bouncer = flake-inputs.self.packages.${pkgs.system}.crowdsec-firewall-bouncer; in { options.security.crowdsec.remediationComponents.firewallBouncer = { enable = lib.mkEnableOption "cs-firewall-bouncer"; settings = lib.mkOption { inherit (settingsFormat) type; default = { }; description = '' The bouncer configuration. Refer to <https://docs.crowdsec.net/u/bouncers/firewall/> for details on supported values. ''; }; }; config = lib.mkIf cfg.enable { security.crowdsec.remediationComponents.firewallBouncer.settings = { mode = lib.mkDefault "${if config.networking.nftables.enable then "nftables" else "iptables"}"; log_mode = "stdout"; iptables_chains = [ "nixos-fw" ]; # Don't let users easily override this; unfortunately we need to # set up this key through substitution at runtime. api_key = lib.mkForce "\${API_KEY}"; api_url = lib.mkDefault "http://${crowdsecCfg.settings.api.server.listen_uri}"; }; systemd = { packages = [ crowdsec-firewall-bouncer ]; services = { crowdsec-firewall-bouncer-setup = { description = "Crowdsec firewall bouncer config preparation"; script = '' if [ ! -e '${crowdsecCfg.stateDirectory}/firewall_bouncer_credentials.yaml' ]; then ${crowdsecCfg.package}/bin/cscli -oraw bouncers add "cs-firewall-bouncer-$(${pkgs.coreutils}/bin/date +%s)" > \ ${crowdsecCfg.stateDirectory}/firewall_bouncer_credentials.yaml fi # Stdout redirection is deliberately used to forcibly # overwrite the file if it exists API_KEY="$(<${crowdsecCfg.stateDirectory}/firewall_bouncer_credentials.yaml)" \ ${lib.getExe pkgs.envsubst} \ -i ${settingsFormat.generate "crowdsec-firewall-bouncer.yaml" cfg.settings} \ > /var/lib/crowdsec/config/crowdsec-firewall-bouncer.yaml ''; serviceConfig = { User = "crowdsec"; Group = "crowdsec"; Type = "oneshot"; RemainAfterExit = true; }; }; crowdsec-firewall-bouncer = { enable = true; after = [ "crowdsec-firewall-bouncer-setup.service" ]; bindsTo = [ "crowdsec-firewall-bouncer-setup.service" ]; requiredBy = [ "crowdsec.service" ]; path = lib.optionals (cfg.settings.mode == "ipset" || cfg.settings.mode == "iptables") [ pkgs.ipset ] ++ lib.optional (cfg.settings.mode == "iptables") pkgs.iptables ++ lib.optional (cfg.settings.mode == "nftables") pkgs.nftables; }; }; }; }; }