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>
56 lines
2.8 KiB
Markdown
56 lines
2.8 KiB
Markdown
---
|
|
title: Build Authentik Python Backend
|
|
modified: 2026-02-28
|
|
status: active
|
|
requires:
|
|
- mirror-authentik-build-deps
|
|
tags:
|
|
- how-to
|
|
- authentik
|
|
- nix
|
|
---
|
|
|
|
# Build Authentik Python Backend
|
|
|
|
Build `authentik-django` — the Python/Django application that forms the core backend of authentik.
|
|
|
|
## Context
|
|
|
|
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.
|
|
|
|
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.
|
|
|
|
## 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 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
|
|
|
|
- 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
|
|
|
|
- [[build-authentik-from-source]] — Parent goal
|
|
- [[authentik-go-server-derivation]] — Depends on this for lifecycle scripts and web assets
|