Skip to content

Commit 7763171

Browse files
committed
(WIP) Install fail2ban using system manager
1 parent fc77a26 commit 7763171

File tree

7 files changed

+153
-5
lines changed

7 files changed

+153
-5
lines changed

flake.lock

Lines changed: 4 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

flake.nix

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,9 @@
3333
inputs.nixpkgs.follows = "nixpkgs";
3434
};
3535
system-manager = {
36-
url = "github:numtide/system-manager";
36+
# FIXME: remove custom branch when this PR is merged:
37+
# https://github.com/numtide/system-manager/pull/266
38+
url = "github:numtide/system-manager/users";
3739
inputs.nixpkgs.follows = "nixpkgs";
3840
};
3941
};

nix/systemConfigs.nix

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
{ self, inputs, ... }:
22
let
33
mkModules = system: [
4+
self.systemModules.fail2ban
45
({
56
services.nginx.enable = true;
67
nixpkgs.hostPlatform = system;
8+
supabase.services.fail2ban.enable = true;
79
})
810
];
911

nix/systemModules/default.nix

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
{
55
imports = [ ./tests ];
66
flake = {
7-
systemModules = { };
7+
systemModules = {
8+
fail2ban = ./fail2ban.nix;
9+
};
810
};
911
}

nix/systemModules/dummy-sshd.nix

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
{ lib, ... }:
2+
{
3+
options = {
4+
services.openssh = lib.mkOption {
5+
type = lib.types.attrs;
6+
default = { };
7+
};
8+
};
9+
}
10+
11+
# FIXME: nix run -L .\#check-system-manager
12+
# error:
13+
# … while evaluating 'strict' to select 'drvPath' on it
14+
# at /builtin/derivation.nix:1:552:
15+
# … while calling the 'derivationStrict' builtin
16+
# at /builtin/derivation.nix:1:208:
17+
# (stack trace truncated; use '--show-trace' to show the full trace)
18+
19+
# error: infinite recursion encountered
20+
# at /nix/store/8cpqym71jjq5frp06ypjsj1iwi3l0fln-source/lib/modules.nix:1442:13:
21+
# 1441| _type = "if";
22+
# 1442| inherit condition content;
23+
# | ^
24+
# 1443| };

nix/systemModules/fail2ban.nix

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
{
2+
lib,
3+
nixosModulesPath,
4+
config,
5+
...
6+
}:
7+
let
8+
cfg = config.supabase.services.fail2ban;
9+
in
10+
{
11+
imports = [
12+
# We use a dummmy sshd module to workaround this error when importing "/services/networking/ssh/sshd.nix":
13+
# error: The option `users' in module `/nix/store/...-source/nix/modules'
14+
# would be a parent of the following options, but its type `attribute set' does not support nested options.
15+
# - option(s) with prefix `users.users' in module `/nix/store/...-source/nixos/modules/services/networking/ssh/sshd.nix'
16+
# FIXME: it would be better to rely on userborn in system-manager:
17+
# https://github.com/numtide/system-manager/pull/266
18+
./dummy-sshd.nix
19+
]
20+
++ map (path: nixosModulesPath + path) [
21+
# "/config/console.nix"
22+
# "/config/shells-environment.nix"
23+
# "/config/system-path.nix"
24+
# "/programs/i3lock.nix"
25+
# "/programs/ssh.nix"
26+
# "/security/pam.nix"
27+
# "/services/networking/firewall.nix"
28+
# "/services/networking/ssh/sshd.nix"
29+
"/services/security/fail2ban.nix"
30+
# "/system/boot/kernel.nix" # ERROR: The option `boot' in module `/nix/store/...-source/nix/modules/upstream/nixpkgs'
31+
# would be a parent of the following options, but its type `raw value' does not support nested options.
32+
];
33+
34+
options = {
35+
supabase.services.fail2ban = {
36+
enable = lib.mkEnableOption "Fail2Ban";
37+
};
38+
};
39+
40+
config = lib.mkIf cfg.enable {
41+
# TODO: (last bit form Ansible task)
42+
# - name: Configure journald
43+
# copy:
44+
# src: files/fail2ban_config/jail-ssh.conf
45+
# dest: /etc/fail2ban/jail.d/sshd.local
46+
# when: debpkg_mode or nixpkg_mode
47+
supabase.services.fail2ban = {
48+
enable = true; # FIXME: fail2ban was disabled in ansible/tasks/setup-fail2ban.yml
49+
bantime = "3600";
50+
jails = {
51+
postgresql = {
52+
settings = {
53+
enabled = true;
54+
port = "5432";
55+
protocol = "tcp";
56+
filter = "postgresql";
57+
logpath = "/var/log/postgresql/auth-failures.csv";
58+
maxretry = 3;
59+
ignoreip = "192.168.0.0/16 172.17.1.0/20";
60+
};
61+
};
62+
pgbouncer = {
63+
settings = {
64+
enabled = true;
65+
port = "6543";
66+
protocol = "tcp";
67+
filter = "pgbouncer";
68+
backend = "systemd[journalflags=1]";
69+
maxretry = 3;
70+
};
71+
};
72+
};
73+
# TODO: extraPackages = [ pkgs.nftables ];
74+
};
75+
76+
environment.etc = {
77+
"fail2ban/jail.local".text = ''
78+
[DEFAULT]
79+
banaction = nftables-multiport
80+
banaction_allports = nftables-allports
81+
'';
82+
83+
"fail2ban/filter.d/postgresql.conf".text = ''
84+
[Definition]
85+
failregex = ^.*,.*,.*,.*,"<HOST>:.*password authentication failed for user.*$
86+
ignoreregex = ^.*,.*,.*,.*,"127\.0\.0\.1.*password authentication failed for user.*$
87+
^.*,.*,.*,.*,"<HOST>:.*password authentication failed for user ""supabase_admin".*$
88+
^.*,.*,.*,.*,"<HOST>:.*password authentication failed for user ""supabase_auth_admin".*$
89+
^.*,.*,.*,.*,"<HOST>:.*password authentication failed for user ""supabase_storage_admin".*$
90+
^.*,.*,.*,.*,"<HOST>:.*password authentication failed for user ""authenticator".*$
91+
^.*,.*,.*,.*,"<HOST>:.*password authentication failed for user ""pgbouncer".*$
92+
'';
93+
94+
"fail2ban/filter.d/pgbouncer.conf".text = ''
95+
[Definition]
96+
failregex = ^.+@<HOST>:.+password authentication failed$
97+
journalmatch = _SYSTEMD_UNIT=pgbouncer.service
98+
'';
99+
};
100+
101+
systemd.services.fail2ban = {
102+
wantedBy = lib.mkForce [
103+
"system-manager.target"
104+
];
105+
# TODO:
106+
# after = [ "nftables.service" ];
107+
# wants = [ "nftables.service" ];
108+
};
109+
};
110+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# from time import sleep
2+
3+
4+
def test_fail2ban_service(host):
5+
# sleep(5000) # Handy for interactive debugging (with docker exec -it $CONTAINER_ID /bin/bash)
6+
assert host.service("fail2ban.service").is_valid
7+
assert host.service("fail2ban.service").is_running, "Fail2Ban service should be running but failed: {}".format(host.run("systemctl status fail2ban.service").stdout)

0 commit comments

Comments
 (0)