charts: headscale config renderer
diff --git a/charts/headscale/templates/config.yaml b/charts/headscale/templates/config.yaml
index 5abe533..3604698 100644
--- a/charts/headscale/templates/config.yaml
+++ b/charts/headscale/templates/config.yaml
@@ -1,295 +1,302 @@
-{{- $secret := include "clientSecret" . -}}
-apiVersion: v1
-kind: ConfigMap
+apiVersion: dodo.cloud.dodo.cloud/v1
+kind: ResourceRenderer
 metadata:
-  name: config
+  name: config-renderer
   namespace: {{ .Release.Namespace }}
-data:
-  config.yaml: |
-    # headscale will look for a configuration file named `config.yaml` (or `config.json`) in the following order:
-    #
-    # - `/etc/headscale`
-    # - `~/.headscale`
-    # - current working directory
-
-    # The url clients will connect to.
-    # Typically this will be a domain like:
-    #
-    # https://myheadscale.example.com:443
-    #
-    server_url: https://{{ .Values.domain }}
-
-    # Address to listen to / bind to on the server
-    #
-    # For production:
-    listen_addr: 0.0.0.0:8080
-    # listen_addr: 127.0.0.1:8080
-
-    # Address to listen to /metrics, you may want
-    # to keep this endpoint private to your internal
-    # network
-    #
-    metrics_listen_addr: 0.0.0.0:9090
-    # metrics_listen_addr: 127.0.0.1:9090
-
-    # Address to listen for gRPC.
-    # gRPC is used for controlling a headscale server
-    # remotely with the CLI
-    # Note: Remote access _only_ works if you have
-    # valid certificates.
-    #
-    # For production:
-    grpc_listen_addr: 0.0.0.0:50443
-    # grpc_listen_addr: 127.0.0.1:50443
-
-    # Allow the gRPC admin interface to run in INSECURE
-    # mode. This is not recommended as the traffic will
-    # be unencrypted. Only enable if you know what you
-    # are doing.
-    grpc_allow_insecure: false
-
-    # Private key used to encrypt the traffic between headscale
-    # and Tailscale clients.
-    # The private key file will be autogenerated if it's missing.
-    #
-    # For production:
-    # /var/lib/headscale/private.key
-    private_key_path: /headscale/data/private.key
-
-    # The Noise section includes specific configuration for the
-    # TS2021 Noise protocol
-    noise:
-      # The Noise private key is used to encrypt the
-      # traffic between headscale and Tailscale clients when
-      # using the new Noise-based protocol. It must be different
-      # from the legacy private key.
-      #
-      # For production:
-      # private_key_path: /var/lib/headscale/noise_private.key
-      private_key_path: /headscale/data/noise_private.key
-
-    # List of IP prefixes to allocate tailaddresses from.
-    # Each prefix consists of either an IPv4 or IPv6 address,
-    # and the associated prefix length, delimited by a slash.
-    ip_prefixes:
-      # - fd7a:115c:a1e0::/48
-      - 100.64.0.0/10
-
-    # DERP is a relay system that Tailscale uses when a direct
-    # connection cannot be established.
-    # https://tailscale.com/blog/how-tailscale-works/#encrypted-tcp-relays-derp
-    #
-    # headscale needs a list of DERP servers that can be presented
-    # to the clients.
-    derp:
-      server:
-        # If enabled, runs the embedded DERP server and merges it into the rest of the DERP config
-        # The Headscale server_url defined above MUST be using https, DERP requires TLS to be in place
-        enabled: false
-
-        # Region ID to use for the embedded DERP server.
-        # The local DERP prevails if the region ID collides with other region ID coming from
-        # the regular DERP config.
-        region_id: 999
-
-        # Region code and name are displayed in the Tailscale UI to identify a DERP region
-        region_code: "headscale"
-        region_name: "Headscale Embedded DERP"
-
-        # Listens over UDP at the configured address for STUN connections - to help with NAT traversal.
-        # When the embedded DERP server is enabled stun_listen_addr MUST be defined.
+spec:
+  secretName: {{ .Values.oauth2.secretName }}
+  resourceTemplate: |
+    apiVersion: v1
+    kind: ConfigMap
+    metadata:
+      name: config
+      namespace: {{ .Release.Namespace }}
+    data:
+      config.yaml: |
+        # headscale will look for a configuration file named `config.yaml` (or `config.json`) in the following order:
         #
