
Deploy brightbean-chat
Open-source ManyChat alternative. Self-hosted chat-marketing automation
Just deployed
Just deployed
Just deployed
/var/lib/postgresql/data
Deploy and Host BrightBean Chat on Railway
BrightBean Chat is an open-source, self-hostable alternative to ManyChat. You get a visual flow builder, a shared inbox, broadcasts, sequences and analytics across Telegram, Instagram, Messenger, WhatsApp, SMS and email. It runs on Django 5, HTMX and PostgreSQL. No Redis, no message broker, no aggregator sitting between you and the platforms.
This template deploys the whole stack: A Postgres database, the web service, and the background worker that runs everything time-based.
About Hosting BrightBean Chat
The app runs as two long-lived processes against one database. web serves
pages, the API and the webhook endpoints. worker claims and runs the queue:
Smart Delay steps, follow-up timers, send retries, sequences, broadcast fanout
and hourly housekeeping.
Both are required. With only web running, nothing errors. Inbound messages
still get answered inline. But every scheduled action sits in the queue with a
due time in the past, and you won't find out until someone asks why the
follow-up never went.
Postgres is the only datastore. It is also the task queue, the lock manager and
the rate limiter, so there is nothing else to run. Migrations are applied before
each deploy of web. Uploaded media and queued contact-import files go to
object storage, because the two services do not share a filesystem.
Webhooks are why the public domain matters. Telegram, Meta and Twilio all deliver events by POSTing to an HTTPS URL you register with them. A deployment that is not publicly reachable can send messages but will never receive one.
After the first deploy:
- Create the first account at
/accounts/signup/. Email verification is optional, so you can sign in straight away. - Connect a channel in Settings, then register the webhook URL with that platform.
- Back up
SECRET_KEYandENCRYPTION_KEY_SALT. They are generated for you, and they decrypt the channel credentials in your database. A dump without them is unreadable. - If you attach a custom domain, update
ALLOWED_HOSTSandAPP_URL. Do it before inviting your team: The domain that appears in account emails is written once, on the first deploy.
Common Use Cases
- Instagram and Messenger comment-to-DM automation with keyword triggers and follow-up sequences.
- WhatsApp and SMS broadcasts to segmented contact lists, rate-limited per platform.
- A shared inbox where a team handles every channel in one place, with assignment and internal notes.
- Lead capture and qualification flows that write to custom fields and hand off to a CRM through the public API or an External Request step.
- Replacing a per-contact SaaS subscription with a fixed hosting bill, with contact data in a database you control.
Dependencies for BrightBean Chat Hosting
PostgreSQL 16 or newer is included in this template.
You supply your own private S3-compatible bucket. Cloudflare R2, AWS S3, Backblaze B2 and MinIO all work, and you enter the bucket name, access key ID, secret access key and endpoint URL at deploy time. Keep the bucket private: Media is delivered by presigned URL, and a public bucket hands out every uploaded file to anyone who guesses a key.
Each platform you connect needs its own credentials, whether that is a bot token, app credentials or API keys. You add those inside the app after deploy, not at deploy time.
SMTP is optional. Password reset and address verification need it, but signup works without it.
Deployment Dependencies
- Source and issues: https://github.com/brightbeanxyz/brightbean-chat
- Self-hosting guide, including the Cloudflare R2 walkthrough: https://github.com/brightbeanxyz/brightbean-chat/blob/main/docs/self-hosting.md
- Cloudflare R2 documentation: https://developers.cloudflare.com/r2/
Why Deploy BrightBean Chat on Railway?
BrightBean Chat needs two long-lived processes, a Postgres database and a public HTTPS endpoint. Railway runs both services from the same Dockerfile in one project, issues the TLS domain the platform webhooks require, and applies migrations as a pre-deploy step, so a schema change ships with the code that needs it.
The worker scales horizontally with no extra configuration. The queue claims
rows with FOR UPDATE SKIP LOCKED, so concurrent workers take disjoint
batches. Duplicating the environment gives you staging: A separate database and
separate variables, deployed from whichever branch you point it at.
Licensed AGPL-3.0
Template Content
APP_URL
The public origin, with https://. Links in emails and media URLs are built from it. Update it when you attach a custom domain.
S3_BUCKET_NAME
Your private bucket for uploaded media and contact imports. The bucket name, not a URL.
S3_ENDPOINT_URL
R2: https://<ACCOUNT_ID>.r2.cloudflarestorage.com, no bucket in the path. Empty for AWS S3.
S3_ACCESS_KEY_ID
Access key for the bucket.
S3_SECRET_ACCESS_KEY
Secret key for the bucket.
APP_URL
Referenced from web. The origin for links in queued messages and emails.
