YotoShelf
Self-Host

Quick Start

Run YotoShelf from the registry image in under five minutes.

Pull and run

The simplest way to start is a single docker run command. Replace the placeholder secrets with random strings of at least 32 characters each.

docker run -d \
  --name yotoshelf \
  -p 8080:8080 \
  -v yotoshelf-db:/data \
  -e YOTOSHELF_DB_PATH=/data/yotoshelf.db \
  -e YOTOSHELF_LIBRARY_PATH=/data/library \
  -e YOTOSHELF_SESSION_SECRET=<random-32-bytes> \
  -e YOTOSHELF_ENCRYPTION_KEY=<random-32-bytes> \
  registry.gitlab.com/yotoshelf/yotoshelf:latest

Then open http://localhost:8080 and create your first admin account.

Required environment variables

The following variables have no defaults and must be set before the server will start in production:

VariablePurpose
YOTOSHELF_SESSION_SECRET Signs session cookies. At least 32 bytes. Rotate to invalidate all sessions.
YOTOSHELF_ENCRYPTION_KEY Encrypts Yoto OAuth tokens at rest. At least 32 bytes. Changing this invalidates stored tokens.

See Configuration for the full variable reference, including database path, library path, SMTP, OIDC, and observability settings.

Volumes and data

YotoShelf writes two kinds of data:

  • Database — a single SQLite file at YOTOSHELF_DB_PATH (default: yotoshelf.db in the working directory). Back this up regularly.
  • Library — audio files, cover images, and generated assets at YOTOSHELF_LIBRARY_PATH (default: library/). Can be large; put it on the storage you intend to keep.

Both paths should be on a persistent volume. A single volume mount works fine — set both variables to paths inside it.

Creating an admin user

If local auth is enabled (the default), the server exposes a create-admin subcommand. Run it once before first login:

docker exec yotoshelf /yotoshelf create-admin \
  --email admin@example.com \
  --password <password> \
  --db-path /data/yotoshelf.db

Alternatively, configure OIDC and set YOTOSHELF_LOCAL_AUTH_ENABLED=false; the first OIDC user to log in is automatically promoted to admin. See Configuration.

Reverse proxy

YotoShelf listens on :8080 (configurable via YOTOSHELF_LISTEN_ADDR). Place it behind a reverse proxy (Caddy, nginx, Traefik) and terminate TLS there. Set YOTOSHELF_TRUST_PROXY=true so audit logs record real client IPs from X-Forwarded-For.

Set YOTOSHELF_PUBLIC_URL to the externally visible URL (e.g. https://yotoshelf.example.com) so OAuth callbacks and share links use the correct base.

Verify the server is up

curl http://localhost:8080/healthz   # → 200 OK
curl http://localhost:8080/readyz    # → 200 OK (checks DB + OIDC + SMTP)