Test any open PR against thelounge/thelounge on a real server.
Live at preview.thelounge.chat
- Dashboard showing all open PRs with one-click deploy
- Each PR gets its own TheLounge instance at
pr-{N}.preview.thelounge.chat - Instances connect to a shared private Ergo IRC server
- Choose public mode (no login) or private mode (add test users from the dashboard)
- Instances auto-shutdown after 6 hours (configurable via
INSTANCE_TTL) - Auto-deploys on push to
mainvia GitHub Actions
Internet → nginx (TLS) → Go app (:8080) → Dashboard UI
→ Reverse proxy to TL containers
→ Ergo IRC (Docker network)
- Go binary — dashboard, API, reverse proxy, GitHub OAuth
- nginx — TLS termination with wildcard cert (via Porkbun DNS challenge)
- Ergo — private IRC server in Docker
- TL instances — each PR runs in its own Docker container, built from source
- Base image cache — pre-built
tl-preview-basewith node_modules, refreshed every 24h
Zero external Go dependencies.
Sign in with GitHub. Access is granted if you are:
- A member of the thelounge GitHub org, OR
- Have at least one merged PR to thelounge/thelounge, OR
- Listed in the
ALLOWED_USERSenv var
- Ubuntu 24.04 droplet (2GB RAM / $12/mo recommended)
- Domain with DNS records:
A preview.thelounge.chat → <droplet IP>A *.preview.thelounge.chat → <droplet IP>
- A GitHub OAuth App:
- Homepage URL:
https://preview.thelounge.chat - Callback URL:
https://preview.thelounge.chat/auth/callback
- Homepage URL:
- A Porkbun API key (for wildcard TLS cert via DNS challenge)
# Copy to server
scp -r preview-service/ root@<IP>:/opt/preview-service/
# SSH in and set credentials
ssh root@<IP>
export PREVIEW_GITHUB_CLIENT_ID=...
export PREVIEW_GITHUB_CLIENT_SECRET=...
export PORKBUN_API_KEY=...
export PORKBUN_SECRET_KEY=...
bash /opt/preview-service/setup.shThe setup script installs Docker, Go, configures nginx with a wildcard TLS cert (via Porkbun DNS), starts Ergo, and creates a systemd service.
Pushes to main auto-deploy via GitHub Actions. Required repo secret:
| Secret | Description |
|---|---|
SSH_PRIVATE_KEY |
SSH private key with root access to the droplet |
Generate a deploy key: ssh-keygen -t ed25519 -f deploy_key -N "", add deploy_key.pub to the server's ~/.ssh/authorized_keys, and set deploy_key as the SSH_PRIVATE_KEY repo secret.
The server also needs to be a git repo — run once on the server:
cd /opt/preview-service && git init && git remote add origin <repo-url>| Variable | Required | Default | Description |
|---|---|---|---|
GITHUB_CLIENT_ID |
Yes | — | GitHub OAuth App client ID |
GITHUB_CLIENT_SECRET |
Yes | — | GitHub OAuth App client secret |
DOMAIN |
No | preview.thelounge.chat |
Base domain |
GITHUB_REPO |
No | thelounge/thelounge |
Repo to list PRs from |
GITHUB_ORG |
No | thelounge |
GitHub org for membership checks |
GITHUB_TOKEN |
No | — | Token for higher API rate limits |
ALLOWED_USERS |
No | — | Comma-separated GitHub usernames always allowed |
LISTEN_ADDR |
No | :8080 |
Address the Go server listens on |
DATA_DIR |
No | /opt/preview/data |
Persistent data directory |
BUILD_DIR |
No | /opt/preview/builds |
Temporary build directory |
ERGO_HOST |
No | ergo |
Ergo IRC server address (Docker hostname) |
INSTANCE_TTL |
No | 6h |
Auto-teardown instances after this duration |
# Start Ergo
docker compose up -d
# Run locally (needs Docker for TL instances)
export GITHUB_CLIENT_ID=...
export GITHUB_CLIENT_SECRET=...
export DOMAIN=localhost:8080
export DATA_DIR=./data
export BUILD_DIR=./builds
export ERGO_HOST=ergo
go run .# Check status
systemctl status preview-service
systemctl status nginx
docker ps # Ergo + TL instances
# View logs
journalctl -u preview-service -f
# Manual deploy
cd /opt/preview-service && git pull && go build -o /usr/local/bin/preview-service . && systemctl restart preview-service