{
  config,
  lib,
  ...
}:
with lib; let
  cfg = config.machine;
  active = name: (elem name cfg.services);
in
  mkIf (elem "fail2ban" cfg.services) {
    services.fail2ban = {
      enable = true;
      jails = {
        DEFAULT = ''
          bantime  = 3600
          blocktype = DROP
          logpath  = /var/log/auth.log
        '';

        ssh = ''
          enabled = ${boolToString (active "openssh")}
          filter = sshd
          maxretry = 4
          action = iptables[name=SSH, port=ssh, protocol=tcp]
        '';
        sshd-ddos = ''
          enabled  = ${boolToString (active "openssh")}
          filter = sshd-ddos
          maxretry = 4
          action   = iptables[name=ssh, port=ssh, protocol=tcp]
        '';

        postfix = ''
          enabled  = ${boolToString (active "mailserver")}
          filter   = postfix
          maxretry = 3
          action   = iptables[name=postfix, port=smtp, protocol=tcp]
        '';
        postfix-sasl = ''
          enabled  = ${boolToString (active "mailserver")}
          filter   = postfix-sasl
          port     = postfix,imap3,imaps,pop3,pop3s
          maxretry = 3
          action   = iptables[name=postfix, port=smtp, protocol=tcp]
        '';
        postfix-ddos = ''
          enabled  = ${boolToString (active "mailserver")}
          filter   = postfix-ddos
          maxretry = 3
          action   = iptables[name=postfix, port=submission, protocol=tcp]
          bantime  = 7200
        '';

        nginx-req-limit = ''
          enabled = ${boolToString (active "nginx")}
          filter = nginx-req-limit
          maxretry = 10
          action = iptables-multiport[name=ReqLimit, port="http,https", protocol=tcp]
          findtime = 600
          bantime = 7200
        '';
      };
    };

    environment.etc."fail2ban/filter.d/sshd-ddos.conf" = {
      enable = active "openssh";
      text = ''
        [Definition]
        failregex = sshd(?:\[\d+\])?: Did not receive identification string from <HOST>$
        ignoreregex =
      '';
    };

    environment.etc."fail2ban/filter.d/postfix-sasl.conf" = {
      enable = active "mailserver";
      text = ''
        # Fail2Ban filter for postfix authentication failures
        [INCLUDES]
        before = common.conf
        [Definition]
        daemon = postfix/smtpd
        failregex = ^%(__prefix_line)swarning: [-._\w]+\[<HOST>\]: SASL (?:LOGIN|PLAIN|(?:CRAM|DIGEST)-MD5) authentication failed(: [ A-Za-z0-9+/]*={0,2})?\s*$
      '';
    };

    environment.etc."fail2ban/filter.d/postfix-ddos.conf" = {
      enable = active "mailserver";
      text = ''
        [Definition]
        failregex = lost connection after EHLO from \S+\[<HOST>\]
      '';
    };

    environment.etc."fail2ban/filter.d/nginx-req-limit.conf" = {
      enable = active "nginx";
      text = ''
        [Definition]
        failregex = limiting requests, excess:.* by zone.*client: <HOST>
      '';
    };

    # Limit stack size to reduce memory usage
    systemd.services.fail2ban.serviceConfig.LimitSTACK = 256 * 1024;
  }