chart: extract hydra maester chart out of auth/charts/hydra.tar.gz (#96)

* chart: extract hydra maester chart out of auth/charts/hydra.tar.gz

* auth: install shared hydra maester during bootstrap

* hydra-maester: fix chart name typo

* hydra-maester: fix charts repo namespace

---------

Co-authored-by: Giorgi Lekveishvili <lekva@gl-mbp-m1-max.local>
diff --git a/charts/hydra-maester/.helmignore b/charts/hydra-maester/.helmignore
new file mode 100644
index 0000000..f0c1319
--- /dev/null
+++ b/charts/hydra-maester/.helmignore
@@ -0,0 +1,21 @@
+# Patterns to ignore when building packages.
+# This supports shell glob matching, relative path matching, and
+# negation (prefixed with !). Only one pattern per line.
+.DS_Store
+# Common VCS dirs
+.git/
+.gitignore
+.bzr/
+.bzrignore
+.hg/
+.hgignore
+.svn/
+# Common backup files
+*.swp
+*.bak
+*.tmp
+*~
+# Various IDEs
+.project
+.idea/
+*.tmproj
diff --git a/charts/hydra-maester/Chart.yaml b/charts/hydra-maester/Chart.yaml
new file mode 100644
index 0000000..81233c5
--- /dev/null
+++ b/charts/hydra-maester/Chart.yaml
@@ -0,0 +1,7 @@
+apiVersion: v2
+appVersion: v0.0.23
+description: A Helm chart for Kubernetes
+icon: https://raw.githubusercontent.com/ory/docs/master/docs/static/img/logo-hydra.svg
+name: hydra-maester
+type: application
+version: 0.33.1
diff --git a/charts/hydra-maester/README.md b/charts/hydra-maester/README.md
new file mode 100644
index 0000000..838ca01
--- /dev/null
+++ b/charts/hydra-maester/README.md
@@ -0,0 +1,44 @@
+# hydra-maester
+
+![Version: 0.33.0](https://img.shields.io/badge/Version-0.33.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: v0.0.23](https://img.shields.io/badge/AppVersion-v0.0.23-informational?style=flat-square)
+
+A Helm chart for Kubernetes
+
+## Values
+
+| Key | Type | Default | Description |
+|-----|------|---------|-------------|
+| adminService | object | `{"endpoint":"/admin/clients","name":null,"port":null}` | Connection data to admin service of Hydra |
+| adminService.endpoint | string | `"/admin/clients"` | Set the clients endpoint, should be `/clients` for Hydra 1.x and `/admin/clients` for Hydra 2.x |
+| adminService.name | string | `nil` | Service name |
+| adminService.port | string | `nil` | Service port |
+| affinity | object | `{}` | Configure node affinity |
+| deployment.args | object | `{"syncPeriod":""}` | Arguments to be passed to the program |
+| deployment.args.syncPeriod | string | `""` | The minimum frequency at which watched resources are reconciled |
+| deployment.automountServiceAccountToken | bool | `true` | This applications connects to the k8s API and requires the permissions |
+| deployment.dnsConfig | object | `{}` | Configure pod dnsConfig. |
+| deployment.extraAnnotations | object | `{}` | Deployment level extra annotations |
+| deployment.extraLabels | object | `{}` | Deployment level extra labels |
+| deployment.nodeSelector | object | `{}` | Node labels for pod assignment. |
+| deployment.podMetadata | object | `{"annotations":{},"labels":{}}` | Specify pod metadata, this metadata is added directly to the pod, and not higher objects |
+| deployment.podMetadata.annotations | object | `{}` | Extra pod level annotations |
+| deployment.podMetadata.labels | object | `{}` | Extra pod level labels |
+| deployment.resources | object | `{}` |  |
+| deployment.securityContext | object | `{"allowPrivilegeEscalation":false,"capabilities":{"drop":["ALL"]},"privileged":false,"readOnlyRootFilesystem":true,"runAsNonRoot":true,"runAsUser":1000,"seccompProfile":{"type":"RuntimeDefault"}}` | Default security context |
+| deployment.serviceAccount | object | `{"annotations":{}}` | Configure service account |
+| deployment.serviceAccount.annotations | object | `{}` | Annotations to add to the service account |
+| deployment.tolerations | list | `[]` | Configure node tolerations. |
+| deployment.topologySpreadConstraints | list | `[]` | Configure pod topologySpreadConstraints. |
+| enabledNamespaces | list | `[]` | The Controller have CREATE and READ access to all Secrets in the namespaces listed below. |
+| forwardedProto | string | `nil` |  |
+| image.pullPolicy | string | `"IfNotPresent"` | Image pull policy |
+| image.repository | string | `"oryd/hydra-maester"` | Ory Hydra-maester image |
+| image.tag | string | `"v0.0.27"` | Ory Hydra-maester version |
+| imagePullSecrets | list | `[]` | Image pull secrets |
+| pdb | object | `{"enabled":false,"spec":{"minAvailable":1}}` | PodDistributionBudget configuration |
+| priorityClassName | string | `""` | Pod priority # https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/ |
+| replicaCount | int | `1` | Number of replicas in deployment |
+| singleNamespaceMode | bool | `false` | Single namespace mode. If enabled the controller will watch for resources only from namespace it is deployed in, ignoring others |
+
+----------------------------------------------
+Autogenerated from chart metadata using [helm-docs v1.11.0](https://github.com/norwoodj/helm-docs/releases/v1.11.0)
diff --git a/charts/hydra-maester/crds/crd-oauth2clients.yaml b/charts/hydra-maester/crds/crd-oauth2clients.yaml
new file mode 100644
index 0000000..ebc9ebb
--- /dev/null
+++ b/charts/hydra-maester/crds/crd-oauth2clients.yaml
@@ -0,0 +1,253 @@
+---
+apiVersion: apiextensions.k8s.io/v1
+kind: CustomResourceDefinition
+metadata:
+  annotations:
+    controller-gen.kubebuilder.io/version: v0.5.0
+  creationTimestamp: null
+  name: oauth2clients.hydra.ory.sh
+spec:
+  group: hydra.ory.sh
+  names:
+    kind: OAuth2Client
+    listKind: OAuth2ClientList
+    plural: oauth2clients
+    singular: oauth2client
+  scope: Namespaced
+  versions:
+    - name: v1alpha1
+      schema:
+        openAPIV3Schema:
+          description: OAuth2Client is the Schema for the oauth2clients API
+          properties:
+            apiVersion:
+              description:
+                "APIVersion defines the versioned schema of this representation
+                of an object. Servers should convert recognized schemas to the
+                latest internal value, and may reject unrecognized values. More
+                info:
+                https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources"
+              type: string
+            kind:
+              description:
+                "Kind is a string value representing the REST resource this
+                object represents. Servers may infer this from the endpoint the
+                client submits requests to. Cannot be updated. In CamelCase.
+                More info:
+                https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds"
+              type: string
+            metadata:
+              type: object
+            spec:
+              description:
+                OAuth2ClientSpec defines the desired state of OAuth2Client
+              properties:
+                allowedCorsOrigins:
+                  description:
+                    AllowedCorsOrigins is an array of allowed CORS origins
+                  items:
+                    description:
+                      RedirectURI represents a redirect URI for the client
+                    pattern: \w+:/?/?[^\s]+
+                    type: string
+                  type: array
+                audience:
+                  description:
+                    Audience is a whitelist defining the audiences this client
+                    is allowed to request tokens for
+                  items:
+                    type: string
+                  type: array
+                clientName:
+                  description:
+                    ClientName is the human-readable string name of the client
+                    to be presented to the end-user during authorization.
+                  type: string
+                grantTypes:
+                  description:
+                    GrantTypes is an array of grant types the client is allowed
+                    to use.
+                  items:
+                    description: GrantType represents an OAuth 2.0 grant type
+                    enum:
+                      - client_credentials
+                      - authorization_code
+                      - implicit
+                      - refresh_token
+                    type: string
+                  maxItems: 4
+                  minItems: 1
+                  type: array
+                hydraAdmin:
+                  description:
+                    HydraAdmin is the optional configuration to use for managing
+                    this client
+                  properties:
+                    endpoint:
+                      description:
+                        Endpoint is the endpoint for the hydra instance on which
+                        to set up the client. This value will override the value
+                        provided to `--endpoint` (defaults to `"/clients"` in
+                        the application)
+                      pattern: (^$|^/.*)
+                      type: string
+                    forwardedProto:
+                      description:
+                        ForwardedProto overrides the `--forwarded-proto` flag.
+                        The value "off" will force this to be off even if
+                        `--forwarded-proto` is specified
+                      pattern: (^$|https?|off)
+                      type: string
+                    port:
+                      description:
+                        Port is the port for the hydra instance on which to set
+                        up the client. This value will override the value
+                        provided to `--hydra-port`
+                      maximum: 65535
+                      type: integer
+                    url:
+                      description:
+                        URL is the URL for the hydra instance on which to set up
+                        the client. This value will override the value provided
+                        to `--hydra-url`
+                      maxLength: 64
+                      pattern: (^$|^https?://.*)
+                      type: string
+                  type: object
+                metadata:
+                  description: Metadata is abritrary data
+                  nullable: true
+                  type: object
+                  x-kubernetes-preserve-unknown-fields: true
+                postLogoutRedirectUris:
+                  description:
+                    PostLogoutRedirectURIs is an array of the post logout
+                    redirect URIs allowed for the application
+                  items:
+                    description:
+                      RedirectURI represents a redirect URI for the client
+                    pattern: \w+:/?/?[^\s]+
+                    type: string
+                  type: array
+                redirectUris:
+                  description:
+                    RedirectURIs is an array of the redirect URIs allowed for
+                    the application
+                  items:
+                    description:
+                      RedirectURI represents a redirect URI for the client
+                    pattern: \w+:/?/?[^\s]+
+                    type: string
+                  type: array
+                responseTypes:
+                  description:
+                    ResponseTypes is an array of the OAuth 2.0 response type
+                    strings that the client can use at the authorization
+                    endpoint.
+                  items:
+                    description:
+                      ResponseType represents an OAuth 2.0 response type strings
+                    enum:
+                      - id_token
+                      - code
+                      - token
+                      - code token
+                      - code id_token
+                      - id_token token
+                      - code id_token token
+                    type: string
+                  maxItems: 3
+                  minItems: 1
+                  type: array
+                scope:
+                  description:
+                    Scope is a string containing a space-separated list of scope
+                    values (as described in Section 3.3 of OAuth 2.0 [RFC6749])
+                    that the client can use when requesting access tokens.
+                  pattern: ([a-zA-Z0-9\.\*]+\s?)+
+                  type: string
+                secretName:
+                  description:
+                    SecretName points to the K8s secret that contains this
+                    client's ID and password
+                  maxLength: 253
+                  minLength: 1
+                  pattern: '[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*'
+                  type: string
+                tokenEndpointAuthMethod:
+                  allOf:
+                    - enum:
+                        - client_secret_basic
+                        - client_secret_post
+                        - private_key_jwt
+                        - none
+                    - enum:
+                        - client_secret_basic
+                        - client_secret_post
+                        - private_key_jwt
+                        - none
+                  description:
+                    Indication which authentication method shoud be used for the
+                    token endpoint
+                  type: string
+              required:
+                - grantTypes
+                - scope
+                - secretName
+              type: object
+            status:
+              description:
+                OAuth2ClientStatus defines the observed state of OAuth2Client
+              properties:
+                conditions:
+                  items:
+                    description:
+                      OAuth2ClientCondition contains condition information for
+                      an OAuth2Client
+                    properties:
+                      status:
+                        enum:
+                          - "True"
+                          - "False"
+                          - Unknown
+                        type: string
+                      type:
+                        type: string
+                    required:
+                      - status
+                      - type
+                    type: object
+                  type: array
+                observedGeneration:
+                  description:
+                    ObservedGeneration represents the most recent generation
+                    observed by the daemon set controller.
+                  format: int64
+                  type: integer
+                reconciliationError:
+                  description:
+                    ReconciliationError represents an error that occurred during
+                    the reconciliation process
+                  properties:
+                    description:
+                      description:
+                        Description is the description of the reconciliation
+                        error
+                      type: string
+                    statusCode:
+                      description:
+                        Code is the status code of the reconciliation error
+                      type: string
+                  type: object
+              type: object
+          type: object
+      served: true
+      storage: true
+      subresources:
+        status: {}
+status:
+  acceptedNames:
+    kind: ""
+    plural: ""
+  conditions: []
+  storedVersions: []
diff --git a/charts/hydra-maester/templates/_helpers.tpl b/charts/hydra-maester/templates/_helpers.tpl
new file mode 100644
index 0000000..b607c67
--- /dev/null
+++ b/charts/hydra-maester/templates/_helpers.tpl
@@ -0,0 +1,59 @@
+{{/* vim: set filetype=mustache: */}}
+{{/*
+Expand the name of the chart.
+*/}}
+{{- define "hydra-maester.name" -}}
+{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}}
+{{- end -}}
+
+{{/*
+Create a default fully qualified app name.
+We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
+If release name contains chart name it will be used as a full name.
+*/}}
+{{- define "hydra-maester.fullname" -}}
+{{- if .Values.fullnameOverride -}}
+{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}}
+{{- else -}}
+{{- $name := default .Chart.Name .Values.nameOverride -}}
+{{- if contains $name .Release.Name -}}
+{{- .Release.Name | trunc 63 | trimSuffix "-" -}}
+{{- else -}}
+{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}}
+{{- end -}}
+{{- end -}}
+{{- end -}}
+
+{{/*
+Create chart name and version as used by the chart label.
+*/}}
+{{- define "hydra-maester.chart" -}}
+{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}}
+{{- end -}}
+
+{{/*
+Common labels
+*/}}
+{{- define "hydra-maester.labels" -}}
+app.kubernetes.io/name: {{ include "hydra-maester.name" . }}
+helm.sh/chart: {{ include "hydra-maester.chart" . }}
+app.kubernetes.io/instance: {{ .Release.Name }}
+{{- if .Chart.AppVersion }}
+app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
+{{- end }}
+app.kubernetes.io/managed-by: {{ .Release.Service }}
+{{- end -}}
+
+
+{{/*
+Get Hydra admin service name
+*/}}
+{{- define "hydra-maester.adminService" -}}
+{{- if .Values.hydraFullnameOverride -}}
+{{- printf "%s-admin"  .Values.hydraFullnameOverride -}}
+{{- else if contains "hydra" .Release.Name -}}
+{{- printf "%s-admin" .Release.Name -}}
+{{- else -}}
+{{- printf "%s-%s-admin" .Release.Name "hydra" -}}
+{{- end -}}
+{{- end -}}
diff --git a/charts/hydra-maester/templates/deployment.yaml b/charts/hydra-maester/templates/deployment.yaml
new file mode 100644
index 0000000..ed9c3b8
--- /dev/null
+++ b/charts/hydra-maester/templates/deployment.yaml
@@ -0,0 +1,97 @@
+---
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  name: {{ include "hydra-maester.fullname" . }}
+  labels:
+    {{- include "hydra-maester.labels" . | nindent 4 }}
+    {{- with .Values.deployment.extraLabels }}
+      {{- toYaml . | nindent 4 }}
+    {{- end }}
+spec:
+  replicas: {{ .Values.replicaCount }}
+  revisionHistoryLimit: 10
+  selector:
+    matchLabels:
+      control-plane: controller-manager
+      app.kubernetes.io/name: {{ include "hydra-maester.fullname" . }}
+      app.kubernetes.io/instance: {{ .Release.Name }}
+  template:
+    metadata:
+      labels:
+        control-plane: controller-manager
+        app.kubernetes.io/name: {{ include "hydra-maester.fullname" . }}
+        app.kubernetes.io/instance: {{ .Release.Name }}
+        {{- with .Values.deployment.extraLabels }}
+          {{- toYaml . | nindent 8 }}
+        {{- end }}
+        {{- with .Values.deployment.podMetadata.labels }}
+          {{- toYaml . | nindent 8 }}
+        {{- end }}
+      annotations:
+        {{- with .Values.deployment.extraAnnotations }}
+          {{- toYaml . | nindent 8 }}
+        {{- end }}
+        {{- with .Values.deployment.podMetadata.annotations }}
+          {{- toYaml . | nindent 8 }}
+        {{- end }}
+    spec:
+      {{- with .Values.imagePullSecrets }}
+      imagePullSecrets:
+        {{- toYaml . | nindent 8 }}
+      {{- end }}
+      containers:
+        - name: {{ .Chart.Name }}
+          image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
+          imagePullPolicy: {{ .Values.image.pullPolicy }}
+          command:
+            - /manager
+          args:
+            - --metrics-addr=127.0.0.1:8080
+            - --hydra-url=http://{{ .Values.adminService.name | default ( include "hydra-maester.adminService" . ) }}
+            - --hydra-port={{ .Values.adminService.port | default 4445 }}
+            {{- with .Values.adminService.endpoint }}
+            - --endpoint={{ . }}
+            {{- end }}
+            {{- if .Values.forwardedProto }}
+            - --forwarded-proto={{ .Values.forwardedProto }}
+            {{- end }}
+            {{- if .Values.singleNamespaceMode }}
+            - --namespace={{ .Release.Namespace }}
+            {{- end }}
+            {{- if .Values.deployment.args.syncPeriod }}
+            - --sync-period={{ .Values.deployment.args.syncPeriod }}
+            {{- end }}
+          resources:
+            {{- toYaml .Values.deployment.resources | nindent 12 }}
+          terminationMessagePath: /dev/termination-log
+          terminationMessagePolicy: File
+          {{- if .Values.deployment.securityContext }}
+          securityContext:
+            {{- toYaml .Values.deployment.securityContext | nindent 12 }}
+          {{- end }}
+      serviceAccountName: {{ include "hydra-maester.fullname" . }}-account
+      automountServiceAccountToken: {{ .Values.deployment.automountServiceAccountToken }}
+      {{- if .Values.priorityClassName }}
+      priorityClassName: {{ .Values.priorityClassName }}
+      {{- end }}
+      nodeSelector:
+      {{- with .Values.deployment.nodeSelector }}
+        {{- toYaml . | nindent 8 }}
+      {{- end }}
+    {{- with .Values.affinity }}
+      affinity:
+        {{- toYaml . | nindent 8 }}
+    {{- end }}
+    {{- with .Values.deployment.tolerations }}
+      tolerations:
+        {{- toYaml . | nindent 8 }}
+    {{- end }}
+    {{- with .Values.deployment.topologySpreadConstraints }}
+      topologySpreadConstraints:
+        {{- toYaml . | nindent 8 }}
+    {{- end }}
+    {{- with .Values.deployment.dnsConfig }}
+      dnsConfig:
+        {{- toYaml . | nindent 8 }}
+    {{- end }}
diff --git a/charts/hydra-maester/templates/pdb.yaml b/charts/hydra-maester/templates/pdb.yaml
new file mode 100644
index 0000000..1be53ba
--- /dev/null
+++ b/charts/hydra-maester/templates/pdb.yaml
@@ -0,0 +1,14 @@
+{{- if .Values.pdb.enabled -}}
+---
+apiVersion: policy/v1
+kind: PodDisruptionBudget
+metadata:
+  name: {{ include "hydra-maester.fullname" . }}
+spec:
+  selector:
+    matchLabels:
+      control-plane: controller-manager
+      app.kubernetes.io/name: {{ include "hydra-maester.fullname" . }}
+      app.kubernetes.io/instance: {{ .Release.Name }}
+  {{ toYaml .Values.pdb.spec }}
+{{- end -}}
\ No newline at end of file
diff --git a/charts/hydra-maester/templates/rbac.yaml b/charts/hydra-maester/templates/rbac.yaml
new file mode 100644
index 0000000..e67cc62
--- /dev/null
+++ b/charts/hydra-maester/templates/rbac.yaml
@@ -0,0 +1,95 @@
+---
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+  name: {{ include "hydra-maester.fullname" . }}-account
+  namespace:  {{ .Release.Namespace }}
+  labels:
+    {{- include "hydra-maester.labels" . | nindent 4 }}
+  {{- with .Values.deployment.serviceAccount.annotations }}
+  annotations:
+    {{- toYaml . | nindent 4 }}
+  {{- end }}
+{{- if not .Values.singleNamespaceMode }}
+---
+kind: ClusterRole
+apiVersion: rbac.authorization.k8s.io/v1
+metadata:
+  name: {{ include "hydra-maester.fullname" . }}-role
+rules:
+  - apiGroups: ["hydra.ory.sh"]
+    resources: ["oauth2clients", "oauth2clients/status"]
+    verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
+  - apiGroups: [""]
+    resources: ["secrets"]
+    verbs: ["list", "watch", "create"]
+---
+kind: ClusterRoleBinding
+apiVersion: rbac.authorization.k8s.io/v1
+metadata:
+  name: {{ include "hydra-maester.fullname" . }}-role-binding
+subjects:
+  - kind: ServiceAccount
+    name: {{ include "hydra-maester.fullname" . }}-account # Service account assigned to the controller pod.
+    namespace:  {{ .Release.Namespace }}
+roleRef:
+  apiGroup: rbac.authorization.k8s.io
+  kind: ClusterRole
+  name: {{ include "hydra-maester.fullname" . }}-role
+{{- end }}
+---
+kind: Role
+apiVersion: rbac.authorization.k8s.io/v1
+metadata:
+  name: {{ include "hydra-maester.fullname" . }}-role
+  namespace:  {{ .Release.Namespace }}
+rules:
+  - apiGroups: [""]
+    resources: ["secrets"]
+    verbs: ["get", "list", "watch", "create"]
+  - apiGroups: ["hydra.ory.sh"]
+    resources: ["oauth2clients", "oauth2clients/status"]
+    verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
+---
+kind: RoleBinding
+apiVersion: rbac.authorization.k8s.io/v1
+metadata:
+  name: {{ include "hydra-maester.fullname" . }}-role-binding
+  namespace:  {{ .Release.Namespace }}
+subjects:
+  - kind: ServiceAccount
+    name: {{ include "hydra-maester.fullname" . }}-account # Service account assigned to the controller pod.
+    namespace:  {{ .Release.Namespace }}
+roleRef:
+  apiGroup: rbac.authorization.k8s.io
+  kind: Role
+  name: {{ include "hydra-maester.fullname" . }}-role
+
+{{- $name := include "hydra-maester.fullname" . -}}
+{{- $namespace := .Release.Namespace -}}
+{{- range .Values.enabledNamespaces }}
+---
+kind: Role
+apiVersion: rbac.authorization.k8s.io/v1
+metadata:
+  name: {{ $name }}-role
+  namespace:  {{ . }}
+rules:
+  - apiGroups: [""]
+    resources: ["secrets"]
+    verbs: ["get", "list", "watch", "create", "update"]
+---
+kind: RoleBinding
+apiVersion: rbac.authorization.k8s.io/v1
+metadata:
+  name: {{ $name }}-role-binding
+  namespace:  {{ . }}
+subjects:
+  - kind: ServiceAccount
+    name: {{ $name }}-account # Service account assigned to the controller pod.
+    namespace:  {{ $namespace }}
+roleRef:
+  apiGroup: rbac.authorization.k8s.io
+  kind: Role
+  name: {{ $name }}-role
+{{- end }}
diff --git a/charts/hydra-maester/values.yaml b/charts/hydra-maester/values.yaml
new file mode 100644
index 0000000..caa6a90
--- /dev/null
+++ b/charts/hydra-maester/values.yaml
@@ -0,0 +1,122 @@
+# -- Number of replicas in deployment
+replicaCount: 1
+
+# -- The Controller have CREATE and READ access to all Secrets in the namespaces listed below.
+enabledNamespaces: []
+
+# -- Single namespace mode. If enabled the controller will watch for resources only from namespace it is deployed in, ignoring others
+singleNamespaceMode: false
+
+image:
+  # -- Ory Hydra-maester image
+  repository: oryd/hydra-maester
+  # -- Ory Hydra-maester version
+  tag: v0.0.27
+  # -- Image pull policy
+  pullPolicy: IfNotPresent
+
+# -- Image pull secrets
+imagePullSecrets: []
+
+# -- Pod priority
+## https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/
+priorityClassName: ""
+
+# -- Connection data to admin service of Hydra
+adminService:
+  # -- Service name
+  name:
+  # -- Service port
+  port:
+  # -- Set the clients endpoint, should be `/clients` for Hydra 1.x and
+  # `/admin/clients` for Hydra 2.x
+  endpoint: /admin/clients
+
+forwardedProto:
+
+deployment:
+  resources:
+    {}
+    #  We usually recommend not to specify default resources and to leave this as a conscious
+    #  choice for the user. This also increases chances charts run on environments with little
+    #  resources, such as Minikube. If you do want to specify resources, uncomment the following
+    #  lines, adjust them as necessary, and remove the curly braces after 'resources:'.
+    # limits:
+    #   cpu: 100m
+    #   memory: 30Mi
+    # requests:
+    #   cpu: 100m
+    #   memory: 20Mi
+
+  # -- Default security context
+  securityContext:
+    capabilities:
+      drop:
+        - ALL
+    seccompProfile:
+      type: RuntimeDefault
+    readOnlyRootFilesystem: true
+    runAsNonRoot: true
+    runAsUser: 1000
+    allowPrivilegeEscalation: false
+    privileged: false
+
+  # -- Node labels for pod assignment.
+  nodeSelector: {}
+  # If you do want to specify node labels, uncomment the following
+  # lines, adjust them as necessary, and remove the curly braces after 'annotations:'.
+  #   foo: bar
+
+  # -- Configure node tolerations.
+  tolerations: []
+  # -- Deployment level extra annotations
+  extraAnnotations: {}
+  # -- Deployment level extra labels
+  extraLabels: {}
+
+  # -- Configure pod topologySpreadConstraints.
+  topologySpreadConstraints: []
+  # - maxSkew: 1
+  #   topologyKey: topology.kubernetes.io/zone
+  #   whenUnsatisfiable: DoNotSchedule
+  #   labelSelector:
+  #     matchLabels:
+  #       app.kubernetes.io/name: hydra
+  #       app.kubernetes.io/instance: hydra
+
+  # -- Configure pod dnsConfig.
+  dnsConfig: {}
+  #   options:
+  #     - name: "ndots"
+  #       value: "1"
+
+  # -- Specify pod metadata, this metadata is added directly to the pod, and not higher objects
+  podMetadata:
+    # -- Extra pod level labels
+    labels: {}
+    # -- Extra pod level annotations
+    annotations: {}
+
+  # https://github.com/kubernetes/kubernetes/issues/57601
+  # -- This applications connects to the k8s API and requires the permissions
+  automountServiceAccountToken: true
+
+  # -- Arguments to be passed to the program
+  args:
+    # -- The minimum frequency at which watched resources are reconciled
+    syncPeriod: ""
+    # syncPeriod: 10h
+
+  # -- Configure service account
+  serviceAccount:
+    # -- Annotations to add to the service account
+    annotations: {}
+
+# -- Configure node affinity
+affinity: {}
+
+# -- PodDistributionBudget configuration
+pdb:
+  enabled: false
+  spec:
+    minAvailable: 1
diff --git a/core/installer/app.go b/core/installer/app.go
index fa2e270..ac83a66 100644
--- a/core/installer/app.go
+++ b/core/installer/app.go
@@ -55,6 +55,7 @@
 	"values-tmpl/private-network.cue",
 	"values-tmpl/resource-renderer-controller.cue",
 	"values-tmpl/welcome.cue",
