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:
jasonwitty
2026-07-26 02:13:56 -07:00
parent ec9b422f87
commit 8afac39d03
40 changed files with 1179 additions and 1 deletions
+69
View File
@@ -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
+18
View File
@@ -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
+10
View File
@@ -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
+4
View File
@@ -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
+18
View File
@@ -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
+32
View File
@@ -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