lab1 is now published with proxyAllowedZones: [internet]. Enabling OAuth does
not disable Portainer's internal login — POST /api/auth stays live and still
accepts the break-glass admin, confirmed against the public endpoint (422
Invalid credentials, not a refused path). So publishing the console publishes a
password path too; the remedy, if that is unacceptable, is to promote an OIDC
user to administrator and delete the local admin, at the cost of break-glass.
Also records that the operator's admin-VPN overlay (admin, 10.255.1.0/24) is
not in the internal default allow-set, which is why a remote admin on the
WireGuard tunnel also gets 403.
Podman is the container foundation, Portainer CE is the web interface onto it,
running as a container on the very engine it manages. This is what the separate
portainer module already did, so it is retired rather than duplicated.
Two sockets on purpose: the rootful one is the Docker-compatible API Portainer
drives (it does not support rootless), the rootless user socket is for people
who ssh in and run containers by hand — which was the original podman module's
point and is worth keeping.
An explicit proxyDomain lets the module publish at the environment's own domain
instead of <module>.<environment-domain>, making it that environment's gateway.
DESIGN.md keeps the Cockpit identity analysis: it is the reason for the change,
and anyone proposing 'just put Cockpit behind forward-auth' should read it.
Portainer stops accepting POST /api/users/admin/init a few minutes after start
and answers 303 with Redirect-Reason: AdminInitTimeout. Any transient failure
during that window therefore made the module permanently un-bootstrappable.
update.sh now restarts the container to reset the timer, waits for the API and
retries once, re-reading the setup token because a fresh one is minted at every
start.
Also splits the OIDC precondition: the single condition reported the secrets env
as missing whenever the admin session was absent, which is what sent the first
debugging pass down the wrong path.
The previous guard was 'does the password file exist'. The first lab1 install
wrote the password, then failed init on the missing setup token — leaving a file
that made every later run skip the bootstrap and then fail to authenticate, so
OIDC never got configured. Ask Portainer instead: try /api/auth, and bootstrap
only when that yields no token. The JWT is then reused for the settings PUT
rather than logging in twice.
First live install on lab1 surfaced two bugs.
Portainer 2.39.6 refuses POST /api/users/admin/init with 403 unless the
X-Setup-Token header carries the token it prints once at startup; update.sh now
reads it out of podman logs, matching the 64-hex value because the log line puts
ANSI colour codes between the key and the token.
The domain fallback asked get_variant_config for the DEFAULT environment, so a
module installed into lab1 advertised portainer-lab1.makerfloss.eu while Caddy
actually publishes portainer-lab1.lab1.makerfloss.eu — which would also have put
a mismatched RedirectURI into Portainer's OAuth settings. It now derives from the
module's own environment, as identity/install-service.sh does.
Confirmed on the live system: identity:identity works — the OIDC application is
created and /etc/secrets/portainer.env is written before install.sh runs.
portainer: Portainer CE on rootful podman (Portainer drives the
Docker-compatible API, and rootless is not supported upstream), published via
network:proxy with proxyAllowedZones left unset so members reach it from a
client zone but the internet does not. Login is OIDC: identity:identity writes
the client credentials, update.sh resolves the endpoints from the discovery
document and PUTs them into /api/settings. A break-glass local admin stays for
when Authentik is down. Multi-host is the agent on :9001 per host.
komodo: scaffold only — komodo.json plus a README that specifies what
install.sh and update.sh must do. GPL, no edition split, but it needs a
database and models builds and stacks, so it is the alternative rather than
the teaching example.
Neither has been run on a live TAPPaaS yet; both are catalogued as incomplete.
Cockpit is not an OIDC client and cannot be configured into one, so
identity:identity is the wrong dependency. Records the three real options —
accessControl URL gating, an Authentik LDAP outpost with SSSD, and a custom
Cockpit auth command — with the recommendation to take the first, raise the
second upstream, and leave the third alone.
Also flags that accessControl's install-service requires proxyDomain in the
resolved config and, unlike identity's, does not derive it — to verify on a
live install before relying on it.
repository.sh takes the URL positionally (name is derived from it), clones over
https, and defaults to the stable branch — which this repo does not have.
README, a module-catalog.json validated against TAPPaaS's
module-catalog-fields.json, and the podman module copied verbatim from
Community/src/larsrossen/containers/podman into a flat src/containers/ layout
(the catalog carries the explicit moduleJson path, so layout is free).