Self-hosting Reborn Apps with Docker Compose
A step-by-step guide to running your own instance of Reborn Apps using Docker Compose.
One of the core benefits of open-source software is the ability to run it yourself. Here’s how to self-host Reborn Apps using Docker Compose.
Prerequisites
- Docker 25+ with Docker Compose
- A server with at least 2 GB RAM
- A domain name and TLS certificate (if you’re exposing the instance to the internet)
Two flows: dev vs production
The repository ships two Docker Compose flows - you need to consciously pick the right one.
| Flow | Source on host? | Image | Boot time | Use case |
|---|---|---|---|---|
Development (docker-compose.yml) | Required (cloned repo) | node:alpine + bind mount + pnpm install at boot | Slow first start, HMR after | Hacking on the code |
Production (docker-compose.prod.yml.example) | Not required at runtime | Pre-built from multi-stage Dockerfile | <15 s, no pnpm install | Running your own instance |
Important: the default
docker-compose.ymlis the dev flow. Pasting it into a panel like Portainer/Coolify without a cloned repo on the host will fail withERR_PNPM_NO_PKG_MANIFEST- the bind mount points at an empty directory. For self-hosting, use the production flow below.
Quick start (production)
git clone https://github.com/fundacja-reborn/reapps.git
cd reapps
cp .env.example .env
cp docker-compose.prod.yml.example docker-compose.prod.yml
Generate secrets and fill in .env:
# Secret generator (one unique value per variable)
openssl rand -base64 48
Minimum values you need to set in .env:
PUBLIC_SITE_URL=https://your-domain.example.com # or http://your-server-ip
DB_USER=postgres
DB_PASSWORD=<strong-random-password>
DB_NAME=reborn
JWT_SECRET=<openssl rand -base64 48>
REFRESH_TOKEN_SECRET=<openssl rand -base64 48>
SESSION_SECRET=<openssl rand -base64 48>
RECOVERY_KEY_SECRET=<openssl rand -base64 48>
Build and start:
docker compose -f docker-compose.yml -f docker-compose.prod.yml \
--profile with-notes up -d --build --wait
After startup the containers listen on ports :4200 (re/task) and :4201 (re/notes) on the Docker host.
Reverse proxy and HTTPS
The apps don’t terminate TLS themselves - in production you need a reverse proxy in front that terminates HTTPS and preserves the /task and /notes path prefixes (those make SSO via shared origin work):
https://your-domain/task/→http://127.0.0.1:4200/task/https://your-domain/notes/→http://127.0.0.1:4201/notes/
nginx, Caddy, Traefik, or Cloudflare Tunnel all work - nginx/dev.conf in the repo is a starting point (for production add listen 443 ssl;, certificate paths, HSTS).
The
docker-compose.proxy.ymlfile in the repo is a development proxy onhttp://localhost:80- useful for local SSO testing, but it does not replace a production reverse proxy with TLS.
Smoke-testing the production image locally
Before pointing a real domain at a fresh image, you can test the production flow on your own machine:
cp docker-compose.localprod.yml.example docker-compose.localprod.yml
docker compose -f docker-compose.yml -f docker-compose.localprod.yml \
-f docker-compose.proxy.yml --profile with-notes -p reborn-localprod \
up -d --build --wait
# → http://localhost/task and http://localhost/notes
This override uses http://localhost as the origin and the dev DB credentials, so it composes cleanly without further configuration.
Portainer, Coolify, Dokploy and other panels
Pasting raw YAML into a panel isn’t enough - the production flow needs the build context (the Dockerfile plus the source tree). Configure the stack so the panel clones the repo from https://github.com/fundacja-reborn/reapps.git instead of pasting YAML into the editor - that way the build has everything it needs. Then point it at two compose files:
docker-compose.ymldocker-compose.prod.yml.example(copied todocker-compose.prod.ymlbefore deploy)
and pass values from .env through the panel’s environment-variable editor.
Why self-host?
For most users, our public instance is the easiest way to get started - it’s free, always up to date, and supported by the community. Self-hosting is an option for individuals and organizations with specific requirements:
- Full control - your data stays on your hardware
- Custom domain - use your own domain name
- Regulatory compliance - meet internal data residency policies
- Same encryption - E2E encryption works identically
💡 Whichever option you choose, consider supporting the project - your donation helps develop Reborn Apps for everyone.
Support
If you run into issues, check the self-hosting section in the README or open an issue on GitHub. The community is here to help.