Skip to main content
This walkthrough assumes you have Docker installed plus API keys for at least one TTS/STT provider (Deepgram or ElevenLabs) and optional LiveKit credentials.
Prefer a managed LiveKit instance? Point LIVEKIT_URL at the internal signaling address and LIVEKIT_PUBLIC_URL at the client-facing domain.
1

Clone and prep configuration

git clone https://github.com/your-org/sayna.git
cd sayna
cp .env.example .env
You can keep using .env, but for local development it’s often clearer to generate a config file and pass it to Sayna:
server:
  host: "0.0.0.0"      # ENV: HOST
  port: 3001           # ENV: PORT

livekit:
  url: "ws://localhost:7880"              # ENV: LIVEKIT_URL
  public_url: "http://localhost:7880"     # ENV: LIVEKIT_PUBLIC_URL
  api_key: "devkey"                       # ENV: LIVEKIT_API_KEY
  api_secret: "secret"                    # ENV: LIVEKIT_API_SECRET

providers:
  deepgram_api_key: "your-deepgram-api-key"       # ENV: DEEPGRAM_API_KEY
  elevenlabs_api_key: "your-elevenlabs-api-key"   # ENV: ELEVENLABS_API_KEY
2

Start LiveKit + Redis

LiveKit needs Redis for state. Run both with Docker Compose:
services:
  redis:
    restart: always
    image: redis:alpine

  livekit:
    image: livekit/livekit-server:v1.9.1
    command: --dev --bind=0.0.0.0
    restart: always
    environment:
      LIVEKIT_CONFIG: |
        port: 7880
        log_level: info
        rtc:
          tcp_port: 7881
          port_range_start: 50000
          port_range_end: 60000
        redis:
          address: redis:6379
    ports:
      - "7880:7880"
      - "7881:7881"
Keep this stack running so Sayna can reach LiveKit on the internal network (ws://localhost:7880 or ws://livekit:7880 if you use the Docker Compose file).
3

Run Sayna locally

If you created config.yaml, run:
cargo run -- -c config.yaml
or simply cargo run when environment variables are already loaded (e.g., via .env).Prefer Docker? Add a Sayna service to the same Compose file so it shares the network with LiveKit:
services:
  sayna:
    build: .
    depends_on:
      - livekit
    environment:
      HOST: 0.0.0.0
      PORT: 3001
      LIVEKIT_URL: ws://livekit:7880
      LIVEKIT_PUBLIC_URL: http://localhost:7880
      LIVEKIT_API_KEY: devkey
      LIVEKIT_API_SECRET: secret
      DEEPGRAM_API_KEY: your-deepgram-api-key
      ELEVENLABS_API_KEY: your-elevenlabs-api-key
    ports:
      - "3001:3001"
Whether you use config files or env vars, make sure the Sayna container can resolve the LiveKit hostname (livekit) and expose port 3001 to your host machine.
4

Smoke test

curl http://localhost:3001/
curl http://localhost:3001/voices
Then connect a WebSocket client, send a config message, and queue a speak payload to hear a synthesized clip. Use /livekit/token to mint attendee tokens if you mirror audio into LiveKit.

Next steps

Review the architecture

Understand the moving parts before you customize providers or pipelines.

Call every REST endpoint

Learn what /voices, /speak, and /livekit/token expect.

Stream over WebSockets

Explore the message schemas for low-latency experiences.

Harden authentication

Pick between API secrets and delegated JWT validation.