No description
  • TypeScript 45.7%
  • Svelte 45.3%
  • JavaScript 4.2%
  • HTML 2.2%
  • CSS 1.4%
  • Other 1.2%
Find a file
2026-07-13 17:43:17 -07:00
.forgejo added index.hml update, new deploy releases 2026-07-12 10:39:29 -07:00
.vscode Initial commit 2026-02-17 13:10:09 -08:00
infra removed code, and updated readme, added MIT license 2026-07-09 11:17:50 -07:00
landing added index.hml update, new deploy releases 2026-07-12 10:39:29 -07:00
src added fix for noise cancelling 2026-07-13 17:43:18 -07:00
src-tauri chore: release 0.1.93 [skip ci] 2026-07-13 17:43:17 -07:00
static updated landing page 2026-02-18 16:05:49 -08:00
.gitignore removed code, and updated readme, added MIT license 2026-07-09 11:17:50 -07:00
.npmrc Initial commit 2026-02-17 13:10:09 -08:00
.prettierignore Initial commit 2026-02-17 13:10:09 -08:00
.prettierrc Initial commit 2026-02-17 13:10:09 -08:00
bun.lock added tests for messages, and cleaned up code 2026-07-12 11:53:57 -07:00
LICENSE removed code, and updated readme, added MIT license 2026-07-09 11:17:50 -07:00
package.json added tests for messages, and cleaned up code 2026-07-12 11:53:57 -07:00
README.md removed code, and updated readme, added MIT license 2026-07-09 11:17:50 -07:00
svelte.config.js removed space 2026-06-24 00:11:41 -07:00
tsconfig.json Initial commit 2026-02-17 13:10:09 -08:00
vite.config.ts test 2026-06-24 13:34:06 -07:00
vitest.config.ts added tests for messages, and cleaned up code 2026-07-12 11:53:57 -07:00

RyftBorn

A self-hosted, open-source Discord alternative. Own your community.

  • Voids — Text channels
  • Drifts — Voice/video channels with screen sharing
  • Tethers — Direct messages
  • Self-hosted — Your data, your server, your rules

Built with SvelteKit, PocketBase, LiveKit, and Tauri.

RyftBorn Discord Equivalent
Ryft Server
Void Text Channel
Drift Voice Channel
Tether DM

Server Installation

Prerequisites

  • A Linux server (VPS, dedicated, or local machine)
  • Docker or Podman with Compose
  • A domain name pointed at your server (for production with TLS)
  • Ports 80, 443, 7881, 3478/udp, 50000-50200/udp open in your firewall

The examples below use podman. Replace with docker if that's what you have.

Podman setup (Linux only)

Podman needs a compose provider and Docker Hub registry configured:

pip3 install podman-compose
echo 'unqualified-search-registries = ["docker.io"]' >> /etc/containers/registries.conf

Quick Start (Local / Development)

This starts the full stack — PocketBase, the WebSocket server, LiveKit, and Caddy (which also builds the frontend image, so the first start takes a few minutes).

git clone https://git.askdavis.com/AskDavis/RyftBorn.git
cd RyftBorn/infra

# Generate secrets and start containers
./setup.sh

setup.sh will:

  1. Prompt for a PocketBase admin email and password
  2. Generate a secret for LiveKit
  3. Write the .env file
  4. Start the containers
  5. Create the PocketBase superuser account
  6. Enable username login

Once complete, the services are available at:

Service URL
PocketBase http://localhost:8090
PB Admin UI http://localhost:8090/_/
WebSocket ws://localhost:7891
LiveKit ws://localhost:7880
Caddy https://localhost (landing) · https://app.localhost (app)

Run the frontend for development:

cd ..
bun install
bun run dev

Open http://localhost:5173 and register your first account. The first user automatically becomes the server owner.


Production Deployment

Production is the same stack pointed at a real domain: Caddy handles reverse proxying with automatic TLS, and LiveKit's embedded TURN server handles NAT traversal for voice/video. The frontend is built inside Docker — no Bun or Node needed on the server.

1. Clone and configure

git clone https://git.askdavis.com/AskDavis/RyftBorn.git
cd RyftBorn/infra

2. Run setup

./setup.sh

3. Set your domain