-        # For more details on how this works, check this great article: https://tailscale.com/blog/how-tailscale-works/
-        stun_listen_addr: "0.0.0.0:3478"
+        # - `/etc/headscale`
+        # - `~/.headscale`
+        # - current working directory
 
-      # List of externally available DERP maps encoded in JSON
-      urls:
-        - https://controlplane.tailscale.com/derpmap/default
+        # The url clients will connect to.
+        # Typically this will be a domain like:
+        #
+        # https://myheadscale.example.com:443
+        #
+        server_url: https://{{ .Values.domain }}
 
-      # Locally available DERP map files encoded in YAML
-      #
-      # This option is mostly interesting for people hosting
-      # their own DERP servers:
-      # https://tailscale.com/kb/1118/custom-derp-servers/
-      #
-      # paths:
-      #   - /etc/headscale/derp-example.yaml
-      paths: []
+        # Address to listen to / bind to on the server
+        #
+        # For production:
+        listen_addr: 0.0.0.0:8080
+        # listen_addr: 127.0.0.1:8080
 
-      # If enabled, a worker will be set up to periodically
-      # refresh the given sources and update the derpmap
-      # will be set up.
-      auto_update_enabled: true
+        # Address to listen to /metrics, you may want
+        # to keep this endpoint private to your internal
+        # network
+        #
+        metrics_listen_addr: 0.0.0.0:9090
+        # metrics_listen_addr: 127.0.0.1:9090
 
-      # How often should we check for DERP updates?
-      update_frequency: 24h
+        # Address to listen for gRPC.
+        # gRPC is used for controlling a headscale server
+        # remotely with the CLI
+        # Note: Remote access _only_ works if you have
+        # valid certificates.
+        #
+        # For production:
+        grpc_listen_addr: 0.0.0.0:50443
+        # grpc_listen_addr: 127.0.0.1:50443
 
-    # Disables the automatic check for headscale updates on startup
-    disable_check_updates: true
+        # Allow the gRPC admin interface to run in INSECURE
+        # mode. This is not recommended as the traffic will
+        # be unencrypted. Only enable if you know what you
+        # are doing.
+        grpc_allow_insecure: false
 
-    # Time before an inactive ephemeral node is deleted?
-    ephemeral_node_inactivity_timeout: 30m
+        # Private key used to encrypt the traffic between headscale
+        # and Tailscale clients.
+        # The private key file will be autogenerated if it's missing.
+        #
+        # For production:
+        # /var/lib/headscale/private.key
+        private_key_path: /headscale/data/private.key
 
-    # Period to check for node updates within the tailnet. A value too low will severely affect
-    # CPU consumption of Headscale. A value too high (over 60s) will cause problems
-    # for the nodes, as they won't get updates or keep alive messages frequently enough.
-    # In case of doubts, do not touch the default 10s.
-    node_update_check_interval: 10s
+        # The Noise section includes specific configuration for the
+        # TS2021 Noise protocol
+        noise:
+          # The Noise private key is used to encrypt the
+          # traffic between headscale and Tailscale clients when
+          # using the new Noise-based protocol. It must be different
+          # from the legacy private key.
+          #
+          # For production:
+          # private_key_path: /var/lib/headscale/noise_private.key
+          private_key_path: /headscale/data/noise_private.key
 
