|
|
||
|---|---|---|
| .github | ||
| apps | ||
| docker | ||
| packages | ||
| scripts | ||
| .dockerignore | ||
| .env.example | ||
| .env.supabase.example | ||
| .gitignore | ||
| CONTRIBUTING.md | ||
| Caddyfile | ||
| Dockerfile | ||
| LICENSE | ||
| README-CUSTOM.md | ||
| README-SELFHOSTED-SUPABASE.md | ||
| README.md | ||
| docker-compose-supabase.yml | ||
| docker-compose.noise.yml | ||
| docker-compose.override.yml | ||
| knip.json | ||
| package.json | ||
| start.sh | ||
| tsconfig.json | ||
README.md
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 or self-host everything together — see the Self-Hosted Guide for the full Docker Compose setup with PostgreSQL, GoTrue, and Kong.
Docker
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 from the Self-Hosted Guide.
Linux binary
curl -L https://github.com/plsechat/pulse-chat/releases/latest/download/pulse-linux-x64 -o pulse
chmod +x pulse
./pulse
After first launch
- Open
http://localhost:4991 - A security token prints to the server console on first run — save it
- Register and log in
- 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–rtcMaxPortcontrols 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 has example configs for Caddy and Nginx.
Built with
Bun · React · tRPC · Drizzle ORM · Mediasoup · Tailwind CSS · Supabase · Signal Protocol