Run your own Lag voice communication space. Single container, zero external dependencies - PostgreSQL, voice server, API, and web UI all bundled in one image.
The voice server will be using live kit. We are planning on releasing the voice system we have built. We have yet to finalise all its functionality and we will be releasing this when it is feature complete.
Pick the script that matches your container runtime:
| Runtime | Script |
|---|---|
| Podman | scripts/podman.sh |
| Docker | scripts/docker.sh |
| nerdctl (containerd) | scripts/nerdctl.sh |
All three scripts are identical in usage — just swap the filename. The examples below use <runtime> as a placeholder. Replace it with podman, docker, or nerdctl.
./scripts/<runtime>.sh upOpen http://localhost:3000 - enter a nickname and start talking.
git clone https://github.com/lag-app/self-host.git
cd self-host
./scripts/<runtime>.sh buildThis builds the image locally and starts it.
podman compose up -d
# or
docker compose up -d| Command | Description |
|---|---|
up |
Pull image and start container (default if no command given) |
down |
Stop and remove container (data volume kept) |
restart |
Stop then start |
build |
Build image from source and start |
logs |
Tail container logs |
status |
Show container status and ports |
shell |
Open a bash shell inside the container |
backup [file] |
Dump PostgreSQL to a SQL file (defaults to backup-YYYYMMDD-HHMMSS.sql) |
restore <file> |
Restore database from a SQL dump |
nuke |
Remove container and data volume — destroys all data |
# Start
./scripts/<runtime>.sh up
# Check if it's running
./scripts/<runtime>.sh status
# View logs
./scripts/<runtime>.sh logs
# Back up your database
./scripts/<runtime>.sh backup my-backup.sql
# Restore from backup
./scripts/<runtime>.sh restore my-backup.sql
# Drop into the container
./scripts/<runtime>.sh shell
# Stop without losing data
./scripts/<runtime>.sh down
# Start it back up
./scripts/<runtime>.sh up
# Wipe everything and start fresh
./scripts/<runtime>.sh nuke
./scripts/<runtime>.sh upOverride the image or container name with environment variables:
LAG_IMAGE=lag LAG_NAME=my-lag ./scripts/<runtime>.sh up| Variable | Default | Description |
|---|---|---|
LAG_IMAGE |
ghcr.io/lag-app/self-host:latest |
Container image to use |
LAG_NAME |
lag |
Container name |
| Port | Protocol | Purpose |
|---|---|---|
| 3000 | TCP | Web UI |
| 7880 | TCP | Voice signaling (HTTP) |
| 7881 | TCP | Voice signaling (TCP) |
| 50000-50200 | UDP | Voice media (RTC) |
Pass these to configure your instance:
SESSION_SECRET=your-secret-here \
EXTERNAL_IP=203.0.113.10 \
LAG_VOICE_KEY=mykey \
LAG_VOICE_SECRET=mysecret \
./scripts/<runtime>.sh up| Variable | Default | Description |
|---|---|---|
SESSION_SECRET |
Auto-generated | Secret for signing session tokens. Set this to persist sessions across container restarts. |
EXTERNAL_IP |
Auto-detected | Public IP for voice connections. Set this if auto-detection fails or you're behind NAT. |
LAG_VOICE_KEY |
devkey |
Voice server API key. Change in production. |
LAG_VOICE_SECRET |
secret |
Voice server API secret. Change in production. |
PostgreSQL data is stored in the lag_data volume. Your rooms, messages, and user sessions persist across container restarts.
# Backup
./scripts/<runtime>.sh backup
# Restore
./scripts/<runtime>.sh restore backup-20260319-143000.sqlFor voice to work when accessed from other machines, ensure the following ports are open:
- TCP 3000 - Web UI
- TCP 7880-7881 - Voice signaling
- UDP 50000-50200 - Voice media
Voice not connecting?
- Set
EXTERNAL_IPto your server's public IP - Ensure UDP ports 50000-50200 are open and forwarded
- Check logs:
./scripts/<runtime>.sh logs
Container won't start?
- Check if ports are already in use:
ss -tlnp | grep -E '3000|7880' - Check status:
./scripts/<runtime>.sh status
Reset everything:
./scripts/<runtime>.sh nuke
./scripts/<runtime>.sh up