-    # SQLite config
-    db_type: sqlite3
+        # List of IP prefixes to allocate tailaddresses from.
+        # Each prefix consists of either an IPv4 or IPv6 address,
+        # and the associated prefix length, delimited by a slash.
+        ip_prefixes:
+          # - fd7a:115c:a1e0::/48
+          - 100.64.0.0/10
 
-    # For production:
-    # db_path: /var/lib/headscale/db.sqlite
-    db_path: /headscale/data/db.sqlite
+        # DERP is a relay system that Tailscale uses when a direct
+        # connection cannot be established.
+        # https://tailscale.com/blog/how-tailscale-works/#encrypted-tcp-relays-derp
+        #
+        # headscale needs a list of DERP servers that can be presented
+        # to the clients.
+        derp:
+          server:
+            # If enabled, runs the embedded DERP server and merges it into the rest of the DERP config
+            # The Headscale server_url defined above MUST be using https, DERP requires TLS to be in place
+            enabled: false
 
-    # # Postgres config
-    # If using a Unix socket to connect to Postgres, set the socket path in the 'host' field and leave 'port' blank.
-    # db_type: postgres
-    # db_host: localhost
-    # db_port: 5432
-    # db_name: headscale
-    # db_user: foo
-    # db_pass: bar
+            # Region ID to use for the embedded DERP server.
+            # The local DERP prevails if the region ID collides with other region ID coming from
+            # the regular DERP config.
+            region_id: 999
 
-    # If other 'sslmode' is required instead of 'require(true)' and 'disabled(false)', set the 'sslmode' you need
-    # in the 'db_ssl' field. Refers to https://www.postgresql.org/docs/current/libpq-ssl.html Table 34.1.
-    # db_ssl: false
+            # Region code and name are displayed in the Tailscale UI to identify a DERP region
+            region_code: "headscale"
+            region_name: "Headscale Embedded DERP"
 
-    ### TLS configuration
-    #
-    ## Let's encrypt / ACME
-    #
-    # headscale supports automatically requesting and setting up
-    # TLS for a domain with Let's Encrypt.
-    #
-    # URL to ACME directory
-    acme_url: https://acme-v02.api.letsencrypt.org/directory
+            # Listens over UDP at the configured address for STUN connections - to help with NAT traversal.
+            # When the embedded DERP server is enabled stun_listen_addr MUST be defined.
+            #
+            # For more details on how this works, check this great article: https://tailscale.com/blog/how-tailscale-works/
+            stun_listen_addr: "0.0.0.0:3478"
 
-    # Email to register with ACME provider
-    acme_email: ""
+          # List of externally available DERP maps encoded in JSON
+          urls:
+            - https://controlplane.tailscale.com/derpmap/default
 
-    # Domain name to request a TLS certificate for:
-    tls_letsencrypt_hostname: ""
+          # Locally available DERP map files encoded in YAML
+          #
+          # This option is mostly interesting for people hosting
+          # their own DERP servers:
+          # https://tailscale.com/kb/1118/custom-derp-servers/
+          #
+          # paths:
+          #   - /etc/headscale/derp-example.yaml
+          paths: []
 
-    # Path to store certificates and metadata needed by
-    # letsencrypt
-    # For production:
-    # tls_letsencrypt_cache_dir: /var/lib/headscale/cache
-    tls_letsencrypt_cache_dir: ./cache
+          # If enabled, a worker will be set up to periodically
+          # refresh the given sources and update the derpmap
+          # will be set up.
+          auto_update_enabled: true
 
-    # Type of ACME challenge to use, currently supported types:
-    # HTTP-01 or TLS-ALPN-01
-    # See [docs/tls.md](docs/tls.md) for more information
-    tls_letsencrypt_challenge_type: HTTP-01
-    # When HTTP-01 challenge is chosen, letsencrypt must set up a
-    # verification endpoint, and it will be listening on:
-    # :http = port 80
-    tls_letsencrypt_listen: ":http"
+          # How often should we check for DERP updates?
+          update_frequency: 24h
 
