feat: add separate headscale for (un-snatted) subnet routing

This commit is contained in:
2025-10-13 15:57:44 +02:00
parent e64ddf76f2
commit 273b9c77d6
6 changed files with 262 additions and 1 deletions
+42
View File
@@ -0,0 +1,42 @@
bases:
- ../envs/environments.yaml.gotmpl
repositories:
- name: headscale
url: https://charts.gabe565.com
commonLabels:
tier: system
releases:
- name: headscale-router
namespace: headscale
chart: headscale/headscale
condition: headscale-router.enabled
values:
- ../values/headscale-router/values/values.yaml
- ../values/headscale-router/values/values-{{ .Environment.Name }}.yaml
postRenderer: ../bin/kustomizer
postRendererArgs:
- ../values/headscale-router/kustomize/{{ .Environment.Name }}
missingFileHandler: Info
- name: manifests
namespace: headscale-system
chart: manifests
condition: headscale-router.enabled
missingFileHandler: Info
values:
- ../values/env.yaml
- ../values/env-{{ requiredEnv "ARGOCD_ENV_CLUSTER_NAME" }}.yaml
- ../values/headscale-router/env.yaml.gotmpl
- ../values/headscale-router/env-{{ requiredEnv "ARGOCD_ENV_CLUSTER_NAME" }}.yaml.gotmpl
hooks:
- events: [ prepare, cleanup ]
showlogs: true
command: ../bin/helmify
args:
- '{{`{{ if eq .Event.Name "prepare" }}build{{ else }}clean{{ end }}`}}'
- '{{`{{ .Release.Chart }}`}}'
- '{{`{{ .Environment.Name }}`}}'
- ../values/headscale-router/manifests
- manifests
@@ -0,0 +1,3 @@
headscale-router:
enabled: true
+4
View File
@@ -0,0 +1,4 @@
headscale-router:
enabled: false
autosync: false
@@ -0,0 +1,42 @@
{{- if .Values.clusterConfig.argo.enabled }}
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: headscale-router
namespace: argocd
annotations:
argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true
finalizers:
- resources-finalizer.argocd.argoproj.io
spec:
destination:
namespace: headscale
server: 'https://kubernetes.default.svc'
sources:
- repoURL: {{ .Values.clusterConfig.manifests }}
targetRevision: HEAD
path: helmfile.d
plugin:
name: helmfile-cmp
env:
- name: CLUSTER_NAME
value: {{ .Values.clusterConfig.cluster }}
- name: HELMFILE_ENVIRONMENT
value: default
- name: HELMFILE_FILE_PATH
value: headscale-router.yaml.gotmpl
project: sys
syncPolicy:
managedNamespaceMetadata:
labels:
component: sys
syncOptions:
- CreateNamespace=true
- ApplyOutOfSyncOnly=true
# - ServerSideApply=true
{{- if .Values.headscale-router.autosync }}
automated:
prune: true
# selfHeal: false
{{- end }}
{{- end }}
+171
View File
@@ -0,0 +1,171 @@
image:
repository: ghcr.io/juanfont/headscale
pullPolicy: IfNotPresent
tag: v0.26.1
args: [ "serve" ]
env:
HEADSCALE_DNS_BASE_DOMAIN: "relay.obx"
# HACK: Workaround for fortigate block of WG udp port
HEADSCALE_RANDOMIZE_CLIENT_PORT: "true"
HEADSCALE_OIDC_ONLY_START_IF_OIDC_IS_AVAILABLE: "true"
HEADSCALE_OIDC_ISSUER: "https://login.microsoftonline.com/3f737008-e9a0-4485-9d27-40329d288089/v2.0"
HEADSCALE_OIDC_CLIENT_ID: "688e9096-f140-4498-a46a-e3d1939184de"
HEADSCALE_OIDC_CLIENT_SECRET: "dPW8Q~1rctY-D0Ih.A1-1KqLl0uj1rX_ixNTcbrh"
# -- Split DNS for obx and ts.obx
HEADSCALE_DNS_NAMESERVERS_SPLIT: |
{
"obx": [ "10.255.241.210" ]
}
# -- Node IPv4 prefixes
HEADSCALE_PREFIXES_V4: "100.64.0.0/10"
# -- Node IPv6 prefixes
HEADSCALE_PREFIXES_V6: "fd7a:115c:a1e0::/48"
# -- Whether to use [MagicDNS](https://tailscale.com/kb/1081/magicdns/).
HEADSCALE_DNS_MAGIC_DNS: "true"
# -- List of DNS servers to expose to clients.
HEADSCALE_DNS_NAMESERVERS_GLOBAL: "1.1.1.1 1.0.0.1"
HEADSCALE_DERP_URLS: "https://controlplane.tailscale.com/derpmap/default"
HEADSCALE_DERP_AUTO_UPDATE_ENABLED: "true"
HEADSCALE_DERP_UPDATE_FREQUENCY: "24h"
HEADSCALE_EPHEMERAL_NODE_INACTIVITY_TIMEOUT: "30m"
ingress:
main:
enabled: true
className: "nginx"
annotations:
cert-manager.io/cluster-issuer: letsencrypt-production
nginx.ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/backend-protocol: HTTP
hosts:
- host: headscale-router.adm.oceanbox.io
paths:
- path: /
tls:
- secretName: headscale-router-tls
hosts:
- headscale-router.adm.oceanbox.io
persistence:
config:
enabled: true
mountPath: /etc/headscale
retain: true
# storageClass: ""
# accessMode: ReadWriteOnce
# size: 1Gi
# -- Enable and configure postgresql database subchart under this key.
# @default -- See [values.yaml](./values.yaml)
postgresql:
enabled: false
auth:
database: headscale
postgresPassword: changeme
primary:
persistence:
enabled: false
# storageClass: ""
# size: 8Gi
serviceMonitor:
main:
# -- Enables or disables the serviceMonitor.
enabled: true
# -- Configures the endpoints for the serviceMonitor.
# @default -- See [values.yaml](./values.yaml)
endpoints:
- port: metrics
scheme: http
path: /metrics
interval: 30s
scrapeTimeout: 10s
configMaps:
acl:
enabled: true
data:
policy: |
{
"groups": {
"group:admin": [
"jonas.juselius@oceanbox.io",
"Moritz.Jorg@oceanbox.io",
"simen.kirkvik@oceanbox.io",
"stig.r.jensen@oceanbox.io",
],
},
"tagOwners": {
"tag:k8s": [ "group:admin" ],
"tag:hpc": [ "group:admin" ],
"tag:tos-relay": [ "group:admin" ],
"tag:vtn-relay": [ "group:admin" ],
"tag:mumindalen": [ "group:admin" ],
"tag:ekman": [ "group:admin" ],
"tag:rossby": [ "group:admin" ],
},
// hosts should be defined using its IP addresses and a subnet mask.
// to define a single host, use a /32 mask. You cannot use DNS entries here,
// as they're prone to be hijacked by replacing their IP addresses.
// see https://github.com/tailscale/tailscale/issues/3800 for more information.
"hosts": {
"ingress.ekman.tos": "10.255.241.99/32",
"ingress.ceph.tos": "10.255.241.10/32",
"ingress.ceph.vtn": "172.16.239.50/32",
"ingress.adm.ceph.vtn": "172.16.239.51/32",
"ingress.oceanbox.tos": "10.255.241.11/32",
"manage.ekman.tos": "10.255.241.99/32",
"k8s.oceanbox.tos": "10.255.241.200/32",
"k8s.ekman.tos": "10.255.241.99/32",
"k8s.ceph.tos": "10.255.241.29/32",
"printer.office.tos": "10.132.46.108/32",
"net.office.tos": "10.132.46.0/24",
"net.dc.tos": "10.255.241.0/24",
"net.100gbe.tos": "10.255.244.0/24",
"net.mgmt.tos": "10.255.240.0/24",
"net.dc.vtn": "172.16.239.0/24",
"net.mgmt.vtn": "172.16.238.0/24",
},
"acls": [
{
"action": "accept",
"src": [ "tag:tos-relay", "net.dc.tos" ],
"dst": [
"tag:vtn-relay:*",
"net.dc.vtn:*",
]
},
{
"action": "accept",
"src": [ "tag:vtn-relay", "net.dc.vtn" ],
"dst": [
"tag:tos-relay:*",
"net.dc.tos:*",
]
},
]
}
dns:
enabled: true
data:
records: |
[
{ "name": "auth.oceanbox.io", "type": "A", "value": "10.255.241.11" },
{ "name": "auth.adm.oceanbox.io", "type": "A", "value": "10.255.241.11" },
{ "name": "keycloak.adm.oceanbox.io", "type": "A", "value": "10.255.241.11" },
{ "name": "grafana.adm.oceanbox.io", "type": "A", "value": "10.255.241.11" },
{ "name": "prometheus.adm.oceanbox.io", "type": "A", "value": "10.255.241.11" },
{ "name": "alertmanager.adm.oceanbox.io", "type": "A", "value": "10.255.241.11" },
{ "name": "argocd.adm.oceanbox.io", "type": "A", "value": "10.255.241.11" },
{ "name": "hubble.adm.oceanbox.io", "type": "A", "value": "10.255.241.11" },
{ "name": "plausible.adm.oceanbox.io", "type": "A", "value": "10.255.241.11" },
{ "name": "dapr.adm.oceanbox.io", "type": "A", "value": "10.255.241.11" },
]
@@ -1,3 +1,2 @@
headscale:
enabled: true