{"diffoscope-json-version": 1, "source1": "/srv/reproducible-results/rbuild-debian/r-b-build.5xyrf6YO/b1/jupyterhub_5.2.1+ds1-4_arm64.changes", "source2": "/srv/reproducible-results/rbuild-debian/r-b-build.5xyrf6YO/b2/jupyterhub_5.2.1+ds1-4_arm64.changes", "unified_diff": null, "details": [{"source1": "Files", "source2": "Files", "unified_diff": "@@ -1,2 +1,2 @@\n \n- e80dc2261ee3d00ee32138852b2711cb 2022500 python optional jupyterhub_5.2.1+ds1-4_all.deb\n+ fcc689bfe0499bd139f150a4794e2128 2022552 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 59496 2025-05-28 09:40:25.000000 control.tar.xz\n--rw-r--r-- 0 0 0 1962812 2025-05-28 09:40:25.000000 data.tar.xz\n+-rw-r--r-- 0 0 0 1962864 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", "comments": ["Ordering differences only"], "unified_diff": "@@ -997,14 +997,888 @@\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+# 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+# \n+# As of JupyterHub 2.0,\n+# full admin rights should not be required,\n+# and more precise permissions can be managed via roles.\n+# \n+# Caution:\n+# \n+# Adding users to `admin_users` can only *grant* admin rights,\n+# removing a username from the admin_users set **DOES NOT** remove admin rights previously granted.\n+# \n+# For an authoritative, restricted set of admins,\n+# assign explicit membership of the `admin` *role*::\n+# \n+# c.JupyterHub.load_roles = [\n+# {\n+# \"name\": \"admin\",\n+# \"users\": [\"admin1\", \"...\"],\n+# }\n+# ]\n+# \n+# Admin users can take every possible action on behalf of all users, for\n+# example:\n+# \n+# - Use the admin panel to see list of users logged in - Add / remove users in\n+# some authenticators - Restart / halt the hub - Start / stop users' single-user\n+# servers - Can access each individual users' single-user server\n+# \n+# Admin access should be treated the same way root access is.\n+# \n+# Defaults to an empty set, in which case no user has admin access.\n+# Default: set()\n+# c.Authenticator.admin_users = set()\n+\n+## Allow every user who can successfully authenticate to access JupyterHub.\n+# \n+# False by default, which means for most Authenticators, _some_ allow-related\n+# configuration is required to allow users to log in.\n+# \n+# Authenticator subclasses may override the default with e.g.::\n+# \n+# @default(\"allow_all\")\n+# def _default_allow_all(self):\n+# # if _any_ auth config (depends on the Authenticator)\n+# if self.allowed_users or self.allowed_groups or self.allow_existing_users:\n+# return False\n+# else:\n+# return True\n+# \n+# .. versionadded:: 5.0\n+# \n+# .. versionchanged:: 5.0\n+# Prior to 5.0, `allow_all` wasn't defined on its own,\n+# and was instead implicitly True when no allow config was provided,\n+# i.e. `allowed_users` unspecified or empty on the base Authenticator class.\n+# \n+# To preserve pre-5.0 behavior,\n+# set `allow_all = True` if you have no other allow configuration.\n+# Default: False\n+# c.Authenticator.allow_all = False\n+\n+## Allow existing users to login.\n+# \n+# Defaults to True if `allowed_users` is set for historical reasons, and False\n+# otherwise.\n+# \n+# With this enabled, all users present in the JupyterHub database are allowed to\n+# login. This has the effect of any user who has _previously_ been allowed to\n+# login via any means will continue to be allowed until the user is deleted via\n+# the /hub/admin page or REST API.\n+# \n+# .. warning::\n+# \n+# Before enabling this you should review the existing users in the\n+# JupyterHub admin panel at `/hub/admin`. You may find users existing\n+# there because they have previously been declared in config such as\n+# `allowed_users` or allowed to sign in.\n+# \n+# .. warning::\n+# \n+# When this is enabled and you wish to remove access for one or more\n+# users previously allowed, you must make sure that they\n+# are removed from the jupyterhub database. This can be tricky to do\n+# if you stop allowing an externally managed group of users for example.\n+# \n+# With this enabled, JupyterHub admin users can visit `/hub/admin` or use\n+# JupyterHub's REST API to add and remove users to manage who can login.\n+# \n+# .. versionadded:: 5.0\n+# Default: False\n+# c.Authenticator.allow_existing_users = False\n+\n+## Set of usernames that are allowed to log in.\n+# \n+# Use this to limit which authenticated users may login. Default behavior: only\n+# users in this set are allowed.\n+# \n+# If empty, does not perform any restriction, in which case any authenticated\n+# user is allowed.\n+# \n+# Authenticators may extend :meth:`.Authenticator.check_allowed` to combine\n+# `allowed_users` with other configuration to either expand or restrict access.\n+# \n+# .. versionchanged:: 1.2\n+# `Authenticator.whitelist` renamed to `allowed_users`\n+# Default: set()\n+# c.Authenticator.allowed_users = set()\n+\n+## Is there any allow config?\n+# \n+# Used to show a warning if it looks like nobody can access the Hub,\n+# which can happen when upgrading to JupyterHub 5,\n+# now that `allow_all` defaults to False.\n+# \n+# Deployments can set this explicitly to True to suppress\n+# the \"No allow config found\" warning.\n+# \n+# Will be True if any config tagged with `.tag(allow_config=True)`\n+# or starts with `allow` is truthy.\n+# \n+# .. versionadded:: 5.0\n+# Default: False\n+# c.Authenticator.any_allow_config = False\n+\n+## The max age (in seconds) of authentication info\n+# before forcing a refresh of user auth info.\n+# \n+# Refreshing auth info allows, e.g. requesting/re-validating auth\n+# tokens.\n+# \n+# See :meth:`.refresh_user` for what happens when user auth info is refreshed\n+# (nothing by default).\n+# Default: 300\n+# c.Authenticator.auth_refresh_age = 300\n+\n+## Automatically begin the login process\n+# \n+# rather than starting with a \"Login with...\" link at `/hub/login`\n+# \n+# To work, `.login_url()` must give a URL other than the default `/hub/login`,\n+# such as an oauth handler or another automatic login handler,\n+# registered with `.get_handlers()`.\n+# \n+# .. versionadded:: 0.8\n+# Default: False\n+# c.Authenticator.auto_login = False\n+\n+## Automatically begin login process for OAuth2 authorization requests\n+# \n+# When another application is using JupyterHub as OAuth2 provider, it sends\n+# users to `/hub/api/oauth2/authorize`. If the user isn't logged in already, and\n+# auto_login is not set, the user will be dumped on the hub's home page, without\n+# any context on what to do next.\n+# \n+# Setting this to true will automatically redirect users to login if they aren't\n+# logged in *only* on the `/hub/api/oauth2/authorize` endpoint.\n+# \n+# .. versionadded:: 1.5\n+# Default: False\n+# c.Authenticator.auto_login_oauth2_authorize = False\n+\n+## Set of usernames that are not allowed to log in.\n+# \n+# Use this with supported authenticators to restrict which users can not log in.\n+# This is an additional block list that further restricts users, beyond whatever\n+# restrictions the authenticator has in place.\n+# \n+# If empty, does not perform any additional restriction.\n+# \n+# .. versionadded: 0.9\n+# \n+# .. versionchanged:: 5.2\n+# Users blocked via `blocked_users` that may have logged in in the past\n+# have all permissions and group membership revoked\n+# and all servers stopped at JupyterHub startup.\n+# Previously, User permissions (e.g. API tokens)\n+# and servers were unaffected and required additional\n+# administrator operations to block after a user is added to `blocked_users`.\n+# \n+# .. versionchanged:: 1.2\n+# `Authenticator.blacklist` renamed to `blocked_users`\n+# Default: set()\n+# c.Authenticator.blocked_users = set()\n+\n+## Delete any users from the database that do not pass validation\n+# \n+# When JupyterHub starts, `.add_user` will be called\n+# on each user in the database to verify that all users are still valid.\n+# \n+# If `delete_invalid_users` is True,\n+# any users that do not pass validation will be deleted from the database.\n+# Use this if users might be deleted from an external system,\n+# such as local user accounts.\n+# \n+# If False (default), invalid users remain in the Hub's database\n+# and a warning will be issued.\n+# This is the default to avoid data loss due to config changes.\n+# Default: False\n+# c.Authenticator.delete_invalid_users = False\n+\n+## Enable persisting auth_state (if available).\n+# \n+# auth_state will be encrypted and stored in the Hub's database.\n+# This can include things like authentication tokens, etc.\n+# to be passed to Spawners as environment variables.\n+# \n+# Encrypting auth_state requires the cryptography package.\n+# \n+# Additionally, the JUPYTERHUB_CRYPT_KEY environment variable must\n+# contain one (or more, separated by ;) 32B encryption keys.\n+# These can be either base64 or hex-encoded.\n+# \n+# If encryption is unavailable, auth_state cannot be persisted.\n+# \n+# New in JupyterHub 0.8\n+# Default: False\n+# c.Authenticator.enable_auth_state = False\n+\n+## Let authenticator manage user groups\n+# \n+# If True, Authenticator.authenticate and/or .refresh_user\n+# may return a list of group names in the 'groups' field,\n+# which will be assigned to the user.\n+# \n+# All group-assignment APIs are disabled if this is True.\n+# Default: False\n+# c.Authenticator.manage_groups = False\n+\n+## Let authenticator manage roles\n+# \n+# If True, Authenticator.authenticate and/or .refresh_user\n+# may return a list of roles in the 'roles' field,\n+# which will be added to the database.\n+# \n+# When enabled, all role management will be handled by the\n+# authenticator; in particular, assignment of roles via\n+# `JupyterHub.load_roles` traitlet will not be possible.\n+# \n+# .. versionadded:: 5.0\n+# Default: False\n+# c.Authenticator.manage_roles = False\n+\n+## The prompt string for the extra OTP (One Time Password) field.\n+# \n+# .. versionadded:: 5.0\n+# Default: 'OTP:'\n+# c.Authenticator.otp_prompt = 'OTP:'\n+\n+## An optional hook function that you can implement to do some bootstrapping work\n+# during authentication. For example, loading user account details from an\n+# external system.\n+# \n+# This function is called after the user has passed all authentication checks\n+# and is ready to successfully authenticate. This function must return the\n+# auth_model dict reguardless of changes to it. The hook is called with 3\n+# positional arguments: `(authenticator, handler, auth_model)`.\n+# \n+# This may be a coroutine.\n+# \n+# .. versionadded: 1.0\n+# \n+# Example::\n+# \n+# import os\n+# import pwd\n+# def my_hook(authenticator, handler, auth_model):\n+# user_data = pwd.getpwnam(auth_model['name'])\n+# spawn_data = {\n+# 'pw_data': user_data\n+# 'gid_list': os.getgrouplist(auth_model['name'], user_data.pw_gid)\n+# }\n+# \n+# if auth_model['auth_state'] is None:\n+# auth_model['auth_state'] = {}\n+# auth_model['auth_state']['spawn_data'] = spawn_data\n+# \n+# return auth_model\n+# \n+# c.Authenticator.post_auth_hook = my_hook\n+# Default: None\n+# c.Authenticator.post_auth_hook = None\n+\n+## Force refresh of auth prior to spawn.\n+# \n+# This forces :meth:`.refresh_user` to be called prior to launching\n+# a server, to ensure that auth state is up-to-date.\n+# \n+# This can be important when e.g. auth tokens that may have expired\n+# are passed to the spawner via environment variables from auth_state.\n+# \n+# If refresh_user cannot refresh the user auth data,\n+# launch will fail until the user logs in again.\n+# Default: False\n+# c.Authenticator.refresh_pre_spawn = False\n+\n+## Prompt for OTP (One Time Password) in the login form.\n+# \n+# .. versionadded:: 5.0\n+# Default: False\n+# c.Authenticator.request_otp = False\n+\n+## Reset managed roles to result of `load_managed_roles()` on startup.\n+# \n+# If True:\n+# - stale managed roles will be removed,\n+# - stale assignments to managed roles will be removed.\n+# \n+# Any role not present in `load_managed_roles()` will be considered\n+# 'stale'.\n+# \n+# The 'stale' status for role assignments is also determined from\n+# `load_managed_roles()` result:\n+# \n+# - user role assignments status will depend on whether the `users` key\n+# is defined or not:\n+# \n+# * if a list is defined under the `users` key and the user is not listed, then the user role assignment will be considered 'stale',\n+# * if the `users` key is not provided, the user role assignment will be preserved;\n+# - service and group role assignments will be considered 'stale':\n+# \n+# * if not included in the `services` and `groups` list,\n+# * if the `services` and `groups` keys are not provided.\n+# \n+# .. versionadded:: 5.0\n+# Default: False\n+# c.Authenticator.reset_managed_roles_on_startup = False\n+\n+## Dictionary mapping authenticator usernames to JupyterHub users.\n+# \n+# Primarily used to normalize OAuth user names to local users.\n+# Default: {}\n+# c.Authenticator.username_map = {}\n+\n+## Regular expression pattern that all valid usernames must match.\n+# \n+# If a username does not match the pattern specified here, authentication will\n+# not be attempted.\n+# \n+# If not set, allow any username.\n+# Default: ''\n+# c.Authenticator.username_pattern = ''\n+\n+## Deprecated, use `Authenticator.allowed_users`\n+# Default: set()\n+# c.Authenticator.whitelist = set()\n+\n+#------------------------------------------------------------------------------\n+# NullAuthenticator(Authenticator) configuration\n+#------------------------------------------------------------------------------\n+## Null Authenticator for JupyterHub\n+# \n+# For cases where authentication should be disabled, e.g. only allowing access\n+# via API tokens.\n+# \n+# .. versionadded:: 2.0\n+\n+## \n+# See also: Authenticator.admin_users\n+# c.NullAuthenticator.admin_users = set()\n+\n+## \n+# See also: Authenticator.allow_all\n+# c.NullAuthenticator.allow_all = False\n+\n+## \n+# See also: Authenticator.allow_existing_users\n+# c.NullAuthenticator.allow_existing_users = False\n+\n+## \n+# See also: Authenticator.allowed_users\n+# c.NullAuthenticator.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+\n+## The max age (in seconds) of authentication info\n+# See also: Authenticator.auth_refresh_age\n+# c.NullAuthenticator.auth_refresh_age = 300\n+\n+## \n+# See also: Authenticator.auto_login_oauth2_authorize\n+# c.NullAuthenticator.auto_login_oauth2_authorize = False\n+\n+## \n+# See also: Authenticator.blocked_users\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.NullAuthenticator.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+\n+## Let authenticator manage user groups\n+# See also: Authenticator.manage_groups\n+# c.NullAuthenticator.manage_groups = False\n+\n+## Let authenticator manage roles\n+# See also: Authenticator.manage_roles\n+# c.NullAuthenticator.manage_roles = False\n+\n+## \n+# See also: Authenticator.otp_prompt\n+# c.NullAuthenticator.otp_prompt = 'OTP:'\n+\n+## \n+# See also: Authenticator.post_auth_hook\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.NullAuthenticator.refresh_pre_spawn = False\n+\n+## \n+# See also: Authenticator.request_otp\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.NullAuthenticator.reset_managed_roles_on_startup = False\n+\n+## Dictionary mapping authenticator usernames to JupyterHub users.\n+# See also: Authenticator.username_map\n+# c.NullAuthenticator.username_map = {}\n+\n+## \n+# See also: Authenticator.username_pattern\n+# c.NullAuthenticator.username_pattern = ''\n+\n+## Deprecated, use `Authenticator.allowed_users`\n+# See also: Authenticator.whitelist\n+# c.NullAuthenticator.whitelist = set()\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+# methods:\n+# \n+# - :meth:`.get_all_routes` return a dictionary of all JupyterHub-related routes\n+# - :meth:`.add_route` adds a route - :meth:`.delete_route` deletes a route\n+# \n+# In addition to these, the following method(s) may need to be implemented:\n+# \n+# - :meth:`.start` start the proxy, if it should be launched by the Hub\n+# instead of externally managed.\n+# If the proxy is externally managed, it should set :attr:`should_start` to False.\n+# - :meth:`.stop` stop the proxy. Only used if :meth:`.start` is also used.\n+# \n+# And the following method(s) are optional, but can be provided:\n+# \n+# - :meth:`.get_route` gets a single route.\n+# There is a default implementation that extracts data from :meth:`.get_all_routes`,\n+# but implementations may choose to provide a more efficient implementation\n+# of fetching a single route.\n+\n+## Additional routes to be maintained in the proxy.\n+# \n+# A dictionary with a route specification as key, and a URL as target. The hub\n+# will ensure this route is present in the proxy.\n+# \n+# If the hub is running in host based mode (with JupyterHub.subdomain_host set),\n+# the routespec *must* have a domain component (example.com/my-url/). If the hub\n+# is not running in host based mode, the routespec *must not* have a domain\n+# component (/my-url/).\n+# \n+# Helpful when the hub is running in API-only mode.\n+# Default: {}\n+# c.Proxy.extra_routes = {}\n+\n+## Should the Hub start the proxy\n+# \n+# If True, the Hub will start the proxy and stop it.\n+# Set to False if the proxy is managed externally,\n+# such as by systemd, docker, or another service manager.\n+# Default: True\n+# c.Proxy.should_start = True\n+\n+#------------------------------------------------------------------------------\n+# ConfigurableHTTPProxy(Proxy) configuration\n+#------------------------------------------------------------------------------\n+## Proxy implementation for the default configurable-http-proxy.\n+# \n+# This is the default proxy implementation for running the nodejs proxy\n+# `configurable-http-proxy`.\n+# \n+# If the proxy should not be run as a subprocess of the Hub, (e.g. in a separate\n+# container), set::\n+# \n+# c.ConfigurableHTTPProxy.should_start = False\n+\n+## The ip (or hostname) of the proxy's API endpoint\n+# Default: ''\n+# c.ConfigurableHTTPProxy.api_url = ''\n+\n+## The Proxy auth token\n+# \n+# Loaded from the CONFIGPROXY_AUTH_TOKEN env variable by default.\n+# Default: ''\n+# c.ConfigurableHTTPProxy.auth_token = ''\n+\n+## Interval (in seconds) at which to check if the proxy is running.\n+# Default: 5\n+# c.ConfigurableHTTPProxy.check_running_interval = 5\n+\n+## The command to start the proxy\n+# Default: ['configurable-http-proxy']\n+# c.ConfigurableHTTPProxy.command = ['configurable-http-proxy']\n+\n+## The number of requests allowed to be concurrently outstanding to the proxy\n+# \n+# Limiting this number avoids potential timeout errors by sending too many\n+# requests to update the proxy at once\n+# Default: 10\n+# c.ConfigurableHTTPProxy.concurrency = 10\n+\n+## Add debug-level logging to the Proxy.\n+# Default: False\n+# c.ConfigurableHTTPProxy.debug = False\n+\n+## \n+# See also: Proxy.extra_routes\n+# c.ConfigurableHTTPProxy.extra_routes = {}\n+\n+## Proxy log level\n+# Choices: any of ['debug', 'info', 'warn', 'error'] (case-insensitive)\n+# Default: 'info'\n+# c.ConfigurableHTTPProxy.log_level = 'info'\n+\n+## File in which to write the PID of the proxy process.\n+# Default: 'jupyterhub-proxy.pid'\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+# 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: 12\n+# c.CryptKeeper.n_threads = 12\n+\n+#------------------------------------------------------------------------------\n+# LocalAuthenticator(Authenticator) 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+# \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.LocalAuthenticator.admin_users = set()\n+\n+## \n+# See also: Authenticator.allow_all\n+# c.LocalAuthenticator.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+\n+## \n+# See also: Authenticator.allowed_users\n+# c.LocalAuthenticator.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+\n+## The max age (in seconds) of authentication info\n+# See also: Authenticator.auth_refresh_age\n+# c.LocalAuthenticator.auth_refresh_age = 300\n+\n+## Automatically begin the login process\n+# See also: Authenticator.auto_login\n+# c.LocalAuthenticator.auto_login = False\n+\n+## \n+# See also: Authenticator.auto_login_oauth2_authorize\n+# c.LocalAuthenticator.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+\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+\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+\n+## Let authenticator manage user groups\n+# See also: Authenticator.manage_groups\n+# c.LocalAuthenticator.manage_groups = False\n+\n+## Let authenticator manage roles\n+# See also: Authenticator.manage_roles\n+# c.LocalAuthenticator.manage_roles = False\n+\n+## \n+# See also: Authenticator.otp_prompt\n+# c.LocalAuthenticator.otp_prompt = 'OTP:'\n+\n+## \n+# See also: Authenticator.post_auth_hook\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.LocalAuthenticator.refresh_pre_spawn = False\n+\n+## \n+# See also: Authenticator.request_otp\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.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.LocalAuthenticator.username_map = {}\n+\n+## \n+# See also: Authenticator.username_pattern\n+# c.LocalAuthenticator.username_pattern = ''\n+\n+## Deprecated, use `Authenticator.allowed_users`\n+# See also: Authenticator.whitelist\n+# c.LocalAuthenticator.whitelist = set()\n+\n+#------------------------------------------------------------------------------\n+# PAMAuthenticator(LocalAuthenticator) 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+# \n+# allowed/blocked rules still apply.\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+\n+## \n+# See also: Authenticator.admin_users\n+# c.PAMAuthenticator.admin_users = set()\n+\n+## \n+# See also: Authenticator.allow_all\n+# c.PAMAuthenticator.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+\n+## \n+# See also: Authenticator.allowed_users\n+# c.PAMAuthenticator.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+\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+\n+## \n+# See also: Authenticator.auto_login_oauth2_authorize\n+# c.PAMAuthenticator.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+\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+\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+\n+## Let authenticator manage user groups\n+# See also: Authenticator.manage_groups\n+# c.PAMAuthenticator.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+\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+\n+## \n+# See also: Authenticator.post_auth_hook\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.PAMAuthenticator.refresh_pre_spawn = False\n+\n+## \n+# See also: Authenticator.request_otp\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.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.PAMAuthenticator.username_map = {}\n+\n+## \n+# See also: Authenticator.username_pattern\n+# c.PAMAuthenticator.username_pattern = ''\n+\n+## Deprecated, use `Authenticator.allowed_users`\n+# See also: Authenticator.whitelist\n+# c.PAMAuthenticator.whitelist = set()\n+\n+#------------------------------------------------------------------------------\n # Spawner(LoggingConfigurable) configuration\n #------------------------------------------------------------------------------\n ## Base class for spawning single-user notebook servers.\n # \n # Subclass this, and override the following methods:\n # \n # - load_state - get_state - start - stop - poll\n@@ -1661,485 +2535,14 @@\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-# 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: 12\n-# c.CryptKeeper.n_threads = 12\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-# \n-# As of JupyterHub 2.0,\n-# full admin rights should not be required,\n-# and more precise permissions can be managed via roles.\n-# \n-# Caution:\n-# \n-# Adding users to `admin_users` can only *grant* admin rights,\n-# removing a username from the admin_users set **DOES NOT** remove admin rights previously granted.\n-# \n-# For an authoritative, restricted set of admins,\n-# assign explicit membership of the `admin` *role*::\n-# \n-# c.JupyterHub.load_roles = [\n-# {\n-# \"name\": \"admin\",\n-# \"users\": [\"admin1\", \"...\"],\n-# }\n-# ]\n-# \n-# Admin users can take every possible action on behalf of all users, for\n-# example:\n-# \n-# - Use the admin panel to see list of users logged in - Add / remove users in\n-# some authenticators - Restart / halt the hub - Start / stop users' single-user\n-# servers - Can access each individual users' single-user server\n-# \n-# Admin access should be treated the same way root access is.\n-# \n-# Defaults to an empty set, in which case no user has admin access.\n-# Default: set()\n-# c.Authenticator.admin_users = set()\n-\n-## Allow every user who can successfully authenticate to access JupyterHub.\n-# \n-# False by default, which means for most Authenticators, _some_ allow-related\n-# configuration is required to allow users to log in.\n-# \n-# Authenticator subclasses may override the default with e.g.::\n-# \n-# @default(\"allow_all\")\n-# def _default_allow_all(self):\n-# # if _any_ auth config (depends on the Authenticator)\n-# if self.allowed_users or self.allowed_groups or self.allow_existing_users:\n-# return False\n-# else:\n-# return True\n-# \n-# .. versionadded:: 5.0\n-# \n-# .. versionchanged:: 5.0\n-# Prior to 5.0, `allow_all` wasn't defined on its own,\n-# and was instead implicitly True when no allow config was provided,\n-# i.e. `allowed_users` unspecified or empty on the base Authenticator class.\n-# \n-# To preserve pre-5.0 behavior,\n-# set `allow_all = True` if you have no other allow configuration.\n-# Default: False\n-# c.Authenticator.allow_all = False\n-\n-## Allow existing users to login.\n-# \n-# Defaults to True if `allowed_users` is set for historical reasons, and False\n-# otherwise.\n-# \n-# With this enabled, all users present in the JupyterHub database are allowed to\n-# login. This has the effect of any user who has _previously_ been allowed to\n-# login via any means will continue to be allowed until the user is deleted via\n-# the /hub/admin page or REST API.\n-# \n-# .. warning::\n-# \n-# Before enabling this you should review the existing users in the\n-# JupyterHub admin panel at `/hub/admin`. You may find users existing\n-# there because they have previously been declared in config such as\n-# `allowed_users` or allowed to sign in.\n-# \n-# .. warning::\n-# \n-# When this is enabled and you wish to remove access for one or more\n-# users previously allowed, you must make sure that they\n-# are removed from the jupyterhub database. This can be tricky to do\n-# if you stop allowing an externally managed group of users for example.\n-# \n-# With this enabled, JupyterHub admin users can visit `/hub/admin` or use\n-# JupyterHub's REST API to add and remove users to manage who can login.\n-# \n-# .. versionadded:: 5.0\n-# Default: False\n-# c.Authenticator.allow_existing_users = False\n-\n-## Set of usernames that are allowed to log in.\n-# \n-# Use this to limit which authenticated users may login. Default behavior: only\n-# users in this set are allowed.\n-# \n-# If empty, does not perform any restriction, in which case any authenticated\n-# user is allowed.\n-# \n-# Authenticators may extend :meth:`.Authenticator.check_allowed` to combine\n-# `allowed_users` with other configuration to either expand or restrict access.\n-# \n-# .. versionchanged:: 1.2\n-# `Authenticator.whitelist` renamed to `allowed_users`\n-# Default: set()\n-# c.Authenticator.allowed_users = set()\n-\n-## Is there any allow config?\n-# \n-# Used to show a warning if it looks like nobody can access the Hub,\n-# which can happen when upgrading to JupyterHub 5,\n-# now that `allow_all` defaults to False.\n-# \n-# Deployments can set this explicitly to True to suppress\n-# the \"No allow config found\" warning.\n-# \n-# Will be True if any config tagged with `.tag(allow_config=True)`\n-# or starts with `allow` is truthy.\n-# \n-# .. versionadded:: 5.0\n-# Default: False\n-# c.Authenticator.any_allow_config = False\n-\n-## The max age (in seconds) of authentication info\n-# before forcing a refresh of user auth info.\n-# \n-# Refreshing auth info allows, e.g. requesting/re-validating auth\n-# tokens.\n-# \n-# See :meth:`.refresh_user` for what happens when user auth info is refreshed\n-# (nothing by default).\n-# Default: 300\n-# c.Authenticator.auth_refresh_age = 300\n-\n-## Automatically begin the login process\n-# \n-# rather than starting with a \"Login with...\" link at `/hub/login`\n-# \n-# To work, `.login_url()` must give a URL other than the default `/hub/login`,\n-# such as an oauth handler or another automatic login handler,\n-# registered with `.get_handlers()`.\n-# \n-# .. versionadded:: 0.8\n-# Default: False\n-# c.Authenticator.auto_login = False\n-\n-## Automatically begin login process for OAuth2 authorization requests\n-# \n-# When another application is using JupyterHub as OAuth2 provider, it sends\n-# users to `/hub/api/oauth2/authorize`. If the user isn't logged in already, and\n-# auto_login is not set, the user will be dumped on the hub's home page, without\n-# any context on what to do next.\n-# \n-# Setting this to true will automatically redirect users to login if they aren't\n-# logged in *only* on the `/hub/api/oauth2/authorize` endpoint.\n-# \n-# .. versionadded:: 1.5\n-# Default: False\n-# c.Authenticator.auto_login_oauth2_authorize = False\n-\n-## Set of usernames that are not allowed to log in.\n-# \n-# Use this with supported authenticators to restrict which users can not log in.\n-# This is an additional block list that further restricts users, beyond whatever\n-# restrictions the authenticator has in place.\n-# \n-# If empty, does not perform any additional restriction.\n-# \n-# .. versionadded: 0.9\n-# \n-# .. versionchanged:: 5.2\n-# Users blocked via `blocked_users` that may have logged in in the past\n-# have all permissions and group membership revoked\n-# and all servers stopped at JupyterHub startup.\n-# Previously, User permissions (e.g. API tokens)\n-# and servers were unaffected and required additional\n-# administrator operations to block after a user is added to `blocked_users`.\n-# \n-# .. versionchanged:: 1.2\n-# `Authenticator.blacklist` renamed to `blocked_users`\n-# Default: set()\n-# c.Authenticator.blocked_users = set()\n-\n-## Delete any users from the database that do not pass validation\n-# \n-# When JupyterHub starts, `.add_user` will be called\n-# on each user in the database to verify that all users are still valid.\n-# \n-# If `delete_invalid_users` is True,\n-# any users that do not pass validation will be deleted from the database.\n-# Use this if users might be deleted from an external system,\n-# such as local user accounts.\n-# \n-# If False (default), invalid users remain in the Hub's database\n-# and a warning will be issued.\n-# This is the default to avoid data loss due to config changes.\n-# Default: False\n-# c.Authenticator.delete_invalid_users = False\n-\n-## Enable persisting auth_state (if available).\n-# \n-# auth_state will be encrypted and stored in the Hub's database.\n-# This can include things like authentication tokens, etc.\n-# to be passed to Spawners as environment variables.\n-# \n-# Encrypting auth_state requires the cryptography package.\n-# \n-# Additionally, the JUPYTERHUB_CRYPT_KEY environment variable must\n-# contain one (or more, separated by ;) 32B encryption keys.\n-# These can be either base64 or hex-encoded.\n-# \n-# If encryption is unavailable, auth_state cannot be persisted.\n-# \n-# New in JupyterHub 0.8\n-# Default: False\n-# c.Authenticator.enable_auth_state = False\n-\n-## Let authenticator manage user groups\n-# \n-# If True, Authenticator.authenticate and/or .refresh_user\n-# may return a list of group names in the 'groups' field,\n-# which will be assigned to the user.\n-# \n-# All group-assignment APIs are disabled if this is True.\n-# Default: False\n-# c.Authenticator.manage_groups = False\n-\n-## Let authenticator manage roles\n-# \n-# If True, Authenticator.authenticate and/or .refresh_user\n-# may return a list of roles in the 'roles' field,\n-# which will be added to the database.\n-# \n-# When enabled, all role management will be handled by the\n-# authenticator; in particular, assignment of roles via\n-# `JupyterHub.load_roles` traitlet will not be possible.\n-# \n-# .. versionadded:: 5.0\n-# Default: False\n-# c.Authenticator.manage_roles = False\n-\n-## The prompt string for the extra OTP (One Time Password) field.\n-# \n-# .. versionadded:: 5.0\n-# Default: 'OTP:'\n-# c.Authenticator.otp_prompt = 'OTP:'\n-\n-## An optional hook function that you can implement to do some bootstrapping work\n-# during authentication. For example, loading user account details from an\n-# external system.\n-# \n-# This function is called after the user has passed all authentication checks\n-# and is ready to successfully authenticate. This function must return the\n-# auth_model dict reguardless of changes to it. The hook is called with 3\n-# positional arguments: `(authenticator, handler, auth_model)`.\n-# \n-# This may be a coroutine.\n-# \n-# .. versionadded: 1.0\n-# \n-# Example::\n-# \n-# import os\n-# import pwd\n-# def my_hook(authenticator, handler, auth_model):\n-# user_data = pwd.getpwnam(auth_model['name'])\n-# spawn_data = {\n-# 'pw_data': user_data\n-# 'gid_list': os.getgrouplist(auth_model['name'], user_data.pw_gid)\n-# }\n-# \n-# if auth_model['auth_state'] is None:\n-# auth_model['auth_state'] = {}\n-# auth_model['auth_state']['spawn_data'] = spawn_data\n-# \n-# return auth_model\n-# \n-# c.Authenticator.post_auth_hook = my_hook\n-# Default: None\n-# c.Authenticator.post_auth_hook = None\n-\n-## Force refresh of auth prior to spawn.\n-# \n-# This forces :meth:`.refresh_user` to be called prior to launching\n-# a server, to ensure that auth state is up-to-date.\n-# \n-# This can be important when e.g. auth tokens that may have expired\n-# are passed to the spawner via environment variables from auth_state.\n-# \n-# If refresh_user cannot refresh the user auth data,\n-# launch will fail until the user logs in again.\n-# Default: False\n-# c.Authenticator.refresh_pre_spawn = False\n-\n-## Prompt for OTP (One Time Password) in the login form.\n-# \n-# .. versionadded:: 5.0\n-# Default: False\n-# c.Authenticator.request_otp = False\n-\n-## Reset managed roles to result of `load_managed_roles()` on startup.\n-# \n-# If True:\n-# - stale managed roles will be removed,\n-# - stale assignments to managed roles will be removed.\n-# \n-# Any role not present in `load_managed_roles()` will be considered\n-# 'stale'.\n-# \n-# The 'stale' status for role assignments is also determined from\n-# `load_managed_roles()` result:\n-# \n-# - user role assignments status will depend on whether the `users` key\n-# is defined or not:\n-# \n-# * if a list is defined under the `users` key and the user is not listed, then the user role assignment will be considered 'stale',\n-# * if the `users` key is not provided, the user role assignment will be preserved;\n-# - service and group role assignments will be considered 'stale':\n-# \n-# * if not included in the `services` and `groups` list,\n-# * if the `services` and `groups` keys are not provided.\n-# \n-# .. versionadded:: 5.0\n-# Default: False\n-# c.Authenticator.reset_managed_roles_on_startup = False\n-\n-## Dictionary mapping authenticator usernames to JupyterHub users.\n-# \n-# Primarily used to normalize OAuth user names to local users.\n-# Default: {}\n-# c.Authenticator.username_map = {}\n-\n-## Regular expression pattern that all valid usernames must match.\n-# \n-# If a username does not match the pattern specified here, authentication will\n-# not be attempted.\n-# \n-# If not set, allow any username.\n-# Default: ''\n-# c.Authenticator.username_pattern = ''\n-\n-## Deprecated, use `Authenticator.allowed_users`\n-# Default: set()\n-# c.Authenticator.whitelist = set()\n-\n-#------------------------------------------------------------------------------\n-# DummyAuthenticator(Authenticator) configuration\n-#------------------------------------------------------------------------------\n-## Dummy Authenticator for testing\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-# \n-# .. versionadded:: 1.0\n-# \n-# .. versionadded:: 5.0\n-# `allow_all` defaults to True,\n-# preserving default behavior.\n-\n-## \n-# See also: Authenticator.admin_users\n-# c.DummyAuthenticator.admin_users = set()\n-\n-## \n-# See also: Authenticator.allow_all\n-# c.DummyAuthenticator.allow_all = False\n-\n-## \n-# See also: Authenticator.allow_existing_users\n-# c.DummyAuthenticator.allow_existing_users = False\n-\n-## \n-# See also: Authenticator.allowed_users\n-# c.DummyAuthenticator.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-\n-## The max age (in seconds) of authentication info\n-# See also: Authenticator.auth_refresh_age\n-# c.DummyAuthenticator.auth_refresh_age = 300\n-\n-## Automatically begin the login process\n-# See also: Authenticator.auto_login\n-# c.DummyAuthenticator.auto_login = False\n-\n-## \n-# See also: Authenticator.auto_login_oauth2_authorize\n-# c.DummyAuthenticator.auto_login_oauth2_authorize = False\n-\n-## \n-# See also: Authenticator.blocked_users\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.DummyAuthenticator.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-\n-## Let authenticator manage user groups\n-# See also: Authenticator.manage_groups\n-# c.DummyAuthenticator.manage_groups = False\n-\n-## Let authenticator manage roles\n-# See also: Authenticator.manage_roles\n-# c.DummyAuthenticator.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-\n-## \n-# See also: Authenticator.post_auth_hook\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.DummyAuthenticator.refresh_pre_spawn = False\n-\n-## \n-# See also: Authenticator.request_otp\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.DummyAuthenticator.reset_managed_roles_on_startup = False\n-\n-## Dictionary mapping authenticator usernames to JupyterHub users.\n-# See also: Authenticator.username_map\n-# c.DummyAuthenticator.username_map = {}\n-\n-## \n-# See also: Authenticator.username_pattern\n-# c.DummyAuthenticator.username_pattern = ''\n-\n-## Deprecated, use `Authenticator.allowed_users`\n-# See also: Authenticator.whitelist\n-# c.DummyAuthenticator.whitelist = set()\n-\n-#------------------------------------------------------------------------------\n # SimpleLocalProcessSpawner(LocalProcessSpawner) 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 # \n@@ -2296,512 +2699,109 @@\n # c.SimpleLocalProcessSpawner.start_timeout = 60\n \n ## \n # See also: LocalProcessSpawner.term_timeout\n # c.SimpleLocalProcessSpawner.term_timeout = 5\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-# methods:\n-# \n-# - :meth:`.get_all_routes` return a dictionary of all JupyterHub-related routes\n-# - :meth:`.add_route` adds a route - :meth:`.delete_route` deletes a route\n-# \n-# In addition to these, the following method(s) may need to be implemented:\n-# \n-# - :meth:`.start` start the proxy, if it should be launched by the Hub\n-# instead of externally managed.\n-# If the proxy is externally managed, it should set :attr:`should_start` to False.\n-# - :meth:`.stop` stop the proxy. Only used if :meth:`.start` is also used.\n-# \n-# And the following method(s) are optional, but can be provided:\n-# \n-# - :meth:`.get_route` gets a single route.\n-# There is a default implementation that extracts data from :meth:`.get_all_routes`,\n-# but implementations may choose to provide a more efficient implementation\n-# of fetching a single route.\n-\n-## Additional routes to be maintained in the proxy.\n-# \n-# A dictionary with a route specification as key, and a URL as target. The hub\n-# will ensure this route is present in the proxy.\n-# \n-# If the hub is running in host based mode (with JupyterHub.subdomain_host set),\n-# the routespec *must* have a domain component (example.com/my-url/). If the hub\n-# is not running in host based mode, the routespec *must not* have a domain\n-# component (/my-url/).\n-# \n-# Helpful when the hub is running in API-only mode.\n-# Default: {}\n-# c.Proxy.extra_routes = {}\n-\n-## Should the Hub start the proxy\n-# \n-# If True, the Hub will start the proxy and stop it.\n-# Set to False if the proxy is managed externally,\n-# such as by systemd, docker, or another service manager.\n-# Default: True\n-# c.Proxy.should_start = True\n-\n-#------------------------------------------------------------------------------\n-# ConfigurableHTTPProxy(Proxy) configuration\n-#------------------------------------------------------------------------------\n-## Proxy implementation for the default configurable-http-proxy.\n-# \n-# This is the default proxy implementation for running the nodejs proxy\n-# `configurable-http-proxy`.\n-# \n-# If the proxy should not be run as a subprocess of the Hub, (e.g. in a separate\n-# container), set::\n-# \n-# c.ConfigurableHTTPProxy.should_start = False\n-\n-## The ip (or hostname) of the proxy's API endpoint\n-# Default: ''\n-# c.ConfigurableHTTPProxy.api_url = ''\n-\n-## The Proxy auth token\n-# \n-# Loaded from the CONFIGPROXY_AUTH_TOKEN env variable by default.\n-# Default: ''\n-# c.ConfigurableHTTPProxy.auth_token = ''\n-\n-## Interval (in seconds) at which to check if the proxy is running.\n-# Default: 5\n-# c.ConfigurableHTTPProxy.check_running_interval = 5\n-\n-## The command to start the proxy\n-# Default: ['configurable-http-proxy']\n-# c.ConfigurableHTTPProxy.command = ['configurable-http-proxy']\n-\n-## The number of requests allowed to be concurrently outstanding to the proxy\n-# \n-# Limiting this number avoids potential timeout errors by sending too many\n-# requests to update the proxy at once\n-# Default: 10\n-# c.ConfigurableHTTPProxy.concurrency = 10\n-\n-## Add debug-level logging to the Proxy.\n-# Default: False\n-# c.ConfigurableHTTPProxy.debug = False\n-\n-## \n-# See also: Proxy.extra_routes\n-# c.ConfigurableHTTPProxy.extra_routes = {}\n-\n-## Proxy log level\n-# Choices: any of ['debug', 'info', 'warn', 'error'] (case-insensitive)\n-# Default: 'info'\n-# c.ConfigurableHTTPProxy.log_level = 'info'\n-\n-## File in which to write the PID of the proxy process.\n-# Default: 'jupyterhub-proxy.pid'\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-# NullAuthenticator(Authenticator) configuration\n-#------------------------------------------------------------------------------\n-## Null Authenticator for JupyterHub\n-# \n-# For cases where authentication should be disabled, e.g. only allowing access\n-# via API tokens.\n-# \n-# .. versionadded:: 2.0\n-\n-## \n-# See also: Authenticator.admin_users\n-# c.NullAuthenticator.admin_users = set()\n-\n-## \n-# See also: Authenticator.allow_all\n-# c.NullAuthenticator.allow_all = False\n-\n-## \n-# See also: Authenticator.allow_existing_users\n-# c.NullAuthenticator.allow_existing_users = False\n-\n-## \n-# See also: Authenticator.allowed_users\n-# c.NullAuthenticator.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-\n-## The max age (in seconds) of authentication info\n-# See also: Authenticator.auth_refresh_age\n-# c.NullAuthenticator.auth_refresh_age = 300\n-\n-## \n-# See also: Authenticator.auto_login_oauth2_authorize\n-# c.NullAuthenticator.auto_login_oauth2_authorize = False\n-\n-## \n-# See also: Authenticator.blocked_users\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.NullAuthenticator.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-\n-## Let authenticator manage user groups\n-# See also: Authenticator.manage_groups\n-# c.NullAuthenticator.manage_groups = False\n-\n-## Let authenticator manage roles\n-# See also: Authenticator.manage_roles\n-# c.NullAuthenticator.manage_roles = False\n-\n-## \n-# See also: Authenticator.otp_prompt\n-# c.NullAuthenticator.otp_prompt = 'OTP:'\n-\n-## \n-# See also: Authenticator.post_auth_hook\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.NullAuthenticator.refresh_pre_spawn = False\n-\n-## \n-# See also: Authenticator.request_otp\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.NullAuthenticator.reset_managed_roles_on_startup = False\n-\n-## Dictionary mapping authenticator usernames to JupyterHub users.\n-# See also: Authenticator.username_map\n-# c.NullAuthenticator.username_map = {}\n-\n-## \n-# See also: Authenticator.username_pattern\n-# c.NullAuthenticator.username_pattern = ''\n-\n-## Deprecated, use `Authenticator.allowed_users`\n-# See also: Authenticator.whitelist\n-# c.NullAuthenticator.whitelist = set()\n-\n-#------------------------------------------------------------------------------\n-# LocalAuthenticator(Authenticator) configuration\n+# DummyAuthenticator(Authenticator) 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-# \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.LocalAuthenticator.admin_users = set()\n-\n-## \n-# See also: Authenticator.allow_all\n-# c.LocalAuthenticator.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-\n-## \n-# See also: Authenticator.allowed_users\n-# c.LocalAuthenticator.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-\n-## The max age (in seconds) of authentication info\n-# See also: Authenticator.auth_refresh_age\n-# c.LocalAuthenticator.auth_refresh_age = 300\n-\n-## Automatically begin the login process\n-# See also: Authenticator.auto_login\n-# c.LocalAuthenticator.auto_login = False\n-\n-## \n-# See also: Authenticator.auto_login_oauth2_authorize\n-# c.LocalAuthenticator.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+## Dummy Authenticator for testing\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.LocalAuthenticator.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-\n-## Let authenticator manage user groups\n-# See also: Authenticator.manage_groups\n-# c.LocalAuthenticator.manage_groups = False\n-\n-## Let authenticator manage roles\n-# See also: Authenticator.manage_roles\n-# c.LocalAuthenticator.manage_roles = False\n-\n-## \n-# See also: Authenticator.otp_prompt\n-# c.LocalAuthenticator.otp_prompt = 'OTP:'\n-\n-## \n-# See also: Authenticator.post_auth_hook\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.LocalAuthenticator.refresh_pre_spawn = False\n-\n-## \n-# See also: Authenticator.request_otp\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.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.LocalAuthenticator.username_map = {}\n-\n-## \n-# See also: Authenticator.username_pattern\n-# c.LocalAuthenticator.username_pattern = ''\n-\n-## Deprecated, use `Authenticator.allowed_users`\n-# See also: Authenticator.whitelist\n-# c.LocalAuthenticator.whitelist = set()\n-\n-#------------------------------------------------------------------------------\n-# PAMAuthenticator(LocalAuthenticator) 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+# 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-# allowed/blocked rules still apply.\n+# .. versionadded:: 1.0\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:: 5.0\n+# `allow_all` defaults to True,\n+# preserving default behavior.\n \n ## \n # See also: Authenticator.admin_users\n-# c.PAMAuthenticator.admin_users = set()\n+# c.DummyAuthenticator.admin_users = set()\n \n ## \n # See also: Authenticator.allow_all\n-# c.PAMAuthenticator.allow_all = False\n+# c.DummyAuthenticator.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.DummyAuthenticator.allow_existing_users = False\n \n ## \n # See also: Authenticator.allowed_users\n-# c.PAMAuthenticator.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.PAMAuthenticator.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.PAMAuthenticator.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.PAMAuthenticator.auto_login = False\n+# c.DummyAuthenticator.auto_login = False\n \n ## \n # See also: Authenticator.auto_login_oauth2_authorize\n-# c.PAMAuthenticator.auto_login_oauth2_authorize = False\n+# c.DummyAuthenticator.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.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.PAMAuthenticator.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.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.DummyAuthenticator.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.DummyAuthenticator.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.DummyAuthenticator.manage_roles = False\n \n ## \n # See also: Authenticator.otp_prompt\n-# c.PAMAuthenticator.otp_prompt = 'OTP:'\n+# c.DummyAuthenticator.otp_prompt = 'OTP:'\n \n-## Round-trip the username via PAM lookups to make sure it is unique\n+## Set a global password for all users wanting to log in.\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+# 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.PAMAuthenticator.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.PAMAuthenticator.refresh_pre_spawn = False\n+# c.DummyAuthenticator.refresh_pre_spawn = False\n \n ## \n # See also: Authenticator.request_otp\n-# c.PAMAuthenticator.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.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.DummyAuthenticator.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.DummyAuthenticator.username_map = {}\n \n ## \n # See also: Authenticator.username_pattern\n-# c.PAMAuthenticator.username_pattern = ''\n+# c.DummyAuthenticator.username_pattern = ''\n \n ## Deprecated, use `Authenticator.allowed_users`\n # See also: Authenticator.whitelist\n-# c.PAMAuthenticator.whitelist = set()\n+# c.DummyAuthenticator.whitelist = set()\n"}]}]}]}]}