TL;DR
In Keycloak: Clients → Create client → OpenID Connect, Client ID proxmox, Client authentication On, Standard flow On, Valid redirect URIs https://pve.example.local:8006 and https://pve.example.local:8006/*. Copy the secret from the Credentials tab.
On a Proxmox node:
| |
Users log in as alice@keycloak. They are created on first login, with no permissions; permissions are still Proxmox ACLs:
| |
How it works
Proxmox has supported openid realms since PVE 7. From issuer-url it downloads /.well-known/openid-configuration and takes the endpoints from there; the login screen shows the realm in the dropdown and the Login button redirects to Keycloak. On the way back, the value of the claim you picked in username-claim becomes the user <claim>@<realm>.
username-claim accepts any claim name. Keycloak sends preferred_username by default (it comes from the username mapper in the profile client scope), so the extra mapper old guides added to expose a claim called username is not needed. If you prefer the email, --username-claim email.
Keycloak, step by step (26)
- Realm. Use the one you have (
labin the example). The issuer ishttps://id.example.local/realms/lab. Since Keycloak 17 there is no/auth/in the path; if you copy/auth/realms/...from an old guide, discovery fails. - Clients → Create client.
- Client type: OpenID Connect. Client ID:
proxmox. Name: whatever you like. - Capability config: Client authentication On (confidential client, with secret). Standard flow On. Everything else Off: Direct access grants, Implicit flow, Service accounts, Authorization.
- Login settings: Root URL
https://pve.example.local:8006; Valid redirect URIshttps://pve.example.local:8006andhttps://pve.example.local:8006/*. Web origins empty: it is a redirect flow, there is no CORS.
- Client type: OpenID Connect. Client ID:
- Credentials → Client secret. That is the
--client-key. - Groups (optional). Clients →
proxmox→ Client scopes →proxmox-dedicated→ Add mapper → By configuration → Group Membership: Namegroups, Token Claim Namegroups, Full group path Off, Add to ID token and Add to userinfo On.
Proxmox, step by step
Through the GUI: Datacenter → Permissions → Realms → Add → OpenID Connect Server: Issuer URL, Realm (the short name, keycloak), Client ID, Client Key, Username Claim preferred_username, Autocreate Users. Or the pveum realm add from the TL;DR; the configuration lands in /etc/pve/domains.cfg and replicates across the cluster.
With groups coming from Keycloak, on recent PVE 8 releases and on PVE 9 (pveum realm add --help tells you whether your version has --groups-claim):
| |
Each group in the claim is created as <group>-keycloak and the user joins them on every login; you assign the ACLs to those groups.
Test before touching anything else: login screen → Realm Keycloak → Login → you come back authenticated and pveum user list shows alice@keycloak.
Traps
Invalid parameter: redirect_uriin Keycloak: the URL you typed in the browser (name, port8006,https) is not in Valid redirect URIs. If you use both the IP and the FQDN, add both.- The node must trust Keycloak’s certificate, not just your browser. With an internal CA: copy the
.crtto/usr/local/share/ca-certificates/and runupdate-ca-certificates. issuer-urlhas to match exactly theissin the tokens:https, no trailing slash,/realms/<realm>.- Time. A skewed clock invalidates tokens;
chronyon the nodes. - Do not let users edit their own username in Keycloak (a warning from Proxmox’s own docs): renaming yourself to
rootis switching accounts in Proxmox. - Do not set
--default 1until it works, and keeproot@pamas the emergency door: if Keycloak is down, theopenidrealm cannot authenticate anyone. - API and CLI. OIDC users have no password in Proxmox; for Terraform, Ansible, or
pveshfrom outside create a token:pveum user token add alice@keycloak automation --privsep 0.
Reference: User Management — OpenID Connect in the Proxmox guide and client creation in the Keycloak documentation.