blumeops/docs/how-to/authentik/build-authentik-from-source.md
Erich Blume f65106dcef 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>
2026-03-01 11:45:39 -08:00

4.3 KiB

title modified status branch requires tags
Build Authentik from Source 2026-02-28 active mikado/authentik-source-build
authentik-go-server-derivation
authentik-web-ui-derivation
authentik-python-backend-derivation
how-to
authentik
nix

Build Authentik from Source

Replace pkgs.authentik from nixpkgs with a custom Nix derivation that builds authentik from source. This removes the dependency on the nixpkgs packaging timeline and gives full version control.

Motivation

The nix-container-builder runner on ringtail resolves nixpkgs via the NixOS nix registry, which pins to nixos-25.11. That channel lags behind upstream authentik releases — e.g. nixos-25.11 has 2025.10.1 while upstream is at 2026.2.0. Building from source lets us target any release.

Target version: 2026.2.0 (latest stable, released 2026-02-24). Notable changes from the nixpkgs reference (2025.12.4): requires Python 3.14, Go 1.25.5.

This also serves as practice for packaging services from source using Nix, relying on nixpkgs only for satellite dependencies (Python interpreter, Node.js, Go toolchain, system libraries).

Architecture

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, 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):

Reference derivation: nixpkgs pkgs/by-name/au/authentik/package.nix — targets 2025.12.4, we are porting to 2026.2.0 so hashes and some deps will differ.

Testing

Nix derivations target x86_64-linux and can't be built on macOS. Test incrementally on ringtail:

# Copy derivation files to a temp dir on ringtail
set tmpdir (ssh ringtail 'mktemp -d /tmp/authentik-test.XXXXXX')
scp containers/authentik/*.nix containers/authentik/*.patch ringtail:$tmpdir/

# Write a test-build.nix that instantiates components, then:
ssh ringtail "cd $tmpdir && nix-build test-build.nix -A <component> --extra-experimental-features 'nix-command flakes'"

# Clean up
ssh ringtail "rm -rf $tmpdir"

Use builtins.getFlake "nixpkgs" instead of <nixpkgs> (ringtail uses flakes, no NIX_PATH).

Prefetch hashes for fetchgit sources:

ssh ringtail 'nix shell nixpkgs#nix-prefetch-git --extra-experimental-features "nix-command flakes" -c nix-prefetch-git --url <url> --rev <tag> --quiet'

What to Do

Once all prerequisites are complete:

  1. Assemble the component derivations into a final ak-wrapped package in containers/authentik/
  2. Update containers/authentik/default.nix to use the custom derivation instead of pkgs.authentik
  3. Test locally via Dagger before pushing to CI: dagger call build-nix --src=. --container-name=authentik
  4. Build and push the container: mise run container-build-and-release authentik
  5. Update argocd/manifests/authentik/kustomization.yaml with the new image tag
  6. Update service-versions.yaml with the new version
  7. Verify deployment: ArgoCD sync, UI login, OAuth2 flows