summary refs log tree commit diff
diff options
context:
space:
mode:
authorMaximilian Bosch <maximilian@mbosch.me>2023-10-31 14:12:00 +0100
committerMaximilian Bosch <maximilian@mbosch.me>2023-10-31 14:17:48 +0100
commit5927d556855d43f1d0495f3fb7ee2a287f04d8ce (patch)
tree2efc9804e86cd4659dbe68946d34a1ca92b2958f
parent80a7f8e986cdb022723044ebf0bb23c2b52a53d8 (diff)
downloadnixpkgs-5927d556855d43f1d0495f3fb7ee2a287f04d8ce.tar
nixpkgs-5927d556855d43f1d0495f3fb7ee2a287f04d8ce.tar.gz
nixpkgs-5927d556855d43f1d0495f3fb7ee2a287f04d8ce.tar.bz2
nixpkgs-5927d556855d43f1d0495f3fb7ee2a287f04d8ce.tar.lz
nixpkgs-5927d556855d43f1d0495f3fb7ee2a287f04d8ce.tar.xz
nixpkgs-5927d556855d43f1d0495f3fb7ee2a287f04d8ce.tar.zst
nixpkgs-5927d556855d43f1d0495f3fb7ee2a287f04d8ce.zip
privacyidea: remove
Related to #262907 (Django3 removal from nixpkgs).

This package already required an unreasonable amount of maintenance
regularly for a such small leaf-package. It has a few highly outdated
dependencies (e.g. flask 1, jinja2 2.11, sqlalchemy 1.3).

After at least each Python package-set update one had to fix up a lot of
dependencies to fix the package itself, so it was only useful on stable
branches. And having so much outdated software in a security-sensitive
piece of software seems questionable.

