From a83d66e50259ff00b66e2c03b1af8bdfe3ff95c2 Mon Sep 17 00:00:00 2001 From: "azykov@mail.ru" Date: Sun, 23 Aug 2026 10:08:33 +0300 Subject: [PATCH] immich temporarily moved to photo2.aggtaa.com. photo-stats removed --- .../base/apps/immich/helmrelease-server.yaml | 4 +- clusters/base/apps/photo-stats/configmap.yaml | 177 ------------------ .../base/apps/photo-stats/helmrelease.yaml | 99 ---------- .../base/apps/photo-stats/helmrepository.yaml | 10 - .../base/apps/photo-stats/kustomization.yaml | 7 - .../base/apps/photo-stats/pv-pvc-data.yaml | 37 ---- clusters/base/namespaces/photo-stats.yaml | 4 - clusters/home/apps/photo-stats.yaml | 17 -- clusters/home/namespaces/kustomization.yaml | 1 - 9 files changed, 2 insertions(+), 354 deletions(-) delete mode 100644 clusters/base/apps/photo-stats/configmap.yaml delete mode 100644 clusters/base/apps/photo-stats/helmrelease.yaml delete mode 100644 clusters/base/apps/photo-stats/helmrepository.yaml delete mode 100644 clusters/base/apps/photo-stats/kustomization.yaml delete mode 100644 clusters/base/apps/photo-stats/pv-pvc-data.yaml delete mode 100644 clusters/base/namespaces/photo-stats.yaml delete mode 100644 clusters/home/apps/photo-stats.yaml diff --git a/clusters/base/apps/immich/helmrelease-server.yaml b/clusters/base/apps/immich/helmrelease-server.yaml index eaf7269..283af2f 100644 --- a/clusters/base/apps/immich/helmrelease-server.yaml +++ b/clusters/base/apps/immich/helmrelease-server.yaml @@ -135,7 +135,7 @@ spec: annotations: cert-manager.io/cluster-issuer: letsencrypt-prod hosts: - - host: photo.aggtaa.com + - host: photo2.aggtaa.com paths: - path: / pathType: Prefix @@ -145,7 +145,7 @@ spec: tls: - secretName: immich-tls hosts: - - photo.aggtaa.com + - photo2.aggtaa.com persistence: # Immich's "library" folder, mergerfs-merged from two disks: recent diff --git a/clusters/base/apps/photo-stats/configmap.yaml b/clusters/base/apps/photo-stats/configmap.yaml deleted file mode 100644 index afa76f4..0000000 --- a/clusters/base/apps/photo-stats/configmap.yaml +++ /dev/null @@ -1,177 +0,0 @@ -apiVersion: v1 -kind: ConfigMap -metadata: - name: photo-stats-script - namespace: photo-stats -data: - scan.py: | - import os - import time - import json - import threading - from datetime import datetime, timezone - - ROOT = "/mnt/sdb2/immich/uploads/library" - OUT_DIR = "/www" - current_date = datetime.now(timezone.utc) - cutoff_date = current_date.replace(year=current_date.year - 1) - CUTOFF = cutoff_date.timestamp() - RESCAN_INTERVAL_SECONDS = 6 * 3600 - - state_lock = threading.Lock() - state = { - "status": "starting", - "cutoff_at": cutoff_date.isoformat(), - "processed": 0, - "total": 0, - "percent": 0.0, - "total_files": 0, - "total_size": 0, - "recent_files": 0, - "recent_size": 0, - "started_at": None, - "finished_at": None, - "error": None, - } - - - def human_size(n): - n = float(n) - for unit in ("B", "KiB", "MiB", "GiB", "TiB", "PiB"): - if abs(n) < 1024.0: - return f"{n:.1f}{unit}" - n /= 1024.0 - return f"{n:.1f}EiB" - - - def render_html(s): - progress_html = "" - if s["status"] == "counting": - progress_html = "

Counting files...

" - elif s["status"] == "scanning": - pct = s["percent"] - progress_html = f""" -

Progress: {s['processed']} / {s['total']} ({pct:.1f}%)

-
- """ - error_html = f"

Error: {s['error']}

" if s["error"] else "" - return f""" - Photo library stats - - -

Photo library stats

-

Status: {s['status']}

