From 510e18e5dc627f17addd5901df8309c04a6a10fd Mon Sep 17 00:00:00 2001 From: Jose Henrique Date: Fri, 28 Aug 2026 16:15:08 -0300 Subject: [PATCH] fix: corrected ApplicationSet template, drop secret stubs from manifests - appset: goTemplate, filename-based app names, .path.path IS the directory, exclude apps/root from the glob (v3.5 git files-generator schema) - remove empty Secret stubs: with prune:true they would overwrite live secret values (openwebui, paperless, vaultwarden-admin-token, password) - secrets stay cluster-managed, not in git --- apps/default/archivebox.yaml | 150 +++++++++++++ apps/default/changedetection.yaml | 189 ++++++++++++++++ apps/default/havenllo.yaml | 171 +++++++++++++++ apps/default/homepage.yaml | 226 ++++++++++++++++++++ apps/default/it-tools.yaml | 106 +++++++++ apps/default/openwebui.yaml | 120 +++++++++++ apps/default/paperless.yaml | 158 ++++++++++++++ apps/default/playwright.yaml | 131 ++++++++++++ apps/default/qbittorrent.yaml | 176 +++++++++++++++ apps/default/searxng.yaml | 136 ++++++++++++ apps/default/sonic.yaml | 79 +++++++ apps/default/stirlingpdf.yaml | 157 ++++++++++++++ apps/default/uptimekuma.yaml | 155 ++++++++++++++ apps/default/vaultwarden.yaml | 152 +++++++++++++ apps/root/applicationset.yaml | 16 +- bootstrap/argocd-install/kustomization.yaml | 4 +- tools/validate_all.sh | 17 ++ 17 files changed, 2138 insertions(+), 5 deletions(-) create mode 100644 apps/default/archivebox.yaml create mode 100644 apps/default/changedetection.yaml create mode 100644 apps/default/havenllo.yaml create mode 100644 apps/default/homepage.yaml create mode 100644 apps/default/it-tools.yaml create mode 100644 apps/default/openwebui.yaml create mode 100644 apps/default/paperless.yaml create mode 100644 apps/default/playwright.yaml create mode 100644 apps/default/qbittorrent.yaml create mode 100644 apps/default/searxng.yaml create mode 100644 apps/default/sonic.yaml create mode 100644 apps/default/stirlingpdf.yaml create mode 100644 apps/default/uptimekuma.yaml create mode 100644 apps/default/vaultwarden.yaml create mode 100644 tools/validate_all.sh diff --git a/apps/default/archivebox.yaml b/apps/default/archivebox.yaml new file mode 100644 index 0000000..912fb3c --- /dev/null +++ b/apps/default/archivebox.yaml @@ -0,0 +1,150 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: archivebox + namespace: default +spec: + replicas: 1 + selector: + matchLabels: + app: archivebox + strategy: + type: Recreate + template: + metadata: + labels: + app: archivebox + spec: + containers: + - env: + - name: SONIC_HOST + value: sonic.default.svc.cluster.local + - name: SONIC_PORT + value: '1491' + - name: SEARCH_BACKEND_ENGINE + value: sonic + - name: SONIC_PASSWORD + valueFrom: + secretKeyRef: + key: password + name: password + - name: ADMIN_USERNAME + value: ivanch + - name: ADMIN_PASSWORD + valueFrom: + secretKeyRef: + key: password + name: password + - name: CSRF_TRUSTED_ORIGINS + value: archive.haven + - name: ALLOWED_HOSTS + value: '*' + - name: PUBLIC_ADD_VIEW + value: 'false' + image: archivebox/archivebox:latest + imagePullPolicy: Always + name: archivebox + ports: + - containerPort: 8000 + protocol: TCP + resources: {} + terminationMessagePath: /dev/termination-log + terminationMessagePolicy: File + volumeMounts: + - mountPath: /data + name: archivebox-data + dnsPolicy: ClusterFirst + restartPolicy: Always + schedulerName: default-scheduler + securityContext: {} + terminationGracePeriodSeconds: 30 + volumes: + - name: archivebox-data + persistentVolumeClaim: + claimName: archivebox-data +status: + availableReplicas: 1 + conditions: + - lastTransitionTime: '2026-05-19T01:51:47Z' + lastUpdateTime: '2026-07-22T10:14:38Z' + message: ReplicaSet "archivebox-bb7f58db4" has successfully progressed. + reason: NewReplicaSetAvailable + status: 'True' + type: Progressing + - lastTransitionTime: '2026-08-28T06:04:13Z' + lastUpdateTime: '2026-08-28T06:04:13Z' + message: Deployment has minimum availability. + reason: MinimumReplicasAvailable + status: 'True' + type: Available + observedGeneration: 94 + readyReplicas: 1 + replicas: 1 + terminatingReplicas: 0 + updatedReplicas: 1 +--- +apiVersion: v1 +kind: Service +metadata: + name: archivebox-svc + namespace: default +spec: + internalTrafficPolicy: Cluster + ipFamilies: + - IPv4 + ipFamilyPolicy: SingleStack + ports: + - port: 8000 + protocol: TCP + targetPort: 8000 + selector: + app: archivebox + sessionAffinity: None + type: ClusterIP +status: + loadBalancer: {} +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: archivebox-ingress + namespace: default +spec: + ingressClassName: nginx + rules: + - host: archive.haven + http: + paths: + - backend: + service: + name: archivebox-svc + port: + number: 8000 + path: / + pathType: Prefix +status: + loadBalancer: + ingress: + - ip: 192.168.20.204 +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: archivebox-data + namespace: default +spec: + accessModes: + - ReadWriteOnce + resources: + limits: + storage: 30Gi + requests: + storage: 10Gi + storageClassName: nfs-client + volumeMode: Filesystem +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 10Gi + phase: Bound diff --git a/apps/default/changedetection.yaml b/apps/default/changedetection.yaml new file mode 100644 index 0000000..479575a --- /dev/null +++ b/apps/default/changedetection.yaml @@ -0,0 +1,189 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app.kubernetes.io/name: changedetection + name: changedetection + namespace: default +spec: + replicas: 1 + selector: + matchLabels: + app.kubernetes.io/name: changedetection + strategy: + type: Recreate + template: + metadata: + labels: + app.kubernetes.io/name: changedetection + spec: + affinity: + nodeAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - preference: + matchExpressions: + - key: kubernetes.io/hostname + operator: In + values: + - iris + weight: 100 + containers: + - env: + - name: PUID + value: '1000' + - name: PGID + value: '1000' + - name: TZ + value: Etc/UTC + - name: BASE_URL + value: http://change.haven/ + - name: PLAYWRIGHT_DRIVER_URL + value: ws://localhost:3000 + image: lscr.io/linuxserver/changedetection.io:latest + imagePullPolicy: Always + name: changedetection + ports: + - containerPort: 5000 + name: http + protocol: TCP + resources: + limits: + cpu: '2' + memory: 1Gi + requests: + cpu: 100m + memory: 256Mi + securityContext: + allowPrivilegeEscalation: false + runAsUser: 0 + terminationMessagePath: /dev/termination-log + terminationMessagePolicy: File + volumeMounts: + - mountPath: /config + name: config + - env: + - name: SCREEN_WIDTH + value: '1920' + - name: SCREEN_HEIGHT + value: '1024' + - name: SCREEN_DEPTH + value: '16' + - name: MAX_CONCURRENT_CHROME_PROCESSES + value: '10' + image: dgtlmoon/sockpuppetbrowser:latest + imagePullPolicy: Always + name: browser-sockpuppet-chrome + ports: + - containerPort: 3000 + name: ws + protocol: TCP + resources: {} + securityContext: + allowPrivilegeEscalation: false + capabilities: + add: + - SYS_ADMIN + drop: + - ALL + terminationMessagePath: /dev/termination-log + terminationMessagePolicy: File + dnsPolicy: ClusterFirst + restartPolicy: Always + schedulerName: default-scheduler + securityContext: {} + terminationGracePeriodSeconds: 30 + volumes: + - name: config + persistentVolumeClaim: + claimName: changedetection-config +status: + availableReplicas: 1 + conditions: + - lastTransitionTime: '2026-08-04T16:20:08Z' + lastUpdateTime: '2026-08-04T16:32:45Z' + message: ReplicaSet "changedetection-77cd668cf4" has successfully progressed. + reason: NewReplicaSetAvailable + status: 'True' + type: Progressing + - lastTransitionTime: '2026-08-28T06:05:12Z' + lastUpdateTime: '2026-08-28T06:05:12Z' + message: Deployment has minimum availability. + reason: MinimumReplicasAvailable + status: 'True' + type: Available + observedGeneration: 22 + readyReplicas: 1 + replicas: 1 + terminatingReplicas: 0 + updatedReplicas: 1 +--- +apiVersion: v1 +kind: Service +metadata: + labels: + app.kubernetes.io/name: changedetection + name: changedetection + namespace: default +spec: + internalTrafficPolicy: Cluster + ipFamilies: + - IPv4 + ipFamilyPolicy: SingleStack + ports: + - name: http + port: 5000 + protocol: TCP + targetPort: http + selector: + app.kubernetes.io/name: changedetection + sessionAffinity: None + type: ClusterIP +status: + loadBalancer: {} +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + labels: + app.kubernetes.io/name: changedetection + name: changedetection + namespace: default +spec: + ingressClassName: nginx + rules: + - host: change.haven + http: + paths: + - backend: + service: + name: changedetection + port: + number: 5000 + path: / + pathType: Prefix +status: + loadBalancer: + ingress: + - ip: 192.168.20.204 +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: changedetection-config + namespace: default +spec: + accessModes: + - ReadWriteOnce + resources: + limits: + storage: 2Gi + requests: + storage: 1Gi + storageClassName: nfs-client + volumeMode: Filesystem +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound diff --git a/apps/default/havenllo.yaml b/apps/default/havenllo.yaml new file mode 100644 index 0000000..f2128d9 --- /dev/null +++ b/apps/default/havenllo.yaml @@ -0,0 +1,171 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app.kubernetes.io/name: havenllo + name: havenllo + namespace: default +spec: + replicas: 1 + selector: + matchLabels: + app.kubernetes.io/name: havenllo + strategy: + type: Recreate + template: + metadata: + labels: + app.kubernetes.io/name: havenllo + spec: + containers: + - env: + - name: HAVENLLO_DATABASE_PATH + value: /data/havenllo.db + - name: HAVENLLO_LISTEN_ADDR + value: :8080 + image: git.ivanch.me/ivanch/havenllo:latest + imagePullPolicy: Always + livenessProbe: + failureThreshold: 3 + httpGet: + path: /api/health + port: http + scheme: HTTP + initialDelaySeconds: 10 + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 2 + name: havenllo + ports: + - containerPort: 8080 + name: http + protocol: TCP + readinessProbe: + failureThreshold: 3 + httpGet: + path: /api/health + port: http + scheme: HTTP + initialDelaySeconds: 2 + periodSeconds: 5 + successThreshold: 1 + timeoutSeconds: 2 + resources: + limits: + cpu: 500m + memory: 256Mi + requests: + cpu: 50m + memory: 64Mi + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + readOnlyRootFilesystem: true + runAsUser: 0 + terminationMessagePath: /dev/termination-log + terminationMessagePolicy: File + volumeMounts: + - mountPath: /data + name: data + dnsPolicy: ClusterFirst + restartPolicy: Always + schedulerName: default-scheduler + securityContext: {} + terminationGracePeriodSeconds: 30 + volumes: + - name: data + persistentVolumeClaim: + claimName: havenllo-data +status: + availableReplicas: 1 + conditions: + - lastTransitionTime: '2026-07-14T13:21:13Z' + lastUpdateTime: '2026-07-21T21:06:45Z' + message: ReplicaSet "havenllo-5d4f8ccb4f" has successfully progressed. + reason: NewReplicaSetAvailable + status: 'True' + type: Progressing + - lastTransitionTime: '2026-08-28T06:04:17Z' + lastUpdateTime: '2026-08-28T06:04:17Z' + message: Deployment has minimum availability. + reason: MinimumReplicasAvailable + status: 'True' + type: Available + observedGeneration: 41 + readyReplicas: 1 + replicas: 1 + terminatingReplicas: 0 + updatedReplicas: 1 +--- +apiVersion: v1 +kind: Service +metadata: + labels: + app.kubernetes.io/name: havenllo + name: havenllo + namespace: default +spec: + internalTrafficPolicy: Cluster + ipFamilies: + - IPv4 + ipFamilyPolicy: SingleStack + ports: + - name: http + port: 8080 + protocol: TCP + targetPort: 8080 + selector: + app.kubernetes.io/name: havenllo + sessionAffinity: None + type: ClusterIP +status: + loadBalancer: {} +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: havenllo + namespace: default +spec: + ingressClassName: nginx-https + rules: + - host: havenllo.haven + http: + paths: + - backend: + service: + name: havenllo + port: + number: 8080 + path: / + pathType: Prefix + tls: + - hosts: + - havenllo.haven + secretName: havenllo-tls +status: + loadBalancer: + ingress: + - ip: 192.168.20.204 +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: havenllo-data + namespace: default +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi + storageClassName: nfs-client + volumeMode: Filesystem +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound diff --git a/apps/default/homepage.yaml b/apps/default/homepage.yaml new file mode 100644 index 0000000..5e0fa8e --- /dev/null +++ b/apps/default/homepage.yaml @@ -0,0 +1,226 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app.kubernetes.io/name: homepage + name: homepage + namespace: default +spec: + replicas: 1 + selector: + matchLabels: + app.kubernetes.io/name: homepage + strategy: + type: Recreate + template: + metadata: + labels: + app.kubernetes.io/name: homepage + spec: + automountServiceAccountToken: true + containers: + - env: + - name: POD_IP + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: status.podIP + - name: HOMEPAGE_ALLOWED_HOSTS + value: '*' + image: ghcr.io/gethomepage/homepage:latest + imagePullPolicy: Always + livenessProbe: + failureThreshold: 3 + httpGet: + path: / + port: 3000 + scheme: HTTP + initialDelaySeconds: 30 + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 1 + name: homepage + ports: + - containerPort: 3000 + name: http + protocol: TCP + readinessProbe: + failureThreshold: 3 + httpGet: + path: / + port: 3000 + scheme: HTTP + initialDelaySeconds: 5 + periodSeconds: 5 + successThreshold: 1 + timeoutSeconds: 1 + resources: + limits: + cpu: 500m + memory: 512Mi + requests: + cpu: 100m + memory: 128Mi + terminationMessagePath: /dev/termination-log + terminationMessagePolicy: File + volumeMounts: + - mountPath: /app/config/logs + name: logs + - mountPath: /app/config + name: homepage-config + - mountPath: /app/public/images + name: homepage-config + subPath: images + dnsPolicy: ClusterFirst + enableServiceLinks: true + restartPolicy: Always + schedulerName: default-scheduler + securityContext: {} + serviceAccount: homepage + serviceAccountName: homepage + terminationGracePeriodSeconds: 30 + volumes: + - name: homepage-config + persistentVolumeClaim: + claimName: homepage-config + - emptyDir: {} + name: logs +status: + availableReplicas: 1 + conditions: + - lastTransitionTime: '2026-05-19T01:51:47Z' + lastUpdateTime: '2026-08-17T09:07:50Z' + message: ReplicaSet "homepage-7b47bf67fb" has successfully progressed. + reason: NewReplicaSetAvailable + status: 'True' + type: Progressing + - lastTransitionTime: '2026-08-28T06:04:23Z' + lastUpdateTime: '2026-08-28T06:04:23Z' + message: Deployment has minimum availability. + reason: MinimumReplicasAvailable + status: 'True' + type: Available + observedGeneration: 96 + readyReplicas: 1 + replicas: 1 + terminatingReplicas: 0 + updatedReplicas: 1 +--- +apiVersion: v1 +kind: Service +metadata: + labels: + app.kubernetes.io/name: homepage + name: homepage + namespace: default +spec: + internalTrafficPolicy: Cluster + ipFamilies: + - IPv4 + ipFamilyPolicy: SingleStack + ports: + - name: http + port: 3000 + protocol: TCP + targetPort: http + selector: + app.kubernetes.io/name: homepage + sessionAffinity: None + type: ClusterIP +status: + loadBalancer: {} +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + labels: + app.kubernetes.io/name: homepage + name: homepage + namespace: default +spec: + ingressClassName: nginx + rules: + - host: homepage.haven + http: + paths: + - backend: + service: + name: homepage + port: + number: 3000 + path: / + pathType: Prefix +status: + loadBalancer: + ingress: + - ip: 192.168.20.204 +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: homepage-config + namespace: default +spec: + accessModes: + - ReadWriteMany + resources: + requests: + storage: 1Gi + storageClassName: nfs-client + volumeMode: Filesystem +status: + accessModes: + - ReadWriteMany + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +data: + bookmarks.yaml: "- Developer:\n - Github:\n - abbr: GH\n href:\ + \ https://github.com/\n" + custom.css: '' + custom.js: '' + docker.yaml: '' + kubernetes.yaml: 'mode: cluster + + ' + services.yaml: "- Essentials:\n - AdGuard Home:\n href: http://adguard.haven/\n\ + \ icon: adguard-home\n widget:\n type: adguard\n \ + \ url: http://adguard.haven/\n username: ivanch\n password:\ + \ ESVEPnull\n - AdGuard Home 2:\n href: http://adguard2.haven/\n \ + \ icon: adguard-home\n widget:\n type: adguard\n \ + \ url: http://adguard2.haven/\n username: ivanch\n password:\ + \ ESVEPnull\n - Home Assistant:\n href: http://homeassistant.haven/\n\ + \ - Traefik:\n href: http://traefik.haven/\n - Dockge:\n href:\ + \ http://dockge.haven/\n - Proxmox:\n href: https://proxmox.haven:8006/\n\ + \ widget:\n type: proxmox\n url: https://proxmox.haven:8006/\n\ + \ token: homepage@pam!token\n secret: 7cadfc2d-560a-4bb4-8d5f-a29f394bc9a0\n\ + \n- Media:\n - Jellyfin:\n href: http://tv.haven/\n icon: jellyfin.png\n\ + \ widget:\n type: jellyfin\n url: http://tv.haven/\n\ + \ key: c933070d9c8341bf8c64e7a792aaa6b9\n enableBlocks: true\n\ + \ enableNowPlaying: true\n - Sonarr:\n href: http://sonarr.haven/\n\ + \ - Radarr:\n href: http://radarr.haven/\n - Prowlarr:\n href:\ + \ http://prowlarr.haven/\n\n- Storage:\n - Transmission:\n href: http://transmission.haven/\n\ + \ - qBitTorrent:\n href: http://qbittorrent.haven/\n - OpenMediaVault:\n\ + \ href: http://omv.haven/\n - ArchiveBox:\n href: http://archive.haven/\n\ + \ - FileBrowser:\n href: http://files.haven/\n - Paperless:\n \ + \ href: http://paperless.haven/\n\n- Other:\n - Uptime Kuma:\n href:\ + \ http://uptimekuma.haven/\n - WireGuard:\n href: http://vpn.haven/\n\ + \ - Beszel:\n href: http://beszel.haven/\n\n- Zephyr:\n - Gitea:\n\ + \ href: http://gitea.ivanch.me/\n - Portainer:\n href: http://portainer.ivanch.me/\n\ + \ - Nginx Proxy Manager:\n href: http://manager.ivanch.me/\n - Homepage:\n\ + \ href: http://ivanch.me/\n" + settings.yaml: '' + widgets.yaml: "- kubernetes:\n cluster:\n show: true\n cpu: true\n\ + \ memory: true\n # network: true\n showLabel: true\n label:\ + \ \"Haven\"\n nodes:\n show: true\n cpu: true\n memory: true\n\ + \ showLabel: true\n- resources:\n backend: resources\n expanded: true\n\ + \ cpu: true\n memory: true\n network: default\n- search:\n provider:\ + \ duckduckgo\n target: _blank\n" +kind: ConfigMap +metadata: + labels: + app.kubernetes.io/name: homepage + name: homepage + namespace: default diff --git a/apps/default/it-tools.yaml b/apps/default/it-tools.yaml new file mode 100644 index 0000000..c00bd12 --- /dev/null +++ b/apps/default/it-tools.yaml @@ -0,0 +1,106 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: it-tools + namespace: default +spec: + replicas: 1 + selector: + matchLabels: + app: it-tools + strategy: + type: Recreate + template: + metadata: + labels: + app: it-tools + spec: + containers: + - image: corentinth/it-tools:latest + imagePullPolicy: Always + name: it-tools + ports: + - containerPort: 80 + protocol: TCP + readinessProbe: + failureThreshold: 3 + httpGet: + path: / + port: 80 + scheme: HTTP + initialDelaySeconds: 5 + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 1 + resources: {} + terminationMessagePath: /dev/termination-log + terminationMessagePolicy: File + dnsPolicy: ClusterFirst + restartPolicy: Always + schedulerName: default-scheduler + securityContext: {} + terminationGracePeriodSeconds: 30 +status: + availableReplicas: 1 + conditions: + - lastTransitionTime: '2026-05-19T01:51:47Z' + lastUpdateTime: '2026-07-22T10:14:45Z' + message: ReplicaSet "it-tools-6fc797dd48" has successfully progressed. + reason: NewReplicaSetAvailable + status: 'True' + type: Progressing + - lastTransitionTime: '2026-08-28T06:04:26Z' + lastUpdateTime: '2026-08-28T06:04:26Z' + message: Deployment has minimum availability. + reason: MinimumReplicasAvailable + status: 'True' + type: Available + observedGeneration: 93 + readyReplicas: 1 + replicas: 1 + terminatingReplicas: 0 + updatedReplicas: 1 +--- +apiVersion: v1 +kind: Service +metadata: + name: it-tools-svc + namespace: default +spec: + internalTrafficPolicy: Cluster + ipFamilies: + - IPv4 + ipFamilyPolicy: SingleStack + ports: + - port: 80 + protocol: TCP + targetPort: 80 + selector: + app: it-tools + sessionAffinity: None + type: ClusterIP +status: + loadBalancer: {} +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: it-tools-ingress + namespace: default +spec: + ingressClassName: nginx + rules: + - host: tools.haven + http: + paths: + - backend: + service: + name: it-tools-svc + port: + number: 80 + path: / + pathType: Prefix +status: + loadBalancer: + ingress: + - ip: 192.168.20.204 diff --git a/apps/default/openwebui.yaml b/apps/default/openwebui.yaml new file mode 100644 index 0000000..ee5017c --- /dev/null +++ b/apps/default/openwebui.yaml @@ -0,0 +1,120 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: openwebui + namespace: default +spec: + replicas: 1 + selector: + matchLabels: + app: openwebui + strategy: + type: Recreate + template: + metadata: + labels: + app: openwebui + spec: + affinity: + nodeAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - preference: + matchExpressions: + - key: kubernetes.io/hostname + operator: In + values: + - iris + weight: 100 + containers: + - env: + - name: PUID + value: '1000' + - name: PGID + value: '1000' + - name: TZ + value: America/Sao_Paulo + - name: DATABASE_URL + valueFrom: + secretKeyRef: + key: DATABASE_URL + name: openwebui-secret + - name: PLAYWRIGHT_WS_URL + value: ws://browserless.default.svc.cluster.local:3000 + image: ghcr.io/open-webui/open-webui:main-slim + imagePullPolicy: Always + name: openwebui + ports: + - containerPort: 8080 + protocol: TCP + resources: + limits: + cpu: '1' + memory: 2Gi + requests: + cpu: 250m + memory: 512Mi + terminationMessagePath: /dev/termination-log + terminationMessagePolicy: File + volumeMounts: + - mountPath: /app/backend/data + name: openwebui-data + dnsPolicy: ClusterFirst + restartPolicy: Always + schedulerName: default-scheduler + securityContext: {} + terminationGracePeriodSeconds: 30 + volumes: + - name: openwebui-data + persistentVolumeClaim: + claimName: openwebui-data +apiVersion: v1 +kind: Service +metadata: + name: openwebui + namespace: default +spec: + internalTrafficPolicy: Cluster + ipFamilies: + - IPv4 + ipFamilyPolicy: SingleStack + ports: + - port: 8080 + protocol: TCP + targetPort: 8080 + selector: + app: openwebui + sessionAffinity: None + type: ClusterIP +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: openwebui + namespace: default +spec: + ingressClassName: nginx + rules: + - host: openwebui.haven + http: + paths: + - backend: + service: + name: openwebui + port: + number: 8080 + path: / + pathType: Prefix +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: openwebui-data + namespace: default +spec: + accessModes: + - ReadWriteOnce + resources: + limits: + storage: 10Gi + requests: + storage: 5Gi + storageClassName: nfs-client + volumeMode: Filesystem diff --git a/apps/default/paperless.yaml b/apps/default/paperless.yaml new file mode 100644 index 0000000..1a9e383 --- /dev/null +++ b/apps/default/paperless.yaml @@ -0,0 +1,158 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: paperless + namespace: default +spec: + replicas: 1 + selector: + matchLabels: + app: paperless + strategy: + type: Recreate + template: + metadata: + labels: + app: paperless + spec: + affinity: + nodeAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - preference: + matchExpressions: + - key: kubernetes.io/hostname + operator: In + values: + - iris + weight: 100 + containers: + - env: + - name: PUID + value: '1000' + - name: PGID + value: '1000' + - name: PAPERLESS_URL + value: http://paperless.haven + - name: PAPERLESS_TIME_ZONE + value: America/Sao_Paulo + - name: PAPERLESS_OCR_LANGUAGE + value: por + - name: PAPERLESS_OCR_LANGUAGES + value: por + - name: PAPERLESS_OCR_USER_ARGS + value: '{"invalidate_digital_signatures": true}' + - name: PAPERLESS_DBHOST + value: postgresql.haven + - name: PAPERLESS_DBNAME + valueFrom: + secretKeyRef: + key: PAPERLESS_DBNAME + name: paperless-secret + - name: PAPERLESS_DBUSER + valueFrom: + secretKeyRef: + key: PAPERLESS_DBUSER + name: paperless-secret + - name: PAPERLESS_DBPASSWORD + valueFrom: + secretKeyRef: + key: PAPERLESS_DBPASSWORD + name: paperless-secret + - name: PAPERLESS_REDIS + value: redis://redis.haven:6379 + - name: PAPERLESS_PORT + value: '8000' + - name: PAPERLESS_SECRET_KEY + valueFrom: + secretKeyRef: + key: PAPERLESS_SECRET_KEY + name: paperless-secret + image: ghcr.io/paperless-ngx/paperless-ngx:latest + imagePullPolicy: Always + name: paperless + ports: + - containerPort: 8000 + name: paperless-port + protocol: TCP + resources: + limits: + cpu: '4' + memory: 1Gi + requests: + cpu: 100m + memory: 256Mi + terminationMessagePath: /dev/termination-log + terminationMessagePolicy: File + volumeMounts: + - mountPath: /usr/src/paperless/data + name: paperless-data + subPath: data + - mountPath: /usr/src/paperless/media + name: paperless-data + subPath: media + - mountPath: /usr/src/paperless/export + name: paperless-data + subPath: export + - mountPath: /usr/src/paperless/consume + name: paperless-data + subPath: consume + dnsPolicy: ClusterFirst + restartPolicy: Always + schedulerName: default-scheduler + securityContext: {} + terminationGracePeriodSeconds: 30 + volumes: + - name: paperless-data + persistentVolumeClaim: + claimName: paperless-data +apiVersion: v1 +kind: Service +metadata: + name: paperless + namespace: default +spec: + internalTrafficPolicy: Cluster + ipFamilies: + - IPv4 + ipFamilyPolicy: SingleStack + ports: + - port: 8000 + protocol: TCP + targetPort: paperless-port + selector: + app: paperless + sessionAffinity: None + type: ClusterIP +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: paperless + namespace: default +spec: + ingressClassName: nginx + rules: + - host: paperless.haven + http: + paths: + - backend: + service: + name: paperless + port: + number: 8000 + path: / + pathType: Prefix +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: paperless-data + namespace: default +spec: + accessModes: + - ReadWriteMany + resources: + limits: + storage: 15Gi + requests: + storage: 5Gi + storageClassName: nfs-client + volumeMode: Filesystem diff --git a/apps/default/playwright.yaml b/apps/default/playwright.yaml new file mode 100644 index 0000000..499dcaa --- /dev/null +++ b/apps/default/playwright.yaml @@ -0,0 +1,131 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: playwright + namespace: default +spec: + replicas: 1 + selector: + matchLabels: + app: playwright + strategy: + type: Recreate + template: + metadata: + labels: + app: playwright + spec: + affinity: + nodeAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - preference: + matchExpressions: + - key: kubernetes.io/hostname + operator: In + values: + - iris + weight: 100 + containers: + - command: + - npx + - -y + - playwright@1.58.0 + - run-server + - --port + - '3000' + - --host + - 0.0.0.0 + env: + - name: TZ + value: America/Sao_Paulo + image: mcr.microsoft.com/playwright:v1.58.0-noble + imagePullPolicy: Always + name: playwright + ports: + - containerPort: 3000 + protocol: TCP + resources: + limits: + cpu: '4' + memory: 4Gi + requests: + cpu: 500m + memory: 512Mi + terminationMessagePath: /dev/termination-log + terminationMessagePolicy: File + volumeMounts: + - mountPath: /dev/shm + name: dshm + dnsPolicy: ClusterFirst + restartPolicy: Always + schedulerName: default-scheduler + securityContext: {} + terminationGracePeriodSeconds: 30 + volumes: + - emptyDir: + medium: Memory + name: dshm +status: + availableReplicas: 1 + conditions: + - lastTransitionTime: '2026-05-29T15:54:24Z' + lastUpdateTime: '2026-07-22T10:14:35Z' + message: ReplicaSet "playwright-86c74d7c78" has successfully progressed. + reason: NewReplicaSetAvailable + status: 'True' + type: Progressing + - lastTransitionTime: '2026-08-28T06:04:14Z' + lastUpdateTime: '2026-08-28T06:04:14Z' + message: Deployment has minimum availability. + reason: MinimumReplicasAvailable + status: 'True' + type: Available + observedGeneration: 95 + readyReplicas: 1 + replicas: 1 + terminatingReplicas: 0 + updatedReplicas: 1 +--- +apiVersion: v1 +kind: Service +metadata: + name: playwright + namespace: default +spec: + internalTrafficPolicy: Cluster + ipFamilies: + - IPv4 + ipFamilyPolicy: SingleStack + ports: + - port: 3000 + protocol: TCP + targetPort: 3000 + selector: + app: playwright + sessionAffinity: None + type: ClusterIP +status: + loadBalancer: {} +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: playwright + namespace: default +spec: + ingressClassName: nginx + rules: + - host: playwright.haven + http: + paths: + - backend: + service: + name: playwright + port: + number: 3000 + path: / + pathType: Prefix +status: + loadBalancer: + ingress: + - ip: 192.168.20.204 diff --git a/apps/default/qbittorrent.yaml b/apps/default/qbittorrent.yaml new file mode 100644 index 0000000..6ff664e --- /dev/null +++ b/apps/default/qbittorrent.yaml @@ -0,0 +1,176 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: qbittorrent + namespace: default +spec: + replicas: 1 + selector: + matchLabels: + app: qbittorrent + strategy: + type: Recreate + template: + metadata: + labels: + app: qbittorrent + spec: + affinity: + nodeAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - preference: + matchExpressions: + - key: kubernetes.io/hostname + operator: In + values: + - iris + weight: 100 + containers: + - env: + - name: PUID + value: '1000' + - name: PGID + value: '1000' + - name: TZ + value: Etc/UTC + - name: WEBUI_PORT + value: '4300' + - name: TORRENTING_PORT + value: '6881' + image: lscr.io/linuxserver/qbittorrent:5.0.4 + imagePullPolicy: Always + name: qbittorrent + ports: + - containerPort: 4300 + name: webui-port + protocol: TCP + - containerPort: 6881 + name: qbit-tcp + protocol: TCP + - containerPort: 6881 + name: qbit-udp + protocol: UDP + resources: + limits: + cpu: '1' + memory: 512Mi + requests: + cpu: 200m + memory: 256Mi + terminationMessagePath: /dev/termination-log + terminationMessagePolicy: File + volumeMounts: + - mountPath: /config + name: qbittorrent-config + - mountPath: /nas + name: nas-storage + dnsPolicy: ClusterFirst + restartPolicy: Always + schedulerName: default-scheduler + securityContext: {} + terminationGracePeriodSeconds: 30 + volumes: + - name: qbittorrent-config + persistentVolumeClaim: + claimName: qbittorrent-config + - name: nas-storage + nfs: + path: /export/Storage + server: 192.168.15.99 +status: + availableReplicas: 1 + conditions: + - lastTransitionTime: '2026-05-19T01:51:48Z' + lastUpdateTime: '2026-07-22T10:14:39Z' + message: ReplicaSet "qbittorrent-56dbf5f6c" has successfully progressed. + reason: NewReplicaSetAvailable + status: 'True' + type: Progressing + - lastTransitionTime: '2026-08-28T06:04:17Z' + lastUpdateTime: '2026-08-28T06:04:17Z' + message: Deployment has minimum availability. + reason: MinimumReplicasAvailable + status: 'True' + type: Available + observedGeneration: 100 + readyReplicas: 1 + replicas: 1 + terminatingReplicas: 0 + updatedReplicas: 1 +--- +apiVersion: v1 +kind: Service +metadata: + name: qbittorrent + namespace: default +spec: + externalTrafficPolicy: Cluster + internalTrafficPolicy: Cluster + ipFamilies: + - IPv4 + ipFamilyPolicy: SingleStack + ports: + - name: webui + nodePort: 30948 + port: 4300 + protocol: TCP + targetPort: webui-port + - name: torrent-tcp + nodePort: 30183 + port: 6881 + protocol: TCP + targetPort: qbit-tcp + - name: torrent-udp + nodePort: 30183 + port: 6881 + protocol: UDP + targetPort: qbit-udp + selector: + app: qbittorrent + sessionAffinity: None + type: NodePort +status: + loadBalancer: {} +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: qbittorrent + namespace: default +spec: + ingressClassName: nginx + rules: + - host: qbittorrent.haven + http: + paths: + - backend: + service: + name: qbittorrent + port: + number: 4300 + path: / + pathType: Prefix +status: + loadBalancer: + ingress: + - ip: 192.168.20.204 +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: qbittorrent-config + namespace: default +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi + storageClassName: nfs-client + volumeMode: Filesystem +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound diff --git a/apps/default/searxng.yaml b/apps/default/searxng.yaml new file mode 100644 index 0000000..855c53d --- /dev/null +++ b/apps/default/searxng.yaml @@ -0,0 +1,136 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: searxng + namespace: default +spec: + replicas: 1 + selector: + matchLabels: + app: searxng + strategy: + type: Recreate + template: + metadata: + labels: + app: searxng + spec: + containers: + - env: + - name: PUID + value: '1000' + - name: PGID + value: '1000' + image: searxng/searxng:latest + imagePullPolicy: Always + name: searxng + ports: + - containerPort: 8080 + name: searxng-port + protocol: TCP + resources: + limits: + cpu: 500m + memory: 512Mi + requests: + cpu: 100m + memory: 256Mi + terminationMessagePath: /dev/termination-log + terminationMessagePolicy: File + volumeMounts: + - mountPath: /etc/searxng + name: searxng-config + dnsPolicy: ClusterFirst + enableServiceLinks: false + restartPolicy: Always + schedulerName: default-scheduler + securityContext: {} + terminationGracePeriodSeconds: 30 + volumes: + - name: searxng-config + persistentVolumeClaim: + claimName: searxng-config +status: + availableReplicas: 1 + conditions: + - lastTransitionTime: '2026-05-19T01:51:48Z' + lastUpdateTime: '2026-07-22T10:15:23Z' + message: ReplicaSet "searxng-d6869bf47" has successfully progressed. + reason: NewReplicaSetAvailable + status: 'True' + type: Progressing + - lastTransitionTime: '2026-08-28T06:04:24Z' + lastUpdateTime: '2026-08-28T06:04:24Z' + message: Deployment has minimum availability. + reason: MinimumReplicasAvailable + status: 'True' + type: Available + observedGeneration: 93 + readyReplicas: 1 + replicas: 1 + terminatingReplicas: 0 + updatedReplicas: 1 +--- +apiVersion: v1 +kind: Service +metadata: + name: searxng + namespace: default +spec: + internalTrafficPolicy: Cluster + ipFamilies: + - IPv4 + ipFamilyPolicy: SingleStack + ports: + - port: 8080 + protocol: TCP + targetPort: searxng-port + selector: + app: searxng + sessionAffinity: None + type: ClusterIP +status: + loadBalancer: {} +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: searxng + namespace: default +spec: + ingressClassName: nginx + rules: + - host: search.haven + http: + paths: + - backend: + service: + name: searxng + port: + number: 8080 + path: / + pathType: Prefix +status: + loadBalancer: + ingress: + - ip: 192.168.20.204 +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: searxng-config + namespace: default +spec: + accessModes: + - ReadWriteMany + resources: + requests: + storage: 1Gi + storageClassName: nfs-client + volumeMode: Filesystem +status: + accessModes: + - ReadWriteMany + capacity: + storage: 1Gi + phase: Bound diff --git a/apps/default/sonic.yaml b/apps/default/sonic.yaml new file mode 100644 index 0000000..aa2a364 --- /dev/null +++ b/apps/default/sonic.yaml @@ -0,0 +1,79 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: sonic + namespace: default +spec: + replicas: 1 + selector: + matchLabels: + app: sonic + strategy: + type: Recreate + template: + metadata: + labels: + app: sonic + spec: + containers: + - env: + - name: SEARCH_BACKEND_PASSWORD + valueFrom: + secretKeyRef: + key: password + name: password + image: archivebox/sonic:latest + imagePullPolicy: Always + name: sonic + ports: + - containerPort: 1491 + protocol: TCP + resources: {} + terminationMessagePath: /dev/termination-log + terminationMessagePolicy: File + dnsPolicy: ClusterFirst + restartPolicy: Always + schedulerName: default-scheduler + securityContext: {} + terminationGracePeriodSeconds: 30 +status: + availableReplicas: 1 + conditions: + - lastTransitionTime: '2026-05-19T01:51:47Z' + lastUpdateTime: '2026-07-22T10:15:06Z' + message: ReplicaSet "sonic-b89458d6c" has successfully progressed. + reason: NewReplicaSetAvailable + status: 'True' + type: Progressing + - lastTransitionTime: '2026-08-28T06:04:13Z' + lastUpdateTime: '2026-08-28T06:04:13Z' + message: Deployment has minimum availability. + reason: MinimumReplicasAvailable + status: 'True' + type: Available + observedGeneration: 93 + readyReplicas: 1 + replicas: 1 + terminatingReplicas: 0 + updatedReplicas: 1 +--- +apiVersion: v1 +kind: Service +metadata: + name: sonic-svc + namespace: default +spec: + internalTrafficPolicy: Cluster + ipFamilies: + - IPv4 + ipFamilyPolicy: SingleStack + ports: + - port: 1491 + protocol: TCP + targetPort: 1491 + selector: + app: sonic + sessionAffinity: None + type: ClusterIP +status: + loadBalancer: {} diff --git a/apps/default/stirlingpdf.yaml b/apps/default/stirlingpdf.yaml new file mode 100644 index 0000000..7d19c18 --- /dev/null +++ b/apps/default/stirlingpdf.yaml @@ -0,0 +1,157 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app: stirlingpdf + name: stirlingpdf + namespace: default +spec: + replicas: 1 + selector: + matchLabels: + app: stirlingpdf + strategy: + type: Recreate + template: + metadata: + labels: + app: stirlingpdf + spec: + containers: + - env: + - name: TZ + value: America/Sao_Paulo + - name: DOCKER_ENABLE_SECURITY + value: 'false' + - name: SECURITY_ENABLELOGIN + value: 'false' + image: stirlingtools/stirling-pdf:latest + imagePullPolicy: Always + name: stirlingpdf + ports: + - containerPort: 8080 + name: http + protocol: TCP + readinessProbe: + failureThreshold: 3 + httpGet: + path: / + port: 8080 + scheme: HTTP + initialDelaySeconds: 20 + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 1 + resources: + limits: + cpu: '2' + memory: 2Gi + requests: + cpu: 100m + memory: 1Gi + securityContext: + allowPrivilegeEscalation: false + runAsUser: 0 + terminationMessagePath: /dev/termination-log + terminationMessagePolicy: File + volumeMounts: + - mountPath: /configs + name: config + dnsPolicy: ClusterFirst + restartPolicy: Always + schedulerName: default-scheduler + securityContext: {} + terminationGracePeriodSeconds: 30 + volumes: + - name: config + persistentVolumeClaim: + claimName: stirlingpdf-config +status: + availableReplicas: 1 + conditions: + - lastTransitionTime: '2026-08-12T01:49:00Z' + lastUpdateTime: '2026-08-12T01:49:43Z' + message: ReplicaSet "stirlingpdf-5d9d988965" has successfully progressed. + reason: NewReplicaSetAvailable + status: 'True' + type: Progressing + - lastTransitionTime: '2026-08-28T06:05:17Z' + lastUpdateTime: '2026-08-28T06:05:17Z' + message: Deployment has minimum availability. + reason: MinimumReplicasAvailable + status: 'True' + type: Available + observedGeneration: 11 + readyReplicas: 1 + replicas: 1 + terminatingReplicas: 0 + updatedReplicas: 1 +--- +apiVersion: v1 +kind: Service +metadata: + labels: + app: stirlingpdf + name: stirlingpdf + namespace: default +spec: + internalTrafficPolicy: Cluster + ipFamilies: + - IPv4 + ipFamilyPolicy: SingleStack + ports: + - name: http + port: 8080 + protocol: TCP + targetPort: http + selector: + app: stirlingpdf + sessionAffinity: None + type: ClusterIP +status: + loadBalancer: {} +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + labels: + app: stirlingpdf + name: stirlingpdf + namespace: default +spec: + ingressClassName: nginx + rules: + - host: stirling.haven + http: + paths: + - backend: + service: + name: stirlingpdf + port: + number: 8080 + path: / + pathType: Prefix +status: + loadBalancer: + ingress: + - ip: 192.168.20.204 +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: stirlingpdf-config + namespace: default +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi + storageClassName: nfs-client + volumeMode: Filesystem +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound diff --git a/apps/default/uptimekuma.yaml b/apps/default/uptimekuma.yaml new file mode 100644 index 0000000..3ce9a8b --- /dev/null +++ b/apps/default/uptimekuma.yaml @@ -0,0 +1,155 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: uptimekuma + namespace: default +spec: + replicas: 1 + selector: + matchLabels: + app: uptimekuma + strategy: + type: Recreate + template: + metadata: + labels: + app: uptimekuma + spec: + containers: + - env: + - name: PUID + value: '1000' + - name: PGID + value: '1000' + image: louislam/uptime-kuma:2 + imagePullPolicy: Always + livenessProbe: + failureThreshold: 3 + httpGet: + path: / + port: 3001 + scheme: HTTP + initialDelaySeconds: 30 + periodSeconds: 60 + successThreshold: 1 + timeoutSeconds: 1 + name: uptimekuma + ports: + - containerPort: 3001 + name: uptimekuma-port + protocol: TCP + readinessProbe: + failureThreshold: 3 + httpGet: + path: / + port: 3001 + scheme: HTTP + initialDelaySeconds: 5 + periodSeconds: 5 + successThreshold: 1 + timeoutSeconds: 1 + resources: + limits: + cpu: 500m + memory: 256Mi + requests: + cpu: 100m + memory: 128Mi + terminationMessagePath: /dev/termination-log + terminationMessagePolicy: File + volumeMounts: + - mountPath: /app/data + name: uptimekuma-config + dnsPolicy: ClusterFirst + restartPolicy: Always + schedulerName: default-scheduler + securityContext: {} + terminationGracePeriodSeconds: 30 + volumes: + - name: uptimekuma-config + persistentVolumeClaim: + claimName: uptimekuma-config +status: + availableReplicas: 1 + conditions: + - lastTransitionTime: '2026-05-19T01:51:48Z' + lastUpdateTime: '2026-07-22T10:17:49Z' + message: ReplicaSet "uptimekuma-5cdbf7d589" has successfully progressed. + reason: NewReplicaSetAvailable + status: 'True' + type: Progressing + - lastTransitionTime: '2026-08-28T06:04:55Z' + lastUpdateTime: '2026-08-28T06:04:55Z' + message: Deployment has minimum availability. + reason: MinimumReplicasAvailable + status: 'True' + type: Available + observedGeneration: 94 + readyReplicas: 1 + replicas: 1 + terminatingReplicas: 0 + updatedReplicas: 1 +--- +apiVersion: v1 +kind: Service +metadata: + name: uptimekuma + namespace: default +spec: + internalTrafficPolicy: Cluster + ipFamilies: + - IPv4 + ipFamilyPolicy: SingleStack + ports: + - port: 3001 + protocol: TCP + targetPort: uptimekuma-port + selector: + app: uptimekuma + sessionAffinity: None + type: ClusterIP +status: + loadBalancer: {} +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: uptimekuma + namespace: default +spec: + ingressClassName: nginx + rules: + - host: uptimekuma.haven + http: + paths: + - backend: + service: + name: uptimekuma + port: + number: 3001 + path: / + pathType: Prefix +status: + loadBalancer: + ingress: + - ip: 192.168.20.204 +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: uptimekuma-config + namespace: default +spec: + accessModes: + - ReadWriteMany + resources: + requests: + storage: 1Gi + storageClassName: nfs-client + volumeMode: Filesystem +status: + accessModes: + - ReadWriteMany + capacity: + storage: 1Gi + phase: Bound diff --git a/apps/default/vaultwarden.yaml b/apps/default/vaultwarden.yaml new file mode 100644 index 0000000..e3e67c3 --- /dev/null +++ b/apps/default/vaultwarden.yaml @@ -0,0 +1,152 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: vaultwarden + namespace: default +spec: + replicas: 1 + selector: + matchLabels: + app: vaultwarden + strategy: + type: Recreate + template: + metadata: + labels: + app: vaultwarden + spec: + containers: + - env: + - name: DOMAIN + value: https://vault.haven + - name: ADMIN_TOKEN + valueFrom: + secretKeyRef: + key: ADMIN_TOKEN + name: vaultwarden-admin-token + image: vaultwarden/server:latest + imagePullPolicy: Always + livenessProbe: + failureThreshold: 6 + httpGet: + path: /alive + port: vault-port + scheme: HTTP + periodSeconds: 15 + successThreshold: 1 + timeoutSeconds: 3 + name: vaultwarden + ports: + - containerPort: 80 + name: vault-port + protocol: TCP + readinessProbe: + failureThreshold: 3 + httpGet: + path: /alive + port: vault-port + scheme: HTTP + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 3 + resources: + limits: + cpu: 250m + memory: 256Mi + requests: + cpu: 250m + memory: 64Mi + startupProbe: + failureThreshold: 30 + httpGet: + path: /alive + port: vault-port + scheme: HTTP + periodSeconds: 5 + successThreshold: 1 + timeoutSeconds: 3 + terminationMessagePath: /dev/termination-log + terminationMessagePolicy: File + volumeMounts: + - mountPath: /data + name: vaultwarden-data + dnsPolicy: ClusterFirst + restartPolicy: Always + schedulerName: default-scheduler + securityContext: {} + terminationGracePeriodSeconds: 30 + volumes: + - name: vaultwarden-data + persistentVolumeClaim: + claimName: vaultwarden-data +apiVersion: v1 +kind: Service +metadata: + name: vaultwarden + namespace: default +spec: + internalTrafficPolicy: Cluster + ipFamilies: + - IPv4 + ipFamilyPolicy: SingleStack + ports: + - port: 80 + protocol: TCP + targetPort: vault-port + selector: + app: vaultwarden + sessionAffinity: None + type: ClusterIP +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: vaultwarden + namespace: default +spec: + ingressClassName: nginx + rules: + - host: vault.haven + http: + paths: + - backend: + service: + name: vaultwarden + port: + number: 80 + path: / + pathType: Prefix + tls: + - hosts: + - vault.haven + secretName: vaultwarden-tls +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: vaultwarden-public + namespace: default +spec: + ingressClassName: nginx + rules: + - host: vault.ivanch.me + http: + paths: + - backend: + service: + name: vaultwarden + port: + number: 80 + path: / + pathType: Prefix +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: vaultwarden-data + namespace: default +spec: + accessModes: + - ReadWriteMany + resources: + requests: + storage: 1Gi + storageClassName: nfs-client + volumeMode: Filesystem diff --git a/apps/root/applicationset.yaml b/apps/root/applicationset.yaml index eab94ec..5738808 100644 --- a/apps/root/applicationset.yaml +++ b/apps/root/applicationset.yaml @@ -4,15 +4,22 @@ metadata: name: haven-apps namespace: argocd spec: + goTemplate: true + goTemplateOptions: ["missingkey=error"] generators: - git: repoURL: https://git.ivanch.me/ivanch/haven-ops.git revision: main files: + # one Application per .yaml under apps// - path: "apps/*/*.yaml" + # never generate apps for the bootstrap/root manifests themselves + - path: "apps/root/*.yaml" + exclude: true template: metadata: - name: "{{path.filenameNormalized}}" + # apps/default/notepad.yaml -> Application "notepad" + name: '{{ .path.filename | trimSuffix ".yaml" }}' namespace: argocd finalizers: - resources-finalizer.argocd.argoproj.io @@ -21,12 +28,13 @@ spec: source: repoURL: https://git.ivanch.me/ivanch/haven-ops.git targetRevision: main - path: "{{path}}" + # in the git files generator .path.path IS the containing directory + path: '{{ .path.path }}' directory: - include: "{{path.filename}}" + include: '{{ .path.filename }}' destination: server: https://kubernetes.default.svc - namespace: "{{path[1]}}" + namespace: '{{ index .path.segments 1 }}' syncPolicy: automated: prune: true diff --git a/bootstrap/argocd-install/kustomization.yaml b/bootstrap/argocd-install/kustomization.yaml index d9b6492..728dbbf 100644 --- a/bootstrap/argocd-install/kustomization.yaml +++ b/bootstrap/argocd-install/kustomization.yaml @@ -4,7 +4,9 @@ kind: Kustomization namespace: argocd resources: - - https://github.com/argoproj/argo-cd.git/manifests/crds?ref=stable + # cluster-install already includes ALL CRDs (applications, appprojects, + # applicationsets). Do NOT also add manifests/crds — kustomize fails with + # "may not add resource with an already registered id". - https://github.com/argoproj/argo-cd.git/manifests/cluster-install?ref=stable - ingress.yaml diff --git a/tools/validate_all.sh b/tools/validate_all.sh new file mode 100644 index 0000000..0af6b9d --- /dev/null +++ b/tools/validate_all.sh @@ -0,0 +1,17 @@ +#!/bin/bash +# Dry-run validate every app manifest in apps/default/ against live cluster +export KUBECONFIG="C:\\Users\\ivanch\\.kube\\config" +cd "C:/Users/ivanch/Desktop/gitops-draft" || exit 1 +fail=0 +for f in apps/default/*.yaml; do + out=$(kubectl.exe apply --dry-run=server -f "$f" 2>&1) + if echo "$out" | grep -qi "error"; then + echo "FAIL: $f" + echo "$out" | grep -i error | head -2 + fail=1 + else + echo "OK: $f" + fi +done +[ $fail -eq 0 ] && echo "ALL apps/default dry-runs clean" +exit $fail