Self-hosted sign-up bounced back to the bootstrap screen for three
compounding reasons:
- better-auth's client resolves { data, error } on HTTP failure; the UI
ignored res.error and showed "Account created — signing you in", hiding
the real 403/429/500.
- trustedOrigins was a static localhost-only list. Browsing the instance
via LAN IP or custom port failed every auth POST once cookies existed.
Origins are now derived from the request's public host (forwarded by
nginx), so any origin serving the app works.
- hasMailTransport threw when core.settings was unreadable (fresh volume,
backend still migrating), so sign-up 500'd and the startup backfill
could crash-loop the service. Both now degrade to "no transport".
Verified live: LAN-style origin sign-up succeeds, missing core.settings
logs a warn instead of exiting, and the frontend shows real errors.
Generated with [Devin](https://devin.ai)
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Primora
Self-hosted backend platform for building products.
Auth, Postgres-backed APIs, object storage, and audit logs on your own hardware.
Quick Start · Documentation · Releases · Contributing
What is Primora?
Primora is a self-hosted backend platform: organizations, projects, auth, S3-style object storage, JSON document collections, scoped API keys, and a full audit log behind one dashboard. Inspired by the UX of Appwrite and Supabase, with no hosted tier - your data stays on your hardware.
Screenshots
| Overview | Storage | Telemetry |
|---|---|---|
![]() |
![]() |
![]() |
Features
- Organizations & projects - workspaces with scoped org and project roles.
- Auth - email/password plus optional GitHub, Google, Discord, and Microsoft OAuth. JWTs verified by the API against JWKS.
- Storage - S3-style buckets on local disk or any S3-compatible backend (AWS, MinIO, Garage, R2), public or private. With
s3the API mints presigned upload/download URLs so large objects skip the backend. - Collections - schema-flexible JSON documents in Postgres JSONB, with filter/order queries.
- Functions - project-scoped JS/TS run by bun/deno — on the host (
exec) or in ephemeral locked-down containers (dockerdriver) — with per-run logs. Trigger them four ways: manual invoke, cron schedules (function_idon a job), inbound hooks (mode: "function"), or domain events (event_patternlikedocument.*). - Vault - AES-256-GCM project secrets plus an Argon2id/XChaCha20 local vault in the CLI and desktop app.
- Automation - scheduled jobs, inbound webhooks, telemetry alert rules, and
secret://refs resolved at delivery. - Realtime - SSE event stream with a typed client SDK (
@primora/client) — channel subscriptions, presence counts, and client-publishedcustom.*events that fan out to webhooks and functions. - API keys -
prm_<prefix>_<secret>credentials, shown once. - Agent setup - every project can mint a
write-scoped key and generate a copyable AI-agent prompt that wires telemetry, database tracking, and MCP/CLI access into any repository. - Audit log - every mutating request recorded, with CSV/JSON export.
- Demo mode - fully client-side seeded workspace via
?demo=true.
Architecture
Browser ──▶ Nginx ──▶ Frontend (SolidJS + Vite)
├──▶ Auth service (Better Auth + Hono)
└──▶ API (Go + Gin) ──▶ PostgreSQL
──▶ DragonflyDB (Redis-compatible cache)
──▶ Local filesystem object storage
Quick Start
Prerequisites: Docker with the Compose plugin.
curl -fsSL https://raw.githubusercontent.com/Dvorinka/Primora/master/install.sh | bash
Installs into ./primora, generates secrets, and starts the stack on port 80.
Or from a clone:
git clone https://github.com/Dvorinka/Primora.git && cd Primora
./scripts/setup.sh # creates .env, generates secrets, starts the stack
Then open http://localhost - or append ?demo=true to explore a seeded
workspace without signing up. For prebuilt images, native development, port
conflicts, and troubleshooting see QUICK_START.md.
Configuration
All configuration lives in .env - see .env.example for the annotated list
and QUICK_START.md for the important ones.
Ecosystem
- CLI -
primorafor orgs, projects, buckets, objects, keys, jobs, and audit — plus an encrypted local secrets vault (vault:*,secrets:*,inject), the shared project vault (secrets:* --remote,secret://NAMErefs in job payloads), an agent credential broker (agent), and compose-stack operator commands (stack:*). - MCP server - exposes
primora_*tools to MCP clients. - Desktop - Tauri 2 shell connecting to your deployment, with tray presence and a local Secrets Vault window (drives the CLI's vault).
- PWA - the dashboard is installable on mobile and desktop browsers.
Documentation
- QUICK_START.md - setup, configuration, troubleshooting
- project_backend.md / project_frontend.md - original design specs
apps/backend/openapi/openapi.yaml- API contract
Contributing
See CONTRIBUTING.md for the development workflow.
Security
See SECURITY.md for reporting vulnerabilities.





