Install the server on Windows 10/11
Written to be followed in order. Each step says how to tell it worked, because several of the failures here are silent — the app starts, looks right, and does nothing useful.
Honesty first: SoundChex is developed on macOS, and the Windows port has had less real-world mileage. The path-handling, LAN-detection and Tailscale-lookup fixes for Windows exist specifically because a Unix-shaped codebase breaks there — which is also why step 7 says to scan a small folder first. If something misbehaves, report it; it will get fixed.
1. Install the toolchain
| Tool | Where | Notes |
|---|---|---|
| PHP 8.4+ | windows.php.net or winget install PHP.PHP | |
| Composer | getcomposer.org | |
| Node 22+ | winget install OpenJS.NodeJS | |
| FFmpeg | winget install Gyan.FFmpeg | Transcoding, captions and durations all shell out to it |
(Rust and Visual Studio Build Tools are only needed to build the desktop app — the server runs without them.)
Reopen your terminal after installing. winget changes the
PATH and an open shell won't see it. Then check: php -v, node -v,
composer -V, ffmpeg -version. FFmpeg is the one most often missing —
without it, files catalogue but won't play, with nothing obvious in the app.
2. Get the code
git clone https://github.com/tripsittr/SoundChex.git
cd SoundChex
composer install
npm install
3. Configure it
copy .env.example .env
php artisan key:generate
Then open .env and set two things.
Where the media is. Absolute paths, comma-separated. Backslashes are fine — the split is on commas, so a drive letter is never mistaken for a separator:
LIBRARY_WATCH_FOLDERS=D:\Media\Music,D:\Media\Films
What the app calls itself. This is the address it advertises to phones and other devices, so the port matters:
APP_URL=http://localhost:8000
4. Give PHP a certificate bundle
Windows PHP ships without one, so every outbound HTTPS request fails with
cURL error 60: unable to get local issuer certificate — metadata, artwork,
subtitles and server transfers alike. It reads as a network problem; it's a configuration one.
macOS and Linux don't hit this.
Download cacert.pem, put it somewhere permanent,
and point php.ini at it:
curl.cainfo = "C:\php\extras\ssl\cacert.pem"
openssl.cafile = "C:\php\extras\ssl\cacert.pem"
Restart php artisan serve and queue:work afterwards
— both need it. Check:
php -r "var_dump(file_get_contents('https://api.themoviedb.org/3/'));"
Anything other than an SSL error means it works.
5. Database, storage link, front end
php artisan migrate --force
php artisan storage:link
npm run build
- Migrate creates SQLite at
database\database.sqlite— no file exists in a fresh clone and none is needed. storage:linkfails silently if skipped — every avatar and artist image 404s. Windows restricts symlink creation: turn on Settings → System → For developers → Developer Mode, or run from an Administrator terminal.- Check:
public\build\manifest.jsonexists (else pages render unstyled), andpublic\storageopens to the contents ofstorage\app\public.
6. Start it
php artisan serve # the app
php artisan queue:work # enrichment, transcoding, downloads
php artisan schedule:work # scanning, backups, pruning
Three terminals — or set the workers up as Windows services with NSSM. The Admin → Services page that manages them on macOS is launchd-based; on Windows it detects this and says so rather than failing.
Check: open http://localhost:8000, register — the first account
becomes the owner.
7. Scan the library — start small
php artisan library:scan
Start with a small folder — a dozen files, not the whole collection. This is
the step most likely to fail on Windows, because path handling is where a Unix-shaped codebase
breaks. If the scan finds nothing, or finds files it can't then play, check the watch-folder
paths first. Check: items appear at http://localhost:8000/app/music
and play.
If something is wrong
| Symptom | Cause |
|---|---|
| Pages render with no styling | npm run build was not run |
| Avatars and artist images 404 | php artisan storage:link skipped or failed |
| Scan finds nothing | Watch folder paths — step 7 |
| Files catalogued but won't play | ffmpeg not on the PATH |
| Phones can't find the server | APP_URL missing its port, or the firewall |
cURL error 60 on anything | No CA bundle — step 4 |
| Services page says unsupported | Expected — it is launchd-only |
The app records what fails: Admin → Device reports shows what each device sent back, filterable by device and log type — more use than guessing.