- Dockerfile 48.6%
- Shell 26.4%
- Python 25%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
Jobs reach a docker:dind sidecar over DOCKER_HOST rather than a host Docker socket. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> |
||
| .forgejo/workflows | ||
| test | ||
| .gitignore | ||
| Dockerfile | ||
| README.md | ||
hitoma-authentik
goauthentik/authentik moved onto a Wolfi userland. It's built from the latest release in a pinned series. Upstream's server image is based on Debian trixie and has around 60 HIGH/CRITICAL findings in OS packages that Authentik doesn't use. This image takes the finished app from ghcr.io/goauthentik/server and installs only the runtime libraries it links against, all from Wolfi. Differences from upstream:
- Wolfi instead of Debian. No apt, util-linux or other Debian userland. Wolfi uses glibc, so upstream's compiled code runs unchanged.
- Not FIPS. Python and OpenSSL come from Wolfi instead of upstream's FIPS builds of each.
- Rebuilt native extensions.
cryptography,lxmlandxmlsecare compiled here against Wolfi's OpenSSL 4 and libxml2 2.15, at the versions in upstream'suv.lock. Upstream's builds target Debian's OpenSSL 3 and libxml2 2.13, which aren't binary-compatible with Wolfi's. - Patched Python packages. Packages with known fixes that upstream's lock doesn't have yet are bumped (
SECURITY_OVERRIDESin the Dockerfile). Each override applies only while upstream's version is older, and the build log says when one can be removed. Upstream pins PyJWT exactly, so the PyJWT override goes against that pin. - No debug mode extras. With
AUTHENTIK_DEBUGGERset, upstream installs debugging packages with apt and uv. Neither exists here.
Ports, volumes, environment variables, the authentik user (uid 1000), the entrypoint and the healthcheck all match upstream. This is a drop-in replacement for ghcr.io/goauthentik/server for both the server and worker commands, including a worker running as root.
docker pull forgejo.hitoma.com/root/hitoma-authentik:2026.8
Only the server image is rebuilt. The embedded outpost inside the server covers proxy and forward-auth. Standalone outposts (ghcr.io/goauthentik/proxy, ldap, radius, rac) still come from upstream.
Tests
Every build has to pass both of these before it's pushed:
- test/verify-image.sh, which needs no database:
- every native extension and the
authentikbinary find all their shared libraries - Python and
cryptographyload the same OpenSSL, andlxmlandxmlsecthe same libxml2 - psycopg uses its C implementation
- the root startup path can drop privileges with
setpriv
- every native extension and the
- test/smoke.sh, against Postgres, with the server and a root worker:
- both containers become healthy, and the logs show no errors
- the login page loads and the embedded outpost answers
- passwords are checked, and an RS256 JWT round-trips (as in OIDC)
- SAML metadata is signed, the signature verifies, and tampering is detected
Both run locally too: test/verify-image.sh IMAGE, then test/smoke.sh IMAGE.
CI
.forgejo/workflows/build.yml builds on every push to main, weekly (Monday 07:17 UTC, without cache, so Wolfi updates are picked up), and on manual dispatch. Dispatch takes an optional version input to build a specific release. Pull requests are built and tested but not pushed. The workflow only resolves the authentik version. Building, testing, scanning and pushing happen in the shared hitoma-image-ci pipeline.
- Authentik version: the newest non-prerelease release in
AUTHENTIK_SERIES(currently2026.8). A new series is never picked up automatically, because it runs database migrations that can't be rolled back. BumpAUTHENTIK_SERIESin the workflow to move to it, after reading upstream's release notes. - Architecture: whatever the runner is. The image isn't built multi-arch.
- Memory: native extensions build one at a time, so a builder with 2 GB of RAM is enough.
If a Wolfi update breaks a rebuilt extension, the build, verify or smoke step fails and nothing is pushed. latest stays on the last good image.
Tags: latest, the series (2026.8), the upstream release (e.g. 2026.8.3), YYYYMMDD, and sha-<short>.
Each build is scanned with Trivy after it passes the tests. Builds of main force-push the badge above and the full JSON report to the single-commit badges branch.
- When the run fails: a fixable HIGH or CRITICAL finding fails the run, and a failed run emails whoever triggered it (the repo owner for scheduled runs). The image is still pushed, but the red run shows an update is needed. For a Python package, add the minimum fixed version to
SECURITY_OVERRIDES. - What doesn't fail it: findings with no fix available are counted on the badge only.
Setup:
- Repository secrets
REGISTRY_USERandREGISTRY_TOKEN(a Forgejo access token withwrite:packagescope). - A Forgejo runner with the
dockerlabel whose job containers can reach a Docker daemon, such as adocker:dindsidecar throughDOCKER_HOST. The smoke test starts its own containers on that daemon. - Actions enabled on the repository (Settings → Units → Actions).