C2(authentik-source-build): impl assemble components into container image
Wire webui → authentik-django → authentik-server and replace pkgs.authentik with custom source-built derivations. The ak wrapper sets PATH/VIRTUAL_ENV and delegates to lifecycle/ak. Tested on ringtail with nix-build test-build.nix -A assembled. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
f58fa079be
commit
6ea5011739
3 changed files with 68 additions and 17 deletions
|
|
@ -9,13 +9,20 @@
|
|||
#
|
||||
# autoPatchelfHook restores RPATHs that were stripped in the FOD.
|
||||
#
|
||||
# Optional input: webui derivation. When provided, resolves @webui@ store
|
||||
# path placeholders in Python source. When null (default), leaves placeholders
|
||||
# for isolated testing.
|
||||
#
|
||||
# Output:
|
||||
# $out/bin/python3.14 venv python (symlink to nix python314)
|
||||
# $out/lib/python3.14/site-packages/ all Python packages
|
||||
# $out/lifecycle/ lifecycle scripts (symlink)
|
||||
# $out/blueprints/ YAML blueprints
|
||||
# $out/manage.py Django management script
|
||||
{ pkgs ? import <nixpkgs> { }, sources ? import ./sources.nix { inherit pkgs; } }:
|
||||
{ pkgs ? import <nixpkgs> { }
|
||||
, sources ? import ./sources.nix { inherit pkgs; }
|
||||
, webui ? null
|
||||
}:
|
||||
|
||||
let
|
||||
python-deps = import ./python-deps.nix { inherit pkgs sources; };
|
||||
|
|
@ -28,6 +35,9 @@ let
|
|||
hash = "sha256-Q6SJed0K6eIrqQ9mNAD4RGx+YCJvnI5E+0KGp5fBtTU=";
|
||||
};
|
||||
|
||||
# When webui is provided, resolve paths directly; otherwise use placeholder
|
||||
webuiPath = if webui != null then "${webui}" else "@webui@";
|
||||
|
||||
sp = "$out/lib/python3.14/site-packages";
|
||||
in
|
||||
|
||||
|
|
@ -122,9 +132,9 @@ pkgs.stdenv.mkDerivation {
|
|||
# Web asset paths: placeholder @webui@ for Go server card to resolve
|
||||
substituteInPlace ${sp}/authentik/stages/email/utils.py \
|
||||
--replace-fail 'Path("web/icons/icon_left_brand.png")' \
|
||||
'Path("@webui@/icons/icon_left_brand.png")' \
|
||||
'Path("${webuiPath}/icons/icon_left_brand.png")' \
|
||||
--replace-fail 'Path("web/dist/assets/icons/icon_left_brand.png")' \
|
||||
'Path("@webui@/dist/assets/icons/icon_left_brand.png")'
|
||||
'Path("${webuiPath}/dist/assets/icons/icon_left_brand.png")'
|
||||
|
||||
# Lifecycle bash script: use Nix store bash (no /usr/bin/env in containers)
|
||||
substituteInPlace ${sp}/lifecycle/ak \
|
||||
|
|
|
|||
|
|
@ -1,19 +1,39 @@
|
|||
# Nix-built Authentik identity provider
|
||||
# Uses nixpkgs authentik package (ak entrypoint wrapping Go server + Python worker)
|
||||
# Built with dockerTools.buildLayeredImage for efficient layer caching
|
||||
# Nix-built Authentik identity provider (from source)
|
||||
#
|
||||
# Assembles four component derivations into a container image:
|
||||
# 1. webui — Lit frontend (esbuild + rollup)
|
||||
# 2. authentik-django — Python backend + lifecycle scripts
|
||||
# 3. authentik-server — Go HTTP server binary
|
||||
# 4. ak wrapper — sets PATH/VIRTUAL_ENV, delegates to lifecycle/ak
|
||||
#
|
||||
# Built with dockerTools.buildLayeredImage for efficient layer caching.
|
||||
{ pkgs ? import <nixpkgs> { } }:
|
||||
|
||||
let
|
||||
# Wrapper entrypoint that sets up /blueprints symlinks before running ak.
|
||||
# buildLayeredImage's extraCommands can't access store paths from contents (they're
|
||||
# in separate layers), so we create the symlinks at container start instead.
|
||||
sources = import ./sources.nix { inherit pkgs; };
|
||||
webui = import ./webui.nix { inherit pkgs sources; };
|
||||
authentik-django = import ./authentik-django.nix { inherit pkgs sources webui; };
|
||||
authentik-server = import ./authentik-server.nix { inherit pkgs sources authentik-django webui; };
|
||||
|
||||
# Wrapper that provides bin/ak with the correct runtime environment.
|
||||
# lifecycle/ak dispatches: "server" → Go binary, "worker"/"migrate"/etc → Python.
|
||||
ak = pkgs.writeShellScriptBin "ak" ''
|
||||
export PYTHONDONTWRITEBYTECODE=1
|
||||
export PATH="${authentik-server}/bin:${authentik-django}/bin:$PATH"
|
||||
export VIRTUAL_ENV="${authentik-django}"
|
||||
cd "${authentik-django}"
|
||||
exec "${authentik-django}/lifecycle/ak" "$@"
|
||||
'';
|
||||
|
||||
# Container entrypoint: symlink built-in blueprints then run ak.
|
||||
# buildLayeredImage's extraCommands can't access store paths from contents
|
||||
# (they're in separate layers), so we create the symlinks at container start.
|
||||
entrypoint = pkgs.writeShellScript "authentik-entrypoint" ''
|
||||
# Link built-in blueprint dirs from the Nix store into /blueprints
|
||||
for item in /nix/store/*authentik-django*/blueprints/*/; do
|
||||
for item in ${authentik-django}/blueprints/*/; do
|
||||
name=$(basename "$item")
|
||||
[ ! -e "/blueprints/$name" ] && ln -s "$item" "/blueprints/$name" 2>/dev/null || true
|
||||
done
|
||||
exec ${pkgs.authentik}/bin/ak "$@"
|
||||
exec ${ak}/bin/ak "$@"
|
||||
'';
|
||||
in
|
||||
|
||||
|
|
@ -22,7 +42,9 @@ pkgs.dockerTools.buildLayeredImage {
|
|||
tag = "latest";
|
||||
|
||||
contents = [
|
||||
pkgs.authentik
|
||||
ak
|
||||
authentik-django
|
||||
authentik-server
|
||||
pkgs.bashInteractive
|
||||
pkgs.coreutils
|
||||
pkgs.cacert
|
||||
|
|
@ -30,9 +52,8 @@ pkgs.dockerTools.buildLayeredImage {
|
|||
];
|
||||
|
||||
# Create /blueprints as world-writable so user 65534 can create symlinks at runtime.
|
||||
# The nixpkgs authentik-django package hardcodes blueprints_dir to its Nix store path,
|
||||
# making custom blueprints mounted at /blueprints/custom invisible. The entrypoint
|
||||
# wrapper populates this directory with symlinks to built-in blueprints on each start.
|
||||
# authentik-django hardcodes blueprints_dir to $out/blueprints; the AUTHENTIK_BLUEPRINTS_DIR
|
||||
# env var overrides it to /blueprints, where custom blueprints are mounted by k8s ConfigMap.
|
||||
extraCommands = ''
|
||||
mkdir -p blueprints
|
||||
chmod 777 blueprints
|
||||
|
|
|
|||
|
|
@ -9,16 +9,36 @@
|
|||
# nix-build test-build.nix -A authentik-server --extra-experimental-features 'nix-command flakes'
|
||||
# nix-build test-build.nix -A webui-deps --extra-experimental-features 'nix-command flakes'
|
||||
# nix-build test-build.nix -A webui --extra-experimental-features 'nix-command flakes'
|
||||
# nix-build test-build.nix -A assembled --extra-experimental-features 'nix-command flakes'
|
||||
let
|
||||
pkgs = (builtins.getFlake "nixpkgs").legacyPackages.x86_64-linux;
|
||||
sources = import ./sources.nix { inherit pkgs; };
|
||||
|
||||
# Individual components (isolated, no cross-wiring)
|
||||
_webui = import ./webui.nix { inherit pkgs sources; };
|
||||
|
||||
# Fully wired assembly (webui → authentik-django → authentik-server)
|
||||
_authentik-django-assembled = import ./authentik-django.nix { inherit pkgs sources; webui = _webui; };
|
||||
_authentik-server-assembled = import ./authentik-server.nix {
|
||||
inherit pkgs sources;
|
||||
authentik-django = _authentik-django-assembled;
|
||||
webui = _webui;
|
||||
};
|
||||
in
|
||||
{
|
||||
# Individual component builds (for debugging in isolation)
|
||||
python-deps = import ./python-deps.nix { inherit pkgs sources; };
|
||||
authentik-django = import ./authentik-django.nix { inherit pkgs sources; };
|
||||
client-go = import ./client-go.nix { inherit pkgs sources; };
|
||||
client-ts = import ./client-ts.nix { inherit pkgs sources; };
|
||||
authentik-server = import ./authentik-server.nix { inherit pkgs sources; };
|
||||
webui-deps = import ./webui-deps.nix { inherit pkgs sources; };
|
||||
webui = import ./webui.nix { inherit pkgs sources; };
|
||||
webui = _webui;
|
||||
|
||||
# Fully assembled stack — tests that all components wire together
|
||||
assembled = pkgs.linkFarm "authentik-assembled-${sources.version}" [
|
||||
{ name = "authentik-django"; path = _authentik-django-assembled; }
|
||||
{ name = "authentik-server"; path = _authentik-server-assembled; }
|
||||
{ name = "webui"; path = _webui; }
|
||||
];
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue