Remove CrowdSec — replaced by fail2ban
https://claude.ai/code/session_01PwAXuaoJx7qD5FhVLsn7Sn
This commit is contained in:
parent
4935d42e48
commit
6b432f3bc2
3 changed files with 0 additions and 212 deletions
|
|
@ -29,7 +29,6 @@
|
|||
./services/jellyfin.nix
|
||||
./services/bazarr.nix
|
||||
./services/cloudflare-ddns.nix
|
||||
./services/crowdsec.nix
|
||||
./services/fail2ban.nix
|
||||
];
|
||||
|
||||
|
|
|
|||
|
|
@ -1,99 +0,0 @@
|
|||
# CrowdSec Setup
|
||||
|
||||
CrowdSec runs as a Docker (OCI) container on FredOS-Mediaserver. The firewall
|
||||
bouncer runs as a native NixOS service and talks to the containerised LAPI over
|
||||
localhost:8080.
|
||||
|
||||
## Why Docker?
|
||||
|
||||
The `crowdsec` package in nixpkgs unstable is incomplete — the NixOS module
|
||||
does not reliably set up the LAPI and hub collections. The official CrowdSec
|
||||
Docker image is well maintained and always up to date.
|
||||
|
||||
## Architecture
|
||||
|
||||
```
|
||||
[journald / log sources]
|
||||
|
|
||||
[CrowdSec LAPI] ← Docker container (port 8080 on localhost)
|
||||
|
|
||||
[firewall-bouncer] ← Native NixOS service (nftables/iptables)
|
||||
```
|
||||
|
||||
## Initial Setup (first deploy)
|
||||
|
||||
After running `nixos-rebuild switch`, the CrowdSec container will be running
|
||||
but the firewall bouncer has no API key yet.
|
||||
|
||||
**1. Generate a bouncer API key:**
|
||||
|
||||
```bash
|
||||
docker exec crowdsec cscli bouncers add firewall-bouncer
|
||||
```
|
||||
|
||||
Copy the key printed to stdout — it is only shown once.
|
||||
|
||||
**2. Store the key on the machine:**
|
||||
|
||||
```bash
|
||||
sudo mkdir -p /var/lib/secrets
|
||||
echo -n "PASTE_KEY_HERE" | sudo tee /var/lib/secrets/crowdsec-bouncer-key
|
||||
sudo chmod 600 /var/lib/secrets/crowdsec-bouncer-key
|
||||
sudo chown root:root /var/lib/secrets/crowdsec-bouncer-key
|
||||
```
|
||||
|
||||
**3. Restart the bouncer:**
|
||||
|
||||
```bash
|
||||
sudo systemctl restart crowdsec-firewall-bouncer
|
||||
sudo systemctl status crowdsec-firewall-bouncer
|
||||
```
|
||||
|
||||
The key file at `/var/lib/secrets/crowdsec-bouncer-key` is not managed by Nix
|
||||
and must be created manually on each new machine. It should never be committed
|
||||
to git.
|
||||
|
||||
## Re-registering the Bouncer
|
||||
|
||||
If the bouncer loses its registration (e.g. after a container wipe):
|
||||
|
||||
```bash
|
||||
# Remove the old registration
|
||||
docker exec crowdsec cscli bouncers delete firewall-bouncer
|
||||
|
||||
# Re-add and capture the new key
|
||||
docker exec crowdsec cscli bouncers add firewall-bouncer
|
||||
|
||||
# Update the key file and restart
|
||||
echo -n "NEW_KEY_HERE" | sudo tee /var/lib/secrets/crowdsec-bouncer-key
|
||||
sudo systemctl restart crowdsec-firewall-bouncer
|
||||
```
|
||||
|
||||
## Useful Commands
|
||||
|
||||
```bash
|
||||
# View active bouncers
|
||||
docker exec crowdsec cscli bouncers list
|
||||
|
||||
# View active decisions (bans)
|
||||
docker exec crowdsec cscli decisions list
|
||||
|
||||
# View alerts
|
||||
docker exec crowdsec cscli alerts list
|
||||
|
||||
# Install/update a collection
|
||||
docker exec crowdsec cscli collections install crowdsecurity/sshd
|
||||
|
||||
# View installed collections
|
||||
docker exec crowdsec cscli collections list
|
||||
```
|
||||
|
||||
## Persistent Data
|
||||
|
||||
The container mounts the following host paths:
|
||||
|
||||
| Host path | Container path | Purpose |
|
||||
|----------------------------------|-------------------------|--------------------------|
|
||||
| `/var/lib/crowdsec/data` | `/var/lib/crowdsec/data`| GeoIP DB, decisions, etc |
|
||||
| `/var/lib/crowdsec/config` | `/etc/crowdsec` | Config, hub, bouncers |
|
||||
| `/var/log/crowdsec` | `/var/log/crowdsec` | CrowdSec logs |
|
||||
|
|
@ -1,112 +0,0 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
let
|
||||
# Acquisition config is written to the host config dir before the container
|
||||
# starts, so it persists across container restarts and reflects Nix config.
|
||||
acquisYaml = ''
|
||||
- source: journalctl
|
||||
journalctl_filter:
|
||||
- "-u"
|
||||
- "sshd"
|
||||
labels:
|
||||
type: syslog
|
||||
'';
|
||||
|
||||
# Generates /run/crowdsec-bouncer/config.yaml at service start, injecting the
|
||||
# API key from /var/lib/secrets/crowdsec-bouncer-key without it ever entering
|
||||
# the Nix store. See services/crowdsec.md for key setup instructions.
|
||||
bouncerPreStart = pkgs.writeShellScript "crowdsec-bouncer-prestart" ''
|
||||
set -euo pipefail
|
||||
|
||||
KEY_FILE=/var/lib/secrets/crowdsec-bouncer-key
|
||||
if [ ! -f "$KEY_FILE" ]; then
|
||||
echo "ERROR: $KEY_FILE not found. See services/crowdsec.md for setup steps." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
API_KEY=$(cat "$KEY_FILE")
|
||||
|
||||
cat > /run/crowdsec-bouncer/config.yaml << EOF
|
||||
mode: nftables
|
||||
pid_dir: /run/crowdsec-bouncer/
|
||||
update_frequency: 10s
|
||||
log_mode: stdout
|
||||
log_level: info
|
||||
api_url: http://127.0.0.1:8080
|
||||
api_key: $API_KEY
|
||||
disable_ipv6: false
|
||||
deny_action: DROP
|
||||
deny_log: false
|
||||
nftables:
|
||||
ipv4:
|
||||
enabled: true
|
||||
set-only: false
|
||||
table: crowdsec
|
||||
chain: crowdsec-chain
|
||||
ipv6:
|
||||
enabled: true
|
||||
set-only: false
|
||||
table: crowdsec6
|
||||
chain: crowdsec-chain6
|
||||
EOF
|
||||
'';
|
||||
in
|
||||
{
|
||||
config = lib.mkIf (config.networking.hostName == "FredOS-Mediaserver") {
|
||||
|
||||
virtualisation.docker.enable = true;
|
||||
virtualisation.oci-containers.backend = "docker";
|
||||
|
||||
# CrowdSec LAPI runs as a Docker container.
|
||||
# Collections are installed on first boot via the COLLECTIONS env var.
|
||||
# Journals are mounted read-only so CrowdSec can run journalctl inside the container.
|
||||
virtualisation.oci-containers.containers.crowdsec = {
|
||||
image = "crowdsecurity/crowdsec:latest";
|
||||
ports = [ "127.0.0.1:8080:8080" ];
|
||||
volumes = [
|
||||
"/var/lib/crowdsec/data:/var/lib/crowdsec/data"
|
||||
"/var/lib/crowdsec/config:/etc/crowdsec"
|
||||
"/var/log/journal:/var/log/journal:ro"
|
||||
"/run/log/journal:/run/log/journal:ro"
|
||||
"/etc/machine-id:/etc/machine-id:ro"
|
||||
];
|
||||
environment = {
|
||||
COLLECTIONS = "crowdsecurity/linux crowdsecurity/sshd";
|
||||
};
|
||||
};
|
||||
|
||||
# Write acquisition config into the host config dir before the container starts.
|
||||
systemd.services.docker-crowdsec.preStart = ''
|
||||
mkdir -p /var/lib/crowdsec/config/acquis.d
|
||||
cat > /var/lib/crowdsec/config/acquis.d/nixos.yaml << 'ACQUIS'
|
||||
${acquisYaml}
|
||||
ACQUIS
|
||||
'';
|
||||
|
||||
systemd.tmpfiles.rules = [
|
||||
"d /var/lib/crowdsec/data 0750 root root -"
|
||||
"d /var/lib/crowdsec/config 0750 root root -"
|
||||
"d /var/lib/secrets 0700 root root -"
|
||||
];
|
||||
|
||||
# Firewall bouncer runs natively. API key is injected at start time from
|
||||
# /var/lib/secrets/crowdsec-bouncer-key — see services/crowdsec.md.
|
||||
systemd.services.crowdsec-firewall-bouncer = {
|
||||
description = "CrowdSec nftables firewall bouncer";
|
||||
after = [ "network.target" "docker-crowdsec.service" ];
|
||||
wants = [ "docker-crowdsec.service" ];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
|
||||
serviceConfig = {
|
||||
Type = "simple";
|
||||
RuntimeDirectory = "crowdsec-bouncer";
|
||||
ExecStartPre = bouncerPreStart;
|
||||
ExecStart = "${pkgs.crowdsec-firewall-bouncer}/bin/cs-firewall-bouncer -c /run/crowdsec-bouncer/config.yaml";
|
||||
Restart = "on-failure";
|
||||
RestartSec = "5s";
|
||||
AmbientCapabilities = [ "CAP_NET_ADMIN" "CAP_NET_RAW" ];
|
||||
CapabilityBoundingSet = [ "CAP_NET_ADMIN" "CAP_NET_RAW" ];
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue