feat(k8s): add K8s manifests for all homelab services

traefik, gitea, adguard, nextcloud, errorpages, homepages,
uptime-kuma, kener, checkmk, headscale, dockmon, metube,
downtify, portainer, netronome, userbot

Includes Helm values, deployments, services, ingress routes,
configmaps, secrets (placeholders), postgres statefulsets,
kustomize overlays, and Traefik dynamic configuration.
This commit is contained in:
2026-06-08 10:51:04 +02:00
parent f3d04e935c
commit 36922a177c
60 changed files with 2596 additions and 5 deletions
+28
View File
@@ -0,0 +1,28 @@
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
@@ -0,0 +1,82 @@
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
@@ -0,0 +1,39 @@
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
@@ -0,0 +1,79 @@
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
@@ -0,0 +1,84 @@
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
+157
View File
@@ -0,0 +1,157 @@
# Headscale main
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: headscale-prod
namespace: headscale
spec:
entryPoints:
- websecure
routes:
- match: Host(`hs.forust.xyz`)
kind: Rule
services:
- name: headscale-service
port: 8080
tls:
{}
---
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: headscale-local
namespace: headscale
spec:
entryPoints:
- websecure
routes:
- match: Host(`hs.workstation.internal`)
kind: Rule
services:
- name: headscale-service
port: 8080
tls:
secretName: local-tls
---
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: headscale-dev
namespace: headscale
spec:
entryPoints:
- websecure
routes:
- match: Host(`hs.gigaforust.internal`)
kind: Rule
services:
- name: headscale-service
port: 8080
tls:
secretName: local-tls
---
# Headscale metrics
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: headscale-metrics-prod
namespace: headscale
spec:
entryPoints:
- websecure
routes:
- match: Host(`hs.forust.xyz`) && PathPrefix(`/metrics`)
kind: Rule
services:
- name: headscale-service
port: 9090
tls:
{}
---
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: headscale-metrics-local
namespace: headscale
spec:
entryPoints:
- websecure
routes:
- match: Host(`hs.workstation.internal`) && PathPrefix(`/metrics`)
kind: Rule
services:
- name: headscale-service
port: 9090
tls:
secretName: local-tls
---
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: headscale-metrics-dev
namespace: headscale
spec:
entryPoints:
- websecure
routes:
- match: Host(`hs.gigaforust.internal`) && PathPrefix(`/metrics`)
kind: Rule
services:
- name: headscale-service
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:
{}
---
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:
secretName: local-tls
+4
View File
@@ -0,0 +1,4 @@
apiVersion: v1
kind: Namespace
metadata:
name: headscale