{"diffoscope-json-version": 1, "source1": "/srv/reproducible-results/rbuild-debian/r-b-build.JtmoGxGD/b1/jupyterhub_5.2.1+ds1-4_amd64.changes", "source2": "/srv/reproducible-results/rbuild-debian/r-b-build.JtmoGxGD/b2/jupyterhub_5.2.1+ds1-4_amd64.changes", "unified_diff": null, "details": [{"source1": "Files", "source2": "Files", "unified_diff": "@@ -1,2 +1,2 @@\n \n- 8b002e4d8b0addb63d91245d96b07950 2022676 python optional jupyterhub_5.2.1+ds1-4_all.deb\n+ 0d79407f3ae22eda6bfc1c7f03f7e884 2022076 python optional jupyterhub_5.2.1+ds1-4_all.deb\n"}, {"source1": "jupyterhub_5.2.1+ds1-4_all.deb", "source2": "jupyterhub_5.2.1+ds1-4_all.deb", "unified_diff": null, "details": [{"source1": "file list", "source2": "file list", "unified_diff": "@@ -1,3 +1,3 @@\n -rw-r--r-- 0 0 0 4 2025-05-28 09:40:25.000000 debian-binary\n -rw-r--r-- 0 0 0 59500 2025-05-28 09:40:25.000000 control.tar.xz\n--rw-r--r-- 0 0 0 1962984 2025-05-28 09:40:25.000000 data.tar.xz\n+-rw-r--r-- 0 0 0 1962384 2025-05-28 09:40:25.000000 data.tar.xz\n"}, {"source1": "control.tar.xz", "source2": "control.tar.xz", "unified_diff": null, "details": [{"source1": "control.tar", "source2": "control.tar", "unified_diff": null, "details": [{"source1": "./md5sums", "source2": "./md5sums", "unified_diff": null, "details": [{"source1": "./md5sums", "source2": "./md5sums", "comments": ["Files differ"], "unified_diff": null}]}]}]}, {"source1": "data.tar.xz", "source2": "data.tar.xz", "unified_diff": null, "details": [{"source1": "data.tar", "source2": "data.tar", "unified_diff": null, "details": [{"source1": "./usr/share/jupyterhub/jupyterhub_config.py", "source2": "./usr/share/jupyterhub/jupyterhub_config.py", "unified_diff": "@@ -997,28 +997,14 @@\n # \n # It should return the new URL to redirect to, or None to preserve current\n # behavior.\n # Default: None\n # c.JupyterHub.user_redirect_hook = None\n \n #------------------------------------------------------------------------------\n-# CryptKeeper(SingletonConfigurable) configuration\n-#------------------------------------------------------------------------------\n-## Encapsulate encryption configuration\n-# \n-# Use via the encryption_config singleton below.\n-\n-# Default: []\n-# c.CryptKeeper.keys = []\n-\n-## The number of threads to allocate for encryption\n-# Default: 42\n-# c.CryptKeeper.n_threads = 42\n-\n-#------------------------------------------------------------------------------\n # Authenticator(LoggingConfigurable) configuration\n #------------------------------------------------------------------------------\n ## Base class for implementing an authentication provider for JupyterHub\n \n ## Set of users that will be granted admin rights on this JupyterHub.\n # \n # Note:\n@@ -2028,370 +2014,337 @@\n # \n # If the process does not exit cleanly after this many seconds of SIGTERM, a\n # SIGKILL is sent.\n # Default: 5\n # c.LocalProcessSpawner.term_timeout = 5\n \n #------------------------------------------------------------------------------\n-# SimpleLocalProcessSpawner(LocalProcessSpawner) configuration\n+# LocalAuthenticator(Authenticator) configuration\n #------------------------------------------------------------------------------\n-## A version of LocalProcessSpawner that doesn't require users to exist on the\n-# system beforehand.\n-# \n-# Only use this for testing.\n+## Base class for Authenticators that work with local Linux/UNIX users\n # \n-# Note: DO NOT USE THIS FOR PRODUCTION USE CASES! It is very insecure, and\n-# provides absolutely no isolation between different users!\n-\n-## \n-# See also: Spawner.args\n-# c.SimpleLocalProcessSpawner.args = []\n-\n-## \n-# See also: Spawner.auth_state_hook\n-# c.SimpleLocalProcessSpawner.auth_state_hook = None\n-\n-## \n-# See also: Spawner.cmd\n-# c.SimpleLocalProcessSpawner.cmd = ['jupyterhub-singleuser']\n-\n-## \n-# See also: Spawner.consecutive_failure_limit\n-# c.SimpleLocalProcessSpawner.consecutive_failure_limit = 0\n-\n-## \n-# See also: Spawner.cpu_guarantee\n-# c.SimpleLocalProcessSpawner.cpu_guarantee = None\n-\n-## \n-# See also: Spawner.cpu_limit\n-# c.SimpleLocalProcessSpawner.cpu_limit = None\n-\n-## Enable debug-logging of the single-user server\n-# See also: Spawner.debug\n-# c.SimpleLocalProcessSpawner.debug = False\n-\n-## \n-# See also: Spawner.default_url\n-# c.SimpleLocalProcessSpawner.default_url = ''\n-\n-## \n-# See also: Spawner.disable_user_config\n-# c.SimpleLocalProcessSpawner.disable_user_config = False\n-\n-## \n-# See also: Spawner.env_keep\n-# c.SimpleLocalProcessSpawner.env_keep = ['JUPYTERHUB_SINGLEUSER_APP']\n-\n-## \n-# See also: Spawner.environment\n-# c.SimpleLocalProcessSpawner.environment = {}\n-\n-## \n-# See also: Spawner.group_overrides\n-# c.SimpleLocalProcessSpawner.group_overrides = traitlets.Undefined\n-\n-## Template to expand to set the user home. {username} is expanded to the\n-# jupyterhub username.\n-# Default: '/tmp/{username}'\n-# c.SimpleLocalProcessSpawner.home_dir_template = '/tmp/{username}'\n-\n-## \n-# See also: Spawner.http_timeout\n-# c.SimpleLocalProcessSpawner.http_timeout = 30\n-\n-## \n-# See also: Spawner.hub_connect_url\n-# c.SimpleLocalProcessSpawner.hub_connect_url = None\n-\n-## \n-# See also: LocalProcessSpawner.interrupt_timeout\n-# c.SimpleLocalProcessSpawner.interrupt_timeout = 10\n-\n-## \n-# See also: Spawner.ip\n-# c.SimpleLocalProcessSpawner.ip = '127.0.0.1'\n-\n-## \n-# See also: LocalProcessSpawner.kill_timeout\n-# c.SimpleLocalProcessSpawner.kill_timeout = 5\n-\n-## \n-# See also: Spawner.mem_guarantee\n-# c.SimpleLocalProcessSpawner.mem_guarantee = None\n-\n-## \n-# See also: Spawner.mem_limit\n-# c.SimpleLocalProcessSpawner.mem_limit = None\n-\n-## \n-# See also: Spawner.notebook_dir\n-# c.SimpleLocalProcessSpawner.notebook_dir = ''\n-\n-## Allowed scopes for oauth tokens issued by this server's oauth client.\n-# See also: Spawner.oauth_client_allowed_scopes\n-# c.SimpleLocalProcessSpawner.oauth_client_allowed_scopes = traitlets.Undefined\n-\n-## Allowed roles for oauth tokens.\n-# See also: Spawner.oauth_roles\n-# c.SimpleLocalProcessSpawner.oauth_roles = traitlets.Undefined\n-\n-## \n-# See also: Spawner.options_form\n-# c.SimpleLocalProcessSpawner.options_form = traitlets.Undefined\n-\n-## \n-# See also: Spawner.options_from_form\n-# c.SimpleLocalProcessSpawner.options_from_form = traitlets.Undefined\n-\n-## \n-# See also: Spawner.poll_interval\n-# c.SimpleLocalProcessSpawner.poll_interval = 30\n-\n-## \n-# See also: Spawner.poll_jitter\n-# c.SimpleLocalProcessSpawner.poll_jitter = 0.1\n-\n-## Extra keyword arguments to pass to Popen\n-# See also: LocalProcessSpawner.popen_kwargs\n-# c.SimpleLocalProcessSpawner.popen_kwargs = {}\n-\n-## \n-# See also: Spawner.port\n-# c.SimpleLocalProcessSpawner.port = 0\n-\n-## \n-# See also: Spawner.post_stop_hook\n-# c.SimpleLocalProcessSpawner.post_stop_hook = None\n-\n-## \n-# See also: Spawner.pre_spawn_hook\n-# c.SimpleLocalProcessSpawner.pre_spawn_hook = None\n-\n-## \n-# See also: Spawner.progress_ready_hook\n-# c.SimpleLocalProcessSpawner.progress_ready_hook = None\n-\n-## The list of scopes to request for $JUPYTERHUB_API_TOKEN\n-# See also: Spawner.server_token_scopes\n-# c.SimpleLocalProcessSpawner.server_token_scopes = traitlets.Undefined\n-\n-## Specify a shell command to launch.\n-# See also: LocalProcessSpawner.shell_cmd\n-# c.SimpleLocalProcessSpawner.shell_cmd = []\n-\n-## List of SSL alt names\n-# See also: Spawner.ssl_alt_names\n-# c.SimpleLocalProcessSpawner.ssl_alt_names = []\n-\n-## Whether to include `DNS:localhost`, `IP:127.0.0.1` in alt names\n-# See also: Spawner.ssl_alt_names_include_local\n-# c.SimpleLocalProcessSpawner.ssl_alt_names_include_local = True\n-\n-## \n-# See also: Spawner.start_timeout\n-# c.SimpleLocalProcessSpawner.start_timeout = 60\n-\n-## \n-# See also: LocalProcessSpawner.term_timeout\n-# c.SimpleLocalProcessSpawner.term_timeout = 5\n+# Checks for local users, and can attempt to create them if they exist.\n \n-#------------------------------------------------------------------------------\n-# DummyAuthenticator(Authenticator) configuration\n-#------------------------------------------------------------------------------\n-## Dummy Authenticator for testing\n+## The command to use for creating users as a list of strings\n # \n-# By default, any username + password is allowed If a non-empty password is set,\n-# any username will be allowed if it logs in with that password.\n+# For each element in the list, the string USERNAME will be replaced with the\n+# user's username. The username will also be appended as the final argument.\n # \n-# .. versionadded:: 1.0\n+# For Linux, the default value is:\n # \n-# .. versionadded:: 5.0\n-# `allow_all` defaults to True,\n-# preserving default behavior.\n+# ['adduser', '-q', '--gecos', '\"\"', '--disabled-password']\n+# \n+# To specify a custom home directory, set this to:\n+# \n+# ['adduser', '-q', '--gecos', '\"\"', '--home', '/customhome/USERNAME', '--\n+# disabled-password']\n+# \n+# This will run the command:\n+# \n+# adduser -q --gecos \"\" --home /customhome/river --disabled-password river\n+# \n+# when the user 'river' is created.\n+# Default: []\n+# c.LocalAuthenticator.add_user_cmd = []\n \n ## \n # See also: Authenticator.admin_users\n-# c.DummyAuthenticator.admin_users = set()\n+# c.LocalAuthenticator.admin_users = set()\n \n ## \n # See also: Authenticator.allow_all\n-# c.DummyAuthenticator.allow_all = False\n+# c.LocalAuthenticator.allow_all = False\n \n ## \n # See also: Authenticator.allow_existing_users\n-# c.DummyAuthenticator.allow_existing_users = False\n+# c.LocalAuthenticator.allow_existing_users = False\n+\n+## Allow login from all users in these UNIX groups.\n+# \n+# .. versionchanged:: 5.0\n+# `allowed_groups` may be specified together with allowed_users,\n+# to grant access by group OR name.\n+# Default: set()\n+# c.LocalAuthenticator.allowed_groups = set()\n \n ## \n # See also: Authenticator.allowed_users\n-# c.DummyAuthenticator.allowed_users = set()\n+# c.LocalAuthenticator.allowed_users = set()\n \n ## Is there any allow config?\n # See also: Authenticator.any_allow_config\n-# c.DummyAuthenticator.any_allow_config = False\n+# c.LocalAuthenticator.any_allow_config = False\n \n ## The max age (in seconds) of authentication info\n # See also: Authenticator.auth_refresh_age\n-# c.DummyAuthenticator.auth_refresh_age = 300\n+# c.LocalAuthenticator.auth_refresh_age = 300\n \n ## Automatically begin the login process\n # See also: Authenticator.auto_login\n-# c.DummyAuthenticator.auto_login = False\n+# c.LocalAuthenticator.auto_login = False\n \n ## \n # See also: Authenticator.auto_login_oauth2_authorize\n-# c.DummyAuthenticator.auto_login_oauth2_authorize = False\n+# c.LocalAuthenticator.auto_login_oauth2_authorize = False\n \n ## \n # See also: Authenticator.blocked_users\n-# c.DummyAuthenticator.blocked_users = set()\n+# c.LocalAuthenticator.blocked_users = set()\n+\n+## If set to True, will attempt to create local system users if they do not exist\n+# already.\n+# \n+# Supports Linux and BSD variants only.\n+# Default: False\n+# c.LocalAuthenticator.create_system_users = False\n \n ## Delete any users from the database that do not pass validation\n # See also: Authenticator.delete_invalid_users\n-# c.DummyAuthenticator.delete_invalid_users = False\n+# c.LocalAuthenticator.delete_invalid_users = False\n \n ## Enable persisting auth_state (if available).\n # See also: Authenticator.enable_auth_state\n-# c.DummyAuthenticator.enable_auth_state = False\n+# c.LocalAuthenticator.enable_auth_state = False\n+\n+## DEPRECATED: use allowed_groups\n+# Default: set()\n+# c.LocalAuthenticator.group_whitelist = set()\n \n ## Let authenticator manage user groups\n # See also: Authenticator.manage_groups\n-# c.DummyAuthenticator.manage_groups = False\n+# c.LocalAuthenticator.manage_groups = False\n \n ## Let authenticator manage roles\n # See also: Authenticator.manage_roles\n-# c.DummyAuthenticator.manage_roles = False\n+# c.LocalAuthenticator.manage_roles = False\n \n ## \n # See also: Authenticator.otp_prompt\n-# c.DummyAuthenticator.otp_prompt = 'OTP:'\n-\n-## Set a global password for all users wanting to log in.\n-# \n-# This allows users with any username to log in with the same static password.\n-# Default: ''\n-# c.DummyAuthenticator.password = ''\n+# c.LocalAuthenticator.otp_prompt = 'OTP:'\n \n ## \n # See also: Authenticator.post_auth_hook\n-# c.DummyAuthenticator.post_auth_hook = None\n+# c.LocalAuthenticator.post_auth_hook = None\n \n ## Force refresh of auth prior to spawn.\n # See also: Authenticator.refresh_pre_spawn\n-# c.DummyAuthenticator.refresh_pre_spawn = False\n+# c.LocalAuthenticator.refresh_pre_spawn = False\n \n ## \n # See also: Authenticator.request_otp\n-# c.DummyAuthenticator.request_otp = False\n+# c.LocalAuthenticator.request_otp = False\n \n ## Reset managed roles to result of `load_managed_roles()` on startup.\n # See also: Authenticator.reset_managed_roles_on_startup\n-# c.DummyAuthenticator.reset_managed_roles_on_startup = False\n+# c.LocalAuthenticator.reset_managed_roles_on_startup = False\n+\n+## Dictionary of uids to use at user creation time. This helps ensure that users\n+# created from the database get the same uid each time they are created in\n+# temporary deployments or containers.\n+# Default: {}\n+# c.LocalAuthenticator.uids = {}\n \n ## Dictionary mapping authenticator usernames to JupyterHub users.\n # See also: Authenticator.username_map\n-# c.DummyAuthenticator.username_map = {}\n+# c.LocalAuthenticator.username_map = {}\n \n ## \n # See also: Authenticator.username_pattern\n-# c.DummyAuthenticator.username_pattern = ''\n+# c.LocalAuthenticator.username_pattern = ''\n \n ## Deprecated, use `Authenticator.allowed_users`\n # See also: Authenticator.whitelist\n-# c.DummyAuthenticator.whitelist = set()\n+# c.LocalAuthenticator.whitelist = set()\n \n #------------------------------------------------------------------------------\n-# NullAuthenticator(Authenticator) configuration\n+# PAMAuthenticator(LocalAuthenticator) configuration\n #------------------------------------------------------------------------------\n-## Null Authenticator for JupyterHub\n+## Authenticate local UNIX users with PAM\n+\n+## \n+# See also: LocalAuthenticator.add_user_cmd\n+# c.PAMAuthenticator.add_user_cmd = []\n+\n+## Authoritative list of user groups that determine admin access. Users not in\n+# these groups can still be granted admin status through admin_users.\n # \n-# For cases where authentication should be disabled, e.g. only allowing access\n-# via API tokens.\n+# allowed/blocked rules still apply.\n # \n-# .. versionadded:: 2.0\n+# Note: As of JupyterHub 2.0, full admin rights should not be required, and more\n+# precise permissions can be managed via roles.\n+# Default: set()\n+# c.PAMAuthenticator.admin_groups = set()\n \n ## \n # See also: Authenticator.admin_users\n-# c.NullAuthenticator.admin_users = set()\n+# c.PAMAuthenticator.admin_users = set()\n \n ## \n # See also: Authenticator.allow_all\n-# c.NullAuthenticator.allow_all = False\n+# c.PAMAuthenticator.allow_all = False\n \n ## \n # See also: Authenticator.allow_existing_users\n-# c.NullAuthenticator.allow_existing_users = False\n+# c.PAMAuthenticator.allow_existing_users = False\n+\n+## \n+# See also: LocalAuthenticator.allowed_groups\n+# c.PAMAuthenticator.allowed_groups = set()\n \n ## \n # See also: Authenticator.allowed_users\n-# c.NullAuthenticator.allowed_users = set()\n+# c.PAMAuthenticator.allowed_users = set()\n \n ## Is there any allow config?\n # See also: Authenticator.any_allow_config\n-# c.NullAuthenticator.any_allow_config = False\n+# c.PAMAuthenticator.any_allow_config = False\n \n ## The max age (in seconds) of authentication info\n # See also: Authenticator.auth_refresh_age\n-# c.NullAuthenticator.auth_refresh_age = 300\n+# c.PAMAuthenticator.auth_refresh_age = 300\n+\n+## Automatically begin the login process\n+# See also: Authenticator.auto_login\n+# c.PAMAuthenticator.auto_login = False\n \n ## \n # See also: Authenticator.auto_login_oauth2_authorize\n-# c.NullAuthenticator.auto_login_oauth2_authorize = False\n+# c.PAMAuthenticator.auto_login_oauth2_authorize = False\n \n ## \n # See also: Authenticator.blocked_users\n-# c.NullAuthenticator.blocked_users = set()\n+# c.PAMAuthenticator.blocked_users = set()\n+\n+## Whether to check the user's account status via PAM during authentication.\n+# \n+# The PAM account stack performs non-authentication based account management. It\n+# is typically used to restrict/permit access to a service and this step is\n+# needed to access the host's user access control.\n+# \n+# Disabling this can be dangerous as authenticated but unauthorized users may be\n+# granted access and, therefore, arbitrary execution on the system.\n+# Default: True\n+# c.PAMAuthenticator.check_account = True\n+\n+## \n+# See also: LocalAuthenticator.create_system_users\n+# c.PAMAuthenticator.create_system_users = False\n \n ## Delete any users from the database that do not pass validation\n # See also: Authenticator.delete_invalid_users\n-# c.NullAuthenticator.delete_invalid_users = False\n+# c.PAMAuthenticator.delete_invalid_users = False\n \n ## Enable persisting auth_state (if available).\n # See also: Authenticator.enable_auth_state\n-# c.NullAuthenticator.enable_auth_state = False\n+# c.PAMAuthenticator.enable_auth_state = False\n+\n+## The text encoding to use when communicating with PAM\n+# Default: 'utf8'\n+# c.PAMAuthenticator.encoding = 'utf8'\n+\n+## Number of executor threads.\n+# \n+# PAM auth requests happen in this thread, so it is mostly waiting for the pam\n+# stack. One thread is usually enough, unless your pam stack is doing something\n+# slow like network requests\n+# Default: 4\n+# c.PAMAuthenticator.executor_threads = 4\n+\n+## DEPRECATED: use allowed_groups\n+# See also: LocalAuthenticator.group_whitelist\n+# c.PAMAuthenticator.group_whitelist = set()\n \n ## Let authenticator manage user groups\n # See also: Authenticator.manage_groups\n-# c.NullAuthenticator.manage_groups = False\n+# c.PAMAuthenticator.manage_groups = False\n \n ## Let authenticator manage roles\n # See also: Authenticator.manage_roles\n-# c.NullAuthenticator.manage_roles = False\n+# c.PAMAuthenticator.manage_roles = False\n+\n+## Whether to open a new PAM session when spawners are started.\n+# \n+# This may trigger things like mounting shared filesystems, loading credentials,\n+# etc. depending on system configuration.\n+# \n+# The lifecycle of PAM sessions is not correct, so many PAM session\n+# configurations will not work.\n+# \n+# If any errors are encountered when opening/closing PAM sessions, this is\n+# automatically set to False.\n+# \n+# .. versionchanged:: 2.2\n+# \n+# Due to longstanding problems in the session lifecycle,\n+# this is now disabled by default.\n+# You may opt-in to opening sessions by setting this to True.\n+# Default: False\n+# c.PAMAuthenticator.open_sessions = False\n \n ## \n # See also: Authenticator.otp_prompt\n-# c.NullAuthenticator.otp_prompt = 'OTP:'\n+# c.PAMAuthenticator.otp_prompt = 'OTP:'\n+\n+## Round-trip the username via PAM lookups to make sure it is unique\n+# \n+# PAM can accept multiple usernames that map to the same user, for example\n+# DOMAIN\\username in some cases. To prevent this, convert username into uid,\n+# then back to uid to normalize.\n+# Default: False\n+# c.PAMAuthenticator.pam_normalize_username = False\n \n ## \n # See also: Authenticator.post_auth_hook\n-# c.NullAuthenticator.post_auth_hook = None\n+# c.PAMAuthenticator.post_auth_hook = None\n \n ## Force refresh of auth prior to spawn.\n # See also: Authenticator.refresh_pre_spawn\n-# c.NullAuthenticator.refresh_pre_spawn = False\n+# c.PAMAuthenticator.refresh_pre_spawn = False\n \n ## \n # See also: Authenticator.request_otp\n-# c.NullAuthenticator.request_otp = False\n+# c.PAMAuthenticator.request_otp = False\n \n ## Reset managed roles to result of `load_managed_roles()` on startup.\n # See also: Authenticator.reset_managed_roles_on_startup\n-# c.NullAuthenticator.reset_managed_roles_on_startup = False\n+# c.PAMAuthenticator.reset_managed_roles_on_startup = False\n+\n+## The name of the PAM service to use for authentication\n+# Default: 'login'\n+# c.PAMAuthenticator.service = 'login'\n+\n+## \n+# See also: LocalAuthenticator.uids\n+# c.PAMAuthenticator.uids = {}\n \n ## Dictionary mapping authenticator usernames to JupyterHub users.\n # See also: Authenticator.username_map\n-# c.NullAuthenticator.username_map = {}\n+# c.PAMAuthenticator.username_map = {}\n \n ## \n # See also: Authenticator.username_pattern\n-# c.NullAuthenticator.username_pattern = ''\n+# c.PAMAuthenticator.username_pattern = ''\n \n ## Deprecated, use `Authenticator.allowed_users`\n # See also: Authenticator.whitelist\n-# c.NullAuthenticator.whitelist = set()\n+# c.PAMAuthenticator.whitelist = set()\n+\n+#------------------------------------------------------------------------------\n+# CryptKeeper(SingletonConfigurable) configuration\n+#------------------------------------------------------------------------------\n+## Encapsulate encryption configuration\n+# \n+# Use via the encryption_config singleton below.\n+\n+# Default: []\n+# c.CryptKeeper.keys = []\n+\n+## The number of threads to allocate for encryption\n+# Default: 40\n+# c.CryptKeeper.n_threads = 40\n \n #------------------------------------------------------------------------------\n # Proxy(LoggingConfigurable) configuration\n #------------------------------------------------------------------------------\n ## Base class for configurable proxies that JupyterHub can use.\n # \n # A proxy implementation should subclass this and must define the following\n@@ -2492,316 +2445,363 @@\n # c.ConfigurableHTTPProxy.pid_file = 'jupyterhub-proxy.pid'\n \n ## Should the Hub start the proxy\n # See also: Proxy.should_start\n # c.ConfigurableHTTPProxy.should_start = True\n \n #------------------------------------------------------------------------------\n-# LocalAuthenticator(Authenticator) configuration\n+# SimpleLocalProcessSpawner(LocalProcessSpawner) configuration\n #------------------------------------------------------------------------------\n-## Base class for Authenticators that work with local Linux/UNIX users\n-# \n-# Checks for local users, and can attempt to create them if they exist.\n-\n-## The command to use for creating users as a list of strings\n-# \n-# For each element in the list, the string USERNAME will be replaced with the\n-# user's username. The username will also be appended as the final argument.\n-# \n-# For Linux, the default value is:\n-# \n-# ['adduser', '-q', '--gecos', '\"\"', '--disabled-password']\n+## A version of LocalProcessSpawner that doesn't require users to exist on the\n+# system beforehand.\n # \n-# To specify a custom home directory, set this to:\n+# Only use this for testing.\n # \n-# ['adduser', '-q', '--gecos', '\"\"', '--home', '/customhome/USERNAME', '--\n-# disabled-password']\n+# Note: DO NOT USE THIS FOR PRODUCTION USE CASES! It is very insecure, and\n+# provides absolutely no isolation between different users!\n+\n+## \n+# See also: Spawner.args\n+# c.SimpleLocalProcessSpawner.args = []\n+\n+## \n+# See also: Spawner.auth_state_hook\n+# c.SimpleLocalProcessSpawner.auth_state_hook = None\n+\n+## \n+# See also: Spawner.cmd\n+# c.SimpleLocalProcessSpawner.cmd = ['jupyterhub-singleuser']\n+\n+## \n+# See also: Spawner.consecutive_failure_limit\n+# c.SimpleLocalProcessSpawner.consecutive_failure_limit = 0\n+\n+## \n+# See also: Spawner.cpu_guarantee\n+# c.SimpleLocalProcessSpawner.cpu_guarantee = None\n+\n+## \n+# See also: Spawner.cpu_limit\n+# c.SimpleLocalProcessSpawner.cpu_limit = None\n+\n+## Enable debug-logging of the single-user server\n+# See also: Spawner.debug\n+# c.SimpleLocalProcessSpawner.debug = False\n+\n+## \n+# See also: Spawner.default_url\n+# c.SimpleLocalProcessSpawner.default_url = ''\n+\n+## \n+# See also: Spawner.disable_user_config\n+# c.SimpleLocalProcessSpawner.disable_user_config = False\n+\n+## \n+# See also: Spawner.env_keep\n+# c.SimpleLocalProcessSpawner.env_keep = ['JUPYTERHUB_SINGLEUSER_APP']\n+\n+## \n+# See also: Spawner.environment\n+# c.SimpleLocalProcessSpawner.environment = {}\n+\n+## \n+# See also: Spawner.group_overrides\n+# c.SimpleLocalProcessSpawner.group_overrides = traitlets.Undefined\n+\n+## Template to expand to set the user home. {username} is expanded to the\n+# jupyterhub username.\n+# Default: '/tmp/{username}'\n+# c.SimpleLocalProcessSpawner.home_dir_template = '/tmp/{username}'\n+\n+## \n+# See also: Spawner.http_timeout\n+# c.SimpleLocalProcessSpawner.http_timeout = 30\n+\n+## \n+# See also: Spawner.hub_connect_url\n+# c.SimpleLocalProcessSpawner.hub_connect_url = None\n+\n+## \n+# See also: LocalProcessSpawner.interrupt_timeout\n+# c.SimpleLocalProcessSpawner.interrupt_timeout = 10\n+\n+## \n+# See also: Spawner.ip\n+# c.SimpleLocalProcessSpawner.ip = '127.0.0.1'\n+\n+## \n+# See also: LocalProcessSpawner.kill_timeout\n+# c.SimpleLocalProcessSpawner.kill_timeout = 5\n+\n+## \n+# See also: Spawner.mem_guarantee\n+# c.SimpleLocalProcessSpawner.mem_guarantee = None\n+\n+## \n+# See also: Spawner.mem_limit\n+# c.SimpleLocalProcessSpawner.mem_limit = None\n+\n+## \n+# See also: Spawner.notebook_dir\n+# c.SimpleLocalProcessSpawner.notebook_dir = ''\n+\n+## Allowed scopes for oauth tokens issued by this server's oauth client.\n+# See also: Spawner.oauth_client_allowed_scopes\n+# c.SimpleLocalProcessSpawner.oauth_client_allowed_scopes = traitlets.Undefined\n+\n+## Allowed roles for oauth tokens.\n+# See also: Spawner.oauth_roles\n+# c.SimpleLocalProcessSpawner.oauth_roles = traitlets.Undefined\n+\n+## \n+# See also: Spawner.options_form\n+# c.SimpleLocalProcessSpawner.options_form = traitlets.Undefined\n+\n+## \n+# See also: Spawner.options_from_form\n+# c.SimpleLocalProcessSpawner.options_from_form = traitlets.Undefined\n+\n+## \n+# See also: Spawner.poll_interval\n+# c.SimpleLocalProcessSpawner.poll_interval = 30\n+\n+## \n+# See also: Spawner.poll_jitter\n+# c.SimpleLocalProcessSpawner.poll_jitter = 0.1\n+\n+## Extra keyword arguments to pass to Popen\n+# See also: LocalProcessSpawner.popen_kwargs\n+# c.SimpleLocalProcessSpawner.popen_kwargs = {}\n+\n+## \n+# See also: Spawner.port\n+# c.SimpleLocalProcessSpawner.port = 0\n+\n+## \n+# See also: Spawner.post_stop_hook\n+# c.SimpleLocalProcessSpawner.post_stop_hook = None\n+\n+## \n+# See also: Spawner.pre_spawn_hook\n+# c.SimpleLocalProcessSpawner.pre_spawn_hook = None\n+\n+## \n+# See also: Spawner.progress_ready_hook\n+# c.SimpleLocalProcessSpawner.progress_ready_hook = None\n+\n+## The list of scopes to request for $JUPYTERHUB_API_TOKEN\n+# See also: Spawner.server_token_scopes\n+# c.SimpleLocalProcessSpawner.server_token_scopes = traitlets.Undefined\n+\n+## Specify a shell command to launch.\n+# See also: LocalProcessSpawner.shell_cmd\n+# c.SimpleLocalProcessSpawner.shell_cmd = []\n+\n+## List of SSL alt names\n+# See also: Spawner.ssl_alt_names\n+# c.SimpleLocalProcessSpawner.ssl_alt_names = []\n+\n+## Whether to include `DNS:localhost`, `IP:127.0.0.1` in alt names\n+# See also: Spawner.ssl_alt_names_include_local\n+# c.SimpleLocalProcessSpawner.ssl_alt_names_include_local = True\n+\n+## \n+# See also: Spawner.start_timeout\n+# c.SimpleLocalProcessSpawner.start_timeout = 60\n+\n+## \n+# See also: LocalProcessSpawner.term_timeout\n+# c.SimpleLocalProcessSpawner.term_timeout = 5\n+\n+#------------------------------------------------------------------------------\n+# DummyAuthenticator(Authenticator) configuration\n+#------------------------------------------------------------------------------\n+## Dummy Authenticator for testing\n # \n-# This will run the command:\n+# By default, any username + password is allowed If a non-empty password is set,\n+# any username will be allowed if it logs in with that password.\n # \n-# adduser -q --gecos \"\" --home /customhome/river --disabled-password river\n+# .. versionadded:: 1.0\n # \n-# when the user 'river' is created.\n-# Default: []\n-# c.LocalAuthenticator.add_user_cmd = []\n+# .. versionadded:: 5.0\n+# `allow_all` defaults to True,\n+# preserving default behavior.\n \n ## \n # See also: Authenticator.admin_users\n-# c.LocalAuthenticator.admin_users = set()\n+# c.DummyAuthenticator.admin_users = set()\n \n ## \n # See also: Authenticator.allow_all\n-# c.LocalAuthenticator.allow_all = False\n+# c.DummyAuthenticator.allow_all = False\n \n ## \n # See also: Authenticator.allow_existing_users\n-# c.LocalAuthenticator.allow_existing_users = False\n-\n-## Allow login from all users in these UNIX groups.\n-# \n-# .. versionchanged:: 5.0\n-# `allowed_groups` may be specified together with allowed_users,\n-# to grant access by group OR name.\n-# Default: set()\n-# c.LocalAuthenticator.allowed_groups = set()\n+# c.DummyAuthenticator.allow_existing_users = False\n \n ## \n # See also: Authenticator.allowed_users\n-# c.LocalAuthenticator.allowed_users = set()\n+# c.DummyAuthenticator.allowed_users = set()\n \n ## Is there any allow config?\n # See also: Authenticator.any_allow_config\n-# c.LocalAuthenticator.any_allow_config = False\n+# c.DummyAuthenticator.any_allow_config = False\n \n ## The max age (in seconds) of authentication info\n # See also: Authenticator.auth_refresh_age\n-# c.LocalAuthenticator.auth_refresh_age = 300\n+# c.DummyAuthenticator.auth_refresh_age = 300\n \n ## Automatically begin the login process\n # See also: Authenticator.auto_login\n-# c.LocalAuthenticator.auto_login = False\n+# c.DummyAuthenticator.auto_login = False\n \n ## \n # See also: Authenticator.auto_login_oauth2_authorize\n-# c.LocalAuthenticator.auto_login_oauth2_authorize = False\n+# c.DummyAuthenticator.auto_login_oauth2_authorize = False\n \n ## \n # See also: Authenticator.blocked_users\n-# c.LocalAuthenticator.blocked_users = set()\n-\n-## If set to True, will attempt to create local system users if they do not exist\n-# already.\n-# \n-# Supports Linux and BSD variants only.\n-# Default: False\n-# c.LocalAuthenticator.create_system_users = False\n+# c.DummyAuthenticator.blocked_users = set()\n \n ## Delete any users from the database that do not pass validation\n # See also: Authenticator.delete_invalid_users\n-# c.LocalAuthenticator.delete_invalid_users = False\n+# c.DummyAuthenticator.delete_invalid_users = False\n \n ## Enable persisting auth_state (if available).\n # See also: Authenticator.enable_auth_state\n-# c.LocalAuthenticator.enable_auth_state = False\n-\n-## DEPRECATED: use allowed_groups\n-# Default: set()\n-# c.LocalAuthenticator.group_whitelist = set()\n+# c.DummyAuthenticator.enable_auth_state = False\n \n ## Let authenticator manage user groups\n # See also: Authenticator.manage_groups\n-# c.LocalAuthenticator.manage_groups = False\n+# c.DummyAuthenticator.manage_groups = False\n \n ## Let authenticator manage roles\n # See also: Authenticator.manage_roles\n-# c.LocalAuthenticator.manage_roles = False\n+# c.DummyAuthenticator.manage_roles = False\n \n ## \n # See also: Authenticator.otp_prompt\n-# c.LocalAuthenticator.otp_prompt = 'OTP:'\n+# c.DummyAuthenticator.otp_prompt = 'OTP:'\n+\n+## Set a global password for all users wanting to log in.\n+# \n+# This allows users with any username to log in with the same static password.\n+# Default: ''\n+# c.DummyAuthenticator.password = ''\n \n ## \n # See also: Authenticator.post_auth_hook\n-# c.LocalAuthenticator.post_auth_hook = None\n+# c.DummyAuthenticator.post_auth_hook = None\n \n ## Force refresh of auth prior to spawn.\n # See also: Authenticator.refresh_pre_spawn\n-# c.LocalAuthenticator.refresh_pre_spawn = False\n+# c.DummyAuthenticator.refresh_pre_spawn = False\n \n ## \n # See also: Authenticator.request_otp\n-# c.LocalAuthenticator.request_otp = False\n+# c.DummyAuthenticator.request_otp = False\n \n ## Reset managed roles to result of `load_managed_roles()` on startup.\n # See also: Authenticator.reset_managed_roles_on_startup\n-# c.LocalAuthenticator.reset_managed_roles_on_startup = False\n-\n-## Dictionary of uids to use at user creation time. This helps ensure that users\n-# created from the database get the same uid each time they are created in\n-# temporary deployments or containers.\n-# Default: {}\n-# c.LocalAuthenticator.uids = {}\n+# c.DummyAuthenticator.reset_managed_roles_on_startup = False\n \n ## Dictionary mapping authenticator usernames to JupyterHub users.\n # See also: Authenticator.username_map\n-# c.LocalAuthenticator.username_map = {}\n+# c.DummyAuthenticator.username_map = {}\n \n ## \n # See also: Authenticator.username_pattern\n-# c.LocalAuthenticator.username_pattern = ''\n+# c.DummyAuthenticator.username_pattern = ''\n \n ## Deprecated, use `Authenticator.allowed_users`\n # See also: Authenticator.whitelist\n-# c.LocalAuthenticator.whitelist = set()\n+# c.DummyAuthenticator.whitelist = set()\n \n #------------------------------------------------------------------------------\n-# PAMAuthenticator(LocalAuthenticator) configuration\n+# NullAuthenticator(Authenticator) configuration\n #------------------------------------------------------------------------------\n-## Authenticate local UNIX users with PAM\n-\n-## \n-# See also: LocalAuthenticator.add_user_cmd\n-# c.PAMAuthenticator.add_user_cmd = []\n-\n-## Authoritative list of user groups that determine admin access. Users not in\n-# these groups can still be granted admin status through admin_users.\n+## Null Authenticator for JupyterHub\n # \n-# allowed/blocked rules still apply.\n+# For cases where authentication should be disabled, e.g. only allowing access\n+# via API tokens.\n # \n-# Note: As of JupyterHub 2.0, full admin rights should not be required, and more\n-# precise permissions can be managed via roles.\n-# Default: set()\n-# c.PAMAuthenticator.admin_groups = set()\n+# .. versionadded:: 2.0\n \n ## \n # See also: Authenticator.admin_users\n-# c.PAMAuthenticator.admin_users = set()\n+# c.NullAuthenticator.admin_users = set()\n \n ## \n # See also: Authenticator.allow_all\n-# c.PAMAuthenticator.allow_all = False\n+# c.NullAuthenticator.allow_all = False\n \n ## \n # See also: Authenticator.allow_existing_users\n-# c.PAMAuthenticator.allow_existing_users = False\n-\n-## \n-# See also: LocalAuthenticator.allowed_groups\n-# c.PAMAuthenticator.allowed_groups = set()\n+# c.NullAuthenticator.allow_existing_users = False\n \n ## \n # See also: Authenticator.allowed_users\n-# c.PAMAuthenticator.allowed_users = set()\n+# c.NullAuthenticator.allowed_users = set()\n \n ## Is there any allow config?\n # See also: Authenticator.any_allow_config\n-# c.PAMAuthenticator.any_allow_config = False\n+# c.NullAuthenticator.any_allow_config = False\n \n ## The max age (in seconds) of authentication info\n # See also: Authenticator.auth_refresh_age\n-# c.PAMAuthenticator.auth_refresh_age = 300\n-\n-## Automatically begin the login process\n-# See also: Authenticator.auto_login\n-# c.PAMAuthenticator.auto_login = False\n+# c.NullAuthenticator.auth_refresh_age = 300\n \n ## \n # See also: Authenticator.auto_login_oauth2_authorize\n-# c.PAMAuthenticator.auto_login_oauth2_authorize = False\n+# c.NullAuthenticator.auto_login_oauth2_authorize = False\n \n ## \n # See also: Authenticator.blocked_users\n-# c.PAMAuthenticator.blocked_users = set()\n-\n-## Whether to check the user's account status via PAM during authentication.\n-# \n-# The PAM account stack performs non-authentication based account management. It\n-# is typically used to restrict/permit access to a service and this step is\n-# needed to access the host's user access control.\n-# \n-# Disabling this can be dangerous as authenticated but unauthorized users may be\n-# granted access and, therefore, arbitrary execution on the system.\n-# Default: True\n-# c.PAMAuthenticator.check_account = True\n-\n-## \n-# See also: LocalAuthenticator.create_system_users\n-# c.PAMAuthenticator.create_system_users = False\n+# c.NullAuthenticator.blocked_users = set()\n \n ## Delete any users from the database that do not pass validation\n # See also: Authenticator.delete_invalid_users\n-# c.PAMAuthenticator.delete_invalid_users = False\n+# c.NullAuthenticator.delete_invalid_users = False\n \n ## Enable persisting auth_state (if available).\n # See also: Authenticator.enable_auth_state\n-# c.PAMAuthenticator.enable_auth_state = False\n-\n-## The text encoding to use when communicating with PAM\n-# Default: 'utf8'\n-# c.PAMAuthenticator.encoding = 'utf8'\n-\n-## Number of executor threads.\n-# \n-# PAM auth requests happen in this thread, so it is mostly waiting for the pam\n-# stack. One thread is usually enough, unless your pam stack is doing something\n-# slow like network requests\n-# Default: 4\n-# c.PAMAuthenticator.executor_threads = 4\n-\n-## DEPRECATED: use allowed_groups\n-# See also: LocalAuthenticator.group_whitelist\n-# c.PAMAuthenticator.group_whitelist = set()\n+# c.NullAuthenticator.enable_auth_state = False\n \n ## Let authenticator manage user groups\n # See also: Authenticator.manage_groups\n-# c.PAMAuthenticator.manage_groups = False\n+# c.NullAuthenticator.manage_groups = False\n \n ## Let authenticator manage roles\n # See also: Authenticator.manage_roles\n-# c.PAMAuthenticator.manage_roles = False\n-\n-## Whether to open a new PAM session when spawners are started.\n-# \n-# This may trigger things like mounting shared filesystems, loading credentials,\n-# etc. depending on system configuration.\n-# \n-# The lifecycle of PAM sessions is not correct, so many PAM session\n-# configurations will not work.\n-# \n-# If any errors are encountered when opening/closing PAM sessions, this is\n-# automatically set to False.\n-# \n-# .. versionchanged:: 2.2\n-# \n-# Due to longstanding problems in the session lifecycle,\n-# this is now disabled by default.\n-# You may opt-in to opening sessions by setting this to True.\n-# Default: False\n-# c.PAMAuthenticator.open_sessions = False\n+# c.NullAuthenticator.manage_roles = False\n \n ## \n # See also: Authenticator.otp_prompt\n-# c.PAMAuthenticator.otp_prompt = 'OTP:'\n-\n-## Round-trip the username via PAM lookups to make sure it is unique\n-# \n-# PAM can accept multiple usernames that map to the same user, for example\n-# DOMAIN\\username in some cases. To prevent this, convert username into uid,\n-# then back to uid to normalize.\n-# Default: False\n-# c.PAMAuthenticator.pam_normalize_username = False\n+# c.NullAuthenticator.otp_prompt = 'OTP:'\n \n ## \n # See also: Authenticator.post_auth_hook\n-# c.PAMAuthenticator.post_auth_hook = None\n+# c.NullAuthenticator.post_auth_hook = None\n \n ## Force refresh of auth prior to spawn.\n # See also: Authenticator.refresh_pre_spawn\n-# c.PAMAuthenticator.refresh_pre_spawn = False\n+# c.NullAuthenticator.refresh_pre_spawn = False\n \n ## \n # See also: Authenticator.request_otp\n-# c.PAMAuthenticator.request_otp = False\n+# c.NullAuthenticator.request_otp = False\n \n ## Reset managed roles to result of `load_managed_roles()` on startup.\n # See also: Authenticator.reset_managed_roles_on_startup\n-# c.PAMAuthenticator.reset_managed_roles_on_startup = False\n-\n-## The name of the PAM service to use for authentication\n-# Default: 'login'\n-# c.PAMAuthenticator.service = 'login'\n-\n-## \n-# See also: LocalAuthenticator.uids\n-# c.PAMAuthenticator.uids = {}\n+# c.NullAuthenticator.reset_managed_roles_on_startup = False\n \n ## Dictionary mapping authenticator usernames to JupyterHub users.\n # See also: Authenticator.username_map\n-# c.PAMAuthenticator.username_map = {}\n+# c.NullAuthenticator.username_map = {}\n \n ## \n # See also: Authenticator.username_pattern\n-# c.PAMAuthenticator.username_pattern = ''\n+# c.NullAuthenticator.username_pattern = ''\n \n ## Deprecated, use `Authenticator.allowed_users`\n # See also: Authenticator.whitelist\n-# c.PAMAuthenticator.whitelist = set()\n+# c.NullAuthenticator.whitelist = set()\n"}]}]}]}]}