-    ## Use already defined certificates:
-    tls_cert_path: ""
-    tls_key_path: ""
+        # Disables the automatic check for headscale updates on startup
+        disable_check_updates: true
 
-    log:
-      # Output formatting for logs: text or json
-      format: text
-      level: info
+        # Time before an inactive ephemeral node is deleted?
+        ephemeral_node_inactivity_timeout: 30m
 
-    # Path to a file containg ACL policies.
-    # ACLs can be defined as YAML or HUJSON.
-    # https://tailscale.com/kb/1018/acls/
-    acl_policy_path: ""
+        # Period to check for node updates within the tailnet. A value too low will severely affect
+        # CPU consumption of Headscale. A value too high (over 60s) will cause problems
+        # for the nodes, as they won't get updates or keep alive messages frequently enough.
+        # In case of doubts, do not touch the default 10s.
+        node_update_check_interval: 10s
 
-    ## DNS
-    #
-    # headscale supports Tailscale's DNS configuration and MagicDNS.
-    # Please have a look to their KB to better understand the concepts:
-    #
-    # - https://tailscale.com/kb/1054/dns/
-    # - https://tailscale.com/kb/1081/magicdns/
-    # - https://tailscale.com/blog/2021-09-private-dns-with-magicdns/
-    #
-    dns_config:
-      # Whether to prefer using Headscale provided DNS or use local.
-      override_local_dns: true
+        # SQLite config
+        db_type: sqlite3
 
-      # List of DNS servers to expose to clients.
-      nameservers:
-        - 8.8.8.8
-        - 1.1.1.1
+        # For production:
+        # db_path: /var/lib/headscale/db.sqlite
+        db_path: /headscale/data/db.sqlite
 
-      # NextDNS (see https://tailscale.com/kb/1218/nextdns/).
-      # "abc123" is example NextDNS ID, replace with yours.
-      #
-      # With metadata sharing:
-      # nameservers:
-      #   - https://dns.nextdns.io/abc123
-      #
-      # Without metadata sharing:
-      # nameservers:
-      #   - 2a07:a8c0::ab:c123
-      #   - 2a07:a8c1::ab:c123
+        # # Postgres config
+        # If using a Unix socket to connect to Postgres, set the socket path in the 'host' field and leave 'port' blank.
+        # db_type: postgres
+        # db_host: localhost
+        # db_port: 5432
+        # db_name: headscale
+        # db_user: foo
+        # db_pass: bar
 
-      # Split DNS (see https://tailscale.com/kb/1054/dns/),
-      # list of search domains and the DNS to query for each one.
-      #
-      # restricted_nameservers:
-      #   foo.bar.com:
-      #     - 1.1.1.1
-      #   darp.headscale.net:
-      #     - 1.1.1.1
-      #     - 8.8.8.8
+        # If other 'sslmode' is required instead of 'require(true)' and 'disabled(false)', set the 'sslmode' you need
+        # in the 'db_ssl' field. Refers to https://www.postgresql.org/docs/current/libpq-ssl.html Table 34.1.
+        # db_ssl: false
 
-      # Search domains to inject.
-      domains: []
+        ### TLS configuration
+        #
+        ## Let's encrypt / ACME
+        #
+        # headscale supports automatically requesting and setting up
+        # TLS for a domain with Let's Encrypt.
+        #
+        # URL to ACME directory
+        acme_url: https://acme-v02.api.letsencrypt.org/directory
 
-      # Whether to use [MagicDNS](https://tailscale.com/kb/1081/magicdns/).
-      # Only works if there is at least a nameserver defined.
-      magic_dns: true
+        # Email to register with ACME provider
+        acme_email: ""
 
-      # Defines the base domain to create the hostnames for MagicDNS.
-      # `base_domain` must be a FQDNs, without the trailing dot.
-      # The FQDN of the hosts will be
-      # `hostname.namespace.base_domain` (e.g., _myhost.mynamespace.example.com_).
-      base_domain: {{ .Values.internalBaseDomain }}
+        # Domain name to request a TLS certificate for:
+        tls_letsencrypt_hostname: ""
 