Edit infra/.env and set your domain (both variables — DOMAIN is used by LiveKit's TURN server, DOMAIN_FRONTEND is what Caddy serves):

DOMAIN=ryftborn.example.com
DOMAIN_FRONTEND=ryftborn.example.com

Optionally add a Klipy API key for GIF support:

VITE_KLIPY_API_KEY=your_key_here

4. Enable TURN and external IP for LiveKit

Still in infra/.env, enable NAT traversal for production:

USE_EXTERNAL_IP=true
TURN_ENABLED=true
LIVEKIT_NODE_IP=

LiveKit's config is generated inside docker-compose.yml from these env vars — you don't need to edit any LiveKit config file. Leave LIVEKIT_NODE_IP empty in production; use_external_ip handles IP discovery.

5. DNS setup

Point two DNS records at your server:

Type Name Value
A ryftborn.example.com Your server IP
A app.ryftborn.example.com Your server IP

The Caddyfile also contains a mail.{$DOMAIN} block that proxies to a Stalwart mail server container. If you don't run one, remove that block from infra/Caddyfile.

6. Build and start everything

podman compose build
podman compose up -d

This builds the SvelteKit frontend inside Docker and starts all services:

Service What it does
PocketBase Auth, database, file storage
WS Server Real-time chat, typing indicators, presence
LiveKit Voice/video channels, screen sharing, embedded TURN for NAT
Caddy Reverse proxy, automatic HTTPS certificates

Caddy automatically provisions TLS certificates once DNS resolves.

7. First-time app setup

  1. Open https://app.ryftborn.example.com
  2. Register the first account — you become the server owner
  3. The Setup Wizard walks you through naming your server, setting visibility, and creating your first channel
  4. Share the link with others so they can register and join

Architecture

Browser / Tauri App
    │
    ├── HTTPS ──► Caddy (reverse proxy)
    │               ├── /api/*, /_/*       ──► PocketBase (auth, data, files)
    │               ├── /ws                ──► WS Server  (real-time chat)
    │               ├── /token             ──► WS Server  (LiveKit tokens)
    │               ├── /preview           ──► WS Server  (link previews)
    │               ├── /password-reset/*  ──► WS Server  (password reset)
    │               ├── /rtc*              ──► LiveKit    (voice/video signaling)
    │               └── /*                 ──► SvelteKit  (frontend SPA)
    │
    └── UDP/TCP ──► LiveKit (WebRTC media on 50000-50200/udp + 7881/tcp,
                    embedded TURN on 3478/udp for NAT traversal)

In development (without Caddy), the app connects to each service directly via port:

  • PocketBase: http://localhost:8090
  • WebSocket: ws://localhost:7891
  • LiveKit: ws://localhost:7880

In production, everything goes through Caddy on a single domain with automatic TLS.


Firewall Ports

Port Protocol Service When needed
80 TCP Caddy (HTTP redirect) Production
443 TCP Caddy (HTTPS) Production
3478 UDP LiveKit embedded TURN Production
7881 TCP LiveKit RTC (TCP fallback) Production
50000-50200 UDP LiveKit RTC media Production
8090 TCP PocketBase Dev only
7891 TCP WebSocket server Dev only
7880 TCP LiveKit signaling Dev only

In production, only ports 80, 443, 7881, 3478/udp, and 50000-50200/udp need to be open. Caddy handles all HTTP(S) routing; WebRTC media flows directly to LiveKit.


Common Operations

# View logs
podman compose logs -f                # all services
podman compose logs -f pocketbase     # single service

# Restart
podman compose down && podman compose up -d

# Rebuild frontend after code changes
podman compose build caddy
podman compose up -d caddy

# PocketBase admin UI
#   Dev:  http://localhost:8090/_/
#   Prod: https://app.ryftborn.example.com/_/

# Back up data
cp -r infra/pocketbase/pb_data infra/pocketbase/pb_data.backup

# Reset everything (destroys all data)
podman compose down
rm -rf infra/pocketbase/pb_data
./setup.sh

Desktop App (Tauri)

The desktop app wraps the same SvelteKit frontend in a native window.

bun install
bun run tauri dev

When connecting from the desktop app, enter your server address (e.g. https://app.ryftborn.example.com) in the connection dialog. The app automatically derives WebSocket and LiveKit URLs from it.


Tech Stack

  • Frontend: SvelteKit + Svelte 5 + TypeScript + Tailwind v4
  • Desktop/Mobile: Tauri v2
  • Backend: PocketBase (auth, CRUD, files, embedded SQLite)
  • Real-time: Bun WebSocket server
  • Voice/Video: LiveKit Server
  • Reverse Proxy: Caddy (automatic TLS)
  • NAT Traversal: LiveKit embedded TURN
  • Icons: Lucide Svelte
  • Package Manager: Bun

Project Structure

src/              # SvelteKit frontend (Svelte 5 + TypeScript + Tailwind v4)
src-tauri/        # Tauri v2 native shell
infra/            # Server infrastructure
  docker-compose.yml    # All services (LiveKit config generated inline from env vars)
  Dockerfile.caddy      # Multi-stage build (frontend + Caddy)
  Caddyfile             # Reverse proxy config
  ws-server/            # Bun WebSocket server
  pocketbase/
    pb_migrations/      # Database schema
    pb_data/            # Database + file storage (created at runtime)
  setup.sh              # First-time setup script
  .env                  # Secrets (generated by setup.sh, not committed)
landing/          # Static landing page served at root domain

License

MIT — see LICENSE.