diff --git a/README.md b/README.md index 251e246..eb13295 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,56 @@ -# Primora +

+ Primora +

-A self-hosted backend platform for building products — auth, Postgres-backed APIs, object storage, JSON document collections, 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. +

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 +

+ +

+ CI + Release + License +

+ +## 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 | +|:-:|:-:| +| ![Project overview](docs/screenshots/overview.png) | ![Object storage](docs/screenshots/storage.png) | +| **Telemetry** | **Collections** | +| ![Telemetry and component health](docs/screenshots/telemetry.png) | ![JSON document collections](docs/screenshots/collections.png) | +| **Automation** | **Audit log** | +| ![Scheduled jobs and live events](docs/screenshots/automation.png) | ![Audit log with export](docs/screenshots/audit.png) | + +## Features + +- **Organizations & projects** - top-level workspaces containing projects, members, and scoped roles (`owner`/`admin`/`member` org roles, `admin`/`developer`/`viewer` project roles). +- **Auth** - email/password plus optional GitHub, Google, Discord, and Microsoft OAuth via Better Auth. JWTs minted by the auth service are verified by the Go API against JWKS. +- **Storage** - S3-style buckets and objects backed by your local filesystem, with public/private visibility and downloadable URLs. +- **Collections** - schema-flexible JSON documents stored in Postgres JSONB. +- **API keys** - `prm__` credentials; secrets are shown once. +- **Audit log** - every mutating request recorded with actor, resource, request ID, and timestamp; CSV/JSON export from the dashboard. +- **Generated client** - the TypeScript client is generated from `apps/backend/openapi/openapi.yaml`, so the API contract is the source of truth. +- **Demo mode** - a fully client-side workspace (`?demo=true` or `VITE_DEMO_MODE=true`) for trying the UI without a backend. + +## Architecture ``` Browser ──▶ Nginx ──▶ Frontend (SolidJS + Vite) @@ -10,18 +60,16 @@ Browser ──▶ Nginx ──▶ Frontend (SolidJS + Vite) ──▶ Local filesystem object storage ``` -## What you get +| Service | Port | Purpose | +|---|---|---| +| nginx | 80 (`NGINX_PORT`) | Reverse proxy - only public entrypoint | +| backend | 8080 (internal) | Go + Gin API | +| auth | 3001 (internal) | Better Auth service | +| postgres | 5432 (`POSTGRES_PORT`) | Primary datastore | +| dragonfly | 6379 (`DRAGONFLY_PORT`) | Redis-compatible cache | +| mailpit (dev) | 8025 (`MAILPIT_HTTP_PORT`) | Email capture with `docker-compose.dev.yml` | -- **Organizations & projects** — top-level workspaces containing projects, members, and scoped roles (`owner`/`admin`/`member` org roles, `admin`/`developer`/`viewer` project roles). -- **Auth** — email/password plus optional GitHub, Google, Discord, and Microsoft OAuth via Better Auth. JWTs minted by the auth service are verified by the Go API against JWKS. -- **Storage** — S3-style buckets and objects backed by your local filesystem, with public/private visibility and downloadable URLs. -- **Collections** — schema-flexible JSON documents stored in Postgres JSONB. -- **API keys** — `prm__` credentials; secrets are shown once. -- **Audit log** — every mutating request recorded with actor, resource, request ID, and timestamp; CSV/JSON export from the dashboard. -- **Generated client** — the TypeScript client is generated from `apps/backend/openapi/openapi.yaml`, so the API contract is the source of truth. -- **Demo mode** — a fully client-side workspace (`?demo=true` or `VITE_DEMO_MODE=true`) for trying the UI without a backend. - -## Install +## Quick Start Prerequisites: Docker with the Compose plugin. @@ -32,7 +80,7 @@ curl -fsSL https://raw.githubusercontent.com/Dvorinka/Primora/master/install.sh ``` Installs into `./primora`, generates secrets, and starts the stack on port 80. -Non-interactive — configure with env vars: +Non-interactive - configure with env vars: ```bash DOMAIN=example.com NGINX_PORT=8080 PRIMORA_DIR=/opt/primora bash install.sh @@ -62,11 +110,10 @@ docker pull ghcr.io/dvorinka/primora-{backend,auth,frontend}:latest docker compose up -d --no-build ``` -Then open `http://localhost`. For local email capture, add the dev overlay +Then open `http://localhost` (or append `?demo=true` to explore a seeded +workspace without signing up). For local email capture, add the dev overlay (`-f docker-compose.dev.yml`) and Mailpit is at `http://localhost/mailpit/`. -If ports `5432` or `6379` are already in use on your machine, set `POSTGRES_PORT` and `DRAGONFLY_PORT` in `.env` — only the host bindings change. - ### Useful commands ```bash @@ -77,7 +124,7 @@ docker compose down # stop (data persists in volumes) docker compose down -v # stop and delete all data ``` -## Verification +### Verify the install | Check | Endpoint | |---|---| @@ -87,6 +134,24 @@ docker compose down -v # stop and delete all data | Auth health | `http://localhost/auth-health` | | OpenAPI spec | `http://localhost/api/v1/openapi.yaml` | +## Configuration + +All configuration lives in `.env` (see `.env.example` for the full list): + +| Variable | Default | Purpose | +|---|---|---| +| `NGINX_PORT` | `80` | Public HTTP port | +| `POSTGRES_PORT` | `5432` | Host binding for Postgres | +| `DRAGONFLY_PORT` | `6379` | Host binding for Dragonfly | +| `JWT_SECRET` | - | Signs API tokens (required) | +| `BETTER_AUTH_SECRET` | - | Signs auth sessions (required) | +| `COOKIE_DOMAIN` | `localhost` | Cookie scope for auth sessions | +| `PRIMORA_ENCRYPTION_KEY` | - | AES-256 key encrypting secrets at rest | + +Only host bindings change when you move ports - the internal network stays +the same. OAuth providers, SMTP, and storage limits are documented in +`.env.example` and [QUICK_START.md](QUICK_START.md). + ## Local development ```bash @@ -116,11 +181,11 @@ Supports session sign-in (`primora login`) and API-key mode (`primora login --ap ## Desktop & phone -- **Desktop** — `apps/desktop` is a Tauri 2 shell (Linux/Windows/macOS). First +- **Desktop** - `apps/desktop` is a Tauri 2 shell (Linux/Windows/macOS). First run asks for your deployment URL, then renders the same dashboard in a webview with a system-tray presence. Nothing is bundled; your server does the work. See [apps/desktop/README.md](apps/desktop/README.md). -- **Phone / PWA** — the dashboard ships a web manifest and service worker. +- **Phone / PWA** - the dashboard ships a web manifest and service worker. Open your deployment in a mobile browser and "Add to Home Screen"; the shell is precached, API traffic always goes to the network. Chromium desktop browsers get an in-app install banner. @@ -141,9 +206,9 @@ apps/ backend/ Go + Gin API, sqlc, migrations, object storage auth/ Better Auth on Hono (sessions, JWT, OAuth, mail) frontend/ SolidJS + Tailwind dashboard - cli/ `primora` CLI — login, context, projects, buckets, objects, keys, audit - mcp/ `@primora/mcp` — MCP stdio server exposing `primora_*` tools - desktop/ Tauri 2 shell — connects to a deployment URL, tray presence + cli/ `primora` CLI - login, context, projects, buckets, objects, keys, audit + mcp/ `@primora/mcp` - MCP stdio server exposing `primora_*` tools + desktop/ Tauri 2 shell - connects to a deployment URL, tray presence packages/ api-client/ OpenAPI-generated TypeScript client (do not hand-edit) shared-types/ @@ -153,10 +218,17 @@ scripts/ setup.sh, verify-production-ready.sh ## Documentation -- [QUICK_START.md](QUICK_START.md) — setup, configuration, troubleshooting -- [project_backend.md](project_backend.md) / [project_frontend.md](project_frontend.md) — original design specs -- [CONTRIBUTING.md](CONTRIBUTING.md) — development workflow -- `apps/backend/openapi/openapi.yaml` — API contract +- [QUICK_START.md](QUICK_START.md) - setup, configuration, troubleshooting +- [project_backend.md](project_backend.md) / [project_frontend.md](project_frontend.md) - original design specs +- `apps/backend/openapi/openapi.yaml` - API contract + +## Contributing + +See [CONTRIBUTING.md](CONTRIBUTING.md) for the development workflow. + +## Security + +See [SECURITY.md](SECURITY.md) for reporting vulnerabilities. ## License diff --git a/docs/screenshots/audit.png b/docs/screenshots/audit.png new file mode 100644 index 0000000..2cd028e Binary files /dev/null and b/docs/screenshots/audit.png differ diff --git a/docs/screenshots/automation.png b/docs/screenshots/automation.png new file mode 100644 index 0000000..7884743 Binary files /dev/null and b/docs/screenshots/automation.png differ diff --git a/docs/screenshots/collections.png b/docs/screenshots/collections.png new file mode 100644 index 0000000..99e8749 Binary files /dev/null and b/docs/screenshots/collections.png differ diff --git a/docs/screenshots/overview.png b/docs/screenshots/overview.png new file mode 100644 index 0000000..aadbd17 Binary files /dev/null and b/docs/screenshots/overview.png differ diff --git a/docs/screenshots/storage.png b/docs/screenshots/storage.png new file mode 100644 index 0000000..eb166ca Binary files /dev/null and b/docs/screenshots/storage.png differ diff --git a/docs/screenshots/telemetry.png b/docs/screenshots/telemetry.png new file mode 100644 index 0000000..7eec974 Binary files /dev/null and b/docs/screenshots/telemetry.png differ diff --git a/primora.svg b/primora.svg new file mode 100644 index 0000000..9e5e5e1 --- /dev/null +++ b/primora.svg @@ -0,0 +1,8 @@ + + + + + + + +