A lean E2EE messenger built in Go with embedded frontend, WebSocket real-time chat, and SQLite storage.
- Single self-contained binary (frontend embedded)
- End 2 End Encryption
- WebSocket messaging
- SQLite DB
- File uploads with configurable limit
- PWA frontend (RTL/Farsi ready)
- Push Notification for new messages
- Backend: Go (Gin), WebSocket hub, JWT auth
- DB: SQLite file
- Storage: Local uploads
- Frontend: Vuejs PWA served by the binary
Requirements: Debian/Ubuntu (systemd), curl, python3, tar, unzip, systemd.
Supported release targets: linux-amd64, linux-arm64.
curl -fsSL https://raw.githubusercontent.com/4xmen/payambar/main/install.sh | sudo bash -s -- --installUpgrade to the latest release:
curl -fsSL https://raw.githubusercontent.com/4xmen/payambar/main/install.sh | sudo bash -s -- --update--install creates everything from scratch:
- Fetches the latest release asset from GitHub and installs the
payambarbinary to/opt/payambar. - Seeds an empty SQLite DB file, installs a systemd unit, enables the service, and starts/restarts it.
- Default port:
8080. ChangePORTorJWT_SECRETin/opt/payambar/.envthensudo systemctl restart payambar.
--update only replaces the binary and restarts the service:
Common commands:
sudo systemctl status payambar
sudo journalctl -u payambar -fmkdir payambar && cd payambar
curl -O https://raw.githubusercontent.com/4xmen/payambar/main/docker-compose.yml
cat > .env <<'EOF'
JWT_SECRET=change-me
# Optional:
# CORS_ORIGINS=https://yourdomain.com
# STUN_SERVERS=stun:stun.l.google.com:19302
EOF
docker-compose up -dOpen http://<server-ip>:8080.
Prereqs: Go 1.25+, Make, SQLite dev headers.
make build-all # builds frontend + backend → bin/payambar
PORT=8080 DATABASE_PATH=./data/payambar.db JWT_SECRET=dev-key ./bin/payambarEnvironment variables (used by the binary and the installer-generated env file):
| Variable | Default | Purpose |
|---|---|---|
PORT |
8080 | HTTP/WebSocket port |
ENVIRONMENT |
production | production or development |
DATABASE_PATH |
/var/lib/payambar/payambar.db (installer) | SQLite file path |
FILE_STORAGE_PATH |
/var/lib/payambar/uploads | Upload directory |
JWT_SECRET |
(randomly generated by installer) | Sign/verify JWT tokens |
CORS_ORIGINS |
* | Allowed origins |
MAX_UPLOAD_SIZE |
10485760 | Max upload bytes (10MB) |
STUN_SERVERS |
stun:stun.l.google.com:19302 | WebRTC STUN list |
TURN_ENABLED |
false | Enable embedded TURN server in the Payambar binary |
TURN_REALM |
payambar.local | TURN realm |
TURN_EXTERNAL_IP |
(empty) | Public IP advertised in relay candidates |
TURN_ADVERTISED_HOST |
(empty) | Host/IP used for generated turn: URL in WebRTC config |
TURN_LISTEN_ADDRESS |
0.0.0.0 | TURN listen address |
TURN_LISTEN_PORT |
3478 | TURN listen port (TCP and UDP) |
TURN_RELAY_ADDRESS |
0.0.0.0 | Local bind address for relay allocations |
TURN_RELAY_MIN_PORT |
49152 | Relay UDP port range start |
TURN_RELAY_MAX_PORT |
49252 | Relay UDP port range end |
TURN_SERVER, TURN_USERNAME, TURN_PASSWORD |
(empty) | TURN URL and credentials used by clients; URL auto-generated when TURN is enabled and TURN_SERVER is empty |
VAPID_PUBLIC_KEY |
(generated by installer) | Web Push VAPID public key |
VAPID_PRIVATE_KEY |
(generated by installer) | Web Push VAPID private key |
PAYAMBAR_ENV_FILE |
(empty) | Optional explicit env-file path for CLI/server startup |
The binary supports operational CLI commands in addition to running the server:
payambar # start HTTP/WebSocket server
payambar status # print app/database/storage statistics
payambar status --json # same stats as JSONsudo systemctl status payambar
sudo systemctl restart payambar
sudo journalctl -u payambar -f- App listens on
PORT(default 8080). Expose/forward this port. - Embedded TURN listens on 3478 TCP/UDP and uses UDP relay range 49152-49252 by default.
make devbuilds frontend and runs backend with local SQLite at./data/payambar.db.- Tests:
make test - Format:
make fmt
Payambar supports text-message E2EE v1 (files/calls are not part of E2EE).
See docs/e2ee-text-v1.md for the proposed text-only E2EE v1 protocol and rollout plan.
- Per-device ECDH P-256 keypair generated in browser.
- Private key is optionally backed up to server encrypted with AES-GCM using a PBKDF2-SHA256 key derived from the login password (150k iterations). Password/derived key are never stored.
- Public key is published via
POST /api/keys/devices; the owner can restore viaGET /api/keys/devices/self. - Send flow: if recipient key exists → encrypt; if missing → warn once and send plaintext so messages stay readable (backward compatible).
Payambar supports Web Push notifications for new messages when the user is offline.
- The installer auto-generates VAPID keys. For manual setup, generate keys and add to your env file:
# Generate with openssl: openssl ecparam -genkey -name prime256v1 -noout -out vapid_private.pem # Then extract keys (or use an online VAPID key generator)
- Users toggle push notifications on/off in their profile modal.
- Push only works on HTTPS or
localhost. make devincludes test VAPID keys for local development.
- Service not up:
sudo journalctl -u payambar -n 50 - DB locked: SQLite allows one writer; retry or migrate to Postgres for scale.
- WebSocket blocked: Ensure port 8080 open and CDN/proxy allows WebSockets.
GNU V3 License