# Synology Container Manager → Project → Create # # Edit BASE if your shared folder is not on volume1: # /volume1/docker/airfreyr # # Required before starting (folders + conf.json must exist): # /volume1/docker/airfreyr/queues/ # /volume1/docker/airfreyr/music/ # /volume1/docker/airfreyr/config/conf.json # /volume1/Music/cds-alac/ (optional mirror library — must be writable) # /volume1/Music/cds-mp3/ (optional mirror library — must be writable) # # Mirror folders need write permission for the container. If copies fail with # EACCES, set PUID/PGID below to your DSM user's UID/GID and ensure those # shared folders grant that user Read/Write. # # No image build. No extra scripts to copy. Uses node:20-alpine only. version: "3.8" services: airfreyr: image: node:20-alpine restart: unless-stopped ports: - "3799:3797" environment: AIRFREYR_REFRESH_HOURS: "3" AIRFREYR_MIRROR_DIRS: "/data/cds-alac,/data/cds-mp3" # Match Synology shared-folder owner (Control Panel → User → admin → UID/GID). # Used to chown mirrored files when the container runs as root. PUID: "1024" PGID: "100" volumes: - /volume1/docker/airfreyr/queues:/data/queues - /volume1/docker/airfreyr/music:/data/music - /volume1/docker/airfreyr/config:/data/config - /volume1/Music/cds-alac:/data/cds-alac - /volume1/Music/cds-mp3:/data/cds-mp3 command: - /bin/sh - -c - | apk add --no-cache python3 bash REFRESH=$(($${AIRFREYR_REFRESH_HOURS:-3} * 3600)) while true; do echo "[airfreyr] starting $$(date -u +%Y-%m-%dT%H:%M:%SZ)" rm -rf /root/.npm/_npx 2>/dev/null || true npx --yes @emgeebee/airfreyr@latest serve --no-logo --no-header \ -H 0.0.0.0 -p 3799 \ -q /data/queues -D /data/music \ -o /data/config/conf.json & PID=$$! ( sleep $$REFRESH; kill $$PID 2>/dev/null || true ) & wait $$PID 2>/dev/null || true sleep 2 done