Compare commits

..

7 Commits

Author SHA1 Message Date
9404b4e71d
chore: enable fail2ban on bicboye
Signed-off-by: Chinmay D. Pai <chinmaydpai@gmail.com>
2024-10-05 21:01:54 +05:30
4cb83f945d
feat: add fail2ban setup for services
Signed-off-by: Chinmay D. Pai <chinmaydpai@gmail.com>
2024-10-05 21:00:53 +05:30
12cf2f3701
chore: harden ssh security
* KbdInteractiveAuthentication: disable keyboard interactive-auth, since
  we solely rely on the SSH key for connection.
* PermitEmptyPasswords: disable empty passwords for SSH connection, again,
  since we use SSH keys.
* Protocol: Explicitly set the SSH protocol to 2, even though it is the
  default value.
* MaxAuthTries: Set auth tries to 3. This is to allow up to 3 keys to try
  connection.
* ChallengeResponseAuthentication: We do not require a challenge-response
  setup.
* AllowTcpForwarding: Allows access to locally-running ports without having
  to expose them. Since all auth methods are disabled, we can enable this.

Signed-off-by: Chinmay D. Pai <chinmaydpai@gmail.com>
2024-10-05 20:53:47 +05:30
d4dc50237a
feat: create module for nginx and prepare for fail2ban setup
* create new module for nginx
* setup cloudflare real_ip_header forwarding for fail2ban setup
* add hsts, improve qualys score

Signed-off-by: Chinmay D. Pai <chinmaydpai@gmail.com>
2024-10-05 20:52:11 +05:30
48752f56b1
fix: use buildGoModule for netbird overlay
Signed-off-by: Chinmay D. Pai <chinmaydpai@gmail.com>
2024-10-05 20:51:41 +05:30
74310f5e34
feat: replace perl activation script with rust-based implementation
Signed-off-by: Chinmay D. Pai <chinmaydpai@gmail.com>
2024-10-05 20:51:00 +05:30
3efee8e004
chore: update flake.lock
Signed-off-by: Chinmay D. Pai <chinmaydpai@gmail.com>
2024-10-05 20:50:32 +05:30
15 changed files with 339 additions and 80 deletions

View File

