diff --git a/.vscode/launch.json b/.vscode/launch.json index ce010f4638..6fa92572df 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -23,7 +23,7 @@ "request": "attach", "connect": { "host": "localhost", - "port": 9901 + "port": 9902 }, "pathMappings": [ { diff --git a/authentik/lib/debug.py b/authentik/lib/debug.py index af56eb4354..c147678096 100644 --- a/authentik/lib/debug.py +++ b/authentik/lib/debug.py @@ -5,7 +5,7 @@ from authentik.lib.config import CONFIG LOGGER = get_logger() -def start_debug_server(**kwargs) -> bool: +def start_debug_server(port_offset: int = 0, **kwargs) -> bool: """Attempt to start a debugpy server in the current process. Returns true if the server was started successfully, otherwise false""" if not CONFIG.get_bool("debug") and not CONFIG.get_bool("debugger"): @@ -21,8 +21,9 @@ def start_debug_server(**kwargs) -> bool: listen: str = CONFIG.get("listen.debug_py", "127.0.0.1:9901") host, _, port = listen.rpartition(":") + port = int(port) + port_offset try: - debugpy.listen((host, int(port)), **kwargs) # nosec + debugpy.listen((host, port), **kwargs) # nosec except RuntimeError: LOGGER.warning("Could not start debug server. Continuing without") return False diff --git a/lifecycle/worker_process.py b/lifecycle/worker_process.py index ac6110e92c..6b32085cac 100755 --- a/lifecycle/worker_process.py +++ b/lifecycle/worker_process.py @@ -13,6 +13,7 @@ from dramatiq import Worker, get_broker from structlog.stdlib import get_logger from authentik.lib.config import CONFIG +from authentik.lib.debug import start_debug_server LOGGER = get_logger() INITIAL_WORKER_ID = 1000 @@ -147,6 +148,8 @@ if __name__ == "__main__": django.setup() + start_debug_server(port_offset=worker_id - INITIAL_WORKER_ID + 1) + if worker_id == INITIAL_WORKER_ID: from lifecycle.migrate import run_migrations diff --git a/website/docs/developer-docs/setup/debugging.md b/website/docs/developer-docs/setup/debugging.md index 1f584f5a86..feed41dd96 100644 --- a/website/docs/developer-docs/setup/debugging.md +++ b/website/docs/developer-docs/setup/debugging.md @@ -22,7 +22,12 @@ Note that due to the Python debugger for VS Code, when a Python file in authenti #### Debug the server or the worker -Whichever process is first started listens on port `9901`. Additional processes started after that will then try to listen on the same port, which will fail, and will simply not start the debugger in that case. +The server and each worker process run their own debug server on a distinct port, derived from the base port set by `AUTHENTIK_LISTEN__DEBUG_PY` (`9901` by default): + +- The **server** (Gunicorn) listens on the base port (`9901`). +- The **worker** runs as one or more processes, controlled by `AUTHENTIK_WORKER__PROCESSES` (defaults to `1`). Each worker process listens on the base port plus an offset, starting at `9902` for the first process, `9903` for the second, and so on. + +In VS Code, use the **Debug: Attach Server Core** launch configuration to attach to the server and **Debug: Attach Worker** to attach to the first worker process. To debug additional worker processes, duplicate the worker configuration and change its port to match (`9903`, `9904`, …). #### Debugging in containers @@ -30,13 +35,14 @@ When debugging an authentik instance running in containers, there are some addit A local clone of the authentik repository is required to set breakpoints in the code. The locally checked out repository must be on the same version/commit as the authentik version running in the containers. To check out version 2024.12.3, for example, run `git checkout version/2024.12.3`. -The debug port needs to be accessible on the local machine. By default, this is port 9901. Additionally, the container being debugged must be started as `root`, because additional dependencies need to be installed on startup. +The debug port needs to be accessible on the local machine. By default, this is port 9901 for the server; the worker uses `9902` and up (one port per worker process). Additionally, the container being debugged must be started as `root`, because additional dependencies need to be installed on startup. When running in Docker Compose, a file `compose.override.yml` can be created next to the authentik `compose.yml` file to expose the port, change the user, and enable debug mode. ```yaml services: - # Replace `server` with `worker` to debug the worker container. + # To debug the worker container instead, use the `worker` service and map + # its worker ports (`9902` and up) rather than `9901`. server: user: root healthcheck: diff --git a/website/docs/install-config/configuration/configuration.mdx b/website/docs/install-config/configuration/configuration.mdx index e08110730b..3bf2ff0ed1 100644 --- a/website/docs/install-config/configuration/configuration.mdx +++ b/website/docs/install-config/configuration/configuration.mdx @@ -386,9 +386,9 @@ Defaults to `0.0.0.0:9900`. ##### `AUTHENTIK_LISTEN__DEBUG_PY` -Listening address:port for Python debugging server, see [Debugging](../../developer-docs/setup/debugging.md). +Base listening address:port for the Python debugging server, see [Debugging](../../developer-docs/setup/debugging.md). -Applies to the Server and the Worker. +Applies to the Server and the Worker. The Server listens on this exact port; each Worker process listens on a successive port (`9902`, `9903`, …). Defaults to `0.0.0.0:9901`.