Installing Che on Minikube with Keycloak as the OIDC provider

You can create a single-node Kubernetes cluster with Minikube to deploy Che and configure it to use Keycloak as the OpenID Connect (OIDC) provider.

Single-node Kubernetes clusters are suited only for testing or development. Do NOT use such clusters to run Che for organizations or developer teams!
Prerequisites
Procedure
  1. Start Minikube. Allocate at least 8GB of RAM and 4 CPU cores:

    minikube start --addons=ingress --vm=true --memory=8192 --cpus=4
  2. Install cert-manager

    helm repo add jetstack https://charts.jetstack.io
    helm repo update
    
    helm install cert-manager jetstack/cert-manager \
      --wait \
      --create-namespace \
      --namespace cert-manager \
      --set installCRDs=true
  3. Install Keycloak:

    kubectl apply -f - <<EOF
    ---
    apiVersion: v1
    kind: Namespace
    metadata:
      name: keycloak
    ---
    apiVersion: cert-manager.io/v1
    kind: Issuer
    metadata:
      name: keycloak-selfsigned
      namespace: keycloak
      labels:
        app: keycloak
    spec:
      selfSigned: {}
    ---
    apiVersion: cert-manager.io/v1
    kind: Certificate
    metadata:
      name: keycloak-selfsigned
      namespace: keycloak
      labels:
        app: keycloak
    spec:
      isCA: true
      commonName: keycloak-selfsigned-ca
      privateKey:
        algorithm: ECDSA
        size: 256
      issuerRef:
        name: keycloak-selfsigned
        kind: Issuer
        group: cert-manager.io
      secretName: ca.crt
    ---
    apiVersion: cert-manager.io/v1
    kind: Issuer
    metadata:
      name: keycloak
      namespace: keycloak
      labels:
        app: keycloak
    spec:
      ca:
        secretName: ca.crt
    ---
    apiVersion: cert-manager.io/v1
    kind: Certificate
    metadata:
      name: keycloak
      namespace: keycloak
      labels:
        app: keycloak
    spec:
      isCA: false
      commonName: keycloak
      dnsNames:
        - keycloak.$(minikube ip).nip.io
      privateKey:
        algorithm: RSA
        encoding: PKCS1
        size: 4096
      issuerRef:
        kind: Issuer
        name: keycloak
        group: cert-manager.io
      secretName: keycloak.tls
      subject:
        organizations:
          - Local Eclipse Che
      usages:
        - server auth
        - digital signature
        - key encipherment
        - key agreement
        - data encipherment
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: keycloak
      namespace: keycloak
      labels:
        app: keycloak
    spec:
      ports:
      - name: http
        port: 8080
        targetPort: 8080
      selector:
        app: keycloak
      type: LoadBalancer
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: keycloak
      namespace: keycloak
      labels:
        app: keycloak
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: keycloak
      template:
        metadata:
          labels:
            app: keycloak
        spec:
          containers:
          - name: keycloak
            image: quay.io/keycloak/keycloak:18.0.2
            args: ["start-dev"]
            env:
            - name: KEYCLOAK_ADMIN
              value: "admin"
            - name: KEYCLOAK_ADMIN_PASSWORD
              value: "admin"
            - name: KC_PROXY
              value: "edge"
            ports:
            - name: http
              containerPort: 8080
            readinessProbe:
              httpGet:
                path: /realms/master
                port: 8080
    ---
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: keycloak
      namespace: keycloak
      annotations:
        nginx.ingress.kubernetes.io/proxy-connect-timeout: '3600'
        nginx.ingress.kubernetes.io/proxy-read-timeout: '3600'
        nginx.ingress.kubernetes.io/ssl-redirect: 'true'
    spec:
      ingressClassName: nginx
      tls:
        - hosts:
            - keycloak.$(minikube ip).nip.io
          secretName: keycloak.tls
      rules:
      - host: keycloak.$(minikube ip).nip.io
        http:
          paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: keycloak
                port:
                  number: 8080
    EOF
  4. Save Keycloak CA certificate:

    kubectl get secret ca.crt -o "jsonpath={.data['ca\.crt']}" -n keycloak | base64 -d > keycloak-ca.crt
  5. Copy Keycloak CA certificate into Minikube:

    minikube ssh sudo "mkdir -p /etc/ca-certificates" && \
    minikube cp keycloak-ca.crt /etc/ca-certificates/keycloak-ca.crt
  6. Configure Minikube to use Keycloak as the OIDC provider:

    minikube start \
        --extra-config=apiserver.oidc-issuer-url=https://keycloak.$(minikube ip).nip.io/realms/che \
        --extra-config=apiserver.oidc-username-claim=email \
        --extra-config=apiserver.oidc-client-id=k8s-client \
        --extra-config=apiserver.oidc-ca-file=/etc/ca-certificates/keycloak-ca.crt
  7. Wait until the Keycloak pod is ready:

    kubectl wait --for=condition=ready pod -l app=keycloak -n keycloak --timeout=120s
  8. Configure Keycloak to create the realm, client, and user:

    You must do this each time you start the Minikube cluster.
    kubectl exec deploy/keycloak -n keycloak -- bash -c \
        "/opt/keycloak/bin/kcadm.sh config credentials \
            --server http://localhost:8080 \
            --realm master \
            --user admin  \
            --password admin && \
        /opt/keycloak/bin/kcadm.sh create realms \
            -s realm='che' \
            -s displayName='che' \
            -s enabled=true \
            -s registrationAllowed=false \
            -s resetPasswordAllowed=true && \
        /opt/keycloak/bin/kcadm.sh create clients \
            -r 'che' \
            -s clientId=k8s-client \
            -s id=k8s-client \
            -s redirectUris='[\"*\"]' \
            -s directAccessGrantsEnabled=true \
            -s secret=eclipse-che && \
        /opt/keycloak/bin/kcadm.sh create users \
            -r 'che' \
            -s username=test \
            -s email=\"test@test.com\" \
            -s enabled=true \
            -s emailVerified=true &&  \
        /opt/keycloak/bin/kcadm.sh set-password \
            -r 'che' \
            --username test \
            --new-password test"
  9. Copy Keycloak CA certificate into the eclipse-che namespace:

    kubectl create namespace eclipse-che &&  \
    kubectl create configmap keycloak-certs \
        --from-file=keycloak-ca.crt=keycloak-ca.crt \
        -n eclipse-che && \
    kubectl label configmap keycloak-certs \
        app.kubernetes.io/part-of=che.eclipse.org \
        app.kubernetes.io/component=ca-bundle \
        -n eclipse-che
  10. Prepare the CheCluster patch:

    cat > che-patch.yaml << EOF
    kind: CheCluster
    apiVersion: org.eclipse.che/v2
    spec:
      networking:
        auth:
          oAuthClientName: k8s-client
          oAuthSecret: eclipse-che
          identityProviderURL: "https://keycloak.$(minikube ip).nip.io/realms/che"
          gateway:
            oAuthProxy:
              cookieExpireSeconds: 300
            deployment:
              containers:
                - env:
                    - name: OAUTH2_PROXY_BACKEND_LOGOUT_URL
                      value: "http://keycloak.$(minikube ip).nip.io/realms/che/protocol/openid-connect/logout?id_token_hint={id_token}"
                  name: oauth-proxy
      components:
        cheServer:
          extraProperties:
            CHE_OIDC_USERNAME__CLAIM: email
    EOF
  11. Create the Che instance with chectl:

    chectl server:deploy --platform k8s --domain $(minikube ip).nip.io --che-operator-cr-patch-yaml che-patch.yaml --skip-cert-manager

    Alternatively, use the Eclipse Che Helm Charts:

    helm install che \
        --namespace eclipse-che \
        --set networking.domain=$(minikube ip).nip.io \
        --set networking.auth.oAuthSecret=eclipse-che \
        --set networking.auth.oAuthClientName=k8s-client \
        --set networking.auth.identityProviderURL=https://keycloak.$(minikube ip).nip.io/realms/che . && \
    sleep 5s && \
    kubectl patch checluster/eclipse-che --patch '{"spec": {"components": {"cheServer": {"extraProperties": {"CHE_OIDC_USERNAME__CLAIM": "email"}}}}}' --type=merge -n eclipse-che
    kubectl patch checluster/eclipse-che --patch '{"spec": {"networking": {"auth": {"gateway": {"deployment": {"containers": [{"name": "oauth-proxy", "env":[{"name": "OAUTH2_PROXY_BACKEND_LOGOUT_URL", "value": "http://keycloak.$(minikube ip).nip.io/realms/che/protocol/openid-connect/logout?id_token_hint={id_token}"}]}]}}}}}}' --type=merge -n eclipse-che
Verification steps
  1. Verify the Che instance status:

    chectl server:status
  2. Navigate to the Che cluster instance:

    chectl dashboard:open
  3. Log in to the Che instance with Username: test and Password: test.