@ -50,11 +50,11 @@
"nixpkgs": "nixpkgs"
},
"locked": {
"lastModified": 1727620986,
"narHash": "sha256-4RlJt1MJmZcuP3ROlrb2YvG8WfH0BM/nGqDgNT/DAwE=",
"lastModified": 1728001451,
"narHash": "sha256-Ost5YHSZZE4ZIKBcWsXC1c7g7n3kIqaNNjs5ula/lAI=",
"owner": "chaotic-cx",
"repo": "nyx",
"rev": "0eee1b2134e9aa3427081715ada883f3523a9608",
"rev": "25f420d9cf70929455ba14642b92ae715ae8d792",
"type": "github"
},
"original": {
@ -136,11 +136,11 @@
]
},
"locked": {
"lastModified": 1727531434,
"narHash": "sha256-b+GBgCWd2N6pkiTkRZaMFOPztPO4IVTaclYPrQl2uLk=",
"lastModified": 1727977578,
"narHash": "sha256-DBORKcmQ7ZjA4qE1MsnF1MmZSokOGrw4W9vTCioOv2U=",
"owner": "nix-community",
"repo": "disko",
"rev": "b709e1cc33fcde71c7db43850a55ebe6449d0959",
"rev": "574400001b3ffe555c7a21e0ff846230759be2ed",
"type": "github"
},
"original": {
@ -158,11 +158,11 @@
"rust-analyzer-src": "rust-analyzer-src"
},
"locked": {
"lastModified": 1727591515,
"narHash": "sha256-ar9oGR8kT3S5K3b0EJrcZp1LjfYQdzWl/bBLCp2o50Y=",
"lastModified": 1727937235,
"narHash": "sha256-Ih4RD65WZZDgtla9Uh8zm6gQJ1zgkXkiU4HKtEwQjvI=",
"owner": "nix-community",
"repo": "fenix",
"rev": "c31647aab5e8a16087da6283ef9b2e6a9aae6772",
"rev": "381781f96b880c2ced9019a9e2406b31ccea82b4",
"type": "github"
},
"original": {
@ -182,11 +182,11 @@
]
},
"locked": {
"lastModified": 1727613000,
"narHash": "sha256-U2hsKF5DbBx5gAzdA4IKTHI3Y0vdI4+Ra9tB21BF6Dw=",
"lastModified": 1728004272,
"narHash": "sha256-7UCbRuv1/G27sVwyTtkYO6Jjdnqx182SzofIvw7FmEs=",
"owner": "nix-community",
"repo": "flake-firefox-nightly",
"rev": "84c46a4c1d0b22992f2b464f658e094704e7edc7",
"rev": "6237aca65390a09acf0c51e3f31448db080066f4",
"type": "github"
},
"original": {
@ -466,11 +466,11 @@
]
},
"locked": {
"lastModified": 1727383923,
"narHash": "sha256-4/vacp3CwdGoPf8U4e/N8OsGYtO09WTcQK5FqYfJbKs=",
"lastModified": 1727817100,
"narHash": "sha256-dlyV9/eiWkm/Y/t2+k4CFZ29tBvCANmJogEYaHeAOTw=",
"owner": "nix-community",
"repo": "home-manager",
"rev": "ffe2d07e771580a005e675108212597e5b367d2d",
"rev": "437ec62009fa8ceb684eb447d455ffba25911cf9",
"type": "github"
},
"original": {
@ -486,11 +486,11 @@
]
},
"locked": {
"lastModified": 1727383923,
"narHash": "sha256-4/vacp3CwdGoPf8U4e/N8OsGYtO09WTcQK5FqYfJbKs=",
"lastModified": 1728026342,
"narHash": "sha256-3mGqKM1jSkc2DrJvR/HCTav0Chd1n8/s1eJ9Y5GzNVM=",
"owner": "nix-community",
"repo": "home-manager",
"rev": "ffe2d07e771580a005e675108212597e5b367d2d",
"rev": "30e04f3d477256de3eb6a7cff608e220087537d4",
"type": "github"
},
"original": {
@ -508,11 +508,11 @@
]
},
"locked": {
"lastModified": 1727453186,
"narHash": "sha256-nZRCfVEZ9osWXsCD0xCpU66M8JkabMTukBzPRrD/CTA=",
"lastModified": 1727865565,
"narHash": "sha256-SBcqfosxb0XlKdIz6QGXCnK4W/TEVHLDZHkRHZ8Me60=",
"owner": "Jovian-Experiments",
"repo": "Jovian-NixOS",
"rev": "3390ff2632d0d8a14c92473db60fa52bf881f979",
"rev": "703c0ac8432f3758987e0788248ddc1a8e0bf412",
"type": "github"
},
"original": {
@ -533,11 +533,11 @@
"rust-overlay": "rust-overlay"
},
"locked": {
"lastModified": 1725379389,
"narHash": "sha256-qS1H/5/20ewJIXmf8FN2A5KTOKKU9elWvCPwdBi1P/U=",
"lastModified": 1727792571,
"narHash": "sha256-KBzRQVE1j2vrSg8WfYJ+vEvFBC25+2VsFSK7VL2kc1M=",
"owner": "nix-community",
"repo": "lanzaboote",
"rev": "e7bd94e0b5ff3c1e686f2101004ebf4fcea9d871",
"rev": "e2365a1d8dccdcf4bca5111672e80df67d90957d",
"type": "github"
},
"original": {
@ -552,11 +552,11 @@
"nixpkgs-lib": "nixpkgs-lib"
},
"locked": {
"lastModified": 1727611937,
"narHash": "sha256-VTtaGRJGFWQzQd7u7iHUJiUUyMbJ3Jcv/ZsXlBXw0Ok=",
"lastModified": 1727710043,
"narHash": "sha256-NpTnTg8oOVvntlTi/t8BUe5msrMmkiZFiOW22fc7B+g=",
"owner": "nix-community",
"repo": "lib-aggregate",
"rev": "74c775886c8f89a0af4743a9144c5bbd04125725",
"rev": "d03a5f88a345d26ca13918071d42dcc960233183",
"type": "github"
},
"original": {
@ -664,11 +664,11 @@
},
"nixos-hardware": {
"locked": {
"lastModified": 1727613673,
"narHash": "sha256-qqIffTQfxMYo3MKQ9BoY2s2mdKZNnUiksdnxv81js9U=",
"lastModified": 1727665282,
"narHash": "sha256-oKtfbQB1MBypqIyzkC8QCQcVGOa1soaXaGgcBIoh14o=",
"owner": "nixos",
"repo": "nixos-hardware",
"rev": "f5c239fa9acb27f0a5326ba2949c00fada89ca9f",
"rev": "11c43c830e533dad1be527ecce379fcf994fbbb5",
"type": "github"
},
"original": {
@ -679,11 +679,11 @@
},
"nixpkgs": {
"locked": {
"lastModified": 1727348695,
"narHash": "sha256-J+PeFKSDV+pHL7ukkfpVzCOO7mBSrrpJ3svwBFABbhI=",
"lastModified": 1727802920,
"narHash": "sha256-HP89HZOT0ReIbI7IJZJQoJgxvB2Tn28V6XS3MNKnfLs=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "1925c603f17fc89f4c8f6bf6f631a802ad85d784",
"rev": "27e30d177e57d912d614c88c622dcfdb2e6e6515",
"type": "github"
},
"original": {
@ -726,11 +726,11 @@
},
"nixpkgs_2": {
"locked": {
"lastModified": 1727348695,
"narHash": "sha256-J+PeFKSDV+pHL7ukkfpVzCOO7mBSrrpJ3svwBFABbhI=",
"lastModified": 1727802920,
"narHash": "sha256-HP89HZOT0ReIbI7IJZJQoJgxvB2Tn28V6XS3MNKnfLs=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "1925c603f17fc89f4c8f6bf6f631a802ad85d784",
"rev": "27e30d177e57d912d614c88c622dcfdb2e6e6515",
"type": "github"
},
"original": {
@ -742,11 +742,11 @@
},
"nur": {
"locked": {
"lastModified": 1727622222,
"narHash": "sha256-Nh4gmTLDYZTKfXWBdL8EocTOyKKn+3nXqlUlg6GcnRE=",
"lastModified": 1728027550,
"narHash": "sha256-be13RazohHlmNJPH/zK9SGns8O0iLfwYzk77sZDB30o=",
"owner": "nix-community",
"repo": "nur",
"rev": "8ad93a63359caf2ed00d647264a59ca030691c71",
"rev": "c9c5e4e57b475f94fa0ba622611428b8fa3bd1cc",
"type": "github"
},
"original": {
@ -804,11 +804,11 @@
"rust-analyzer-src": {
"flake": false,
"locked": {
"lastModified": 1727465975,
"narHash": "sha256-jrr8r2CT9jsi6XDTTX+E39/CakTcQ9RYRp6rWGzLkk0=",
"lastModified": 1727778987,
"narHash": "sha256-OTI1eKQ3WIkj6q8PROpPY1vhaxYRdiS1btSfBowQPps=",
"owner": "rust-lang",
"repo": "rust-analyzer",
"rev": "546339a7be357b3e95fc4b79a8816dce540d477b",
"rev": "e1a76671af2fbc74c84c18ba18fcda5e653d7531",
"type": "github"
},
"original": {
@ -910,11 +910,11 @@
]
},
"locked": {
"lastModified": 1727611199,
"narHash": "sha256-oSZ0ChAOyg7FnXdvEePuBE/bW6krrtP64f+39l4iz0k=",
"lastModified": 1727991738,
"narHash": "sha256-bNy/zyUOp381G/KMiIfM5qD9fD+gMs2y3IdSlTKT4r8=",
"owner": "nix-community",
"repo": "srvos",
"rev": "6441ddae7ab6a0f66fb4f2c8f72e03466508fa61",
"rev": "c20ad69680e9f62fabc32c511c3964b8af55f955",
"type": "github"
},
"original": {

View File

@ -77,5 +77,10 @@
];
};
};
system.switch = {
enable = false;
enableNg = true;
};
};
}

View File

@ -1,5 +1,8 @@
{ config, lib, ... }:
{
config,
lib,
...
}: {
options.snowflake.core.sshd = {
enable = lib.mkEnableOption "Enable core sshd configuration";
};
@ -11,6 +14,12 @@
# Disable password auth and root login.
PasswordAuthentication = false;
PermitRootLogin = "no";
KbdInteractiveAuthentication = false;
PermitEmptyPasswords = false;
Protocol = 2;
MaxAuthTries = 3;
ChallengeResponseAuthentication = false;
AllowTcpForwarding = "yes";
};
openFirewall = true;
};

