diff --git a/webui/index.html b/webui/index.html index 067b7cb5..e74151f3 100644 --- a/webui/index.html +++ b/webui/index.html @@ -4401,7 +4401,7 @@ Documentation - + diff --git a/webui/static/docs.js b/webui/static/docs.js index 9c1a2ab5..e7ee579d 100644 --- a/webui/static/docs.js +++ b/webui/static/docs.js @@ -12,6 +12,7 @@ const DOCS_SECTIONS = [ { id: 'gs-first-setup', title: 'First-Time Setup' }, { id: 'gs-connecting', title: 'Connecting Services' }, { id: 'gs-interface', title: 'Understanding the Interface' }, + { id: 'gs-folders', title: 'Folder Setup (Downloads & Transfer)' }, { id: 'gs-docker', title: 'Docker & Deployment' } ], content: () => ` @@ -75,6 +76,181 @@ const DOCS_SECTIONS = [ Version & Updates: Click the version number in the sidebar footer to open the What's New modal, which shows detailed release notes for every feature and fix. SoulSync automatically checks for updates by comparing your running version against the latest GitHub commit. If an update is available, a banner appears in the modal. Docker users are notified when a new image has been pushed to the repo. + + Folder Setup (Downloads & Transfer) + SoulSync uses three folders to manage your music files. Most setup issues come from incorrect folder configuration — especially in Docker. Read this section carefully. + + ⚠️ + Docker users — there are TWO steps, not one! + Step 1: Map your volumes in docker-compose.yml — this makes folders accessible to the container. + Step 2: Configure the paths in SoulSync Settings → Download Settings — this tells the app where to look. + Setting up docker-compose volumes alone is not enough. You must also configure the app settings. If you skip Step 2, downloads will complete but nothing will transfer, post-processing will fail silently, and tracks will re-download repeatedly. + + + The Three Folders + + FolderDefault (Docker)Purpose + + Download Path/app/downloadsWhere slskd/YouTube/Tidal initially saves downloaded files. This is a temporary staging area — files should not stay here permanently. + Transfer Path/app/TransferWhere post-processed files are moved after tagging and renaming. This must be the folder your media server (Plex/Jellyfin/Navidrome) monitors. + Staging Path/app/StagingFor the Import feature only. Drop audio files here to import them into your library via the Import page. + + + + How Files Flow + ℹ️ + The complete download-to-library pipeline: + 1. You search for music in SoulSync and click download + 2. SoulSync tells slskd to download the file → slskd saves it to its download folder + 3. SoulSync detects the completed download in the Download Path + 4. Post-processing runs: AcoustID verification → metadata tagging → cover art embedding → lyrics fetch + 5. File is renamed and organized (e.g., Artist/Album/01 - Title.flac) + 6. File is moved from Download Path → Transfer Path + 7. Media server scan is triggered → file appears in your library + If any step fails, the pipeline stops. The most common failure point is Step 3 — SoulSync can't find the file because the Download Path doesn't match where slskd actually saved it. + + + Docker Setup: The Full Picture + In Docker, every app runs in its own isolated container with its own filesystem. Volume mounts in docker-compose create "bridges" between your host folders and the container. But SoulSync doesn't automatically know where those bridges go — you have to tell it via the Settings page. + + Here's what happens with a properly configured setup: + + 🗂️ + HOST (your server) + /mnt/data/slskd-downloads/ ← where slskd saves files on your server + /mnt/media/music/ ← where Plex/Jellyfin/Navidrome watches + docker-compose.yml (the bridges) + /mnt/data/slskd-downloads:/app/downloads + /mnt/media/music:/app/Transfer + CONTAINER (what SoulSync sees) + /app/downloads/ ← same files as /mnt/data/slskd-downloads/ + /app/Transfer/ ← same files as /mnt/media/music/ + SoulSync Settings (what you enter in the app) + Download Path: /app/downloads + Transfer Path: /app/Transfer + + + The #1 Mistake: Not Configuring App Settings + Many users set up their docker-compose volumes correctly but never open SoulSync Settings to configure the paths. The app defaults may not match your volume mounts. You must go to Settings → Download Settings and verify that: + + Download Path matches where slskd puts completed files inside the container (usually /app/downloads) + Transfer Path matches where you mounted your media library inside the container (usually /app/Transfer) + + ⚠️ + "I set up my docker-compose but nothing transfers" — this almost always means the app settings weren't configured. Docker-compose makes the folders accessible. The app settings tell SoulSync where to look. Both are required. + + + The #2 Mistake: Download Path Doesn't Match slskd + The Download Path in SoulSync must point to the exact same physical folder where slskd saves its completed downloads. If they don't match, SoulSync can't find the files and post-processing fails silently. + + ℹ️ + Both SoulSync and slskd must see the same download folder. + slskd container: + • slskd downloads to /downloads/complete inside its own container + • slskd docker-compose: - /mnt/data/slskd-downloads:/downloads/complete + SoulSync container: + • SoulSync docker-compose: - /mnt/data/slskd-downloads:/app/downloads (same host folder!) + • SoulSync Setting: Download Path = /app/downloads + The key: both containers mount the same host folder (/mnt/data/slskd-downloads). The container-internal paths can be different — that's fine. What matters is they point to the same physical directory on your server. + + + The #3 Mistake: Using Host Paths in Settings + If you're running in Docker, the paths you enter in SoulSync's Settings page must be container-side paths (the right side of the : in your volume mount), not host paths (the left side). SoulSync runs inside the container and can only see its own filesystem. + + + Setting ValueResult + + ✅/app/downloadsCorrect — this is the container-side path (right side of :) + ✅/app/TransferCorrect — this is the container-side path (right side of :) + ❌/mnt/data/slskd-downloadsWrong — this is the host path (left side of :), doesn't exist inside the container + ❌/mnt/musicWrong — host path, the container can't see this + ❌./downloadsWrong — relative path, use the full container path /app/downloads + + + + Transfer Path = Media Server's Music Folder + Your Transfer Path must ultimately point to the same physical directory your media server monitors. This is how new music appears in Plex/Jellyfin/Navidrome. + 💡 + Example with Plex: + • Plex monitors /mnt/media/music on the host + • SoulSync docker-compose: - /mnt/media/music:/app/Transfer:rw + • SoulSync Settings: Transfer Path = /app/Transfer + Result: SoulSync writes to /app/Transfer inside the container → appears at /mnt/media/music on the host → Plex sees it and adds it to your library. + + + Complete Docker Compose Example (slskd + SoulSync) + Here's a working example showing both slskd and SoulSync configured to share the same download folder: + 📋 + # docker-compose.yml + services: + slskd: + image: slskd/slskd:latest + volumes: + # slskd saves completed downloads here + - /mnt/data/slskd-downloads:/downloads + - /docker/slskd/config:/app + soulsync: + image: boulderbadgedad/soulsync:latest + volumes: + # SAME host folder as slskd — this is the key! + - /mnt/data/slskd-downloads:/app/downloads + # Your media server's music folder + - /mnt/media/music:/app/Transfer:rw + # Config, logs, staging, database + - /docker/soulsync/config:/app/config + - /docker/soulsync/logs:/app/logs + - /docker/soulsync/staging:/app/Staging + - soulsync_database:/app/data + # Then in SoulSync Settings: + # Download Path: /app/downloads + # Transfer Path: /app/Transfer + + + Setup Checklist + Go through every item. If you miss any single one, the pipeline will break: + + slskd download folder is mounted in SoulSync's container — Both containers must mount the same host directory. The host paths (left side of :) must be identical. + Media server's music folder is mounted as Transfer — Mount the folder your Plex/Jellyfin/Navidrome monitors as /app/Transfer with :rw permissions. + SoulSync Settings are configured — Open Settings → Download Settings. Set Download Path to /app/downloads and Transfer Path to /app/Transfer (or whatever container paths you used on the right side of :). + slskd URL and API key are set — In Settings → Soulseek, enter your slskd URL (e.g., http://slskd:5030 or http://host.docker.internal:5030) and API key. + PUID/PGID match your host user — Run id on your host. Set those values in docker-compose environment variables. Both slskd and SoulSync should use the same PUID/PGID. + Test with one track — Download a single track. Watch the logs. If it downloads but doesn't transfer, the paths are wrong. + + + Permissions + If paths are correct but files still won't transfer, it's usually a permissions issue. SoulSync needs read + write access to all three folders. + + Set PUID and PGID in your docker-compose to match the user that owns your music folders (run id on your host to find your UID/GID — usually 1000/1000) + Ensure the Transfer folder is writable: chmod -R 755 /mnt/media/music (use your actual host path) + If using multiple containers (slskd + SoulSync), both must use the same PUID/PGID so file permissions are compatible + NFS/CIFS/network mounts may need additional permissions — test with a local folder first to isolate the issue + + + Verifying Your Setup + Run these commands to confirm everything is wired up correctly: + + Verify downloads are visible: docker exec soulsync-webui ls -la /app/downloads — you should see slskd's downloaded files here. If empty or "No such file or directory", your volume mount is wrong. + Verify Transfer is writable: docker exec soulsync-webui touch /app/Transfer/test.txt && echo "OK" — then check that test.txt appears in your media server's music folder on the host. Clean up after: rm /mnt/media/music/test.txt + Verify permissions: docker exec soulsync-webui id — the uid and gid should match your PUID/PGID values. + Verify app settings: Open SoulSync Settings → Download Settings. Confirm the Download Path and Transfer Path show container paths (like /app/downloads), not host paths. + Test a single download: Search for a track, download it, and watch the logs. Enable DEBUG logging in Settings for full detail. Check logs/app.log for any path errors. + + + Troubleshooting + + SymptomLikely CauseFix + + Files download but never transferApp settings not configured — docker-compose volumes are set but SoulSync Settings still have defaults or wrong pathsOpen Settings → Download Settings and set Download Path + Transfer Path to your container-side mount paths. + Post-processing log is emptySoulSync can't find the downloaded file at the expected path — the Download Path in Settings doesn't match where slskd actually saves files inside the containerRun docker exec soulsync-webui ls /app/downloads to see what's actually there. The Download Path in Settings must match this path exactly. + Same tracks downloading multiple timesPost-processing fails so SoulSync thinks the track was never downloaded successfully. On resume, it tries again.Fix the folder paths first. Once post-processing works, files move to Transfer and SoulSync knows they exist. + Files not renamed properlyPost-processing isn't running (path mismatch) or file organization is disabled in SettingsVerify File Organization is enabled in Settings → Processing & Organization. Fix Download Path first. + Permission denied in logsContainer user can't write to the Transfer folder on the hostSet PUID/PGID to match the host user that owns the music folder. Run chmod -R 755 on the Transfer host folder. + Media server doesn't see new filesTransfer Path doesn't map to the folder your media server monitorsEnsure the host path in your SoulSync volume mount (/mnt/media/music:/app/Transfer) is the same folder Plex/Jellyfin/Navidrome watches. + slskd downloads work fine on their own but not through SoulSyncslskd's download folder and SoulSync's Download Path point to different physical locationsBoth containers must mount the same host directory. Check the left side of : in both docker-compose volume entries — they must match. + + + 💡Still stuck? Enable DEBUG logging in Settings, download a single track, and check logs/app.log. The post-processing log will show exactly where the file pipeline breaks — whether it's a path not found, permission denied, or verification failure. If the post-processing log is empty, the issue is almost certainly a path mismatch (SoulSync never found the file to process). + Docker & Deployment SoulSync runs in Docker with the following environment variables: @@ -86,8 +262,21 @@ const DOCS_SECTIONS = [ SOULSYNC_COMMIT_SHA(auto)Baked in at Docker build time. Used for update detection — compares against GitHub's latest commit. - Key volume mounts: Map your download path, transfer path (media server's monitored folder), and staging path to host directories. Ensure the paths configured in SoulSync Settings match the container-side mount points. - ⚠️If using slskd in a separate container, make sure both containers can access the same download directory. A common issue is slskd writing to a path that SoulSync can't read because the volume mounts don't align. Both containers must see the same files at the same internal path. + Key Volume Mounts + Your docker-compose volumes section must include these mappings. The left side is your host path, the right side is where SoulSync sees it inside the container: + + MountContainer PathWhat Goes Here + + slskd downloads/app/downloadsMust be the same physical folder slskd writes completed downloads to. Both containers mount the same host directory. + Music library/app/TransferYour media server's monitored music folder. Add :rw to ensure write access. + Staging/app/Staging(Optional) For the Import feature — drop files here to import them. + Config/app/configStores config.json and encryption key. Persists settings across restarts. + Logs/app/logsApplication logs including app.log and post-processing.log. + Database/app/dataMust use a named volume (not a host path). Host path mounts can cause database corruption. + + + ⚠️slskd + SoulSync shared downloads: If slskd runs in a separate container, both containers must mount the same host directory for downloads. A common issue is slskd writing to a path that SoulSync can't read because the volume mounts don't align. Both containers must see the same files. See the Folder Setup section above for detailed examples. + ⚠️Database volume: Always use a named volume for the database (soulsync_database:/app/data), never a host path mount. Host path mounts can cause SQLite corruption, especially on networked file systems or when permissions don't align. Podman / Rootless Docker: SoulSync supports Podman rootless (keep-id) and rootless Docker setups. The entrypoint handles permission alignment automatically. Config migration: When upgrading from older versions, SoulSync automatically migrates settings from config.json to the database on first startup. No manual migration is needed. @@ -840,13 +1029,14 @@ const DOCS_SECTIONS = [ Download Settings Download Source Mode — Soulseek, YouTube, Tidal, or Hybrid. Hybrid tries your primary source first, then falls back to alternates. See Download Sources in the Music Downloads section for details. - Download Path — Where files are initially downloaded and processed - Transfer Path — Where processed files are moved after tagging and organization. Should point to your media server's monitored folder. - Staging Path — Folder for the Import feature (files placed here appear on the Import page) + Download Path — The folder where files are initially downloaded. This must match the folder your download source (slskd) writes to. In Docker, this is the container-side mount point (e.g., /app/downloads), not the host path. SoulSync monitors this folder for completed downloads to begin post-processing. + Transfer Path — The final destination for processed music files. After tagging, renaming, and organizing, files are moved here. This must point to your media server's monitored music folder (the folder Plex/Jellyfin/Navidrome watches for new content). In Docker, use the container-side path (e.g., /app/Transfer). + Staging Path — Folder for the Import feature (files placed here appear on the Import page). Separate from the download/transfer pipeline. iTunes Country — Storefront region for iTunes/Apple Music lookups (US, GB, FR, JP, etc.). Changes apply immediately to all searches without restarting. ID-based lookups automatically try up to 10 regional storefronts as fallback when the primary country returns no results. Lossy Copy — When enabled, creates a lower-bitrate MP3 copy of every downloaded file. Configure the output bitrate (default 320kbps) and output folder. Optionally delete the original lossless file after creating the lossy copy. Useful for syncing to mobile devices or streaming servers with bandwidth constraints. Content Filtering — Toggle explicit content filtering to control whether explicit tracks appear in search results and downloads. + ⚠️Docker users: Always use container-side paths in these settings (e.g., /app/downloads, /app/Transfer). Never use host paths like /mnt/music — the container can't access those. Your docker-compose volumes section is where host paths are mapped to container paths. See Getting Started → Folder Setup for a complete walkthrough. Processing & Organization @@ -1100,7 +1290,7 @@ function initializeDocsPage() { }); // Search filter - const searchInput = document.getElementById('docs-search'); + const searchInput = document.getElementById('docs-search-input'); if (searchInput) { searchInput.addEventListener('input', () => { const q = searchInput.value.toLowerCase().trim(); @@ -1153,6 +1343,14 @@ function initializeDocsPage() { } }); + // Default to first section if nothing scrolled past threshold yet + if (!activeSection && DOCS_SECTIONS.length) { + activeSection = DOCS_SECTIONS[0].id; + if (DOCS_SECTIONS[0].children && DOCS_SECTIONS[0].children.length) { + activeChild = DOCS_SECTIONS[0].children[0].id; + } + } + // Update nav highlighting nav.querySelectorAll('.docs-nav-section-title').forEach(t => { const isActive = t.dataset.target === activeSection; @@ -1168,7 +1366,8 @@ function initializeDocsPage() { }); } - // Auto-expand first section + // Reset scroll position and auto-expand first section + if (docsContent) docsContent.scrollTop = 0; const firstTitle = nav.querySelector('.docs-nav-section-title'); if (firstTitle) { firstTitle.classList.add('expanded', 'active');
Version & Updates: Click the version number in the sidebar footer to open the What's New modal, which shows detailed release notes for every feature and fix. SoulSync automatically checks for updates by comparing your running version against the latest GitHub commit. If an update is available, a banner appears in the modal. Docker users are notified when a new image has been pushed to the repo.
SoulSync uses three folders to manage your music files. Most setup issues come from incorrect folder configuration — especially in Docker. Read this section carefully.
docker-compose.yml
/app/downloads
/app/Transfer
/app/Staging
Artist/Album/01 - Title.flac
In Docker, every app runs in its own isolated container with its own filesystem. Volume mounts in docker-compose create "bridges" between your host folders and the container. But SoulSync doesn't automatically know where those bridges go — you have to tell it via the Settings page.
Here's what happens with a properly configured setup:
/mnt/data/slskd-downloads/
/mnt/media/music/
/mnt/data/slskd-downloads
/mnt/media/music
/app/downloads/
/app/Transfer/
Many users set up their docker-compose volumes correctly but never open SoulSync Settings to configure the paths. The app defaults may not match your volume mounts. You must go to Settings → Download Settings and verify that:
The Download Path in SoulSync must point to the exact same physical folder where slskd saves its completed downloads. If they don't match, SoulSync can't find the files and post-processing fails silently.
/downloads/complete
- /mnt/data/slskd-downloads:/downloads/complete
- /mnt/data/slskd-downloads:/app/downloads
If you're running in Docker, the paths you enter in SoulSync's Settings page must be container-side paths (the right side of the : in your volume mount), not host paths (the left side). SoulSync runs inside the container and can only see its own filesystem.
:
/mnt/music
./downloads
Your Transfer Path must ultimately point to the same physical directory your media server monitors. This is how new music appears in Plex/Jellyfin/Navidrome.
- /mnt/media/music:/app/Transfer:rw
Here's a working example showing both slskd and SoulSync configured to share the same download folder:
# docker-compose.yml
services:
slskd:
image: slskd/slskd:latest
volumes:
# slskd saves completed downloads here
- /mnt/data/slskd-downloads:/downloads
- /docker/slskd/config:/app
soulsync:
image: boulderbadgedad/soulsync:latest
# SAME host folder as slskd — this is the key!
# Your media server's music folder
# Config, logs, staging, database
- /docker/soulsync/config:/app/config
- /docker/soulsync/logs:/app/logs
- /docker/soulsync/staging:/app/Staging
- soulsync_database:/app/data
# Then in SoulSync Settings:
# Download Path: /app/downloads
# Transfer Path: /app/Transfer
Go through every item. If you miss any single one, the pipeline will break:
:rw
http://slskd:5030
http://host.docker.internal:5030
id
If paths are correct but files still won't transfer, it's usually a permissions issue. SoulSync needs read + write access to all three folders.
PUID
PGID
chmod -R 755 /mnt/media/music
Run these commands to confirm everything is wired up correctly:
docker exec soulsync-webui ls -la /app/downloads
docker exec soulsync-webui touch /app/Transfer/test.txt && echo "OK"
test.txt
rm /mnt/media/music/test.txt
docker exec soulsync-webui id
logs/app.log
docker exec soulsync-webui ls /app/downloads
chmod -R 755
/mnt/media/music:/app/Transfer
SoulSync runs in Docker with the following environment variables:
SOULSYNC_COMMIT_SHA
Key volume mounts: Map your download path, transfer path (media server's monitored folder), and staging path to host directories. Ensure the paths configured in SoulSync Settings match the container-side mount points.
Your docker-compose volumes section must include these mappings. The left side is your host path, the right side is where SoulSync sees it inside the container:
volumes
/app/config
config.json
/app/logs
app.log
post-processing.log
/app/data
soulsync_database:/app/data
Podman / Rootless Docker: SoulSync supports Podman rootless (keep-id) and rootless Docker setups. The entrypoint handles permission alignment automatically.
Config migration: When upgrading from older versions, SoulSync automatically migrates settings from config.json to the database on first startup. No manual migration is needed.