diff --git a/apps/default/archivebox.yaml b/apps/default/archivebox.yaml index 912fb3c..3e674ce 100644 --- a/apps/default/archivebox.yaml +++ b/apps/default/archivebox.yaml @@ -1,3 +1,39 @@ +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: sonic + namespace: default +spec: + replicas: 1 + selector: + matchLabels: + app: sonic + template: + metadata: + labels: + app: sonic + spec: + containers: + - name: sonic + image: archivebox/sonic:latest + imagePullPolicy: Always + ports: + - containerPort: 1491 + env: + - name: SEARCH_BACKEND_PASSWORD + valueFrom: + secretKeyRef: + name: password + key: password + resources: + requests: + memory: "64Mi" + cpu: "50m" + limits: + memory: "128Mi" + cpu: "200m" +--- apiVersion: apps/v1 kind: Deployment metadata: @@ -8,80 +44,69 @@ spec: 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 + - name: archivebox + image: archivebox/archivebox:latest + imagePullPolicy: Always + ports: + - containerPort: 8000 + 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: + name: password + key: password + - name: ADMIN_USERNAME + value: "ivanch" + - name: ADMIN_PASSWORD + valueFrom: + secretKeyRef: + name: password + key: password + - name: CSRF_TRUSTED_ORIGINS + value: "archive.haven" + - name: ALLOWED_HOSTS + value: "*" + - name: PUBLIC_ADD_VIEW + value: "false" + volumeMounts: + - name: archivebox-data + mountPath: /data + resources: + requests: + memory: "256Mi" + cpu: "100m" + limits: + memory: "2Gi" + cpu: "3000m" 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 + - name: archivebox-data + persistentVolumeClaim: + claimName: archivebox-data +--- +apiVersion: v1 +kind: Service +metadata: + name: sonic-svc + namespace: default +spec: + selector: + app: sonic + ports: + - protocol: TCP + port: 1491 + targetPort: 1491 --- apiVersion: v1 kind: Service @@ -89,20 +114,30 @@ 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: {} + ports: + - protocol: TCP + port: 8000 + targetPort: 8000 +--- +# 3) PersistentVolumeClaim +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: archivebox-data + namespace: default + annotations: + nfs.io/storage-path: "archivebox-data" +spec: + storageClassName: "nfs-client" + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 10Gi + limits: + storage: 30Gi --- apiVersion: networking.k8s.io/v1 kind: Ingress @@ -112,39 +147,13 @@ metadata: 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 + - host: "archive.haven" + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: archivebox-svc + port: + number: 8000 diff --git a/apps/default/changedetection.yaml b/apps/default/changedetection.yaml index 479575a..b380ce0 100644 --- a/apps/default/changedetection.yaml +++ b/apps/default/changedetection.yaml @@ -1,12 +1,13 @@ apiVersion: apps/v1 kind: Deployment metadata: - labels: - app.kubernetes.io/name: changedetection name: changedetection namespace: default + labels: + app.kubernetes.io/name: changedetection spec: replicas: 1 + revisionHistoryLimit: 10 selector: matchLabels: app.kubernetes.io/name: changedetection @@ -20,170 +21,134 @@ spec: affinity: nodeAffinity: preferredDuringSchedulingIgnoredDuringExecution: - - preference: - matchExpressions: - - key: kubernetes.io/hostname - operator: In - values: - - iris - weight: 100 + - weight: 100 + preference: + matchExpressions: + - key: kubernetes.io/hostname + operator: In + values: + - iris 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 + - name: changedetection + image: lscr.io/linuxserver/changedetection.io:latest + imagePullPolicy: Always + 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" + ports: + - containerPort: 5000 + name: http + protocol: TCP + resources: + requests: + cpu: 100m + memory: 256Mi + limits: + cpu: 2000m + memory: 1Gi + securityContext: + allowPrivilegeEscalation: false + runAsUser: 0 + volumeMounts: + - name: config + mountPath: /config + - name: browser-sockpuppet-chrome + image: dgtlmoon/sockpuppetbrowser:latest + imagePullPolicy: Always + env: + - name: SCREEN_WIDTH + value: "1920" + - name: SCREEN_HEIGHT + value: "1024" + - name: SCREEN_DEPTH + value: "16" + - name: MAX_CONCURRENT_CHROME_PROCESSES + value: "10" + ports: + - containerPort: 3000 + name: ws + protocol: TCP + resources: + requests: + cpu: 100m + memory: 256Mi + limits: + cpu: 2000m + memory: 4Gi + securityContext: + allowPrivilegeEscalation: false + capabilities: + add: + - SYS_ADMIN + drop: + - ALL + volumes: + - name: config + persistentVolumeClaim: + claimName: changedetection-config 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 + labels: + app.kubernetes.io/name: changedetection spec: - internalTrafficPolicy: Cluster - ipFamilies: - - IPv4 - ipFamilyPolicy: SingleStack - ports: - - name: http - port: 5000 - protocol: TCP - targetPort: http + type: ClusterIP 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 + ports: + - name: http + port: 5000 + protocol: TCP + targetPort: http --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: changedetection-config namespace: default + annotations: + nfs.io/storage-path: "changedetection-config" spec: + storageClassName: "nfs-client" accessModes: - - ReadWriteOnce + - ReadWriteOnce resources: - limits: - storage: 2Gi requests: storage: 1Gi - storageClassName: nfs-client - volumeMode: Filesystem -status: - accessModes: - - ReadWriteOnce - capacity: - storage: 1Gi - phase: Bound + limits: + storage: 2Gi +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: changedetection + namespace: default + labels: + app.kubernetes.io/name: changedetection +spec: + ingressClassName: nginx + rules: + - host: change.haven + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: changedetection + port: + number: 5000 diff --git a/apps/default/havenllo.yaml b/apps/default/havenllo.yaml index f2128d9..c623eab 100644 --- a/apps/default/havenllo.yaml +++ b/apps/default/havenllo.yaml @@ -1,12 +1,14 @@ +--- apiVersion: apps/v1 kind: Deployment metadata: - labels: - app.kubernetes.io/name: havenllo name: havenllo namespace: default + labels: + app.kubernetes.io/name: havenllo spec: replicas: 1 + revisionHistoryLimit: 10 selector: matchLabels: app.kubernetes.io/name: havenllo @@ -18,154 +20,106 @@ spec: 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 + - name: havenllo + image: git.ivanch.me/ivanch/havenllo:latest + imagePullPolicy: Always + env: + - name: HAVENLLO_DATABASE_PATH + value: /data/havenllo.db + - name: HAVENLLO_LISTEN_ADDR + value: :8080 + ports: + - containerPort: 8080 + name: http + protocol: TCP + livenessProbe: + httpGet: + path: /api/health + port: http + scheme: HTTP + initialDelaySeconds: 10 + periodSeconds: 10 + timeoutSeconds: 2 + failureThreshold: 3 + successThreshold: 1 + readinessProbe: + httpGet: + path: /api/health + port: http + scheme: HTTP + initialDelaySeconds: 2 + periodSeconds: 5 + timeoutSeconds: 2 + failureThreshold: 3 + successThreshold: 1 + resources: + requests: + cpu: 50m + memory: 64Mi + limits: + cpu: 500m + memory: 256Mi + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + readOnlyRootFilesystem: true + runAsUser: 0 + terminationMessagePath: /dev/termination-log + terminationMessagePolicy: File + volumeMounts: + - name: data + mountPath: /data + volumes: + - name: data + persistentVolumeClaim: + claimName: havenllo-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 + labels: + app.kubernetes.io/name: havenllo spec: - internalTrafficPolicy: Cluster - ipFamilies: - - IPv4 - ipFamilyPolicy: SingleStack + type: ClusterIP + sessionAffinity: None ports: - - name: http - port: 8080 - protocol: TCP - targetPort: 8080 + - name: http + port: 8080 + protocol: TCP + targetPort: 8080 selector: app.kubernetes.io/name: havenllo - sessionAffinity: None - type: ClusterIP -status: - loadBalancer: {} + ipFamilies: + - IPv4 + ipFamilyPolicy: SingleStack + internalTrafficPolicy: Cluster --- apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: havenllo namespace: default + labels: + app.kubernetes.io/name: havenllo 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 + - host: havenllo.haven + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: havenllo + port: + number: 8080 diff --git a/apps/default/homepage.yaml b/apps/default/homepage.yaml index 5e0fa8e..9d6d64c 100644 --- a/apps/default/homepage.yaml +++ b/apps/default/homepage.yaml @@ -1,226 +1,206 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + name: homepage + namespace: default + labels: + app.kubernetes.io/name: homepage +secrets: + - name: homepage +--- +apiVersion: v1 +kind: Secret +type: kubernetes.io/service-account-token +metadata: + name: homepage + namespace: default + labels: + app.kubernetes.io/name: homepage + annotations: + kubernetes.io/service-account.name: homepage +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: homepage + labels: + app.kubernetes.io/name: homepage +rules: + - apiGroups: + - "" + resources: + - namespaces + - pods + - nodes + verbs: + - get + - list + - apiGroups: + - extensions + - networking.k8s.io + resources: + - ingresses + verbs: + - get + - list + - apiGroups: + - traefik.io + resources: + - ingressroutes + verbs: + - get + - list + - apiGroups: + - gateway.networking.k8s.io + resources: + - httproutes + - gateways + verbs: + - get + - list + - apiGroups: + - metrics.k8s.io + resources: + - nodes + - pods + verbs: + - get + - list +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: homepage + labels: + app.kubernetes.io/name: homepage +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: homepage +subjects: + - kind: ServiceAccount + name: homepage + namespace: default +--- apiVersion: apps/v1 kind: Deployment metadata: - labels: - app.kubernetes.io/name: homepage name: homepage namespace: default + labels: + app.kubernetes.io/name: homepage spec: + revisionHistoryLimit: 3 replicas: 1 + strategy: + type: RollingUpdate selector: matchLabels: app.kubernetes.io/name: homepage - strategy: - type: Recreate template: metadata: labels: app.kubernetes.io/name: homepage + annotations: + configmap.reloader/checksum: '{{ include (print $.Template.BasePath "/app/config/services.yaml") . | sha256sum }}' 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 + automountServiceAccountToken: true + enableServiceLinks: true + containers: + - name: homepage + image: "ghcr.io/gethomepage/homepage:latest" + imagePullPolicy: Always + env: + - name: HOMEPAGE_ALLOWED_HOSTS + value: "*" + ports: + - name: http + containerPort: 3000 + protocol: TCP + livenessProbe: + httpGet: + path: / + port: 3000 + initialDelaySeconds: 30 + periodSeconds: 10 + readinessProbe: + httpGet: + path: / + port: 3000 + initialDelaySeconds: 5 + periodSeconds: 5 + volumeMounts: + - name: logs + mountPath: /app/config/logs + - name: homepage-config + mountPath: /app/config + - name: homepage-config + mountPath: /app/public/images + subPath: images + resources: + requests: + memory: "128Mi" + cpu: "100m" + limits: + memory: "512Mi" + cpu: "500m" 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 + - name: homepage-config + persistentVolumeClaim: + claimName: homepage-config + - name: logs + emptyDir: {} --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: homepage-config namespace: default + annotations: + nfs.io/storage-path: "homepage-config" spec: + storageClassName: "nfs-client" accessModes: - - ReadWriteMany + - 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 +kind: Service metadata: - labels: - app.kubernetes.io/name: homepage name: homepage namespace: default + labels: + app.kubernetes.io/name: homepage +spec: + type: ClusterIP + ports: + - port: 3000 + targetPort: http + protocol: TCP + name: http + selector: + app.kubernetes.io/name: homepage +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: homepage + namespace: default + labels: + app.kubernetes.io/name: homepage +spec: + ingressClassName: nginx + rules: + - host: "homepage.haven" + http: + paths: + - path: "/" + pathType: Prefix + backend: + service: + name: homepage + port: + number: 3000 diff --git a/apps/default/it-tools.yaml b/apps/default/it-tools.yaml index c00bd12..d45234d 100644 --- a/apps/default/it-tools.yaml +++ b/apps/default/it-tools.yaml @@ -1,3 +1,4 @@ +--- apiVersion: apps/v1 kind: Deployment metadata: @@ -8,58 +9,30 @@ spec: 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 + - name: it-tools + image: corentinth/it-tools:latest + imagePullPolicy: Always + ports: + - containerPort: 80 + readinessProbe: + httpGet: + path: / + port: 80 + initialDelaySeconds: 5 + periodSeconds: 10 + resources: + requests: + memory: "64Mi" + cpu: "50m" + limits: + memory: "128Mi" + cpu: "200m" --- apiVersion: v1 kind: Service @@ -67,20 +40,12 @@ 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: {} + ports: + - protocol: TCP + port: 80 + targetPort: 80 --- apiVersion: networking.k8s.io/v1 kind: Ingress @@ -90,17 +55,13 @@ metadata: 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 + - host: "tools.haven" + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: it-tools-svc + port: + number: 80 diff --git a/apps/default/notepad.yaml b/apps/default/notepad.yaml index 4df4cb6..39ad2d4 100644 --- a/apps/default/notepad.yaml +++ b/apps/default/notepad.yaml @@ -1,34 +1,14 @@ -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - name: notepad-data - namespace: default - annotations: - nfs.io/storage-path: notepad-data -spec: - accessModes: - - ReadWriteOnce - resources: - requests: - storage: 1Gi - storageClassName: nfs-client --- apiVersion: apps/v1 kind: Deployment metadata: name: notepad namespace: default - labels: - app: notepad spec: replicas: 1 selector: matchLabels: app: notepad - # RWO PVC + single replica: Recreate avoids the two-ReplicaSet PVC fight - # on rollout (see homelab-deploy skill: single-writer state). - strategy: - type: Recreate template: metadata: labels: @@ -41,7 +21,10 @@ spec: command: - sh - -c - - mkdir -p /var/www/html/_tmp && cp -n /var/www/html/notes.htaccess /var/www/html/_tmp/.htaccess 2>/dev/null; exec docker-php-entrypoint apache2-foreground + - >- + mkdir -p /var/www/html/_tmp && + cp -n /var/www/html/notes.htaccess /var/www/html/_tmp/.htaccess 2>/dev/null; + exec docker-php-entrypoint apache2-foreground ports: - containerPort: 80 resources: @@ -58,6 +41,7 @@ spec: - name: notepad-data persistentVolumeClaim: claimName: notepad-data + --- apiVersion: v1 kind: Service @@ -72,6 +56,21 @@ spec: - port: 80 targetPort: 80 --- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: notepad-data + namespace: default + annotations: + nfs.io/storage-path: "notepad-data" +spec: + storageClassName: "nfs-client" + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi +--- apiVersion: networking.k8s.io/v1 kind: Ingress metadata: @@ -90,6 +89,3 @@ spec: name: notepad port: number: 80 -# NOTE: the Argo Application manifest for notepad lives in apps/root/notepad.yaml -# (watched by the root app-of-apps). Do not add Application objects to this -# directory — this path is what the Application itself watches. diff --git a/apps/default/openwebui.yaml b/apps/default/openwebui.yaml index ee5017c..fbab3ab 100644 --- a/apps/default/openwebui.yaml +++ b/apps/default/openwebui.yaml @@ -8,8 +8,6 @@ spec: selector: matchLabels: app: openwebui - strategy: - type: Recreate template: metadata: labels: @@ -18,103 +16,93 @@ spec: affinity: nodeAffinity: preferredDuringSchedulingIgnoredDuringExecution: - - preference: - matchExpressions: - - key: kubernetes.io/hostname - operator: In - values: - - iris - weight: 100 + - weight: 100 + preference: + matchExpressions: + - key: kubernetes.io/hostname + operator: In + values: + - iris 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 + - name: openwebui + image: ghcr.io/open-webui/open-webui:main-slim + imagePullPolicy: Always + ports: + - containerPort: 8080 + env: + - name: PUID + value: "1000" + - name: PGID + value: "1000" + - name: TZ + value: "America/Sao_Paulo" + - name: DATABASE_URL + valueFrom: + secretKeyRef: + name: openwebui-secret + key: DATABASE_URL + resources: + requests: + cpu: "250m" + memory: "512Mi" + limits: + cpu: "1000m" + memory: "2Gi" + volumeMounts: + - name: openwebui-data + mountPath: /app/backend/data volumes: - - name: openwebui-data - persistentVolumeClaim: - claimName: openwebui-data + - 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 + type: ClusterIP 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 + ports: + - port: 8080 + targetPort: 8080 +--- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: openwebui-data namespace: default + annotations: + nfs.io/storage-path: "openwebui-data" spec: + storageClassName: "nfs-client" accessModes: - - ReadWriteOnce + - ReadWriteOnce resources: - limits: - storage: 10Gi requests: storage: 5Gi - storageClassName: nfs-client - volumeMode: Filesystem + limits: + storage: 10Gi +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: openwebui + namespace: default + annotations: + nginx.ingress.kubernetes.io/proxy-body-size: "50m" +spec: + ingressClassName: nginx + rules: + - host: openwebui.haven + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: openwebui + port: + number: 8080 diff --git a/apps/default/paperless.yaml b/apps/default/paperless.yaml index 1a9e383..66932e1 100644 --- a/apps/default/paperless.yaml +++ b/apps/default/paperless.yaml @@ -1,3 +1,5 @@ +--- +# 1) Deployment apiVersion: apps/v1 kind: Deployment metadata: @@ -8,8 +10,6 @@ spec: selector: matchLabels: app: paperless - strategy: - type: Recreate template: metadata: labels: @@ -18,111 +18,119 @@ spec: affinity: nodeAffinity: preferredDuringSchedulingIgnoredDuringExecution: - - preference: - matchExpressions: - - key: kubernetes.io/hostname - operator: In - values: - - iris - weight: 100 + - weight: 100 + preference: + matchExpressions: + - key: kubernetes.io/hostname + operator: In + values: + - iris 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 + - name: paperless + image: ghcr.io/paperless-ngx/paperless-ngx:latest + imagePullPolicy: Always + 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: + name: paperless-secret + key: PAPERLESS_DBNAME + - name: PAPERLESS_DBUSER + valueFrom: + secretKeyRef: + name: paperless-secret + key: PAPERLESS_DBUSER + - name: PAPERLESS_DBPASSWORD + valueFrom: + secretKeyRef: + name: paperless-secret + key: PAPERLESS_DBPASSWORD + - name: PAPERLESS_REDIS + value: "redis://redis.haven:6379" + - name: PAPERLESS_PORT + value: "8000" + - name: PAPERLESS_SECRET_KEY + valueFrom: + secretKeyRef: + name: paperless-secret + key: PAPERLESS_SECRET_KEY + ports: + - containerPort: 8000 + name: paperless-port + resources: + requests: + cpu: "100m" + memory: "256Mi" + limits: + cpu: "4000m" + memory: "1Gi" + volumeMounts: + - name: paperless-data + subPath: data + mountPath: /usr/src/paperless/data + - name: paperless-data + subPath: media + mountPath: /usr/src/paperless/media + - name: paperless-data + subPath: export + mountPath: /usr/src/paperless/export + - name: paperless-data + subPath: consume + mountPath: /usr/src/paperless/consume volumes: - - name: paperless-data - persistentVolumeClaim: - claimName: paperless-data + - name: paperless-data + persistentVolumeClaim: + claimName: paperless-data +--- +# 2) Service apiVersion: v1 kind: Service metadata: name: paperless namespace: default spec: - internalTrafficPolicy: Cluster - ipFamilies: - - IPv4 - ipFamilyPolicy: SingleStack - ports: - - port: 8000 - protocol: TCP - targetPort: paperless-port + type: ClusterIP selector: app: paperless - sessionAffinity: None - type: ClusterIP + ports: + - port: 8000 + targetPort: paperless-port +--- +# 3) PersistentVolumeClaim +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: paperless-data + namespace: default + annotations: + nfs.io/storage-path: "paperless-data" +spec: + storageClassName: "nfs-client" + accessModes: + - ReadWriteMany + resources: + requests: + storage: 5Gi + limits: + storage: 15Gi +--- +# 4) Ingress apiVersion: networking.k8s.io/v1 kind: Ingress metadata: @@ -131,28 +139,13 @@ metadata: 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 + - host: paperless.haven + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: paperless + port: + number: 8000 diff --git a/apps/default/qbittorrent.yaml b/apps/default/qbittorrent.yaml index 6ff664e..d03e7a7 100644 --- a/apps/default/qbittorrent.yaml +++ b/apps/default/qbittorrent.yaml @@ -1,3 +1,5 @@ +--- +# 1) Deployment apiVersion: apps/v1 kind: Deployment metadata: @@ -8,8 +10,6 @@ spec: selector: matchLabels: app: qbittorrent - strategy: - type: Recreate template: metadata: labels: @@ -18,159 +18,115 @@ spec: affinity: nodeAffinity: preferredDuringSchedulingIgnoredDuringExecution: - - preference: + - weight: 100 + 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 + - name: qbittorrent + image: lscr.io/linuxserver/qbittorrent:5.0.4 + imagePullPolicy: Always + resources: + requests: + cpu: 200m + memory: 256Mi + limits: + cpu: 1000m + memory: 512Mi + ports: + - containerPort: 4300 + name: webui-port + - containerPort: 6881 + name: qbit-tcp + protocol: TCP + - containerPort: 6881 + name: qbit-udp + protocol: UDP + env: + - name: PUID + value: "1000" + - name: PGID + value: "1000" + - name: TZ + value: "Etc/UTC" + - name: WEBUI_PORT + value: "4300" + - name: TORRENTING_PORT + value: "6881" + volumeMounts: + - name: qbittorrent-config + mountPath: /config + - name: nas-storage + mountPath: /nas 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 + - name: qbittorrent-config + persistentVolumeClaim: + claimName: qbittorrent-config + - name: nas-storage + nfs: + server: 192.168.15.99 + path: /export/Storage --- +# PVC +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: qbittorrent-config + namespace: default + annotations: + nfs.io/storage-path: "qbittorrent-config" +spec: + storageClassName: "nfs-client" + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi +--- +# 2) Service 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 + type: NodePort selector: app: qbittorrent - sessionAffinity: None - type: NodePort -status: - loadBalancer: {} + ports: + - port: 4300 + targetPort: webui-port + name: webui + - port: 6881 + targetPort: qbit-tcp + name: torrent-tcp + protocol: TCP + - port: 6881 + targetPort: qbit-udp + name: torrent-udp + protocol: UDP --- +# 4) Ingress (Traefik) apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: qbittorrent namespace: default + annotations: + traefik.ingress.kubernetes.io/router.entrypoints: web 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 + - host: qbittorrent.haven + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: qbittorrent + port: + number: 4300 \ No newline at end of file diff --git a/apps/default/searxng.yaml b/apps/default/searxng.yaml index 855c53d..21a4b46 100644 --- a/apps/default/searxng.yaml +++ b/apps/default/searxng.yaml @@ -1,3 +1,5 @@ +--- +# 1) Deployment apiVersion: apps/v1 kind: Deployment metadata: @@ -8,90 +10,70 @@ spec: 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 + containers: + - name: searxng + image: searxng/searxng:latest + imagePullPolicy: Always + env: + - name: PUID + value: "1000" + - name: PGID + value: "1000" + ports: + - containerPort: 8080 + name: searxng-port + resources: + requests: + cpu: "100m" + memory: "256Mi" + limits: + cpu: "500m" + memory: "512Mi" + volumeMounts: + - name: searxng-config + mountPath: /etc/searxng 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 + - name: searxng-config + persistentVolumeClaim: + claimName: searxng-config --- +# 2) Service apiVersion: v1 kind: Service metadata: name: searxng namespace: default spec: - internalTrafficPolicy: Cluster - ipFamilies: - - IPv4 - ipFamilyPolicy: SingleStack - ports: - - port: 8080 - protocol: TCP - targetPort: searxng-port + type: ClusterIP selector: app: searxng - sessionAffinity: None - type: ClusterIP -status: - loadBalancer: {} + ports: + - port: 8080 + targetPort: searxng-port --- +# 3) PersistentVolumeClaim +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: searxng-config + namespace: default + annotations: + nfs.io/storage-path: "searxng-config" +spec: + storageClassName: "nfs-client" + accessModes: + - ReadWriteMany + resources: + requests: + storage: 1Gi +--- +# 4) Ingress apiVersion: networking.k8s.io/v1 kind: Ingress metadata: @@ -100,37 +82,13 @@ metadata: 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 + - host: search.haven + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: searxng + port: + number: 8080 \ No newline at end of file diff --git a/apps/default/sonic.yaml b/apps/default/sonic.yaml deleted file mode 100644 index aa2a364..0000000 --- a/apps/default/sonic.yaml +++ /dev/null @@ -1,79 +0,0 @@ -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 index 7d19c18..384a5f4 100644 --- a/apps/default/stirlingpdf.yaml +++ b/apps/default/stirlingpdf.yaml @@ -1,157 +1,113 @@ +--- +# 1) Deployment - Stirling-PDF apiVersion: apps/v1 kind: Deployment metadata: - labels: - app: stirlingpdf name: stirlingpdf namespace: default + labels: + app: stirlingpdf 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 + - name: stirlingpdf + image: stirlingtools/stirling-pdf:latest + imagePullPolicy: Always + env: + - name: TZ + value: "America/Sao_Paulo" + - name: DOCKER_ENABLE_SECURITY + value: "false" + - name: SECURITY_ENABLELOGIN + value: "false" + ports: + - containerPort: 8080 + name: http + readinessProbe: + httpGet: + path: / + port: 8080 + initialDelaySeconds: 20 + periodSeconds: 10 + resources: + requests: + cpu: 100m + memory: 1Gi + limits: + cpu: 2000m + memory: 2Gi + securityContext: + allowPrivilegeEscalation: false + runAsUser: 0 + volumeMounts: + - name: config + mountPath: /configs 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 + - name: config + persistentVolumeClaim: + claimName: stirlingpdf-config + terminationGracePeriodSeconds: 30 --- +# 2) Service apiVersion: v1 kind: Service metadata: - labels: - app: stirlingpdf name: stirlingpdf namespace: default + labels: + app: stirlingpdf spec: - internalTrafficPolicy: Cluster - ipFamilies: - - IPv4 - ipFamilyPolicy: SingleStack - ports: - - name: http - port: 8080 - protocol: TCP - targetPort: http + type: ClusterIP 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 + ports: + - name: http + port: 8080 + protocol: TCP + targetPort: http --- +# 3) PersistentVolumeClaim apiVersion: v1 kind: PersistentVolumeClaim metadata: name: stirlingpdf-config namespace: default + annotations: + nfs.io/storage-path: "stirlingpdf-config" spec: + storageClassName: "nfs-client" accessModes: - - ReadWriteOnce + - ReadWriteOnce resources: requests: storage: 1Gi - storageClassName: nfs-client - volumeMode: Filesystem -status: - accessModes: - - ReadWriteOnce - capacity: - storage: 1Gi - phase: Bound +--- +# 4) Ingress +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: stirlingpdf + namespace: default + labels: + app: stirlingpdf +spec: + ingressClassName: nginx + rules: + - host: stirling.haven + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: stirlingpdf + port: + number: 8080 diff --git a/apps/default/uptimekuma.yaml b/apps/default/uptimekuma.yaml index 3ce9a8b..0158634 100644 --- a/apps/default/uptimekuma.yaml +++ b/apps/default/uptimekuma.yaml @@ -1,3 +1,5 @@ +--- +# 1) Deployment apiVersion: apps/v1 kind: Deployment metadata: @@ -5,112 +7,86 @@ metadata: namespace: default spec: replicas: 1 + strategy: + type: Recreate 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 + - name: uptimekuma + image: louislam/uptime-kuma:2 + imagePullPolicy: Always + env: + - name: PUID + value: "1000" + - name: PGID + value: "1000" + ports: + - containerPort: 3001 + name: uptimekuma-port + resources: + requests: + memory: "128Mi" + cpu: "100m" + limits: + memory: "256Mi" + cpu: "500m" + livenessProbe: + httpGet: + path: / + port: 3001 + initialDelaySeconds: 30 + periodSeconds: 60 + readinessProbe: + httpGet: + path: / + port: 3001 + initialDelaySeconds: 5 + periodSeconds: 5 + volumeMounts: + - name: uptimekuma-config + mountPath: /app/data 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 + - name: uptimekuma-config + persistentVolumeClaim: + claimName: uptimekuma-config --- +# 2) Service apiVersion: v1 kind: Service metadata: name: uptimekuma namespace: default spec: - internalTrafficPolicy: Cluster - ipFamilies: - - IPv4 - ipFamilyPolicy: SingleStack - ports: - - port: 3001 - protocol: TCP - targetPort: uptimekuma-port + type: ClusterIP selector: app: uptimekuma - sessionAffinity: None - type: ClusterIP -status: - loadBalancer: {} + ports: + - port: 3001 + targetPort: uptimekuma-port --- +# 3) PersistentVolumeClaim +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: uptimekuma-config + namespace: default + annotations: + nfs.io/storage-path: "uptimekuma-config" +spec: + storageClassName: "nfs-client" + accessModes: + - ReadWriteMany + resources: + requests: + storage: 1Gi +--- +# 4) Ingress apiVersion: networking.k8s.io/v1 kind: Ingress metadata: @@ -119,37 +95,13 @@ metadata: 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 + - host: uptimekuma.haven + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: uptimekuma + port: + number: 3001 \ No newline at end of file diff --git a/apps/default/vaultwarden.yaml b/apps/default/vaultwarden.yaml index e3e67c3..6cc5ace 100644 --- a/apps/default/vaultwarden.yaml +++ b/apps/default/vaultwarden.yaml @@ -1,3 +1,5 @@ +--- +# 1) Deployment apiVersion: apps/v1 kind: Deployment metadata: @@ -8,117 +10,124 @@ spec: 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 + - name: vaultwarden + image: vaultwarden/server:latest + imagePullPolicy: Always + env: + - name: DOMAIN + value: "https://vault.haven" + - name: ADMIN_TOKEN + valueFrom: + secretKeyRef: + name: vaultwarden-admin-token + key: ADMIN_TOKEN + ports: + - containerPort: 80 + name: vault-port + # /alive requires no authentication and verifies the Vaultwarden process + startupProbe: + httpGet: + path: /alive + port: vault-port + scheme: HTTP + periodSeconds: 5 + timeoutSeconds: 3 + failureThreshold: 30 + readinessProbe: + httpGet: + path: /alive + port: vault-port + scheme: HTTP + periodSeconds: 10 + timeoutSeconds: 3 + failureThreshold: 3 + livenessProbe: + httpGet: + path: /alive + port: vault-port + scheme: HTTP + periodSeconds: 15 + timeoutSeconds: 3 + failureThreshold: 6 + volumeMounts: + - name: vaultwarden-data + mountPath: /data + resources: + requests: + cpu: 250m + memory: 64Mi + limits: + cpu: 250m + memory: 256Mi volumes: - - name: vaultwarden-data - persistentVolumeClaim: - claimName: vaultwarden-data + - name: vaultwarden-data + persistentVolumeClaim: + claimName: vaultwarden-data +--- +# 2) Service apiVersion: v1 kind: Service metadata: name: vaultwarden namespace: default spec: - internalTrafficPolicy: Cluster - ipFamilies: - - IPv4 - ipFamilyPolicy: SingleStack - ports: - - port: 80 - protocol: TCP - targetPort: vault-port + type: ClusterIP selector: app: vaultwarden - sessionAffinity: None - type: ClusterIP + ports: + - port: 80 + targetPort: vault-port +--- +# 3) PersistentVolumeClaim (for /data) +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: vaultwarden-data + namespace: default + annotations: + nfs.io/storage-path: "vaultwarden-data" +spec: + storageClassName: "nfs-client" + accessModes: + - ReadWriteMany + resources: + requests: + storage: 1Gi +--- +# 4) Ingress apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: vaultwarden namespace: default + annotations: + cert-manager.io/cluster-issuer: internal-ca + nginx.ingress.kubernetes.io/force-ssl-redirect: "true" 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 + - hosts: + - vault.haven + secretName: vaultwarden-tls + rules: + - host: vault.haven + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: vaultwarden + port: + number: 80 +--- +# 4) Ingress apiVersion: networking.k8s.io/v1 kind: Ingress metadata: @@ -127,26 +136,13 @@ metadata: 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 + - host: vault.ivanch.me + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: vaultwarden + port: + number: 80