Restructure docs: consolidate, recategorize, and extract
- Consolidate 4 Authentik Nix derivation docs into one card (authentik-nix-build-components.md) - Merge build-grafana-container + build-grafana-sidecar into build-grafana-images.md - Move agent-change-process from how-to/ to explanation/ (it's a methodology doc, not a task guide) - Extract Caddy custom build section from reference card into how-to/deployment/build-caddy-with-plugins.md - Move expose-service-publicly from how-to/ to tutorials/ (it's a comprehensive walkthrough, not a quick task reference) - Update all wiki-link references across affected docs Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
ac01c2d6e2
commit
f46a04b902
17 changed files with 246 additions and 321 deletions
|
|
@ -1,14 +1,16 @@
|
||||||
---
|
---
|
||||||
title: Agent Change Process
|
title: Agent Change Process
|
||||||
modified: 2026-03-04
|
modified: 2026-03-15
|
||||||
last-reviewed: 2026-02-23
|
last-reviewed: 2026-02-23
|
||||||
tags:
|
tags:
|
||||||
- how-to
|
- explanation
|
||||||
- ai
|
- ai
|
||||||
---
|
---
|
||||||
|
|
||||||
# Agent Change Process
|
# Agent Change Process
|
||||||
|
|
||||||
|
> **Note:** This article was drafted by AI and reviewed by Erich. I plan to rewrite all explanatory content in my own words - these serve as placeholders to establish the documentation structure.
|
||||||
|
|
||||||
How to classify and execute infrastructure changes, especially when working with AI agents that may lose context across sessions.
|
How to classify and execute infrastructure changes, especially when working with AI agents that may lose context across sessions.
|
||||||
|
|
||||||
## Change Classification
|
## Change Classification
|
||||||
|
|
@ -1,50 +0,0 @@
|
||||||
---
|
|
||||||
title: Generate Authentik API Clients
|
|
||||||
modified: 2026-03-01
|
|
||||||
last-reviewed: 2026-03-01
|
|
||||||
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 (via `api-go-vendor-hook.nix`)
|
|
||||||
- TypeScript client replaces `web/node_modules/@goauthentik/api/` in the web UI build (symlinked in `webui.nix`)
|
|
||||||
|
|
||||||
## Testing on Ringtail
|
|
||||||
|
|
||||||
The `test-build.nix` harness in `containers/authentik/` supports individual component builds:
|
|
||||||
|
|
||||||
```fish
|
|
||||||
set tmpdir (ssh ringtail 'mktemp -d /tmp/authentik-test.XXXXXX')
|
|
||||||
scp containers/authentik/*.nix ringtail:$tmpdir/
|
|
||||||
ssh ringtail "cd $tmpdir && nix-build test-build.nix -A client-go --extra-experimental-features 'nix-command flakes'"
|
|
||||||
ssh ringtail "cd $tmpdir && nix-build test-build.nix -A client-ts --extra-experimental-features 'nix-command flakes'"
|
|
||||||
ssh ringtail "rm -rf $tmpdir"
|
|
||||||
```
|
|
||||||
|
|
||||||
## Related
|
|
||||||
|
|
||||||
- [[build-authentik-from-source]] — Parent goal
|
|
||||||
- [[authentik-go-server-derivation]] — Consumer of Go client
|
|
||||||
- [[authentik-web-ui-derivation]] — Consumer of TypeScript client
|
|
||||||
|
|
@ -1,50 +0,0 @@
|
||||||
---
|
|
||||||
title: Build Authentik Go Server
|
|
||||||
modified: 2026-03-02
|
|
||||||
last-reviewed: 2026-03-02
|
|
||||||
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` → `${webAssetsPath}` (the webui derivation)
|
|
||||||
- `internal/web/static.go`: `./web` → `${webAssetsPath}` (the webui derivation)
|
|
||||||
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)
|
|
||||||
136
docs/how-to/authentik/authentik-nix-build-components.md
Normal file
136
docs/how-to/authentik/authentik-nix-build-components.md
Normal file
|
|
@ -0,0 +1,136 @@
|
||||||
|
---
|
||||||
|
title: Authentik Nix Build Components
|
||||||
|
modified: 2026-03-15
|
||||||
|
last-reviewed: 2026-03-15
|
||||||
|
tags:
|
||||||
|
- how-to
|
||||||
|
- authentik
|
||||||
|
- nix
|
||||||
|
---
|
||||||
|
|
||||||
|
# Authentik Nix Build Components
|
||||||
|
|
||||||
|
Detailed reference for the four Nix derivations that make up the authentik from-source build. See [[build-authentik-from-source]] for the parent overview and version update workflow.
|
||||||
|
|
||||||
|
## API Client Generation
|
||||||
|
|
||||||
|
Go and TypeScript API client bindings generated from authentik's OpenAPI spec (`schema.yml`).
|
||||||
|
|
||||||
|
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`.
|
||||||
|
|
||||||
|
**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 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 (via `api-go-vendor-hook.nix`)
|
||||||
|
- TypeScript client replaces `web/node_modules/@goauthentik/api/` in the web UI build (symlinked in `webui.nix`)
|
||||||
|
|
||||||
|
## Python Backend
|
||||||
|
|
||||||
|
`authentik-django` — the Python/Django application that forms the core backend.
|
||||||
|
|
||||||
|
Authentik 2026.2.0 requires Python 3.14 (`requires-python = "==3.14.*"`). Instead of carrying individual overrides for each broken nixpkgs python314 package, we use **`uv`** to install Python dependencies from PyPI, where upstream maintainers have already published Python 3.14-compatible wheels.
|
||||||
|
|
||||||
|
### Approach: uv sync FOD + autoPatchelfHook
|
||||||
|
|
||||||
|
Nix builds are sandboxed with no network access. The pattern is:
|
||||||
|
|
||||||
|
1. **Fixed-output derivation (FOD)** — `uv sync --frozen` fetches and installs all dependencies into a venv. FODs are allowed network access because the output hash is declared upfront. Compiled `.so` files reference Nix store paths (RPATHs to libxml2, krb5, etc.), which FODs must not contain, so we strip references with `remove-references-to` and delete `bin/` and `.pyc` files.
|
||||||
|
2. **Main derivation** — copies the FOD's `lib/python3.14/site-packages/`, recreates `bin/` with proper python symlinks, restores `pyvenv.cfg`, and runs `autoPatchelfHook` to re-link `.so` files 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:**
|
||||||
|
|
||||||
|
1. Create the FOD (`python-deps.nix`) that runs `uv sync --frozen --no-install-project --no-install-workspace --no-dev`, then strips all Nix store references from the output
|
||||||
|
2. Create the main derivation (`authentik-django.nix`) that copies the FOD's site-packages, recreates venv, runs `autoPatchelfHook`, copies in-tree workspace packages, and applies path patches
|
||||||
|
3. 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 `cp314` wheels where available, sdist builds otherwise)
|
||||||
|
- The FOD hash must be recomputed when `uv.lock` changes
|
||||||
|
- 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)
|
||||||
|
|
||||||
|
### Lessons Learned
|
||||||
|
|
||||||
|
| 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"` |
|
||||||
|
| xmlsec linker error `-lltdl` | Add `pkgs.libtool` to buildInputs (provides libltdl) |
|
||||||
|
| psycopg-c needs `libpq` | Add `pkgs.libpq` to buildInputs |
|
||||||
|
| Static `refTargets` list missed 6 store refs | Dynamic discovery: `grep -aohE '/nix/store/...'` finds all refs |
|
||||||
|
| autoPatchelfHook can't find libraries | `buildInputs` in main derivation must include all libraries that `.so` files link against |
|
||||||
|
| `FieldError: Cannot resolve keyword 'group_id'` | Django migration ordering bug — add explicit dependency via `substituteInPlace`. Upstream [#19616](https://github.com/goauthentik/authentik/issues/19616) |
|
||||||
|
|
||||||
|
The `uv sync` completes in ~3.5 minutes. Dynamic reference discovery finds 19 unique store paths. `autoPatchelfHook` in the main derivation resolves all NEEDED entries with 0 unsatisfied dependencies.
|
||||||
|
|
||||||
|
## Web UI
|
||||||
|
|
||||||
|
Lit-based TypeScript web frontend built with esbuild + rollup.
|
||||||
|
|
||||||
|
As of 2026.2.0, the main build uses **esbuild** (via wireit) and the SFE sub-package uses **rollup**. Two-phase Nix build:
|
||||||
|
|
||||||
|
1. **`webui-deps.nix`** — Fixed-output derivation that runs `npm ci` to fetch Node dependencies. Platform-specific output hash.
|
||||||
|
2. **`webui.nix`** — Copies deps, patches in the generated TypeScript API client (`client-ts`), patches shebangs, runs `npm run build` (wireit/esbuild) and `npm run build:sfe` (rollup).
|
||||||
|
|
||||||
|
**Key details:**
|
||||||
|
|
||||||
|
- **Node.js:** `nodejs_24` (authentik requires Node >= 24, npm >= 11.6.2)
|
||||||
|
- **Build time:** ~33s on ringtail (x86_64-linux)
|
||||||
|
- **FOD hash:** Platform-specific — updates needed on each version bump
|
||||||
|
- **Output:** `$out/dist/` (JS/CSS bundles) and `$out/authentik/` (static icons)
|
||||||
|
- **Docusaurus website** (`/help` endpoint) is not built — optional
|
||||||
|
|
||||||
|
**Key lessons:**
|
||||||
|
|
||||||
|
- The 2026.2.0 build switched from rollup to esbuild for the main frontend
|
||||||
|
- The version string in `packages/core/version/node.js` uses a JSON import-with-assertion that must be patched to hardcode the version
|
||||||
|
- `NODE_OPTIONS=--openssl-legacy-provider` is needed for compatibility
|
||||||
|
- Workspace packages have separate `node_modules/` — the FOD must collect all of them
|
||||||
|
|
||||||
|
## Go Server
|
||||||
|
|
||||||
|
The Go HTTP server binary (`cmd/server`) that serves the web UI, REST API, and spawns gunicorn for the Django backend.
|
||||||
|
|
||||||
|
**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 for lifecycle scripts and web assets
|
||||||
|
4. Compute the `vendorHash` — the hook replaces vendored API code *after* hash verification
|
||||||
|
5. Rename the output binary from `server` to `authentik`
|
||||||
|
|
||||||
|
**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
|
||||||
|
|
||||||
|
## Testing on Ringtail
|
||||||
|
|
||||||
|
The `test-build.nix` harness in `containers/authentik/` supports individual component builds:
|
||||||
|
|
||||||
|
```fish
|
||||||
|
set tmpdir (ssh ringtail 'mktemp -d /tmp/authentik-test.XXXXXX')
|
||||||
|
scp containers/authentik/*.nix ringtail:$tmpdir/
|
||||||
|
ssh ringtail "cd $tmpdir && nix-build test-build.nix -A client-go --extra-experimental-features 'nix-command flakes'"
|
||||||
|
ssh ringtail "cd $tmpdir && nix-build test-build.nix -A assembled --extra-experimental-features 'nix-command flakes'"
|
||||||
|
ssh ringtail "rm -rf $tmpdir"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Related
|
||||||
|
|
||||||
|
- [[build-authentik-from-source]] — Parent overview and version update workflow
|
||||||
|
- [[mirror-authentik-build-deps]] — Supply chain mirrors for source repos
|
||||||
|
- [[deploy-authentik]] — Deployment goal
|
||||||
|
|
@ -1,76 +0,0 @@
|
||||||
---
|
|
||||||
title: Build Authentik Python Backend
|
|
||||||
modified: 2026-03-01
|
|
||||||
last-reviewed: 2026-03-02
|
|
||||||
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 sync FOD + autoPatchelfHook
|
|
||||||
|
|
||||||
Nix builds are sandboxed with no network access. The pattern is:
|
|
||||||
|
|
||||||
1. **Fixed-output derivation (FOD)** — `uv sync --frozen` fetches and installs all dependencies into a venv. FODs are allowed network access because the output hash is declared upfront. Compiled `.so` files reference Nix store paths (RPATHs to libxml2, krb5, etc.), which FODs must not contain, so we strip references with `remove-references-to` and delete `bin/` and `.pyc` files.
|
|
||||||
2. **Main derivation** — copies the FOD's `lib/python3.14/site-packages/`, recreates `bin/` with proper python symlinks, restores `pyvenv.cfg`, and runs `autoPatchelfHook` to re-link `.so` files 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
|
|
||||||
|
|
||||||
1. Create the FOD (`python-deps.nix`) that runs `uv sync --frozen --no-install-project --no-install-workspace --no-dev`, then strips all Nix store references from the output
|
|
||||||
2. Create the main derivation (`authentik-django.nix`) that:
|
|
||||||
- Copies the FOD's site-packages
|
|
||||||
- Recreates venv `bin/` and `pyvenv.cfg`
|
|
||||||
- Runs `autoPatchelfHook` to restore `.so` RPATHs
|
|
||||||
- Copies 4 in-tree workspace packages directly into site-packages
|
|
||||||
- Copies `authentik/` and `lifecycle/` into site-packages
|
|
||||||
- Copies `opencontainers` from `fetchFromGitHub` into site-packages
|
|
||||||
3. Apply `substituteInPlace` patches for Nix store paths in `settings.py`, `default.yml`, `email/utils.py`
|
|
||||||
4. Copy lifecycle scripts, `manage.py`, blueprints into the output
|
|
||||||
5. 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 `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)
|
|
||||||
|
|
||||||
## Lessons Learned
|
|
||||||
|
|
||||||
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 |
|
|
||||||
| Static `refTargets` list missed 6 store refs | Replaced with dynamic discovery: `grep -aohE '/nix/store/...'` finds all refs, `remove-references-to` strips them |
|
|
||||||
| `xargs grep` exit code 123 under `pipefail` | Wrap pipeline in `{ ... \|\| true; }` — grep returning 1 (no match) causes xargs to return 123 |
|
|
||||||
| `grep -aoE` includes filename prefix in output | Use `grep -aohE` (`-h` suppresses filenames) to get clean store paths |
|
|
||||||
| autoPatchelfHook can't find libraries | `buildInputs` in main derivation must include all libraries that `.so` files link against |
|
|
||||||
| `FieldError: Cannot resolve keyword 'group_id'` on startup | Django migration ordering bug: `authentik_rbac/0010` (drops `Role.group_id`) can run before `authentik_core/0056` (reads it). Add explicit dependency via `substituteInPlace` on the migration file. Upstream [#19616](https://github.com/goauthentik/authentik/issues/19616) |
|
|
||||||
|
|
||||||
The `uv sync` completes in ~3.5 minutes. Dynamic reference discovery finds 19 unique store paths and strips all of them. After stripping, `remove-references-to` mangles hashes to `eeee...` bytes — about 40 files still "contain" `/nix/store/` strings but with invalid hashes, which is expected and harmless. `autoPatchelfHook` in the main derivation resolves all NEEDED entries with 0 unsatisfied dependencies.
|
|
||||||
|
|
||||||
Build verified: `$out/bin/python3.14 -c "import authentik"` succeeds, along with all key dependencies (django 5.2.11, lxml, xmlsec, psycopg, guardian, opencontainers).
|
|
||||||
|
|
||||||
## Related
|
|
||||||
|
|
||||||
- [[build-authentik-from-source]] — Parent goal
|
|
||||||
- [[authentik-go-server-derivation]] — Depends on this for lifecycle scripts and web assets
|
|
||||||
|
|
@ -1,41 +0,0 @@
|
||||||
---
|
|
||||||
title: Build Authentik Web UI
|
|
||||||
modified: 2026-03-01
|
|
||||||
last-reviewed: 2026-03-02
|
|
||||||
tags:
|
|
||||||
- how-to
|
|
||||||
- authentik
|
|
||||||
- nix
|
|
||||||
---
|
|
||||||
|
|
||||||
# Build Authentik Web UI
|
|
||||||
|
|
||||||
Build the Lit-based TypeScript web frontend for authentik.
|
|
||||||
|
|
||||||
## Overview
|
|
||||||
|
|
||||||
The web UI lives in `web/` in the authentik repo. As of 2026.2.0, the main build uses **esbuild** (via wireit) and the SFE sub-package uses **rollup**. The Nix build uses a two-phase approach:
|
|
||||||
|
|
||||||
1. **`webui-deps.nix`** — Fixed-output derivation that runs `npm ci` to fetch Node dependencies. Platform-specific output hash (npm downloads architecture-specific native binaries for esbuild, rollup, and SWC).
|
|
||||||
2. **`webui.nix`** — Copies deps, patches in the generated TypeScript API client (`client-ts`), patches shebangs, then runs `npm run build` (wireit/esbuild) and `npm run build:sfe` (rollup). Output includes `dist/` and `authentik/` static directories.
|
|
||||||
|
|
||||||
## Build Details
|
|
||||||
|
|
||||||
- **Node.js:** `nodejs_24` (authentik requires Node >= 24, npm >= 11.6.2)
|
|
||||||
- **Build time:** ~33s on ringtail (x86_64-linux)
|
|
||||||
- **FOD hash:** Platform-specific — will need updating on each authentik version bump
|
|
||||||
- **Output:** `$out/dist/` (JS/CSS bundles) and `$out/authentik/` (static SVG/PNG icons)
|
|
||||||
- **Consumed by:** Go server (`authentik-server.nix` via `webui` parameter) for static file serving, and `authentik-django.nix` for email template icon paths
|
|
||||||
- **Docusaurus website** (`/help` endpoint) is not built — optional and can be added later
|
|
||||||
|
|
||||||
## Key Lessons
|
|
||||||
|
|
||||||
- The 2026.2.0 build switched from rollup to esbuild for the main frontend. Only the SFE sub-package still uses rollup.
|
|
||||||
- The version string in `packages/core/version/node.js` uses a JSON import-with-assertion that doesn't resolve in the Nix sandbox — must be patched to hardcode the version.
|
|
||||||
- `NODE_OPTIONS=--openssl-legacy-provider` is needed for compatibility.
|
|
||||||
- Workspace packages have separate `node_modules/` directories — the FOD must collect all of them via `find`.
|
|
||||||
|
|
||||||
## Related
|
|
||||||
|
|
||||||
- [[build-authentik-from-source]] — Parent goal
|
|
||||||
- [[authentik-api-client-generation]] — Provides TypeScript client (prerequisite)
|
|
||||||
|
|
@ -21,7 +21,7 @@ The nix-container-builder runner on ringtail resolves `nixpkgs` via the NixOS ni
|
||||||
Authentik has four build components assembled by `containers/authentik/default.nix`:
|
Authentik has four build components assembled by `containers/authentik/default.nix`:
|
||||||
|
|
||||||
1. **API client generation** (`client-go.nix`, `client-ts.nix`) — Go and TypeScript bindings generated from `schema.yml` (OpenAPI)
|
1. **API client generation** (`client-go.nix`, `client-ts.nix`) — Go and TypeScript bindings generated from `schema.yml` (OpenAPI)
|
||||||
2. **Python backend** (`authentik-django.nix`) — Django application with 60+ Python dependencies installed via `uv` from PyPI (see [[authentik-python-backend-derivation]])
|
2. **Python backend** (`authentik-django.nix`) — Django application with 60+ Python dependencies installed via `uv` from PyPI (see [[authentik-nix-build-components#Python Backend]])
|
||||||
3. **Web UI** (`webui.nix`) — Lit-based TypeScript frontend built with esbuild + rollup
|
3. **Web UI** (`webui.nix`) — Lit-based TypeScript frontend built with esbuild + rollup
|
||||||
4. **Go server** (`authentik-server.nix`) — HTTP server binary that serves the web UI and spawns gunicorn for Django
|
4. **Go server** (`authentik-server.nix`) — HTTP server binary that serves the web UI and spawns gunicorn for Django
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -32,4 +32,4 @@ Previously, `authentik-community/django-rest-framework` (a DRF fork) was also ne
|
||||||
## Related
|
## Related
|
||||||
|
|
||||||
- [[build-authentik-from-source]] — Parent goal
|
- [[build-authentik-from-source]] — Parent goal
|
||||||
- [[authentik-api-client-generation]] — Consumes client-go mirror
|
- [[authentik-nix-build-components]] — Consumes client-go mirror
|
||||||
|
|
|
||||||
38
docs/how-to/deployment/build-caddy-with-plugins.md
Normal file
38
docs/how-to/deployment/build-caddy-with-plugins.md
Normal file
|
|
@ -0,0 +1,38 @@
|
||||||
|
---
|
||||||
|
title: Build Caddy with Plugins
|
||||||
|
modified: 2026-03-15
|
||||||
|
last-reviewed: 2026-03-15
|
||||||
|
tags:
|
||||||
|
- how-to
|
||||||
|
- caddy
|
||||||
|
- networking
|
||||||
|
---
|
||||||
|
|
||||||
|
# Build Caddy with Plugins
|
||||||
|
|
||||||
|
Caddy is built from source using `xcaddy` with two plugins:
|
||||||
|
|
||||||
|
- `github.com/caddy-dns/gandi` — ACME DNS-01 challenges via Gandi API
|
||||||
|
- `github.com/mholt/caddy-l4` — Layer 4 (TCP/UDP) proxying
|
||||||
|
|
||||||
|
## How to Build
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Source and build location (mirrored on forge)
|
||||||
|
~/code/3rd/caddy/bin/caddy
|
||||||
|
|
||||||
|
# Build via mise task in the caddy clone
|
||||||
|
cd ~/code/3rd/caddy && mise run build
|
||||||
|
```
|
||||||
|
|
||||||
|
## Forge Mirrors
|
||||||
|
|
||||||
|
- `mirrors/caddy`
|
||||||
|
- `mirrors/caddy-gandi`
|
||||||
|
- `mirrors/xcaddy`
|
||||||
|
- `mirrors/caddy-l4`
|
||||||
|
|
||||||
|
## Related
|
||||||
|
|
||||||
|
- [[caddy]] — Service reference card
|
||||||
|
- [[routing]] — Service routing architecture
|
||||||
|
|
@ -1,40 +0,0 @@
|
||||||
---
|
|
||||||
title: Build Grafana Container
|
|
||||||
modified: 2026-02-28
|
|
||||||
last-reviewed: 2026-02-28
|
|
||||||
tags:
|
|
||||||
- how-to
|
|
||||||
- grafana
|
|
||||||
- containers
|
|
||||||
---
|
|
||||||
|
|
||||||
# Build Grafana Container
|
|
||||||
|
|
||||||
Home-built Grafana container image published to `registry.ops.eblu.me/blumeops/grafana`.
|
|
||||||
|
|
||||||
## How It Works
|
|
||||||
|
|
||||||
The Dockerfile at `containers/grafana/Dockerfile` downloads the official Grafana OSS tarball for the target architecture (arm64/amd64), installs it into Alpine, and sets up standard paths.
|
|
||||||
|
|
||||||
To build and push a new version:
|
|
||||||
|
|
||||||
```fish
|
|
||||||
# Update version in Dockerfile
|
|
||||||
# ARG CONTAINER_APP_VERSION=12.3.3
|
|
||||||
|
|
||||||
mise run container-build-and-release grafana
|
|
||||||
```
|
|
||||||
|
|
||||||
## Gotchas
|
|
||||||
|
|
||||||
- **Tarball directory name:** Extracts to `grafana-<version>` (e.g. `grafana-12.3.3`), *not* `grafana-v<version>`.
|
|
||||||
- **Binary PATH:** The binary lives at `bin/grafana` inside the extracted directory. The Dockerfile sets `ENV PATH="/usr/share/grafana/bin:$PATH"`.
|
|
||||||
- **UID 472:** Matches the official Grafana image for PVC ownership compatibility.
|
|
||||||
|
|
||||||
## Related
|
|
||||||
|
|
||||||
- [[grafana]] — Service reference card
|
|
||||||
- [[upgrade-grafana]] — Migration context
|
|
||||||
- [[kustomize-grafana-deployment]] — Kustomize manifest structure
|
|
||||||
- [[build-grafana-sidecar]] — Home-built sidecar container
|
|
||||||
- [[build-container-image]] — Standard container build workflow
|
|
||||||
60
docs/how-to/grafana/build-grafana-images.md
Normal file
60
docs/how-to/grafana/build-grafana-images.md
Normal file
|
|
@ -0,0 +1,60 @@
|
||||||
|
---
|
||||||
|
title: Build Grafana Images
|
||||||
|
modified: 2026-03-15
|
||||||
|
last-reviewed: 2026-03-15
|
||||||
|
tags:
|
||||||
|
- how-to
|
||||||
|
- grafana
|
||||||
|
- containers
|
||||||
|
---
|
||||||
|
|
||||||
|
# Build Grafana Images
|
||||||
|
|
||||||
|
Home-built container images for Grafana and its dashboard sidecar, published to `registry.ops.eblu.me/blumeops/`.
|
||||||
|
|
||||||
|
## Grafana
|
||||||
|
|
||||||
|
**Dockerfile:** `containers/grafana/Dockerfile`
|
||||||
|
**Image:** `registry.ops.eblu.me/blumeops/grafana`
|
||||||
|
|
||||||
|
Downloads the official Grafana OSS tarball for the target architecture (arm64/amd64), installs it into Alpine, and sets up standard paths.
|
||||||
|
|
||||||
|
```fish
|
||||||
|
# Update version in Dockerfile
|
||||||
|
# ARG CONTAINER_APP_VERSION=12.3.3
|
||||||
|
|
||||||
|
mise run container-build-and-release grafana
|
||||||
|
```
|
||||||
|
|
||||||
|
**Gotchas:**
|
||||||
|
|
||||||
|
- **Tarball directory name:** Extracts to `grafana-<version>` (e.g. `grafana-12.3.3`), *not* `grafana-v<version>`.
|
||||||
|
- **Binary PATH:** The binary lives at `bin/grafana` inside the extracted directory. The Dockerfile sets `ENV PATH="/usr/share/grafana/bin:$PATH"`.
|
||||||
|
- **UID 472:** Matches the official Grafana image for PVC ownership compatibility.
|
||||||
|
|
||||||
|
## Grafana Sidecar
|
||||||
|
|
||||||
|
**Dockerfile:** `containers/grafana-sidecar/Dockerfile`
|
||||||
|
**Image:** `registry.ops.eblu.me/blumeops/grafana-sidecar`
|
||||||
|
|
||||||
|
Clones the [kiwigrid/k8s-sidecar](https://github.com/kiwigrid/k8s-sidecar) source from the forge mirror, installs Python dependencies into a venv, and copies the application into a minimal Alpine runtime image.
|
||||||
|
|
||||||
|
```fish
|
||||||
|
# Update version in Dockerfile
|
||||||
|
# ARG CONTAINER_APP_VERSION=1.28.0
|
||||||
|
|
||||||
|
mise run container-build-and-release grafana-sidecar
|
||||||
|
```
|
||||||
|
|
||||||
|
**Gotchas:**
|
||||||
|
|
||||||
|
- **Pinned to v1.28.0:** v2.x has a 135% memory regression ([#462](https://github.com/kiwigrid/k8s-sidecar/issues/462)) and `readOnlyRootFilesystem` crashloop ([#3936](https://github.com/grafana/helm-charts/issues/3936)). Upgrade separately after upstream fixes land.
|
||||||
|
- **UID 65534:** Matches upstream's `nobody` user convention for non-root execution.
|
||||||
|
- **Forge mirror name:** `mirrors/kiwigrid-grafana-sidecar` (not `k8s-sidecar`).
|
||||||
|
|
||||||
|
## Related
|
||||||
|
|
||||||
|
- [[grafana]] — Service reference card
|
||||||
|
- [[upgrade-grafana]] — Migration context and future upgrade steps
|
||||||
|
- [[kustomize-grafana-deployment]] — Kustomize manifest structure
|
||||||
|
- [[build-container-image]] — Standard container build workflow
|
||||||
|
|
@ -1,39 +0,0 @@
|
||||||
---
|
|
||||||
title: Build Grafana Sidecar
|
|
||||||
modified: 2026-03-03
|
|
||||||
last-reviewed: 2026-03-03
|
|
||||||
tags:
|
|
||||||
- how-to
|
|
||||||
- grafana
|
|
||||||
- containers
|
|
||||||
---
|
|
||||||
|
|
||||||
# Build Grafana Sidecar
|
|
||||||
|
|
||||||
Home-built k8s-sidecar container image published to `registry.ops.eblu.me/blumeops/grafana-sidecar`.
|
|
||||||
|
|
||||||
## How It Works
|
|
||||||
|
|
||||||
The Dockerfile at `containers/grafana-sidecar/Dockerfile` clones the [kiwigrid/k8s-sidecar](https://github.com/kiwigrid/k8s-sidecar) source from the forge mirror, installs Python dependencies into a venv, and copies the application into a minimal Alpine runtime image.
|
|
||||||
|
|
||||||
To build and push a new version:
|
|
||||||
|
|
||||||
```fish
|
|
||||||
# Update version in Dockerfile
|
|
||||||
# ARG CONTAINER_APP_VERSION=1.28.0
|
|
||||||
|
|
||||||
mise run container-build-and-release grafana-sidecar
|
|
||||||
```
|
|
||||||
|
|
||||||
## Gotchas
|
|
||||||
|
|
||||||
- **Pinned to v1.28.0:** v2.x has a 135% memory regression ([#462](https://github.com/kiwigrid/k8s-sidecar/issues/462)) and `readOnlyRootFilesystem` crashloop ([#3936](https://github.com/grafana/helm-charts/issues/3936)). Upgrade separately after upstream fixes land.
|
|
||||||
- **UID 65534:** Matches upstream's `nobody` user convention for non-root execution.
|
|
||||||
- **Forge mirror name:** `mirrors/kiwigrid-grafana-sidecar` (not `k8s-sidecar`).
|
|
||||||
|
|
||||||
## Related
|
|
||||||
|
|
||||||
- [[grafana]] — Service reference card
|
|
||||||
- [[build-grafana-container]] — Home-built Grafana container
|
|
||||||
- [[kustomize-grafana-deployment]] — Kustomize manifest structure
|
|
||||||
- [[build-container-image]] — Standard container build workflow
|
|
||||||
|
|
@ -34,5 +34,5 @@ Grafana is deployed via plain Kustomize manifests in `argocd/manifests/grafana/`
|
||||||
## Related
|
## Related
|
||||||
|
|
||||||
- [[upgrade-grafana]] — Migration context
|
- [[upgrade-grafana]] — Migration context
|
||||||
- [[build-grafana-sidecar]] — Home-built sidecar container
|
- [[build-grafana-images]] — Home-built container images
|
||||||
- [[grafana]] — Service reference card
|
- [[grafana]] — Service reference card
|
||||||
|
|
|
||||||
|
|
@ -43,6 +43,5 @@ The SQLite PVC is disposable — dashboards come from ConfigMaps and datasources
|
||||||
## Related
|
## Related
|
||||||
|
|
||||||
- [[grafana]] — Service reference card
|
- [[grafana]] — Service reference card
|
||||||
- [[build-grafana-container]] — Building the container image
|
- [[build-grafana-images]] — Building the container images
|
||||||
- [[build-grafana-sidecar]] — Building the dashboard sidecar image
|
|
||||||
- [[kustomize-grafana-deployment]] — Kustomize manifest structure
|
- [[kustomize-grafana-deployment]] — Kustomize manifest structure
|
||||||
|
|
|
||||||
|
|
@ -87,20 +87,7 @@ Caddy has no authentication layer — it is a plain reverse proxy. Access contro
|
||||||
|
|
||||||
## Custom Build
|
## Custom Build
|
||||||
|
|
||||||
Caddy is built from source using `xcaddy` with two plugins:
|
Custom `xcaddy` build with Gandi DNS and L4 plugins. See [[build-caddy-with-plugins]] for build instructions and forge mirror details.
|
||||||
|
|
||||||
- `github.com/caddy-dns/gandi` — ACME DNS-01 challenges via Gandi API
|
|
||||||
- `github.com/mholt/caddy-l4` — Layer 4 (TCP/UDP) proxying
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Source and build location (mirrored on forge)
|
|
||||||
~/code/3rd/caddy/bin/caddy
|
|
||||||
|
|
||||||
# Build via mise task in the caddy clone
|
|
||||||
cd ~/code/3rd/caddy && mise run build
|
|
||||||
```
|
|
||||||
|
|
||||||
Forge mirrors: `mirrors/caddy`, `mirrors/caddy-gandi`, `mirrors/xcaddy`, `mirrors/caddy-l4`.
|
|
||||||
|
|
||||||
## Related
|
## Related
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -59,8 +59,7 @@ Optional annotation: `grafana_folder: "FolderName"`
|
||||||
|
|
||||||
## Related
|
## Related
|
||||||
|
|
||||||
- [[build-grafana-container]] - Home-built container image
|
- [[build-grafana-images]] - Home-built container images (Grafana + sidecar)
|
||||||
- [[build-grafana-sidecar]] - Home-built sidecar container
|
|
||||||
- [[kustomize-grafana-deployment]] - Kustomize manifest structure
|
- [[kustomize-grafana-deployment]] - Kustomize manifest structure
|
||||||
- [[authentik]] - OIDC identity provider for SSO
|
- [[authentik]] - OIDC identity provider for SSO
|
||||||
- [[migrate-grafana-to-authentik]] - How SSO was migrated from Dex to Authentik
|
- [[migrate-grafana-to-authentik]] - How SSO was migrated from Dex to Authentik
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
---
|
---
|
||||||
title: Expose a Service Publicly
|
title: Expose a Service Publicly
|
||||||
modified: 2026-03-03
|
modified: 2026-03-15
|
||||||
last-reviewed: 2026-03-03
|
last-reviewed: 2026-03-03
|
||||||
tags:
|
tags:
|
||||||
- how-to
|
- tutorials
|
||||||
- fly-io
|
- fly-io
|
||||||
- tailscale
|
- tailscale
|
||||||
- networking
|
- networking
|
||||||
Loading…
Add table
Add a link
Reference in a new issue