Skip to content

Self-hosting

Terminal window
git clone https://github.com/ideascoldigital/groveback
cd groveback
cp .env.example .env # set JWT_SECRET
docker compose up -d
curl localhost:8080/api/v1/health

This brings up the app plus a single-node MongoDB replica set. The replica set matters: realtime uses Change Streams, which a standalone mongod cannot serve.

Generate a secret:

Terminal window
openssl rand -base64 32
Variable Why
JWT_SECRET A real value. Anything not starting with dev-secret also puts the server into production posture.
GROVEBACK_SECRET_KEY At least 16 characters. Encrypts integration and BYO secrets at rest — the server refuses to start in production without it.
MONGO_URL A replica set.
GROVEBACK_BASE_URL The public URL, so OAuth callbacks and signed URLs resolve.

Production posture has one more consequence: GROVEBACK_DEV_ADMIN_KEY is refused unless GROVEBACK_DEV=1. A known admin key on a production deployment is not a warning-level mistake.

Full list at environment variables.

Blobs land in MongoDB by default, which caps individual files at the 16 MB BSON limit. For anything real, configure S3:

Terminal window
S3_ENDPOINT=https://s3.example.com
S3_ACCESS_KEY_ID=
S3_SECRET_ACCESS_KEY=
S3_BUCKET=groveback
S3_REGION=us-east-1

All three of endpoint, key and secret must be set or S3 stays off.

Without REDIS_URL, functions run inline and there is no persistent queue — pending webhook deliveries are lost on restart, and cron triggers do not work at all. With it, BullMQ handles both.

Terminal window
REDIS_URL=redis://localhost:6379

RESEND_API_KEY and RESEND_FROM enable transactional email — verification and password reset.

Note the deliberate fallback: without a mailer, the email-verification gate is disabled rather than locking every user out of a deployment that cannot send mail.

By default the deployment serves one project (GROVEBACK_PROJECT_ID, default proj_dev).

Set GROVEBACK_MULTI_PROJECT=1 to serve every active control-plane project from one instance, routed by the token’s pid and by slug for function URLs.

Two layers supply collection policies: a groveback.policies.json file of deployment defaults (mount it via the commented lines in docker-compose.yml), and per-project policies managed at runtime through the admin API or the dashboard. Project policies shadow the file defaults.

Reading a policy back tells you which layer it came from via source.

GROVEBACK_OPERATORS is a comma-separated list of emails allowed to use /api/v1/control/admin/* — plan management, per-user limits, the cost model. Unset means those routes fail closed, which is the right default.

Entirely opt-in. Without STRIPE_SECRET_KEY there is no billing service, no billing route, and nothing is limited — the self-host default is unlimited.

Served at /dashboard. dashboard/dist/ is git-ignored and built in Docker and CI (the dashboard stage of the backend Dockerfile). Build it locally with:

Terminal window
make dashboard

Without it, bun run dev falls back to a legacy embedded page.

Terminal window
curl localhost:8080/api/v1/health

Returns liveness plus version, commit (GROVEBACK_COMMIT) and chartVersion (CHART_VERSION) — wire those at build time so a running instance can tell you what it is.

Path What
/dashboard The admin SPA.
/docs Swagger UI over the OpenAPI spec.
/graphiql The GraphQL IDE.
/examples/oauth A minimal OAuth login tester.
/api/v1/openapi.json The spec itself — typed per project when called with an admin token.

make help lists everything.

Terminal window
make up # docker compose self-host
make down
make logs
make health
make dev # in-memory, no DB
make dev-mongo # replica-set Mongo + server
make dev-vector # Mongo + embeddings + MinIO + Redis + dashboard
make dev-tools # Bull Board, RedisInsight, Mongo Express
make check # typecheck + unit suite