# ansipa Single Sign-On How identity flows through the ansipa stack, which services can actually use it, and how to wire the infrastructure appliances (Proxmox VE/BS, OPNsense) into it. The rule for this stack: **no service keeps its own account list.** Every account lives in FreeIPA, and every login is decided either by Keycloak or by FreeIPA itself. The only exceptions are two deliberate break-glass local admins, documented at the bottom. --- ## The identity chain ``` FreeIPA ── accounts, groups, sudo/HBAC rules. The source of truth. │ ├─ LDAP (READ_ONLY federation) ──▶ Keycloak ── issues OIDC/SAML │ │ │ ├─▶ Nextcloud (user_oidc) │ ├─▶ Proxmox VE (OpenID realm) │ ├─▶ Proxmox Backup (OpenID realm) │ └─▶ OPNsense (see caveat) │ └─ LDAP (direct bind) ───────────▶ CheckMK └ no SAML/OIDC in the Community edition, so it binds IPA itself ``` Keycloak mirrors FreeIPA read-only. Creating a user in Keycloak's own database is always a mistake here — it produces an account IPA does not know about, and it will not survive a re-sync. --- ## Support matrix | Service | Method | Edition/version caveat | |---|---|---| | Nextcloud | OIDC via Keycloak, accounts from IPA LDAP | `user_oidc` app must be installed | | Proxmox VE | OpenID Connect realm | PVE 7.0+ | | Proxmox Backup Server | OpenID Connect realm | PBS 2.2+ | | CheckMK | **Direct LDAP to FreeIPA** | SAML is commercial-only; OIDC unsupported in every edition | | OPNsense | LDAP to FreeIPA (recommended) | No built-in OIDC relying-party support | ### The two that cannot use Keycloak **CheckMK.** The Community (Raw) edition has no SAML — the docs state plainly that "SAML is supported in the commercial editions" — and no edition of CheckMK supports OIDC at all. The old `mod_auth_mellon` workaround was dropped in 2.3. So CheckMK binds FreeIPA over LDAP directly. Identity still comes from one place, it just takes a shorter path. Run `./checkmk-ldap-configure.sh`. **OPNsense.** It can consume LDAP and RADIUS, but it is not an OIDC relying party, so Keycloak cannot front the web UI. Point it at FreeIPA's LDAP directly (System → Access → Servers), which keeps accounts centralised even though the login is not federated. The `opnsense` Keycloak client that `keycloak-configure.sh` can provision is only useful if you put an OIDC-aware proxy in front of the UI, or for OPNsense plugins that speak OIDC. --- ## Setup order Everything below assumes the stack is up (`./run.sh all`). ```bash cd setup/modules/FreeipaAnsible/image ./keycloak-configure.sh # IPA LDAP federation + OIDC clients + groups claim ./nextcloud-configure.sh # Nextcloud → IPA LDAP + Keycloak OIDC ./checkmk-ldap-configure.sh # CheckMK → IPA LDAP directly ``` `keycloak-configure.sh` writes each client's secret to `image/.oidc-secrets` (mode 0600, gitignored). Clients are only created for relying parties whose base URL is set in `.env` — `NC_PUBLIC_URL`, `PVE_URL`, `PBS_URL`, `OPNSENSE_URL`. Set one later and re-run; existing clients keep their secrets. The discovery URL every relying party needs is: ``` https:///auth/realms//.well-known/openid-configuration ``` --- ## Nextcloud Two backends do two different jobs, and both are required: - **`user_ldap`** binds FreeIPA and owns the account list. Users, display names, mail and group membership come from IPA and are read-only. - **`user_oidc`** performs the login against Keycloak, so password policy, MFA and session control stay in one place. The join between them is the username, and it is the part that breaks if you change it carelessly. Nextcloud's internal username is pinned to the IPA `uid` (`ldapExpertUsernameAttr`), and the OIDC provider maps `preferred_username` onto it with **unique-uid disabled**. Leave unique-uid on and `user_oidc` hashes the claim into an ID of its own, so every SSO login creates a second, empty account beside the LDAP one. Verify after setup: ```bash docker compose exec -u www-data nextcloud php occ user:list ``` That should list your FreeIPA users. Log in once through the Keycloak button, then run it again — if a second account appeared for the same person, the uid mapping is wrong. Restrict who gets an account with `NC_LDAP_GROUP=usr_nextcloud` in `.env`; the LDAP filter also excludes IPA-disabled users (`nsAccountLock=TRUE`), so disabling someone in IPA locks them out of Nextcloud too. --- ## Proxmox VE Set `PVE_URL=https://pve.example.com:8006` in `.env`, re-run `./keycloak-configure.sh`, then on the PVE node: ```bash pveum realm add keycloak \ --type openid \ --issuer-url https:///auth/realms/ \ --client-id proxmox-ve \ --client-key \ --username-claim username \ --autocreate 1 ``` `--username-claim` accepts only `subject`, `username` or `email` — not `preferred_username`, despite that being the underlying claim name. `username` is the one you want; it is what makes the PVE user match the IPA uid. `--autocreate 1` creates the PVE user entry on first login. It does **not** grant permissions: assign those to groups under Datacenter → Permissions. Two things that reliably break this: - Keycloak must be reachable from the PVE node over **HTTPS with a certificate the node trusts**. A self-signed gateway cert produces an opaque HTTP 500 at login; install the CA on the node. - Proxmox expects RS256-signed tokens, which is Keycloak's default. Do not switch the realm or client to ES256/HS256. ## Proxmox Backup Server Same model, `PBS_URL` and the `proxmox-bs` client: ```bash proxmox-backup-manager openid create keycloak \ --issuer-url https:///auth/realms/ \ --client-id proxmox-bs \ --client-key \ --username-claim username \ --autocreate true ``` PBS needs its own client — reusing the PVE one fails on the redirect URI. --- ## Monitoring the same appliances Separate from SSO, and worth not conflating: these appliances are also monitored, and monitoring uses CheckMK's automation credentials, never a user identity. ### Proxmox VE / PBS — already wired `ansipa-infra-checkmk-install.sh` installs the agent, drops the `ansipa_pve` / `ansipa_pbs` local check and registers the host under `/ansipa/infra`. Run it on each node: ```bash ./ansipa-infra-checkmk-install.sh https://mon.example.com:8090 cmk ``` That covers cluster quorum, storage utilisation, guest counts and backup freshness (PVE); datastore usage, last-backup outcome and task failures (PBS). **Also worth enabling:** CheckMK ships a built-in *Proxmox VE special agent* (Setup → Agents → VM, cloud, container → Proxmox VE) that talks to the PVE API on port 8006 and generates piggyback data for the guests. It complements the local checks rather than replacing them — the special agent sees the cluster from outside and gives you per-VM data, the local check sees the node from inside. Create a dedicated `checkmk@pve` user in the *Proxmox VE authentication server* realm for it, not an OIDC user: the special agent needs a password it can present non-interactively. ### OPNsense — new ```bash scp ansipa-opnsense-*.sh root@fw:/root/ ssh root@fw /root/ansipa-opnsense-checkmk-install.sh \ https://mon.example.com:8090 cmk ``` Adds `Ansipa_OPN_Gateways`, `Ansipa_OPN_States` (pf state table against its hard limit — the check that actually catches a firewall falling over), `Ansipa_OPN_Firmware`, and `Ansipa_OPN_CARP` on HA pairs. The transport is deliberately **agent-over-SSH**, not the usual TCP 6556 via inetd. OPNsense generates `/etc/inetd.conf`, `/etc/services` and `/etc/hosts.allow` from `config.xml`, so it reverts those edits on the next reboot or config apply and monitoring dies quietly weeks later. With the SSH datasource nothing listens on the firewall and nothing gets overwritten. The installer prints the exact key-restriction and CheckMK rule to add. If you would rather not give CheckMK SSH access at all, enable SNMP on the firewall and set the host to SNMP in CheckMK — you get interfaces, CPU, memory and uptime, but none of the `Ansipa_OPN_*` checks, which need local execution. ### Keycloak itself Keycloak exposes Prometheus-format metrics on the management port 9000 (`/metrics`, with `KC_HEALTH_ENABLED=true` already set in the compose file). CheckMK Raw can scrape those, and health endpoints `/health/ready` and `/health/live` are the cheap liveness signal. Note these live on port **9000** and are *not* under `KC_HTTP_RELATIVE_PATH` — probing `https://gateway/auth/health/ready` returns 404 and will look like an outage that is not there. --- ## Packet captures to the SmartestHome LLM Short answer: **not through CheckMK.** Passing a CheckMK API key to the LLM is a good idea, but it buys you monitoring state, not packet data. **Why not.** CheckMK is a state-and-metrics system. Its REST API exposes hosts, services, service states, metrics, events, downtimes and comments — there is no packet-capture object and no blob transport. You could technically smuggle base64 pcap through a custom agent section, but the agent payload is re-parsed in full on every check cycle (60s by default): captures are megabytes per second, agent output is expected to be kilobytes, and you would blow up the monitoring core to build a bad file transfer. **What does work, with the same "one API key" ergonomics:** 1. **Give the LLM the CheckMK REST API for state.** One automation secret gets it every host, every service, current and historical metrics, and the event console. That answers "what is broken, since when, and what changed" — which is most of what you actually want an LLM triaging. 2. **Put the packet analysis where the packets are.** Run Suricata or Zeek on the OPNsense box (both are OPNsense plugins). They turn traffic into structured events — `eve.json`, Zeek logs — which is far better LLM input than raw pcap anyway, and orders of magnitude smaller. 3. **Bridge the two.** A local check on the firewall summarises IDS alert counts/severities into CheckMK, so alerts show up beside everything else and the LLM can see them through the same API key. When it needs detail, it fetches the full event from the Suricata/Zeek store — a second, narrow credential — using the timestamp and flow ID CheckMK gave it. That keeps the "one key for situational awareness" property you wanted, without making the monitoring system carry traffic it was never designed to move. If you do want genuine on-demand pcap, the honest design is a small capture service on the firewall exposing an authenticated endpoint, referenced *from* a CheckMK service — not tunnelled through it. --- ## Break-glass accounts Two local accounts deliberately do not live in FreeIPA, because they are how you get in when the directory or Keycloak is the thing that is broken: | Account | Where | Reach it at | |---|---|---| | `cmkadmin` | CheckMK | `/cmk/` normal login form | | `ncadmin` (`NC_ADMIN_USER`) | Nextcloud | `/nextcloud/login?direct=1` | Keep both in a password manager. Everything else — including your own day-to-day admin account — should be an IPA identity.