Skip to content

cold-code-labs/hauldr

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

170 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Hauldr

Hauldr

A multi-tenant, self-hostable Backend-as-a-Service on real Postgres.

The developer experience of a managed platform, the lightweight footprint of an embedded database, and true multi-tenancy — on infrastructure you own.

License: Apache 2.0 Status: pre-alpha Built on Postgres


In Old Norse law, a hauldr was a freeholder — someone who held their land outright, by inherited right, answering to no lord. Hauldr is a backend you hold the same way: your data, your Postgres, your box. No landlord.

What is Hauldr?

Hauldr is an open-source backend platform you run yourself. It gives a small team the same building blocks a managed BaaS would — authentication, a real SQL database with row-level security, file storage, realtime, and a typed client SDK — but each tenant project is isolated, lightweight, and provisioned in seconds, all on top of standard, battle-tested open-source components.

It is designed for the shape of work where you run many small applications (one per client, per product, per internal tool) and want each one to have a proper database with real auth and access control — without paying the per-app overhead of a heavyweight stack or the per-seat bill of a hosted vendor.

Three moving parts:

  1. Control plane — a self-hosted panel (Supabase-like UX) plus a management API for creating and operating projects.
  2. Shared data plane — a Postgres cluster fronted by a multi-tenant connection pooler, with one database per project.
  3. Per-project satellites — only the services a given project asks for (auth always; a REST API layer à-la-carte).

Quick start

Self-host the whole stack on any Docker host with one command:

git clone https://github.com/cold-code-labs/hauldr
cd hauldr
./scripts/selfhost-up.sh

The script generates a .env with strong secrets, builds and starts everything (Postgres, the multi-tenant pooler, the control plane, project-zero auth, Realtime, Garage object storage, and the panel), waits until it's healthy, and provisions a demo project so there's something to poke at immediately.

Then open the panel and configure your first access:

http://localhost:3000/setup

A first-run wizard walks you through creating the operator account and your organization — then you're in the panel. (Prefer to stay in the terminal? Skip the panel and drive everything through the management API below.)

Create and inspect a project through the management API:

API=http://localhost:8787
KEY=$(grep '^HAULDR_API_KEY=' .env | cut -d= -f2)

# Create a project (its own database + auth, REST layer optional)
curl -sX POST $API/v1/projects -H "Authorization: Bearer $KEY" \
  -H 'content-type: application/json' -d '{"name":"blog","rest":true}'

# Its endpoints, keys, and connection strings
curl -s $API/v1/projects/blog -H "Authorization: Bearer $KEY" | jq

Then talk to that project from your app with the SDK:

import { createClient } from "@hauldr/client"
const hauldr = createClient({ url: PROJECT_URL, db: { connectionString } })
await hauldr.auth.signUp({ email, password })
await hauldr.db.asUser(token).insert("todos", { title: "hello" }) // RLS-scoped

Prefer to run the pieces by hand, or develop on Hauldr itself? See self-hosting.md and development.md.

Note on the panel. The management API, CLI, and SDK are the complete self-serve surface. The web panel (./panel) is an early UI; it builds out of the box against an open design-system fallback (panel/vendor, no private access needed) and swaps back to Cold Code Labs' branded packages with a one-line change — see panel/vendor/README.md.

Why it exists

The two ends of the spectrum each have a cost:

  • Heavyweight managed stacks are excellent but assume one big tenant. Running dozens of small isolated apps means dozens of full deployments, or giving up isolation.
  • Embedded single-file databases are wonderfully light, but you eventually hit real ceilings: concurrent writers, true SQL, row-level security, point-in- time recovery, connection scaling.

Hauldr sits in the middle deliberately: heavy things are shared (one Postgres cluster, one pooler, one object store, multi-tenant), light things are per- project and optional. A project is just a database, an auth service, and a JWT secret — measured in tens of megabytes, not gigabytes.

Principles

  1. Shared is heavy, per-project is light and optional. Multi-tenancy lives in the shared plane; each project only carries what it actually needs.
  2. One auth model, always. Every project ships with its own GoTrue instance and its own JWT secret. Row-level security is always on — access control is enforced by the database, reading the claims from the auth token.
  3. Real Postgres underneath. No reimplemented query engine. Extensions (pgvector, etc.) are enabled per-database, on demand.
  4. Scale honestly. A multi-tenant pooler keeps connections under control; tiering lets a project that outgrows the shared cluster move to a dedicated one without changing application code.
  5. Assemble upstream, don't reinvent. Hauldr builds the panel, the provisioner, the SDK, and the conventions. It never rewrites the database, the pooler, or the auth server — those are proven projects, used as-is.

