fix: switched headscale to external-service (managed by docker, routed by k8s)

- Changed ports for headscale to prefix "1"
This commit is contained in:
2026-06-09 09:01:44 +02:00
parent d85b3f02f5
commit 22ffd779cc
8 changed files with 151 additions and 402 deletions
+6 -1
View File
@@ -4,6 +4,9 @@ services:
restart: unless-stopped restart: unless-stopped
container_name: headscale-server container_name: headscale-server
command: serve command: serve
ports:
- 18080:8080
- 19090:9090
networks: networks:
- proxy - proxy
volumes: volumes:
@@ -54,7 +57,7 @@ services:
container_name: headplane container_name: headplane
restart: unless-stopped restart: unless-stopped
ports: ports:
- '3000:3000' - '13000:3000'
volumes: volumes:
- ./config/headplane.yaml:/etc/headplane/config.yaml - ./config/headplane.yaml:/etc/headplane/config.yaml
- ./config/headscale.yaml:/etc/headscale/config.yaml - ./config/headscale.yaml:/etc/headscale/config.yaml
@@ -65,6 +68,8 @@ services:
web: web:
image: goodieshq/headscale-admin:latest image: goodieshq/headscale-admin:latest
restart: unless-stopped restart: unless-stopped
ports:
- 10080:80
labels: labels:
- "traefik.enable=true" - "traefik.enable=true"
- "traefik.http.services.headscale-ui.loadbalancer.server.port=80" - "traefik.http.services.headscale-ui.loadbalancer.server.port=80"
+59
View File
@@ -0,0 +1,59 @@
apiVersion: v1
kind: Service
metadata:
name: headscale-server-external
namespace: headscale
spec:
ports:
- port: 8080
targetPort: 18080
name: http
- port: 9090
targetPort: 19090
name: metrics
---
apiVersion: discovery.k8s.io/v1
kind: EndpointSlice
metadata:
name: headscale-server-external
namespace: headscale
labels:
kubernetes.io/service-name: headscale-server-external
addressType: IPv4
ports:
- port: 18080
protocol: TCP
name: http
- port: 19090
protocol: TCP
name: metrics
endpoints:
- addresses:
- "192.168.88.100"
---
apiVersion: v1
kind: Service
metadata:
name: headscale-ui-external
namespace: headscale
spec:
ports:
- port: 80
targetPort: 10080
name: http
---
apiVersion: discovery.k8s.io/v1
kind: EndpointSlice
metadata:
name: headscale-ui-external
namespace: headscale
labels:
kubernetes.io/service-name: headscale-ui-external
addressType: IPv4
ports:
- port: 10080
protocol: TCP
name: http
endpoints:
- addresses:
- "192.168.88.100"
-28
View File
@@ -1,28 +0,0 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: headplane-config
namespace: headscale
data:
config.yaml: |
server:
host: "0.0.0.0"
port: 3000
base_url: https://hs.forust.xyz
cookie_secure: true
cookie_max_age: 86400
data_path: "/var/lib/headplane"
headscale:
url: "http://headscale-service:8080"
config_path: "/etc/headscale/config.yaml"
config_strict: true
integration:
docker:
enabled: true
container_label: "me.tale.headplane.target=headscale"
container_name: "headscale"
socket: "unix:///var/run/docker.sock"
kubernetes:
enabled: false
proc:
enabled: false
-82
View File
@@ -1,82 +0,0 @@
apiVersion: v1
kind: Service
metadata:
name: headplane-service
namespace: headscale
spec:
selector:
app: headplane
ports:
- port: 3000
targetPort: 3000
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: headplane-deployment
namespace: headscale
spec:
replicas: 1
selector:
matchLabels:
app: headplane
template:
metadata:
labels:
app: headplane
spec:
containers:
- name: headplane
image: ghcr.io/tale/headplane:latest
ports:
- containerPort: 3000
resources:
requests:
memory: "128Mi"
cpu: "100m"
limits:
memory: "512Mi"
cpu: "500m"
env:
- name: COOKIE_SECRET
valueFrom:
secretKeyRef:
name: headscale-secrets
key: HEADPLANE_COOKIE_SECRET
- name: CONFIG_PATH
value: "/etc/headplane/config.yaml"
volumeMounts:
- name: config
mountPath: /etc/headplane
- name: headscale-config
mountPath: /etc/headscale
- name: data
mountPath: /var/lib/headplane
- name: docker-sock
mountPath: /var/run/docker.sock
volumes:
- name: config
configMap:
name: headplane-config
- name: headscale-config
configMap:
name: headscale-config
- name: data
persistentVolumeClaim:
claimName: headplane-data-pvc
- name: docker-sock
hostPath:
path: /var/run/docker.sock
type: Socket
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: headplane-data-pvc
namespace: headscale
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
-39
View File
@@ -1,39 +0,0 @@
apiVersion: v1
kind: Service
metadata:
name: headscale-admin-service
namespace: headscale
spec:
selector:
app: headscale-admin
ports:
- port: 80
targetPort: 80
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: headscale-admin-deployment
namespace: headscale
spec:
replicas: 1
selector:
matchLabels:
app: headscale-admin
template:
metadata:
labels:
app: headscale-admin
spec:
containers:
- name: headscale-admin
image: goodieshq/headscale-admin:latest
ports:
- containerPort: 80
resources:
requests:
memory: "64Mi"
cpu: "50m"
limits:
memory: "256Mi"
cpu: "200m"
-79
View File
@@ -1,79 +0,0 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: headscale-config
namespace: headscale
data:
config.yaml: |
server_url: https://hs.forust.xyz
listen_addr: 0.0.0.0:8080
metrics_listen_addr: 0.0.0.0:9090
grpc_listen_addr: 127.0.0.1:50443
grpc_allow_insecure: false
noise:
private_key_path: /var/lib/headscale/noise_private.key
prefixes:
v4: 100.64.0.0/10
v6: fd7a:115c:a1e0::/48
allocation: sequential
derp:
server:
enabled: true
region_id: 999
region_code: "headscale"
region_name: "Headscale Embedded DERP"
stun_listen_addr: "0.0.0.0:3478"
private_key_path: /var/lib/headscale/derp_server_private.key
automatically_add_embedded_derp_region: true
ipv4: 1.2.3.4
ipv6: 2001:db8::1
urls:
- https://controlplane.tailscale.com/derpmap/default
paths: []
auto_update_enabled: true
update_frequency: 24h
disable_check_updates: false
ephemeral_node_inactivity_timeout: 30m
database:
type: sqlite
debug: false
gorm:
prepare_stmt: true
parameterized_queries: true
skip_err_record_not_found: true
slow_threshold: 1000
sqlite:
path: /var/lib/headscale/db.sqlite
write_ahead_log: true
wal_autocheckpoint: 1000
acme_url: https://acme-v02.api.letsencrypt.org/directory
acme_email: ""
tls_letsencrypt_hostname: ""
tls_letsencrypt_cache_dir: /var/lib/headscale/cache
tls_letsencrypt_challenge_type: HTTP-01
tls_letsencrypt_listen: ":http"
tls_cert_path: ""
tls_key_path: ""
log:
format: text
level: info
policy:
mode: database
path: ""
dns:
magic_dns: true
base_domain: example.com
nameservers:
global:
- 1.1.1.1
- 1.0.0.1
- 2606:4700:4700::1111
- 2606:4700:4700::1001
split: {}
search_domains: []
extra_records: []
unix_socket: /var/run/headscale/headscale.sock
unix_socket_permission: "0770"
logtail:
enabled: false
randomize_client_port: false
-84
View File
@@ -1,84 +0,0 @@
apiVersion: v1
kind: Service
metadata:
name: headscale-service
namespace: headscale
spec:
selector:
app: headscale
ports:
- name: http
port: 8080
targetPort: 8080
- name: metrics
port: 9090
targetPort: 9090
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: headscale-deployment
namespace: headscale
spec:
replicas: 1
selector:
matchLabels:
app: headscale
template:
metadata:
labels:
app: headscale
spec:
containers:
- name: headscale
image: headscale/headscale:latest
command: ["serve"]
ports:
- containerPort: 8080
name: http
- containerPort: 9090
name: metrics
resources:
requests:
memory: "256Mi"
cpu: "250m"
limits:
memory: "1Gi"
cpu: "1"
livenessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 30
periodSeconds: 15
timeoutSeconds: 5
readinessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 10
periodSeconds: 10
volumeMounts:
- name: config
mountPath: /etc/headscale
- name: data
mountPath: /var/lib/headscale
volumes:
- name: config
configMap:
name: headscale-config
- name: data
persistentVolumeClaim:
claimName: headscale-data-pvc
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: headscale-data-pvc
namespace: headscale
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 5Gi
+86 -89
View File
@@ -1,56 +1,107 @@
# Headscale main
apiVersion: traefik.io/v1alpha1 apiVersion: traefik.io/v1alpha1
kind: IngressRoute kind: IngressRoute
metadata: metadata:
name: headscale-prod name: headscale-server-prod
namespace: headscale namespace: headscale
spec: spec:
entryPoints: entryPoints:
- websecure - websecure
routes: routes:
- match: Host(`hs.forust.xyz`) - match: Host(`hs.forust.xyz`)
kind: Rule kind: Rule
services: services:
- name: headscale-service - name: headscale-server-external
port: 8080 port: 8080
tls: tls:
certResolver: letsencrypt certResolver: letsencrypt
--- ---
apiVersion: traefik.io/v1alpha1 apiVersion: traefik.io/v1alpha1
kind: IngressRoute kind: IngressRoute
metadata: metadata:
name: headscale-local name: headscale-server-local
namespace: headscale namespace: headscale
spec: spec:
entryPoints: entryPoints:
- websecure - websecure
routes: routes:
- match: Host(`hs.workstation.internal`) - match: Host(`hs.workstation.internal`)
kind: Rule kind: Rule
services: services:
- name: headscale-service - name: headscale-server-external
port: 8080 port: 8080
tls: tls:
secretName: local-tls secretName: local-tls
--- ---
apiVersion: traefik.io/v1alpha1 apiVersion: traefik.io/v1alpha1
kind: IngressRoute kind: IngressRoute
metadata: metadata:
name: headscale-dev name: headscale-server-dev
namespace: headscale namespace: headscale
spec: spec:
entryPoints: entryPoints:
- websecure - websecure
routes: routes:
- match: Host(`hs.gigaforust.internal`) - match: Host(`hs.gigaforust.internal`)
kind: Rule kind: Rule
services: services:
- name: headscale-service - name: headscale-server-external
port: 8080 port: 8080
tls:
secretName: local-tls
---
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: headscale-ui-prod
namespace: headscale
spec:
entryPoints:
- websecure
routes:
- match: Host(`hs.forust.xyz`) && PathPrefix(`/admin`)
kind: Rule
middlewares:
- name: security-chain@file
services:
- name: headscale-ui-external
port: 80
tls:
certResolver: letsencrypt
---
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: headscale-ui-local
namespace: headscale
spec:
entryPoints:
- websecure
routes:
- match: Host(`hs.workstation.internal`) && PathPrefix(`/admin`)
kind: Rule
services:
- name: headscale-ui-external
port: 80
tls:
secretName: local-tls
---
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: headscale-ui-dev
namespace: headscale
spec:
entryPoints:
- websecure
routes:
- match: Host(`hs.gigaforust.internal`) && PathPrefix(`/admin`)
kind: Rule
services:
- name: headscale-ui-external
port: 80
tls: tls:
secretName: local-tls secretName: local-tls
--- ---
# Headscale metrics
apiVersion: traefik.io/v1alpha1 apiVersion: traefik.io/v1alpha1
kind: IngressRoute kind: IngressRoute
metadata: metadata:
@@ -60,11 +111,11 @@ spec:
entryPoints: entryPoints:
- websecure - websecure
routes: routes:
- match: Host(`hs.forust.xyz`) && PathPrefix(`/metrics`) - match: Host(`hs.forust.xyz`) && PathPrefix(`/metrics`)
kind: Rule kind: Rule
services: services:
- name: headscale-service - name: headscale-server-external
port: 9090 port: 9090
tls: tls:
certResolver: letsencrypt certResolver: letsencrypt
--- ---
@@ -77,11 +128,11 @@ spec:
entryPoints: entryPoints:
- websecure - websecure
routes: routes:
- match: Host(`hs.workstation.internal`) && PathPrefix(`/metrics`) - match: Host(`hs.workstation.internal`) && PathPrefix(`/metrics`)
kind: Rule kind: Rule
services: services:
- name: headscale-service - name: headscale-server-external
port: 9090 port: 9090
tls: tls:
secretName: local-tls secretName: local-tls
--- ---
@@ -94,64 +145,10 @@ spec:
entryPoints: entryPoints:
- websecure - websecure
routes: routes:
- match: Host(`hs.gigaforust.internal`) && PathPrefix(`/metrics`) - match: Host(`hs.gigaforust.internal`) && PathPrefix(`/metrics`)
kind: Rule kind: Rule
services: services:
- name: headscale-service - name: headscale-server-external
port: 9090 port: 9090
tls:
secretName: local-tls
---
# Headscale admin UI
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: headscale-admin-prod
namespace: headscale
spec:
entryPoints:
- websecure
routes:
- match: Host(`hs.forust.xyz`) && PathPrefix(`/admin`)
kind: Rule
middlewares:
- name: security-chain@file
services:
- name: headscale-admin-service
port: 80
tls:
certResolver: letsencrypt
---
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: headscale-admin-local
namespace: headscale
spec:
entryPoints:
- websecure
routes:
- match: Host(`hs.workstation.internal`) && PathPrefix(`/admin`)
kind: Rule
services:
- name: headscale-admin-service
port: 80
tls:
secretName: local-tls
---
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: headscale-admin-dev
namespace: headscale
spec:
entryPoints:
- websecure
routes:
- match: Host(`hs.gigaforust.internal`) && PathPrefix(`/admin`)
kind: Rule
services:
- name: headscale-admin-service
port: 80
tls: tls:
secretName: local-tls secretName: local-tls