From 4ddc5e015189acdcc0dd5d44e7a9ec2c1df56d8c Mon Sep 17 00:00:00 2001 From: ahmza Date: Fri, 9 Oct 2026 10:41:09 +0000 Subject: [PATCH] added soulsync 3.5.3 --- apps/soulsync.yaml | 26 +++++++ apps/soulsync/deployment.yaml | 129 ++++++++++++++++++++++++++++++++++ apps/soulsync/ingress.yaml | 28 ++++++++ apps/soulsync/namespace.yaml | 4 ++ apps/soulsync/pvc.yaml | 41 +++++++++++ apps/soulsync/service.yaml | 12 ++++ docs/network.md | 7 +- 7 files changed, 245 insertions(+), 2 deletions(-) create mode 100644 apps/soulsync.yaml create mode 100644 apps/soulsync/deployment.yaml create mode 100644 apps/soulsync/ingress.yaml create mode 100644 apps/soulsync/namespace.yaml create mode 100644 apps/soulsync/pvc.yaml create mode 100644 apps/soulsync/service.yaml diff --git a/apps/soulsync.yaml b/apps/soulsync.yaml new file mode 100644 index 0000000..cbc575f --- /dev/null +++ b/apps/soulsync.yaml @@ -0,0 +1,26 @@ +# This ArgoCD application deploys soulsync to manage media discovery. +# The Deployment pins a reviewed SoulSync release for repeatable GitOps syncs. +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: soulsync + namespace: argocd + # skipping resources-finalizer.argocd.argoproj.io as soulsync will create configs +spec: + project: default + + source: + repoURL: https://tea.ahmza.com/ahmza.com/k8s-starter-pack.git + targetRevision: main + path: apps/soulsync + + destination: + server: https://kubernetes.default.svc + namespace: soulsync + + syncPolicy: + automated: + prune: true + selfHeal: true + syncOptions: + - CreateNamespace=true diff --git a/apps/soulsync/deployment.yaml b/apps/soulsync/deployment.yaml new file mode 100644 index 0000000..8d31db2 --- /dev/null +++ b/apps/soulsync/deployment.yaml @@ -0,0 +1,129 @@ +# Pin SoulSync so an upstream `latest` update cannot change the running app +# without a reviewed Git commit. +apiVersion: apps/v1 +kind: Deployment +metadata: + name: soulsync + namespace: soulsync +spec: + # not critical infra, a single pod should suffice + replicas: 1 + strategy: + type: Recreate + selector: + matchLabels: + app: soulsync + template: + metadata: + labels: + app: soulsync + spec: + containers: + - name: soulsync + image: boulderbadgedad/soulsync:3.5.3 + imagePullPolicy: IfNotPresent + env: + - name: PUID + value: "1000" + - name: PGID + value: "1000" + - name: UMASK + value: "022" + - name: PYTHONPATH + value: "/app" + - name: SOULSYNC_CONFIG_PATH + value: "/app/config/config.json" + - name: TZ + value: "Europe/London" + ports: + # HTTPS terminates at ingress-nginx, which forwards the UI and both + # OAuth callback paths to SoulSync's main web server on this port. + - name: http + containerPort: 8008 + protocol: TCP + # Kubernetes ignores the Docker image's HEALTHCHECK, so define probes + # here to keep traffic away until SoulSync has actually started and to + # restart it if its web server later stops responding. + startupProbe: + httpGet: + path: / + port: http + periodSeconds: 5 + timeoutSeconds: 3 + failureThreshold: 24 + readinessProbe: + httpGet: + path: / + port: http + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 3 + livenessProbe: + httpGet: + path: / + port: http + periodSeconds: 30 + timeoutSeconds: 10 + failureThreshold: 3 + # Match the upstream Compose defaults: scheduling reserves enough for + # normal operation while limits protect the rest of the cluster. + resources: + requests: + cpu: 500m + memory: 512Mi + limits: + cpu: "2" + memory: 2Gi + volumeMounts: + - name: soulsync-db + mountPath: /app/data + - name: soulsync-config + mountPath: /app/config + - name: soulsync-logs + mountPath: /app/logs + - name: downloads + mountPath: /app/downloads + - name: music + mountPath: /app/Transfer + - name: podcasts + mountPath: /app/podcasts + - name: audiobooks + mountPath: /app/audiobooks + - name: movies + mountPath: /media/movies + - name: tvshows + mountPath: /media/tv + volumes: + - name: soulsync-db + persistentVolumeClaim: + claimName: soulsync-db + - name: soulsync-config + persistentVolumeClaim: + claimName: soulsync-config + - name: soulsync-logs + persistentVolumeClaim: + claimName: soulsync-logs + - name: downloads + nfs: + server: nas.ahmza.com + path: /srv/media/torrents + - name: music + nfs: + server: nas.ahmza.com + path: /srv/media/Music + - name: podcasts + nfs: + server: nas.ahmza.com + path: /srv/media/Podcasts + - name: audiobooks + nfs: + server: nas.ahmza.com + path: /srv/media/Audiobooks + - name: movies + nfs: + server: nas.ahmza.com + path: /srv/media/Movies + - name: tvshows + nfs: + server: nas.ahmza.com + path: /srv/media/TVShows diff --git a/apps/soulsync/ingress.yaml b/apps/soulsync/ingress.yaml new file mode 100644 index 0000000..48a3171 --- /dev/null +++ b/apps/soulsync/ingress.yaml @@ -0,0 +1,28 @@ +# routes for soulsync.ahmza.com through ingress-nginx (docs/11-ingress.md) +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: soulsync + namespace: soulsync + annotations: + cert-manager.io/cluster-issuer: letsencrypt-prod +spec: + # Select ingress-nginx explicitly rather than relying on whichever ingress + # controller happens to be configured as the cluster-wide default. + ingressClassName: nginx + tls: + - hosts: + - soulsync.ahmza.com + # cert-manager keeps this up to date. nothing to do by hand + secretName: soulsync-tls + rules: + - host: soulsync.ahmza.com + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: soulsync + port: + number: 8008 diff --git a/apps/soulsync/namespace.yaml b/apps/soulsync/namespace.yaml new file mode 100644 index 0000000..bdb82a7 --- /dev/null +++ b/apps/soulsync/namespace.yaml @@ -0,0 +1,4 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: soulsync diff --git a/apps/soulsync/pvc.yaml b/apps/soulsync/pvc.yaml new file mode 100644 index 0000000..5c53eaf --- /dev/null +++ b/apps/soulsync/pvc.yaml @@ -0,0 +1,41 @@ +# Keep SoulSync's databases and downloaded artwork on Longhorn so they survive +# Pod replacement (see docs/06-longhorn.md). +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: soulsync-db + namespace: soulsync +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 10Gi +--- +# Configuration can contain connection settings and OAuth tokens, so persist it +# without putting those credentials in this public Git repository. +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: soulsync-config + namespace: soulsync +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi +--- +# Persistent logs remain available when the container is recreated and make +# failures that happened before a restart easier to diagnose. +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: soulsync-logs + namespace: soulsync +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 2Gi diff --git a/apps/soulsync/service.yaml b/apps/soulsync/service.yaml new file mode 100644 index 0000000..c3bd37c --- /dev/null +++ b/apps/soulsync/service.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: Service +metadata: + name: soulsync + namespace: soulsync +spec: + selector: + app: soulsync + ports: + - name: http + port: 8008 + targetPort: http diff --git a/docs/network.md b/docs/network.md index edc8c26..d1170d4 100644 --- a/docs/network.md +++ b/docs/network.md @@ -61,13 +61,16 @@ only when it's the protocol default (80 for `http://`, 443 for `https://`) ## Hostnames routed through ingress-nginx -Every real DNS record pointing at ingress-nginx's shared address -(`10.10.60.12`), and which app it reaches. All hosted on Cloudflare. +Every real hostname routed to ingress-nginx's shared address +(`10.10.60.12`), and which app it reaches. Public DNS is hosted on +Cloudflare; internal overrides are served by Technitium where noted. | Hostname | App | Namespace | TLS | Source | |---|---|---|---|---| | `demo.ahmza.com` | Demo app | `demo` | Yes — `letsencrypt-prod`, real trusted cert (see [`docs/12-cert-manager.md`](12-cert-manager.md)) | [`apps/demo/ingress.yaml`](../apps/demo/ingress.yaml) | | `mc.ahmza.com` | Packwiz modpack files | `mcpacks` | Yes — `letsencrypt-prod`, real trusted certificate | [`apps/mcpacks/ingress.yaml`](../apps/mcpacks/ingress.yaml) | +| `bazarr.ahmza.com` | Bazarr subtitle manager | `bazarr` | Yes — `letsencrypt-prod`, real trusted certificate; Technitium overrides Cloudflare's NetBird route on the LAN | [`apps/bazarr/ingress.yaml`](../apps/bazarr/ingress.yaml) | +| `soulsync.ahmza.com` | SoulSync media discovery | `soulsync` | Configured for `letsencrypt-prod`; verify the certificate after the first deployment; Technitium routes LAN clients to `10.10.60.12` | [`apps/soulsync/ingress.yaml`](../apps/soulsync/ingress.yaml) | Add a row here every time you point a new hostname at this cluster (see [`docs/11-ingress.md`](11-ingress.md)). The DNS record itself lives in