C2(authentik-source-build): plan pivot to uv-based Python packaging
Drop the nixpkgs packageOverrides approach for Python deps. Instead, use uv + fixed-output derivation to install from PyPI where cp314 wheels already exist. Eliminates the entire class of Python 3.14 nixpkgs compat issues (astor, dacite, exceptiongroup, pydantic-core). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
df327d3a44
commit
f65106dcef
2 changed files with 28 additions and 19 deletions
|
|
@ -16,32 +16,39 @@ Build `authentik-django` — the Python/Django application that forms the core b
|
|||
|
||||
## Context
|
||||
|
||||
This is the most complex component. The nixpkgs derivation uses `python3.override` with extensive `packageOverrides` to handle authentik's non-standard dependencies:
|
||||
Authentik 2026.2.0 requires Python 3.14 (`requires-python = "==3.14.*"`). The nixpkgs reference derivation (2025.12.4) builds all 60+ Python deps through nix's `python3.override` with `packageOverrides`. This approach breaks on Python 3.14 because many nixpkgs python314 packages haven't been updated — astor, dacite, exceptiongroup, and pydantic-core all fail to build.
|
||||
|
||||
- **4 in-tree Python packages** built from the monorepo: `ak-guardian`, `django-channels-postgres`, `django-dramatiq-postgres`, `django-postgres-cache`
|
||||
- **Forked `djangorestframework`** from `authentik-community/django-rest-framework` (specific commit)
|
||||
- **Pinned `dramatiq`** at 1.17.1 (upstream uses newer versions that break authentik)
|
||||
- **Django 5** forced via `django_5`
|
||||
- **60+ Python dependencies** from nixpkgs
|
||||
Instead of carrying individual overrides for each broken package, we use **`uv`** to install Python dependencies from PyPI, where upstream maintainers have already published Python 3.14-compatible wheels. Nix provides only the Python interpreter and system libraries.
|
||||
|
||||
Post-install, the derivation patches hardcoded paths in `settings.py`, `default.yml`, `email/utils.py`, and `files/backends/file.py` to reference Nix store paths.
|
||||
## Approach: uv + fixed-output derivation
|
||||
|
||||
Nix builds are sandboxed with no network access. The pattern is:
|
||||
|
||||
1. **Fixed-output derivation (FOD)** — downloads all wheels/sdists from PyPI. FODs are allowed network access because the output hash is declared upfront (like `fetchurl`). Locked by authentik's `uv.lock`.
|
||||
2. **Main derivation** — builds a Python venv from the downloaded packages using `uv pip install --find-links <FOD> --no-index`. No network needed.
|
||||
|
||||
This aligns with how authentik upstream builds (they use `uv` as their package manager).
|
||||
|
||||
## What to Do
|
||||
|
||||
1. Create a Python package override set that builds the 4 in-tree packages from source
|
||||
2. Pin the forked `djangorestframework` and `dramatiq` versions
|
||||
3. Build `authentik-django` using `hatchling` as the build backend
|
||||
4. Apply the 4 `substituteInPlace` patches for Nix store path references
|
||||
5. Copy lifecycle scripts, `manage.py`, blueprints, and web assets into the output
|
||||
6. Verify: `python -c "import authentik"` succeeds
|
||||
1. Create a FOD that runs `uv pip download` to fetch all Python dependencies locked by `uv.lock`
|
||||
2. Create the main derivation that:
|
||||
- Sets up a Python 3.14 venv via `uv`
|
||||
- Installs all dependencies from the FOD (offline, `--no-index`)
|
||||
- Installs the 4 in-tree packages from the monorepo source (`ak-guardian`, `django-channels-postgres`, `django-dramatiq-postgres`, `django-postgres-cache`)
|
||||
- Installs authentik itself
|
||||
3. Apply `substituteInPlace` patches for Nix store paths in `settings.py`, `default.yml`, `email/utils.py`, `files/backends/file.py`
|
||||
4. Copy lifecycle scripts, `manage.py`, blueprints, and web assets into the output
|
||||
5. Verify: `python -c "import authentik"` succeeds
|
||||
|
||||
## Key Details
|
||||
|
||||
- Build backend: `hatchling`
|
||||
- Entry point: `manage.py` (Django management commands)
|
||||
- Lifecycle scripts: `lifecycle/` directory (used by Go server and `ak` wrapper)
|
||||
- Blueprints: `blueprints/` directory (YAML IaC definitions)
|
||||
- The output must include `web/` assets (email templates reference them)
|
||||
- Nix provides: `python314`, `uv`, system libraries (`libxml2`, `libxslt`, `openssl`, `libffi`, `zlib`, etc.)
|
||||
- PyPI provides: all Python packages (via pre-built `cp314` wheels where available, sdist builds otherwise)
|
||||
- The FOD hash must be recomputed when `uv.lock` changes
|
||||
- `manylinux` wheels bundle some `.so` files — acceptable for a container image
|
||||
- The 4 in-tree packages are installed from monorepo source, not PyPI
|
||||
- Standard `djangorestframework` 3.16.1 from PyPI (no longer forked as of 2026.2.0)
|
||||
|
||||
## Related
|
||||
|
||||
|
|
|
|||
|
|
@ -30,12 +30,14 @@ This also serves as practice for packaging services from source using Nix, relyi
|
|||
Authentik has four build components that must be assembled:
|
||||
|
||||
1. **API client generation** — Go and TypeScript bindings generated from `schema.yml` (OpenAPI)
|
||||
2. **Python backend** (`authentik-django`) — Django application with 60+ Python dependencies, including 4 in-tree packages and a forked `djangorestframework`
|
||||
2. **Python backend** (`authentik-django`) — Django application with 60+ Python dependencies, installed via `uv` from PyPI rather than nixpkgs (see [[authentik-python-backend-derivation]])
|
||||
3. **Web UI** — Lit-based TypeScript frontend built with Rollup
|
||||
4. **Go server** — HTTP server binary (`cmd/server`) that serves the web UI and spawns gunicorn for Django
|
||||
|
||||
The final package is the `ak` bash wrapper that orchestrates Go server + Python worker.
|
||||
|
||||
**Python packaging strategy:** Nix provides the Python 3.14 interpreter and system libraries. Python packages are installed from PyPI using `uv`, locked by authentik's `uv.lock`. This avoids nixpkgs' Python 3.14 compatibility issues (many packages in nixos-25.11's python314 set fail to build) and aligns with upstream's build process.
|
||||
|
||||
## Source
|
||||
|
||||
Forge mirrors (all derivations should fetch from forge, not GitHub):
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue