Keycloak Deployment

1. Overview

Keycloak serves as the SAML/OIDC Identity Provider (IdP) for the DomusDigitalis home enterprise network.

2. Infrastructure

Component Value

Hostname

keycloak-01.inside.domusdigitalis.dev

IP Address

10.50.1.x (internal network)

Port

8443 (HTTPS only)

OS

Fedora Cloud (VM)

Container Runtime

Docker / Podman

Database

PostgreSQL

TLS Certificate

DOMUS PKI (Vault-issued)

3. Prerequisites

  • Fedora Cloud VM provisioned

  • Docker or Podman installed

  • PostgreSQL database available

  • TLS certificate from DOMUS PKI (Vault)

  • DNS record for keycloak-01.inside.domusdigitalis.dev

4. Directory Structure

/opt/keycloak/
├── docker-compose.yml
├── conf/
│   ├── cert.pem        # TLS certificate
│   └── key.pem         # TLS private key
└── data/               # PostgreSQL data (if local)

5. Docker Compose Configuration

version: '3.8'

services:
  keycloak:
    image: quay.io/keycloak/keycloak:latest
    container_name: keycloak
    command: start
    environment:
      KC_DB: postgres
      KC_DB_URL: jdbc:postgresql://localhost:5432/keycloak
      KC_DB_USERNAME: keycloak
      KC_DB_PASSWORD: ${KC_DB_PASSWORD}
      KC_HOSTNAME: keycloak-01.inside.domusdigitalis.dev
      KC_HTTPS_CERTIFICATE_FILE: /opt/keycloak/conf/cert.pem
      KC_HTTPS_CERTIFICATE_KEY_FILE: /opt/keycloak/conf/key.pem
      KC_HTTPS_PORT: 8443
      KC_HTTP_ENABLED: "false"
      KEYCLOAK_ADMIN: admin
      KEYCLOAK_ADMIN_PASSWORD: ${KEYCLOAK_ADMIN_PASSWORD}
    ports:
      - "8443:8443"
    volumes:
      - /opt/keycloak/conf:/opt/keycloak/conf:ro
    restart: unless-stopped
    user: "1000:1000"

  postgres:
    image: postgres:15
    container_name: keycloak-db
    environment:
      POSTGRES_DB: keycloak
      POSTGRES_USER: keycloak
      POSTGRES_PASSWORD: ${KC_DB_PASSWORD}
    volumes:
      - /opt/keycloak/data:/var/lib/postgresql/data
    restart: unless-stopped

6. TLS Certificate Setup

6.1. Issue from Vault PKI

# On certmgr-01 or workstation with Vault access
vault write pki_int/issue/domus-server \
  common_name="keycloak-01.inside.domusdigitalis.dev" \
  alt_names="keycloak-01" \
  ttl="8760h" \
  -format=json > /tmp/keycloak-cert.json

6.2. Extract Certificate Components

jq -r '.data.certificate' /tmp/keycloak-cert.json > /tmp/cert.pem
jq -r '.data.private_key' /tmp/keycloak-cert.json > /tmp/key.pem

6.3. Install Certificate

# Copy to Keycloak host
scp /tmp/cert.pem /tmp/key.pem keycloak-01:/opt/keycloak/conf/

# Set permissions (Keycloak runs as UID 1000)
ssh keycloak-01 'cd /opt/keycloak/conf && \
  sudo chown 1000:1000 cert.pem key.pem && \
  sudo chmod 444 cert.pem && \
  sudo chmod 400 key.pem'

# SELinux context (Fedora/RHEL)
ssh keycloak-01 'sudo chcon -t svirt_sandbox_file_t /opt/keycloak/conf/cert.pem /opt/keycloak/conf/key.pem'

7. Environment Variables

Store secrets using gopass:

# Credentials stored in gopass
gopass show d000/keycloak/admin
gopass show d000/keycloak/db-password

8. Starting Keycloak

# SSH to Keycloak host
ssh keycloak-01

# Load secrets and start
cd /opt/keycloak
export KC_DB_PASSWORD=$(gopass show -o d000/keycloak/db-password)
export KEYCLOAK_ADMIN_PASSWORD=$(gopass show -o d000/keycloak/admin)
sudo -E docker-compose up -d

# Verify running
sudo docker ps --filter name=keycloak
sudo docker logs keycloak --tail 50

9. Verification

9.1. Test HTTPS Access

# Should return Keycloak welcome page
curl -k https://keycloak-01.inside.domusdigitalis.dev:8443/

# Check realm endpoint
curl -k https://keycloak-01.inside.domusdigitalis.dev:8443/realms/domusdigitalis

9.2. Admin Console

https://keycloak-01.inside.domusdigitalis.dev:8443/admin/

10. Maintenance

10.1. View Logs

ssh keycloak-01 'sudo docker logs keycloak --tail 100'
ssh keycloak-01 'sudo docker logs keycloak -f'  # Follow

10.2. Restart Keycloak

ssh keycloak-01 'sudo docker restart keycloak'

10.3. Update Keycloak

ssh keycloak-01 'cd /opt/keycloak && sudo docker-compose pull && sudo docker-compose up -d'

10.4. Backup Realm

ssh keycloak-01 'TOKEN=$(curl -ks https://localhost:8443/realms/master/protocol/openid-connect/token \
  -d "client_id=admin-cli" \
  -d "username=admin" \
  -d "password=<PASSWORD>" \
  -d "grant_type=password" | jq -r .access_token) && \
curl -ks https://localhost:8443/admin/realms/domusdigitalis \
  -H "Authorization: Bearer $TOKEN" > /tmp/realm-backup.json'

11. Troubleshooting

11.1. Container Won’t Start

# Check logs
docker logs keycloak

# Common issues:
# - Certificate permission denied: chown 1000:1000 + SELinux context
# - Database connection: verify PostgreSQL is running
# - Port conflict: check nothing else on 8443

11.2. Certificate Issues

# Verify certificate
openssl x509 -in /opt/keycloak/conf/cert.pem -text -noout | head -20

# Check SAN (required for modern browsers)
openssl x509 -in /opt/keycloak/conf/cert.pem -text -noout | grep -A1 "Subject Alternative Name"