-    # Unix socket used for the CLI to connect without authentication
-    # Note: for production you will want to set this to something like:
-    # unix_socket: /var/run/headscale.sock
-    unix_socket: ./headscale.sock
-    unix_socket_permission: "0770"
-    #
-    # headscale supports experimental OpenID connect support,
-    # it is still being tested and might have some bugs, please
-    # help us test it.
-    # OpenID Connect
-    oidc:
-      only_start_if_oidc_is_available: false
-      issuer: {{ .Values.oauth2.hydraPublic }}
-      client_id: {{ .Values.oauth2.clientId }}
-      client_secret: {{ $secret }}
-      scope: ["openid", "profile", "email"]
-      extra_params:
-        domain_hint: lekva.me
-      allowed_domains:
-        - lekva.me
-      # allowed_groups:
-      #   - /headscale
-      # allowed_users:
-      #   - alice@example.com
-      strip_email_domain: true
+        # Path to store certificates and metadata needed by
+        # letsencrypt
+        # For production:
+        # tls_letsencrypt_cache_dir: /var/lib/headscale/cache
+        tls_letsencrypt_cache_dir: ./cache
 
-    # Logtail configuration
-    # Logtail is Tailscales logging and auditing infrastructure, it allows the control panel
-    # to instruct tailscale nodes to log their activity to a remote server.
-    logtail:
-      # Enable logtail for this headscales clients.
-      # As there is currently no support for overriding the log server in headscale, this is
-      # disabled by default. Enabling this will make your clients send logs to Tailscale Inc.
-      enabled: false
+        # Type of ACME challenge to use, currently supported types:
+        # HTTP-01 or TLS-ALPN-01
+        # See [docs/tls.md](docs/tls.md) for more information
+        tls_letsencrypt_challenge_type: HTTP-01
+        # When HTTP-01 challenge is chosen, letsencrypt must set up a
+        # verification endpoint, and it will be listening on:
+        # :http = port 80
+        tls_letsencrypt_listen: ":http"
 
