Unverified Commit c3615b0f authored by Maximilian Bosch's avatar Maximilian Bosch Committed by GitHub
Browse files

nixos/nextcloud: Allow disabling initial admin user creation on Nextcloud >= 32 (#418378)

parents 80fc98a0 e739c5d7
Loading
Loading
Loading
Loading
+43 −17
Original line number Diff line number Diff line
@@ -647,7 +647,7 @@ in
        '';
      };
      adminuser = lib.mkOption {
        type = lib.types.str;
        type = lib.types.nullOr lib.types.str;
        default = "root";
        description = ''
          Username for the admin account. The username is only set during the
@@ -656,7 +656,7 @@ in
        '';
      };
      adminpassFile = lib.mkOption {
        type = lib.types.str;
        type = lib.types.nullOr lib.types.str;
        description = ''
          The full path to a file that contains the admin's password. The password is
          set only in the initial setup of Nextcloud by the systemd service `nextcloud-setup.service`.
@@ -1124,6 +1124,26 @@ in
              https://docs.nextcloud.com/server/latest/admin_manual/configuration_database/db_conversion.html
            '';
          }
          {
            assertion =
              lib.versionAtLeast overridePackage.version "32.0.0"
              || (cfg.config.adminuser != null && cfg.config.adminpassFile != null);
            message = ''
              Disabling initial admin user creation is only available on Nextcloud >= 32.0.0.
            '';
          }
          {
            assertion = cfg.config.adminuser == null -> cfg.config.adminpassFile == null;
            message = ''
              If `services.nextcloud.config.adminuser` is null, `services.nextcloud.config.adminpassFile` must be null as well in order to disable initial admin user creation.
            '';
          }
          {
            assertion = cfg.config.adminpassFile == null -> cfg.config.adminuser == null;
            message = ''
              If `services.nextcloud.config.adminpassFile` is null, `services.nextcloud.config.adminuser` must be null as well in order to disable initial admin user creation.
            '';
          }
        ];
      }

@@ -1167,10 +1187,14 @@ in
                    arg = "DBPASS";
                    value = if c.dbpassFile != null then ''"$(<"$CREDENTIALS_DIRECTORY/dbpass")"'' else ''""'';
                  };
                  adminpass = {
                  adminpass =
                    if c.adminpassFile != null then
                      {
                        arg = "ADMINPASS";
                        value = ''"$(<"$CREDENTIALS_DIRECTORY/adminpass")"'';
                  };
                      }
                    else
                      null;
                  installFlags = lib.concatStringsSep " \\\n    " (
                    lib.mapAttrsToList (k: v: "${k} ${toString v}") {
                      "--database" = ''"${c.dbtype}"'';
@@ -1181,15 +1205,16 @@ in
                      ${if c.dbhost != null then "--database-host" else null} = ''"${c.dbhost}"'';
                      ${if c.dbuser != null then "--database-user" else null} = ''"${c.dbuser}"'';
                      "--database-pass" = "\"\$${dbpass.arg}\"";
                      "--admin-user" = ''"${c.adminuser}"'';
                      "--admin-pass" = "\"\$${adminpass.arg}\"";
                      ${if c.adminuser != null then "--admin-user" else null} = ''"${c.adminuser}"'';
                      ${if adminpass != null then "--admin-pass" else null} = "\"\$${adminpass.arg}\"";
                      ${if c.adminuser == null && adminpass == null then "--disable-admin-user" else null} = "";
                      "--data-dir" = ''"${datadir}/data"'';
                    }
                  );
                in
                ''
                  ${mkExport dbpass}
                  ${mkExport adminpass}
                  ${lib.optionalString (adminpass != null) (mkExport adminpass)}
                  ${lib.getExe occ} maintenance:install \
                      ${installFlags}
                '';
@@ -1216,10 +1241,12 @@ in
                    exit 1
                  fi
                ''}
                ${lib.optionalString (c.adminpassFile != null) ''
                  if [ -z "$(<"$CREDENTIALS_DIRECTORY/adminpass")" ]; then
                    echo "adminpassFile ${c.adminpassFile} is empty!"
                    exit 1
                  fi
                ''}

                # Check if systemd-tmpfiles setup worked correctly
                if [[ ! -O "${datadir}/config" ]]; then
@@ -1261,9 +1288,8 @@ in
              '';
              serviceConfig.Type = "oneshot";
              serviceConfig.User = "nextcloud";
              serviceConfig.LoadCredential = [
                "adminpass:${cfg.config.adminpassFile}"
              ]
              serviceConfig.LoadCredential =
                lib.optional (cfg.config.adminpassFile != null) "adminpass:${cfg.config.adminpassFile}"
                ++ runtimeSystemdCredentials;
              # On Nextcloud ≥ 26, it is not necessary to patch the database files to prevent
              # an automatic creation of the database user.
+12 −9
Original line number Diff line number Diff line
@@ -30,8 +30,8 @@ let
        }
      ];

      adminuser = "root";
      adminpass = "hunter2";
      adminuser = pkgs.lib.mkDefault "root";
      adminpass = pkgs.lib.mkDefault "hunter2";

      test-helpers.rclone = "${pkgs.writeShellScript "rclone" ''
        set -euo pipefail
@@ -129,13 +129,16 @@ let
          }
        );
    in
    map callNextcloudTest [
    map callNextcloudTest (
      [
        ./basic.nix
        ./with-declarative-redis-and-secrets.nix
        ./with-mysql-and-memcached.nix
        ./with-postgresql-and-redis.nix
        ./with-objectstore.nix
    ];
      ]
      ++ (pkgs.lib.optional (version >= 32) ./without-admin-user.nix)
    );
in
listToAttrs (
  concatMap genTests [
+48 −0
Original line number Diff line number Diff line
{
  name,
  pkgs,
  testBase,
  system,
  ...
}:

with import ../../lib/testing-python.nix { inherit system pkgs; };
runTest (
  {
    config,
    lib,
    ...
  }:
  rec {
    inherit name;

    meta.maintainers = lib.teams.nextcloud.members;

    imports = [ testBase ];

    nodes = {
      nextcloud =
        { config, pkgs, ... }:
        {
          services.nextcloud = {
            config = {
              dbtype = "sqlite";
              adminuser = null;
              adminpassFile = lib.mkForce null;
            };
          };
        };
    };

    adminuser = "root";
    # This needs to be a "secure" password, since the password_policy app is enabled after installation and will forbid "simple" passwords.
    adminpass = "+CVpTwaOEktxsFc6";

    # Manually create the adminuser to make the default set of tests pass.
    # If adminuser was already created during the installation this command would not succeed.
    # This user name must always match the default value in services.nextcloud.config.adminuser!
    test-helpers.init = ''
      nextcloud.succeed("OC_PASS=${adminpass} nextcloud-occ user:add ${adminuser} --password-from-env")
    '';
  }
)