Production deploy for musicshare.binarygnome.com
- docker-compose.prod.yml overlay: Caddy with automatic HTTPS on one origin (web at /, API at /api incl. websocket), internal-only Postgres/ Redis/API/web, secure cookies, private-network servers blocked, nightly pg_dump backups kept 14 days - deploy/export-db.sh and import-db.sh to carry a database to the server (same TOKEN_ENCRYPTION_KEY required for stored connections) - Base compose no longer requires apps/api/.env - README: deployment, Spotify via scrobblers, SMTP settings Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MzFywujuH9TiuXbr9vjoX8
This commit is contained in:
@@ -23,6 +23,18 @@ docker compose up -d --build # Postgres, Redis, migrations, API, wor
|
||||
Open http://localhost:3737. Logs: `docker compose logs -f api worker`. Stop: `docker compose down` (data is kept in volumes).
|
||||
Migrations run automatically before the API and worker start. A Jellyfin/Plex server on your machine is reachable from the containers as `host.docker.internal`.
|
||||
|
||||
## Deploying (musicshare.binarygnome.com)
|
||||
|
||||
Everything is served from one origin: the web app at `/`, the API at `/api` (Caddy strips the prefix), including the `/api/ws` websocket. Caddy obtains and renews HTTPS certificates automatically.
|
||||
|
||||
1. **DNS:** an `A` record (and `AAAA` if the server has IPv6) for `musicshare.binarygnome.com` pointing at the server. Ports 80 and 443 must reach it.
|
||||
2. **Config:** `cp deploy/production.env.example deploy/production.env` and fill it in (`openssl rand -base64 32` for the password and encryption key).
|
||||
3. **Start:** `docker compose -f docker-compose.yml -f docker-compose.prod.yml --env-file deploy/production.env up -d --build`
|
||||
4. **Spotify (optional):** app credentials only enable exact Spotify links; no redirect URI is needed.
|
||||
5. **Mobile builds:** set `EXPO_PUBLIC_API_URL=https://musicshare.binarygnome.com/api` and `EXPO_PUBLIC_WEB_URL=https://musicshare.binarygnome.com`.
|
||||
|
||||
In production only Caddy is exposed; Postgres, Redis, the API and the web app stay on the internal Docker network. A `backup` service writes a gzipped `pg_dump` to `./backups` nightly and keeps 14 days. Copy that folder off the server regularly. The website is installable as a PWA once it's on HTTPS.
|
||||
|
||||
## Running for development (hot reload)
|
||||
|
||||
Requires Node 22.13+ and Docker.
|
||||
@@ -40,9 +52,9 @@ Optional keys in `apps/api/.env`:
|
||||
|
||||
| Key | Enables |
|
||||
|---|---|
|
||||
| `SPOTIFY_CLIENT_ID/SECRET` | Spotify connections + exact Spotify links via ISRC. Add redirect URI `http://127.0.0.1:4000/connections/spotify/callback` in the Spotify dashboard (Spotify rejects `localhost`). |
|
||||
| `SPOTIFY_CLIENT_ID/SECRET` | Optional: exact "Open in Spotify" links via catalog search (app-level credentials; no user sign-in). Without it, Spotify links come from song.link or a search. |
|
||||
| `LASTFM_API_KEY` | Last.fm connections (covers YouTube Music, Tidal, Deezer, SoundCloud… via scrobbling) |
|
||||
| `LASTFM_SHARED_SECRET` | One-tap "Sign in with Last.fm" (instead of typing a username). Also powers "Spotify via Last.fm", the route that works for every Spotify user while direct Spotify sign-in is capped. |
|
||||
| `LASTFM_SHARED_SECRET` | One-tap "Sign in with Last.fm" (instead of typing a username). Also the main route for Spotify: users link Spotify to Last.fm on Last.fm's site. |
|
||||
| `APPLE_TEAM_ID`, `APPLE_MUSICKIT_KEY_ID`, `APPLE_MUSICKIT_PRIVATE_KEY` | Apple Music. Create a key with MusicKit enabled under Apple Developer → Keys; paste the `.p8` contents with newlines as `\n`. |
|
||||
| `ODESLI_API_KEY` | Direct YouTube Music + TIDAL links via song.link. Without it, those fall back to search links. |
|
||||
| `PLEX_CLIENT_ID` | Identifies the app in Plex's sign-in flow. Pick a unique value before launch and never change it. |
|
||||
@@ -61,7 +73,7 @@ npm run mobile # starts Metro; scan the QR code with a dev build or Expo
|
||||
- The app talks to the API on the same host as Metro (your LAN IP, port 4000), so phone and computer must be on the same network. Set `EXPO_PUBLIC_API_URL` for other environments.
|
||||
- The app includes custom native code (the Android now-playing reader), so it needs a **development build**, not Expo Go: `npm run android -w @musicshare/mobile` (needs the Android SDK and JDK 17) or `npx eas-cli@latest build --profile development`. In Expo Go the reader is simply hidden.
|
||||
- `android/` and `ios/` are generated by `expo prebuild` and gitignored; configure native settings in `app.json` and `modules/`.
|
||||
- **Spotify/Plex sign-in from a phone:** the OAuth callback goes to `API_PUBLIC_URL`, which defaults to `127.0.0.1` — that's the phone itself. Expose the API with a tunnel (`cloudflared tunnel --url http://localhost:4000`) and set `API_PUBLIC_URL` to the https URL (and add it as a redirect URI in the Spotify dashboard).
|
||||
- **Plex/Last.fm sign-in from a phone:** the sign-in callback goes to `API_PUBLIC_URL`, so set it to an address the phone can reach (your LAN IP, a tunnel, or the production domain).
|
||||
- Bundle IDs are `tech.chrisedwards.musicshare` (in `apps/mobile/app.json`); change before your first store build, they're permanent after.
|
||||
|
||||
### Tests
|
||||
@@ -111,7 +123,7 @@ Links are https universal links, so on phones they open the native app. Missing
|
||||
|
||||
| Service | Status | Notes |
|
||||
|---|---|---|
|
||||
| Spotify | ✅ | **Development mode now caps an app at 5 allow-listed users** (Feb 2026). Accounts beyond that are sent back with a "limited during beta" message offering Spotify via Last.fm. Since May 2025, extended quota is only granted to registered businesses with an established user base, so plan for this before launch. Last.fm is the fallback for Spotify users beyond the cap. |
|
||||
| Spotify | ✅ | **No direct sign-in** (Spotify caps new apps at 5 accounts). Users link Spotify to **Last.fm** or **ListenBrainz** (Spotify's own integrations) and we read it from there; on Android the phone reader shares Spotify automatically. Guided in onboarding and Settings. |
|
||||
| Last.fm | ✅ | Covers almost any service via scrobbling |
|
||||
| ListenBrainz | ✅ | |
|
||||
| Plex | ✅ | Plex sign-in (PIN flow), server discovery via plex.tv, polls `/status/sessions` on each server (remote → relay → LAN). Optional Plex Pass webhook for instant updates. |
|
||||
|
||||
Reference in New Issue
Block a user