-    # Enabling this option makes devices prefer a random port for WireGuard traffic over the
-    # default static port 41641. This option is intended as a workaround for some buggy
-    # firewall devices. See https://tailscale.com/kb/1181/firewalls/ for more information.
-    randomize_client_port: true
+        ## Use already defined certificates:
+        tls_cert_path: ""
+        tls_key_path: ""
+
+        log:
+          # Output formatting for logs: text or json
+          format: text
+          level: info
+
+        # Path to a file containg ACL policies.
+        # ACLs can be defined as YAML or HUJSON.
+        # https://tailscale.com/kb/1018/acls/
+        acl_policy_path: ""
+
+        ## DNS
+        #
+        # headscale supports Tailscale's DNS configuration and MagicDNS.
+        # Please have a look to their KB to better understand the concepts:
+        #
+        # - https://tailscale.com/kb/1054/dns/
+        # - https://tailscale.com/kb/1081/magicdns/
+        # - https://tailscale.com/blog/2021-09-private-dns-with-magicdns/
+        #
+        dns_config:
+          # Whether to prefer using Headscale provided DNS or use local.
+          override_local_dns: true
+
+          # List of DNS servers to expose to clients.
+          nameservers:
+            - 8.8.8.8
+            - 1.1.1.1
+
+          # NextDNS (see https://tailscale.com/kb/1218/nextdns/).
+          # "abc123" is example NextDNS ID, replace with yours.
+          #
+          # With metadata sharing:
+          # nameservers:
+          #   - https://dns.nextdns.io/abc123
+          #
+          # Without metadata sharing:
+          # nameservers:
+          #   - 2a07:a8c0::ab:c123
+          #   - 2a07:a8c1::ab:c123
+
+          # Split DNS (see https://tailscale.com/kb/1054/dns/),
+          # list of search domains and the DNS to query for each one.
+          #
+          # restricted_nameservers:
+          #   foo.bar.com:
+          #     - 1.1.1.1
+          #   darp.headscale.net:
+          #     - 1.1.1.1
+          #     - 8.8.8.8
+
+          # Search domains to inject.
+          domains: []
+
+          # Whether to use [MagicDNS](https://tailscale.com/kb/1081/magicdns/).
+          # Only works if there is at least a nameserver defined.
+          magic_dns: true
+
+          # Defines the base domain to create the hostnames for MagicDNS.
+          # `base_domain` must be a FQDNs, without the trailing dot.
+          # The FQDN of the hosts will be
+          # `hostname.namespace.base_domain` (e.g., _myhost.mynamespace.example.com_).
+          base_domain: {{ .Values.internalBaseDomain }}
+
+        # Unix socket used for the CLI to connect without authentication
+        # Note: for production you will want to set this to something like:
+        # unix_socket: /var/run/headscale.sock
+        unix_socket: ./headscale.sock
+        unix_socket_permission: "0770"
+        #
+        # headscale supports experimental OpenID connect support,
+        # it is still being tested and might have some bugs, please
+        # help us test it.
+        # OpenID Connect
+        oidc:
+          only_start_if_oidc_is_available: false
+          issuer: {{ .Values.oauth2.hydraPublic }}
+          client_id: {{`{{ .client_id }}`}}
+          client_secret: {{`{{ .client_secret }}`}}
+          scope: ["openid", "profile", "email"]
+          extra_params:
+            domain_hint: {{ .Values.domain }}
+          allowed_domains:
+            - {{ .Values.domain }}
+          # allowed_groups:
+          #   - /headscale
+          # allowed_users:
+          #   - alice@example.com
+          strip_email_domain: true
+
+        # Logtail configuration
+        # Logtail is Tailscales logging and auditing infrastructure, it allows the control panel
+        # to instruct tailscale nodes to log their activity to a remote server.
+        logtail:
+          # Enable logtail for this headscales clients.
+          # As there is currently no support for overriding the log server in headscale, this is
+          # disabled by default. Enabling this will make your clients send logs to Tailscale Inc.
+          enabled: false
+
+        # Enabling this option makes devices prefer a random port for WireGuard traffic over the
+        # default static port 41641. This option is intended as a workaround for some buggy
+        # firewall devices. See https://tailscale.com/kb/1181/firewalls/ for more information.
+        randomize_client_port: true
diff --git a/charts/headscale/templates/oauth2-client.yaml b/charts/headscale/templates/oauth2-client.yaml
index d9c5cd1..0bd797a 100644
--- a/charts/headscale/templates/oauth2-client.yaml
+++ b/charts/headscale/templates/oauth2-client.yaml
@@ -1,4 +1,3 @@
-{{- $secret := include "clientSecret" . -}}
 apiVersion: hydra.ory.sh/v1alpha1
 kind: OAuth2Client
 metadata:
@@ -18,12 +17,3 @@
     port: 80
     endpoint: /admin/clients
     forwardedProto: https
----
-apiVersion: v1
-kind: Secret
-metadata:
-  name: {{ .Values.oauth2.secretName }}
-  namespace: {{ .Release.Namespace }}
-data:
-  client_id: {{ .Values.oauth2.clientId | b64enc}}
-  client_secret: {{ $secret | b64enc }}
diff --git a/charts/headscale/values.yaml b/charts/headscale/values.yaml
index f5da1f7..1f8b60b 100644
--- a/charts/headscale/values.yaml
+++ b/charts/headscale/values.yaml
@@ -11,7 +11,5 @@
 oauth2:
   hydraAdmin: http://hydra-admin
   hydraPublic: https://hydra.example.com
-  clientId: headscale
-  clientSecret: ""
   secretName: oauth2-client-headscale
 ipAddressPool: example-headscale