Skip to content

About

No description, website, or topics provided.

Resources

Stars

1 star

Watchers

0 watching

Forks

Latest commit

 

History

46 Commits

Folders and files

Repository files navigation

lavalink-ops

Self-hosted Lavalink audio node with YouTube anti-detection and web-based admin panel.

Components

Service Purpose Port
Lavalink Audio sending node (Discord) 2333
yt-cipher YouTube signature deciphering 8001
bgutil-pot PoToken generation (BotGuard) 4416
Admin Panel Config management + monitoring 8080

Quick Start

# One-click setup — generates all secrets, creates .env, prepares directories
./setup.sh

# Start the stack
docker compose up --build -d

Visit http://localhost:8080 and log in with the admin password printed by the setup script.

Manual Setup

If you prefer to configure manually:

cp .env.example .env
# Edit .env with your own passwords/tokens
# Then sync the lavalink password and cipher token into config/application.yml
docker compose up --build -d

YouTube Anti-Detection

Three independent mechanisms work together:

  1. OAuth — Authenticates as a real Google user (use a burner account!)
  2. PoToken — Proof-of-origin token from BotGuard attestation
  3. Remote Cipher — Offloads signature deciphering to yt-cipher

The admin panel manages the lifecycle of all three.

Architecture

See docs/DESIGN.md for the full architecture document.

Cloud Deployment

terraform/ has ready-to-go modules for deploying the stack to a single cloud VM. AWS, UpCloud, and Vultr are supported. Each module provisions a hardened instance with IPv6 enabled (useful for Lavalink's IP rotation) and prints an SSH-tunnel command for reaching the admin panel.

Health & Monitoring

The admin panel exposes JSON probes for external monitors (CloudWatch, Uptime Kuma, Pingdom, etc). These bypass the login cookie so a monitor can scrape them, but they only return service status — no credentials or config.

Endpoint Returns
GET /healthz Aggregate. 200 if Lavalink is up; 503 otherwise. Body lists per-service state.
GET /healthz/lavalink 200/503 for Lavalink only.
GET /healthz/cipher 200/503 for yt-cipher.
GET /healthz/pot 200/503 for bgutil-pot.

Example body:

{"status":"ok","services":{"lavalink":"ok","cipher":"ok","pot":"down"},"checked_at":"2026-04-23T02:30:00+00:00"}

cipher and pot are reported but advisory — they can flap without flipping the aggregate to 503, since Lavalink can serve non-YouTube sources without them. If you need either to gate alerts, scrape its dedicated endpoint.

The HTML dashboard at /health is unchanged and still requires login.

Public exposure: these endpoints leak that the stack exists and which services run. Fine for the SSH-tunnel default (loopback only). If you put admin behind a public reverse proxy, scope /healthz* to your monitor's IP at the proxy, otherwise you're broadcasting your topology.

Security Notes

  • Never expose the admin panel to the public internet without a reverse proxy + auth
  • The admin panel reaches Docker through tecnativa/docker-socket-proxy, configured with a custom haproxy.cfg (in config/dockerproxy/) that allowlists exactly five endpoint+method combinations: GET /_ping, GET /version, GET /containers/{name}/json, GET /containers/{id}/logs, and POST /containers/{id}/restart. Everything else (including containers.create, start, kill, exec, prune, and the entire images/volumes/networks/swarm surface) returns 403, so an admin RCE cannot pivot to host root via the Docker API.
  • OAuth uses burner Google accounts — never your primary
  • All secrets are auto-generated by setup.sh — no default passwords in production

License

MIT (see LICENSE)

About

No description, website, or topics provided.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages