Self-Hosting
ProBeya's supported self-hosted path is the checked-in Docker Compose stack. It packages the Next.js application, WebSocket service, Docusaurus site, and a dedicated database schema operation with PostgreSQL 16, Redis 7, MinIO, ClamAV, and Nginx.
Requirements
| Component | Minimum | Recommended production baseline |
|---|---|---|
| CPU | 2 cores | 4+ cores |
| RAM | 4 GB | 8+ GB |
| Storage | 20 GB SSD | 100+ GB persistent SSD plus off-host backups |
| Docker | 24+ with Compose v2 | Current supported release |
| Network | Public IP/domain | TLS on ports 80 and 443 |
PostgreSQL 16 is the supported database version. The included production deployment publishes only Nginx; infrastructure ports are bound to loopback.
Supported Deployment
Follow Docker Deployment. Every Compose command must use both files:
docker compose \
-f docker/docker-compose.yml \
-f docker/docker-compose.prod.yml \
<command>
The production overlay is not standalone. There is no api service or
apps/api executable: the tRPC and HTTP API run in the Next.js web service.
The hardened MVP intentionally excludes cron handlers, GraphQL, REST v1, the
broad MCP tool catalog, enterprise
SSO/SAML, dedicated integration endpoints, public sharing links, and global
template galleries until each has a tenant-aware RLS contract. Nginx fails
closed for the excluded API routes, and the production build fixes both SSO
feature flags to false. The exact support boundary is documented in
Docker Deployment.
The production shell deliberately exposes only Dashboard, Forms, Settings, and the Workspace → Project → Board tree. Its settings navigation is limited to profile, security, organization, members, and billing; the enterprise navigation remains a non-hardened development surface.
For another orchestrator, build and operate the checked-in images:
docker/Dockerfile.webdocker/Dockerfile.wsdocker/Dockerfile.docsdocker/Dockerfile.schema
You must reproduce the same runtime/admin database separation, one-shot MinIO bootstrap, ClamAV fail-closed behavior, health checks, and schema ordering. The repository does not currently include supported Helm charts or Kubernetes manifests.
Network and DNS
The included Nginx configuration expects separate public origins for the web application, WebSocket service, documentation, and object storage. Tenant routing also requires wildcard DNS for application subdomains.
probeya.example.com -> deployment public IP
*.probeya.example.com -> deployment public IP
ws.example.com -> deployment public IP
docs.example.com -> deployment public IP
files.example.com -> deployment public IP
Use a wildcard or SAN certificate that covers the hostnames configured in
docker/nginx/probeya.conf. Realtime clients connect directly to the value of
NEXT_PUBLIC_WS_URL; the main application hostname has no /ws fallback.
Database Operations
Use this order for a fresh V2 setup and post-baseline V2 upgrades:
- Stop application writes.
- Create and verify a PostgreSQL backup.
- Run the
ownershipprofile operation. - Run the
schemaprofile operation. - Start
web,ws,docusaurus, and Nginx only after the schema check passes.
The exact commands are in Database Schema Operations.
The schema operation runs db:migrate, apply-rls, and check-rls in that
order. Never run schema commands inside the standalone web image, and never
provide an admin database URL to web or ws.
The one-time Phase 143 cutover requires an empty PostgreSQL 16 target; an MVP-v0 database is backed up and replaced, not migrated in place.
Backups
Back up PostgreSQL and the private object-storage bucket. Keep copies outside the host and regularly prove restoration into an isolated environment.
Create a custom-format PostgreSQL backup from the Compose deployment:
docker compose \
-f docker/docker-compose.yml \
-f docker/docker-compose.prod.yml \
exec -T postgres sh -ec \
'pg_dump --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" --format=custom' \
> probeya-$(date +%Y%m%d-%H%M%S).dump
Use your S3-compatible provider's versioning, replication, and backup tooling
for S3_BUCKET. Do not make uploads/attachments/ public as a shortcut for
backup access.
Upgrading
git pull --ff-only origin main
# Validate environment interpolation before stopping writers.
docker compose \
-f docker/docker-compose.yml \
-f docker/docker-compose.prod.yml \
config --quiet
# Follow backup -> ownership -> schema, then rebuild and start.
docker compose \
-f docker/docker-compose.yml \
-f docker/docker-compose.prod.yml \
build web ws docusaurus
docker compose \
-f docker/docker-compose.yml \
-f docker/docker-compose.prod.yml \
up -d
Never pull and restart application containers before the release's database operations have succeeded.
Health and Logs
| Endpoint | Meaning |
|---|---|
GET /api/health on web | Process liveness |
GET /api/ready on web | PostgreSQL and Redis readiness |
GET /health on ws | WebSocket service health |
GET /healthz on docusaurus | Documentation service health |
docker compose \
-f docker/docker-compose.yml \
-f docker/docker-compose.prod.yml \
ps
docker compose \
-f docker/docker-compose.yml \
-f docker/docker-compose.prod.yml \
logs -f web ws postgres redis minio clamav
For the complete operator contract, keep
docker/README.md
as the canonical runbook.