From 7cff3ae32d5068d7cde4169cf470f8b44e4c5a6d Mon Sep 17 00:00:00 2001 From: Kilian Kluge Date: Fri, 28 Mar 2025 20:02:41 +0100 Subject: [PATCH 01/11] Fix headscale service annotations --- deploy/charts/nebulous/Chart.yaml | 2 +- deploy/charts/nebulous/templates/headscale.yaml | 6 +++--- deploy/charts/nebulous/templates/ingress.yaml | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/deploy/charts/nebulous/Chart.yaml b/deploy/charts/nebulous/Chart.yaml index 7620500..0f6ab81 100644 --- a/deploy/charts/nebulous/Chart.yaml +++ b/deploy/charts/nebulous/Chart.yaml @@ -7,7 +7,7 @@ home: https://github.com/agentsea/nebulous # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.2.0 +version: 0.2.1 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to diff --git a/deploy/charts/nebulous/templates/headscale.yaml b/deploy/charts/nebulous/templates/headscale.yaml index 43382ec..205efb5 100644 --- a/deploy/charts/nebulous/templates/headscale.yaml +++ b/deploy/charts/nebulous/templates/headscale.yaml @@ -254,9 +254,9 @@ metadata: labels: {{- include "common.labels" . | nindent 4 }} {{- with .Values.headscale.service.annotations }} - annotations: - {{- toYaml . | nindent 4 }} - {{- end }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} spec: selector: app: {{ include "headscale.name" . }} diff --git a/deploy/charts/nebulous/templates/ingress.yaml b/deploy/charts/nebulous/templates/ingress.yaml index 31edfb6..caeca6a 100644 --- a/deploy/charts/nebulous/templates/ingress.yaml +++ b/deploy/charts/nebulous/templates/ingress.yaml @@ -11,7 +11,7 @@ metadata: {{- toYaml . | nindent 4 }} {{- end }} spec: - {{- with .Values.ingress.className }} + {{- with .Values.ingress.ingressClassName }} ingressClassName: {{.}} {{- end }} rules: From b3df4fc2b1ee4bec5926ce56d4ba0866e38fec86 Mon Sep 17 00:00:00 2001 From: Kilian Kluge Date: Fri, 28 Mar 2025 21:09:42 +0100 Subject: [PATCH 02/11] Configure deployment for tailscale --- deploy/charts/nebulous/templates/_helpers.tpl | 2 +- .../charts/nebulous/templates/deployment.yaml | 24 +++++++++++++++---- 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/deploy/charts/nebulous/templates/_helpers.tpl b/deploy/charts/nebulous/templates/_helpers.tpl index 3deb881..24ef8e6 100644 --- a/deploy/charts/nebulous/templates/_helpers.tpl +++ b/deploy/charts/nebulous/templates/_helpers.tpl @@ -46,7 +46,7 @@ headscale {{- end }} {{- define "headscale.host" -}} -{{- include "headscale.serviceName" . }}.{{- include "headscale.namespace" . }}.svc.cluster.local +http://{{- include "headscale.serviceName" . }}.{{- include "headscale.namespace" . }}.svc.cluster.local {{- end }} {{- define "postgres.name" -}} diff --git a/deploy/charts/nebulous/templates/deployment.yaml b/deploy/charts/nebulous/templates/deployment.yaml index f21a147..52aa5b2 100644 --- a/deploy/charts/nebulous/templates/deployment.yaml +++ b/deploy/charts/nebulous/templates/deployment.yaml @@ -19,6 +19,8 @@ spec: "helm.sh/restart-timestamp": "{{ now | date "20250101010203" }}" {{- end }} spec: + hostNetwork: true + dnsPolicy: ClusterFirstWithHostNet serviceAccountName: {{ include "nebulous.serviceAccountName" . }} containers: - name: nebulous-server @@ -26,6 +28,12 @@ spec: {{- with .Values.image.pullPolicy }} imagePullPolicy: {{.}} {{- end }} + securityContext: + capabilities: + add: + - NET_ADMIN + - NET_RAW + privileged: true ports: - containerPort: 3000 env: @@ -62,14 +70,14 @@ spec: - name: AWS_SECRET_ACCESS_KEY valueFrom: secretKeyRef: - name: {{ .Values.providers.aws.secret.name }} + name: {{ .Values.providers.aws.secret.name }} key: {{ .Values.providers.aws.secret.keys.secretAccessKey }} {{- end }} {{- if .Values.providers.runpod.enabled }} - name: RUNPOD_API_KEY valueFrom: secretKeyRef: - name: {{ .Values.providers.runpod.secret.name }} + name: {{ .Values.providers.runpod.secret.name }} key: {{ .Values.providers.runpod.secret.keys.apiKey }} {{- end }} - name: TS_AUTHKEY @@ -79,9 +87,9 @@ spec: key: {{ .Values.tailscale.secret.keys.authKey }} - name: TS_LOGINSERVER valueFrom: - secretKeyRef: - name: {{ .Values.tailscale.secret.name }} - key: {{ .Values.tailscale.secret.keys.loginServer }} + secretKeyRef: + name: {{ .Values.tailscale.secret.name }} + key: {{ .Values.tailscale.secret.keys.loginServer }} - name: RUST_LOG value: {{ .Values.logLevel | lower }} envFrom: @@ -96,6 +104,8 @@ spec: mountPath: /datasets - name: model-pvc mountPath: /models + - name: dev-net-tun + mountPath: /dev/net/tun volumes: - name: huggingface-pvc persistentVolumeClaim: @@ -109,3 +119,7 @@ spec: - name: model-pvc persistentVolumeClaim: claimName: {{ .Values.storage.model.claimName }} + - name: dev-net-tun + hostPath: + path: /dev/net/tun + type: CharDevice From ad306a3a779389a8511778c5a485c3c1a3042bb3 Mon Sep 17 00:00:00 2001 From: Kilian Kluge Date: Mon, 31 Mar 2025 20:14:47 +0200 Subject: [PATCH 03/11] Improve headscale configurability --- deploy/charts/nebulous/README.md | 6 ++++-- deploy/charts/nebulous/templates/_helpers.tpl | 2 +- deploy/charts/nebulous/templates/deployment.yaml | 2 ++ deploy/charts/nebulous/templates/headscale.yaml | 11 +++++++---- deploy/charts/nebulous/values.yaml | 9 ++++++++- 5 files changed, 22 insertions(+), 8 deletions(-) diff --git a/deploy/charts/nebulous/README.md b/deploy/charts/nebulous/README.md index 0b68418..5ed0cb0 100644 --- a/deploy/charts/nebulous/README.md +++ b/deploy/charts/nebulous/README.md @@ -1,6 +1,6 @@ # nebulous -![Version: 0.2.0](https://img.shields.io/badge/Version-0.2.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 0.1.61](https://img.shields.io/badge/AppVersion-0.1.61-informational?style=flat-square) +![Version: 0.2.1](https://img.shields.io/badge/Version-0.2.1-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 0.1.61](https://img.shields.io/badge/AppVersion-0.1.61-informational?style=flat-square) A cross-cloud container orchestrator for AI workloads @@ -40,11 +40,13 @@ helm install nebulous nebulous/nebulous -f values.yaml \ | headscale.derp.configMap.name | string | `""` | The name of the ConfigMap containing the DERP server configuration. | | headscale.derp.externalMaps | list | `[]` | URLs of externally available DERP maps encoded in JSON. | | headscale.dns.base_domain | string | `""` | The base domain for MagicDNS hostnames. Cannot be the same as the Headscale server's domain. Refer to https://github.com/juanfont/headscale/blob/main/config-example.yaml for details. | -| headscale.domain | string | `""` | The domain under which the Headscale server is exposed. | +| headscale.domain | string | `""` | The domain under which the Headscale server is exposed. Required if create is true. The headscale server must be reachable at https://${domain}:443. | | headscale.imageTag | string | `"latest"` | The Headscale image tag. | | headscale.ingress.annotations | object | `{}` | Annotations to add to the Ingress resource. | | headscale.ingress.enabled | bool | `false` | If enabled, create an Ingress resource. Ignored unless 'enabled' is true. | | headscale.ingress.ingressClassName | string | `""` | The ingress class. | +| headscale.log.format | string | `"text"` | The log format of the Headscale server. Options are "text" or "json". | +| headscale.log.level | string | `"info"` | The log level of the Headscale server. Options are "off", "trace", "debug", "info", "warn", "error". | | headscale.namespaceOverride | string | `""` | Namespace override for the Headscale deployment. | | headscale.prefixes | object | `{"v4":"100.64.0.0/10","v6":"fd7a:115c:a1e0::/48"}` | Prefixes to allocate tailaddresses from. Must be within the IP ranges supported by the Tailscale client. Refer to https://github.com/juanfont/headscale/blob/main/config-example.yaml for details. | | headscale.privateKeys.claimName | string | `"headscale-keys-pvc"` | The name of the PersistentVolumeClaim for the Headscale private keys. | diff --git a/deploy/charts/nebulous/templates/_helpers.tpl b/deploy/charts/nebulous/templates/_helpers.tpl index 24ef8e6..bdbb867 100644 --- a/deploy/charts/nebulous/templates/_helpers.tpl +++ b/deploy/charts/nebulous/templates/_helpers.tpl @@ -46,7 +46,7 @@ headscale {{- end }} {{- define "headscale.host" -}} -http://{{- include "headscale.serviceName" . }}.{{- include "headscale.namespace" . }}.svc.cluster.local +https://{{- required ".Values.headscale.domain is required" .Values.headscale.domain }} {{- end }} {{- define "postgres.name" -}} diff --git a/deploy/charts/nebulous/templates/deployment.yaml b/deploy/charts/nebulous/templates/deployment.yaml index 52aa5b2..03418f4 100644 --- a/deploy/charts/nebulous/templates/deployment.yaml +++ b/deploy/charts/nebulous/templates/deployment.yaml @@ -7,6 +7,8 @@ metadata: {{- include "common.labels" . | nindent 4 }} spec: replicas: 1 + strategy: + type: Recreate selector: matchLabels: app: {{ include "nebulous.appSelector" . }} diff --git a/deploy/charts/nebulous/templates/headscale.yaml b/deploy/charts/nebulous/templates/headscale.yaml index 205efb5..aa90bf0 100644 --- a/deploy/charts/nebulous/templates/headscale.yaml +++ b/deploy/charts/nebulous/templates/headscale.yaml @@ -34,6 +34,9 @@ data: {{- end }} dns: base_domain: {{ .Values.headscale.dns.base_domain }} + log: + format: {{ .Values.headscale.log.format }} + level: {{ .Values.headscale.log.level }} --- {{- if .Values.headscale.sqlite.createPersistentVolumeClaim }} apiVersion: v1 @@ -235,10 +238,10 @@ spec: done; POD_NAME=$(kubectl get pod -l app={{ include "headscale.name" . }} -n {{ include "headscale.namespace" . }} -o jsonpath='{.items[0].metadata.name}') - kubectl exec $POD_NAME -- headscale users create nebu || echo 'User nebu already exists. That is OK.'; + kubectl exec $POD_NAME -n {{ include "headscale.namespace" . }} -- headscale users create nebu || echo 'User nebu already exists. That is OK.'; - API_KEY=$(kubectl exec $POD_NAME -- headscale apikeys create --expiration 99y); - AUTH_KEY=$(kubectl exec $POD_NAME -- headscale preauthkeys create --user nebu --reusable); + API_KEY=$(kubectl exec $POD_NAME -n {{ include "headscale.namespace" . }} -- headscale apikeys create --expiration 99y); + AUTH_KEY=$(kubectl exec $POD_NAME -n {{ include "headscale.namespace" . }} -- headscale preauthkeys create --user nebu --reusable); kubectl create secret generic {{ .Values.tailscale.secret.name }} -n {{ include "nebulous.namespace" . }} \ --from-literal={{ .Values.tailscale.secret.keys.apiKey }}=$API_KEY \ @@ -303,7 +306,7 @@ spec: paths: - backend: service: - name: {{ include "headscale.name" . }} + name: {{ include "headscale.serviceName" . }} port: number: {{ .Values.headscale.service.port }} path: / diff --git a/deploy/charts/nebulous/values.yaml b/deploy/charts/nebulous/values.yaml index 55c04b0..7b19860 100644 --- a/deploy/charts/nebulous/values.yaml +++ b/deploy/charts/nebulous/values.yaml @@ -186,7 +186,8 @@ headscale: namespaceOverride: "" # -- The Headscale image tag. imageTag: "latest" - # -- The domain under which the Headscale server is exposed. + # -- The domain under which the Headscale server is exposed. Required if create is true. + # The headscale server must be reachable at https://${domain}:443. domain: "" # -- Prefixes to allocate tailaddresses from. Must be within the IP ranges supported by the Tailscale client. @@ -200,6 +201,12 @@ headscale: # Refer to https://github.com/juanfont/headscale/blob/main/config-example.yaml for details. base_domain: "" + log: + # -- The log level of the Headscale server. Options are "off", "trace", "debug", "info", "warn", "error". + level: "info" + # -- The log format of the Headscale server. Options are "text" or "json". + format: "text" + # -- The Headscale DERP configuration. Either 'externalMapUrls' or 'configMap' must be set. derp: # -- URLs of externally available DERP maps encoded in JSON. From 256fcda7c34949381d1d07467a0a292a4236fef1 Mon Sep 17 00:00:00 2001 From: Kilian Kluge Date: Mon, 31 Mar 2025 20:39:02 +0200 Subject: [PATCH 04/11] Simplify Ingress resources --- .../charts/nebulous/templates/headscale.yaml | 18 +++++------------- deploy/charts/nebulous/templates/ingress.yaml | 18 +++++------------- deploy/charts/nebulous/templates/redis.yaml | 18 +++++------------- 3 files changed, 15 insertions(+), 39 deletions(-) diff --git a/deploy/charts/nebulous/templates/headscale.yaml b/deploy/charts/nebulous/templates/headscale.yaml index aa90bf0..b7559e0 100644 --- a/deploy/charts/nebulous/templates/headscale.yaml +++ b/deploy/charts/nebulous/templates/headscale.yaml @@ -301,18 +301,10 @@ spec: {{- with .Values.headscale.ingress.ingressClassName }} ingressClassName: {{.}} {{- end }} - rules: - - http: - paths: - - backend: - service: - name: {{ include "headscale.serviceName" . }} - port: - number: {{ .Values.headscale.service.port }} - path: / - pathType: Prefix - {{- with .Values.headscale.domain }} - host: {{.}} - {{- end }} + defaultBackend: + service: + name: {{ include "headscale.serviceName" . }} + port: + number: {{ .Values.headscale.service.port }} {{- end }} {{- end }} diff --git a/deploy/charts/nebulous/templates/ingress.yaml b/deploy/charts/nebulous/templates/ingress.yaml index caeca6a..bdd3de1 100644 --- a/deploy/charts/nebulous/templates/ingress.yaml +++ b/deploy/charts/nebulous/templates/ingress.yaml @@ -14,17 +14,9 @@ spec: {{- with .Values.ingress.ingressClassName }} ingressClassName: {{.}} {{- end }} - rules: - - http: - paths: - - backend: - service: - name: {{ include "nebulous.serviceName" . }} - port: - number: {{ .Values.service.port }} - path: / - pathType: Prefix - {{- with .Values.ingress.host }} - host: {{.}} - {{- end }} + defaultBackend: + service: + name: {{ include "nebulous.serviceName" . }} + port: + number: {{ .Values.service.port }} {{- end }} diff --git a/deploy/charts/nebulous/templates/redis.yaml b/deploy/charts/nebulous/templates/redis.yaml index 557e8c7..9480780 100644 --- a/deploy/charts/nebulous/templates/redis.yaml +++ b/deploy/charts/nebulous/templates/redis.yaml @@ -84,18 +84,10 @@ spec: {{- with .Values.redis.ingress.ingressClassName }} ingressClassName: {{.}} {{- end }} - rules: - - http: - paths: - - backend: - service: - name: {{ include "redis.name" . }} - port: - number: {{ .Values.redis.auth.port }} - path: / - pathType: Prefix - {{- with .Values.redis.ingress.host }} - host: {{.}} - {{- end }} + defaultBackend: + service: + name: {{ include "redis.name" . }} + port: + number: {{ .Values.redis.auth.port }} {{- end }} {{- end }} From fe074131e30dc19ae67317e364b33d46a1af095d Mon Sep 17 00:00:00 2001 From: Kilian Kluge Date: Tue, 1 Apr 2025 21:30:46 +0200 Subject: [PATCH 05/11] Add LoadBalancer service and Let's Encrypt support --- deploy/charts/nebulous/README.md | 7 +++ .../charts/nebulous/templates/headscale.yaml | 47 ++++++++++++++++--- deploy/charts/nebulous/values.yaml | 19 ++++++++ 3 files changed, 66 insertions(+), 7 deletions(-) diff --git a/deploy/charts/nebulous/README.md b/deploy/charts/nebulous/README.md index 5ed0cb0..9a80336 100644 --- a/deploy/charts/nebulous/README.md +++ b/deploy/charts/nebulous/README.md @@ -56,10 +56,17 @@ helm install nebulous nebulous/nebulous -f values.yaml \ | headscale.service.annotations | object | `{}` | The annotations to add to the Kubernetes service. | | headscale.service.nameOverride | string | `""` | Override the name of the Kubernetes service. | | headscale.service.port | int | `80` | The port of the Kubernetes service. | +| headscale.service.type | string | `"ClusterIP"` | The type of the Kubernetes service. Options are "ClusterIP", "NodePort", and "LoadBalancer". | | headscale.sqlite.claimName | string | `"headscale-sqlite-pvc"` | The name of the PersistentVolumeClaim for the Headscale sqlite database. | | headscale.sqlite.createPersistentVolumeClaim | bool | `true` | If true, create a PersistentVolumeClaim for the Headscale sqlite database. | | headscale.sqlite.size | string | `"10Gi"` | The size of the PersistentVolumeClaim created for the Headscale sqlite database. | | headscale.sqlite.storageClassName | string | `""` | The storage class of the PersistentVolumeClaim created for the Headscale sqlite database. | +| headscale.tls.letsencrypt.claimName | string | `"headscale-tls-pvc"` | The name of the PersistentVolumeClaim for the Headscale Let's Encrypt cache. | +| headscale.tls.letsencrypt.createPersistentVolumeClaim | bool | `true` | If true, create a PersistentVolumeClaim for the Headscale Let's Encrypt cache. | +| headscale.tls.letsencrypt.email | string | `""` | The email address for the Let's Encrypt certificate. | +| headscale.tls.letsencrypt.hostname | string | `""` | The hostname for the Let's Encrypt certificate. Has to match the domain of the Headscale server. | +| headscale.tls.letsencrypt.size | string | `"16Mi"` | The size of the PersistentVolumeClaim created for the Headscale Let's Encrypt cache. | +| headscale.tls.letsencrypt.storageClassName | string | `""` | The storage class of the PersistentVolumeClaim created for the Headscale Let's Encrypt cache. | | image.pullPolicy | string | `"IfNotPresent"` | | | image.repository | string | `"us-docker.pkg.dev/agentsea-dev/nebulous/server"` | The repository to pull the server image from. | | image.tag | string | `""` | The nebulous image tag. Defaults to the Helm chart's appVersion. | diff --git a/deploy/charts/nebulous/templates/headscale.yaml b/deploy/charts/nebulous/templates/headscale.yaml index b7559e0..a60c403 100644 --- a/deploy/charts/nebulous/templates/headscale.yaml +++ b/deploy/charts/nebulous/templates/headscale.yaml @@ -11,15 +11,20 @@ data: server_url: {{ printf "https://%s:443" .Values.headscale.domain }} listen_addr: 0.0.0.0:8080 metrics_listen_addr: 0.0.0.0:9090 - # TLS termination happens at the Ingress level - # (see https://headscale.net/stable/ref/integration/reverse-proxy/#tls) - tls_cert_path: "" - tls_key_path: "" noise: private_key_path: /mnt/keys/noise_private.key prefixes: v4: 100.64.0.0/10 v6: fd7a:115c:a1e0::/48 + {{- if .Values.headscale.tls.letsencrypt.hostname }} + tls_letsencrypt_hostname: {{ .Values.headscale.tls.letsencrypt.hostname }} + tls_letsencrypt_email: {{ .Values.headscale.tls.letsencrypt.email }} + tls_letsencrypt_listen: ":http" + tls_letsencrypt_cache_dir: /mnt/letsencrypt + tls_letsencrypt_challenge_type: HTTP-01 + {{- end }} + tls_cert_path: "" + tls_key_path: "" database: type: sqlite derp: @@ -76,6 +81,25 @@ spec: storage: {{ .Values.headscale.privateKeys.size }} --- {{- end }} +{{- if .Values.headscale.tls.letsencrypt.createPersistentVolumeClaim }} +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: {{ .Values.headscale.tls.letsencrypt.claimName }} + namespace: {{ include "headscale.namespace" . }} + labels: + {{- include "common.labels" . | nindent 4 }} +spec: + {{- with .Values.headscale.tls.letsencrypt.storageClassName }} + storageClassName: {{.}} + {{- end }} + accessModes: + - ReadWriteOnce + resources: + requests: + storage: {{ .Values.headscale.tls.letsencrypt.size }} +--- +{{- end }} apiVersion: apps/v1 kind: Deployment metadata: @@ -108,7 +132,11 @@ spec: - mountPath: /mnt/sqlite name: sqlite - mountPath: /mnt/keys - name: private-keys + name: private-key + {{- if .Values.headscale.tls.letsencrypt.hostname }} + - mountPath: /mnt/letsencrypt + name: tls-letsencrypt + {{- end }} {{- if .Values.headscale.derp.configMap.name }} - mountPath: /mnt/derp name: derp-config @@ -123,6 +151,11 @@ spec: - name: private-keys persistentVolumeClaim: claimName: {{ .Values.headscale.privateKeys.claimName }} + {{- if .Values.headscale.tls.letsencrypt.hostname }} + - name: tls-letsencrypt + persistentVolumeClaim: + claimName: {{ .Values.headscale.tls.letsencrypt.claimName }} + {{- end }} {{- if .Values.headscale.derp.configMap.name }} - name: derp-config configMap: @@ -267,7 +300,7 @@ spec: - protocol: TCP port: {{ .Values.headscale.service.port }} targetPort: 8080 - type: ClusterIP + type: {{ .Values.headscale.service.type }} --- apiVersion: v1 kind: Service @@ -305,6 +338,6 @@ spec: service: name: {{ include "headscale.serviceName" . }} port: - number: {{ .Values.headscale.service.port }} + number: {{ .Values.headscale.service.port }} {{- end }} {{- end }} diff --git a/deploy/charts/nebulous/values.yaml b/deploy/charts/nebulous/values.yaml index 7b19860..5f00825 100644 --- a/deploy/charts/nebulous/values.yaml +++ b/deploy/charts/nebulous/values.yaml @@ -239,9 +239,28 @@ headscale: # -- The storage class of the PersistentVolumeClaim created for the Headscale private keys. storageClassName: "" + tls: + letsencrypt: + # -- The hostname for the Let's Encrypt certificate. Has to match the domain of the Headscale server. + hostname: "" + # -- The email address for the Let's Encrypt certificate. + email: "" + + # -- The name of the PersistentVolumeClaim for the Headscale Let's Encrypt cache. + claimName: "headscale-tls-pvc" + + # -- If true, create a PersistentVolumeClaim for the Headscale Let's Encrypt cache. + createPersistentVolumeClaim: true + # -- The size of the PersistentVolumeClaim created for the Headscale Let's Encrypt cache. + size: "16Mi" + # -- The storage class of the PersistentVolumeClaim created for the Headscale Let's Encrypt cache. + storageClassName: "" + service: # -- The port of the Kubernetes service. port: 80 + # -- The type of the Kubernetes service. Options are "ClusterIP", "NodePort", and "LoadBalancer". + type: "ClusterIP" # -- The annotations to add to the Kubernetes service. annotations: { } # -- Override the name of the Kubernetes service. From 8e83bc8df853b30f494801bee6e5822238205085 Mon Sep 17 00:00:00 2001 From: Kilian Kluge Date: Tue, 1 Apr 2025 22:17:55 +0200 Subject: [PATCH 06/11] Fix Let's Encrypt configuration --- deploy/charts/nebulous/templates/headscale.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/deploy/charts/nebulous/templates/headscale.yaml b/deploy/charts/nebulous/templates/headscale.yaml index a60c403..6ffaad1 100644 --- a/deploy/charts/nebulous/templates/headscale.yaml +++ b/deploy/charts/nebulous/templates/headscale.yaml @@ -18,7 +18,7 @@ data: v6: fd7a:115c:a1e0::/48 {{- if .Values.headscale.tls.letsencrypt.hostname }} tls_letsencrypt_hostname: {{ .Values.headscale.tls.letsencrypt.hostname }} - tls_letsencrypt_email: {{ .Values.headscale.tls.letsencrypt.email }} + acme_email: {{ .Values.headscale.tls.letsencrypt.email }} tls_letsencrypt_listen: ":http" tls_letsencrypt_cache_dir: /mnt/letsencrypt tls_letsencrypt_challenge_type: HTTP-01 @@ -81,7 +81,7 @@ spec: storage: {{ .Values.headscale.privateKeys.size }} --- {{- end }} -{{- if .Values.headscale.tls.letsencrypt.createPersistentVolumeClaim }} +{{- if and .Values.headscale.tls.letsencrypt.hostname .Values.headscale.tls.letsencrypt.createPersistentVolumeClaim }} apiVersion: v1 kind: PersistentVolumeClaim metadata: @@ -132,7 +132,7 @@ spec: - mountPath: /mnt/sqlite name: sqlite - mountPath: /mnt/keys - name: private-key + name: private-keys {{- if .Values.headscale.tls.letsencrypt.hostname }} - mountPath: /mnt/letsencrypt name: tls-letsencrypt From 57cbfcc0e1e38ae7f76967bfca26f42021e7f5bc Mon Sep 17 00:00:00 2001 From: Kilian Kluge Date: Thu, 3 Apr 2025 22:55:57 +0200 Subject: [PATCH 07/11] Bump Helm chart v0.2.1 to nebulous to 0.1.75 --- deploy/charts/nebulous/Chart.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deploy/charts/nebulous/Chart.yaml b/deploy/charts/nebulous/Chart.yaml index 0f6ab81..d4efc13 100644 --- a/deploy/charts/nebulous/Chart.yaml +++ b/deploy/charts/nebulous/Chart.yaml @@ -13,4 +13,4 @@ version: 0.2.1 # incremented each time you make changes to the application. Versions are not expected to # follow Semantic Versioning. They should reflect the version the application is using. # It is recommended to use it with quotes. -appVersion: "0.1.61" +appVersion: "0.1.75" From d7307ac64d18c40bee392f7e892ff4ae2762d933 Mon Sep 17 00:00:00 2001 From: Kilian Kluge Date: Tue, 15 Apr 2025 23:52:51 +0200 Subject: [PATCH 08/11] fix: drop Ingress for Redis --- deploy/charts/nebulous/README.md | 6 +----- deploy/charts/nebulous/templates/redis.yaml | 23 --------------------- deploy/charts/nebulous/values.yaml | 11 ---------- 3 files changed, 1 insertion(+), 39 deletions(-) diff --git a/deploy/charts/nebulous/README.md b/deploy/charts/nebulous/README.md index 9a80336..3ff213c 100644 --- a/deploy/charts/nebulous/README.md +++ b/deploy/charts/nebulous/README.md @@ -1,6 +1,6 @@ # nebulous -![Version: 0.2.1](https://img.shields.io/badge/Version-0.2.1-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 0.1.61](https://img.shields.io/badge/AppVersion-0.1.61-informational?style=flat-square) +![Version: 0.2.1](https://img.shields.io/badge/Version-0.2.1-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 0.1.75](https://img.shields.io/badge/AppVersion-0.1.75-informational?style=flat-square) A cross-cloud container orchestrator for AI workloads @@ -100,10 +100,6 @@ helm install nebulous nebulous/nebulous -f values.yaml \ | redis.auth | object | `{"database":0,"host":"","password":"nebulous","port":6379}` | Manual configuration of the Redis connection. Except for 'host', this information is also used if 'create' is true. | | redis.create | bool | `false` | If enabled, create a Redis deployment and service. Not recommended for production. | | redis.imageTag | string | `"latest"` | The redis image tag. Ignored unless 'create' is true. | -| redis.ingress.annotations | object | `{}` | Annotations to add to the Ingress resource. | -| redis.ingress.enabled | bool | `false` | If enabled, create an Ingress resource. Ignored unless 'create' is true. | -| redis.ingress.host | string | `""` | The host field of the Ingress rule. | -| redis.ingress.ingressClassName | string | `""` | The ingress class. | | redis.secret.keys.connection_string | string | `"CONNECTION_STRING"` | The key in the secret containing the Redis connection string. | | redis.secret.keys.password | string | `"PASSWORD"` | The key in the secret containing the Redis password. | | redis.secret.name | string | `"redis-secret"` | Name of the secret with the Redis connection string and password. | diff --git a/deploy/charts/nebulous/templates/redis.yaml b/deploy/charts/nebulous/templates/redis.yaml index 9480780..7922015 100644 --- a/deploy/charts/nebulous/templates/redis.yaml +++ b/deploy/charts/nebulous/templates/redis.yaml @@ -67,27 +67,4 @@ spec: port: {{ .Values.redis.auth.port }} targetPort: 6379 type: ClusterIP ---- -{{- if .Values.redis.ingress.enabled }} -apiVersion: networking.k8s.io/v1 -kind: Ingress -metadata: - name: {{ include "redis.serviceName" . }} - namespace: {{ include "nebulous.namespace" . }} - labels: - {{- include "common.labels" . | nindent 4 }} - {{- with .Values.redis.ingress.annotations }} - annotations: - {{- toYaml . | nindent 4 }} - {{- end }} -spec: - {{- with .Values.redis.ingress.ingressClassName }} - ingressClassName: {{.}} - {{- end }} - defaultBackend: - service: - name: {{ include "redis.name" . }} - port: - number: {{ .Values.redis.auth.port }} -{{- end }} {{- end }} diff --git a/deploy/charts/nebulous/values.yaml b/deploy/charts/nebulous/values.yaml index 5f00825..8cbd0e7 100644 --- a/deploy/charts/nebulous/values.yaml +++ b/deploy/charts/nebulous/values.yaml @@ -167,17 +167,6 @@ redis: # -- Override the name of the Kubernetes service. nameOverride: "" - ingress: - # -- If enabled, create an Ingress resource. Ignored unless 'create' is true. - enabled: false - - # -- Annotations to add to the Ingress resource. - annotations: { } - # -- The ingress class. - ingressClassName: "" - # -- The host field of the Ingress rule. - host: "" - ## Headscale configuration headscale: # -- If true, create a Headscale deployment and service. Overrides tailscale configuration. Not recommended for production. From 96fe699229093f28260c5bc491c92caf3e4df50a Mon Sep 17 00:00:00 2001 From: Kilian Kluge Date: Wed, 16 Apr 2025 00:08:14 +0200 Subject: [PATCH 09/11] feat: Redis on tailnet --- deploy/charts/nebulous/README.md | 1 - deploy/charts/nebulous/templates/_helpers.tpl | 8 +++++ deploy/charts/nebulous/templates/redis.yaml | 29 +++++++++++++++++++ deploy/charts/nebulous/values.yaml | 2 -- 4 files changed, 37 insertions(+), 3 deletions(-) diff --git a/deploy/charts/nebulous/README.md b/deploy/charts/nebulous/README.md index 3ff213c..31cc4bf 100644 --- a/deploy/charts/nebulous/README.md +++ b/deploy/charts/nebulous/README.md @@ -130,6 +130,5 @@ helm install nebulous nebulous/nebulous -f values.yaml \ | tailscale.loginServer | string | `"https://login.tailscale.com"` | The Tailscale host to connect to. If headscale.enabled is true, this is ignored. | | tailscale.secret.keys.apiKey | string | `"API_KEY"` | The key in the secret containing the Tailscale API key | | tailscale.secret.keys.authKey | string | `"AUTH_KEY"` | The key in the secret containing the Tailscale auth key | -| tailscale.secret.keys.loginServer | string | `"LOGIN_SERVER"` | The key in the secret containing the Tailscale host. | | tailscale.secret.name | string | `"tailscale-secret"` | Name of the secret with the Redis connection string and password. | diff --git a/deploy/charts/nebulous/templates/_helpers.tpl b/deploy/charts/nebulous/templates/_helpers.tpl index bdbb867..1b4eeeb 100644 --- a/deploy/charts/nebulous/templates/_helpers.tpl +++ b/deploy/charts/nebulous/templates/_helpers.tpl @@ -49,6 +49,14 @@ headscale https://{{- required ".Values.headscale.domain is required" .Values.headscale.domain }} {{- end }} +{{- define "tailscale.loginServer" }} +{{- if .Values.headscale.create }} +{{- include "headscale.host" . }} +{{- else }} +{{- required ".Values.tailscale.loginServer is required" .Values.tailscale.loginServer }} +{{- end }} +{{- end }} + {{- define "postgres.name" -}} postgres {{- end }} diff --git a/deploy/charts/nebulous/templates/redis.yaml b/deploy/charts/nebulous/templates/redis.yaml index 7922015..7430bf5 100644 --- a/deploy/charts/nebulous/templates/redis.yaml +++ b/deploy/charts/nebulous/templates/redis.yaml @@ -30,7 +30,31 @@ spec: labels: app: {{ include "redis.name" . }} spec: + hostNetwork: true + dnsPolicy: ClusterFirstWithHostNet containers: + - name: tailscale + image: tailscale/tailscale:latest + env: + - name: TS_STATE_DIR + value: /var/lib/tailscale + - name: TS_USERSPACE + value: "true" + - name: TS_AUTH_KEY + valueFrom: + secretKeyRef: + name: {{ .Values.tailscale.secret.name }} + key: {{ .Values.tailscale.secret.keys.authKey }} + - name: TS_EXTRA_ARGS + value: --login-server {{ include "tailscale.loginServer" . }} + volumeMounts: + - name: dev-net-tun + mountPath: /dev/net/tun + securityContext: + capabilities: + add: + - NET_ADMIN + - NET_RAW - name: redis image: "redis:{{ .Values.redis.imageTag }}" command: @@ -47,6 +71,11 @@ spec: key: {{ .Values.redis.secret.keys.password }} ports: - containerPort: 6379 + volumes: + - name: dev-net-tun + hostPath: + path: /dev/net/tun + type: CharDevice --- apiVersion: v1 kind: Service diff --git a/deploy/charts/nebulous/values.yaml b/deploy/charts/nebulous/values.yaml index 8cbd0e7..96d4b1a 100644 --- a/deploy/charts/nebulous/values.yaml +++ b/deploy/charts/nebulous/values.yaml @@ -56,8 +56,6 @@ tailscale: # -- Name of the secret with the Redis connection string and password. name: "tailscale-secret" keys: - # -- The key in the secret containing the Tailscale host. - loginServer: "LOGIN_SERVER" # -- The key in the secret containing the Tailscale API key apiKey: "API_KEY" # -- The key in the secret containing the Tailscale auth key From 13780e45988414346316f817808b2918da9a36fb Mon Sep 17 00:00:00 2001 From: Kilian Kluge Date: Wed, 16 Apr 2025 16:27:39 +0200 Subject: [PATCH 10/11] Unify spelling of values --- deploy/charts/nebulous/README.md | 6 +++--- deploy/charts/nebulous/templates/deployment.yaml | 4 ++-- deploy/charts/nebulous/templates/headscale.yaml | 2 +- deploy/charts/nebulous/templates/postgres.yaml | 2 +- deploy/charts/nebulous/templates/redis.yaml | 2 +- deploy/charts/nebulous/values.yaml | 6 +++--- 6 files changed, 11 insertions(+), 11 deletions(-) diff --git a/deploy/charts/nebulous/README.md b/deploy/charts/nebulous/README.md index 31cc4bf..57ba550 100644 --- a/deploy/charts/nebulous/README.md +++ b/deploy/charts/nebulous/README.md @@ -39,7 +39,7 @@ helm install nebulous nebulous/nebulous -f values.yaml \ | headscale.derp.configMap.key | string | `"servers.yaml"` | The key in the ConfigMap containing the DERP server configuration YAML file. | | headscale.derp.configMap.name | string | `""` | The name of the ConfigMap containing the DERP server configuration. | | headscale.derp.externalMaps | list | `[]` | URLs of externally available DERP maps encoded in JSON. | -| headscale.dns.base_domain | string | `""` | The base domain for MagicDNS hostnames. Cannot be the same as the Headscale server's domain. Refer to https://github.com/juanfont/headscale/blob/main/config-example.yaml for details. | +| headscale.dns.baseDomain | string | `""` | The base domain for MagicDNS hostnames. Cannot be the same as the Headscale server's domain. Refer to https://github.com/juanfont/headscale/blob/main/config-example.yaml for details. | | headscale.domain | string | `""` | The domain under which the Headscale server is exposed. Required if create is true. The headscale server must be reachable at https://${domain}:443. | | headscale.imageTag | string | `"latest"` | The Headscale image tag. | | headscale.ingress.annotations | object | `{}` | Annotations to add to the Ingress resource. | @@ -86,7 +86,7 @@ helm install nebulous nebulous/nebulous -f values.yaml \ | postgres.persistence.enabled | bool | `false` | If enabled, use a PersistentVolumeClaim for the Postgres data. Ignored unless 'create' is true. | | postgres.persistence.size | string | `"100Gi"` | The size of the PersistentVolumeClaim for the Postgres data. | | postgres.persistence.storageClassName | string | `""` | The storage class of the PersistentVolumeClaim for the Postgres data. | -| postgres.secret.keys.connection_string | string | `"CONNECTION_STRING"` | The key in the secret containing the Postgres connection string. | +| postgres.secret.keys.connectionString | string | `"CONNECTION_STRING"` | The key in the secret containing the Postgres connection string. | | postgres.secret.name | string | `"postgres-secret"` | Name of the secret with the Postgres connection string. | | providers.aws.auth | object | `{"accessKeyId":"","secretAccessKey":""}` | Manual configuration of the AWS credentials. Not recommended for production. | | providers.aws.enabled | bool | `false` | Enable access to AWS. | @@ -100,7 +100,7 @@ helm install nebulous nebulous/nebulous -f values.yaml \ | redis.auth | object | `{"database":0,"host":"","password":"nebulous","port":6379}` | Manual configuration of the Redis connection. Except for 'host', this information is also used if 'create' is true. | | redis.create | bool | `false` | If enabled, create a Redis deployment and service. Not recommended for production. | | redis.imageTag | string | `"latest"` | The redis image tag. Ignored unless 'create' is true. | -| redis.secret.keys.connection_string | string | `"CONNECTION_STRING"` | The key in the secret containing the Redis connection string. | +| redis.secret.keys.connectionString | string | `"CONNECTION_STRING"` | The key in the secret containing the Redis connection string. | | redis.secret.keys.password | string | `"PASSWORD"` | The key in the secret containing the Redis password. | | redis.secret.name | string | `"redis-secret"` | Name of the secret with the Redis connection string and password. | | redis.service.annotations | object | `{}` | The annotations to add to the Kubernetes service. | diff --git a/deploy/charts/nebulous/templates/deployment.yaml b/deploy/charts/nebulous/templates/deployment.yaml index 03418f4..a5ffff6 100644 --- a/deploy/charts/nebulous/templates/deployment.yaml +++ b/deploy/charts/nebulous/templates/deployment.yaml @@ -48,7 +48,7 @@ spec: valueFrom: secretKeyRef: name: {{ .Values.postgres.secret.name }} - key: {{ .Values.postgres.secret.keys.connection_string }} + key: {{ .Values.postgres.secret.keys.connectionString }} - name: MESSAGE_QUEUE_TYPE value: {{ .Values.messageQueue.type }} {{- if eq .Values.messageQueue.type "redis" }} @@ -56,7 +56,7 @@ spec: valueFrom: secretKeyRef: name: {{ .Values.redis.secret.name }} - key: {{ .Values.redis.secret.keys.connection_string }} + key: {{ .Values.redis.secret.keys.connectionString }} - name: REDIS_PASSWORD valueFrom: secretKeyRef: diff --git a/deploy/charts/nebulous/templates/headscale.yaml b/deploy/charts/nebulous/templates/headscale.yaml index 6ffaad1..e220217 100644 --- a/deploy/charts/nebulous/templates/headscale.yaml +++ b/deploy/charts/nebulous/templates/headscale.yaml @@ -38,7 +38,7 @@ data: - /mnt/derp/{{ .Values.headscale.derp.configMap.key }} {{- end }} dns: - base_domain: {{ .Values.headscale.dns.base_domain }} + base_domain: {{ .Values.headscale.dns.baseDomain }} log: format: {{ .Values.headscale.log.format }} level: {{ .Values.headscale.log.level }} diff --git a/deploy/charts/nebulous/templates/postgres.yaml b/deploy/charts/nebulous/templates/postgres.yaml index fc5dfa1..59f309d 100644 --- a/deploy/charts/nebulous/templates/postgres.yaml +++ b/deploy/charts/nebulous/templates/postgres.yaml @@ -8,7 +8,7 @@ metadata: {{- include "common.labels" . | nindent 4 }} type: Opaque data: - {{ .Values.postgres.secret.keys.connection_string }}: {{ printf "postgresql://%s:%s@%s:%d/%s" .Values.postgres.auth.user .Values.postgres.auth.password (include "postgres.host") (int .Values.postgres.auth.port) .Values.postgres.auth.database | b64enc }} + {{ .Values.postgres.secret.keys.connectionString }}: {{ printf "postgresql://%s:%s@%s:%d/%s" .Values.postgres.auth.user .Values.postgres.auth.password (include "postgres.host") (int .Values.postgres.auth.port) .Values.postgres.auth.database | b64enc }} --- {{- end }} {{- if .Values.postgres.create }} diff --git a/deploy/charts/nebulous/templates/redis.yaml b/deploy/charts/nebulous/templates/redis.yaml index 7430bf5..1e8f8b0 100644 --- a/deploy/charts/nebulous/templates/redis.yaml +++ b/deploy/charts/nebulous/templates/redis.yaml @@ -8,7 +8,7 @@ metadata: {{- include "common.labels" . | nindent 4 }} type: Opaque data: - {{ .Values.redis.secret.keys.connection_string }}: {{ printf "redis://%s:%d/%d" (include "redis.host" .) (int .Values.redis.auth.port) (int .Values.redis.auth.database) | b64enc }} + {{ .Values.redis.secret.keys.connectionString }}: {{ printf "redis://%s:%d/%d" (include "redis.host" .) (int .Values.redis.auth.port) (int .Values.redis.auth.database) | b64enc }} {{ .Values.redis.secret.keys.password}}: {{ .Values.redis.auth.password | b64enc }} --- {{- end }} diff --git a/deploy/charts/nebulous/values.yaml b/deploy/charts/nebulous/values.yaml index 96d4b1a..43cfc6b 100644 --- a/deploy/charts/nebulous/values.yaml +++ b/deploy/charts/nebulous/values.yaml @@ -109,7 +109,7 @@ postgres: name: "postgres-secret" keys: # -- The key in the secret containing the Postgres connection string. - connection_string: "CONNECTION_STRING" + connectionString: "CONNECTION_STRING" # -- Manual configuration of the Postgres connection. Except for 'host', this information is also used if 'create' is true. auth: @@ -143,7 +143,7 @@ redis: name: "redis-secret" keys: # -- The key in the secret containing the Redis connection string. - connection_string: "CONNECTION_STRING" + connectionString: "CONNECTION_STRING" # -- The key in the secret containing the Redis password. password: "PASSWORD" @@ -186,7 +186,7 @@ headscale: dns: # -- The base domain for MagicDNS hostnames. Cannot be the same as the Headscale server's domain. # Refer to https://github.com/juanfont/headscale/blob/main/config-example.yaml for details. - base_domain: "" + baseDomain: "" log: # -- The log level of the Headscale server. Options are "off", "trace", "debug", "info", "warn", "error". From 76663a22fb5ab8a730f9a76466ce1ccb9ea86554 Mon Sep 17 00:00:00 2001 From: Kilian Kluge Date: Thu, 17 Apr 2025 20:10:52 +0200 Subject: [PATCH 11/11] fix: remove headscale API key management from Helm chart --- .../charts/nebulous/templates/headscale.yaml | 76 ++----------------- 1 file changed, 6 insertions(+), 70 deletions(-) diff --git a/deploy/charts/nebulous/templates/headscale.yaml b/deploy/charts/nebulous/templates/headscale.yaml index e220217..e4f7249 100644 --- a/deploy/charts/nebulous/templates/headscale.yaml +++ b/deploy/charts/nebulous/templates/headscale.yaml @@ -162,14 +162,6 @@ spec: name: {{ .Values.headscale.derp.configMap.name }} {{- end }} --- -apiVersion: v1 -kind: ServiceAccount -metadata: - name: headscale-api-key-generator - namespace: {{ include "nebulous.namespace" . }} - labels: - {{- include "common.labels" . | nindent 4 }} ---- apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: @@ -191,7 +183,7 @@ metadata: {{- include "common.labels" . | nindent 4 }} subjects: - kind: ServiceAccount - name: headscale-api-key-generator + name: {{ include "nebulous.serviceAccountName" . }} namespace: {{ include "nebulous.namespace" . }} roleRef: kind: Role @@ -201,87 +193,31 @@ roleRef: apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: - name: secret-writer + name: secret-management namespace: {{ include "nebulous.namespace" . }} labels: {{- include "common.labels" . | nindent 4 }} rules: - apiGroups: [ "" ] resources: [ "secrets" ] - verbs: [ "create", "delete", "get", "list" ] + verbs: [ "create", "delete", "get", "list", "patch", "update" ] --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: - name: allow-secret-creation + name: secret-management namespace: {{ include "nebulous.namespace" . }} labels: {{- include "common.labels" . | nindent 4 }} subjects: - kind: ServiceAccount - name: headscale-api-key-generator + name: {{ include "nebulous.serviceAccountName" . }} namespace: {{ include "nebulous.namespace" . }} roleRef: kind: Role - name: secret-writer + name: secret-management apiGroup: rbac.authorization.k8s.io --- -apiVersion: batch/v1 -kind: Job -metadata: - name: delete-old-tailscale-secret - annotations: - "helm.sh/hook": pre-upgrade - "helm.sh/hook-weight": "-10" -spec: - template: - spec: - restartPolicy: Never - serviceAccountName: headscale-api-key-generator - containers: - - name: delete-secret - image: bitnami/kubectl - command: - - "/bin/sh" - - "-c" - - "kubectl delete secret {{ .Values.tailscale.secret.name }} -n {{ include "nebulous.namespace" . }} --ignore-not-found" ---- -apiVersion: batch/v1 -kind: Job -metadata: - name: generate-tailscale-secret-for-headscale - namespace: {{ include "nebulous.namespace" . }} - labels: - {{- include "common.labels" . | nindent 4 }} - annotations: - "helm.sh/hook": "post-install,post-upgrade" - "helm.sh/hook-weight": "5" -spec: - template: - spec: - serviceAccountName: headscale-api-key-generator - restartPolicy: OnFailure - containers: - - name: api-key-generator - image: bitnami/kubectl - command: [ "/bin/sh", "-c", " - echo 'Waiting for Headscale Pod to be ready...'; - until kubectl get pod -l app={{ include "headscale.name" . }} -n {{ include "headscale.namespace" . }} -o jsonpath='{.items[0].status.phase}' | grep -q Running; do - sleep 1; - done; - POD_NAME=$(kubectl get pod -l app={{ include "headscale.name" . }} -n {{ include "headscale.namespace" . }} -o jsonpath='{.items[0].metadata.name}') - - kubectl exec $POD_NAME -n {{ include "headscale.namespace" . }} -- headscale users create nebu || echo 'User nebu already exists. That is OK.'; - - API_KEY=$(kubectl exec $POD_NAME -n {{ include "headscale.namespace" . }} -- headscale apikeys create --expiration 99y); - AUTH_KEY=$(kubectl exec $POD_NAME -n {{ include "headscale.namespace" . }} -- headscale preauthkeys create --user nebu --reusable); - - kubectl create secret generic {{ .Values.tailscale.secret.name }} -n {{ include "nebulous.namespace" . }} \ - --from-literal={{ .Values.tailscale.secret.keys.apiKey }}=$API_KEY \ - --from-literal={{ .Values.tailscale.secret.keys.authKey }}=$AUTH_KEY \ - --from-literal={{ .Values.tailscale.secret.keys.loginServer }}={{ include "headscale.host" . }}; - " ] ---- apiVersion: v1 kind: Service metadata: