Your Spotify
A self-hosted Spotify listening statistics tracker.
Your Spotify is an open-source application that tracks your Spotify listening history and provides detailed statistics and visualizations about your music habits. It consists of a server (Node.js + MongoDB) and a React client. Self-hosting keeps your listening data private and gives you unlimited historical tracking compared to Spotify Wrapped.
Alternatives considered
Cloud Hosted
| Tool | Open Source | Free Tier | Monthly Cost |
|---|---|---|---|
| Last.fm | No | Yes | Free / From $3/mo |
| Stats.fm | No | Limited | Free / Plus varies |
Installation
Architecture
- Deployments:
client(React web UI) andserver(Node.js API) - Images:
yooooomi/your_spotify_client:1.19.0,yooooomi/your_spotify_server:1.19.0,mongo:6.0.27-jammy(all digest-pinned) - Database: MongoDB StatefulSet with Longhorn-encrypted PVC (
mongodb-data-mongodb-0-longhorn) - Networking: Separate services for client (port 80) and server; HTTPRoute via internal gateway
Security
- Runs as
runAsUser: 0,runAsNonRoot: false - MongoDB Longhorn PVC encrypted at rest via SOPS-managed keys
Updates
Managed by Renovate. All images are digest-pinned.
Data Management
- Database: MongoDB StatefulSet (
mongodb-data-mongodb-0-longhorn, Longhorn-encrypted) - Backups: k8up
Schedulebacks up MongoDB Longhorn PVC to Hetzner S3. MongoDB annotated withk8up.io/backupcommand: mongodump.
User Management
No OIDC. Authentication uses Spotify OAuth — users log in with their Spotify account. No internal user management.
Configuration Management
- Spotify API credentials (
SPOTIFY_PUBLIC,SPOTIFY_SECRET) from SOPS-encrypted secret - MongoDB endpoint, API and client URLs from SOPS-encrypted secret
Administration
Usage
Log in with your Spotify account to authorize data collection. The server continuously receives listening events from Spotify. Browse the web UI to view your top artists, albums, tracks, and listening patterns over time. Historical data accumulates as long as the service runs.
Cluster-specific deviations from the above live in the per-cluster README — see k8s/apps/talos/spotify/README.md.
Cluster Deployment
Your Spotify — Talos cluster
Cluster-specific notes only. General product info, "why we use it", and alternatives live in docusaurus/docs/apps/spotify.mdx.
Deviations from defaults
Defaults live in docusaurus/docs/apps/spotify.mdx — document anything this cluster does differently here, with a one-line reason.
- Image:
mongo:6.0.28-jammy@sha256:a90cef0143bed76540c2b7e6f299a02165e59b07e459b2fd7fef031c5accf5fd - Image:
yooooomi/your_spotify_client:1.20.0@sha256:e4da90a0634c7862f9f4e893026ee8cd91380234fa2125b88b26c6fb9da3d47e - Image:
yooooomi/your_spotify_server:1.20.0@sha256:624ea009f2ef9d877989bee9c7913ac66840449f566517871696c31a8ea13ddf
Rendered manifests (kustomize build)
apiVersion: apps/v1
kind: Deployment
metadata:
annotations:
kustomize.toolkit.fluxcd.io/force: enabled
labels:
app: client
name: client
namespace: spotify
spec:
replicas: 1
selector:
matchLabels:
app: client
homepage: active
ingress: internal
strategy:
type: Recreate
template:
metadata:
labels:
app: client
homepage: active
ingress: internal
spec:
containers:
- env:
- name: LOG_LEVEL
value: debug
- name: API_ENDPOINT
value: https://spotify-server.int.kueber.eu
image: yooooomi/your_spotify_client:1.20.0@sha256:e4da90a0634c7862f9f4e893026ee8cd91380234fa2125b88b26c6fb9da3d47e
name: client
ports:
- containerPort: 3000
name: web
protocol: TCP
---
apiVersion: apps/v1
kind: Deployment
metadata:
annotations:
kustomize.toolkit.fluxcd.io/force: enabled
labels:
app: server
name: server
namespace: spotify
spec:
replicas: 1
selector:
matchLabels:
app: server
homepage: active
ingress: internal
strategy:
type: Recreate
template:
metadata:
labels:
app: server
homepage: active
ingress: internal
spec:
containers:
- env:
- name: NODE_ENV
value: production
- name: API_ENDPOINT
value: https://spotify-server.int.kueber.eu
- name: CLIENT_ENDPOINT
value: https://spotify.int.kueber.eu
- name: MONGO_ENDPOINT
valueFrom:
secretKeyRef:
key: MONGO_ENDPOINT
name: spotify
- name: SPOTIFY_PUBLIC
valueFrom:
secretKeyRef:
key: SPOTIFY_PUBLIC
name: spotify
- name: SPOTIFY_SECRET
valueFrom:
secretKeyRef:
key: SPOTIFY_SECRET
name: spotify
image: yooooomi/your_spotify_server:1.20.0@sha256:624ea009f2ef9d877989bee9c7913ac66840449f566517871696c31a8ea13ddf
name: server
ports:
- containerPort: 8080
name: web
protocol: TCP
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: mongodb
namespace: spotify
spec:
replicas: 1
selector:
matchLabels:
app: mongodb
template:
metadata:
annotations:
k8up.io/backupcommand: >-
sh -c 'mongodump --username="$MONGO_INITDB_ROOT_USERNAME" --password="$MONGO_INITDB_ROOT_PASSWORD"
--authenticationDatabase=admin --archive --gzip' > spotify.archive.gz
k8up.io/file-extension: .gz
labels:
app: mongodb
namespace: default
spec:
containers:
- args:
- '--auth'
env:
- name: MONGO_INITDB_ROOT_USERNAME
valueFrom:
secretKeyRef:
key: MONGO_USERNAME
name: spotify
- name: MONGO_INITDB_ROOT_PASSWORD
valueFrom:
secretKeyRef:
key: MONGO_PASSWORD
name: spotify
image: mongo:6.0.28-jammy@sha256:a90cef0143bed76540c2b7e6f299a02165e59b07e459b2fd7fef031c5accf5fd
name: mongodb
ports:
- containerPort: 27012
volumeMounts:
- mountPath: /data/db
name: mongodb-data
volumeClaimTemplates:
- metadata:
name: mongodb-data
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
storageClassName: longhorn-encrypted