[[_keycloak_cr]] === Installing {project_name} using a custom resource You can use the Operator to automate the installation of {project_name} by creating a Keycloak custom resource. When you use a custom resource to install {project_name}, you create the components and services that are described here and illustrated in the graphic that follows. * `keycloak-db-secret` - Stores properties such as the database username, password, and external address (if you connect to an external database) * `credentials-` - Admin username and password to log into the {project_name} admin console (the `` is based on the `Keycloak` custom resource name) * `keycloak` - Keycloak deployment specification that is implemented as a StatefulSet with high availability support * `keycloak-postgresql` - Starts a PostgreSQL database installation * `keycloak-discovery` Service - Performs `JDBC_PING` discovery * `keycloak` Service - Connects to {project_name} through HTTPS (HTTP is not supported) * `keycloak-postgresql` Service - Connects an internal and external, if used, database instance * `keycloak` Route - The URL for accessing the {project_name} admin console from OpenShift ifeval::[{project_community}==true] * `keycloak` Ingress - The URL for accessing the {project_name} admin console from Kubernetes endif::[] .How Operator components and services interact image:{project_images}/operator-components.png[] ==== The Keycloak custom resource The Keycloak custom resource is a YAML file that defines the parameters for installation. This file contains three properties. * `instances` - controls the number of instances running in high availability mode. * `externalAccess` - if the `enabled` is `True`, the Operator creates a route for OpenShift ifeval::[{project_community}==true] or an Ingress for Kubernetes endif::[] for the {project_name} cluster. You can set `host` to override the automatically chosen host name for Route ifeval::[{project_community}==true] or default value `keycloak.local` set for Ingress. endif::[] * `externalDatabase` - in order to connect to an externally hosted database. That topic is covered in the xref:_external_database[external database] section of this guide. Setting it to false should be used only for testing purposes and will install an embedded PostgreSQL database. Be aware that externalDatabase:false is *NOT* supported in production environments. .Example YAML file for a Keycloak custom resource ```yaml apiVersion: keycloak.org/v1alpha1 kind: Keycloak metadata: ifeval::[{project_community}==true] name: example-keycloak endif::[] ifeval::[{project_product}==true] name: example-sso endif::[] labels: ifeval::[{project_community}==true] app: example-keycloak endif::[] ifeval::[{project_product}==true] app: sso endif::[] spec: instances: 1 externalAccess: enabled: True ``` [NOTE] ==== You can update the YAML file and the changes appear in the {project_name} admin console, however changes to the admin console do not update the custom resource. ==== ==== Creating a Keycloak custom resource on OpenShift On OpenShift, you use the custom resource to create a route, which is the URL of the admin console, and find the secret, which holds the username and password for the admin console. .Prerequisites * You have a YAML file for this custom resource. * You have cluster-admin permission or an equivalent level of permissions granted by an administrator. ifeval::[{project_community}==true] * If you want to start tracking all Operator activities now, install the monitoring application before you create this custom resource. See xref:_monitoring-operator[The Application Monitoring Operator]. endif::[] .Procedure . Create a route using your YAML file: `{create_cmd} -f .yaml -n `. For example: + [source,bash,subs=+attributes] ---- ifeval::[{project_community}==true] $ {create_cmd} -f keycloak.yaml -n keycloak keycloak.keycloak.org/example-keycloak created endif::[] ifeval::[{project_product}==true] $ {create_cmd} -f sso.yaml -n sso keycloak.keycloak.org/example-sso created endif::[] ---- + A route is created in OpenShift. . Log into the OpenShift web console. . Select `Networking`, `Routes` and search for Keycloak. + .Routes screen in OpenShift web console image:images/route-ocp.png[] . On the screen with the Keycloak route, click the URL under `Location`. + The {project_name} admin console login screen appears. + .Admin console login screen image:images/login-empty.png[] . Locate the username and password for the admin console in the OpenShift web console; under `Workloads`, click `Secrets` and search for Keycloak. + .Secrets screen in OpenShift web console image:images/secrets-ocp.png[] . Enter the username and password into the admin console login screen. + .Admin console login screen image:images/login-complete.png[] + You are now logged into an instance of {project_name} that was installed by a Keycloak custom resource. You are ready to create custom resources for realms, clients, and users. + .{project_name} master realm image:images/new_install_cr.png[] . Check the status of the custom resource: + [source,bash,subs=+attributes] ---- $ {create_cmd_brief} describe keycloak ---- ifeval::[{project_community}==true] ==== Creating a Keycloak custom resource on Kubernetes On Kubernetes, you use the custom resource to create an ingress, which is the IP address of the admin console, and find the secret, which holds the username and password for that console. .Prerequisites * You have a YAML file for this custom resource. * You have cluster-admin permission or an equivalent level of permissions granted by an administrator. .Procedure . Create the ingress using your YAML file. `{create_cmd} -f .yaml -n `. For example: + [source,bash,subs=+attributes] ---- $ {create_cmd} -f keycloak.yaml -n keycloak keycloak.keycloak.org/example-keycloak created ---- . Find the ingress: `{create_cmd_brief} get ingress -n `. For example: + [source,bash,subs=+attributes] ---- $ {create_cmd_brief} get ingress -n example-keycloak NAME HOSTS ADDRESS PORTS AGE keycloak keycloak.redhat.com 192.0.2.0 80 3m ---- . Copy and paste the ADDRESS (the ingress) into a web browser. + The {project_name} admin console login screen appears. + .Admin console login screen image:images/login-empty.png[] . Locate the username and password. + [source,bash,subs=+attributes] ---- $ {create_cmd_brief} get secret credential- -o go-template='{{range $k,$v := .data}}{{printf "%s: " $k}}{{if not $v}}{{$v}}{{else}}{{$v | base64decode}}{{end}}{{"\n"}}{{end}}' ---- . Enter the username and password in the admin console login screen. + .Admin console login screen image:images/login-complete.png[] + You are now logged into an instance of {project_name} that was installed by a Keycloak custom resource. You are ready to create custom resources for realms, clients, and users. + .Admin console master realm image:images/new_install_cr.png[] endif::[] .Results After the Operator processes the custom resource, view the status with this command: [source,bash,subs=+attributes] ---- $ {create_cmd_brief} describe keycloak ---- .Keycloak custom resource Status ```yaml Name: example-keycloak Namespace: keycloak ifeval::[{project_community}==true] Labels: app=example-keycloak endif::[] ifeval::[{project_product}==true] Labels: app=sso endif::[] Annotations: API Version: keycloak.org/v1alpha1 Kind: Keycloak Spec: External Access: Enabled: true Instances: 1 Status: Credential Secret: credential-example-keycloak Internal URL: https:// Message: Phase: reconciling Ready: true Secondary Resources: Deployment: keycloak-postgresql Persistent Volume Claim: keycloak-postgresql-claim Prometheus Rule: keycloak Route: keycloak Secret: credential-example-keycloak keycloak-db-secret Service: keycloak-postgresql keycloak keycloak-discovery Service Monitor: keycloak Stateful Set: keycloak Version: Events: ``` .Additional resources * Once the installation of {project_name} completes, you are ready to xref:_realm-cr[create a realm custom resource]. * An external database is the supported option and needs to be enabled in the Keycloak custom resource. You can disable this option only for testing and enable it when you switch to a production environment. See xref:_external_database[Connecting to an external database].