Architecture at a glance

   CONTROL PLANE                         DATA PLANE  (shared)
 ┌─────────────────────┐           ┌──────────────────────────────────────┐
 │ Hauldr Panel        │           │  Connection pooler (multi-tenant)     │
 │  (SQL / tables /    │ ── API ──▶│   routes project → database           │
 │   auth / RLS /      │           │         │                             │
 │   keys / logs /     │◀── meta ──│  Postgres  (1+ cluster, 1 DB/project) │
 │   backups)          │           │   ├ db_acme   ├ db_shop   ├ …         │
 │                     │           └──────────────────────────────────────┘
 │ Hauldr API (mgmt)   │              ▲ per-project, à-la-carte
 └──────────┬──────────┘              │  ┌ Auth (GoTrue)   [always]
            │ called by               │  └ REST (PostgREST) [optional]
   your provisioning automation       │     realtime = shared WS · storage = S3

Full detail in docs/architecture.md.

The SDK — @hauldr/client

The SDK is the layer that makes a decomposed backend feel like one thing. It hides the pooler, the auth server, and the object store behind a small surface:

npm i @hauldr/client
import { createClient } from "@hauldr/client"

const hauldr = createClient({ url: PROJECT_URL, db: { connectionString } })

// Auth — full lifecycle (signup, OAuth, magic-link, MFA, reset)
const { access_token } = await hauldr.auth.signInWithPassword({ email, password })

// Data — RLS-aware; the caller's claim is injected per transaction
await hauldr.db.asUser(access_token).insert("posts", { title: "hello" })
const posts = await hauldr.db.asUser(access_token).select("posts")

// Files — S3-style upload + signed URLs
const { url } = await hauldr.files.upload("avatars", file)

// Realtime — WebSocket via a shared, multi-tenant Realtime service
hauldr.live.on("posts", (change) => render(change))
Namespace Backed by
hauldr.auth GoTrue (lifecycle / OAuth / magic-link / MFA)
hauldr.db Typed queries through the pooler (RLS-aware)
hauldr.files Object storage over standard S3
hauldr.live Shared Realtime over WebSocket (broadcast · presence · changes)

See docs/sdk.md.

There's also a tiny CLI for deploying a project's edge functions: npm i -g @hauldr/cli (or npx @hauldr/cli functions list <project>) — see @hauldr/cli.

Documentation

Doc What's inside
Architecture The full system: control plane, data plane, satellites
Development The isolated local dev stack (v17, hot-reload panel + control plane)
Concepts Glossary and the model behind projects, tenancy, tiering
Auth & data GoTrue, RLS, server actions vs. REST, claim injection
Data plane Postgres, the pooler, migrations, backups, tiering
Storage S3-compatible object storage, buckets, durability
Functions Per-project edge functions: enabling, deploying, cron
SDK @hauldr/client surface and usage
Self-hosting Bootstrap, "project zero", running the stack
Roadmap Phased delivery plan

Status

Hauldr is pre-alpha and developed in the open. The foundational architectural decisions are settled. The control plane provisions projects end-to-end — auth always, REST / storage / realtime à-la-carte — over a multi-tenant pooler, and it already runs a real fleet of applications. What's left is operational polish (backups / PITR, tiering, per-project metrics) and a one-click migration path. Expect breaking changes until a tagged release.

Self-hosting on a single Docker host is a one command away (scripts/selfhost-up.sh); the management API, CLI, and SDK are the complete self-serve surface. Known gaps a contributor could pick up:

  • Panel design system. The panel now builds against an open fallback (panel/vendor); the richer Cold Code Labs component set stays private. A fuller open design system (more components, the real brand-neutral polish) is welcome.
  • Per-project Functions route through a reverse proxy, so they require HAULDR_NAMESPACE_PATTERN + a Traefik-style gateway (not bare localhost).
  • Scheduled jobs / cron need the pg_cron/pg_net extensions (the supabase/postgres image), not stock postgres:16.

See the roadmap for what's coming and in what order.

Built on the shoulders of

Hauldr is an assembly of excellent open-source projects:

Contributing

Contributions are welcome — see CONTRIBUTING.md. Please also read the Code of Conduct and our security policy.

License

Apache License 2.0.

About

A multi-tenant, self-hostable Backend-as-a-Service on real Postgres.

Topics

Resources

License

Code of conduct

Contributing

Security policy

Stars

1 star

Watchers

0 watching

Forks

Packages

 
 
 

Contributors