View File

@ -58,9 +58,34 @@
forceSSL = true;
locations."/" = {
proxyPass = "http://localhost:8096/";
extraConfig = ''
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
'';
};
};
};
};
services.fail2ban.jails.jellyfin = {
enabled = true;
filter = "jellyfin";
};
environment.etc = {
jellyfin = {
target = "fail2ban/filter.d/jellyfin.conf";
text = ''
[INCLUDES]
before = common.conf
[Definition]
failregex = ^.*Authentication request for .* has been denied \(IP: "<ADDR>"\)\.
ignoreregex =
journalmatch = _SYSTEMD_UNIT=jellyfin.service
'';
};
};
};
}

View File

@ -22,5 +22,20 @@
};
};
};
environment.etc = {
jellyseerr = {
target = "fail2ban/filter.d/jellyseerr.conf";
text = ''
[INCLUDES]
before = common.conf
[Definition]
failregex = ^.*\[warn\]\[API\]: Failed sign-in attempt using invalid Overseerr password {"ip":"<HOST>","email":
^.*\[warn\]\[Auth\]: Failed login attempt from user with incorrect Jellyfin credentials {"account":{"ip":"<HOST>","email":
ignoreregex =
journalmatch = _SYSTEMD_UNIT=jellyseerr.service
'';
};
};
};
}

View File

@ -0,0 +1,67 @@
{
config,
lib,
...
}: {
options.snowflake.services.fail2ban = {
enable = lib.mkEnableOption "Enable fail2ban service";
extraIgnoreIPs = lib.mkOption {
type = lib.types.listOf lib.types.str;
default = [];
description = "List of IPs to ignore for fail2ban alongside the default local subnets and loopback";
};
};
config = let
cfg = config.snowflake.services.fail2ban;
in
lib.mkIf cfg.enable {
services.fail2ban = {
enable = true;
maxretry = 3;
banaction-allports = "iptables-allports";
bantime-increment = {
enable = true;
maxtime = "168h";
factor = "4";
};
ignoreIPs =
[
"192.168.69.0/16"
"172.16.0.0/12"
"127.0.0.0/8"
]
++ cfg.extraIgnoreIPs;
jails = {
DEFAULT = {
blocktype = "DROP";
bantime = "6h";
findtime = "6h";
};
sshd = {
settings = {
enabled = true;
findtime = "1d";
maxretry = 4;
mode = "aggressive";
port = "ssh";
logpath = "%(sshd_log)s";
backend = "%(sshd_backend)s";
};
};
port-scan = {
filter = "port-scan";
action = "iptables-allports[name=port-scan]";
bantime = 86400;
maxretry = 2;
};
};
};
};
}

View File

@ -108,5 +108,22 @@
};
};
};
services.fail2ban.jails.gitea = {
enabled = true;
filter = "gitea";
};
environment.etc = {
gitea = {
target = "fail2ban/filter.d/gitea.conf";
text = ''
[Definition]
failregex = .*(Failed authentication attempt|invalid credentials|Attempted access of unknown user).* from <HOST>
ignoreregex =
journalmatch = _SYSTEMD_UNIT=gitea.service
'';
};
};
};
}

