Get started
Other platforms
What Bouée needs from any platform that runs containers: Kubernetes, Render, Railway and the rest.
bin/install on a server with Docker and Fly.io are the two installs these docs walk through. Anywhere else that runs a container, follow the platform's own guide for a Docker image with PostgreSQL and object storage, and give Bouée the following.
The image
One image, built from the repository's Dockerfile (target runner), both migrates and serves:
- Serving:
node server.jslistens on port 3000 (PORT).GET /api/healthanswers 200 while the database answers, for the platform's health check. - Migrating:
/app/bin/migrateapplies the database migrations and exits. Run it before a new version serves: as a release or pre-deploy command, a Kubernetes init container or Job, or Compose'smigrateservice. - Keep one instance running. Mail comes in and goes out from the running server, and its sweeps (retries, expiry, auto-close) run on timers inside it. Several instances are fine; none is not.
What it connects to
- PostgreSQL 16 or later.
DATABASE_URLis what the app uses. When it goes through a connection pooler, setDIRECT_DATABASE_URLto a direct connection for the migrations. - An S3-compatible bucket (Amazon S3, Cloudflare R2, Tigris, Garage or MinIO):
S3_ENDPOINT,S3_BUCKET,S3_REGION,S3_ACCESS_KEY_ID,S3_SECRET_ACCESS_KEY, andS3_FORCE_PATH_STYLE=truewhere the store needs path-style addresses. Keep the bucket private. - Resend, with
RESEND_API_KEY(Email).
The environment
| Variable | |
|---|---|
APP_URL | The https address people open. |
DATABASE_URL | As above. |
BETTER_AUTH_SECRET, PORTAL_LINK_SECRET, SECRET_ENCRYPTION_KEY | Generated once, each with openssl rand -base64 32. Keep a copy apart from the platform: a restored database needs the same SECRET_ENCRYPTION_KEY. |
S3_* | As above. |
RESEND_API_KEY | A Resend key with full access. |
BOUEE_CONFIG | Where the platform mounts bouee.yaml, read-only, such as /config/bouee.yaml. |
TRUSTED_PROXIES | How many proxies add to X-Forwarded-For in front of Bouée: 1 behind one load balancer. |
.env.example explains every variable, the optional ones included.
In front of it
- TLS for
APP_URL's hostname, and for each brand hostname Bouée serves: a wildcard certificate covers brand subdomains under ahosted_domain, and a customer's own hostname needs one of its own. - The Host header passed through unchanged. Bouée decides from it what each hostname may reach: a brand's hostname serves only its knowledge base.
- Request bodies of 64 MB, just above Bouée's own 60 MiB limit, for attachments; and no path prefix: Bouée answers at the root of its hostname.
- Inbound https from Resend to
APP_URL/api/inbound/…, which is how incoming mail arrives.
Asking the running app
bin/bouee's commands run inside any container of the image:
node /app/bin/bouee.mjs status # also dns-records and provisionWith Kubernetes, that is kubectl exec deploy/bouee -- node /app/bin/bouee.mjs status.