├── .gitignore ├── LICENSE ├── README.md ├── db ├── README.md └── psql_connect.sh ├── deployments ├── helm │ ├── README.md │ └── keycloak-k8s-local │ │ ├── .helmignore │ │ ├── Chart.yaml │ │ ├── templates │ │ ├── 01_namespace.yml │ │ ├── 02_secrets.yml │ │ ├── 03_storage.yml │ │ ├── 04_postgres.yml │ │ ├── 05_keycloak.yml │ │ ├── 06_ingress.yml │ │ └── _helpers.tpl │ │ └── values.yaml └── manual │ ├── 01_namespace.yml │ ├── 02_secrets.yml │ ├── 03_storage.yml │ ├── 04_postgres.yml │ ├── 05_keycloak.yml │ ├── 06_ingress.yml │ ├── README.md │ └── tls │ ├── README.md │ ├── create_tls_secret.sh │ ├── tls.crt │ └── tls.key ├── gifs ├── create_cluster.gif ├── keycloak_postgres_on_k8s.gif ├── kubernetes_dashboard.gif └── psql_connect.gif ├── images ├── db_connect.png ├── get_pods.png ├── get_secret.png ├── helm_install.png ├── keycloak_deployment_in_k8s.png └── watch_query.png ├── keycloak.code-workspace ├── kind ├── README.md └── config.yml └── kube_dashboard ├── README.md ├── get_token.sh ├── install.sh └── setup_access.yml /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Harris Brakmić 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Keycloak on k8s 2 | 3 | ![keycloak_video](gifs/keycloak_postgres_on_k8s.gif) 4 | 5 | This repo contains configuration files from the [article on running Keycloak on k8s](https://blog.brakmic.com/keycloak-with-postgresql-on-kubernetes/). 6 | 7 | The following packages and tools have been used to setup the system: 8 | 9 | * Keycloak 10 | * PostgreSQL 11 | * Kind 12 | * Helm 13 | * Kubernetes Dashboard 14 | 15 | ### Manual installation 16 | 17 | To install everything by hand, use the YAMLs located [here](./deployments/manual/README.md). 18 | 19 | ### Helm installation 20 | 21 | For Helm installation go [here](./deployments/helm/README.md). 22 | 23 | ### Kubernetes Dashboard installation 24 | 25 | To install Kubernetes Dashboard use the scripts located [here](./kube_dashboard/README.md). 26 | 27 | ### LICENSE 28 | [MIT](LICNSE.md) -------------------------------------------------------------------------------- /db/README.md: -------------------------------------------------------------------------------- 1 | ## Connect with Postgres DB within Kubernetes 2 | 3 | * Query Postgres Pod with `kubectl get pods -n hbr-keycloak` (substitute your namespace if it differs) 4 | 5 | ![get_pods](../images/get_pods.png) 6 | 7 | * Use its name as parameter when calling `psql_connect.sh` 8 | 9 | ![db_connect](../images/db_connect.png) -------------------------------------------------------------------------------- /db/psql_connect.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | kubectl exec -it $1 -n hbr-keycloak -- psql -h localhost -U postgres --password -p 5432 keycloak -------------------------------------------------------------------------------- /deployments/helm/README.md: -------------------------------------------------------------------------------- 1 | ## Helm installation 2 | 3 | * Install Helm first. This of course depends on your OS. Check [Helm docs](https://helm.sh/docs/intro/install/) for more info. 4 | * Check predefined [values](./keycloak-k8s-local/values.yaml) in the Helm package directory of this project. Change them according to your preferences. 5 | * Install deployments with `helm install keycloak-k8s-local keycloak-k8s-local` 6 | 7 | ![helm_install](../../images/helm_install.png) 8 | 9 | * Check current status with `watch -n 1 kubectl get all -n hbr-keycloak` or via [Kubernetes Dashboard](../../kube_dashboard/README.md) 10 | * Uninstall with `helm uninstall keycloak-k8s-local` -------------------------------------------------------------------------------- /deployments/helm/keycloak-k8s-local/.helmignore: -------------------------------------------------------------------------------- 1 | # Patterns to ignore when building packages. 2 | # This supports shell glob matching, relative path matching, and 3 | # negation (prefixed with !). Only one pattern per line. 4 | .DS_Store 5 | # Common VCS dirs 6 | .git/ 7 | .gitignore 8 | .bzr/ 9 | .bzrignore 10 | .hg/ 11 | .hgignore 12 | .svn/ 13 | # Common backup files 14 | *.swp 15 | *.bak 16 | *.tmp 17 | *.orig 18 | *~ 19 | # Various IDEs 20 | .project 21 | .idea/ 22 | *.tmproj 23 | .vscode/ 24 | -------------------------------------------------------------------------------- /deployments/helm/keycloak-k8s-local/Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v2 2 | name: keycloak-k8s-local 3 | description: A local k8s keycloak with postgres db 4 | 5 | # A chart can be either an 'application' or a 'library' chart. 6 | # 7 | # Application charts are a collection of templates that can be packaged into versioned archives 8 | # to be deployed. 9 | # 10 | # Library charts provide useful utilities or functions for the chart developer. They're included as 11 | # a dependency of application charts to inject those utilities and functions into the rendering 12 | # pipeline. Library charts do not define any templates and therefore cannot be deployed. 13 | type: application 14 | 15 | # This is the chart version. This version number should be incremented each time you make changes 16 | # to the chart and its templates, including the app version. 17 | # Versions are expected to follow Semantic Versioning (https://semver.org/) 18 | version: 0.1.0 19 | 20 | # This is the version number of the application being deployed. This version number should be 21 | # incremented each time you make changes to the application. Versions are not expected to 22 | # follow Semantic Versioning. They should reflect the version the application is using. 23 | # It is recommended to use it with quotes. 24 | appVersion: "1.16.0" 25 | -------------------------------------------------------------------------------- /deployments/helm/keycloak-k8s-local/templates/01_namespace.yml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Namespace 3 | metadata: 4 | name: "{{ .Values.namespace }}" 5 | -------------------------------------------------------------------------------- /deployments/helm/keycloak-k8s-local/templates/02_secrets.yml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Secret 3 | metadata: 4 | name: "{{ .Values.secrets.postgres.name }}" 5 | namespace: "{{ .Values.namespace }}" 6 | type: Opaque 7 | stringData: 8 | POSTGRES_USER: "{{ .Values.secrets.postgres.admin.name }}" 9 | POSTGRES_PASSWORD: "{{ .Values.secrets.postgres.admin.password }}" 10 | POSTGRES_DB: "{{ .Values.deployments.postgres.db.name }}" 11 | --- 12 | apiVersion: v1 13 | kind: Secret 14 | metadata: 15 | name: "{{ .Values.secrets.tls.name }}" 16 | namespace: "{{ .Values.namespace }}" 17 | type: kubernetes.io/tls 18 | data: 19 | tls.crt: "{{ .Values.secrets.tls.cert }}" 20 | tls.key: "{{ .Values.secrets.tls.key }}" 21 | --- 22 | apiVersion: v1 23 | kind: Secret 24 | metadata: 25 | name: "{{ .Values.secrets.keycloak.name }}" 26 | namespace: "{{ .Values.namespace }}" 27 | type: Opaque 28 | stringData: 29 | KEYCLOAK_ADMIN: "{{ .Values.secrets.keycloak.admin.name }}" 30 | KEYCLOAK_ADMIN_PASSWORD: "{{ .Values.secrets.keycloak.admin.password }}" 31 | -------------------------------------------------------------------------------- /deployments/helm/keycloak-k8s-local/templates/03_storage.yml: -------------------------------------------------------------------------------- 1 | kind: PersistentVolume 2 | apiVersion: v1 3 | metadata: 4 | name: "{{ .Values.pv.name }}" 5 | namespace: "{{ .Values.namespace }}" 6 | labels: 7 | type: local 8 | app: "{{ .Values.deployments.postgres.service.name }}" 9 | spec: 10 | storageClassName: "standard" 11 | capacity: 12 | storage: "{{ .Values.pv.size }}" 13 | accessModes: 14 | - ReadWriteMany 15 | persistentVolumeReclaimPolicy: Retain 16 | hostPath: 17 | path: "/mnt/data" 18 | --- 19 | apiVersion: v1 20 | kind: PersistentVolumeClaim 21 | metadata: 22 | name: "{{ .Values.pvc.name }}" 23 | namespace: "{{ .Values.namespace }}" 24 | labels: 25 | app: "{{ .Values.deployments.postgres.service.name }}" 26 | spec: 27 | storageClassName: "standard" 28 | accessModes: 29 | - ReadWriteMany 30 | resources: 31 | requests: 32 | storage: "{{ .Values.pvc.size }}" 33 | -------------------------------------------------------------------------------- /deployments/helm/keycloak-k8s-local/templates/04_postgres.yml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: "{{ .Values.deployments.postgres.service.name }}" 5 | namespace: "{{ .Values.namespace }}" 6 | labels: 7 | app: "{{ .Values.deployments.postgres.service.name }}" 8 | spec: 9 | ports: 10 | - port: {{.Values.deployments.postgres.service.port}} 11 | name: "{{ .Values.deployments.postgres.service.name }}" 12 | selector: 13 | app: "{{ .Values.deployments.postgres.service.name }}" 14 | type: ClusterIP 15 | --- 16 | apiVersion: apps/v1 17 | kind: Deployment 18 | metadata: 19 | name: "{{ .Values.deployments.postgres.service.name }}" 20 | namespace: "{{ .Values.namespace }}" 21 | spec: 22 | selector: 23 | matchLabels: 24 | app: "{{ .Values.deployments.postgres.service.name }}" 25 | strategy: 26 | type: Recreate 27 | template: 28 | metadata: 29 | labels: 30 | app: "{{ .Values.deployments.postgres.service.name }}" 31 | spec: 32 | containers: 33 | - image: "{{ .Values.deployments.postgres.image.name }}" 34 | name: "{{ .Values.deployments.postgres.service.name }}" 35 | envFrom: 36 | - secretRef: 37 | name: "{{ .Values.secrets.postgres.name }}" 38 | ports: 39 | - containerPort: {{.Values.deployments.postgres.service.port}} 40 | name: "{{ .Values.deployments.postgres.service.name }}" 41 | securityContext: 42 | privileged: false 43 | volumeMounts: 44 | - name: "{{ .Values.deployments.postgres.volume.name }}" 45 | mountPath: "{{ .Values.deployments.postgres.volume.path }}" 46 | resources: 47 | limits: 48 | memory: 512Mi 49 | cpu: "1" 50 | requests: 51 | memory: 256Mi 52 | cpu: "0.2" 53 | volumes: 54 | - name: "{{ .Values.deployments.postgres.volume.name }}" 55 | persistentVolumeClaim: 56 | claimName: "{{ .Values.pvc.name }}" 57 | -------------------------------------------------------------------------------- /deployments/helm/keycloak-k8s-local/templates/05_keycloak.yml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: "{{ .Values.deployments.keycloak.service.name }}" 5 | namespace: "{{ .Values.namespace }}" 6 | labels: 7 | app: "{{ .Values.deployments.keycloak.service.name }}" 8 | spec: 9 | ports: 10 | - name: https 11 | port: {{.Values.deployments.securePort}} 12 | targetPort: {{.Values.deployments.keycloak.ports.containerPort}} 13 | selector: 14 | app: "{{ .Values.deployments.keycloak.service.name }}" 15 | type: LoadBalancer 16 | --- 17 | apiVersion: apps/v1 18 | kind: Deployment 19 | metadata: 20 | name: "{{ .Values.deployments.keycloak.service.name }}" 21 | namespace: "{{ .Values.namespace }}" 22 | labels: 23 | app: "{{ .Values.deployments.keycloak.service.name }}" 24 | spec: 25 | replicas: 1 26 | selector: 27 | matchLabels: 28 | app: "{{ .Values.deployments.keycloak.service.name }}" 29 | template: 30 | metadata: 31 | labels: 32 | app: "{{ .Values.deployments.keycloak.service.name }}" 33 | spec: 34 | containers: 35 | - name: "{{ .Values.deployments.keycloak.service.name }}" 36 | image: quay.io/keycloak/keycloak:21.0.2 37 | args: ["start-dev"] 38 | env: 39 | - name: KEYCLOAK_ADMIN 40 | valueFrom: 41 | secretKeyRef: 42 | key: KEYCLOAK_ADMIN 43 | name: "{{ .Values.secrets.keycloak.name }}" 44 | - name: KEYCLOAK_ADMIN_PASSWORD 45 | valueFrom: 46 | secretKeyRef: 47 | key: KEYCLOAK_ADMIN_PASSWORD 48 | name: "{{ .Values.secrets.keycloak.name }}" 49 | - name: KC_PROXY 50 | value: "edge" 51 | - name: KC_HEALTH_ENABLED 52 | value: "true" 53 | - name: KC_METRICS_ENABLED 54 | value: "true" 55 | - name: KC_HOSTNAME_STRICT_HTTPS 56 | value: "true" 57 | - name: KC_LOG_LEVEL 58 | value: INFO 59 | - name: KC_DB 60 | value: postgres 61 | - name: KC_DB_URL 62 | value: "jdbc:postgresql://{{ .Values.deployments.postgres.service.name }}/{{ .Values.deployments.postgres.db.name }}" 63 | - name: KC_DB_USERNAME 64 | valueFrom: 65 | secretKeyRef: 66 | name: "{{ .Values.secrets.postgres.name }}" 67 | key: POSTGRES_USER 68 | - name: KC_DB_PASSWORD 69 | valueFrom: 70 | secretKeyRef: 71 | name: "{{ .Values.secrets.postgres.name }}" 72 | key: POSTGRES_PASSWORD 73 | ports: 74 | - name: http 75 | containerPort: 76 | {{.Values.deployments.keycloak.ports.containerPort}} 77 | readinessProbe: 78 | httpGet: 79 | path: /health/ready 80 | port: {{.Values.deployments.keycloak.ports.containerPort}} 81 | initialDelaySeconds: 250 82 | periodSeconds: 10 83 | livenessProbe: 84 | httpGet: 85 | path: /health/live 86 | port: {{.Values.deployments.keycloak.ports.containerPort}} 87 | initialDelaySeconds: 500 88 | periodSeconds: 30 89 | resources: 90 | limits: 91 | memory: 512Mi 92 | cpu: "1" 93 | requests: 94 | memory: 256Mi 95 | cpu: "0.2" 96 | -------------------------------------------------------------------------------- /deployments/helm/keycloak-k8s-local/templates/06_ingress.yml: -------------------------------------------------------------------------------- 1 | apiVersion: networking.k8s.io/v1 2 | kind: Ingress 3 | metadata: 4 | name: "{{ .Values.deployments.keycloak.service.name }}" 5 | namespace: "{{ .Values.namespace }}" 6 | spec: 7 | tls: 8 | - hosts: 9 | - "{{ .Values.deployments.ingress.host }}" 10 | secretName: "{{ .Values.secrets.tls.name }}" 11 | rules: 12 | - host: "{{ .Values.deployments.ingress.host }}" 13 | http: 14 | paths: 15 | - path: / 16 | pathType: Prefix 17 | backend: 18 | service: 19 | name: "{{ .Values.deployments.keycloak.service.name }}" 20 | port: 21 | number: {{.Values.deployments.securePort}} 22 | -------------------------------------------------------------------------------- /deployments/helm/keycloak-k8s-local/templates/_helpers.tpl: -------------------------------------------------------------------------------- 1 | {{/* 2 | Expand the name of the chart. 3 | */}} 4 | {{- define "keycloak-k8s-local.name" -}} 5 | {{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} 6 | {{- end }} 7 | 8 | {{/* 9 | Create a default fully qualified app name. 10 | We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). 11 | If release name contains chart name it will be used as a full name. 12 | */}} 13 | {{- define "keycloak-k8s-local.fullname" -}} 14 | {{- if .Values.fullnameOverride }} 15 | {{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} 16 | {{- else }} 17 | {{- $name := default .Chart.Name .Values.nameOverride }} 18 | {{- if contains $name .Release.Name }} 19 | {{- .Release.Name | trunc 63 | trimSuffix "-" }} 20 | {{- else }} 21 | {{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} 22 | {{- end }} 23 | {{- end }} 24 | {{- end }} 25 | 26 | {{/* 27 | Create chart name and version as used by the chart label. 28 | */}} 29 | {{- define "keycloak-k8s-local.chart" -}} 30 | {{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} 31 | {{- end }} 32 | 33 | {{/* 34 | Common labels 35 | */}} 36 | {{- define "keycloak-k8s-local.labels" -}} 37 | helm.sh/chart: {{ include "keycloak-k8s-local.chart" . }} 38 | {{ include "keycloak-k8s-local.selectorLabels" . }} 39 | {{- if .Chart.AppVersion }} 40 | app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} 41 | {{- end }} 42 | app.kubernetes.io/managed-by: {{ .Release.Service }} 43 | {{- end }} 44 | 45 | {{/* 46 | Selector labels 47 | */}} 48 | {{- define "keycloak-k8s-local.selectorLabels" -}} 49 | app.kubernetes.io/name: {{ include "keycloak-k8s-local.name" . }} 50 | app.kubernetes.io/instance: {{ .Release.Name }} 51 | {{- end }} 52 | 53 | {{/* 54 | Create the name of the service account to use 55 | */}} 56 | {{- define "keycloak-k8s-local.serviceAccountName" -}} 57 | {{- if .Values.serviceAccount.create }} 58 | {{- default (include "keycloak-k8s-local.fullname" .) .Values.serviceAccount.name }} 59 | {{- else }} 60 | {{- default "default" .Values.serviceAccount.name }} 61 | {{- end }} 62 | {{- end }} 63 | -------------------------------------------------------------------------------- /deployments/helm/keycloak-k8s-local/values.yaml: -------------------------------------------------------------------------------- 1 | namespace: hbr-keycloak 2 | 3 | # Postgres account data, web server certificates, and keycloak admin user 4 | secrets: 5 | postgres: 6 | name: postgres-credentials 7 | admin: 8 | name: postgres 9 | password: aab++112 10 | tls: 11 | name: tls-secret 12 | cert: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURMVENDQWhXZ0F3SUJBZ0lVUVRQREtLUGtRYjZBYWNXN2htTFdtSThOOVg4d0RRWUpLb1pJaHZjTkFRRUwKQlFBd0pqRVJNQThHQTFVRUF3d0libWRwYm5oemRtTXhFVEFQQmdOVkJBb01DRzVuYVc1NGMzWmpNQjRYRFRJegpNRFF3T1RBM01qSTFOVm9YRFRJME1EUXdPREEzTWpJMU5Wb3dKakVSTUE4R0ExVUVBd3dJYm1kcGJuaHpkbU14CkVUQVBCZ05WQkFvTUNHNW5hVzU0YzNaak1JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0MKQVFFQWwrai9XcFVwQmtNdFBkemV4SGM0WlZHeENpdDlxUmRlV1FDay9JUXNVS1JkNGJSQTlFMXRGTzNheENnRQpKcGdYL1RHSHhid2VvMFVrU3BRU2czYzBoZ09KaWJKWGxlTmpsM0VTOXNmQWVCZEdVVFNMYzFtZ0x0Sm5sYklaClE2U3NnZ3RuZ3VGSFRZcFBoblBCZ1MzTkFjYk1WK01ZTlNEamVXQnJWTVI3RWM5YmJrT3d3VHNod1lXNEorTzUKdUdRTlhYUWNLWFdDdTRRZXpoUmNnOVhseEhWUTkxTURnNEJLbk5jUm9QdVRBaHdlWUJGSGZTenNJbTBQTzE5Qgp1c093cmJCTXNhV2UyZzRqbEIrZmtCMExLbS84RklRZnVXUS95eTVZYnpoK0kzT0xoUTdvYmNQUzlBNHl1R0Y1CnhVNExZbFRpNFN2UnBGSHN0QUxQT0JzVzd3SURBUUFCbzFNd1VUQWRCZ05WSFE0RUZnUVV5SkFxV21ISEtiTzEKWk0vMDhzc2NHRkFYQ1h3d0h3WURWUjBqQkJnd0ZvQVV5SkFxV21ISEtiTzFaTS8wOHNzY0dGQVhDWHd3RHdZRApWUjBUQVFIL0JBVXdBd0VCL3pBTkJna3Foa2lHOXcwQkFRc0ZBQU9DQVFFQWE0Sk8xSGZ6Z0FPTTJUb3JmRFFEClhVNWM3bENjYmRDa1ZGeHBBQUlyeVo3WWljMm1mcllTNHMwMTU1dHVqUTNqLy9hVlYwTWFpOU96bGVTdmFockQKeU9veE9INzUrZWtUd1BkSHhvaHoxbFI5dW1yRUNBcXlIYnR2SXBCcFliTXFnZmp6KzJZNFBib290ZmhjMHVWZwptRFRsN1d3ak1XMURiQmlsM3ptSlRZZU5vSThUTXlCTWhwcGt0UndDVkM4VGRsRHNBUHZFWlZXUDBpL3VGOHBDCmZlZXFiaEtQSHZjZUV5V3Q4U0N0aDhmaDAycnViQlBjT3RycmtuUUlxakpxeVFPUFFXNjM1TGpxQTM0aWpBcEEKNDJxTlIzWGJvdTFOSkM3Wk8vdzJQYmtLZnlCNkNrdmRHQ3dOZWxjSnpRZXN1RWd6NDNrS240RUVIK09vUkFVTQprdz09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K 13 | key: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2d0lCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktrd2dnU2xBZ0VBQW9JQkFRQ1g2UDlhbFNrR1F5MDkKM043RWR6aGxVYkVLSzMycEYxNVpBS1Q4aEN4UXBGM2h0RUQwVFcwVTdkckVLQVFtbUJmOU1ZZkZ2QjZqUlNSSwpsQktEZHpTR0E0bUpzbGVWNDJPWGNSTDJ4OEI0RjBaUk5JdHpXYUF1MG1lVnNobERwS3lDQzJlQzRVZE5paytHCmM4R0JMYzBCeHN4WDR4ZzFJT041WUd0VXhIc1J6MXR1UTdEQk95SEJoYmduNDdtNFpBMWRkQndwZFlLN2hCN08KRkZ5RDFlWEVkVkQzVXdPRGdFcWMxeEdnKzVNQ0hCNWdFVWQ5TE93aWJRODdYMEc2dzdDdHNFeXhwWjdhRGlPVQpINStRSFFzcWIvd1VoQis1WkQvTExsaHZPSDRqYzR1RkR1aHR3OUwwRGpLNFlYbkZUZ3RpVk9MaEs5R2tVZXkwCkFzODRHeGJ2QWdNQkFBRUNnZ0VBT2dic2srTnFXbFFLMGhpdWw0bWE1MGovUVkwL1lQbm1Oa1ZDd0pxVWV2RnUKVXlzUnJNQnVySkgzQVByd0t2WHFJL05wazZTNlowK2YvMFQwbFhkUmZ1ZVhBQnc1eksyaGUxWGNFcHhXN3dpaworWndDc0x0SnJ0ajhiSGd0b21NaTZrSUU5aityaHZrUVM2R29CdnBCMXkzakhLZEl0ZktzTWM4YzhMSmsrSFlRCkltS09RWlpZQ3lzZlpQTld3NW5oR3k0VlpoeGo3T2J5MHJiLzU0bHVXNkdoSE9yY1hXRXVwbWY5UGNibVYzeHkKV0pvWmJOb1hKZjFEakhZeHltWmFIRnlPQ3ZVT1hDQmJiTzBQNENlbm0yYjJ0Wm8vWlo2VUxpeFNTUExiUlF3MApnbSs4K0prVzhRZS9WT2N5MjdNV0trbUVGUUV3T0dkQUR3dnQ3Q04rRVFLQmdRREhLd3JTVlpMa2FrZkFDTXZ3CkJCcXppT0xZQkxVRFhWNDVCV0w1eHpMK2lGbmJMUnROQndzeXd6MGh4KzNxeXdoRm5IQStKMURVcXg4cDkvR08KRER5Y0REZFUzbk1VandPNFNwMUdNeUtHb1B5bWk3aVFrWFBOT3Y3TXFpRmtvZitvcHBBSWV5U3RvTURvdkJidQpxL2lMWXM0MnJvNTF3NWtkYkVJTVE4TkpNd0tCZ1FERFFkTUg1V2NrNG96b3JlY3REU1VLZ1lUMzc4MnJHZzNFClRxTFdmYUZFcGtaUi9qVVU4OHp2VytBTTlDYXJQUFd1ZFZWaU1MNTAyWktqM0RCQ3pORGQ2ZkxCdHFmSGRCbnkKWnMvcWYvb2hya0kwOHIrRjZibFV0ejZJWWQxeFZBM2dENFJYY2tpWXpCWGhYYTNYVmVTNllBWFI4bmF4RmZiZwptYW9DUU5jVFZRS0JnUUNHWFRaV3dkNXdkSGJsU2NuenFZRXQvN294eTdNbWl2WEcrQ2hXcEJsMStCek9yWGFPCmw2THBZeWU1dzN4eGV2bWdwTEpnYS91dkRhYmZsR01FMXFLSkVBREFJN1oxZHlvbVNVZ2pGTnBGQXhTUGN4RlgKanBrV0txZTlBVVczODBaYnk4cTl2ZjMzbU15cjlrQnVVZHhDaEt6ajNRMUV5MmxmblNwTnhlVllXd0tCZ1FDSwplSXI5Ulk0QlZYMFNvZ21aSklKSlVoTUhkaFFJTEtEb3Y4K3hoMFN3RjY4MUJLK0dYV1BQdC90TGxIWTc2QzVmCmU2eUN4d2k2ZTNZSUtPWTg2VjJTa3cvcW11dWZnbEhJVzJ0RjVWNXhObENUbGplRzgzclFmbWVsZHFvQmJkZXQKTjdQbUJCRkI4ekh0TW05UGtBVjJ1eFJGa01ybHlTcmNtMzA2dmRzSlJRS0JnUUNINERRZEFNbnVMVk9UMVU4RwpzY0h2RmlpZFN2aEZ3dk45ejNpU2JmZytKbHRmYkxQbXlEREdGc2lIQzZQcG4yZHdneVp2MjZxYnRvVE9oZjRMClNkcTZDWjJVZi80c3RpbWJWbEtxK2J4UzdxMENIanYrYWtqUWwwbC9wY3cwOWdMU2ZDYmd5dEdMQXA4WW5VQXAKOWhiczF4RUFmcXJEdzdIbVkyb2dBanFuSFE9PQotLS0tLUVORCBQUklWQVRFIEtFWS0tLS0tCg== 14 | keycloak: 15 | name: keycloak-secrets 16 | admin: 17 | name: admin 18 | password: admin 19 | 20 | # Postgres, Keycloak and Ingress deployments 21 | deployments: 22 | securePort: 443 23 | postgres: 24 | image: 25 | name: postgres:latest 26 | db: 27 | name: keycloak 28 | service: 29 | name: postgres 30 | port: 5432 31 | volume: 32 | name: postgres-storage 33 | path: /var/lib/postgresql/data 34 | keycloak: 35 | service: 36 | name: keycloak 37 | ports: 38 | containerPort: 8080 39 | ingress: 40 | host: localhost 41 | 42 | # PersistenVolume / PersistenVolumeClaims 43 | pv: 44 | name: postgres-pv 45 | size: 1Gi 46 | pvc: 47 | name: postgres-pvc 48 | size: 1Gi 49 | -------------------------------------------------------------------------------- /deployments/manual/01_namespace.yml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Namespace 3 | metadata: 4 | name: hbr-keycloak -------------------------------------------------------------------------------- /deployments/manual/02_secrets.yml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Secret 3 | metadata: 4 | name: postgres-credentials 5 | namespace: hbr-keycloak 6 | type: Opaque 7 | stringData: 8 | POSTGRES_USER: postgres 9 | POSTGRES_PASSWORD: aab++112 10 | POSTGRES_DB: keycloak 11 | --- 12 | apiVersion: v1 13 | kind: Secret 14 | metadata: 15 | name: tls-secret 16 | namespace: hbr-keycloak 17 | type: kubernetes.io/tls 18 | data: 19 | tls.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURMVENDQWhXZ0F3SUJBZ0lVUVRQREtLUGtRYjZBYWNXN2htTFdtSThOOVg4d0RRWUpLb1pJaHZjTkFRRUwKQlFBd0pqRVJNQThHQTFVRUF3d0libWRwYm5oemRtTXhFVEFQQmdOVkJBb01DRzVuYVc1NGMzWmpNQjRYRFRJegpNRFF3T1RBM01qSTFOVm9YRFRJME1EUXdPREEzTWpJMU5Wb3dKakVSTUE4R0ExVUVBd3dJYm1kcGJuaHpkbU14CkVUQVBCZ05WQkFvTUNHNW5hVzU0YzNaak1JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0MKQVFFQWwrai9XcFVwQmtNdFBkemV4SGM0WlZHeENpdDlxUmRlV1FDay9JUXNVS1JkNGJSQTlFMXRGTzNheENnRQpKcGdYL1RHSHhid2VvMFVrU3BRU2czYzBoZ09KaWJKWGxlTmpsM0VTOXNmQWVCZEdVVFNMYzFtZ0x0Sm5sYklaClE2U3NnZ3RuZ3VGSFRZcFBoblBCZ1MzTkFjYk1WK01ZTlNEamVXQnJWTVI3RWM5YmJrT3d3VHNod1lXNEorTzUKdUdRTlhYUWNLWFdDdTRRZXpoUmNnOVhseEhWUTkxTURnNEJLbk5jUm9QdVRBaHdlWUJGSGZTenNJbTBQTzE5Qgp1c093cmJCTXNhV2UyZzRqbEIrZmtCMExLbS84RklRZnVXUS95eTVZYnpoK0kzT0xoUTdvYmNQUzlBNHl1R0Y1CnhVNExZbFRpNFN2UnBGSHN0QUxQT0JzVzd3SURBUUFCbzFNd1VUQWRCZ05WSFE0RUZnUVV5SkFxV21ISEtiTzEKWk0vMDhzc2NHRkFYQ1h3d0h3WURWUjBqQkJnd0ZvQVV5SkFxV21ISEtiTzFaTS8wOHNzY0dGQVhDWHd3RHdZRApWUjBUQVFIL0JBVXdBd0VCL3pBTkJna3Foa2lHOXcwQkFRc0ZBQU9DQVFFQWE0Sk8xSGZ6Z0FPTTJUb3JmRFFEClhVNWM3bENjYmRDa1ZGeHBBQUlyeVo3WWljMm1mcllTNHMwMTU1dHVqUTNqLy9hVlYwTWFpOU96bGVTdmFockQKeU9veE9INzUrZWtUd1BkSHhvaHoxbFI5dW1yRUNBcXlIYnR2SXBCcFliTXFnZmp6KzJZNFBib290ZmhjMHVWZwptRFRsN1d3ak1XMURiQmlsM3ptSlRZZU5vSThUTXlCTWhwcGt0UndDVkM4VGRsRHNBUHZFWlZXUDBpL3VGOHBDCmZlZXFiaEtQSHZjZUV5V3Q4U0N0aDhmaDAycnViQlBjT3RycmtuUUlxakpxeVFPUFFXNjM1TGpxQTM0aWpBcEEKNDJxTlIzWGJvdTFOSkM3Wk8vdzJQYmtLZnlCNkNrdmRHQ3dOZWxjSnpRZXN1RWd6NDNrS240RUVIK09vUkFVTQprdz09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K 20 | tls.key: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2d0lCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktrd2dnU2xBZ0VBQW9JQkFRQ1g2UDlhbFNrR1F5MDkKM043RWR6aGxVYkVLSzMycEYxNVpBS1Q4aEN4UXBGM2h0RUQwVFcwVTdkckVLQVFtbUJmOU1ZZkZ2QjZqUlNSSwpsQktEZHpTR0E0bUpzbGVWNDJPWGNSTDJ4OEI0RjBaUk5JdHpXYUF1MG1lVnNobERwS3lDQzJlQzRVZE5paytHCmM4R0JMYzBCeHN4WDR4ZzFJT041WUd0VXhIc1J6MXR1UTdEQk95SEJoYmduNDdtNFpBMWRkQndwZFlLN2hCN08KRkZ5RDFlWEVkVkQzVXdPRGdFcWMxeEdnKzVNQ0hCNWdFVWQ5TE93aWJRODdYMEc2dzdDdHNFeXhwWjdhRGlPVQpINStRSFFzcWIvd1VoQis1WkQvTExsaHZPSDRqYzR1RkR1aHR3OUwwRGpLNFlYbkZUZ3RpVk9MaEs5R2tVZXkwCkFzODRHeGJ2QWdNQkFBRUNnZ0VBT2dic2srTnFXbFFLMGhpdWw0bWE1MGovUVkwL1lQbm1Oa1ZDd0pxVWV2RnUKVXlzUnJNQnVySkgzQVByd0t2WHFJL05wazZTNlowK2YvMFQwbFhkUmZ1ZVhBQnc1eksyaGUxWGNFcHhXN3dpaworWndDc0x0SnJ0ajhiSGd0b21NaTZrSUU5aityaHZrUVM2R29CdnBCMXkzakhLZEl0ZktzTWM4YzhMSmsrSFlRCkltS09RWlpZQ3lzZlpQTld3NW5oR3k0VlpoeGo3T2J5MHJiLzU0bHVXNkdoSE9yY1hXRXVwbWY5UGNibVYzeHkKV0pvWmJOb1hKZjFEakhZeHltWmFIRnlPQ3ZVT1hDQmJiTzBQNENlbm0yYjJ0Wm8vWlo2VUxpeFNTUExiUlF3MApnbSs4K0prVzhRZS9WT2N5MjdNV0trbUVGUUV3T0dkQUR3dnQ3Q04rRVFLQmdRREhLd3JTVlpMa2FrZkFDTXZ3CkJCcXppT0xZQkxVRFhWNDVCV0w1eHpMK2lGbmJMUnROQndzeXd6MGh4KzNxeXdoRm5IQStKMURVcXg4cDkvR08KRER5Y0REZFUzbk1VandPNFNwMUdNeUtHb1B5bWk3aVFrWFBOT3Y3TXFpRmtvZitvcHBBSWV5U3RvTURvdkJidQpxL2lMWXM0MnJvNTF3NWtkYkVJTVE4TkpNd0tCZ1FERFFkTUg1V2NrNG96b3JlY3REU1VLZ1lUMzc4MnJHZzNFClRxTFdmYUZFcGtaUi9qVVU4OHp2VytBTTlDYXJQUFd1ZFZWaU1MNTAyWktqM0RCQ3pORGQ2ZkxCdHFmSGRCbnkKWnMvcWYvb2hya0kwOHIrRjZibFV0ejZJWWQxeFZBM2dENFJYY2tpWXpCWGhYYTNYVmVTNllBWFI4bmF4RmZiZwptYW9DUU5jVFZRS0JnUUNHWFRaV3dkNXdkSGJsU2NuenFZRXQvN294eTdNbWl2WEcrQ2hXcEJsMStCek9yWGFPCmw2THBZeWU1dzN4eGV2bWdwTEpnYS91dkRhYmZsR01FMXFLSkVBREFJN1oxZHlvbVNVZ2pGTnBGQXhTUGN4RlgKanBrV0txZTlBVVczODBaYnk4cTl2ZjMzbU15cjlrQnVVZHhDaEt6ajNRMUV5MmxmblNwTnhlVllXd0tCZ1FDSwplSXI5Ulk0QlZYMFNvZ21aSklKSlVoTUhkaFFJTEtEb3Y4K3hoMFN3RjY4MUJLK0dYV1BQdC90TGxIWTc2QzVmCmU2eUN4d2k2ZTNZSUtPWTg2VjJTa3cvcW11dWZnbEhJVzJ0RjVWNXhObENUbGplRzgzclFmbWVsZHFvQmJkZXQKTjdQbUJCRkI4ekh0TW05UGtBVjJ1eFJGa01ybHlTcmNtMzA2dmRzSlJRS0JnUUNINERRZEFNbnVMVk9UMVU4RwpzY0h2RmlpZFN2aEZ3dk45ejNpU2JmZytKbHRmYkxQbXlEREdGc2lIQzZQcG4yZHdneVp2MjZxYnRvVE9oZjRMClNkcTZDWjJVZi80c3RpbWJWbEtxK2J4UzdxMENIanYrYWtqUWwwbC9wY3cwOWdMU2ZDYmd5dEdMQXA4WW5VQXAKOWhiczF4RUFmcXJEdzdIbVkyb2dBanFuSFE9PQotLS0tLUVORCBQUklWQVRFIEtFWS0tLS0tCg== 21 | --- 22 | apiVersion: v1 23 | kind: Secret 24 | metadata: 25 | name: keycloak-secrets 26 | namespace: hbr-keycloak 27 | type: Opaque 28 | stringData: 29 | KEYCLOAK_ADMIN: admin 30 | KEYCLOAK_ADMIN_PASSWORD: admin 31 | -------------------------------------------------------------------------------- /deployments/manual/03_storage.yml: -------------------------------------------------------------------------------- 1 | kind: PersistentVolume 2 | apiVersion: v1 3 | metadata: 4 | name: postgres-pv 5 | namespace: hbr-keycloak 6 | labels: 7 | type: local 8 | app: postgres 9 | spec: 10 | storageClassName: "standard" 11 | capacity: 12 | storage: 1Gi 13 | accessModes: 14 | - ReadWriteMany 15 | persistentVolumeReclaimPolicy: Retain 16 | hostPath: 17 | path: "/mnt/data" 18 | --- 19 | apiVersion: v1 20 | kind: PersistentVolumeClaim 21 | metadata: 22 | name: postgres-pvc 23 | namespace: hbr-keycloak 24 | labels: 25 | app: postgres 26 | spec: 27 | storageClassName: "standard" 28 | accessModes: 29 | - ReadWriteMany 30 | resources: 31 | requests: 32 | storage: 1Gi 33 | -------------------------------------------------------------------------------- /deployments/manual/04_postgres.yml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: postgres 5 | namespace: hbr-keycloak 6 | labels: 7 | app: postgres 8 | spec: 9 | ports: 10 | - port: 5432 11 | name: postgres 12 | selector: 13 | app: postgres 14 | type: ClusterIP 15 | --- 16 | apiVersion: apps/v1 17 | kind: Deployment 18 | metadata: 19 | name: postgres 20 | namespace: hbr-keycloak 21 | spec: 22 | selector: 23 | matchLabels: 24 | app: postgres 25 | strategy: 26 | type: Recreate 27 | template: 28 | metadata: 29 | labels: 30 | app: postgres 31 | spec: 32 | containers: 33 | - image: postgres:latest 34 | name: postgres 35 | envFrom: 36 | - secretRef: 37 | name: postgres-credentials 38 | ports: 39 | - containerPort: 5432 40 | name: postgres 41 | securityContext: 42 | privileged: false 43 | volumeMounts: 44 | - name: postgres-storage 45 | mountPath: /var/lib/postgresql/data 46 | resources: 47 | limits: 48 | memory: 512Mi 49 | cpu: "1" 50 | requests: 51 | memory: 256Mi 52 | cpu: "0.2" 53 | volumes: 54 | - name: postgres-storage 55 | persistentVolumeClaim: 56 | claimName: postgres-pvc 57 | 58 | -------------------------------------------------------------------------------- /deployments/manual/05_keycloak.yml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: keycloak 5 | namespace: hbr-keycloak 6 | labels: 7 | app: keycloak 8 | spec: 9 | ports: 10 | - name: https 11 | port: 443 12 | targetPort: 8080 13 | selector: 14 | app: keycloak 15 | type: LoadBalancer 16 | --- 17 | apiVersion: apps/v1 18 | kind: Deployment 19 | metadata: 20 | name: keycloak 21 | namespace: hbr-keycloak 22 | labels: 23 | app: keycloak 24 | spec: 25 | replicas: 1 26 | selector: 27 | matchLabels: 28 | app: keycloak 29 | template: 30 | metadata: 31 | labels: 32 | app: keycloak 33 | spec: 34 | containers: 35 | - name: keycloak 36 | image: quay.io/keycloak/keycloak:21.0.2 37 | args: ["start-dev"] 38 | env: 39 | - name: KEYCLOAK_ADMIN 40 | valueFrom: 41 | secretKeyRef: 42 | key: KEYCLOAK_ADMIN 43 | name: keycloak-secrets 44 | - name: KEYCLOAK_ADMIN_PASSWORD 45 | valueFrom: 46 | secretKeyRef: 47 | key: KEYCLOAK_ADMIN_PASSWORD 48 | name: keycloak-secrets 49 | - name: KC_PROXY 50 | value: "edge" 51 | - name: KC_HEALTH_ENABLED 52 | value: "true" 53 | - name: KC_METRICS_ENABLED 54 | value: "true" 55 | - name: KC_HOSTNAME_STRICT_HTTPS 56 | value: "true" 57 | - name: KC_LOG_LEVEL 58 | value: INFO 59 | - name: KC_DB 60 | value: postgres 61 | - name: POSTGRES_DB 62 | valueFrom: 63 | secretKeyRef: 64 | name: postgres-credentials 65 | key: POSTGRES_DB 66 | - name: KC_DB_URL 67 | value: jdbc:postgresql://postgres/$(POSTGRES_DB) 68 | - name: KC_DB_USERNAME 69 | valueFrom: 70 | secretKeyRef: 71 | name: postgres-credentials 72 | key: POSTGRES_USER 73 | - name: KC_DB_PASSWORD 74 | valueFrom: 75 | secretKeyRef: 76 | name: postgres-credentials 77 | key: POSTGRES_PASSWORD 78 | ports: 79 | - name: http 80 | containerPort: 8080 81 | readinessProbe: 82 | httpGet: 83 | path: /health/ready 84 | port: 8080 85 | initialDelaySeconds: 250 86 | periodSeconds: 10 87 | livenessProbe: 88 | httpGet: 89 | path: /health/live 90 | port: 8080 91 | initialDelaySeconds: 500 92 | periodSeconds: 30 93 | resources: 94 | limits: 95 | memory: 512Mi 96 | cpu: "1" 97 | requests: 98 | memory: 256Mi 99 | cpu: "0.2" 100 | 101 | -------------------------------------------------------------------------------- /deployments/manual/06_ingress.yml: -------------------------------------------------------------------------------- 1 | apiVersion: networking.k8s.io/v1 2 | kind: Ingress 3 | metadata: 4 | name: keycloak 5 | namespace: hbr-keycloak 6 | spec: 7 | tls: 8 | - hosts: 9 | - localhost 10 | secretName: tls-secret 11 | rules: 12 | - host: localhost 13 | http: 14 | paths: 15 | - path: / 16 | pathType: Prefix 17 | backend: 18 | service: 19 | name: keycloak 20 | port: 21 | number: 443 -------------------------------------------------------------------------------- /deployments/manual/README.md: -------------------------------------------------------------------------------- 1 | ## Manual setup 2 | 3 | * Apply the YAMLS in numerical order like: `kubectl apply -f 01_namespace.yaml -f 02_secrets.yml ...` 4 | * Enter `watch -n 1 kubectl get all -n hbr-keycloak` to query the current state of deployments. 5 | 6 | ![watch_query](./../../images/watch_query.png) 7 | 8 | * Depending on your machine the deployment of all components will take a minute or two. 9 | * Meanwhile, you could install the [Kubernetes Dashboard](../../kube_dashboard/README.md) to get a nice graphical overview of your k8s system. 10 | 11 | **Hint**: most values and names in these YAMLs are hard-coded. For a more flexible variant, check the alternative [Helm installation](../helm/README.md). -------------------------------------------------------------------------------- /deployments/manual/tls/README.md: -------------------------------------------------------------------------------- 1 | ## Create TLS certs and keys for Ingress 2 | 3 | * Use `create_tls_secret.sh` to generate a new [Secret](https://kubernetes.io/docs/concepts/configuration/secret/) of type TLS 4 | 5 | **Hint**: this is not needed to run the demo as all needed Secrets get automatically created in [02_secrets.yml](../02_secrets.yml). 6 | 7 | To read the contents of a Secret use kubectl, for example: `kubectl get secret keycloak-secrets -n hbr-keycloak -oyaml` 8 | 9 | ![get_secret](../../../images/get_secret.png) -------------------------------------------------------------------------------- /deployments/manual/tls/create_tls_secret.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | kubectl create secret tls nginx-selfsigned-secret --key tls.key --cert tls.crt -n hbr-keycloak -------------------------------------------------------------------------------- /deployments/manual/tls/tls.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIDLTCCAhWgAwIBAgIUQTPDKKPkQb6AacW7hmLWmI8N9X8wDQYJKoZIhvcNAQEL 3 | BQAwJjERMA8GA1UEAwwIbmdpbnhzdmMxETAPBgNVBAoMCG5naW54c3ZjMB4XDTIz 4 | MDQwOTA3MjI1NVoXDTI0MDQwODA3MjI1NVowJjERMA8GA1UEAwwIbmdpbnhzdmMx 5 | ETAPBgNVBAoMCG5naW54c3ZjMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC 6 | AQEAl+j/WpUpBkMtPdzexHc4ZVGxCit9qRdeWQCk/IQsUKRd4bRA9E1tFO3axCgE 7 | JpgX/TGHxbweo0UkSpQSg3c0hgOJibJXleNjl3ES9sfAeBdGUTSLc1mgLtJnlbIZ 8 | Q6SsggtnguFHTYpPhnPBgS3NAcbMV+MYNSDjeWBrVMR7Ec9bbkOwwTshwYW4J+O5 9 | uGQNXXQcKXWCu4QezhRcg9XlxHVQ91MDg4BKnNcRoPuTAhweYBFHfSzsIm0PO19B 10 | usOwrbBMsaWe2g4jlB+fkB0LKm/8FIQfuWQ/yy5Ybzh+I3OLhQ7obcPS9A4yuGF5 11 | xU4LYlTi4SvRpFHstALPOBsW7wIDAQABo1MwUTAdBgNVHQ4EFgQUyJAqWmHHKbO1 12 | ZM/08sscGFAXCXwwHwYDVR0jBBgwFoAUyJAqWmHHKbO1ZM/08sscGFAXCXwwDwYD 13 | VR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAa4JO1HfzgAOM2TorfDQD 14 | XU5c7lCcbdCkVFxpAAIryZ7Yic2mfrYS4s0155tujQ3j//aVV0Mai9OzleSvahrD 15 | yOoxOH75+ekTwPdHxohz1lR9umrECAqyHbtvIpBpYbMqgfjz+2Y4Pbootfhc0uVg 16 | mDTl7WwjMW1DbBil3zmJTYeNoI8TMyBMhppktRwCVC8TdlDsAPvEZVWP0i/uF8pC 17 | feeqbhKPHvceEyWt8SCth8fh02rubBPcOtrrknQIqjJqyQOPQW635LjqA34ijApA 18 | 42qNR3Xbou1NJC7ZO/w2PbkKfyB6CkvdGCwNelcJzQesuEgz43kKn4EEH+OoRAUM 19 | kw== 20 | -----END CERTIFICATE----- 21 | -------------------------------------------------------------------------------- /deployments/manual/tls/tls.key: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQCX6P9alSkGQy09 3 | 3N7EdzhlUbEKK32pF15ZAKT8hCxQpF3htED0TW0U7drEKAQmmBf9MYfFvB6jRSRK 4 | lBKDdzSGA4mJsleV42OXcRL2x8B4F0ZRNItzWaAu0meVshlDpKyCC2eC4UdNik+G 5 | c8GBLc0BxsxX4xg1ION5YGtUxHsRz1tuQ7DBOyHBhbgn47m4ZA1ddBwpdYK7hB7O 6 | FFyD1eXEdVD3UwODgEqc1xGg+5MCHB5gEUd9LOwibQ87X0G6w7CtsEyxpZ7aDiOU 7 | H5+QHQsqb/wUhB+5ZD/LLlhvOH4jc4uFDuhtw9L0DjK4YXnFTgtiVOLhK9GkUey0 8 | As84GxbvAgMBAAECggEAOgbsk+NqWlQK0hiul4ma50j/QY0/YPnmNkVCwJqUevFu 9 | UysRrMBurJH3APrwKvXqI/Npk6S6Z0+f/0T0lXdRfueXABw5zK2he1XcEpxW7wik 10 | +ZwCsLtJrtj8bHgtomMi6kIE9j+rhvkQS6GoBvpB1y3jHKdItfKsMc8c8LJk+HYQ 11 | ImKOQZZYCysfZPNWw5nhGy4VZhxj7Oby0rb/54luW6GhHOrcXWEupmf9PcbmV3xy 12 | WJoZbNoXJf1DjHYxymZaHFyOCvUOXCBbbO0P4Cenm2b2tZo/ZZ6ULixSSPLbRQw0 13 | gm+8+JkW8Qe/VOcy27MWKkmEFQEwOGdADwvt7CN+EQKBgQDHKwrSVZLkakfACMvw 14 | BBqziOLYBLUDXV45BWL5xzL+iFnbLRtNBwsywz0hx+3qywhFnHA+J1DUqx8p9/GO 15 | DDycDDdU3nMUjwO4Sp1GMyKGoPymi7iQkXPNOv7MqiFkof+oppAIeyStoMDovBbu 16 | q/iLYs42ro51w5kdbEIMQ8NJMwKBgQDDQdMH5Wck4ozorectDSUKgYT3782rGg3E 17 | TqLWfaFEpkZR/jUU88zvW+AM9CarPPWudVViML502ZKj3DBCzNDd6fLBtqfHdBny 18 | Zs/qf/ohrkI08r+F6blUtz6IYd1xVA3gD4RXckiYzBXhXa3XVeS6YAXR8naxFfbg 19 | maoCQNcTVQKBgQCGXTZWwd5wdHblScnzqYEt/7oxy7MmivXG+ChWpBl1+BzOrXaO 20 | l6LpYye5w3xxevmgpLJga/uvDabflGME1qKJEADAI7Z1dyomSUgjFNpFAxSPcxFX 21 | jpkWKqe9AUW380Zby8q9vf33mMyr9kBuUdxChKzj3Q1Ey2lfnSpNxeVYWwKBgQCK 22 | eIr9RY4BVX0SogmZJIJJUhMHdhQILKDov8+xh0SwF681BK+GXWPPt/tLlHY76C5f 23 | e6yCxwi6e3YIKOY86V2Skw/qmuufglHIW2tF5V5xNlCTljeG83rQfmeldqoBbdet 24 | N7PmBBFB8zHtMm9PkAV2uxRFkMrlySrcm306vdsJRQKBgQCH4DQdAMnuLVOT1U8G 25 | scHvFiidSvhFwvN9z3iSbfg+JltfbLPmyDDGFsiHC6Ppn2dwgyZv26qbtoTOhf4L 26 | Sdq6CZ2Uf/4stimbVlKq+bxS7q0CHjv+akjQl0l/pcw09gLSfCbgytGLAp8YnUAp 27 | 9hbs1xEAfqrDw7HmY2ogAjqnHQ== 28 | -----END PRIVATE KEY----- 29 | -------------------------------------------------------------------------------- /gifs/create_cluster.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brakmic/Keycloak_on_Kubernetes/9776ef026874eefd70e6d6036132302d0b02f1d2/gifs/create_cluster.gif -------------------------------------------------------------------------------- /gifs/keycloak_postgres_on_k8s.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brakmic/Keycloak_on_Kubernetes/9776ef026874eefd70e6d6036132302d0b02f1d2/gifs/keycloak_postgres_on_k8s.gif -------------------------------------------------------------------------------- /gifs/kubernetes_dashboard.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brakmic/Keycloak_on_Kubernetes/9776ef026874eefd70e6d6036132302d0b02f1d2/gifs/kubernetes_dashboard.gif -------------------------------------------------------------------------------- /gifs/psql_connect.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brakmic/Keycloak_on_Kubernetes/9776ef026874eefd70e6d6036132302d0b02f1d2/gifs/psql_connect.gif -------------------------------------------------------------------------------- /images/db_connect.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brakmic/Keycloak_on_Kubernetes/9776ef026874eefd70e6d6036132302d0b02f1d2/images/db_connect.png -------------------------------------------------------------------------------- /images/get_pods.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brakmic/Keycloak_on_Kubernetes/9776ef026874eefd70e6d6036132302d0b02f1d2/images/get_pods.png -------------------------------------------------------------------------------- /images/get_secret.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brakmic/Keycloak_on_Kubernetes/9776ef026874eefd70e6d6036132302d0b02f1d2/images/get_secret.png -------------------------------------------------------------------------------- /images/helm_install.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brakmic/Keycloak_on_Kubernetes/9776ef026874eefd70e6d6036132302d0b02f1d2/images/helm_install.png -------------------------------------------------------------------------------- /images/keycloak_deployment_in_k8s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brakmic/Keycloak_on_Kubernetes/9776ef026874eefd70e6d6036132302d0b02f1d2/images/keycloak_deployment_in_k8s.png -------------------------------------------------------------------------------- /images/watch_query.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brakmic/Keycloak_on_Kubernetes/9776ef026874eefd70e6d6036132302d0b02f1d2/images/watch_query.png -------------------------------------------------------------------------------- /keycloak.code-workspace: -------------------------------------------------------------------------------- 1 | { 2 | "folders": [ 3 | { 4 | "path": "." 5 | } 6 | ] 7 | } -------------------------------------------------------------------------------- /kind/README.md: -------------------------------------------------------------------------------- 1 | ## Kind configuration 2 | 3 | You can use this config.yml to create a Kind environment with three nodes. 4 | 5 | Just execute this command: `kind create cluster --name hbr-cluster --config=config.yml` 6 | 7 | ![create_cluster](./../gifs/create_cluster.gif) -------------------------------------------------------------------------------- /kind/config.yml: -------------------------------------------------------------------------------- 1 | kind: Cluster 2 | apiVersion: kind.x-k8s.io/v1alpha4 3 | name: hbr-cluster 4 | nodes: 5 | - role: control-plane 6 | kubeadmConfigPatches: 7 | - | 8 | kind: InitConfiguration 9 | nodeRegistration: 10 | kubeletExtraArgs: 11 | node-labels: "ingress-ready=true" 12 | extraPortMappings: 13 | - containerPort: 80 14 | hostPort: 80 15 | protocol: TCP 16 | - containerPort: 443 17 | hostPort: 443 18 | protocol: TCP 19 | - role: worker 20 | - role: worker 21 | -------------------------------------------------------------------------------- /kube_dashboard/README.md: -------------------------------------------------------------------------------- 1 | ### Installing [Kubernetes Dashboard](https://github.com/kubernetes/dashboard) 2 | 3 | * Execute `install.sh` 4 | * Create [ClusterRoleBinding](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#clusterrolebinding-example) and [ServiceAccount](https://kubernetes.io/docs/reference/access-authn-authz/service-accounts-admin/) with `kubectl apply -f setup_access.yml` 5 | * Open proxy with `kubectl proxy` in a separate shell, and keep it activated! 6 | * Create a token with `get_token.sh` 7 | * Open Dashboard on this [URL](http://localhost:8001/api/v1/namespaces/kubernetes-dashboard/services/https:kubernetes-dashboard:/proxy/). 8 | * Enter the token. 9 | 10 | ![kube_dashboard](../gifs/kubernetes_dashboard.gif) -------------------------------------------------------------------------------- /kube_dashboard/get_token.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | kubectl -n kubernetes-dashboard create token admin-user -------------------------------------------------------------------------------- /kube_dashboard/install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.7.0/aio/deploy/recommended.yaml 3 | kubectl apply -f setup_access.yml -------------------------------------------------------------------------------- /kube_dashboard/setup_access.yml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRoleBinding 3 | metadata: 4 | name: admin-user 5 | roleRef: 6 | apiGroup: rbac.authorization.k8s.io 7 | kind: ClusterRole 8 | name: cluster-admin 9 | subjects: 10 | - kind: ServiceAccount 11 | name: admin-user 12 | namespace: kubernetes-dashboard 13 | --- 14 | apiVersion: v1 15 | kind: ServiceAccount 16 | metadata: 17 | name: admin-user 18 | namespace: kubernetes-dashboard --------------------------------------------------------------------------------