View File

@ -47,5 +47,25 @@
};
};
};
services.fail2ban.jails.immich = {
enabled = true;
filter = "immich";
};
environment.etc = {
immich = {
target = "fail2ban/filter.d/immich.conf";
text = ''
[INCLUDES]
before = common.conf
[Definition]
failregex = ^.*Username or password is incorrect\. Try again\. IP: <ADDR>\. Username:.*$
ignoreregex =
journalmatch = _SYSTEMD_UNIT=immich-server.service
'';
};
};
};
}

View File

@ -1,5 +1,8 @@
{ config, lib, ... }:
{
config,
lib,
...
}: {
options.snowflake.services.miniflux = {
enable = lib.mkEnableOption "Enable miniflux service";
@ -20,10 +23,9 @@
};
};
config =
let
cfg = config.snowflake.services.miniflux;
in
config = let
cfg = config.snowflake.services.miniflux;
in
lib.mkIf cfg.enable {
age.secrets.miniflux = {
inherit (cfg.adminTokenFile) file;
@ -49,7 +51,6 @@
proxyPass = "http://localhost:${toString cfg.listenPort}";
extraConfig = ''
proxy_redirect off;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
'';
@ -57,5 +58,22 @@
};
};
};
services.fail2ban.jails.miniflux = {
enabled = true;
filter = "miniflux";
};
environment.etc = {
miniflux = {
target = "fail2ban/filter.d/miniflux.conf";
text = ''
[Definition]
failregex = ^.*msg="[^"]*(Incorrect|Invalid) username or password[^"]*".*client_ip=<ADDR>
ignoreregex =
journalmatch = _SYSTEMD_UNIT=miniflux.service
'';
};
};
};
}

View File

