
[[_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-<CR-Name>` - Admin username and password to log into the {project_name} admin console (the `<CR-Name>` 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.
* `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 <filename>.yaml -n <namespace>`. 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 <CR-name>
----

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 <filename>.yaml -n <namespace>`.  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 <CR-name>`. 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-<CR-Name> -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 <CR-name>
----

.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:  <none>
API Version:  keycloak.org/v1alpha1
Kind:         Keycloak
Spec:
  External Access:
    Enabled:  true
  Instances:  1
Status:
  Credential Secret:  credential-example-keycloak
  Internal URL:       https://<External URL to the deployed instance>
  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].
