Import manifests reverse-engineered from live cluster
Captured 2026-07-26 from rpi-master (k3s v1.30.3) and cleaned of runtime fields. Six apps as per-app kustomizations: vaultwarden, searxng, home-assistant, nginx, pihole(+unbound), unified-streaming. Intentional divergences from live state: - pihole WEBPASSWORD and USP_LICENSE_KEY moved from inline plaintext env to secretKeyRef (secrets gitignored; templates in secret.example.yaml) - HA ingress defaultBackend fixed (pointed at nonexistent service) - unifiedstreaming-svc kept as ClusterIP (LoadBalancer could never bind port 80 behind svclb-traefik) Validated against the live cluster with kubectl apply --dry-run=server: no immutable-field conflicts; one-time kubectl replace procedure for the two env->secretKeyRef migrations documented in README. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,74 @@
|
||||
# Originally installed via helm chart home-assistant-13.3.0 (release record no
|
||||
# longer in cluster); managed as a raw manifest since. Selector labels are
|
||||
# immutable — do not change them.
|
||||
# NOTE: /config/configuration.yaml (on the PV, not in git) must keep
|
||||
# http.trusted_proxies: [10.42.0.0/16] so traefik can reach HA from any node.
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: home-assistant
|
||||
namespace: home-assistant
|
||||
labels:
|
||||
app.kubernetes.io/instance: home-assistant
|
||||
app.kubernetes.io/name: home-assistant
|
||||
spec:
|
||||
replicas: 1
|
||||
revisionHistoryLimit: 3
|
||||
selector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/instance: home-assistant
|
||||
app.kubernetes.io/name: home-assistant
|
||||
strategy:
|
||||
type: Recreate
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app.kubernetes.io/instance: home-assistant
|
||||
app.kubernetes.io/name: home-assistant
|
||||
spec:
|
||||
affinity:
|
||||
nodeAffinity:
|
||||
requiredDuringSchedulingIgnoredDuringExecution:
|
||||
nodeSelectorTerms:
|
||||
- matchExpressions:
|
||||
- key: cpu
|
||||
operator: In
|
||||
values:
|
||||
- arm
|
||||
- key: controller
|
||||
operator: NotIn
|
||||
values:
|
||||
- "true"
|
||||
containers:
|
||||
- name: home-assistant
|
||||
image: ghcr.io/home-assistant/home-assistant:stable
|
||||
imagePullPolicy: Always
|
||||
env:
|
||||
- name: TZ
|
||||
value: UTC
|
||||
ports:
|
||||
- name: http
|
||||
containerPort: 8123
|
||||
protocol: TCP
|
||||
startupProbe:
|
||||
tcpSocket:
|
||||
port: 8123
|
||||
failureThreshold: 30
|
||||
periodSeconds: 5
|
||||
livenessProbe:
|
||||
tcpSocket:
|
||||
port: 8123
|
||||
failureThreshold: 3
|
||||
periodSeconds: 10
|
||||
readinessProbe:
|
||||
tcpSocket:
|
||||
port: 8123
|
||||
failureThreshold: 3
|
||||
periodSeconds: 10
|
||||
volumeMounts:
|
||||
- name: config
|
||||
mountPath: /config
|
||||
volumes:
|
||||
- name: config
|
||||
persistentVolumeClaim:
|
||||
claimName: home-assistant
|
||||
@@ -0,0 +1,37 @@
|
||||
# NOTE: the live object's defaultBackend pointed at a service named
|
||||
# "home-assistant", which does not exist (the real service is
|
||||
# "home-assistant-svc"). Fixed here — this is the one intentional divergence
|
||||
# from the cluster state captured 2026-07-26.
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: home-assistant
|
||||
namespace: home-assistant
|
||||
spec:
|
||||
ingressClassName: traefik
|
||||
defaultBackend:
|
||||
service:
|
||||
name: home-assistant-svc
|
||||
port:
|
||||
number: 80
|
||||
rules:
|
||||
- host: ha.wittyoneoff.com
|
||||
http:
|
||||
paths:
|
||||
- path: /
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: home-assistant-svc
|
||||
port:
|
||||
number: 80
|
||||
- host: ha-origin.wittyoneoff.com
|
||||
http:
|
||||
paths:
|
||||
- path: /
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: home-assistant-svc
|
||||
port:
|
||||
number: 80
|
||||
@@ -0,0 +1,8 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
resources:
|
||||
- namespace.yaml
|
||||
- storage.yaml
|
||||
- deployment.yaml
|
||||
- service.yaml
|
||||
- ingress.yaml
|
||||
@@ -0,0 +1,4 @@
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: home-assistant
|
||||
@@ -0,0 +1,15 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: home-assistant-svc
|
||||
namespace: home-assistant
|
||||
spec:
|
||||
type: ClusterIP
|
||||
selector:
|
||||
app.kubernetes.io/instance: home-assistant
|
||||
app.kubernetes.io/name: home-assistant
|
||||
ports:
|
||||
- name: http
|
||||
port: 80
|
||||
targetPort: 8123
|
||||
protocol: TCP
|
||||
@@ -0,0 +1,30 @@
|
||||
# /config lives on GlusterFS (/mnt/gvolume0 mounted on every node).
|
||||
# Known risk: HA recorder DB on gluster + non-atomic renames → occasional
|
||||
# .storage write errors. See homelab notes.
|
||||
apiVersion: v1
|
||||
kind: PersistentVolume
|
||||
metadata:
|
||||
name: home-assistant-pv
|
||||
spec:
|
||||
capacity:
|
||||
storage: 10Gi
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
persistentVolumeReclaimPolicy: Retain
|
||||
volumeMode: Filesystem
|
||||
hostPath:
|
||||
path: /mnt/gvolume0/home-assistant
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: home-assistant
|
||||
namespace: home-assistant
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
resources:
|
||||
requests:
|
||||
storage: 10Gi
|
||||
storageClassName: ""
|
||||
volumeName: home-assistant-pv
|
||||
@@ -0,0 +1,59 @@
|
||||
# Created via Rancher originally — the workload.user.cattle.io selector label
|
||||
# is immutable on the live object; do not change it.
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: nginx
|
||||
namespace: nginx
|
||||
labels:
|
||||
workload.user.cattle.io/workloadselector: apps.deployment-nginx-nginx
|
||||
spec:
|
||||
replicas: 3
|
||||
selector:
|
||||
matchLabels:
|
||||
workload.user.cattle.io/workloadselector: apps.deployment-nginx-nginx
|
||||
strategy:
|
||||
type: RollingUpdate
|
||||
rollingUpdate:
|
||||
maxSurge: 25%
|
||||
maxUnavailable: 25%
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
workload.user.cattle.io/workloadselector: apps.deployment-nginx-nginx
|
||||
spec:
|
||||
affinity:
|
||||
nodeAffinity:
|
||||
requiredDuringSchedulingIgnoredDuringExecution:
|
||||
nodeSelectorTerms:
|
||||
- matchExpressions:
|
||||
- key: cpu
|
||||
operator: In
|
||||
values:
|
||||
- arm
|
||||
- key: controller
|
||||
operator: NotIn
|
||||
values:
|
||||
- "true"
|
||||
containers:
|
||||
- name: nginx
|
||||
image: nginx:latest
|
||||
imagePullPolicy: Always
|
||||
ports:
|
||||
- name: http
|
||||
containerPort: 80
|
||||
protocol: TCP
|
||||
volumeMounts:
|
||||
- name: vol-vnbxq
|
||||
mountPath: /usr/share/nginx/html
|
||||
subPath: www
|
||||
- name: vol-vnbxq
|
||||
mountPath: /etc/nginx/conf
|
||||
subPath: conf
|
||||
- name: vol-vnbxq
|
||||
mountPath: /etc/nginx/conf.d
|
||||
subPath: conf.d
|
||||
volumes:
|
||||
- name: vol-vnbxq
|
||||
persistentVolumeClaim:
|
||||
claimName: nginx
|
||||
@@ -0,0 +1,28 @@
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: nginx
|
||||
namespace: nginx
|
||||
spec:
|
||||
ingressClassName: traefik
|
||||
rules:
|
||||
- host: www.wittyoneoff.com
|
||||
http:
|
||||
paths:
|
||||
- path: /
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: nginx
|
||||
port:
|
||||
number: 80
|
||||
- host: www.ramonaajj.com
|
||||
http:
|
||||
paths:
|
||||
- path: /
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: nginx
|
||||
port:
|
||||
number: 80
|
||||
@@ -0,0 +1,8 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
resources:
|
||||
- namespace.yaml
|
||||
- storage.yaml
|
||||
- deployment.yaml
|
||||
- service.yaml
|
||||
- ingress.yaml
|
||||
@@ -0,0 +1,4 @@
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: nginx
|
||||
@@ -0,0 +1,14 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: nginx
|
||||
namespace: nginx
|
||||
spec:
|
||||
type: ClusterIP
|
||||
selector:
|
||||
workload.user.cattle.io/workloadselector: apps.deployment-nginx-nginx
|
||||
ports:
|
||||
- name: http
|
||||
port: 80
|
||||
targetPort: 80
|
||||
protocol: TCP
|
||||
@@ -0,0 +1,35 @@
|
||||
# Static site content + nginx config live on GlusterFS:
|
||||
# /mnt/gvolume0/nginx/www → /usr/share/nginx/html
|
||||
# /mnt/gvolume0/nginx/conf → /etc/nginx/conf
|
||||
# /mnt/gvolume0/nginx/conf.d → /etc/nginx/conf.d
|
||||
apiVersion: v1
|
||||
kind: PersistentVolume
|
||||
metadata:
|
||||
name: nginx-gvolume0
|
||||
spec:
|
||||
capacity:
|
||||
storage: 50Gi
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
- ReadOnlyMany
|
||||
- ReadWriteMany
|
||||
persistentVolumeReclaimPolicy: Retain
|
||||
volumeMode: Filesystem
|
||||
hostPath:
|
||||
path: /mnt/gvolume0/nginx
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: nginx
|
||||
namespace: nginx
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
- ReadOnlyMany
|
||||
- ReadWriteMany
|
||||
resources:
|
||||
requests:
|
||||
storage: 50Gi
|
||||
storageClassName: ""
|
||||
volumeName: nginx-gvolume0
|
||||
@@ -0,0 +1,86 @@
|
||||
# DIVERGENCE from live state (intentional): the live deployment has WEBPASSWORD
|
||||
# as a plaintext env value. Here it comes from the `pihole-admin` secret —
|
||||
# create it (see secret.example.yaml) BEFORE applying this, or the pod will
|
||||
# fail with CreateContainerConfigError.
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: pihole
|
||||
namespace: pihole
|
||||
labels:
|
||||
app: pihole
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: pihole
|
||||
strategy:
|
||||
type: RollingUpdate
|
||||
rollingUpdate:
|
||||
maxSurge: 0
|
||||
maxUnavailable: 1
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: pihole
|
||||
spec:
|
||||
affinity:
|
||||
nodeAffinity:
|
||||
preferredDuringSchedulingIgnoredDuringExecution:
|
||||
- weight: 1
|
||||
preference:
|
||||
matchExpressions:
|
||||
- key: cpu
|
||||
operator: In
|
||||
values:
|
||||
- arm
|
||||
- key: model
|
||||
operator: In
|
||||
values:
|
||||
- raspi
|
||||
containers:
|
||||
- name: pihole
|
||||
image: pihole/pihole:latest
|
||||
imagePullPolicy: IfNotPresent
|
||||
env:
|
||||
- name: TZ
|
||||
value: America/Los_Angeles
|
||||
- name: WEBPASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: pihole-admin
|
||||
key: WEBPASSWORD
|
||||
- name: PIHOLE_UID
|
||||
value: "0"
|
||||
ports:
|
||||
- containerPort: 53
|
||||
protocol: TCP
|
||||
- containerPort: 53
|
||||
protocol: UDP
|
||||
- containerPort: 67
|
||||
protocol: UDP
|
||||
- containerPort: 80
|
||||
protocol: TCP
|
||||
- containerPort: 443
|
||||
protocol: TCP
|
||||
resources:
|
||||
requests:
|
||||
cpu: 100m
|
||||
memory: 128Mi
|
||||
limits:
|
||||
cpu: "1"
|
||||
memory: 2Gi
|
||||
securityContext:
|
||||
privileged: true
|
||||
volumeMounts:
|
||||
- name: gv-pihole
|
||||
mountPath: /etc/pihole
|
||||
- name: gv-pihole-dnsmasq-volume
|
||||
mountPath: /etc/dnsmasq.d
|
||||
volumes:
|
||||
- name: gv-pihole
|
||||
persistentVolumeClaim:
|
||||
claimName: pihole-gvolume0
|
||||
- name: gv-pihole-dnsmasq-volume
|
||||
persistentVolumeClaim:
|
||||
claimName: pihole-dnsmasq-volume
|
||||
@@ -0,0 +1,54 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: unbound
|
||||
namespace: pihole
|
||||
labels:
|
||||
app: unbound
|
||||
spec:
|
||||
replicas: 3
|
||||
selector:
|
||||
matchLabels:
|
||||
app: unbound
|
||||
strategy:
|
||||
type: RollingUpdate
|
||||
rollingUpdate:
|
||||
maxSurge: 25%
|
||||
maxUnavailable: 25%
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: unbound
|
||||
spec:
|
||||
affinity:
|
||||
nodeAffinity:
|
||||
preferredDuringSchedulingIgnoredDuringExecution:
|
||||
- weight: 1
|
||||
preference:
|
||||
matchExpressions:
|
||||
- key: cpu
|
||||
operator: In
|
||||
values:
|
||||
- arm
|
||||
- key: model
|
||||
operator: In
|
||||
values:
|
||||
- raspi
|
||||
containers:
|
||||
- name: unbound
|
||||
image: docker.io/mvance/unbound-rpi:latest
|
||||
imagePullPolicy: Always
|
||||
ports:
|
||||
- name: svc-53-udp
|
||||
containerPort: 53
|
||||
protocol: UDP
|
||||
- name: svc-53-tcp
|
||||
containerPort: 53
|
||||
protocol: TCP
|
||||
resources:
|
||||
requests:
|
||||
cpu: 250m
|
||||
memory: 50Mi
|
||||
limits:
|
||||
cpu: "1"
|
||||
memory: 1Gi
|
||||
@@ -0,0 +1,10 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
# secret.example.yaml is intentionally NOT listed — copy it to secret.yaml
|
||||
# (gitignored) and apply manually once per cluster.
|
||||
resources:
|
||||
- namespace.yaml
|
||||
- storage.yaml
|
||||
- deployment-pihole.yaml
|
||||
- deployment-unbound.yaml
|
||||
- service.yaml
|
||||
@@ -0,0 +1,4 @@
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: pihole
|
||||
@@ -0,0 +1,13 @@
|
||||
# Copy to secret.yaml (gitignored), set the real admin password, apply once:
|
||||
# kubectl apply -f secret.yaml
|
||||
# Or create directly without a file:
|
||||
# kubectl create secret generic pihole-admin -n pihole \
|
||||
# --from-literal=WEBPASSWORD='...'
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: pihole-admin
|
||||
namespace: pihole
|
||||
type: Opaque
|
||||
stringData:
|
||||
WEBPASSWORD: CHANGE-ME
|
||||
@@ -0,0 +1,53 @@
|
||||
# pihole-svc is type LoadBalancer → k3s klipper-lb (svclb) binds host ports
|
||||
# 8000/53/67 on the nodes it schedules on. NodePorts are pinned so they
|
||||
# survive re-creation.
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: pihole-svc
|
||||
namespace: pihole
|
||||
spec:
|
||||
type: LoadBalancer
|
||||
externalTrafficPolicy: Cluster
|
||||
selector:
|
||||
app: pihole
|
||||
ports:
|
||||
- name: http-admin
|
||||
port: 8000
|
||||
targetPort: 80
|
||||
nodePort: 31120
|
||||
protocol: TCP
|
||||
- name: tcp-53
|
||||
port: 53
|
||||
targetPort: 53
|
||||
nodePort: 32580
|
||||
protocol: TCP
|
||||
- name: udp-53
|
||||
port: 53
|
||||
targetPort: 53
|
||||
nodePort: 31281
|
||||
protocol: UDP
|
||||
- name: udp-67
|
||||
port: 67
|
||||
targetPort: 67
|
||||
nodePort: 31025
|
||||
protocol: UDP
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: unbound-service
|
||||
namespace: pihole
|
||||
spec:
|
||||
type: ClusterIP
|
||||
selector:
|
||||
app: unbound
|
||||
ports:
|
||||
- name: udp-53
|
||||
port: 53
|
||||
targetPort: 53
|
||||
protocol: UDP
|
||||
- name: tcp-53
|
||||
port: 53
|
||||
targetPort: 53
|
||||
protocol: TCP
|
||||
@@ -0,0 +1,55 @@
|
||||
apiVersion: v1
|
||||
kind: PersistentVolume
|
||||
metadata:
|
||||
name: pihole-gvolume0-pv
|
||||
spec:
|
||||
capacity:
|
||||
storage: 10Gi
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
persistentVolumeReclaimPolicy: Retain
|
||||
volumeMode: Filesystem
|
||||
hostPath:
|
||||
path: /mnt/gvolume0/pihole
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: PersistentVolume
|
||||
metadata:
|
||||
name: pihole-dnsmasq-volume-pv
|
||||
spec:
|
||||
capacity:
|
||||
storage: 10Gi
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
persistentVolumeReclaimPolicy: Retain
|
||||
volumeMode: Filesystem
|
||||
hostPath:
|
||||
path: /mnt/gvolume0/pihole-dnsmasq-volume
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: pihole-gvolume0
|
||||
namespace: pihole
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
resources:
|
||||
requests:
|
||||
storage: 10Gi
|
||||
storageClassName: ""
|
||||
volumeName: pihole-gvolume0-pv
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: pihole-dnsmasq-volume
|
||||
namespace: pihole
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
resources:
|
||||
requests:
|
||||
storage: 10Gi
|
||||
storageClassName: ""
|
||||
volumeName: pihole-dnsmasq-volume-pv
|
||||
@@ -0,0 +1,78 @@
|
||||
# Helm release searxng-1723974683 (chart searxng-1.0.0) in the *default*
|
||||
# namespace — the release is still recorded in the cluster, so if you ever
|
||||
# `helm upgrade` it, helm and this manifest will fight. Prefer retiring the
|
||||
# helm release (helm delete --no-hooks would delete resources; instead just
|
||||
# treat this repo as the source of truth and never run helm against it).
|
||||
# Names keep the timestamped release suffix because selectors are immutable.
|
||||
# NOTE (faithful to live state): TZ value "America/Los Angeles" is missing the
|
||||
# underscore — an invalid tzdata name, so searxng falls back to UTC. Kept as-is;
|
||||
# fix to America/Los_Angeles when convenient.
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: searxng-1723974683
|
||||
namespace: default
|
||||
labels:
|
||||
app.kubernetes.io/instance: searxng-1723974683
|
||||
app.kubernetes.io/name: searxng
|
||||
spec:
|
||||
replicas: 1
|
||||
revisionHistoryLimit: 3
|
||||
selector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/instance: searxng-1723974683
|
||||
app.kubernetes.io/name: searxng
|
||||
strategy:
|
||||
type: RollingUpdate
|
||||
rollingUpdate:
|
||||
maxSurge: 25%
|
||||
maxUnavailable: 25%
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app.kubernetes.io/instance: searxng-1723974683
|
||||
app.kubernetes.io/name: searxng
|
||||
spec:
|
||||
containers:
|
||||
- name: searxng-1723974683
|
||||
image: searxng/searxng:latest
|
||||
imagePullPolicy: Always
|
||||
env:
|
||||
- name: AUTOCOMPLETE
|
||||
value: google
|
||||
- name: BASE_URL
|
||||
value: http://searxng.wittyoneoff.com/
|
||||
- name: INSTANCE_NAME
|
||||
value: witty-one-off-searxng
|
||||
- name: TZ
|
||||
value: America/Los Angeles
|
||||
ports:
|
||||
- name: http
|
||||
containerPort: 8080
|
||||
protocol: TCP
|
||||
startupProbe:
|
||||
httpGet:
|
||||
path: /healthz
|
||||
port: 8080
|
||||
failureThreshold: 30
|
||||
periodSeconds: 5
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /healthz
|
||||
port: 8080
|
||||
failureThreshold: 3
|
||||
periodSeconds: 10
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /healthz
|
||||
port: 8080
|
||||
failureThreshold: 3
|
||||
periodSeconds: 10
|
||||
volumeMounts:
|
||||
- name: searxng-config
|
||||
mountPath: /etc/searxng/settings.yml
|
||||
subPath: settings.yml
|
||||
volumes:
|
||||
- name: searxng-config
|
||||
secret:
|
||||
secretName: searxng-1723974683-config
|
||||
@@ -0,0 +1,33 @@
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: searxng-ingress
|
||||
namespace: default
|
||||
spec:
|
||||
ingressClassName: traefik
|
||||
defaultBackend:
|
||||
service:
|
||||
name: searxng-1723974683
|
||||
port:
|
||||
number: 8080
|
||||
rules:
|
||||
- host: searxng.wittyoneoff.com
|
||||
http:
|
||||
paths:
|
||||
- path: /
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: searxng-1723974683
|
||||
port:
|
||||
number: 8080
|
||||
- host: origin-searxng.wittyoneoff.com
|
||||
http:
|
||||
paths:
|
||||
- path: /
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: searxng-1723974683
|
||||
port:
|
||||
number: 8080
|
||||
@@ -0,0 +1,8 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
# secret.example.yaml is intentionally NOT listed — copy it to secret.yaml
|
||||
# (gitignored) and apply manually once per cluster.
|
||||
resources:
|
||||
- deployment.yaml
|
||||
- service.yaml
|
||||
- ingress.yaml
|
||||
@@ -0,0 +1,14 @@
|
||||
# Copy to secret.yaml (gitignored), set a real secret_key, and apply once:
|
||||
# kubectl apply -f secret.yaml
|
||||
# The secret already exists in the cluster; this file only documents its shape.
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: searxng-1723974683-config
|
||||
namespace: default
|
||||
type: Opaque
|
||||
stringData:
|
||||
settings.yml: |
|
||||
server:
|
||||
secret_key: CHANGE-ME
|
||||
use_default_settings: true
|
||||
@@ -0,0 +1,18 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: searxng-1723974683
|
||||
namespace: default
|
||||
labels:
|
||||
app.kubernetes.io/instance: searxng-1723974683
|
||||
app.kubernetes.io/name: searxng
|
||||
spec:
|
||||
type: ClusterIP
|
||||
selector:
|
||||
app.kubernetes.io/instance: searxng-1723974683
|
||||
app.kubernetes.io/name: searxng
|
||||
ports:
|
||||
- name: http
|
||||
port: 8080
|
||||
targetPort: http
|
||||
protocol: TCP
|
||||
@@ -0,0 +1,69 @@
|
||||
# DIVERGENCE from live state (intentional): the live deployment has
|
||||
# USP_LICENSE_KEY as a plaintext env value. Here it comes from the
|
||||
# `usp-license` secret — create it (see secret.example.yaml) BEFORE applying
|
||||
# this. The Rancher-era selector label is immutable; do not change it.
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: unifiedstreaming
|
||||
namespace: unified-streaming
|
||||
labels:
|
||||
workload.user.cattle.io/workloadselector: apps.deployment-unified-streaming-unifiedstreaming
|
||||
spec:
|
||||
replicas: 3
|
||||
selector:
|
||||
matchLabels:
|
||||
workload.user.cattle.io/workloadselector: apps.deployment-unified-streaming-unifiedstreaming
|
||||
strategy:
|
||||
type: RollingUpdate
|
||||
rollingUpdate:
|
||||
maxSurge: 25%
|
||||
maxUnavailable: 25%
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: unifiedstreaming
|
||||
workload.user.cattle.io/workloadselector: apps.deployment-unified-streaming-unifiedstreaming
|
||||
spec:
|
||||
affinity:
|
||||
nodeAffinity:
|
||||
requiredDuringSchedulingIgnoredDuringExecution:
|
||||
nodeSelectorTerms:
|
||||
- matchExpressions:
|
||||
- key: cpu
|
||||
operator: In
|
||||
values:
|
||||
- arm
|
||||
- key: controller
|
||||
operator: NotIn
|
||||
values:
|
||||
- "true"
|
||||
containers:
|
||||
- name: unifiedstreaming
|
||||
image: unifiedstreaming/origin:latest
|
||||
imagePullPolicy: Always
|
||||
env:
|
||||
- name: USP_LICENSE_KEY
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: usp-license
|
||||
key: USP_LICENSE_KEY
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /
|
||||
port: 80
|
||||
failureThreshold: 3
|
||||
periodSeconds: 10
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /
|
||||
port: 80
|
||||
failureThreshold: 3
|
||||
periodSeconds: 10
|
||||
volumeMounts:
|
||||
- name: vol-apn2a
|
||||
mountPath: /var/www/unified-origin
|
||||
volumes:
|
||||
- name: vol-apn2a
|
||||
persistentVolumeClaim:
|
||||
claimName: unified-streaming-pvc
|
||||
@@ -0,0 +1,18 @@
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: unified-streaming-ing
|
||||
namespace: unified-streaming
|
||||
spec:
|
||||
ingressClassName: traefik
|
||||
rules:
|
||||
- host: unified.wittyoneoff.com
|
||||
http:
|
||||
paths:
|
||||
- path: /
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: unifiedstreaming-svc
|
||||
port:
|
||||
number: 80
|
||||
@@ -0,0 +1,10 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
# secret.example.yaml is intentionally NOT listed — copy it to secret.yaml
|
||||
# (gitignored) and apply manually once per cluster.
|
||||
resources:
|
||||
- namespace.yaml
|
||||
- storage.yaml
|
||||
- deployment.yaml
|
||||
- service.yaml
|
||||
- ingress.yaml
|
||||
@@ -0,0 +1,4 @@
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: unified-streaming
|
||||
@@ -0,0 +1,16 @@
|
||||
# Copy to secret.yaml (gitignored), paste the real USP license key, apply once:
|
||||
# kubectl apply -f secret.yaml
|
||||
# Or create directly:
|
||||
# kubectl create secret generic usp-license -n unified-streaming \
|
||||
# --from-literal=USP_LICENSE_KEY='<base64-looking license blob>'
|
||||
# The current key can be read from the live deployment:
|
||||
# kubectl get deploy -n unified-streaming unifiedstreaming \
|
||||
# -o jsonpath='{.spec.template.spec.containers[0].env[?(@.name=="USP_LICENSE_KEY")].value}'
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: usp-license
|
||||
namespace: unified-streaming
|
||||
type: Opaque
|
||||
stringData:
|
||||
USP_LICENSE_KEY: CHANGE-ME
|
||||
@@ -0,0 +1,18 @@
|
||||
# ClusterIP on purpose: this was type LoadBalancer for ~2 years, but klipper-lb
|
||||
# can never bind host port 80 (svclb-traefik owns it on every node), so the
|
||||
# svclb pods sat Pending forever. Traffic flows through the ingress. Changed
|
||||
# to ClusterIP 2026-07-26.
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: unifiedstreaming-svc
|
||||
namespace: unified-streaming
|
||||
spec:
|
||||
type: ClusterIP
|
||||
selector:
|
||||
app: unifiedstreaming
|
||||
ports:
|
||||
- name: http
|
||||
port: 80
|
||||
targetPort: 80
|
||||
protocol: TCP
|
||||
@@ -0,0 +1,32 @@
|
||||
# Origin content (ism/ismv etc.) on GlusterFS, served by all replicas.
|
||||
apiVersion: v1
|
||||
kind: PersistentVolume
|
||||
metadata:
|
||||
name: unified-streaming-pv
|
||||
spec:
|
||||
capacity:
|
||||
storage: 100Gi
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
- ReadOnlyMany
|
||||
- ReadWriteMany
|
||||
persistentVolumeReclaimPolicy: Retain
|
||||
volumeMode: Filesystem
|
||||
hostPath:
|
||||
path: /mnt/gvolume0/unified-streaming
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: unified-streaming-pvc
|
||||
namespace: unified-streaming
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
- ReadOnlyMany
|
||||
- ReadWriteMany
|
||||
resources:
|
||||
requests:
|
||||
storage: 100Gi
|
||||
storageClassName: ""
|
||||
volumeName: unified-streaming-pv
|
||||
@@ -0,0 +1,75 @@
|
||||
# Originally installed via helm chart vaultwarden-5.1.0 (release record no longer
|
||||
# in cluster); managed as a raw manifest since. Selector labels are immutable —
|
||||
# do not change them.
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: bitwarden-vaultwarden
|
||||
namespace: bitwarden
|
||||
labels:
|
||||
app.kubernetes.io/instance: bitwarden
|
||||
app.kubernetes.io/name: vaultwarden
|
||||
spec:
|
||||
replicas: 1
|
||||
revisionHistoryLimit: 3
|
||||
selector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/instance: bitwarden
|
||||
app.kubernetes.io/name: vaultwarden
|
||||
strategy:
|
||||
type: Recreate
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app.kubernetes.io/instance: bitwarden
|
||||
app.kubernetes.io/name: vaultwarden
|
||||
spec:
|
||||
affinity:
|
||||
nodeAffinity:
|
||||
requiredDuringSchedulingIgnoredDuringExecution:
|
||||
nodeSelectorTerms:
|
||||
- matchExpressions:
|
||||
- key: cpu
|
||||
operator: In
|
||||
values:
|
||||
- arm
|
||||
- key: controller
|
||||
operator: NotIn
|
||||
values:
|
||||
- "true"
|
||||
containers:
|
||||
- name: bitwarden-vaultwarden
|
||||
image: vaultwarden/server:1.35.4
|
||||
imagePullPolicy: IfNotPresent
|
||||
env:
|
||||
- name: DATA_FOLDER
|
||||
value: config
|
||||
ports:
|
||||
- name: http
|
||||
containerPort: 80
|
||||
protocol: TCP
|
||||
- name: websocket
|
||||
containerPort: 3012
|
||||
protocol: TCP
|
||||
startupProbe:
|
||||
tcpSocket:
|
||||
port: 80
|
||||
failureThreshold: 30
|
||||
periodSeconds: 5
|
||||
livenessProbe:
|
||||
tcpSocket:
|
||||
port: 80
|
||||
failureThreshold: 3
|
||||
periodSeconds: 10
|
||||
readinessProbe:
|
||||
tcpSocket:
|
||||
port: 80
|
||||
failureThreshold: 3
|
||||
periodSeconds: 10
|
||||
volumeMounts:
|
||||
- name: config
|
||||
mountPath: /config
|
||||
volumes:
|
||||
- name: config
|
||||
persistentVolumeClaim:
|
||||
claimName: bitwarden-gvolume0
|
||||
@@ -0,0 +1,23 @@
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: bitwarden
|
||||
namespace: bitwarden
|
||||
spec:
|
||||
ingressClassName: traefik
|
||||
defaultBackend:
|
||||
service:
|
||||
name: bitwarden-vaultwarden-svc
|
||||
port:
|
||||
number: 8080
|
||||
rules:
|
||||
- host: pm.wittyoneoff.com
|
||||
http:
|
||||
paths:
|
||||
- path: /
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: bitwarden-vaultwarden-svc
|
||||
port:
|
||||
number: 8080
|
||||
@@ -0,0 +1,8 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
resources:
|
||||
- namespace.yaml
|
||||
- storage.yaml
|
||||
- deployment.yaml
|
||||
- service.yaml
|
||||
- ingress.yaml
|
||||
@@ -0,0 +1,4 @@
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: bitwarden
|
||||
@@ -0,0 +1,19 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: bitwarden-vaultwarden-svc
|
||||
namespace: bitwarden
|
||||
spec:
|
||||
type: ClusterIP
|
||||
selector:
|
||||
app.kubernetes.io/instance: bitwarden
|
||||
app.kubernetes.io/name: vaultwarden
|
||||
ports:
|
||||
- name: http
|
||||
port: 8080
|
||||
targetPort: 80
|
||||
protocol: TCP
|
||||
- name: websocket
|
||||
port: 3012
|
||||
targetPort: websocket
|
||||
protocol: TCP
|
||||
@@ -0,0 +1,30 @@
|
||||
# GlusterFS-backed volume: /mnt/gvolume0 is the gluster mount present on every node.
|
||||
apiVersion: v1
|
||||
kind: PersistentVolume
|
||||
metadata:
|
||||
name: bitwarden-pv
|
||||
spec:
|
||||
capacity:
|
||||
storage: 10Gi
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
- ReadWriteMany
|
||||
- ReadOnlyMany
|
||||
persistentVolumeReclaimPolicy: Retain
|
||||
volumeMode: Filesystem
|
||||
hostPath:
|
||||
path: /mnt/gvolume0/bitwarden
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: bitwarden-gvolume0
|
||||
namespace: bitwarden
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
resources:
|
||||
requests:
|
||||
storage: 10Gi
|
||||
storageClassName: ""
|
||||
volumeName: bitwarden-pv
|
||||
Reference in New Issue
Block a user