Self-host in 10 minutes
One Docker stack, one PostgreSQL database, one reverse proxy. Chatalot is designed to be installed once and maintained for years — nothing exotic, nothing federated, nothing cloud-bound.
Prerequisites
- A Linux server with Docker and Docker Compose (any modern distro — Ubuntu 22.04+, Debian 12+, Alpine, etc.)
- A public domain name pointed at the server
- TLS (Let's Encrypt is typical; Caddy handles it automatically)
- 2 GB RAM minimum (recommended: 4 GB); 10 GB disk for the application, plus whatever you want for file uploads and message history
Quickstart
1. Clone the repository
git clone https://github.com/seglamater/chatalot.git
cd chatalot
2. Generate secrets
./scripts/generate-secrets.sh
./scripts/generate-keys.sh
These scripts create secrets/jwt_private.pem,
secrets/jwt_public.pem, a random DB_PASSWORD, and a
TOTP_ENCRYPTION_KEY. All files live in secrets/ and
should NEVER be committed to version control.
3. Configure .env
cp .env.example .env
$EDITOR .env
Set at minimum:
PUBLIC_URL— e.g.https://chat.example.comADMIN_USERNAME— the account that gets admin privileges on first loginREGISTRATION_MODE—invite_only(recommended),open, orclosed
4. Start the stack
docker compose up -d
PostgreSQL starts first; migrations apply automatically; the Chatalot server comes up next. After a minute, health check:
curl https://chat.example.com/health
# expect: {"status":"ok","version":"...","uptime_secs":N,"db_healthy":true}
5. Register the admin user
Navigate to your PUBLIC_URL and register. The first account matching
ADMIN_USERNAME gets admin privileges. Enable 2FA immediately
(Settings → Security → TOTP).
Voice and video (WebRTC)
Chatalot uses peer-to-peer WebRTC with a TURN server for NAT traversal. The
included coturn profile handles this:
docker compose --profile turn up -d
Set TURN_USER, TURN_PASSWORD, and
TURN_EXTERNAL_IP in .env. For production, consider
a dedicated TURN server with per-session ephemeral credentials (planned feature).
Backups
The PostgreSQL database contains all message ciphertext, user accounts, settings,
and per-user encrypted keys. Back it up. Uploaded files live in a bind-mounted
directory — back that up too. The secrets/ directory is
irreplaceable: without those keys, previously-encrypted TOTP secrets cannot be
decrypted. Archive it separately.
Updating
A managed update system (in development) will let clients apply vendor-pushed updates with one click, including signature verification and automatic rollback on failure. Until that ships, the update path is:
git pull
docker compose pull
docker compose up -d
Troubleshooting
The source repository has extensive admin-guide and self-hosting docs. Common issues:
- Health endpoint returns
degraded: database is unreachable. Check thechatalot-dbcontainer logs. - WebSocket disconnects frequently: your reverse proxy may need
WebSocket upgrade headers. Caddy handles these automatically; nginx needs
explicit
Upgrade/Connectiondirectives. - Voice calls fail: TURN not reachable. Check firewall allows 3478/udp and 49152-65535/udp (or your configured range).
Need more detail? Full admin guide in the repo →