- {progress_html} - {error_html} - - - - - - - -
Total files{s['total_files']}
Total size{human_size(s['total_size'])} ({s['total_size']} bytes)
Files newer than {s['cutoff_at']}{s['recent_files']}
Size of files newer than {s['cutoff_at']}{human_size(s['recent_size'])} ({s['recent_size']} bytes)
Last scan started{s['started_at'] or '-'}
Last scan finished{s['finished_at'] or '-'}
- """ - - - def write_output(): - with state_lock: - s = dict(state) - html = render_html(s) - - tmp = os.path.join(OUT_DIR, "index.html.tmp") - with open(tmp, "w") as f: - f.write(html) - os.replace(tmp, os.path.join(OUT_DIR, "index.html")) - - tmp = os.path.join(OUT_DIR, "stats.json.tmp") - with open(tmp, "w") as f: - json.dump(s, f, indent=2) - os.replace(tmp, os.path.join(OUT_DIR, "stats.json")) - - - def scan_once(): - with state_lock: - state.update(status="counting", started_at=datetime.now(timezone.utc).isoformat(), - finished_at=None, error=None, processed=0, total=0, percent=0.0) - write_output() - - total = 0 - try: - for _dirpath, _dirs, files in os.walk(ROOT): - total += len(files) - except OSError as e: - with state_lock: - state.update(status="error", error=str(e)) - write_output() - return - - with state_lock: - state.update(total=total, status="scanning") - write_output() - - processed = 0 - total_files = 0 - total_size = 0 - recent_files = 0 - recent_size = 0 - last_write = time.time() - - try: - for dirpath, _dirs, files in os.walk(ROOT): - for name in files: - fp = os.path.join(dirpath, name) - processed += 1 - try: - st = os.stat(fp) - except OSError: - continue - total_files += 1 - total_size += st.st_size - if st.st_mtime >= CUTOFF: - recent_files += 1 - recent_size += st.st_size - - now = time.time() - if now - last_write > 2: - with state_lock: - state.update( - processed=processed, total_files=total_files, - total_size=total_size, recent_files=recent_files, - recent_size=recent_size, - percent=(processed / total * 100) if total else 100.0, - ) - write_output() - last_write = now - except OSError as e: - with state_lock: - state.update(status="error", error=str(e)) - write_output() - return - - with state_lock: - state.update( - processed=processed, total_files=total_files, total_size=total_size, - recent_files=recent_files, recent_size=recent_size, percent=100.0, - status="done", finished_at=datetime.now(timezone.utc).isoformat(), - ) - write_output() - - - def main(): - os.makedirs(OUT_DIR, exist_ok=True) - write_output() - while True: - scan_once() - time.sleep(RESCAN_INTERVAL_SECONDS) - - - if __name__ == "__main__": - main() diff --git a/clusters/base/apps/photo-stats/helmrelease.yaml b/clusters/base/apps/photo-stats/helmrelease.yaml deleted file mode 100644 index ded6cd0..0000000 --- a/clusters/base/apps/photo-stats/helmrelease.yaml +++ /dev/null @@ -1,99 +0,0 @@ -apiVersion: helm.toolkit.fluxcd.io/v2 -kind: HelmRelease -metadata: - name: photo-stats - namespace: photo-stats -spec: - interval: 30m - chartRef: - kind: OCIRepository - name: photo-stats - driftDetection: - mode: enabled - values: - controllers: - app: - containers: - # walks the immich library over NFS (read-only) and periodically - # writes index.html/stats.json into the shared "www" volume; the - # "web" container just serves whatever is currently on disk there. - scanner: - image: - repository: python - tag: 3.13-alpine - command: - - python3 - - /app/scan.py - resources: - requests: - cpu: 50m - memory: 64Mi - limits: - memory: 256Mi - web: - image: - repository: nginx - tag: 1.27-alpine - probes: - liveness: - enabled: true - readiness: - enabled: true - resources: - requests: - cpu: 10m - memory: 16Mi - limits: - memory: 64Mi - - service: - app: - controller: app - ports: - http: - port: 80 - - ingress: - app: - className: traefik - annotations: - cert-manager.io/cluster-issuer: letsencrypt-prod - hosts: - - host: stats.photo.aggtaa.com - paths: - - path: / - pathType: Prefix - service: - identifier: app - port: http - tls: - - secretName: photo-stats-tls - hosts: - - stats.photo.aggtaa.com - - persistence: - script: - type: configMap - name: photo-stats-script - advancedMounts: - app: - scanner: - - path: /app/scan.py - subPath: scan.py - readOnly: true - data: - type: persistentVolumeClaim - existingClaim: photo-stats-nas1-sdb2 - advancedMounts: - app: - scanner: - - path: /mnt/sdb2 - readOnly: true - www: - type: emptyDir - advancedMounts: - app: - scanner: - - path: /www - web: - - path: /usr/share/nginx/html diff --git a/clusters/base/apps/photo-stats/helmrepository.yaml b/clusters/base/apps/photo-stats/helmrepository.yaml deleted file mode 100644 index c8f381a..0000000 --- a/clusters/base/apps/photo-stats/helmrepository.yaml +++ /dev/null @@ -1,10 +0,0 @@ -apiVersion: source.toolkit.fluxcd.io/v1 -kind: OCIRepository -metadata: - name: photo-stats - namespace: photo-stats -spec: - interval: 1h - url: oci://ghcr.io/bjw-s-labs/helm/app-template - ref: - tag: "5.0.1" diff --git a/clusters/base/apps/photo-stats/kustomization.yaml b/clusters/base/apps/photo-stats/kustomization.yaml deleted file mode 100644 index 39a396d..0000000 --- a/clusters/base/apps/photo-stats/kustomization.yaml +++ /dev/null @@ -1,7 +0,0 @@ -apiVersion: kustomize.config.k8s.io/v1beta1 -kind: Kustomization -resources: - - helmrepository.yaml - - configmap.yaml - - pv-pvc-data.yaml - - helmrelease.yaml diff --git a/clusters/base/apps/photo-stats/pv-pvc-data.yaml b/clusters/base/apps/photo-stats/pv-pvc-data.yaml deleted file mode 100644 index 29bb943..0000000 --- a/clusters/base/apps/photo-stats/pv-pvc-data.yaml +++ /dev/null @@ -1,37 +0,0 @@ -apiVersion: v1 -kind: PersistentVolume -metadata: - name: photo-stats-nas1-sdb2-nfs -spec: - capacity: - storage: 1Ti - accessModes: - - ReadOnlyMany - persistentVolumeReclaimPolicy: Retain - storageClassName: "" - mountOptions: - - nfsvers=3 - - nolock - nfs: - server: 10.0.64.80 - path: /mnt/sdb2 - readOnly: true - claimRef: - namespace: photo-stats - name: photo-stats-nas1-sdb2 ---- -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - name: photo-stats-nas1-sdb2 - namespace: photo-stats - annotations: - helm.sh/resource-policy: keep -spec: - accessModes: - - ReadOnlyMany - storageClassName: "" - volumeName: photo-stats-nas1-sdb2-nfs - resources: - requests: - storage: 1Ti diff --git a/clusters/base/namespaces/photo-stats.yaml b/clusters/base/namespaces/photo-stats.yaml deleted file mode 100644 index 0331213..0000000 --- a/clusters/base/namespaces/photo-stats.yaml +++ /dev/null @@ -1,4 +0,0 @@ -apiVersion: v1 -kind: Namespace -metadata: - name: photo-stats diff --git a/clusters/home/apps/photo-stats.yaml b/clusters/home/apps/photo-stats.yaml deleted file mode 100644 index 3086112..0000000 --- a/clusters/home/apps/photo-stats.yaml +++ /dev/null @@ -1,17 +0,0 @@ -apiVersion: kustomize.toolkit.fluxcd.io/v1 -kind: Kustomization -metadata: - name: photo-stats - namespace: flux-system -spec: - interval: 10m - sourceRef: - kind: GitRepository - name: flux-system - path: ./clusters/base/apps/photo-stats - prune: true - wait: true - dependsOn: - - name: namespaces - - name: infra - retryInterval: 5s diff --git a/clusters/home/namespaces/kustomization.yaml b/clusters/home/namespaces/kustomization.yaml index bed8eba..e3bf2ee 100644 --- a/clusters/home/namespaces/kustomization.yaml +++ b/clusters/home/namespaces/kustomization.yaml @@ -16,4 +16,3 @@ resources: - ../../base/namespaces/nfs.yaml - ../../base/namespaces/syncthing.yaml - ../../base/namespaces/photo.yaml - - ../../base/namespaces/photo-stats.yaml