Sign inSign up

sandeepsb/cedarwing

By sandeepsb

•Updated 2 months ago

Self-hosted Xtream Codes IPTV proxy & panel for TiViMate, Smarters and Kodi

Image
Integration & delivery
1

3.8K

sandeepsb/cedarwing repository overview

⁠Cedarwing

A self-hosted Xtream Codes proxy and control panel — in a single container.

Point Cedarwing at your existing Xtream or M3U lines and it becomes one tidy dashboard: hand out a separate login to every device, watch what's playing live, route any provider through WireGuard, and browse a full TV guide in the browser. No panel sprawl, no per-app credentials to juggle.

  • One panel, every device — issue per-device logins (TiViMate, IPTV Smarters, any Xtream player) and revoke them individually.
  • Bring your own sources — Xtream Codes and raw M3U, validated before they're saved, deduped into clean playlists.
  • WireGuard egress — send some or all of a playlist's traffic through a tunnel, per category (live / VOD / series / catch-up).
  • Built-in guide & player — scrubbable EPG, catch-up, and in-browser playback with on-the-fly remuxing.
  • Live view & stats — see who's watching in real time, with history and per-channel analytics.
  • Typed REST API — every action in the UI is scriptable; browse it at /api/docs.

Full Rust, one small image, Postgres for storage.


⁠Quick start

Save this as docker-compose.yml, set a master key, and bring it up:

services:
  db:
    image: postgres:17-alpine
    environment:
      POSTGRES_USER: cedarwing
      POSTGRES_PASSWORD: cedarwing
      POSTGRES_DB: cedarwing
    volumes:
      - cedarwing-db:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U cedarwing"]
      interval: 5s
      timeout: 5s
      retries: 10

  app:
    image: sandeepsb/cedarwing:latest
    depends_on:
      db:
        condition: service_healthy
    environment:
      CW_DATABASE_URL: postgres://cedarwing:cedarwing@db:5432/cedarwing
      CW_BIND_ADDR: 0.0.0.0:8080
      # Public URL for M3U / stream links. Leave unset behind a reverse proxy —
      # it's derived from the incoming request automatically.
      CW_PUBLIC_URL: ${CW_PUBLIC_URL:-http://localhost:8080}
      # Encrypts stored provider credentials. Generate once, then keep it safe:
      #   openssl rand -base64 32
      CW_MASTER_KEY: ${CW_MASTER_KEY:?set CW_MASTER_KEY in your environment or .env}
    ports:
      - "8080:8080"

volumes:
  cedarwing-db:
export CW_MASTER_KEY=$(openssl rand -base64 32)
docker compose up -d

Open http://localhost:8080⁠, create your admin account, and add your first source. Database migrations run automatically on start — there's no separate migrate step.


⁠Configuration

VariableRequiredNotes
CW_DATABASE_URLyesPostgres connection string. Any reachable Postgres works.
CW_MASTER_KEYyes32-byte base64 (openssl rand -base64 32). Encrypts stored secrets — losing or rotating it makes existing encrypted data unreadable, so treat it as a key, not a password.
CW_PUBLIC_URLnoCanonical URL for stream / M3U links. Unset ⇒ derived per-request from Host / X-Forwarded-*, which is what makes a bare reverse-proxy setup work with zero config.
CW_BIND_ADDRnoDefault 0.0.0.0:8080.
CW_LOGnoTracing filter, e.g. info,cw_api=debug.
CW_OMDB_KEYnoOMDb API key (omdbapi.com⁠, free tier) to show IMDb / Rotten Tomatoes ratings for what's playing. Ratings are hidden when unset.

Behind nginx, Caddy or Cloudflare Tunnel, just proxy to port 8080 and leave CW_PUBLIC_URL unset.


⁠Tags

  • latest — the newest released build.
  • vX.Y.Z — immutable, per-release tags (e.g. v1.0.1). Pin one of these in production so a redeploy can't surprise you.

Both linux/amd64 and linux/arm64 are published under every tag.


Tag summary

Content type

Image

Digest

sha256:1baaf3eb3…

Size

200.3 MB

Last updated

2 months ago

docker pull sandeepsb/cedarwing