Start C2 Mikado chain: build authentik from source
Create goal card and 4 prerequisite cards for building authentik from a custom Nix derivation instead of using pkgs.authentik from nixpkgs. This removes the dependency on the nixpkgs packaging timeline and gives full version control over authentik releases. Chain: mikado/authentik-source-build Leaf nodes: authentik-api-client-generation, authentik-python-backend-derivation Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
922265c88f
commit
7094ea7d3e
7 changed files with 252 additions and 0 deletions
1
docs/changelog.d/authentik-source-build.infra.md
Normal file
1
docs/changelog.d/authentik-source-build.infra.md
Normal file
|
|
@ -0,0 +1 @@
|
|||
Start C2 Mikado chain: build authentik from a custom Nix derivation (from source) to replace nixpkgs dependency and gain full version control.
|
||||
39
docs/how-to/authentik/authentik-api-client-generation.md
Normal file
39
docs/how-to/authentik/authentik-api-client-generation.md
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
---
|
||||
title: Generate Authentik API Clients
|
||||
modified: 2026-02-28
|
||||
status: active
|
||||
tags:
|
||||
- how-to
|
||||
- authentik
|
||||
- nix
|
||||
---
|
||||
|
||||
# Generate Authentik API Clients
|
||||
|
||||
Build Go and TypeScript API client bindings from authentik's OpenAPI spec (`schema.yml`). These are build-time inputs for the Go server and web UI respectively.
|
||||
|
||||
## Context
|
||||
|
||||
Authentik maintains a separate repo ([`goauthentik/client-go`](https://github.com/goauthentik/client-go)) with pre-generated Go client code. The nixpkgs derivation fetches this and injects it into the Go vendor directory via a setup hook (`apiGoVendorHook`). The TypeScript client is generated inline from `schema.yml` using `openapi-generator-cli`.
|
||||
|
||||
Both clients are generated from the same `schema.yml` OpenAPI spec in the main authentik repo.
|
||||
|
||||
## What to Do
|
||||
|
||||
1. Create a Nix derivation (`client-go`) that generates Go API client bindings from `schema.yml` using `openapi-generator-cli`
|
||||
2. Create a Nix derivation (`client-ts`) that generates TypeScript fetch client bindings from the same spec
|
||||
3. Create a setup hook (`apiGoVendorHook`) that replaces `goauthentik.io/api/v3` in the Go vendor directory with the generated client
|
||||
4. Verify the generated code compiles (Go: `go build`, TypeScript: type-check with `tsc`)
|
||||
|
||||
## Key Details
|
||||
|
||||
- Source spec: `schema.yml` in the authentik repo root
|
||||
- Go client replaces `vendor/goauthentik.io/api/v3/` in the server build
|
||||
- TypeScript client replaces `web/node_modules/@goauthentik/api/` in the web UI build
|
||||
- The nixpkgs derivation patches the generated Go client (`client-go-config.patch`) — check if still needed
|
||||
|
||||
## Related
|
||||
|
||||
- [[build-authentik-from-source]] — Parent goal
|
||||
- [[authentik-go-server-derivation]] — Consumer of Go client
|
||||
- [[authentik-web-ui-derivation]] — Consumer of TypeScript client
|
||||
52
docs/how-to/authentik/authentik-go-server-derivation.md
Normal file
52
docs/how-to/authentik/authentik-go-server-derivation.md
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
---
|
||||
title: Build Authentik Go Server
|
||||
modified: 2026-02-28
|
||||
status: active
|
||||
requires:
|
||||
- authentik-api-client-generation
|
||||
- authentik-python-backend-derivation
|
||||
tags:
|
||||
- how-to
|
||||
- authentik
|
||||
- nix
|
||||
---
|
||||
|
||||
# Build Authentik Go Server
|
||||
|
||||
Build the Go HTTP server binary (`cmd/server`) that serves the web UI, REST API, and spawns gunicorn for the Django backend.
|
||||
|
||||
## Context
|
||||
|
||||
The Go server is built with `buildGoModule` from the `cmd/server` subpackage. It's a Cobra-based binary that:
|
||||
|
||||
- Serves static web assets and the REST API
|
||||
- Runs an embedded reverse proxy outpost
|
||||
- Spawns `gounicorn` (gunicorn) to run the Django application
|
||||
- Manages health checks
|
||||
|
||||
The nixpkgs derivation patches store paths into two Go source files so the compiled binary can find Python lifecycle scripts and web assets at runtime.
|
||||
|
||||
## What to Do
|
||||
|
||||
1. Create a `buildGoModule` derivation for `cmd/server` from the authentik source
|
||||
2. Inject the generated Go API client into the vendor directory (via `apiGoVendorHook`)
|
||||
3. Apply `substituteInPlace` patches to hardcode Nix store paths:
|
||||
- `internal/gounicorn/gounicorn.go`: `./lifecycle` → `${authentik-django}/lifecycle`
|
||||
- `web/static.go`: `./web` → `${authentik-django}/web`
|
||||
4. Compute the `vendorHash` — note that the hook replaces vendored API code *after* hash verification, so the hash reflects `go.sum` only
|
||||
5. Rename the output binary from `server` to `authentik`
|
||||
6. Verify: `./authentik --help` runs successfully
|
||||
|
||||
## Key Details
|
||||
|
||||
- Go module: `goauthentik.io`
|
||||
- Subpackage: `./cmd/server`
|
||||
- CGO: disabled
|
||||
- The `vendorHash` must be computed with the vendor replacement hook excluded (`overrideModAttrs`)
|
||||
- Outpost binaries (`cmd/ldap`, `cmd/proxy`, `cmd/radius`) are separate and not needed for basic deployment
|
||||
|
||||
## Related
|
||||
|
||||
- [[build-authentik-from-source]] — Parent goal
|
||||
- [[authentik-api-client-generation]] — Provides Go client (prerequisite)
|
||||
- [[authentik-python-backend-derivation]] — Provides lifecycle scripts and web assets (prerequisite)
|
||||
47
docs/how-to/authentik/authentik-python-backend-derivation.md
Normal file
47
docs/how-to/authentik/authentik-python-backend-derivation.md
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
---
|
||||
title: Build Authentik Python Backend
|
||||
modified: 2026-02-28
|
||||
status: active
|
||||
tags:
|
||||
- how-to
|
||||
- authentik
|
||||
- nix
|
||||
---
|
||||
|
||||
# Build Authentik Python Backend
|
||||
|
||||
Build `authentik-django` — the Python/Django application that forms the core backend of authentik.
|
||||
|
||||
## Context
|
||||
|
||||
This is the most complex component. The nixpkgs derivation uses `python3.override` with extensive `packageOverrides` to handle authentik's non-standard dependencies:
|
||||
|
||||
- **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
|
||||
|
||||
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.
|
||||
|
||||
## 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
|
||||
|
||||
## 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)
|
||||
|
||||
## Related
|
||||
|
||||
- [[build-authentik-from-source]] — Parent goal
|
||||
- [[authentik-go-server-derivation]] — Depends on this for lifecycle scripts and web assets
|
||||
45
docs/how-to/authentik/authentik-web-ui-derivation.md
Normal file
45
docs/how-to/authentik/authentik-web-ui-derivation.md
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
---
|
||||
title: Build Authentik Web UI
|
||||
modified: 2026-02-28
|
||||
status: active
|
||||
requires:
|
||||
- authentik-api-client-generation
|
||||
tags:
|
||||
- how-to
|
||||
- authentik
|
||||
- nix
|
||||
---
|
||||
|
||||
# Build Authentik Web UI
|
||||
|
||||
Build the Lit-based TypeScript web frontend for authentik.
|
||||
|
||||
## Context
|
||||
|
||||
The web UI lives in `web/` in the authentik repo. It's built with Rollup and uses Lit web components. The nixpkgs derivation builds this in two phases:
|
||||
|
||||
1. **`webui-deps`** — Fixed-output derivation that runs `npm ci` to fetch Node dependencies. Uses platform-specific output hashes (aarch64-linux vs x86_64-linux).
|
||||
2. **`webui`** — Patches in the generated TypeScript API client (`client-ts`), then runs `npm run build`. Output includes `dist/` and `authentik/` static directories.
|
||||
|
||||
There's also a **`website`** derivation (Docusaurus-based API docs at `website/`) that produces the `/help` endpoint. This is optional but included in the nixpkgs build.
|
||||
|
||||
## What to Do
|
||||
|
||||
1. Create a fixed-output derivation for `npm ci` in `web/` (platform-specific hashes)
|
||||
2. Patch the generated TypeScript client into `web/node_modules/@goauthentik/api/`
|
||||
3. Build with `npm run build` — produces `dist/` and `authentik/` directories
|
||||
4. Optionally build the Docusaurus website (`website/`) for the `/help` endpoint
|
||||
5. Verify: static assets exist and reference correct paths
|
||||
|
||||
## Key Details
|
||||
|
||||
- Build tool: Rollup (via npm scripts)
|
||||
- Node.js version: `nodejs_24` in current nixpkgs (check upstream requirements)
|
||||
- The TypeScript API client must be patched in before the build
|
||||
- Fixed-output hashes break on any npm dependency change — will need updating per release
|
||||
- Output is consumed by both `authentik-django` (email templates) and the Go server (static serving)
|
||||
|
||||
## Related
|
||||
|
||||
- [[build-authentik-from-source]] — Parent goal
|
||||
- [[authentik-api-client-generation]] — Provides TypeScript client (prerequisite)
|
||||
58
docs/how-to/authentik/build-authentik-from-source.md
Normal file
58
docs/how-to/authentik/build-authentik-from-source.md
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
---
|
||||
title: Build Authentik from Source
|
||||
modified: 2026-02-28
|
||||
status: active
|
||||
branch: mikado/authentik-source-build
|
||||
requires:
|
||||
- authentik-go-server-derivation
|
||||
- authentik-web-ui-derivation
|
||||
- authentik-python-backend-derivation
|
||||
tags:
|
||||
- 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 2025.12.4+. Building from source lets us target any release.
|
||||
|
||||
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, including 4 in-tree packages and a forked `djangorestframework`
|
||||
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.
|
||||
|
||||
## Source
|
||||
|
||||
Forge mirror: https://forge.ops.eblu.me/mirrors/authentik (upstream: `goauthentik/authentik`)
|
||||
|
||||
Reference derivation: [nixpkgs `pkgs/by-name/au/authentik/package.nix`](https://github.com/NixOS/nixpkgs/tree/master/pkgs/by-name/au/authentik)
|
||||
|
||||
## 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. Build and push the container: `mise run container-build-and-release authentik`
|
||||
4. Update `argocd/manifests/authentik/kustomization.yaml` with the new image tag
|
||||
5. Update `service-versions.yaml` with the new version
|
||||
6. Verify deployment: ArgoCD sync, UI login, OAuth2 flows
|
||||
|
||||
## Related
|
||||
|
||||
- [[build-authentik-container]] — Current nixpkgs-based build (to be replaced)
|
||||
- [[deploy-authentik]] — Parent deployment goal
|
||||
- [[agent-change-process]] — C2 methodology
|
||||
|
|
@ -96,6 +96,16 @@ Mikado chain for deploying Authentik. Track progress with `mise run docs-mikado
|
|||
- [[create-authentik-secrets]]
|
||||
- [[migrate-grafana-to-authentik]]
|
||||
|
||||
## Authentik Source Build
|
||||
|
||||
Mikado chain for building Authentik from a custom Nix derivation (from source). Track progress with `mise run docs-mikado build-authentik-from-source`.
|
||||
|
||||
- [[build-authentik-from-source]]
|
||||
- [[authentik-api-client-generation]]
|
||||
- [[authentik-python-backend-derivation]]
|
||||
- [[authentik-web-ui-derivation]]
|
||||
- [[authentik-go-server-derivation]]
|
||||
|
||||
## Grafana
|
||||
|
||||
Mikado chain for upgrading Grafana to 12.x with kustomize and home-built containers. Track progress with `mise run docs-mikado upgrade-grafana`.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue