Keycloak identitate-zerbitzaria da: erabiltzaile eta pasahitz bakarrarekin zerbitzu guztietan sartzeko aukera ematen du (SSO). Gida honetan Podman-ekin (root gabe), Quadlet-ekin, Traefik-ekin eta PostgreSQL-ekin muntatzen dut. Domeinuak adibidezkoak dira (example.com), eta sekretuak ez dira inoiz repositoriora igotzen.

Diseinua

Hiru ideia nagusi daude:

  • Bi edukiontzi: Keycloak eta PostgreSQL, bakoitza bere .container fitxategiarekin.
  • Bi sare: publikoa Traefik-ek ikusi behar dituen zerbitzuentzat, eta pribatua datu-baserako. Datu-basea pribatua sarean bakarrik dago, portu argitaraturik gabe.
  • Bi helbide: sso.example.com publikoa da (saioa hasteko eta aplikazioentzat), eta sso-admin.example.com kudeaketa-kontsolarako, sare lokaletik bakarrik. Kudeaketa-kontsola internetetik ez ateratzea Keycloak-en dokumentazioaren gomendioa da.

1. Karpetak eta sekretuak

Zerbitzu bakoitzak bere karpeta du, eta .container fitxategiak config/ barruan daude. Sekretuak .env fitxategietan gordetzen dira, ausaz sortuta eta pantailan erakutsi gabe:

mkdir -p ~/podman/keycloak/config ~/podman/keycloak/db
chmod 750 ~/podman/keycloak/db
cd ~/podman/keycloak/config

DBPASS=$(openssl rand -hex 24)
ADMINPASS=$(openssl rand -hex 16)
printf 'KC_DB_PASSWORD=%s\nKC_BOOTSTRAP_ADMIN_USERNAME=tmpadmin\nKC_BOOTSTRAP_ADMIN_PASSWORD=%s\n' "$DBPASS" "$ADMINPASS" > keycloak.env
printf 'POSTGRES_PASSWORD=%s\n' "$DBPASS" > keycloak-db.env
chmod 600 keycloak.env keycloak-db.env
unset DBPASS ADMINPASS

Gero, Git-ek ez ditzan sekretuak eta datu-basea igo:

cd ~/podman
printf '\n*.env\nkeycloak/db/\n' >> .gitignore

Hasierako \n-ak aurreko lerroarekin ez itsasteko balio du.

2. PostgreSQL

keycloak/config/keycloak-db.container:

[Unit]
Description=Keycloak PostgreSQL
After=network-online.target
Wants=network-online.target

[Container]
Image=docker.io/library/postgres:16-alpine
ContainerName=keycloak_db
EnvironmentFile=%h/podman/keycloak/config/keycloak-db.env
Environment=POSTGRES_USER=keycloak
Environment=POSTGRES_DB=keycloak
Volume=%h/podman/keycloak/db:/var/lib/postgresql/data:U
Network=pribatua.network

[Service]
Restart=always
TimeoutStartSec=300

[Install]
WantedBy=default.target

Ez du PublishPort lerrorik: pribatua sareko edukiontziek bakarrik atzitu dezakete. :U-k Podman-i eskatzen dio karpetaren jabea barruko erabiltzaileari egokitzeko.

3. Keycloak

keycloak/config/keycloak.container:

[Unit]
Description=Keycloak
After=network-online.target keycloak-db.service
Wants=network-online.target keycloak-db.service

[Container]
Image=quay.io/keycloak/keycloak:26.6.4
ContainerName=keycloak
EnvironmentFile=%h/podman/keycloak/config/keycloak.env
Environment=KC_DB=postgres
Environment=KC_DB_URL=jdbc:postgresql://keycloak_db:5432/keycloak
Environment=KC_DB_USERNAME=keycloak
Environment=KC_HOSTNAME=https://sso.example.com
Environment=KC_HOSTNAME_ADMIN=https://sso-admin.example.com
Environment=KC_HTTP_ENABLED=true
Environment=KC_PROXY_HEADERS=xforwarded
Exec=start
Network=publikoa.network
Network=pribatua.network
PublishPort=127.0.0.1:8080:8080

[Service]
Restart=always
TimeoutStartSec=300

[Install]
WantedBy=default.target

Aukera garrantzitsuenak:

  • Exec=start: ekoizpen modua.
  • KC_HOSTNAME eta KC_HOSTNAME_ADMIN: helbide publikoa eta kudeaketa-kontsolarena, bereizita.
  • KC_HTTP_ENABLED=true: HTTPS Traefik-ek kudeatzen du, eta Keycloak-ek HTTP hutsa jasotzen du.
  • KC_PROXY_HEADERS=xforwarded: proxyak bidalitako goiburuak fidagarritzat hartzen ditu.
  • PublishPort=127.0.0.1:8080:8080: portua ordenagailu horretan bakarrik dago zabalik, Traefik-entzat.

Estekak sortu eta abiarazi:

ln -s ~/podman/keycloak/config/keycloak-db.container ~/.config/containers/systemd/
ln -s ~/podman/keycloak/config/keycloak.container ~/.config/containers/systemd/
systemctl --user daemon-reload
systemctl --user start keycloak-db keycloak

Lehen abiaraztean denbora behar du, datu-basearen taulak sortzen dituelako.

4. Traefik: publikoa eta kudeaketa bereizita

traefik/dynamic/keycloak.yml:

http:
  routers:
    keycloak-publikoa:
      rule: "Host(`sso.example.com`) && (PathPrefix(`/realms/`) || PathPrefix(`/resources/`) || Path(`/robots.txt`)) && !PathPrefix(`/realms/master`)"
      entryPoints:
        - websecure
      service: keycloak
      tls:
        certResolver: cloudflare

    keycloak-admin:
      rule: "Host(`sso-admin.example.com`)"
      entryPoints:
        - websecure
      service: keycloak
      middlewares:
        - lokalak
      tls:
        certResolver: cloudflare

  services:
    keycloak:
      loadBalancer:
        servers:
          - url: "http://127.0.0.1:8080"
  • Router publikoak /realms/, /resources/ eta /robots.txt bakarrik uzten ditu, eta master realm-a blokeatzen du.
  • Kudeaketa-routerrak dena uzten du, baina lokalak iragazkiarekin: zure sare lokaleko barrutiak onartzen dituen ipAllowList middleware-a.

Traefik-ek dynamic karpeta automatikoki berrirakurtzen du.

5. DNS

  • sso.example.com: erregistro publikoa Cloudflare-n.
  • sso-admin.example.com: ez da Cloudflare-n sortzen. DNS lokalean bakarrik, zerbitzariaren IP-ra.

Ziurtagiriak DNS-01 erronkarekin lortzen dira (Cloudflare), beraz zerbitzua ez da internetetik atzigarria izan behar ziurtagiria jasotzeko.

6. Lehen sarrera

  1. Ireki https://sso-admin.example.com sare lokaletik.

  2. Sartu tmpadmin erabiltzailearekin. Pasahitza keycloak.env fitxategian dago:

    grep BOOTSTRAP_ADMIN_PASSWORD ~/podman/keycloak/config/keycloak.env
    
  3. master realm-ean, sortu behin betiko administratzaile bat: Users → Add user. Gero Credentials fitxan pasahitz bat ezarri, eta Role mapping fitxan admin rola esleitu.

  4. Hasi saioa erabiltzaile berriarekin eta ezabatu tmpadmin.

  5. Aktibatu bi urratseko autentifikazioa administratzaile berriarentzat: Required user actions → Configure OTP.

7. Realm-a, erabiltzaileak eta taldeak

master realm-a ez da aplikazioentzat; kudeaketarako bakarrik da.

  1. Goiko ezkerreko menuan, Create realm → izena: homelab.
  2. Groups → Create group: adibidez admins eta familia.
  3. Users → Add user: erabiltzaile-izena, posta, izena eta abizena; Email verified aktibatu. Credentials fitxan pasahitza ezarri, eta Groups fitxan taldea esleitu.

8. Aplikazio bat konektatu: BookStack adibidea

Keycloak-en:

  1. Clients → Create client: Client type OpenID Connect, Client ID bookstack.
  2. Client authentication aktibatuta, eta Standard flow bakarrik.
  3. Valid redirect URIs: https://wiki.example.com/oidc/callback.
  4. Gorde, eta Credentials fitxan Client secret kopiatu.

BookStack-en, bookstack.container fitxategian gehitu:

Environment=AUTH_METHOD=oidc
Environment=OIDC_NAME=Keycloak
Environment=OIDC_DISPLAY_NAME_CLAIMS=name
Environment=OIDC_CLIENT_ID=bookstack
Environment=OIDC_ISSUER=https://sso.example.com/realms/homelab
Environment=OIDC_ISSUER_DISCOVER=true
Environment=OIDC_END_SESSION_ENDPOINT=true

Sekretua bookstack.env fitxategian gorde, historialean geratu gabe:

cd ~/podman/bookstack/config
read -rs SECRET
printf 'OIDC_CLIENT_SECRET=%s\n' "$SECRET" >> bookstack.env
unset SECRET
systemctl --user daemon-reload
systemctl --user restart bookstack

Kontuan izan: OIDC aktibatzean pasahitz bidezko formularioa desagertzen da. Aurretik, lehendik dagoen administratzailearen profilean, External Authentication ID eremua Keycloak-eko erabiltzailearen IDarekin bete (Users zerrendan ikusten da), bestela BookStack-ek posta bera duen kontu bat dagoela esan dezake.

9. Gomendioak

  • Ez erabili master realm-a aplikazioentzat, eta kudeaketa-kontsola ez atera internetera.

  • Traefik Network=host moduan dabil, horrela bezeroen IP errealak ikusten ditu eta ipAllowList ondo funtzionatzen du. Sare birtualekin, Podman rootless-ean, eskaera guztiak gateway-aren IPrekin iristen dira eta iragazkiak ez du ezer iragazten.

  • Finkatu Keycloak-en bertsioa (ez erabili latest), eta eguneratu aurretik datu-basearen kopia egin:

    podman exec keycloak_db pg_dump -U keycloak keycloak | gzip > keycloak-$(date +%F).sql.gz
    
  • .env fitxategiak ez dira Git-era igotzen. Gorde kopia bat pasahitz-kudeatzailean, bestela zerbitzaria galduz gero sekretuak galduko dituzu.