Skip to content

Commit d31c0d3

Browse files
committed
(WIP) Install fail2ban using system manager
1 parent 8fac60d commit d31c0d3

File tree

5 files changed

+121
-1
lines changed

5 files changed

+121
-1
lines changed

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: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{ lib, ... }:
2+
{
3+
options = {
4+
services.openssh = lib.mkOption {
5+
type = lib.types.attrs;
6+
default = { };
7+
};
8+
};
9+
}

nix/systemModules/fail2ban.nix

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
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+
"/services/security/fail2ban.nix"
22+
];
23+
24+
options = {
25+
supabase.services.fail2ban = {
26+
enable = lib.mkEnableOption "Fail2Ban";
27+
};
28+
};
29+
30+
config = lib.mkIf cfg.enable {
31+
# TODO: (last bit form Ansible task)
32+
# - name: Configure journald
33+
# copy:
34+
# src: files/fail2ban_config/jail-ssh.conf
35+
# dest: /etc/fail2ban/jail.d/sshd.local
36+
# when: debpkg_mode or nixpkg_mode
37+
supabase.services.fail2ban = {
38+
enable = true; # FIXME: fail2ban was disabled in ansible/tasks/setup-fail2ban.yml
39+
bantime = "3600";
40+
jails = {
41+
postgresql = {
42+
settings = {
43+
enabled = true;
44+
port = "5432";
45+
protocol = "tcp";
46+
filter = "postgresql";
47+
logpath = "/var/log/postgresql/auth-failures.csv";
48+
maxretry = 3;
49+
ignoreip = "192.168.0.0/16 172.17.1.0/20";
50+
};
51+
};
52+
pgbouncer = {
53+
settings = {
54+
enabled = true;
55+
port = "6543";
56+
protocol = "tcp";
57+
filter = "pgbouncer";
58+
backend = "systemd[journalflags=1]";
59+
maxretry = 3;
60+
};
61+
};
62+
};
63+
# TODO: extraPackages = [ pkgs.nftables ];
64+
};
65+
66+
environment.etc = {
67+
"fail2ban/jail.local".text = ''
68+
[DEFAULT]
69+
banaction = nftables-multiport
70+
banaction_allports = nftables-allports
71+
'';
72+
73+
"fail2ban/filter.d/postgresql.conf".text = ''
74+
[Definition]
75+
failregex = ^.*,.*,.*,.*,"<HOST>:.*password authentication failed for user.*$
76+
ignoreregex = ^.*,.*,.*,.*,"127\.0\.0\.1.*password authentication failed for user.*$
77+
^.*,.*,.*,.*,"<HOST>:.*password authentication failed for user ""supabase_admin".*$
78+
^.*,.*,.*,.*,"<HOST>:.*password authentication failed for user ""supabase_auth_admin".*$
79+
^.*,.*,.*,.*,"<HOST>:.*password authentication failed for user ""supabase_storage_admin".*$
80+
^.*,.*,.*,.*,"<HOST>:.*password authentication failed for user ""authenticator".*$
81+
^.*,.*,.*,.*,"<HOST>:.*password authentication failed for user ""pgbouncer".*$
82+
'';
83+
84+
"fail2ban/filter.d/pgbouncer.conf".text = ''
85+
[Definition]
86+
failregex = ^.+@<HOST>:.+password authentication failed$
87+
journalmatch = _SYSTEMD_UNIT=pgbouncer.service
88+
'';
89+
};
90+
91+
systemd.services.fail2ban = {
92+
wantedBy = lib.mkForce [
93+
"system-manager.target"
94+
];
95+
# TODO:
96+
# after = [ "nftables.service" ];
97+
# wants = [ "nftables.service" ];
98+
};
99+
};
100+
}
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)