From 119b6819f3bdea11188a94c219dd8203d57df851 Mon Sep 17 00:00:00 2001 From: SebastianStork Date: Sun, 25 May 2025 18:33:04 +0200 Subject: [PATCH] Install and configure crowdsec on cirrus --- flake.lock | 60 +++++++++++++++- flake.nix | 5 ++ hosts/cirrus/default.nix | 9 +++ hosts/cirrus/secrets.yaml | 6 +- modules/system/crowdsec/default.nix | 74 ++++++++++++++++++++ modules/system/crowdsec/firewall-bouncer.nix | 32 +++++++++ 6 files changed, 181 insertions(+), 5 deletions(-) create mode 100644 modules/system/crowdsec/default.nix create mode 100644 modules/system/crowdsec/firewall-bouncer.nix diff --git a/flake.lock b/flake.lock index 24e802e..98acbfb 100644 --- a/flake.lock +++ b/flake.lock @@ -16,6 +16,27 @@ "type": "github" } }, + "crowdsec": { + "inputs": { + "flake-utils": "flake-utils", + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1742920128, + "narHash": "sha256-VPjnjtAksihLezhc+ZmnqGu18mHr4QVKa1kSZQ8rJL4=", + "ref": "refs/heads/main", + "rev": "40e937689d318ee85b1d9763189a65e6f0b4028d", + "revCount": 40, + "type": "git", + "url": "https://codeberg.org/kampka/nix-flake-crowdsec.git" + }, + "original": { + "type": "git", + "url": "https://codeberg.org/kampka/nix-flake-crowdsec.git" + } + }, "deploy-rs": { "inputs": { "flake-compat": "flake-compat", @@ -133,7 +154,24 @@ }, "flake-utils": { "inputs": { - "systems": "systems_2" + "systems": "systems" + }, + "locked": { + "lastModified": 1731533236, + "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", + "type": "github" + }, + "original": { + "id": "flake-utils", + "type": "indirect" + } + }, + "flake-utils_2": { + "inputs": { + "systems": "systems_3" }, "locked": { "lastModified": 1731533236, @@ -248,7 +286,7 @@ }, "nix-vscode-extensions": { "inputs": { - "flake-utils": "flake-utils", + "flake-utils": "flake-utils_2", "nixpkgs": [ "nixpkgs" ] @@ -373,6 +411,7 @@ "root": { "inputs": { "betterfox": "betterfox", + "crowdsec": "crowdsec", "deploy-rs": "deploy-rs", "disko": "disko", "firefox-addons": "firefox-addons", @@ -439,6 +478,21 @@ "type": "github" } }, + "systems_3": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, "treefmt-nix": { "inputs": { "nixpkgs": [ @@ -461,7 +515,7 @@ }, "utils": { "inputs": { - "systems": "systems" + "systems": "systems_2" }, "locked": { "lastModified": 1701680307, diff --git a/flake.nix b/flake.nix index 645983d..7710274 100644 --- a/flake.nix +++ b/flake.nix @@ -43,6 +43,11 @@ inputs.nixpkgs.follows = "nixpkgs"; }; + crowdsec = { + url = "git+https://codeberg.org/kampka/nix-flake-crowdsec.git"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + nix-vscode-extensions = { url = "github:nix-community/nix-vscode-extensions"; inputs.nixpkgs.follows = "nixpkgs"; diff --git a/hosts/cirrus/default.nix b/hosts/cirrus/default.nix index 0c41578..9a24169 100644 --- a/hosts/cirrus/default.nix +++ b/hosts/cirrus/default.nix @@ -17,6 +17,15 @@ subdomain = "docs"; backups.enable = true; }; + + crowdsec = { + enable = true; + firewallBouncer.enable = true; + sources = [ + "iptables" + "caddy" + ]; + }; }; services.caddy = { diff --git a/hosts/cirrus/secrets.yaml b/hosts/cirrus/secrets.yaml index 7f93232..128bdd6 100644 --- a/hosts/cirrus/secrets.yaml +++ b/hosts/cirrus/secrets.yaml @@ -7,6 +7,8 @@ restic: environment: ENC[AES256_GCM,data:oPgJ20N7eO0W+SnRPA/uaGDbYBpKX3jWixuVIG0+eBRRlaPWBFpJKA7CK9oVvwuqQUtGiRnoR2gqO42C22WRSiHXqe1zoarhvQMcXy8CTQd6Y+k5iMspSzMZynfkMapooK4=,iv:Ub1ONOcoEZ52E8W1qK93xpmYXMUiVszFbHoO/pUa/Mo=,tag:2yTJZmirhPIN01cB5F0Lsw==,type:str] password: ENC[AES256_GCM,data:gMd4G8o83r3sTZEH1kRkn05Mye96sHV2mdRWNbbS,iv:E2hBYbvpCMDul81lgUBNVr5Fm7x0u1f9cEkma9jKwYE=,tag:CeFrP3pO1VmGxcvj7b7pYA==,type:str] healthchecks-ping-key: ENC[AES256_GCM,data:HT6bEtZ4ii3na8VDRA59GHtRuaOV+w==,iv:ZZlnpDPoPUYgq/jHOfCqHMUmKpPUTpXmZp3GWxYAL3I=,tag:Lg97lItvoGzXqoz6Pwadfw==,type:str] +crowdsec: + enrollment-key: ENC[AES256_GCM,data:gcoLmZGUqH0brtvcXiZwXr7CSc9GfEWkvA==,iv:ZLz/3LXSYVXQtcyPZ62qOuslexdXh7jvX0MzoXjlRgM=,tag:V/SwXnNDQkiRQEu90ZTnTg==,type:str] sops: age: - recipient: age1mpq8m4p7dnxh5ze3fh7etd2k6sp85zdnmp9te3e9chcw4pw07pcq960zh5 @@ -27,7 +29,7 @@ sops: aHNody9YR2ZKTDNINmNvbGNHb0dCRVkKXcUQxU0Craqkze0l0mH75MKTnkf7a/ae XeqWVJRO1WpG+UhF3QB3yMq9uy0vlc3JnD3LsE0inWUSl0s6AgDZOg== -----END AGE ENCRYPTED FILE----- - lastmodified: "2025-05-24T12:58:09Z" - mac: ENC[AES256_GCM,data:V9bfym3Qm6Rf11UJY3VeWXfeA6wg/nFqroz9SMOSJHs6G8+QQ9NrOs6/5JP9mEZE9d6pR4Sqi/5WOFboi24dbAwx/0LVWDiWOMKzIDnOEB6FPYACefSBafrW7OAd5M9xacNTsLAHZMZytGpH0P+WW3EgQz2HuSJl/L42TunmyZo=,iv:KhoDvgOOOKu/RkDOE9DgGZdVB0TibAWjPLJBFNvPNuw=,tag:q3F8PdSDP1ORDpOiy8W+4Q==,type:str] + lastmodified: "2025-05-24T18:15:52Z" + mac: ENC[AES256_GCM,data:FIDuoiN8YmRCDHvl0SYN+HZKP+zgE1ZDEBSD8mePkLd6WfBtKQOS7bXr0GS5lfdui0H2e8tWDz1pMENlI69S3ZimAc8AYCJwyw0cyzRCjUNvicgJaxVP70faOhXTKXQnCu5Dxul/bYpzqvhhVUzhRfhoPxLLCSU7Hh05kqt3OJw=,iv:fWy6mXq0AQTjpWs1jyzqzwKA/hjd0Pvig9j1ZbdDDng=,tag:iHYPmJn6x6HJj3Q6LbEC/A==,type:str] unencrypted_suffix: _unencrypted version: 3.10.2 diff --git a/modules/system/crowdsec/default.nix b/modules/system/crowdsec/default.nix new file mode 100644 index 0000000..6197952 --- /dev/null +++ b/modules/system/crowdsec/default.nix @@ -0,0 +1,74 @@ +{ + config, + inputs, + pkgs, + lib, + ... +}: +let + cfg = config.myConfig.crowdsec; +in +{ + imports = [ inputs.crowdsec.nixosModules.crowdsec ]; + + options.myConfig.crowdsec = { + enable = lib.mkEnableOption ""; + apiPort = lib.mkOption { + type = lib.types.port; + default = 8080; + }; + sources = lib.mkOption { + type = lib.types.listOf ( + lib.types.enum [ + "iptables" + "caddy" + ] + ); + default = [ ]; + }; + }; + + config = lib.mkIf cfg.enable { + nixpkgs.overlays = [ inputs.crowdsec.overlays.default ]; + + sops.secrets."crowdsec/enrollment-key".owner = config.users.users.crowdsec.name; + + services.crowdsec = { + enable = true; + package = inputs.crowdsec.packages.${pkgs.system}.crowdsec; + enrollKeyFile = config.sops.secrets."crowdsec/enrollment-key".path; + settings = { + api.server.listen_uri = "127.0.0.1:${toString cfg.apiPort}"; + prometheus.enabled = false; + }; + + acquisitions = [ + (lib.mkIf (lib.elem "iptables" cfg.sources) { + source = "journalctl"; + journalctl_filter = [ "-k" ]; + labels.type = "syslog"; + }) + (lib.mkIf (lib.elem "caddy" cfg.sources) { + source = "journalctl"; + journalctl_filter = [ "_SYSTEMD_UNIT=caddy.service" ]; + labels.type = "syslog"; + }) + ]; + }; + + systemd.services.crowdsec.preStart = + let + collections = lib.flatten [ + "crowdsecurity/linux" + (lib.optional (lib.elem "iptables" cfg.sources) "crowdsecurity/iptables") + (lib.optional (lib.elem "caddy" cfg.sources) "crowdsecurity/caddy") + ]; + addCollection = collection: '' + if ! cscli collections list | grep -q "${collection}"; then + cscli collections install ${collection} + fi + ''; + in + collections |> lib.map addCollection |> lib.concatLines; + }; +} diff --git a/modules/system/crowdsec/firewall-bouncer.nix b/modules/system/crowdsec/firewall-bouncer.nix new file mode 100644 index 0000000..95f775a --- /dev/null +++ b/modules/system/crowdsec/firewall-bouncer.nix @@ -0,0 +1,32 @@ +{ + config, + inputs, + pkgs, + lib, + ... +}: +let + cfg = config.myConfig.crowdsec; +in +{ + imports = [ inputs.crowdsec.nixosModules.crowdsec-firewall-bouncer ]; + + options.myConfig.crowdsec.firewallBouncer.enable = lib.mkEnableOption ""; + + config = lib.mkIf cfg.firewallBouncer.enable { + services.crowdsec-firewall-bouncer = { + enable = true; + package = inputs.crowdsec.packages.${pkgs.system}.crowdsec-firewall-bouncer; + settings = { + api_key = "cs-firewall-bouncer"; + api_url = "http://127.0.0.1:${toString cfg.apiPort}"; + }; + }; + + systemd.services.crowdsec.preStart = '' + if ! cscli bouncers list | grep -q "firewall-bouncer"; then + cscli bouncers add "firewall-bouncer" --key "cs-firewall-bouncer" + fi + ''; + }; +}