Security (P0): - Remove committed session-secret default; auto-generate and persist a random secret to the config volume when SESSION_SECRET is unset (prevents forgeable session cookies / auth bypass). - Validate playlist names to a safe charset and render sldl configs via literal Python substitution instead of sed (closes a command-injection and path-traversal path through playlist names). - shlex-quote credential values written to shell-sourced env files, and strip newlines from values patched into .conf files. - Render playlist .conf files 0600; warn at startup if the master key is co-located with the config volume; document keeping it separate. Portability: - Configurable timezone via TZ (default UTC) instead of hardcoded Edmonton. - Remove personal defaults (navidrome user "andrew", ephemeral.club URLs). - Ship generic example seeds; move the cross-album dedup keep-list and the legacy playlist import to editable config files; drop the personal _upgrade.csv. - Generic VPN reference in docker-compose.snippet.yml. First-run experience: - Redirect to /setup instead of 500 when OIDC is unconfigured; surface a missing master key inline; entrypoint exits with an actionable message when the config folder is not writable. - Add unauthenticated /health (JSON) and /setup (checklist) diagnostics. Docs: - Write docs/ARCHITECTURE.md and docs/MIGRATION.md (previously referenced but missing); expand README with ownership, backups, advanced settings, and migration guidance. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2.8 KiB
Migrating from the legacy scripts
This is only for people moving from the earlier version of this project, when
it was a collection of scripts under /opt/sldl with credentials scattered in
separate config folders. If you are setting up alembic fresh, ignore this file
and follow the README.
The migration does two things: bring your old playlists in, and bring your old credentials in. Order matters, so do them in this order.
1. Import your playlists
seed_legacy() reads a JSON file at /config/pipeline/legacy-playlists.json
and creates a playlist row for each entry. The file is not shipped with your
playlists in it; you provide it. There is an example to copy from at
pipeline/configs/legacy-playlists.json.example.
Each entry looks like this:
[
{
"name": "techno",
"spotify_url": "https://open.spotify.com/playlist/your-id-here",
"cron_expr": "0 1 * * *",
"no_m3u": false
}
]
Put your file at /config/pipeline/legacy-playlists.json, then run the seed
once:
docker exec alembic python -c "from app.db import SessionLocal; from app.services import playlist_service; db=SessionLocal(); print('created', playlist_service.seed_legacy(db)); db.close()"
It is safe to run more than once. It skips any playlist name that already exists.
2. Import your credentials
Do this after step 1, not before. The credential import re-renders every existing playlist config file with your Soulseek and Spotify details. If no playlists exist yet, that render has nothing to write to and the step quietly does nothing.
scripts/import_legacy_credentials.py reads your old plaintext credentials and
saves them into alembic's encrypted store. It only reads the legacy files, it
never changes them, and it is safe to run more than once.
It expects your old config folders bind-mounted read-only at /legacy/*. Run
it as a one-off container against the same image and config volume, for example:
docker run --rm \
-v /path/to/alembic-config:/config \
-v /path/to/old/opt-sldl:/legacy/opt-sldl:ro \
-v /path/to/old/bandcampconfig:/legacy/bandcampconfig:ro \
-v /path/to/old/azuracastconfig:/legacy/azuracastconfig:ro \
-v /path/to/old/qobuzconfig:/legacy/qobuzconfig:ro \
-v /path/to/old/telegramconfig:/legacy/telegramconfig:ro \
--secret ... \
--entrypoint python \
alembic:latest /app/scripts/import_legacy_credentials.py
Leave off any -v /legacy/... mount for a service you never used. The importer
skips a legacy folder that is not present.
3. Retire the old services
Once alembic is running your syncs and you have confirmed a playlist downloads and imports correctly, you can remove the old on-demand download service and the old import service from your compose file. Keep your old config folders backed up until you are confident, since the importer only reads them.