diff --git a/README.md b/README.md index b4b3a75..1cecd6d 100644 --- a/README.md +++ b/README.md @@ -34,6 +34,7 @@ De HTPC omgeving omvat onder andere de volgende diensten: | **Jackett / Prowlarr** | `9117` / `9696` | Torrent- en usenet indexer proxy | | **SABnzbd / Transmission** | `8080` / `9091` | Downloadclients voor media-acquisitie (BitTorrent peer-poort `53662`) | | **slskd** | `5030` / `50300` | Soulseek peer-to-peer client en web daemon (HTTP: `5030`, Soulseek listen: `50300`) | +| **Radio Chicken & Icecast** | `5000` / `8000` | Gepersonaliseerd radiostation, Icecast audio/video streams, live web-UI en clip downloader | --- @@ -117,3 +118,27 @@ De Jellyfin media server (`jellyfin`) draait als pod in de `htpc` namespace: # Oude host bestanden en service opruimen: ./cleanup_old_jellyfin.sh ``` + +### Radio Chicken & Icecast +Het Radio Chicken streamingplatform en Icecast server draaien als multi-container pod (`radio-chicken`) in de `htpc` namespace: + +- **Containers in pod**: + - `icecast` (`moul/icecast:latest`): Luistert op poort `8000` (ClusterIP + HostPort `8000`) voor audio (`/chicken`) en live webm video (`/chicken_video.webm`). + - `radio-chicken` (`git.bnhmeijer.nl/bart/radio-chicken:latest`): Flask web-UI, stemsynthese, live ffmpeg hardware transcoding en streaming naar Icecast op poort `5000` (ClusterIP + HostPort `5000`). + - `autoplacer` (`git.bnhmeijer.nl/bart/radio-chicken-autoplacer:latest`): Achtergrond-worker die nummers in Jellyfin analyseert en in playlists plaatst. + - `mv-downloader` (`git.bnhmeijer.nl/bart/radio-chicken-mv-downloader:latest`): Achtergrond-worker die ontbrekende videoclips van favoriete nummers automatisch downloadt via YouTube naar `/music_videos`. +- **Dataopslag**: PersistentVolumeClaim `radio-chicken-data` (10Gi, `local-path` op `/datadisk/infra/pv`), gemigreerd vanuit `/home/bart/jellyfinradio/data` en `webroot` via init-container. +- **Mediaopslag**: HostPath `/datadisk/htpc/music_video` gemount op `/music_videos`. +- **Hardware Transcoding**: Directe hardware-acceleratie via VA-API met AMD Phoenix2 iGPU (`/dev/dri` hostPath gemount met `privileged: true`). +- **Netwerk & Ingress**: Luistert op poort `5000` en `8000`. De Apache reverse proxy routeert `/radio/live`, `/radio/vote` en `/radio/` direct door naar `127.0.0.1:5000` en `127.0.0.1:8000`. +- **Migratie, Terugrol & Opruimen**: + ```bash + # Migratie uitvoeren (maakt backup, sync video's, stopt host containers, start pod): + ./migrate_radio_chicken_to_cluster.sh + + # Terugrollen naar standalone host containers indien gewenst: + ./rollback_radio_chicken_migration.sh + + # Oude host containers opruimen: + ./cleanup_old_radio_chicken.sh + ``` diff --git a/cleanup_old_radio_chicken.sh b/cleanup_old_radio_chicken.sh new file mode 100755 index 0000000..70003c8 --- /dev/null +++ b/cleanup_old_radio_chicken.sh @@ -0,0 +1,42 @@ +#!/usr/bin/env bash +# ============================================================================== +# Radio Chicken Host Cleanup Script +# ============================================================================== +set -euo pipefail + +CLUSTER_HOST="10.2.0.4" +SSH_USER="bart" + +COLOR_GREEN="\033[0;32m" +COLOR_YELLOW="\033[1;33m" +COLOR_RED="\033[0;31m" +COLOR_RESET="\033[0m" + +log_info() { echo -e "${COLOR_GREEN}[INFO]${COLOR_RESET} $1"; } +log_warn() { echo -e "${COLOR_YELLOW}[WARN]${COLOR_RESET} $1"; } +log_err() { echo -e "${COLOR_RED}[ERROR]${COLOR_RESET} $1"; } + +echo "========================================================================" +echo " OPRUIMEN OUDE RADIO CHICKEN DOCKER CONTAINERS OP HOST (${CLUSTER_HOST})" +echo "========================================================================" +echo "Let op: Voer dit script pas uit nadat de Kubernetes pod stabiel draait." +echo "Dit script verwijdert de gestopte Docker containers (barttradio, icecast," +echo "radio_chicken_autoplacer, radio_chicken_mv_downloader)." +echo "De code en configuratie in /home/bart/jellyfinradio blijven onaangeraakt." +echo "========================================================================" +echo "" + +read -p "Weet je zeker dat je de oude Docker containers wilt verwijderen? (j/N): " -r CONFIRM +if [[ ! "$CONFIRM" =~ ^[jJyY]$ ]]; then + log_info "Opruimen geannuleerd." + exit 0 +fi + +log_info "Verwijderen van oude host Docker containers..." +ssh "${SSH_USER}@${CLUSTER_HOST}" " + echo '--> Verwijderen van containers...' + docker rm -f barttradio radio_chicken_autoplacer radio_chicken_mv_downloader icecast 2>/dev/null || true + echo 'Containers opgeruimd.' +" + +log_info "Opruimactie succesvol afgerond." diff --git a/k8s/kustomization.yaml b/k8s/kustomization.yaml index 0c07799..3b8ba01 100644 --- a/k8s/kustomization.yaml +++ b/k8s/kustomization.yaml @@ -13,5 +13,6 @@ resources: - jackett - flaresolverr - jellyfin + - radio-chicken diff --git a/k8s/radio-chicken/configmap.yaml b/k8s/radio-chicken/configmap.yaml new file mode 100644 index 0000000..c1e10ee --- /dev/null +++ b/k8s/radio-chicken/configmap.yaml @@ -0,0 +1,74 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: radio-chicken-icecast-config + namespace: htpc + labels: + app.kubernetes.io/name: radio-chicken + app.kubernetes.io/part-of: htpc +data: + icecast.xml: | + + Radio Chicken Coop + admin@localhost + + + 500 + 20 + 524288 + 30 + 15 + 10 + 1 + 65535 + + + + hackme + hackme + admin + hackme + + + localhost + + + 8000 + + + 1 + + + /var/log/icecast2 + /usr/share/icecast2/web + /usr/share/icecast2/admin + + + + + access.log + error.log + 3 + 10000 + + + + 0 + + + + + /chicken + /standby.ogg + 1 + 1 + + + + + /chicken_video.webm + /standby_video.webm + 1 + 1 + + diff --git a/k8s/radio-chicken/deployment.yaml b/k8s/radio-chicken/deployment.yaml new file mode 100644 index 0000000..86c8515 --- /dev/null +++ b/k8s/radio-chicken/deployment.yaml @@ -0,0 +1,229 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: radio-chicken + namespace: htpc + labels: + app.kubernetes.io/name: radio-chicken + app.kubernetes.io/part-of: htpc +spec: + replicas: 1 + strategy: + type: Recreate + selector: + matchLabels: + app: radio-chicken + template: + metadata: + labels: + app: radio-chicken + app.kubernetes.io/name: radio-chicken + app.kubernetes.io/part-of: htpc + spec: + nodeSelector: + kubernetes.io/hostname: vmserver + initContainers: + - name: migrate-data + image: alpine:3.20 + imagePullPolicy: IfNotPresent + command: + - /bin/sh + - -c + - | + echo "Checking and preparing directories for Radio Chicken..." + mkdir -p /data/data /data/webroot + + if [ ! -f /data/data/settings.json ] && [ -f /host-radio/data/settings.json ]; then + echo "Syncing Radio Chicken data and cache from host (/home/bart/jellyfinradio/data)..." + cp -a /host-radio/data/* /data/data/ || true + fi + + if [ ! -f /data/webroot/standby.ogg ] && [ -d /host-radio/webroot ]; then + echo "Syncing standby media files from host (/home/bart/jellyfinradio/webroot)..." + cp -a /host-radio/webroot/* /data/webroot/ || true + fi + + chmod -R 777 /data + echo "Init container completed successfully." + volumeMounts: + - name: data + mountPath: /data + - name: host-radio + mountPath: /host-radio + readOnly: true + containers: + # Container 1: Icecast Audio & Video Streaming Server + - name: icecast + image: moul/icecast:latest + imagePullPolicy: IfNotPresent + env: + - name: ICECAST_SOURCE_PASSWORD + value: "hackme" + - name: ICECAST_ADMIN_PASSWORD + value: "hackme" + - name: ICECAST_PASSWORD + value: "hackme" + ports: + - name: icecast + containerPort: 8000 + hostPort: 8000 + protocol: TCP + resources: + requests: + cpu: 50m + memory: 64Mi + limits: + cpu: 500m + memory: 512Mi + volumeMounts: + - name: icecast-config + mountPath: /etc/icecast2/icecast.xml + subPath: icecast.xml + - name: data + mountPath: /usr/share/icecast2/web/standby.ogg + subPath: webroot/standby.ogg + - name: data + mountPath: /usr/share/icecast2/web/standby.mp3 + subPath: webroot/standby.mp3 + - name: data + mountPath: /usr/share/icecast2/web/standby_video.webm + subPath: webroot/standby_video.webm + livenessProbe: + httpGet: + path: /status-json.xsl + port: 8000 + initialDelaySeconds: 15 + periodSeconds: 20 + timeoutSeconds: 5 + readinessProbe: + httpGet: + path: /status-json.xsl + port: 8000 + initialDelaySeconds: 5 + periodSeconds: 10 + timeoutSeconds: 5 + + # Container 2: Radio Chicken Web Application & Audio/Video Streamer + - name: radio-chicken + image: git.bnhmeijer.nl/bart/radio-chicken:latest + imagePullPolicy: IfNotPresent + securityContext: + privileged: true + env: + - name: JELLYFIN_URL + value: "http://jellyfin:8096/jellyfin" + - name: JELLYFIN_API_KEY + value: "c58f4b427eaf475aafd86abd87f139af" + - name: JELLYFIN_USER_ID + value: "40a220e1e05e4a4395c9b0c6569f6e82" + - name: ICECAST_URL + value: "icecast://source:hackme@127.0.0.1:8000/chicken" + - name: VIDEO_ENCODER + value: "h264_vaapi" + - name: VAAPI_DEVICE + value: "/dev/dri/renderD128" + ports: + - name: web + containerPort: 5000 + hostPort: 5000 + protocol: TCP + resources: + requests: + cpu: 200m + memory: 1Gi + limits: + cpu: 4000m + memory: 6Gi + volumeMounts: + - name: data + mountPath: /app/data + subPath: data + - name: music-videos + mountPath: /music_videos + - name: dri + mountPath: /dev/dri + livenessProbe: + httpGet: + path: /live + port: 5000 + initialDelaySeconds: 45 + periodSeconds: 20 + timeoutSeconds: 5 + readinessProbe: + httpGet: + path: /live + port: 5000 + initialDelaySeconds: 20 + periodSeconds: 10 + timeoutSeconds: 5 + + # Container 3: Radio Chicken Autoplacer Worker + - name: autoplacer + image: git.bnhmeijer.nl/bart/radio-chicken-autoplacer:latest + imagePullPolicy: IfNotPresent + env: + - name: JELLYFIN_URL + value: "http://jellyfin:8096/jellyfin" + - name: JELLYFIN_API_KEY + value: "c58f4b427eaf475aafd86abd87f139af" + - name: JELLYFIN_USER_ID + value: "40a220e1e05e4a4395c9b0c6569f6e82" + - name: CHECK_INTERVAL_SECONDS + value: "60" + - name: PROCESS_DELAY_SECONDS + value: "3" + resources: + requests: + cpu: 50m + memory: 256Mi + limits: + cpu: 1000m + memory: 2Gi + + # Container 4: Radio Chicken Music Video Downloader Worker + - name: mv-downloader + image: git.bnhmeijer.nl/bart/radio-chicken-mv-downloader:latest + imagePullPolicy: IfNotPresent + env: + - name: JELLYFIN_URL + value: "http://jellyfin:8096/jellyfin" + - name: JELLYFIN_API_KEY + value: "c58f4b427eaf475aafd86abd87f139af" + - name: JELLYFIN_USER_ID + value: "40a220e1e05e4a4395c9b0c6569f6e82" + - name: MUSIC_VIDEOS_DIR + value: "/music_videos" + - name: CHECK_INTERVAL_SECONDS + value: "3600" + - name: PROCESS_DELAY_SECONDS + value: "3" + resources: + requests: + cpu: 50m + memory: 256Mi + limits: + cpu: 2000m + memory: 2Gi + volumeMounts: + - name: music-videos + mountPath: /music_videos + + volumes: + - name: data + persistentVolumeClaim: + claimName: radio-chicken-data + - name: icecast-config + configMap: + name: radio-chicken-icecast-config + - name: music-videos + hostPath: + path: /datadisk/htpc/music_video + type: Directory + - name: dri + hostPath: + path: /dev/dri + type: Directory + - name: host-radio + hostPath: + path: /home/bart/jellyfinradio + type: DirectoryOrCreate diff --git a/k8s/radio-chicken/kustomization.yaml b/k8s/radio-chicken/kustomization.yaml new file mode 100644 index 0000000..e7bbfd8 --- /dev/null +++ b/k8s/radio-chicken/kustomization.yaml @@ -0,0 +1,8 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization + +resources: + - configmap.yaml + - pvc.yaml + - service.yaml + - deployment.yaml diff --git a/k8s/radio-chicken/pvc.yaml b/k8s/radio-chicken/pvc.yaml new file mode 100644 index 0000000..70f4f90 --- /dev/null +++ b/k8s/radio-chicken/pvc.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: radio-chicken-data + namespace: htpc + labels: + app.kubernetes.io/name: radio-chicken + app.kubernetes.io/part-of: htpc +spec: + accessModes: + - ReadWriteOnce + storageClassName: local-path + resources: + requests: + storage: 10Gi diff --git a/k8s/radio-chicken/service.yaml b/k8s/radio-chicken/service.yaml new file mode 100644 index 0000000..d600ee0 --- /dev/null +++ b/k8s/radio-chicken/service.yaml @@ -0,0 +1,21 @@ +apiVersion: v1 +kind: Service +metadata: + name: radio-chicken + namespace: htpc + labels: + app.kubernetes.io/name: radio-chicken + app.kubernetes.io/part-of: htpc +spec: + type: ClusterIP + selector: + app: radio-chicken + ports: + - name: http-web + port: 5000 + targetPort: 5000 + protocol: TCP + - name: http-icecast + port: 8000 + targetPort: 8000 + protocol: TCP diff --git a/migrate_radio_chicken_to_cluster.sh b/migrate_radio_chicken_to_cluster.sh new file mode 100755 index 0000000..269aad8 --- /dev/null +++ b/migrate_radio_chicken_to_cluster.sh @@ -0,0 +1,139 @@ +#!/usr/bin/env bash +# ============================================================================== +# Radio Chicken Migration Script: Host Docker -> Kubernetes Cluster (htpc namespace) +# ============================================================================== +set -euo pipefail + +CLUSTER_HOST="10.2.0.4" +SSH_USER="bart" +HTPC_NS="htpc" +BACKUP_DIR="/storage/backups" +DATE_STR=$(date +%Y-%m-%d) +KUBECONFIG_PATH="${KUBECONFIG:-$HOME/.kube/config_vmserver}" + +COLOR_GREEN="\033[0;32m" +COLOR_YELLOW="\033[1;33m" +COLOR_RED="\033[0;31m" +COLOR_BLUE="\033[0;34m" +COLOR_RESET="\033[0m" + +log_info() { echo -e "${COLOR_GREEN}[INFO]${COLOR_RESET} $1"; } +log_step() { echo -e "\n${COLOR_BLUE}==>${COLOR_RESET} ${COLOR_GREEN}$1${COLOR_RESET}"; } +log_warn() { echo -e "${COLOR_YELLOW}[WARN]${COLOR_RESET} $1"; } +log_err() { echo -e "${COLOR_RED}[ERROR]${COLOR_RESET} $1"; } + +echo "========================================================================" +echo " RADIO CHICKEN MIGRATIE NAAR KUBERNETES CLUSTER (NAMESPACE: ${HTPC_NS})" +echo "========================================================================" +echo "Bron: Standalone Docker containers op ${CLUSTER_HOST}" +echo " (barttradio, icecast, autoplacer, mv_downloader)" +echo "Config: /home/bart/jellyfinradio/{data,webroot,icecast.xml}" +echo "Videos: /home/bart/jellyfinradio/music_videos -> /datadisk/htpc/music_video" +echo "Doel: K8s Pod 'radio-chicken' in namespace '${HTPC_NS}'" +echo "Poorten: 5000 (Web UI / API / WS) & 8000 (Icecast Streams)" +echo "Transcode: AMD VA-API (/dev/dri/renderD128)" +echo "========================================================================" +echo "" + +read -p "Weet je zeker dat je de Radio Chicken migratie naar Kubernetes wilt starten? (j/N): " -r CONFIRM +if [[ ! "$CONFIRM" =~ ^[jJyY]$ ]]; then + log_info "Migratie geannuleerd." + exit 0 +fi + +# ------------------------------------------------------------------------------ +# STAP 1: PRE-FLIGHT CHECKS +# ------------------------------------------------------------------------------ +log_step "1. Pre-flight checks uitvoeren..." + +log_info "Verbinding testen naar host (${CLUSTER_HOST})..." +ssh -o BatchMode=yes -o ConnectTimeout=5 "${SSH_USER}@${CLUSTER_HOST}" "true" || { + log_err "Kan niet verbinden met host (${CLUSTER_HOST}) via SSH." + exit 1 +} + +log_info "Controleren van KUBECONFIG verbinding..." +KUBECONFIG="${KUBECONFIG_PATH}" kubectl get nodes | grep -q "vmserver" || { + log_err "Kan vmserver node niet bereiken via kubectl (KUBECONFIG=${KUBECONFIG_PATH})!" + exit 1 +} + +# ------------------------------------------------------------------------------ +# STAP 2: RESERVEKOPIE MAKEN VAN BESTAANDE DATA OP DE HOST +# ------------------------------------------------------------------------------ +log_step "2. Reservekopie maken van /home/bart/jellyfinradio/data op ${CLUSTER_HOST}..." +ssh "${SSH_USER}@${CLUSTER_HOST}" " + mkdir -p '${BACKUP_DIR}' + if [ -d '/home/bart/jellyfinradio/data' ]; then + echo 'Inpakken van Radio Chicken data naar ${BACKUP_DIR}/radio_chicken_backup_${DATE_STR}.tar.gz...' + tar -czf '${BACKUP_DIR}/radio_chicken_backup_${DATE_STR}.tar.gz' \ + -C /home/bart/jellyfinradio data webroot + echo 'Backup gereed:' + ls -lh '${BACKUP_DIR}/radio_chicken_backup_${DATE_STR}.tar.gz' + else + echo 'Geen bestaande data directory gevonden in /home/bart/jellyfinradio/data.' + fi +" + +# ------------------------------------------------------------------------------ +# STAP 3: DOWNLOADS SYNCRHONISEREN NAAR /datadisk/htpc/music_video +# ------------------------------------------------------------------------------ +log_step "3. Pas gedownloade videoclips samenvoegen naar /datadisk/htpc/music_video..." +ssh "${SSH_USER}@${CLUSTER_HOST}" " + if [ -d '/home/bart/jellyfinradio/music_videos' ]; then + echo 'Kopiëren van unieke videobestanden en NFOs naar /datadisk/htpc/music_video/...' + cp -rn /home/bart/jellyfinradio/music_videos/* /datadisk/htpc/music_video/ 2>/dev/null || true + echo 'Synchronisatie voltooid.' + fi +" + +# ------------------------------------------------------------------------------ +# STAP 4: STANDALONE DOCKER CONTAINERS STOPPEN OP DE HOST +# ------------------------------------------------------------------------------ +log_step "4. Standalone Docker containers stoppen op ${CLUSTER_HOST}..." +ssh "${SSH_USER}@${CLUSTER_HOST}" " + echo '--> Stoppen van barttradio, radio_chicken_autoplacer, radio_chicken_mv_downloader, icecast...' + docker stop barttradio radio_chicken_autoplacer radio_chicken_mv_downloader icecast 2>/dev/null || true +" + +# ------------------------------------------------------------------------------ +# STAP 5: KUBERNETES MANIFESTS TOEPASSEN +# ------------------------------------------------------------------------------ +log_step "5. Kubernetes manifests toepassen..." +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +KUBECONFIG="${KUBECONFIG_PATH}" kubectl apply -k "${SCRIPT_DIR}/k8s/" + +log_info "Wachten op succesvolle uitrol van Radio Chicken pod..." +KUBECONFIG="${KUBECONFIG_PATH}" kubectl rollout status deployment/radio-chicken -n "${HTPC_NS}" --timeout=300s + +# ------------------------------------------------------------------------------ +# STAP 6: VERIFICATIE +# ------------------------------------------------------------------------------ +log_step "6. Verificatie van endpoints..." + +log_info "Controleren van Icecast stream endpoint (poort 8000)..." +if curl -s -f -o /dev/null "http://${CLUSTER_HOST}:8000/status-json.xsl"; then + log_info "✅ Icecast reageert succesvol op http://${CLUSTER_HOST}:8000/status-json.xsl" +else + log_warn "⚠️ Icecast status kon niet worden opgevraagd op poort 8000." +fi + +log_info "Controleren van Radio Chicken web/live endpoint (poort 5000)..." +if curl -s -f -o /dev/null "http://${CLUSTER_HOST}:5000/live"; then + log_info "✅ Radio Chicken web interface reageert succesvol op http://${CLUSTER_HOST}:5000/live" +else + log_warn "⚠️ Radio Chicken web interface reageert nog niet direct op poort 5000." +fi + +log_info "Controleren van Apache reverse proxy (https://thuus.bnhmeijer.nl/radio/live)..." +HTTP_CODE=$(curl -s -k -o /dev/null -w "%{http_code}" "https://thuus.bnhmeijer.nl/radio/live" || true) +if [ "$HTTP_CODE" = "200" ]; then + log_info "✅ Apache reverse proxy routeert succesvol naar Radio Chicken (/radio/live) [HTTP 200]" +else + log_warn "⚠️ Apache reverse proxy gaf HTTP status: ${HTTP_CODE} voor /radio/live." +fi + +echo "" +echo "========================================================================" +log_info "Migratie van Radio Chicken naar Kubernetes is succesvol voltooid!" +echo "========================================================================" diff --git a/rollback_radio_chicken_migration.sh b/rollback_radio_chicken_migration.sh new file mode 100755 index 0000000..33ec2ce --- /dev/null +++ b/rollback_radio_chicken_migration.sh @@ -0,0 +1,50 @@ +#!/usr/bin/env bash +# ============================================================================== +# Rollback Script: Radio Chicken Kubernetes -> Standalone Docker on Host +# ============================================================================== +set -euo pipefail + +CLUSTER_HOST="10.2.0.4" +SSH_USER="bart" +HTPC_NS="htpc" +KUBECONFIG_PATH="${KUBECONFIG:-$HOME/.kube/config_vmserver}" + +COLOR_GREEN="\033[0;32m" +COLOR_YELLOW="\033[1;33m" +COLOR_RED="\033[0;31m" +COLOR_RESET="\033[0m" + +log_info() { echo -e "${COLOR_GREEN}[INFO]${COLOR_RESET} $1"; } +log_warn() { echo -e "${COLOR_YELLOW}[WARN]${COLOR_RESET} $1"; } +log_err() { echo -e "${COLOR_RED}[ERROR]${COLOR_RESET} $1"; } + +echo "========================================================================" +echo " TERUGROLLEN RADIO CHICKEN: KUBERNETES -> STANDALONE HOST DOCKER" +echo "========================================================================" +read -p "Weet je zeker dat je Radio Chicken wilt terugrollen naar de host Docker containers? (j/N): " -r CONFIRM +if [[ ! "$CONFIRM" =~ ^[jJyY]$ ]]; then + log_info "Terugrol geannuleerd." + exit 0 +fi + +log_info "1. Schalen van Kubernetes deployment/radio-chicken naar 0..." +KUBECONFIG="${KUBECONFIG_PATH}" kubectl scale deployment/radio-chicken -n "${HTPC_NS}" --replicas=0 + +log_info "2. Herstarten van Docker containers op ${CLUSTER_HOST}..." +ssh "${SSH_USER}@${CLUSTER_HOST}" " + cd /home/bart/jellyfinradio + echo '--> Starten van docker-compose...' + docker compose up -d +" + +log_info "3. Verifiëren van status op ${CLUSTER_HOST}..." +sleep 5 +if curl -s -f -o /dev/null "http://${CLUSTER_HOST}:5000/live"; then + log_info "✅ Radio Chicken draait weer op de host via Docker." +else + log_warn "⚠️ Radio Chicken reageert nog niet direct op poort 5000." +fi + +echo "========================================================================" +log_info "Terugrol voltooid." +echo "========================================================================"