A self-hosted, open-source community platform built for privacy and control.
Note: The project is currently in beta. Breaking changes may occur before v1.0. Read What v1.0 Does and Doesn't Do before deploying — it spells out which features are real today (search, voice, federation) and which (E2EE, simulcast, FTS) are explicitly deferred.
Pufferblow is a self-hosted platform for building online communities — think of it as a privacy-respecting, open-source alternative to Discord or Guilded that you fully own and operate.
You host the server on your own machine or VPS. You control the data, the rules, and the people. No third-party company can read your messages, sell your data, or shut down your community.
Key properties:
- Self-hosted — runs on any Linux machine or VPS; no cloud dependency
- Encrypted at rest — messages are AES-encrypted in the database; passwords hashed with bcrypt. (Transport is TLS; end-to-end encryption is on the roadmap, not in v1.0 — see
V1_0_CAVEATS.md.) - Federated — instances can connect to each other via ActivityPub, so communities on separate servers can interact
- Role-based — a fine-grained privilege system lets you delegate moderation, file management, channel control, and more
- Voice-capable — integrated WebRTC voice channels through the companion
media-sfuservice - Extensible — a REST API and official Python SDK (
pypufferblow) let you build bots and integrations
Pufferblow is made up of four repositories that work together:
| Repository | Language | Role |
|---|---|---|
| pufferblow | Python / FastAPI | Control plane — REST API, auth, storage, federation |
| client | TypeScript / React / Electron | Desktop and web client |
| media-sfu | Go / Pion WebRTC | Media plane — WebRTC voice forwarding |
| pypufferblow | Python | Official SDK and bot framework |
- Python 3.10 or later
- PostgreSQL 14 or later
- A Linux or macOS host (Windows via WSL is supported for development)
Optional but recommended for voice channels:
- A running media-sfu instance
- A TURN server (e.g. coturn) for clients behind strict NAT
Pufferblow isn't on PyPI yet — install from the repository:
git clone https://github.com/PufferBlow/pufferblow.git
cd pufferblow
poetry installIf you'd rather not use Poetry:
pip install .A published PyPI release will land alongside the v1.0 tag. For
the most stable deploy path today, see
DOCKER_PRODUCTION.md — the Compose stack
boots the server, Postgres, memcached, and (optionally) media-sfu
in one command.
Run the interactive setup wizard. It creates ~/.pufferblow/config.toml and initialises the database:
pufferblow setupThe wizard will ask for:
- PostgreSQL connection details
- An admin account (username + password)
- Server name and description
pufferblow serveThe API will be available at http://0.0.0.0:7575 by default.
All runtime settings live in ~/.pufferblow/config.toml. The file is created by pufferblow setup and documented inline.
Key sections:
[server]
host = "0.0.0.0"
port = 7575
workers = 4
[database]
host = "localhost"
port = 5432
username = "pufferblow"
password = "change-me"
database = "pufferblow"
[security]
cors_origins = ["http://localhost:5173"]
cors_allow_credentials = true
[media-sfu]
bootstrap_secret = "change-this"
bootstrap_config_url = "http://localhost:7575/api/internal/v1/voice/bootstrap-config"
bind_addr = "0.0.0.0:8787"After any change, restart the server to apply it.
pufferblow version Print the installed version.
pufferblow setup Interactive first-time setup wizard.
pufferblow setup --update-server Update server name/description/welcome.
pufferblow setup --setup-media-sfu Rotate the [media-sfu] section of config.toml.
pufferblow setup --backup Configure scheduled database backups.
pufferblow serve Start the API server.
pufferblow serve --dev Run with uvicorn auto-reload (development only).
pufferblow migrate Apply pending schema changes (idempotent).
pufferblow migrate --check Report schema drift without applying (exits 1 on drift).
pufferblow doctor Read-only health check (DB, schema, storage, secrets, SFU).
pufferblow backup now Run pg_dump immediately.
pufferblow backup mirror Mirror the database to BACKUP_MIRROR_DSN immediately.
pufferblow storage setup Wizard for the storage backend (local FS vs S3).
pufferblow storage test Round-trip a small upload through the configured backend.
pufferblow storage migrate ... Move file objects between backends.
migrate is the database schema migration; storage migrate moves
uploaded files between backends. They're independent — see
ADMIN.md for the full operator guide.
The REST API is available at /api/v1/. Interactive documentation (Swagger UI) is served at /docs when the server is running.
| Endpoint | Description |
|---|---|
GET /healthz |
Control-plane health |
GET /readyz |
Readiness check |
GET /api/v1/system/instance-health |
Full health including media-sfu |
| Resource | Prefix |
|---|---|
| Users | /api/v1/users |
| Channels | /api/v1/channels |
| Messages | /api/v1/messages |
| Storage | /api/v1/storage |
| Roles & Privileges | /api/v1/system |
| Federation | /api/v1/federation |
| Voice | /api/v2/voice |
| Direct Messages | /api/v1/dms |
┌────────────────────────────────┐
│ Pufferblow API │
│ (FastAPI · Python control │
│ plane, port 7575) │
└──────────┬─────────────────────┘
│
┌────────────────┼────────────────┐
│ │ │
┌────────▼──────┐ ┌──────▼──────┐ ┌─────▼──────────┐
│ PostgreSQL │ │ media-sfu │ │ File Storage │
│ (state + │ │ (Go WebRTC │ │ (local or S3) │
│ messages) │ │ SFU :8787)│ │ │
└───────────────┘ └─────────────┘ └─────────────────┘
- Passwords are hashed with bcrypt before storage. Plain-text passwords are never persisted.
- Messages are AES-encrypted (with a PBKDF2-derived per-record key) before they are written to the database. This protects against database leaks — it is not end-to-end encryption; the server holds the keys.
- Auth tokens are JWT-based with configurable access (15 min default) and refresh (30 day default) lifetimes.
- Rate limiting is applied per IP before requests reach route handlers.
- CORS origins are explicitly allowlisted in
config.toml. - Internal API calls between Pufferblow and media-sfu are signed with HMAC-SHA256.
Every instance ships with four built-in roles: owner, admin, moderator, and user. Custom roles can be created from a catalogue of granular privileges:
create_channels · delete_channels · edit_channels · manage_channel_users · view_private_channels · send_messages · delete_messages · edit_messages · ban_users · mute_users · moderate_content · view_audit_logs · manage_storage · upload_files · delete_files · view_files · manage_server_settings · manage_server_privileges · view_server_stats · manage_background_tasks · manage_blocked_ips · view_users · edit_users · reset_user_tokens
Pufferblow implements a subset of ActivityPub so instances can talk to each other:
- Follow remote users (
user@other-instance.org) - Send and receive cross-instance direct messages
- Resolve remote actor profiles via WebFinger
Relevant endpoints: /.well-known/webfinger, /ap/users/{id}, /api/v1/federation/*
For operating a federated instance — TURN setup, latency expectations, debugging stuck deliveries — see FEDERATION.md.
| Doc | Purpose |
|---|---|
| V1_0_CAVEATS.md | What ships in v1.0 and what's deferred. |
| DOCKER_PRODUCTION.md | One-command Compose stack: services, ports, env vars. |
| ADMIN.md | CLI reference, secret rotation, storage, audit log, blocked IPs. |
| BACKUP.md | What to back up, how often, and how to restore on a fresh host. |
| FEDERATION.md | What federates, TURN setup, latency, debugging stuck deliveries. |
| SECURITY.md | Security model, threat boundaries, vulnerability reporting. |
Contributions are welcome. Please open an issue before starting work on a non-trivial change so we can discuss approach.
- Fork the repository
- Create a branch:
git checkout -b feature/your-feature - Commit your changes:
git commit -m "feat: describe the change" - Open a pull request against
main
|
ramsy0dev 💻 🚧 📖 |
Pufferblow is released under the GNU General Public License v3.0.