Your Spotify

Your Spotify is a self-hosted web application that tracks your Spotify listening history and displays detailed statistics and visualisations of your music habits.

This compose file deploys Your Spotify, a FerretDB for data storage. Both the API and client are proxied through a Traefik reverse proxy with Cloudflare TLS certificates, and all persistent data is stored on NFS volumes.

Docker Compose

# compose.yaml

services:
  your-spotify-api:
    image: yooooomi/your_spotify_server
    container_name: your-spotify-api
    restart: unless-stopped
    depends_on:
      your-spotify-ferret:
        condition: service_healthy
      your-spotify-postgres:
        condition: service_healthy
    # ports:
    #  - 8080:8080
    networks:
      - your-spotify
      - your-spotify_proxy
    environment:
      API_ENDPOINT: https://your-spotify-api.${TRAEFIK_BASE_URL}
      CLIENT_ENDPOINT: https://your-spotify.${TRAEFIK_BASE_URL}
      SPOTIFY_PUBLIC: ${SPOTIFY_CLIENT_ID}
      SPOTIFY_SECRET: ${SPOTIFY_CLIENT_SECRET}
      MONGO_ENDPOINT: mongodb://${POSTGRES_USERNAME}:${POSTGRES_PASSWORD}@your-spotify-ferret:27017
      TIMEZONE: Europe/London
    labels:
      - "traefik.enable=true"
      - "traefik.docker.network=your-spotify_proxy"

      - "traefik.http.services.your-spotify-api.loadbalancer.server.port=8080"

      - "traefik.http.routers.your-spotify-api.rule=Host(`your-spotify-api.${TRAEFIK_BASE_URL}`)"
      - "traefik.http.routers.your-spotify-api.entrypoints=websecure"
      - "traefik.http.routers.your-spotify-api.tls.certresolver=cloudflare"

  your-spotify-postgres:
    image: ghcr.io/ferretdb/postgres-documentdb:17
    container_name: your-spotify-postgres
    restart: unless-stopped
    # ports:
    #   - 5432:5432
    networks:
      - your-spotify
    volumes:
      - type: volume
        source: docker-nfs
        target: /var/lib/postgresql/data
        volume:
          subpath: your-spotify/postgres
    healthcheck:
      test:
        ["CMD", "pg_isready", "-U", "${POSTGRES_USERNAME}", "-d", "${POSTGRES_DB}"]
      interval: 10s
      timeout: 5s
      retries: 5
    environment:
      POSTGRES_USER: ${POSTGRES_USERNAME}
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
      POSTGRES_DB: ${POSTGRES_DB}
      TZ: Europe/London

  your-spotify-ferret:
    image: ghcr.io/ferretdb/ferretdb:2
    container_name: your-spotify-ferret
    restart: unless-stopped
    depends_on:
      your-spotify-postgres:
        condition: service_healthy
    networks:
      - your-spotify
    volumes:
      - type: volume
        source: docker-nfs
        target: /state
        volume:
          subpath: your-spotify/ferret
    healthcheck:
      test: ["CMD", "/ferretdb", "ping"]
      interval: 30s
      timeout: 5s
      retries: 3
      start_period: 10s
    environment:
      FERRETDB_POSTGRESQL_URL: postgres://${POSTGRES_USERNAME}:${POSTGRES_PASSWORD}@your-spotify-postgres:5432/${POSTGRES_DB}
      TZ: Europe/London

  your-spotify-client:
    image: yooooomi/your_spotify_client
    container_name: your-spotify-client
    restart: unless-stopped
    # ports:
    #  - 3000:3000
    networks:
      - your-spotify
      - your-spotify_proxy
    environment:
      API_ENDPOINT: https://your-spotify-api.${TRAEFIK_BASE_URL}
      TIMEZONE: Europe/London
    labels:
      - "traefik.enable=true"
      - "traefik.docker.network=your-spotify_proxy"

      - "traefik.http.services.your-spotify.loadbalancer.server.port=3000"

      - "traefik.http.routers.your-spotify.rule=Host(`your-spotify.${TRAEFIK_BASE_URL}`)"
      - "traefik.http.routers.your-spotify.entrypoints=websecure"
      - "traefik.http.routers.your-spotify.tls.certresolver=cloudflare"

volumes:
  docker-nfs:
    driver: local
    driver_opts:
      type: nfs
      o: addr=xxx.xxx.xxx.xxx,nolock,soft,rw,nfsvers=4.2
      device: :/mnt/nfs-volume

networks:
  your-spotify:
    name: your-spotify
  your-spotify_proxy:
    name: your-spotify_proxy

Environment Variables

# .env

TRAEFIK_BASE_URL=
SPOTIFY_CLIENT_ID=
SPOTIFY_CLIENT_SECRET=
POSTGRES_USERNAME=
POSTGRES_PASSWORD=
POSTGRES_DB=

Traefik Configuration

# compose.yaml (excerpt)

services:
  traefik:
    image: traefik:latest
    container_name: traefik
    ...
    networks:
      - traefik
      # here
      - your-spotify_proxy
    ...

networks:
  # here
  your-spotify_proxy:
    name: your-spotify_proxy