Make OAuth callback ports configurable via environment variables

Hardcoded ports 8888/8889 conflict when SoulSync runs behind Gluetun or
other containers that claim those ports. Introduce SOULSYNC_SPOTIFY_CALLBACK_PORT
and SOULSYNC_TIDAL_CALLBACK_PORT env vars (defaulting to 8888/8889) so
users can remap without rebuilding the image.

docker-compose.yml exposes the vars with comments explaining how to keep
the port mappings in sync with the redirect URI in Settings → Connections.
This commit is contained in:
Broque Thomas 2026-04-14 14:08:31 -07:00
parent 6e405143a7
commit 1071b2ebe5
3 changed files with 39 additions and 30 deletions

View file

@ -1,3 +1,4 @@
import os
import requests import requests
import time import time
import re import re
@ -119,7 +120,8 @@ class TidalClient:
self.alt_base_url = "https://api.tidal.com/v1" # Alternative API base self.alt_base_url = "https://api.tidal.com/v1" # Alternative API base
self.auth_url = "https://login.tidal.com/authorize" self.auth_url = "https://login.tidal.com/authorize"
self.token_url = "https://auth.tidal.com/v1/oauth2/token" self.token_url = "https://auth.tidal.com/v1/oauth2/token"
self.redirect_uri = "http://127.0.0.1:8889/tidal/callback" # Default, will be updated from config _tidal_port = int(os.environ.get('SOULSYNC_TIDAL_CALLBACK_PORT', 8889))
self.redirect_uri = f"http://127.0.0.1:{_tidal_port}/tidal/callback" # Default, will be updated from config
self.session = requests.Session() self.session = requests.Session()
self.auth_server = None self.auth_server = None
self.auth_code = None self.auth_code = None
@ -347,7 +349,7 @@ class TidalClient:
pass # Suppress server logs pass # Suppress server logs
try: try:
port = 8889 port = int(os.environ.get('SOULSYNC_TIDAL_CALLBACK_PORT', 8889))
self.auth_server = HTTPServer(('localhost', port), CallbackHandler) self.auth_server = HTTPServer(('localhost', port), CallbackHandler)
server_thread = threading.Thread(target=self.auth_server.serve_forever) server_thread = threading.Thread(target=self.auth_server.serve_forever)
server_thread.daemon = True server_thread.daemon = True

View file

@ -20,10 +20,15 @@ services:
- SOULSYNC_CONFIG_PATH=/app/config/config.json - SOULSYNC_CONFIG_PATH=/app/config/config.json
# Set timezone (change to your timezone) # Set timezone (change to your timezone)
- TZ=America/New_York - TZ=America/New_York
# OAuth callback ports. If 8888/8889 conflict with another container (e.g. Gluetun),
# change the port numbers below AND update the matching port mappings in the ports section.
# Then update the redirect URI in SoulSync → Settings → Connections to match.
- SOULSYNC_SPOTIFY_CALLBACK_PORT=8888
- SOULSYNC_TIDAL_CALLBACK_PORT=8889
ports: ports:
- "8008:8008" # Main web app - "8008:8008" # Main web app
- "8888:8888" # Spotify OAuth callback - "8888:8888" # Spotify OAuth callback — keep in sync with SOULSYNC_SPOTIFY_CALLBACK_PORT above
- "8889:8889" # Tidal OAuth callback - "8889:8889" # Tidal OAuth callback — keep in sync with SOULSYNC_TIDAL_CALLBACK_PORT above
volumes: volumes:
# Persistent data volumes # Persistent data volumes
- ./config:/app/config - ./config:/app/config

View file

@ -49711,15 +49711,16 @@ def start_oauth_callback_servers():
# Start Spotify callback server # Start Spotify callback server
def run_spotify_server(): def run_spotify_server():
spotify_port = int(os.environ.get('SOULSYNC_SPOTIFY_CALLBACK_PORT', 8888))
try: try:
bind_addr = ('0.0.0.0', 8888) bind_addr = ('0.0.0.0', spotify_port)
spotify_server = HTTPServer(bind_addr, SpotifyCallbackHandler) spotify_server = HTTPServer(bind_addr, SpotifyCallbackHandler)
_oauth_logger.info(f"Spotify OAuth callback server listening on {bind_addr[0]}:{bind_addr[1]}") _oauth_logger.info(f"Spotify OAuth callback server listening on {bind_addr[0]}:{bind_addr[1]}")
print(f"Started Spotify OAuth callback server on {bind_addr[0]}:{bind_addr[1]}") print(f"Started Spotify OAuth callback server on {bind_addr[0]}:{bind_addr[1]}")
spotify_server.serve_forever() spotify_server.serve_forever()
except OSError as e: except OSError as e:
_oauth_logger.error(f"Failed to start Spotify callback server on port 8888: {e} — port may already be in use") _oauth_logger.error(f"Failed to start Spotify callback server on port {spotify_port}: {e} — port may already be in use")
print(f"Failed to start Spotify callback server on port 8888: {e}") print(f"Failed to start Spotify callback server on port {spotify_port}: {e}")
except Exception as e: except Exception as e:
_oauth_logger.error(f"Failed to start Spotify callback server: {e}") _oauth_logger.error(f"Failed to start Spotify callback server: {e}")
print(f"Failed to start Spotify callback server: {e}") print(f"Failed to start Spotify callback server: {e}")
@ -49789,9 +49790,10 @@ def start_oauth_callback_servers():
def run_tidal_server(): def run_tidal_server():
try: try:
tidal_server = HTTPServer(('0.0.0.0', 8889), TidalCallbackHandler) tidal_port = int(os.environ.get('SOULSYNC_TIDAL_CALLBACK_PORT', 8889))
print("Started Tidal OAuth callback server on port 8889") tidal_server = HTTPServer(('0.0.0.0', tidal_port), TidalCallbackHandler)
print(f"Tidal server listening on all interfaces, port 8889") print(f"Started Tidal OAuth callback server on port {tidal_port}")
print(f"Tidal server listening on all interfaces, port {tidal_port}")
tidal_server.serve_forever() tidal_server.serve_forever()
except Exception as e: except Exception as e:
print(f"Failed to start Tidal callback server: {e}") print(f"Failed to start Tidal callback server: {e}")