This shows you the differences between two versions of the page.
| Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
| computing:keycloak [2026/10/10 01:13] – oemb1905 | computing:keycloak [2026/10/10 04:51] (current) – oemb1905 | ||
|---|---|---|---|
| Line 14: | Line 14: | ||
| ==== Introduction ==== | ==== Introduction ==== | ||
| - | Rootless Podman as user '' | ||
| - | ^ Role ^ Bind ^ Public ^ | + | This tutorial is for Debian users desiring to spin up an OCI container for Keycloak. |
| - | | Keycloak | + | |
| - | | Postgres | internal only | none | | + | |
| - | + | ||
| - | Images: | + | |
| * '' | * '' | ||
| * '' | * '' | ||
| - | Network: '' | + | Keycloak requires its own network |
| - | Data: '' | + | |
| - | Do not use '' | + | |
| ==== 1. Directory (worker) ==== | ==== 1. Directory (worker) ==== | ||
| < | < | ||
| mkdir -p ~/ | mkdir -p ~/ | ||
| - | </code> | + | podman pull docker.io/library/ |
| - | + | podman pull quay.io/ | |
| - | ==== 2. Network (worker) ==== | + | |
| - | < | + | |
| podman network exists keycloak_default || podman network create keycloak_default | podman network exists keycloak_default || podman network create keycloak_default | ||
| </ | </ | ||
| ==== 3. Secrets ==== | ==== 3. Secrets ==== | ||
| - | Placeholders used below: | + | |
| + | Now that we have the images and project directories, | ||
| < | < | ||
| - | POSTGRES_PASSWORD=replace-with-your-db-password | + | umask 077 |
| - | KC_BOOTSTRAP_ADMIN_PASSWORD=replace-with-your-bootstrap-admin-password | + | openssl rand -hex 32 > ~/keycloak/db.secret |
| + | openssl rand -hex 32 > ~/keycloak/bootstrap-admin.secret | ||
| + | chmod 600 ~/ | ||
| </ | </ | ||
| - | |||
| - | Bootstrap admin credentials apply only on an empty database. After the first start, change the admin password in the GUI. Do not rely on the env vars after that. | ||
| ==== 4. Quadlets ==== | ==== 4. Quadlets ==== | ||
| - | File: '' | + | |
| + | We can now safely create the quadlet | ||
| < | < | ||
| - | systemctl --user disable --now container-keycloak.service container-keycloak-postgres.service 2>/ | ||
| - | rm -f ~/ | ||
| - | ~/ | ||
| - | podman rm -f keycloak keycloak-postgres | ||
| - | |||
| - | mkdir -p ~/ | ||
| - | |||
| cat > ~/ | cat > ~/ | ||
| [Container] | [Container] | ||
| Line 109: | Line 96: | ||
| </ | </ | ||
| - | '' | + | ==== 5. Verify ==== |
| - | Keycloak depends on Postgres via the '' | + | Once you create |
| - | ==== 5. Verify ==== | ||
| < | < | ||
| systemctl --user is-active container-keycloak-postgres.service container-keycloak.service | systemctl --user is-active container-keycloak-postgres.service container-keycloak.service | ||
| Line 121: | Line 107: | ||
| </ | </ | ||
| - | Expect both '' | + | If everything is alright, we should see '' |
| ==== 6. Upgrade script ==== | ==== 6. Upgrade script ==== | ||
| - | ''/ | + | |
| + | OCI Containers aren't worth much without the ability to pull updates and patches quickly and painlessly. For me, a simple shell script gets this job done. Here's and example folks can tweak/edit to their liking: | ||
| < | < | ||
| #!/bin/bash | #!/bin/bash | ||
| set -euo pipefail | set -euo pipefail | ||
| + | export XDG_RUNTIME_DIR=/ | ||
| + | export DBUS_SESSION_BUS_ADDRESS=unix: | ||
| podman pull docker.io/ | podman pull docker.io/ | ||
| Line 144: | Line 133: | ||
| </ | </ | ||
| - | Run it as '' | + | Once this runs successfully, |
| - | < | + | ==== 7. Apache reverse proxy (root) ==== |
| - | su - worker -c '/ | + | |
| - | </ | + | |
| - | Do not ''sudo -u worker'' | + | Let's make sure the apache proxy/ |
| - | ==== 7. Apache reverse proxy (root) ==== | ||
| < | < | ||
| - | a2enmod proxy proxy_http proxy_wstunnel headers rewrite ssl | + | a2enmod proxy proxy_http proxy_wstunnel headers rewrite ssl authz_host |
| + | certbot certonly --apache -d auth.haacksnetworking.org | ||
| </ | </ | ||
| - | ''/ | + | Create the virtual host for http '' |
| < | < | ||
| Line 165: | Line 152: | ||
| RewriteRule ^ https:// | RewriteRule ^ https:// | ||
| </ | </ | ||
| + | </ | ||
| + | Likewise, create the virtual host for the tls block. You can optionally drop this underneath the http vhost, but/and I prefer them to be separate. | ||
| + | |||
| + | < | ||
| < | < | ||
| ServerName auth.haacksnetworking.org | ServerName auth.haacksnetworking.org | ||
| Line 184: | Line 175: | ||
| </ | </ | ||
| </ | </ | ||
| + | |||
| + | Finally, check the configurations, | ||
| < | < | ||
| Line 191: | Line 184: | ||
| </ | </ | ||
| - | '' | + | Check the output for any errors. In my notes, I had: '' |
| ==== 8. First login ==== | ==== 8. First login ==== | ||
| + | |||
| + | When you first open keycloak, you want to remove the temp password and set up the admin account and master realm. | ||
| + | |||
| - Open '' | - Open '' | ||
| - Administration Console | - Administration Console | ||
| Line 202: | Line 198: | ||
| * Frontend URL: '' | * Frontend URL: '' | ||
| * Require SSL: external requests (or all) | * Require SSL: external requests (or all) | ||
| - | |||
| - | Do not keep the bootstrap password. | ||
| ==== 9. Incus OIDC ==== | ==== 9. Incus OIDC ==== | ||
| - | Stay out of '' | ||
| - | **Realm** | + | We will now create a dedicated real for Incus' Web GUI called " |
| - | | + | |
| - | * Enabled: on | + | |
| - | Issuer | + | **Users** |
| - | '' | + | Create one user per person using these recommendations: |
| - | + | ||
| - | < | + | |
| - | curl -sI https:// | + | |
| - | </ | + | |
| - | + | ||
| - | Must be 200. The '' | + | |
| - | + | ||
| - | **Users** (in realm '' | + | |
| * Username for SSO | * Username for SSO | ||
| Line 230: | Line 214: | ||
| * Credentials → password, Temporary **off** | * Credentials → password, Temporary **off** | ||
| - | Create one user per human. Do not log into Incus as Keycloak '' | + | After you create the user account, you create |
| **Client** | **Client** | ||
| Line 243: | Line 227: | ||
| * Web origins: '' | * Web origins: '' | ||
| * Save | * Save | ||
| - | |||
| - | No client secret. Incus does not send one. | ||
| **Incus** | **Incus** | ||
| + | |||
| + | Configure incus on the CLI to accept the issuer: | ||
| < | < | ||
| Line 253: | Line 237: | ||
| incus config set oidc.scopes=openid, | incus config set oidc.scopes=openid, | ||
| incus config set oidc.claim=preferred_username | incus config set oidc.claim=preferred_username | ||
| - | </ | ||
| - | |||
| - | '' | ||
| - | |||
| - | < | ||
| incus config show | grep oidc | incus config show | grep oidc | ||
| </ | </ | ||
| - | Open the Incus UI → Login with SSO → Keycloak '' | + | Open the Incus UI → Login with SSO → Keycloak '' |
| - | + | ||
| - | Then grant that identity. SSO alone is not admin: | + | |
| < | < | ||
| Line 269: | Line 246: | ||
| </ | </ | ||
| - | From the unix socket as root, grant Admin (or project access) to the new '' | + | From the unix socket as root, grant Admin (or project access) to the new '' |
| - | + | ||
| - | ==== Facts ==== | + | |
| - | * | + | |
| - | --- // | + | --- // |