@ -0,0 +1,69 @@
{
config,
lib,
...
}: {
options.snowflake.services.nginx = {
enable = lib.mkEnableOption "Enable nginx service";
acmeEmail = lib.mkOption {
type = lib.types.str;
description = "Email to use for ACME SSL certificates";
};
enableCloudflareRealIP = lib.mkEnableOption "Enable setting real_ip_header from Cloudflare IPs";
};
config = let
cfg = config.snowflake.services.nginx;
in
lib.mkIf cfg.enable {
security.acme.defaults.email = cfg.acmeEmail;
security.dhparams = {
enable = true;
params.nginx = {};
};
services.nginx = {
enable = true;
recommendedProxySettings = true;
recommendedOptimisation = true;
recommendedGzipSettings = true;
recommendedTlsSettings = true;
sslDhparam = config.security.dhparams.params.nginx.path;
# Disable default_server access and return HTTP 444.
appendHttpConfig =
''
# Strict Transport Security (HSTS): Yes
add_header Strict-Transport-Security "max-age=31536000; includeSubdomains; preload";
# Enable CSP
add_header Content-Security-Policy "script-src 'self'; object-src 'none'; base-uri 'none';" always;
# Minimize information leaked to other domains
add_header 'Referrer-Policy' 'origin-when-cross-origin';
# Disable embedding as a frame
add_header X-Frame-Options DENY;
# Prevent injection of code in other mime types (XSS Attacks)
add_header X-Content-Type-Options nosniff;
server {
listen 80 http2 default_server;
listen 443 ssl http2 default_server;
ssl_reject_handshake on;
return 444;
}
''
++ lib.optionalString cfg.enableCloudflareRealIP ''
${lib.concatMapStrings (ip: "set_real_ip_from ${ip};\n")
(lib.filter (line: line != "")
(lib.splitString "\n" ''
${lib.readFile (lib.fetchurl "https://www.cloudflare.com/ips-v4/")}
${lib.readFile (lib.fetchurl "https://www.cloudflare.com/ips-v6/")}
''))}
real_ip_header CF-Connecting-IP;
'';
};
};
}

View File

@ -48,7 +48,6 @@
proxy_redirect off;
proxy_buffering off;
proxy_request_buffering off;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
client_max_body_size 0;

View File

@ -73,5 +73,22 @@
echo ${path}/exported/
'';
};
services.fail2ban.jails.paperless = {
enabled = true;
filter = "paperless";
};
environment.etc = {
paperless-ngx = {
target = "fail2ban/filter.d/paperless.conf";
text = ''
[Definition]
failregex = Login failed for user `.*` from (?:IP|private IP) `<HOST>`\.$
ignoreregex =
journalmatch = _SYSTEMD_UNIT=paperless-web.service
'';
};
};
};
}

View File

@ -77,5 +77,20 @@
snowflake.services.backups.config.vaultwarden.paths = [
"/var/lib/bitwarden_rs"
];
environment.etc = {
vaultwarden = {
target = "fail2ban/filter.d/vaultwarden.conf";
text = ''
[INCLUDES]
before = common.conf
[Definition]
failregex = ^.*Username or password is incorrect\. Try again\. IP: <ADDR>\. Username:.*$
ignoreregex =
journalmatch = _SYSTEMD_UNIT=vaultwarden.service
'';
};
};
};
}

View File

@ -2,7 +2,7 @@ _: _self: super: let
version = "0.29.4";
in {
netbird = super.netbird.override {
buildGo123Module = args:
buildGoModule = args:
super.buildGo123Module (
args
// {

View File

@ -31,32 +31,6 @@
powerManagement.powertop.enable = true;
services.thermald.enable = true;
# TODO: move to module
security.acme.defaults.email = "chinmaydpai@gmail.com";
security.dhparams = {
enable = true;
params.nginx = {};
};
services.nginx = {
enable = true;
recommendedProxySettings = true;
recommendedOptimisation = true;
recommendedGzipSettings = true;
recommendedTlsSettings = true;
sslDhparam = config.security.dhparams.params.nginx.path;
# Disable default_server access and return HTTP 444.
appendHttpConfig = ''
server {
listen 80 http2 default_server;
listen 443 ssl http2 default_server;
ssl_reject_handshake on;
return 444;
}
'';
};
snowflake = {
stateVersion = "24.05";
@ -128,6 +102,8 @@
resticEnvironmentFile = userdata.secrets.services.backups.environment;
};
fail2ban.enable = true;
gitea = {
enable = true;
domain = "git.deku.moe";
@ -146,6 +122,12 @@
adminTokenFile = userdata.secrets.services.miniflux.password;
};
nginx = {
enable = true;
acmeEmail = "chinmaydpai@gmail.com";
enableCloudflareRealIP = true;
};
ntfy-sh = {
enable = true;
domain = "ntfy.deku.moe";
@ -175,6 +157,7 @@
package = pkgs.maych-in;
domain = "maych.in";
};
unifi-controller = {
enable = true;
unpoller = {