Document approach pivot from uv pip download (doesn't exist in uv 0.9.29) to uv sync FOD + autoPatchelfHook. Record build issue fixes: pg_config, gssapi S4U headers, xmlsec libltdl, FOD store reference stripping. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
4.3 KiB
| title | modified | status | requires | tags | ||||
|---|---|---|---|---|---|---|---|---|
| Build Authentik Python Backend | 2026-02-28 | active |
|
|
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 sync FOD + autoPatchelfHook
Nix builds are sandboxed with no network access. The pattern is:
- Fixed-output derivation (FOD) —
uv sync --frozenfetches and installs all dependencies into a venv. FODs are allowed network access because the output hash is declared upfront. Compiled.sofiles reference Nix store paths (RPATHs to libxml2, krb5, etc.), which FODs must not contain, so we strip references withremove-references-toand deletebin/and.pycfiles. - Main derivation — copies the FOD's
lib/python3.14/site-packages/, recreatesbin/with proper python symlinks, restorespyvenv.cfg, and runsautoPatchelfHookto re-link.sofiles against the correct Nix store libraries.
Why not uv pip download + uv pip install --no-index? uv pip download does not exist in uv 0.9.29 (nixpkgs). And the download-only approach has further complications with sdist-only packages (psycopg-c, gssapi) that must be compiled anyway.
What to Do
- Create the FOD (
python-deps.nix) that runsuv sync --frozen --no-install-project --no-install-workspace --no-dev, then strips all Nix store references from the output - Create the main derivation (
authentik-django.nix) that:- Copies the FOD's site-packages
- Recreates venv
bin/andpyvenv.cfg - Runs
autoPatchelfHookto restore.soRPATHs - Copies 4 in-tree workspace packages directly into site-packages
- Copies
authentik/andlifecycle/into site-packages - Copies
opencontainersfromfetchFromGitHubinto site-packages
- Apply
substituteInPlacepatches for Nix store paths insettings.py,default.yml,email/utils.py - Copy lifecycle scripts,
manage.py, blueprints into the output - Verify:
$out/bin/python3.14 -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
cp314wheels where available, sdist builds otherwise) - The FOD hash must be recomputed when
uv.lockchanges manylinuxwheels bundle some.sofiles — acceptable for a container image- The 4 in-tree packages are installed from monorepo source, not PyPI
- Standard
djangorestframework3.16.1 from PyPI (no longer forked as of 2026.2.0)
Lessons Learned (WIP)
Build issues encountered and resolved:
| Issue | Fix |
|---|---|
pg_config not found for psycopg-c |
Use pkgs.postgresql.pg_config (separate derivation), not pkgs.postgresql |
gssapi gss_acquire_cred_impersonate_name undeclared |
NIX_CFLAGS_COMPILE="-include gssapi/gssapi_ext.h" — function is in gssapi_ext.h, not auto-included |
xmlsec linker error -lltdl |
Add pkgs.libtool to buildInputs (provides libltdl) |
psycopg-c needs libpq |
Add pkgs.libpq to buildInputs |
| FOD references 19 store paths | Strip with remove-references-to, delete bin/ and .pyc files, placeholder pyvenv.cfg |
| Still 6 residual store refs | Need to add glibc.dev and other -dev outputs to refTargets list — WIP |
The uv sync completes in ~3.5 minutes. Reference stripping reduced 19 → 6 remaining store refs. Next iteration needs to capture all remaining dev/lib output paths in the refTargets list.
Related
- build-authentik-from-source — Parent goal
- authentik-go-server-derivation — Depends on this for lifecycle scripts and web assets