Pulse Chat
A self-hosted chat platform built for privacy, voice, and connecting communities.
plse.chat ·
Self-Hosting Guide ·
Releases
---
> [!NOTE]
> Pulse Chat is in alpha (v0.1.3). Expect bugs and breaking changes between updates.
## Why Pulse?
Pulse is a self-hosted alternative to Discord and Slack that puts you in control. Every message can be end-to-end encrypted, voice and video stay on your infrastructure, and federation lets separate instances talk to each other — no central service required.
## What's included
| | |
|---|---|
| **Encrypted messaging** | Signal Protocol (X3DH + Double Ratchet) for DMs and channels |
| **Voice & video** | WebRTC-powered calls with screen sharing via Mediasoup |
| **Federation** | Link multiple Pulse instances so users can discover and join across servers |
| **Forum channels** | Threaded discussions with tags for long-form topics |
| **Channels & DMs** | Real-time text with file uploads, reactions, threads, and mentions |
| **Roles & permissions** | Granular access control at the server, channel, and user level |
| **Custom emojis** | Upload and manage emojis per server |
| **Automod** | Keyword filters, regex rules, mention limits, and link blocking |
| **Webhooks** | Push events to external services |
| **OAuth login** | Google, Discord, Facebook, Twitch — toggle each on or off |
| **Invite-only mode** | Lock down registration so only invited users can join |
## Getting started
Pulse needs a Supabase backend (auth + database). You can use [Supabase Cloud](https://supabase.com) or self-host everything together — see the [Self-Hosted Guide](README-SELFHOSTED-SUPABASE.md) for the full Docker Compose setup with PostgreSQL, GoTrue, and Kong.
### Docker
```bash
docker run \
-p 4991:4991/tcp \
-p 40000-40020:40000-40020/tcp \
-p 40000-40020:40000-40020/udp \
-v ./data:/root/.config/pulse \
--name pulse \
ghcr.io/plsechat/pulse-chat:latest
```
For production with Supabase bundled, use [docker-compose-supabase.yml](docker-compose-supabase.yml) from the [Self-Hosted Guide](README-SELFHOSTED-SUPABASE.md).
### Linux binary
```bash
curl -L https://github.com/plsechat/pulse-chat/releases/latest/download/pulse-linux-x64 -o pulse
chmod +x pulse
./pulse
```
### After first launch
1. Open `http://localhost:4991`
2. A **security token** prints to the server console on first run — save it
3. Register and log in
4. Claim ownership: open the browser console and run `useToken('your_token_here')`
## Configuration
A config file is generated at `~/.config/pulse/config.ini` on first run.
| Section | Key | Default | What it does |
|---|---|---|---|
| server | `port` | `4991` | HTTP / WebSocket port |
| server | `debug` | `false` | Verbose logging |
| server | `autoupdate` | `false` | Auto-check for updates |
| http | `maxFiles` | `40` | Max files per upload |
| http | `maxFileSize` | `100` | Max file size (MB) |
| mediasoup | `worker.rtcMinPort` | `40000` | WebRTC port range start |
| mediasoup | `worker.rtcMaxPort` | `40020` | WebRTC port range end |
| mediasoup | `video.initialAvailableOutgoingBitrate` | `6000000` | Bandwidth per stream (bps) |
| federation | `enabled` | `false` | Turn on federation |
| federation | `domain` | — | Your public domain (required for federation) |
> [!IMPORTANT]
> The port range `rtcMinPort`–`rtcMaxPort` controls how many concurrent voice/video connections are possible. Each connection uses one UDP port. Open these ports (TCP + UDP) in your firewall, and map the range in Docker if applicable.
## HTTPS
Pulse doesn't terminate TLS. Put a reverse proxy in front — Caddy, Nginx, or Traefik all work. The [Self-Hosted Guide](README-SELFHOSTED-SUPABASE.md#set-up-https) has example configs for Caddy and Nginx.
## Built with
[Bun](https://bun.sh) · [React](https://react.dev) · [tRPC](https://trpc.io) · [Drizzle ORM](https://orm.drizzle.team) · [Mediasoup](https://mediasoup.org) · [Tailwind CSS](https://tailwindcss.com) · [Supabase](https://supabase.com) · [Signal Protocol](https://signal.org/docs/)
## License
[AGPL-3.0](LICENSE)