Run it yourself, properly
One image, three processes: the app, a worker and a websocket server. A Postgres database, an S3-compatible bucket, an SMTP server. Nothing here assumes a particular cloud.
What runs where
Same image, three commands. Background jobs queue in Postgres itself, so there's no separate queue server to run.
Your VPS · ghcr.io/…/slate:[version]
node apps/web/server.jsnode apps/worker/dist/index.cjsnode apps/realtime/dist/server.cjsYours to choose
Swap the parts, keep the app
Each outside service is reached through one interface in the code. Changing provider is configuration, not a fork.
| Seam | What it needs | Works with |
|---|---|---|
| Storage | An S3-compatible API | Any S3-compatible bucket, including MinIO on the same box |
| A transport | SMTP, or Resend | |
| Payments | A payment provider | Stripe or GoCardless |
| Queue | Postgres | The database you already run |
Your clients' files, on your disk
When you run it, the database and the bucket are yours. Backups are whatever you already trust, and nothing leaves the box unless you point a seam at a service outside it.
The fonts ship inside the image and the build doesn't fetch from Google, so it works behind a restrictive egress policy.
What you take on
Self-hosting means you own the backups, the upgrades and the 3am page. If that's not a trade you want, the managed version is the same software with us holding the pager.
- Self-hosted
- You run the box, the backups and the upgrades
- Managed
- We run it; same software, same data model
- Upgrades
- A new tagged image
- Moving between them
- Your data exports either way