Finally, globin and I won't be available for maintaining this now that
Mayflower is migrating to another solution (and we'll do that as well)
and I'd expect this to bitrot extremely quick if we both bail out.
-rw-r--r--nixos/doc/manual/release-notes/rl-2311.section.md2
-rw-r--r--nixos/modules/module-list.nix1
-rw-r--r--nixos/modules/services/security/privacyidea.nix458
-rw-r--r--nixos/tests/all-tests.nix1
-rw-r--r--nixos/tests/privacyidea.nix43
-rw-r--r--pkgs/applications/misc/privacyidea/default.nix263
-rw-r--r--pkgs/development/python-modules/privacyidea-ldap-proxy/default.nix32
-rw-r--r--pkgs/top-level/aliases.nix1
-rw-r--r--pkgs/top-level/all-packages.nix2
-rw-r--r--pkgs/top-level/python-aliases.nix2
-rw-r--r--pkgs/top-level/python-packages.nix2
11 files changed, 4 insertions, 803 deletions
diff --git a/nixos/doc/manual/release-notes/rl-2311.section.md b/nixos/doc/manual/release-notes/rl-2311.section.md
index 7af4a99906c..276e7c9384e 100644
--- a/nixos/doc/manual/release-notes/rl-2311.section.md
+++ b/nixos/doc/manual/release-notes/rl-2311.section.md
@@ -339,6 +339,8 @@
 
 - `service.borgmatic.settings.location` and `services.borgmatic.configurations.<name>.location` are deprecated, please move your options out of sections to the global scope.
 
+- `privacyidea` (and the corresponding `privacyidea-ldap-proxy`) has been removed from nixpkgs because it has severely outdated dependencies that became unmaintainable with nixpkgs' python package-set.
+
 - `dagger` was removed because using a package called `dagger` and packaging it from source violates their trademark policy.
 
 - `win-virtio` package was renamed to `virtio-win` to be consistent with the upstream package name.
diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix
index 4949eb6f298..5647e89e541 100644
--- a/nixos/modules/module-list.nix
+++ b/nixos/modules/module-list.nix
@@ -1176,7 +1176,6 @@
   ./services/security/opensnitch.nix
   ./services/security/pass-secret-service.nix
   ./services/security/physlock.nix
-  ./services/security/privacyidea.nix
   ./services/security/shibboleth-sp.nix
   ./services/security/sks.nix
   ./services/security/sshguard.nix
diff --git a/nixos/modules/services/security/privacyidea.nix b/nixos/modules/services/security/privacyidea.nix
deleted file mode 100644
index 664335cb58e..00000000000
--- a/nixos/modules/services/security/privacyidea.nix
+++ /dev/null
@@ -1,458 +0,0 @@
-{ config, lib, options, pkgs, ... }:
-
-with lib;
-
-let
-  cfg = config.services.privacyidea;
-  opt = options.services.privacyidea;
-
-  uwsgi = pkgs.uwsgi.override { plugins = [ "python3" ]; python3 = pkgs.python310; };
-  python = uwsgi.python3;
-  penv = python.withPackages (const [ pkgs.privacyidea ]);
-  logCfg = pkgs.writeText "privacyidea-log.cfg" ''
-    [formatters]
-    keys=detail
-
-    [handlers]
-    keys=stream
-
-    [formatter_detail]
-    class=privacyidea.lib.log.SecureFormatter
-    format=[%(asctime)s][%(process)d][%(thread)d][%(levelname)s][%(name)s:%(lineno)d] %(message)s
-
-    [handler_stream]
-    class=StreamHandler
-    level=NOTSET
-    formatter=detail
-    args=(sys.stdout,)
-
-    [loggers]
-    keys=root,privacyidea
-
-    [logger_privacyidea]
-    handlers=stream
-    qualname=privacyidea
-    level=INFO
-
-    [logger_root]
-    handlers=stream
-    level=ERROR
-  '';
-
-  piCfgFile = pkgs.writeText "privacyidea.cfg" ''
-    SUPERUSER_REALM = [ '${concatStringsSep "', '" cfg.superuserRealm}' ]
-    SQLALCHEMY_DATABASE_URI = 'postgresql+psycopg2:///privacyidea'
-    SECRET_KEY = '${cfg.secretKey}'
-    PI_PEPPER = '${cfg.pepper}'
-    PI_ENCFILE = '${cfg.encFile}'
-    PI_AUDIT_KEY_PRIVATE = '${cfg.auditKeyPrivate}'
-    PI_AUDIT_KEY_PUBLIC = '${cfg.auditKeyPublic}'
-    PI_LOGCONFIG = '${logCfg}'
-    ${cfg.extraConfig}
-  '';
-
-  renderValue = x:
-    if isList x then concatMapStringsSep "," (x: ''"${x}"'') x
-    else if isString x && hasInfix "," x then ''"${x}"''
-    else x;
-
-  ldapProxyConfig = pkgs.writeText "ldap-proxy.ini"
-    (generators.toINI {}
-      (flip mapAttrs cfg.ldap-proxy.settings
-        (const (mapAttrs (const renderValue)))));
-
-  privacyidea-token-janitor = pkgs.writeShellScriptBin "privacyidea-token-janitor" ''
-    exec -a privacyidea-token-janitor \
-      /run/wrappers/bin/sudo -u ${cfg.user} \
-      env PRIVACYIDEA_CONFIGFILE=${cfg.stateDir}/privacyidea.cfg \
-      ${penv}/bin/privacyidea-token-janitor $@
-  '';
-in
-
-{
-  options = {
-    services.privacyidea = {
-      enable = mkEnableOption (lib.mdDoc "PrivacyIDEA");
-
-      environmentFile = mkOption {
-        type = types.nullOr types.path;
-        default = null;
-        example = "/root/privacyidea.env";
-        description = lib.mdDoc ''
-          File to load as environment file. Environment variables
-          from this file will be interpolated into the config file
-          using `envsubst` which is helpful for specifying
-          secrets:
-          ```
-          { services.privacyidea.secretKey = "$SECRET"; }
-          ```
-
-          The environment-file can now specify the actual secret key:
-          ```
-          SECRET=veryverytopsecret
-          ```
-        '';
-      };
-
-      stateDir = mkOption {
-        type = types.str;
-        default = "/var/lib/privacyidea";
-        description = lib.mdDoc ''
-          Directory where all PrivacyIDEA files will be placed by default.
-        '';
-      };
-
-      superuserRealm = mkOption {
-        type = types.listOf types.str;
-        default = [ "super" "administrators" ];
-        description = lib.mdDoc ''
-          The realm where users are allowed to login as administrators.
-        '';
-      };
-
-      secretKey = mkOption {
-        type = types.str;
-        example = "t0p s3cr3t";
-        description = lib.mdDoc ''
-          This is used to encrypt the auth_token.
-        '';
-      };
-
-      pepper = mkOption {
-        type = types.str;
-        example = "Never know...";
-        description = lib.mdDoc ''
-          This is used to encrypt the admin passwords.
-        '';
-      };
-
-      encFile = mkOption {
-        type = types.str;
-        default = "${cfg.stateDir}/enckey";
-        defaultText = literalExpression ''"''${config.${opt.stateDir}}/enckey"'';
-        description = lib.mdDoc ''
-          This is used to encrypt the token data and token passwords
-        '';
-      };
-
-      auditKeyPrivate = mkOption {
-        type = types.str;
-        default = "${cfg.stateDir}/private.pem";
-        defaultText = literalExpression ''"''${config.${opt.stateDir}}/private.pem"'';
-        description = lib.mdDoc ''
-          Private Key for signing the audit log.
-        '';
-      };
-
-      auditKeyPublic = mkOption {
-        type = types.str;
-        default = "${cfg.stateDir}/public.pem";
-        defaultText = literalExpression ''"''${config.${opt.stateDir}}/public.pem"'';
-        description = lib.mdDoc ''
-          Public key for checking signatures of the audit log.
-        '';
-      };
-
-      adminPasswordFile = mkOption {
-        type = types.path;
-        description = lib.mdDoc "File containing password for the admin user";
-      };
-
-      adminEmail = mkOption {
-        type = types.str;
-        example = "admin@example.com";
-        description = lib.mdDoc "Mail address for the admin user";
-      };
-
-      extraConfig = mkOption {
-        type = types.lines;
-        default = "";
-        description = lib.mdDoc ''
-          Extra configuration options for pi.cfg.
-        '';
-      };
-
-      user = mkOption {
-        type = types.str;
-        default = "privacyidea";
-        description = lib.mdDoc "User account under which PrivacyIDEA runs.";
-      };
-
-      group = mkOption {
-        type = types.str;
-        default = "privacyidea";
-        description = lib.mdDoc "Group account under which PrivacyIDEA runs.";
-      };
-
-      tokenjanitor = {
-        enable = mkEnableOption (lib.mdDoc "automatic runs of the token janitor");
-        interval = mkOption {
-          default = "quarterly";
-          type = types.str;
-          description = lib.mdDoc ''
-            Interval in which the cleanup program is supposed to run.
-            See {manpage}`systemd.time(7)` for further information.
-          '';
-        };
-        action = mkOption {
-          type = types.enum [ "delete" "mark" "disable" "unassign" ];
-          description = lib.mdDoc ''
-            Which action to take for matching tokens.
-          '';
-        };
-        unassigned = mkOption {
-          default = false;
-          type = types.bool;
-          description = lib.mdDoc ''
-            Whether to search for **unassigned** tokens
-            and apply [](#opt-services.privacyidea.tokenjanitor.action)
-            onto them.
-          '';
-        };
-        orphaned = mkOption {
-          default = true;
-          type = types.bool;
-          description = lib.mdDoc ''
-            Whether to search for **orphaned** tokens
-            and apply [](#opt-services.privacyidea.tokenjanitor.action)
-            onto them.
-          '';
-        };
-      };
-
-      ldap-proxy = {
-        enable = mkEnableOption (lib.mdDoc "PrivacyIDEA LDAP Proxy");
-
-        configFile = mkOption {
-          type = types.nullOr types.path;
-          default = null;
-          description = lib.mdDoc ''
-            Path to PrivacyIDEA LDAP Proxy configuration (proxy.ini).
-          '';
-        };
-
-        user = mkOption {
-          type = types.str;
-          default = "pi-ldap-proxy";
-          description = lib.mdDoc "User account under which PrivacyIDEA LDAP proxy runs.";
-        };
-
-        group = mkOption {
-          type = types.str;
-          default = "pi-ldap-proxy";
-          description = lib.mdDoc "Group account under which PrivacyIDEA LDAP proxy runs.";
-        };
-
-        settings = mkOption {
-          type = with types; attrsOf (attrsOf (oneOf [ str bool int (listOf str) ]));
-          default = {};
-          description = lib.mdDoc ''
-            Attribute-set containing the settings for `privacyidea-ldap-proxy`.
-            It's possible to pass secrets using env-vars as substitutes and
-            use the option [](#opt-services.privacyidea.ldap-proxy.environmentFile)
-            to inject them via `envsubst`.
-          '';
-        };
-
-        environmentFile = mkOption {
-          default = null;
-          type = types.nullOr types.str;
-          description = lib.mdDoc ''
-            Environment file containing secrets to be substituted into
-            [](#opt-services.privacyidea.ldap-proxy.settings).
-          '';
-        };
-      };
-    };
-  };
-
-  config = mkMerge [
-
-    (mkIf cfg.enable {
-
-      assertions = [
-        {
-          assertion = cfg.tokenjanitor.enable -> (cfg.tokenjanitor.orphaned || cfg.tokenjanitor.unassigned);
-          message = ''
-            privacyidea-token-janitor has no effect if neither orphaned nor unassigned tokens
-            are to be searched.
-          '';
-        }
-      ];
-
-      environment.systemPackages = [ pkgs.privacyidea (hiPrio privacyidea-token-janitor) ];
-
-      services.postgresql.enable = mkDefault true;
-
-      systemd.services.privacyidea-tokenjanitor = mkIf cfg.tokenjanitor.enable {
-        environment.PRIVACYIDEA_CONFIGFILE = "${cfg.stateDir}/privacyidea.cfg";
-        path = [ penv ];
-        serviceConfig = {
-          CapabilityBoundingSet = [ "" ];
-          ExecStart = "${pkgs.writeShellScript "pi-token-janitor" ''
-            ${optionalString cfg.tokenjanitor.orphaned ''
-              echo >&2 "Removing orphaned tokens..."
-              privacyidea-token-janitor find \
-                --orphaned true \
-                --action ${cfg.tokenjanitor.action}
-            ''}
-            ${optionalString cfg.tokenjanitor.unassigned ''
-              echo >&2 "Removing unassigned tokens..."
-              privacyidea-token-janitor find \
-                --assigned false \
-                --action ${cfg.tokenjanitor.action}
-            ''}
-          ''}";
-          Group = cfg.group;
-          LockPersonality = true;
-          MemoryDenyWriteExecute = true;
-          ProtectHome = true;
-          ProtectHostname = true;
-          ProtectKernelLogs = true;
-          ProtectKernelModules = true;
-          ProtectKernelTunables = true;
-          ProtectSystem = "strict";
-          ReadWritePaths = cfg.stateDir;
-          Type = "oneshot";
-          User = cfg.user;
-          WorkingDirectory = cfg.stateDir;
-        };
-      };
-      systemd.timers.privacyidea-tokenjanitor = mkIf cfg.tokenjanitor.enable {
-        wantedBy = [ "timers.target" ];
-        timerConfig.OnCalendar = cfg.tokenjanitor.interval;
-        timerConfig.Persistent = true;
-      };
-
-      systemd.services.privacyidea = let
-        piuwsgi = pkgs.writeText "uwsgi.json" (builtins.toJSON {
-          uwsgi = {
-            buffer-size = 8192;
-            plugins = [ "python3" ];
-            pythonpath = "${penv}/${uwsgi.python3.sitePackages}";
-            socket = "/run/privacyidea/socket";
-            uid = cfg.user;
-            gid = cfg.group;
-            chmod-socket = 770;
-            chown-socket = "${cfg.user}:nginx";
-            chdir = cfg.stateDir;
-            wsgi-file = "${penv}/etc/privacyidea/privacyideaapp.wsgi";
-            processes = 4;
-            harakiri = 60;
-            reload-mercy = 8;
-            stats = "/run/privacyidea/stats.socket";
-            max-requests = 2000;
-            limit-as = 1024;
-            reload-on-as = 512;
-            reload-on-rss = 256;
-            no-orphans = true;
-            vacuum = true;
-          };
-        });
-      in {
-        wantedBy = [ "multi-user.target" ];
-        after = [ "postgresql.service" ];
-        path = with pkgs; [ openssl ];
-        environment.PRIVACYIDEA_CONFIGFILE = "${cfg.stateDir}/privacyidea.cfg";
-        preStart = let
-          pi-manage = "${config.security.sudo.package}/bin/sudo -u privacyidea -HE ${penv}/bin/pi-manage";
-          pgsu = config.services.postgresql.superUser;
-          psql = config.services.postgresql.package;
-        in ''
-          mkdir -p ${cfg.stateDir} /run/privacyidea
-          chown ${cfg.user}:${cfg.group} -R ${cfg.stateDir} /run/privacyidea
-          umask 077
-          ${lib.getBin pkgs.envsubst}/bin/envsubst -o ${cfg.stateDir}/privacyidea.cfg \
-                                                   -i "${piCfgFile}"
-          chown ${cfg.user}:${cfg.group} ${cfg.stateDir}/privacyidea.cfg
-          if ! test -e "${cfg.stateDir}/db-created"; then
-            ${config.security.sudo.package}/bin/sudo -u ${pgsu} ${psql}/bin/createuser --no-superuser --no-createdb --no-createrole ${cfg.user}
-            ${config.security.sudo.package}/bin/sudo -u ${pgsu} ${psql}/bin/createdb --owner ${cfg.user} privacyidea
-            ${pi-manage} create_enckey
-            ${pi-manage} create_audit_keys
-            ${pi-manage} createdb
-            ${pi-manage} admin add admin -e ${cfg.adminEmail} -p "$(cat ${cfg.adminPasswordFile})"
-            ${pi-manage} db stamp head -d ${penv}/lib/privacyidea/migrations
-            touch "${cfg.stateDir}/db-created"
-            chmod g+r "${cfg.stateDir}/enckey" "${cfg.stateDir}/private.pem"
-          fi
-          ${pi-manage} db upgrade -d ${penv}/lib/privacyidea/migrations
-        '';
-        serviceConfig = {
-          Type = "notify";
-          ExecStart = "${uwsgi}/bin/uwsgi --json ${piuwsgi}";
-          ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
-          EnvironmentFile = lib.mkIf (cfg.environmentFile != null) cfg.environmentFile;
-          ExecStop = "${pkgs.coreutils}/bin/kill -INT $MAINPID";
-          NotifyAccess = "main";
-          KillSignal = "SIGQUIT";
-        };
-      };
-
-      users.users.privacyidea = mkIf (cfg.user == "privacyidea") {
-        group = cfg.group;
-        isSystemUser = true;
-      };
-
-      users.groups.privacyidea = mkIf (cfg.group == "privacyidea") {};
-    })
-
-    (mkIf cfg.ldap-proxy.enable {
-
-      assertions = [
-        { assertion = let
-            xor = a: b: a && !b || !a && b;
-          in xor (cfg.ldap-proxy.settings == {}) (cfg.ldap-proxy.configFile == null);
-          message = "configFile & settings are mutually exclusive for services.privacyidea.ldap-proxy!";
-        }
-      ];
-
-      warnings = mkIf (cfg.ldap-proxy.configFile != null) [
-        "Using services.privacyidea.ldap-proxy.configFile is deprecated! Use the RFC42-style settings option instead!"
-      ];
-
-      systemd.services.privacyidea-ldap-proxy = let
-        ldap-proxy-env = pkgs.python3.withPackages (ps: [ ps.privacyidea-ldap-proxy ]);
-      in {
-        description = "privacyIDEA LDAP proxy";
-        wantedBy = [ "multi-user.target" ];
-        serviceConfig = {
-          User = cfg.ldap-proxy.user;
-          Group = cfg.ldap-proxy.group;
-          StateDirectory = "privacyidea-ldap-proxy";
-          EnvironmentFile = mkIf (cfg.ldap-proxy.environmentFile != null)
-            [ cfg.ldap-proxy.environmentFile ];
-          ExecStartPre =
-            "${pkgs.writeShellScript "substitute-secrets-ldap-proxy" ''
-              umask 0077
-              ${pkgs.envsubst}/bin/envsubst \
-                -i ${ldapProxyConfig} \
-                -o $STATE_DIRECTORY/ldap-proxy.ini
-            ''}";
-          ExecStart = let
-            configPath = if cfg.ldap-proxy.settings != {}
-              then "%S/privacyidea-ldap-proxy/ldap-proxy.ini"
-              else cfg.ldap-proxy.configFile;
-          in ''
-            ${ldap-proxy-env}/bin/twistd \
-              --nodaemon \
-              --pidfile= \
-              -u ${cfg.ldap-proxy.user} \
-              -g ${cfg.ldap-proxy.group} \
-              ldap-proxy \
-              -c ${configPath}
-          '';
-          Restart = "always";
-        };
-      };
-
-      users.users.pi-ldap-proxy = mkIf (cfg.ldap-proxy.user == "pi-ldap-proxy") {
-        group = cfg.ldap-proxy.group;
-        isSystemUser = true;
-      };
-
-      users.groups.pi-ldap-proxy = mkIf (cfg.ldap-proxy.group == "pi-ldap-proxy") {};
-    })
-  ];
-
-}
diff --git a/nixos/tests/all-tests.nix b/nixos/tests/all-tests.nix
index 456efe14464..0a3bbf37c6b 100644
--- a/nixos/tests/all-tests.nix
+++ b/nixos/tests/all-tests.nix
@@ -685,7 +685,6 @@ in {
   predictable-interface-names = handleTest ./predictable-interface-names.nix {};
   printing-socket = handleTest ./printing.nix { socket = true; };
   printing-service = handleTest ./printing.nix { socket = false; };
-  privacyidea = handleTest ./privacyidea.nix {};
   privoxy = handleTest ./privoxy.nix {};
   prometheus = handleTest ./prometheus.nix {};
   prometheus-exporters = handleTest ./prometheus-exporters.nix {};
diff --git a/nixos/tests/privacyidea.nix b/nixos/tests/privacyidea.nix
deleted file mode 100644
index 401ad72c37b..00000000000
--- a/nixos/tests/privacyidea.nix
+++ /dev/null
@@ -1,43 +0,0 @@
-# Miscellaneous small tests that don't warrant their own VM run.
-
-import ./make-test-python.nix ({ pkgs, ...} : rec {
-  name = "privacyidea";
-  meta = with pkgs.lib.maintainers; {
-    maintainers = [ ];
-  };
-
-  nodes.machine = { ... }: {
-    virtualisation.cores = 2;
-
-    services.privacyidea = {
-      enable = true;
-      secretKey = "$SECRET_KEY";
-      pepper = "$PEPPER";
-      adminPasswordFile = pkgs.writeText "admin-password" "testing";
-      adminEmail = "root@localhost";
-
-      # Don't try this at home!
-      environmentFile = pkgs.writeText "pi-secrets.env" ''
-        SECRET_KEY=testing
-        PEPPER=testing
-      '';
-    };
-    services.nginx = {
-      enable = true;
-      virtualHosts."_".locations."/".extraConfig = ''
-        uwsgi_pass unix:/run/privacyidea/socket;
-      '';
-    };
-  };
-
-  testScript = ''
-    machine.start()
-    machine.wait_for_unit("multi-user.target")
-    machine.succeed("curl --fail http://localhost | grep privacyIDEA")
-    machine.succeed("grep \"SECRET_KEY = 'testing'\" /var/lib/privacyidea/privacyidea.cfg")
-    machine.succeed("grep \"PI_PEPPER = 'testing'\" /var/lib/privacyidea/privacyidea.cfg")
-    machine.succeed(
-        "curl --fail http://localhost/auth -F username=admin -F password=testing | grep token"
-    )
-  '';
-})
diff --git a/pkgs/applications/misc/privacyidea/default.nix b/pkgs/applications/misc/privacyidea/default.nix
deleted file mode 100644
index 9cdf4da33ef..00000000000
--- a/pkgs/applications/misc/privacyidea/default.nix
+++ /dev/null
@@ -1,263 +0,0 @@
-{ lib, fetchFromGitHub, cacert, openssl, nixosTests
-, python310, fetchPypi, fetchpatch
-}:
-
-let
-  dropDocOutput = { outputs, ... }: {
-    outputs = lib.filter (x: x != "doc") outputs;
-  };
-
-  # Follow issue below for Python 3.11 support
-  # https://github.com/privacyidea/privacyidea/issues/3593
-  python3' = python310.override {
-    packageOverrides = self: super: {
-      django = super.django_3;
-
-      sqlalchemy = super.sqlalchemy.overridePythonAttrs (oldAttrs: rec {
-        version = "1.3.24";
-        src = fetchPypi {
-          inherit (oldAttrs) pname;
-          inherit version;
-          hash = "sha256-67t3fL+TEjWbiXv4G6ANrg9ctp+6KhgmXcwYpvXvdRk=";
-        };
-        doCheck = false;
-      });
-      # version 3.3.0+ does not support SQLAlchemy 1.3
-      factory-boy = super.factory-boy.overridePythonAttrs (oldAttrs: rec {
-        version = "3.2.1";
-        src = oldAttrs.src.override {
-          inherit version;
-          hash = "sha256-qY0newwEfHXrbkq4UIp/gfsD0sshmG9ieRNUbveipV4=";
-        };
-        postPatch = "";
-      });
-      # fails with `no tests ran in 1.75s`
-      alembic = super.alembic.overridePythonAttrs (lib.const {
-        doCheck = false;
-      });
-      flask-migrate = super.flask-migrate.overridePythonAttrs (oldAttrs: rec {
-        version = "2.7.0";
-        src = fetchPypi {
-          pname = "Flask-Migrate";
-          inherit version;
-          hash = "sha256-ri8FZxWIdi3YOiHYsYxR/jVehng+JFlJlf+Nc4Df/jg=";
-        };
-      });
-      flask-sqlalchemy = super.flask-sqlalchemy.overridePythonAttrs (old: rec {
-        version = "2.5.1";
-        format = "setuptools";
-        src = fetchPypi {
-          pname = "Flask-SQLAlchemy";
-          inherit version;
-          hash = "sha256:2bda44b43e7cacb15d4e05ff3cc1f8bc97936cc464623424102bfc2c35e95912";
-        };
-      });
-      # Taken from by https://github.com/NixOS/nixpkgs/pull/173090/commits/d2c0c7eb4cc91beb0a1adbaf13abc0a526a21708
-      werkzeug = super.werkzeug.overridePythonAttrs (old: rec {
-        version = "1.0.1";
-        src = old.src.override {
-          inherit version;
-          hash = "sha256-bICx5a02ZSkOo5MguR4b4eDV9gZSuWSjBwIW3oPS5Hw=";
-        };
-        nativeCheckInputs = old.nativeCheckInputs ++ (with self; [
-          requests
-        ]);
-        doCheck = false;
-      });
-      # Required by flask-1.1
-      jinja2 = super.jinja2.overridePythonAttrs (old: rec {
-        version = "2.11.3";
-        src = old.src.override {
-          inherit version;
-          hash = "sha256-ptWEM94K6AA0fKsfowQ867q+i6qdKeZo8cdoy4ejM8Y=";
-        };
-        patches = [
-          # python 3.10 compat fixes. In later upstream releases, but these
-          # are not compatible with flask 1 which we need here :(
-          (fetchpatch {
-            url = "https://github.com/thmo/jinja/commit/1efb4cc918b4f3d097c376596da101de9f76585a.patch";
-            hash = "sha256-GFaSvYxgzOEFmnnDIfcf0ImScNTh1lR4lxt2Uz1DYdU=";
-          })
-          (fetchpatch {
-            url = "https://github.com/mkrizek/jinja/commit/bd8bad37d1c0e2d8995a44fd88e234f5340afec5.patch";
-            hash = "sha256-Uow+gaO+/dH6zavC0X/SsuMAfhTLRWpamVlL87DXDRA=";
-            excludes = [ "CHANGES.rst" ];
-          })
-        ];
-      });
-      # Required by jinja2-2.11.3
-      markupsafe = super.markupsafe.overridePythonAttrs (old: rec {
-        version = "2.0.1";
-        src = old.src.override {
-          inherit version;
-          hash = "sha256-WUxngH+xYjizDES99082wCzfItHIzake+KDtjav1Ygo=";
-        };
-      });
-      itsdangerous = super.itsdangerous.overridePythonAttrs (old: rec {
-        version = "1.1.0";
-        src = old.src.override {
-          inherit version;
-          hash = "sha256-MhsDPQfypBNtPsdi6snxahDM1g9TwMka+QIXrOe6Hxk=";
-        };
-      });
-      flask = super.flask.overridePythonAttrs (old: rec {
-        version = "1.1.4";
-        src = old.src.override {
-          inherit version;
-          hash = "sha256-D762GA04OpGG0NbtlU4AQq2fGODo3giLK0GdUmkn0ZY=";
-        };
-      });
-      sqlsoup = super.sqlsoup.overrideAttrs ({ meta ? {}, ... }: {
-        meta = meta // { broken = false; };
-      });
-      click = super.click.overridePythonAttrs (old: rec {
-        version = "7.1.2";
-        src = old.src.override {
-          inherit version;
-          hash = "sha256-0rUlXHxjSbwb0eWeCM0SrLvWPOZJ8liHVXg6qU37axo=";
-        };
-        disabledTests = [ "test_bytes_args" ]; # https://github.com/pallets/click/commit/6e05e1fa1c2804
-      });
-      # Now requires `lingua` as check input that requires a newer `click`,
-      # however `click-7` is needed by the older flask we need here. Since it's just
-      # for the test-suite apparently, let's skip it for now.
-      mako = super.mako.overridePythonAttrs (lib.const {
-        nativeCheckInputs = [];
-        doCheck = false;
-      });
-      # Requires pytest-httpserver as checkInput now which requires Werkzeug>=2 which is not
-      # supported by current privacyIDEA.
-      responses = super.responses.overridePythonAttrs (lib.const {
-        doCheck = false;
-      });
-      flask-babel = (super.flask-babel.override {
-        sphinxHook = null;
-        furo = null;
-      }).overridePythonAttrs (old: (dropDocOutput old) // rec {
-        pname = "Flask-Babel";
-        version = "2.0.0";
-        format = "setuptools";
-        src = fetchPypi {
-          inherit pname;
-          inherit version;
-          hash = "sha256:f9faf45cdb2e1a32ea2ec14403587d4295108f35017a7821a2b1acb8cfd9257d";
-        };
-        disabledTests = [
-          # AssertionError: assert 'Apr 12, 2010...46:00\u202fPM' == 'Apr 12, 2010, 1:46:00 PM'
-          # Note the `\u202f` (narrow, no-break space) vs space.
-          "test_basics"
-          "test_init_app"
-          "test_custom_locale_selector"
-          "test_refreshing"
-        ];
-      });
-      psycopg2 = (super.psycopg2.override {
-        sphinxHook = null;
-        sphinx-better-theme = null;
-      }).overridePythonAttrs dropDocOutput;
-      pyjwt = (super.pyjwt.override {
-        sphinxHook = null;
-        sphinx-rtd-theme = null;
-      }).overridePythonAttrs (old: (dropDocOutput old) // { format = "setuptools"; });
-      beautifulsoup4 = (super.beautifulsoup4.override {
-        sphinxHook = null;
-      }).overridePythonAttrs dropDocOutput;
-      pydash = (super.pydash.override {
-        sphinx-rtd-theme = null;
-      }).overridePythonAttrs (old: rec {
-        version = "5.1.0";
-        src = fetchPypi {
-          inherit (old) pname;
-          inherit version;
-          hash = "sha256-GysFCsG64EnNB/WSCxT6u+UmOPSF2a2h6xFanuv/aDU=";
-        };
-        format = "setuptools";
-        doCheck = false;
-      });
-      pyopenssl = (super.pyopenssl.override {
-        sphinxHook = null;
-        sphinx-rtd-theme = null;
-      }).overridePythonAttrs dropDocOutput;
-      deprecated = (super.deprecated.override {
-        sphinxHook = null;
-      }).overridePythonAttrs dropDocOutput;
-      wrapt = (super.wrapt.override {
-        sphinxHook = null;
-        sphinx-rtd-theme = null;
-      }).overridePythonAttrs dropDocOutput;
-    };
-  };
-in
-python3'.pkgs.buildPythonPackage rec {
-  pname = "privacyIDEA";
-  version = "3.8.1";
-  format = "setuptools";
-
-  src = fetchFromGitHub {
-    owner = pname;
-    repo = pname;
-    rev = "v${version}";
-    hash = "sha256-SYXw8PBCb514v3rcy15W/vZS5JyMsu81D2sJmviLRtw=";
-    fetchSubmodules = true;
-  };
-
-  patches = [
-    # https://github.com/privacyidea/privacyidea/pull/3611
-    (fetchpatch {
-      url = "https://github.com/privacyidea/privacyidea/commit/7db6509721726a34e8528437ddbd4210019b11ef.patch";
-      sha256 = "sha256-ZvtauCs1vWyxzGbA0B2+gG8q5JyUO8DF8nm/3/vcYmE=";
-    })
-  ];
-
-  propagatedBuildInputs = with python3'.pkgs; [
-    cryptography pyrad pymysql python-dateutil flask-versioned flask-script
-    defusedxml croniter flask-migrate pyjwt configobj sqlsoup pillow
-    python-gnupg passlib pyopenssl beautifulsoup4 smpplib flask-babel
-    ldap3 huey pyyaml qrcode oauth2client requests lxml cbor2 psycopg2
-    pydash ecdsa google-auth importlib-metadata argon2-cffi bcrypt segno
-  ];
-
-  passthru.tests = { inherit (nixosTests) privacyidea; };
-
-  nativeCheckInputs = with python3'.pkgs; [ openssl mock pytestCheckHook responses testfixtures ];
-  preCheck = "export HOME=$(mktemp -d)";
-  postCheck = "unset HOME";
-  disabledTests = [
-    # expects `/home/` to exist, fails with `FileNotFoundError: [Errno 2] No such file or directory: '/home/'`.
-    "test_01_loading_scripts"
-
-    # Tries to connect to `fcm.googleapis.com`.
-    "test_02_api_push_poll"
-    "test_04_decline_auth_request"
-
-    # Timezone info not available in build sandbox
-    "test_14_convert_timestamp_to_utc"
-
-    # Fails because of different logger configurations
-    "test_01_create_default_app"
-    "test_03_logging_config_file"
-    "test_04_logging_config_yaml"
-    "test_05_logging_config_broken_yaml"
-  ];
-
-  pythonImportsCheck = [ "privacyidea" ];
-
-  postPatch = ''
-    patchShebangs tests/testdata/scripts
-    substituteInPlace privacyidea/lib/resolvers/LDAPIdResolver.py --replace \
-      "/etc/privacyidea/ldap-ca.crt" \
-      "${cacert}/etc/ssl/certs/ca-bundle.crt"
-  '';
-
-  postInstall = ''
-    rm -r $out/${python3'.sitePackages}/tests
-  '';
-
-  meta = with lib; {
-    description = "Multi factor authentication system (2FA, MFA, OTP Server)";
-    license = licenses.agpl3Plus;
-    homepage = "http://www.privacyidea.org";
-    maintainers = with maintainers; [ ma27 ];
-    platforms = platforms.linux;
-  };
-}
diff --git a/pkgs/development/python-modules/privacyidea-ldap-proxy/default.nix b/pkgs/development/python-modules/privacyidea-ldap-proxy/default.nix
deleted file mode 100644
index 0b2a85f7e94..00000000000
--- a/pkgs/development/python-modules/privacyidea-ldap-proxy/default.nix
+++ /dev/null
@@ -1,32 +0,0 @@
-{ lib, buildPythonPackage, fetchFromGitHub, twisted, ldaptor, configobj, fetchpatch }:
-
-buildPythonPackage rec {
-  pname = "privacyidea-ldap-proxy";
-  version = "0.7";
-
-  src = fetchFromGitHub {
-    owner = "privacyidea";
-    repo = pname;
-    rev = "v${version}";
-    sha256 = "1i2kgxqd38xvb42qj0a4a35w4vk0fyp3n7w48kqmvrxc77p6r6i8";
-  };
-
-  patches = [
-    # support for LDAPCompareRequest.
-    (fetchpatch {
-      url = "https://github.com/mayflower/privacyidea-ldap-proxy/commit/a13356717379b174f1a6abf767faa0dbd459f5dd.patch";
-      hash = "sha256-SBTj9ayQ8JFD8BoYIl77nxWVV3PXnHZ8JMlJnxd/nEk=";
-    })
-  ];
-
-  propagatedBuildInputs = [ twisted ldaptor configobj ];
-
-  pythonImportsCheck = [ "pi_ldapproxy" ];
-
-  meta = with lib; {
-    description = "LDAP Proxy to intercept LDAP binds and authenticate against privacyIDEA";
-    homepage = "https://github.com/privacyidea/privacyidea-ldap-proxy";
-    license = licenses.agpl3Only;
-    maintainers = [ ];
-  };
-}
diff --git a/pkgs/top-level/aliases.nix b/pkgs/top-level/aliases.nix
index 85ac74fae7d..38c4126a20f 100644
--- a/pkgs/top-level/aliases.nix
+++ b/pkgs/top-level/aliases.nix
@@ -710,6 +710,7 @@ mapAliases ({
   pinentry_qt = throw "'pinentry_qt' has been renamed to/replaced by 'pinentry-qt'"; # Converted to throw 2023-09-10
   pinentry_qt5 = pinentry-qt; # Added 2020-02-11
   poetry2nix = throw "poetry2nix is now maintained out-of-tree. Please use https://github.com/nix-community/poetry2nix/"; # Added 2023-10-26
+  privacyidea = throw "privacyidea has been removed from nixpkgs"; # Added 2023-10-31
   probe-rs-cli = throw "probe-rs-cli is now part of the probe-rs package"; # Added 2023-07-03
   processing3 = throw "'processing3' has been renamed to/replaced by 'processing'"; # Converted to throw 2023-09-10
   prometheus-dmarc-exporter = dmarc-metrics-exporter; # added 2022-05-31
diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix
index 77aaee8aa69..9d9a3a7a404 100644
--- a/pkgs/top-level/all-packages.nix
+++ b/pkgs/top-level/all-packages.nix
@@ -19871,8 +19871,6 @@ with pkgs;
 
   premake = premake4;
 
-  privacyidea = callPackage ../applications/misc/privacyidea { };
-
   process-compose = callPackage ../applications/misc/process-compose { };
 
   process-viewer = callPackage ../applications/misc/process-viewer { };
diff --git a/pkgs/top-level/python-aliases.nix b/pkgs/top-level/python-aliases.nix
index f11511b81f9..5e273836060 100644
--- a/pkgs/top-level/python-aliases.nix
+++ b/pkgs/top-level/python-aliases.nix
@@ -262,7 +262,7 @@ mapAliases ({
   poster3 = throw "poster3 is unmaintained and source is no longer available"; # added 2023-05-29
   postorius = throw "Please use pkgs.mailmanPackages.postorius"; # added 2022-04-29
   powerlineMemSegment = powerline-mem-segment; # added 2021-10-08
-  privacyidea = throw "privacyidea has been renamed to pkgs.privacyidea"; # added 2021-06-20
+  privacyidea-ldap-proxy = throw "privacyidea-ldap-proxy has been removed from nixpkgs"; # added 2023-10-31
   prometheus_client = prometheus-client; # added 2021-06-10
   prompt_toolkit = prompt-toolkit; # added 2021-07-22
   protonup = protonup-ng; # Added 2022-11-06
diff --git a/pkgs/top-level/python-packages.nix b/pkgs/top-level/python-packages.nix
index a71c3ed14ea..797fb18a26f 100644
--- a/pkgs/top-level/python-packages.nix
+++ b/pkgs/top-level/python-packages.nix
@@ -9510,8 +9510,6 @@ self: super: with self; {
 
   prison = callPackage ../development/python-modules/prison { };
 
-  privacyidea-ldap-proxy = callPackage ../development/python-modules/privacyidea-ldap-proxy { };
-
   proboscis = callPackage ../development/python-modules/proboscis { };
 
   process-tests = callPackage ../development/python-modules/process-tests { };