+	"values-tmpl/hydra-maester.cue",
 }
 
 const cueBaseConfigImports = `
diff --git a/core/installer/bootstrapper.go b/core/installer/bootstrapper.go
index c5de23d..e496709 100644
--- a/core/installer/bootstrapper.go
+++ b/core/installer/bootstrapper.go
@@ -97,6 +97,10 @@
 	if err := b.installEnvManager(ss, repoIO, nsGen, b.ns, env); err != nil {
 		return err
 	}
+	fmt.Println("Installing Ory Hydra Maester")
+	if err := b.installOryHydraMaester(ss, repoIO, nsGen, b.ns, env); err != nil {
+		return err
+	}
 	fmt.Println("Environment ready to use")
 	return nil
 }
@@ -521,6 +525,36 @@
 	return repo.InstallApp(app, filepath.Join("/infrastructure", app.Name()), derived.Values, derived)
 }
 
+func (b Bootstrapper) installOryHydraMaester(ss *soft.Client, repo RepoIO, nsGen NamespaceGenerator, nsCreator NamespaceCreator, env EnvConfig) error {
+	appRepo := NewInMemoryAppRepository(CreateAllApps())
+	app, err := appRepo.Find("hydra-maester")
+	if err != nil {
+		return err
+	}
+	namespaces := make([]string, len(app.Namespaces()))
+	for i, n := range app.Namespaces() {
+		namespaces[i], err = nsGen.Generate(n)
+		if err != nil {
+			return err
+		}
+	}
+	for _, n := range namespaces {
+		if err := nsCreator.Create(n); err != nil {
+			return err
+		}
+	}
+	derived := Derived{
+		Global: Values{
+			PCloudEnvName: env.Name,
+		},
+		Values: map[string]any{},
+	}
+	if len(namespaces) > 0 {
+		derived.Release.Namespace = namespaces[0]
+	}
+	return repo.InstallApp(app, filepath.Join("/infrastructure", app.Name()), derived.Values, derived)
+}
+
 func (b Bootstrapper) installDNSZoneManager(ss *soft.Client, repo RepoIO, nsGen NamespaceGenerator, nsCreator NamespaceCreator, env EnvConfig) error {
 	const (
 		volumeClaimName = "dns-zone-configs"
diff --git a/core/installer/values-tmpl/core-auth.cue b/core/installer/values-tmpl/core-auth.cue
index 0d99ffd..99840ab 100644
--- a/core/installer/values-tmpl/core-auth.cue
+++ b/core/installer/values-tmpl/core-auth.cue
@@ -48,12 +48,6 @@
 		tag: "v2.2.0-distroless"
 		pullPolicy: "IfNotPresent"
 	}
-	"hydra-maester": {
-		repository: "giolekva"
-		name: "ory-hydra-maester"
-		tag: "latest"
-		pullPolicy: "Always"
-	}
 	ui: {
 		repository: "giolekva"
 		name: "auth-ui"
@@ -378,18 +372,7 @@
 					enabled: true
 				}
 				maester: {
-					enabled: true
-				}
-				"hydra-maester": {
-					adminService: {
-						name: "hydra-admin"
-						port: 80
-					}
-					image: {
-						repository: images["hydra-maester"].fullName
-						tag: images["hydra-maester"].tag
-						pullPolicy: images["hydra-maester"].pullPolicy
-					}
+					enabled: false
 				}
 				hydra: {
 					automigration: {
diff --git a/core/installer/values-tmpl/hydra-maester.cue b/core/installer/values-tmpl/hydra-maester.cue
new file mode 100644
index 0000000..4f76f84
--- /dev/null
+++ b/core/installer/values-tmpl/hydra-maester.cue
@@ -0,0 +1,42 @@
+input: {}
+
+name: "hydra-maester"
+namespace: "auth"
+
+images: {
+	hydraMaester: {
+		repository: "giolekva"
+		name: "ory-hydra-maester"
+		tag: "latest"
+		pullPolicy: "Always"
+	}
+}
+
+charts: {
+	hydraMaester: {
+		chart: "charts/hydra-maester"
+		sourceRef: {
+			kind: "GitRepository"
+			name: "pcloud"
+			namespace: global.pcloudEnvName
+		}
+	}
+}
+
+helm: {
+	"hydra-maester": {
+		chart: charts.hydraMaester
+		values: {
+			adminService: {
+				name: "foo.bar.svc.cluster.local"
+				port: 80
+				scheme: "http"
+			}
+			image: {
+				repository: images.hydraMaester.fullName
+				tag: images.hydraMaester.tag
+				pullPolicy: images.hydraMaester.pullPolicy
+			}
+		}
+	}
+}