blumeops/containers/authentik/default.nix
Erich Blume fd0bebb0fc
All checks were successful
Build Container / detect (push) Successful in 3s
Build Container / build-dockerfile (alloy) (push) Successful in 12s
Build Container / build-dockerfile (ntfy) (push) Successful in 11s
Build Container / build-nix (alloy) (push) Successful in 20s
Build Container / build-nix (authentik) (push) Successful in 6m10s
Build Container / build-nix (authentik-redis) (push) Successful in 20s
Build Container / build-nix (ntfy) (push) Successful in 6s
Localize authentik-redis container (#309)
## Summary

- Replace upstream `docker.io/library/redis:7-alpine` (Redis 7.4.8) with a nix-built container using Redis 8.2.3 from nixpkgs
- Introduce **attached service pattern**: `parent` field in service-versions.yaml, `<parent>-<component>` naming convention, and `assert pkgs.redis.version == version` in default.nix to prevent silent version drift on `flake.lock` updates
- Document the pattern in [[review-services]] so future attached services slot in cleanly
- Backfill `parent: grafana` on existing `grafana-sidecar` entry

## Version drift protection

1. `flake.lock` update bumps nixpkgs redis → `assert` in `default.nix` breaks `nix-build`
2. Developer updates `version` in `default.nix` → prek's `container-version-check` demands matching `service-versions.yaml` update
3. Both must agree before commit succeeds

## Test plan

- [ ] Build container from branch on ringtail (`mise run container-build-and-release authentik-redis`)
- [ ] Update kustomization `newTag` to branch-built image tag
- [ ] Sync authentik ArgoCD app from branch (`argocd app set authentik --revision localize-redis && argocd app sync authentik`)
- [ ] Verify Authentik login, session persistence, and task queue still work
- [ ] After merge: C0 follow-up to update `newTag` to the main-built image tag

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Reviewed-on: #309
2026-03-24 13:27:36 -07:00

76 lines
2.7 KiB
Nix

# 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
sources = import ./sources.nix { inherit pkgs; };
# Duplicated from sources.nix so build-container-nix.yaml can grep it
version = "2026.2.0";
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" ''
for item in ${authentik-django}/blueprints/*/; do
name=$(basename "$item")
[ ! -e "/blueprints/$name" ] && ln -s "$item" "/blueprints/$name" 2>/dev/null || true
done
exec ${ak}/bin/ak "$@"
'';
in
pkgs.dockerTools.buildLayeredImage {
name = "blumeops/authentik";
contents = [
ak
authentik-django
authentik-server
pkgs.bashInteractive
pkgs.coreutils
pkgs.cacert
pkgs.tzdata
];
# Create /blueprints as world-writable so user 65534 can create symlinks at runtime.
# 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 tmp
chmod 777 blueprints tmp
'';
config = {
Entrypoint = [ "${entrypoint}" ];
Env = [
"SSL_CERT_FILE=${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt"
"TZDIR=${pkgs.tzdata}/share/zoneinfo"
"TMPDIR=/tmp"
"AUTHENTIK_BLUEPRINTS_DIR=/blueprints"
];
ExposedPorts = {
"9000/tcp" = { };
"9443/tcp" = { };
};
User = "65534";
};
}