diff --git a/README.md b/README.md index 7c1908e..2c46110 100644 --- a/README.md +++ b/README.md @@ -51,7 +51,6 @@ nix multi user, multi system, configuration with `sops` secret management, `home - syncthing folder passwords - nfs export should be backed by the same values for server and client - move fail2ban configs out of fail2ban.nix and into configs for their respective services -- move extra custom configuration for services out of host config and instead extend services ## New Features - offline access for nfs mounts (overlay with rsync might be a good option here? https://www.spinics.net/lists/linux-unionfs/msg07105.html note about nfs4 and overlay fs) - samba mounts diff --git a/configurations/nixos/defiant/configuration.nix b/configurations/nixos/defiant/configuration.nix index 5c3a7ed..78c215d 100644 --- a/configurations/nixos/defiant/configuration.nix +++ b/configurations/nixos/defiant/configuration.nix @@ -48,9 +48,6 @@ ]; }; }; - fail2ban = { - enable = true; - }; network_storage = { enable = true; directories = [ @@ -74,7 +71,7 @@ folder = "media"; user = "jellyfin"; group = "jellyfin_media"; - bind = config.host.jellyfin.media_directory; + bind = config.services.jellyfin.media_directory; } ]; nfs = { @@ -94,19 +91,6 @@ }; }; }; - jellyfin = { - enable = true; - subdomain = "media"; - extraSubdomains = ["jellyfin"]; - }; - forgejo = { - enable = true; - subdomain = "git"; - }; - searx = { - enable = true; - subdomain = "search"; - }; home-assistant = { enable = false; subdomain = "home"; @@ -114,10 +98,6 @@ adguardhome = { enable = false; }; - immich = { - enable = true; - subdomain = "photos"; - }; sync = { enable = true; folders = { @@ -187,6 +167,29 @@ "--accept-dns=false" ]; }; + + fail2ban.enable = true; + + jellyfin = { + enable = true; + subdomain = "media"; + extraSubdomains = ["jellyfin"]; + }; + + immich = { + enable = true; + subdomain = "photos"; + }; + + forgejo = { + enable = true; + subdomain = "git"; + }; + + searx = { + enable = true; + subdomain = "search"; + }; }; # disable computer sleeping diff --git a/modules/nixos-modules/server/fail2ban.nix b/modules/nixos-modules/server/fail2ban.nix index f410aeb..be83e6f 100644 --- a/modules/nixos-modules/server/fail2ban.nix +++ b/modules/nixos-modules/server/fail2ban.nix @@ -7,11 +7,7 @@ dataFolder = "/var/lib/fail2ban"; dataFile = "fail2ban.sqlite3"; in { - options.host.fail2ban = { - enable = lib.mkEnableOption "should fail 2 ban be enabled on this server"; - }; - - config = lib.mkIf config.host.fail2ban.enable (lib.mkMerge [ + config = lib.mkIf config.services.fail2ban.enable (lib.mkMerge [ { environment.etc = { "fail2ban/filter.d/nginx.local".text = lib.mkIf config.services.nginx.enable ( @@ -20,18 +16,6 @@ in { failregex = "limiting requests, excess:.* by zone.*client: " '') ); - "fail2ban/filter.d/jellyfin.local".text = lib.mkIf config.services.jellyfin.enable ( - pkgs.lib.mkDefault (pkgs.lib.mkAfter '' - [Definition] - failregex = "^.*Authentication request for .* has been denied \\\(IP: \"\"\\\)\\\." - '') - ); - "fail2ban/filter.d/forgejo.local".text = lib.mkIf config.services.forgejo.enable ( - pkgs.lib.mkDefault (pkgs.lib.mkAfter '' - [Definition] - failregex = ".*(Failed authentication attempt|invalid credentials|Attempted access of unknown user).* from " - '') - ); # "fail2ban/filter.d/hass.local".text = lib.mkIf config.services.home-assistant.enable ( # pkgs.lib.mkDefault (pkgs.lib.mkAfter '' # [INCLUDES] @@ -46,17 +30,9 @@ in { # datepattern = ^%%Y-%%m-%%d %%H:%%M:%%S # '') # ); - "fail2ban/filter.d/immich.local".text = lib.mkIf config.services.immich.enable ( - pkgs.lib.mkDefault (pkgs.lib.mkAfter '' - [Definition] - failregex = immich-server.*Failed login attempt for user.+from ip address\s? - journalmatch = CONTAINER_TAG=immich-server - '') - ); }; services.fail2ban = { - enable = true; maxretry = 5; ignoreIP = [ # Whitelist local networks @@ -85,26 +61,6 @@ in { bantime = 600; maxretry = 5; }; - jellyfin-iptables.settings = lib.mkIf config.services.jellyfin.enable { - enabled = true; - filter = "jellyfin"; - action = ''iptables-multiport[name=HTTP, port="http,https"]''; - logpath = "${config.services.jellyfin.dataDir}/log/*.log"; - backend = "auto"; - findtime = 600; - bantime = 600; - maxretry = 5; - }; - forgejo-iptables.settings = lib.mkIf config.services.forgejo.enable { - enabled = true; - filter = "forgejo"; - action = ''iptables-multiport[name=HTTP, port="http,https"]''; - logpath = "${config.services.forgejo.settings.log.ROOT_PATH}/*.log"; - backend = "auto"; - findtime = 600; - bantime = 600; - maxretry = 5; - }; # home-assistant-iptables.settings = lib.mkIf config.services.home-assistant.enable { # enabled = true; # filter = "hass"; @@ -115,11 +71,6 @@ in { # bantime = 600; # maxretry = 5; # }; - immich-iptables.settings = lib.mkIf config.services.immich.enable { - enabled = true; - filter = "immich"; - backend = "systemd"; - }; # TODO; figure out if there is any fail2ban things we can do on searx # searx-iptables.settings = lib.mkIf config.services.searx.enable {}; }; @@ -134,8 +85,6 @@ in { ]; environment.persistence."/persist/system/root" = { - enable = true; - hideMounts = true; directories = [ { directory = dataFolder; diff --git a/modules/nixos-modules/server/forgejo.nix b/modules/nixos-modules/server/forgejo.nix index f0c1974..40a5303 100644 --- a/modules/nixos-modules/server/forgejo.nix +++ b/modules/nixos-modules/server/forgejo.nix @@ -1,6 +1,7 @@ { lib, config, + pkgs, ... }: let forgejoPort = 8081; @@ -8,8 +9,7 @@ db_user = "forgejo"; sshPort = 22222; in { - options.host.forgejo = { - enable = lib.mkEnableOption "should forgejo be enabled on this computer"; + options.services.forgejo = { subdomain = lib.mkOption { type = lib.types.str; description = "subdomain of base domain that forgejo will be hosted at"; @@ -17,10 +17,10 @@ in { }; }; - config = lib.mkIf config.host.forgejo.enable (lib.mkMerge [ + config = lib.mkIf config.services.forgejo.enable (lib.mkMerge [ { host = { - reverse_proxy.subdomains.${config.host.forgejo.subdomain} = { + reverse_proxy.subdomains.${config.services.forgejo.subdomain} = { target = "http://localhost:${toString forgejoPort}"; }; postgres = { @@ -33,32 +33,29 @@ in { }; }; - services = { - forgejo = { - enable = true; - database = { - type = "postgres"; - socket = "/run/postgresql"; + services.forgejo = { + database = { + type = "postgres"; + socket = "/run/postgresql"; + }; + lfs.enable = true; + settings = { + server = { + DOMAIN = "${config.services.forgejo.subdomain}.${config.host.reverse_proxy.hostname}"; + HTTP_PORT = forgejoPort; + START_SSH_SERVER = true; + SSH_LISTEN_PORT = sshPort; + SSH_PORT = 22; + BUILTIN_SSH_SERVER_USER = config.users.users.git.name; + ROOT_URL = "https://git.jan-leila.com"; }; - lfs.enable = true; - settings = { - server = { - DOMAIN = "${config.host.forgejo.subdomain}.${config.host.reverse_proxy.hostname}"; - HTTP_PORT = forgejoPort; - START_SSH_SERVER = true; - SSH_LISTEN_PORT = sshPort; - SSH_PORT = 22; - BUILTIN_SSH_SERVER_USER = config.users.users.git.name; - ROOT_URL = "https://git.jan-leila.com"; - }; - service = { - DISABLE_REGISTRATION = true; - }; - database = { - DB_TYPE = "postgres"; - NAME = db_user; - USER = db_user; - }; + service = { + DISABLE_REGISTRATION = true; + }; + database = { + DB_TYPE = "postgres"; + NAME = db_user; + USER = db_user; }; }; }; @@ -67,6 +64,31 @@ in { config.services.forgejo.settings.server.SSH_LISTEN_PORT ]; } + (lib.mkIf config.services.fail2ban.enable { + environment.etc = { + "fail2ban/filter.d/forgejo.local".text = lib.mkIf config.services.forgejo.enable ( + pkgs.lib.mkDefault (pkgs.lib.mkAfter '' + [Definition] + failregex = ".*(Failed authentication attempt|invalid credentials|Attempted access of unknown user).* from " + '') + ); + }; + + services.fail2ban = { + jails = { + forgejo-iptables.settings = lib.mkIf config.services.forgejo.enable { + enabled = true; + filter = "forgejo"; + action = ''iptables-multiport[name=HTTP, port="http,https"]''; + logpath = "${config.services.forgejo.settings.log.ROOT_PATH}/*.log"; + backend = "auto"; + findtime = 600; + bantime = 600; + maxretry = 5; + }; + }; + }; + }) (lib.mkIf config.host.impermanence.enable { assertions = [ { diff --git a/modules/nixos-modules/server/immich.nix b/modules/nixos-modules/server/immich.nix index 2756e5c..e7088a9 100644 --- a/modules/nixos-modules/server/immich.nix +++ b/modules/nixos-modules/server/immich.nix @@ -1,12 +1,12 @@ { lib, config, + pkgs, ... }: let mediaLocation = "/var/lib/immich"; in { - options.host.immich = { - enable = lib.mkEnableOption "should immich be enabled on this computer"; + options.services.immich = { subdomain = lib.mkOption { type = lib.types.str; description = "subdomain of base domain that immich will be hosted at"; @@ -14,10 +14,10 @@ in { }; }; - config = lib.mkIf config.host.immich.enable (lib.mkMerge [ + config = lib.mkIf config.services.immich.enable (lib.mkMerge [ { host = { - reverse_proxy.subdomains.${config.host.immich.subdomain} = { + reverse_proxy.subdomains.${config.services.immich.subdomain} = { target = "http://localhost:${toString config.services.immich.port}"; websockets.enable = true; @@ -44,12 +44,6 @@ in { }; }; - services.immich = { - enable = true; - port = 2283; - # redis.enable = false; - }; - networking.firewall.interfaces.${config.services.tailscale.interfaceName} = { allowedUDPPorts = [ config.services.immich.port @@ -59,6 +53,27 @@ in { ]; }; } + (lib.mkIf config.services.fail2ban.enable { + environment.etc = { + "fail2ban/filter.d/immich.local".text = lib.mkIf config.services.immich.enable ( + pkgs.lib.mkDefault (pkgs.lib.mkAfter '' + [Definition] + failregex = immich-server.*Failed login attempt for user.+from ip address\s? + journalmatch = CONTAINER_TAG=immich-server + '') + ); + }; + + services.fail2ban = { + jails = { + immich-iptables.settings = lib.mkIf config.services.immich.enable { + enabled = true; + filter = "immich"; + backend = "systemd"; + }; + }; + }; + }) (lib.mkIf config.host.impermanence.enable { assertions = [ { @@ -67,8 +82,6 @@ in { } ]; environment.persistence."/persist/system/root" = { - enable = true; - hideMounts = true; directories = [ { directory = mediaLocation; diff --git a/modules/nixos-modules/server/jellyfin.nix b/modules/nixos-modules/server/jellyfin.nix index 77d5744..010ea1a 100644 --- a/modules/nixos-modules/server/jellyfin.nix +++ b/modules/nixos-modules/server/jellyfin.nix @@ -8,8 +8,7 @@ jellyfin_data_directory = "/var/lib/jellyfin"; jellyfin_cache_directory = "/var/cache/jellyfin"; in { - options.host.jellyfin = { - enable = lib.mkEnableOption "should jellyfin be enabled on this computer"; + options.services.jellyfin = { subdomain = lib.mkOption { type = lib.types.str; description = "subdomain of base domain that jellyfin will be hosted at"; @@ -27,16 +26,14 @@ in { }; }; - config = lib.mkIf config.host.jellyfin.enable ( + config = lib.mkIf config.services.jellyfin.enable ( lib.mkMerge [ { - services.jellyfin.enable = true; - host.reverse_proxy.subdomains.jellyfin = { target = "http://localhost:${toString jellyfinPort}"; - subdomain = config.host.jellyfin.subdomain; - extraSubdomains = config.host.jellyfin.extraSubdomains; + subdomain = config.services.jellyfin.subdomain; + extraSubdomains = config.services.jellyfin.extraSubdomains; forwardHeaders.enable = true; @@ -53,6 +50,31 @@ in { pkgs.jellyfin-ffmpeg ]; } + (lib.mkIf config.services.fail2ban.enable { + environment.etc = { + "fail2ban/filter.d/jellyfin.local".text = lib.mkIf config.services.jellyfin.enable ( + pkgs.lib.mkDefault (pkgs.lib.mkAfter '' + [Definition] + failregex = "^.*Authentication request for .* has been denied \\\(IP: \"\"\\\)\\\." + '') + ); + }; + + services.fail2ban = { + jails = { + jellyfin-iptables.settings = lib.mkIf config.services.jellyfin.enable { + enabled = true; + filter = "jellyfin"; + action = ''iptables-multiport[name=HTTP, port="http,https"]''; + logpath = "${config.services.jellyfin.dataDir}/log/*.log"; + backend = "auto"; + findtime = 600; + bantime = 600; + maxretry = 5; + }; + }; + }; + }) (lib.mkIf config.host.impermanence.enable { fileSystems."/persist/system/jellyfin".neededForBoot = true; @@ -82,8 +104,6 @@ in { environment.persistence = { "/persist/system/root" = { - enable = true; - hideMounts = true; directories = [ { directory = jellyfin_data_directory; @@ -103,7 +123,7 @@ in { hideMounts = true; directories = [ { - directory = config.host.jellyfin.media_directory; + directory = config.services.jellyfin.media_directory; user = "jellyfin"; group = "jellyfin_media"; mode = "1770"; diff --git a/modules/nixos-modules/server/searx.nix b/modules/nixos-modules/server/searx.nix index c578b41..d357308 100644 --- a/modules/nixos-modules/server/searx.nix +++ b/modules/nixos-modules/server/searx.nix @@ -4,8 +4,7 @@ inputs, ... }: { - options.host.searx = { - enable = lib.mkEnableOption "should searx be enabled on this computer"; + options.services.searx = { subdomain = lib.mkOption { type = lib.types.str; description = "subdomain of base domain that searx will be hosted at"; @@ -13,7 +12,7 @@ }; }; - config = lib.mkIf config.host.searx.enable { + config = lib.mkIf config.services.searx.enable { sops.secrets = { "services/searx" = { sopsFile = "${inputs.secrets}/defiant-services.yaml"; @@ -21,56 +20,53 @@ }; host = { reverse_proxy.subdomains.searx = { - subdomain = config.host.searx.subdomain; + subdomain = config.services.searx.subdomain; target = "http://localhost:${toString config.services.searx.settings.server.port}"; }; }; - services = { - searx = { - enable = true; - environmentFile = config.sops.secrets."services/searx".path; + services.searx = { + environmentFile = config.sops.secrets."services/searx".path; - # Rate limiting - limiterSettings = { - real_ip = { - x_for = 1; - ipv4_prefix = 32; - ipv6_prefix = 56; - }; - - botdetection = { - ip_limit = { - filter_link_local = true; - link_token = true; - }; - }; + # Rate limiting + limiterSettings = { + real_ip = { + x_for = 1; + ipv4_prefix = 32; + ipv6_prefix = 56; }; - settings = { - server = { - port = 8083; - secret_key = "@SEARXNG_SECRET@"; + botdetection = { + ip_limit = { + filter_link_local = true; + link_token = true; }; - - # Search engine settings - search = { - safe_search = 2; - autocomplete_min = 2; - autocomplete = "duckduckgo"; - }; - - # Enabled plugins - enabled_plugins = [ - "Basic Calculator" - "Hash plugin" - "Tor check plugin" - "Open Access DOI rewrite" - "Hostnames plugin" - "Unit converter plugin" - "Tracker URL remover" - ]; }; }; + + settings = { + server = { + port = 8083; + secret_key = "@SEARXNG_SECRET@"; + }; + + # Search engine settings + search = { + safe_search = 2; + autocomplete_min = 2; + autocomplete = "duckduckgo"; + }; + + # Enabled plugins + enabled_plugins = [ + "Basic Calculator" + "Hash plugin" + "Tor check plugin" + "Open Access DOI rewrite" + "Hostnames plugin" + "Unit converter plugin" + "Tracker URL remover" + ]; + }; }; }; }