Custotal

00 Self-hosted CRM · Apache-2.0

Your customer data,
in your custody.

Custotal is a self-hosted CRM a small B2B sales team can actually run: one API process, one PostgreSQL database, one Compose file — and no third party holding your customer list. It is built for teams that already run their own infrastructure.

No sign-up page. Provision the first administrator with one command.

The live demo is the same UI on seeded mock data — nothing to install.

Stand it up this afternoon and expect it to still be running, unchanged, in three years.

Live workspace

single tenant · your PostgreSQL

3–15
People on the team it is built for
~5 min
Clone to a working workspace
1
API process to operate
0
Per-seat fees, at any team size
  • Apache-2.0
  • Self-hosted
  • One tenant
  • One deal pipeline
  • No telemetry
  • No sign-up wall
  • No per-seat fees
  • Your PostgreSQL, your backups
  • Source you can read end to end
  • No PII in logs
  • 30-day recovery
  • pg_dump backups

01 The custody question

SaaS CRMs win on convenience.
Custotal hands you the keys.

A SaaS CRM wins on “there is nothing to operate”. A heavyweight self-hosted CRM wins on configurability. Custotal trades both away for a system you can read end to end.

Every alternative is a trade-off. Custotal’s trade-off is that you own the system. That is the whole point.
01 Browser React 19 SPA · React Router 8 data router · lazy-loaded route chunks
02 nginx Serves the SPA, proxies /api and /health · included in the Compose stack
03 Express 5 API One process, one instance · routes → services → db
04 PostgreSQL 18 Your database, your backups · uuidv7 primary keys

Four parts, all of them yours. Nothing in this path is a managed service, and nothing in it reports back to us.

For your engineer

The session is an opaque, database-backed ct_session cookie: only the token digest is stored, so a leaked database does not hand over live sessions.

Prisma 7 reaches PostgreSQL through @prisma/adapter-pg, and every primary key uses PostgreSQL 18’s built-in uuidv7() default.

Under pnpm dev there is no nginx — Vite serves the SPA on :5173 and proxies /api to :4000, keeping requests same-origin so the cookie flows.

02 Stated plainly

Why not something else?

Every alternative is a trade-off. Here is Custotal’s, on one page, before you spend an afternoon on it.

Custotal compared with a SaaS CRM and a heavyweight self-hosted CRM
Dimension Custotal SaaS CRM Heavyweight self-hosted CRM
Where your data lives Your PostgreSQL database The vendor's cloud Your database
Time to a workspace ~5 minutes: clone, install, migrate, create one admin Minutes to sign up, then configuration to fit your process Days to weeks: stack, modules, permissions, upgrades
What you operate One API process and one SPA. Compose stack included Nothing Several services plus a broad configuration surface
Scope Focused on small-team selling Very broad: automation, service desk, CPQ Very broad, extensible by design
Ongoing cost Your infrastructure; no per-seat fee Per seat, recurring Your infrastructure plus admin time
Getting data in CSV import wizard with column mapping and a dry run Vendor-dependent exports Often a scripted migration

Scroll the table sideways to compare every column →

Note what this table does not claim. SaaS CRMs win on “there is nothing to operate”; heavyweight open-source CRMs win on configurability. Custotal concedes both, and offers one thing instead: a system you can read end to end, run on one box, and walk away from without asking permission.

03 The working surface

Ten things, and nothing else.

Deliberately narrow. Custotal is not a platform, not a marketing suite and not a service you sign up for — it is the working surface of a small B2B sales team, and nothing it cannot justify.

01

Customers

Every contact and account in one place, with role links between them — who works where, who to bill — and full audit fields, so you can see who changed what and when.

02

Interactions

Log emails, calls, meetings and notes with channel and direction, attached to the contact, account and deal they belong to, on one reverse-chronological timeline. Nobody has to ask “did anyone follow up?”

03

Pipeline

Drag a deal between stages. Every move is recorded, probability updates itself, and closed-lost deals require a reason — a forecast you can trust without chasing status updates.

04

Tasks

My-tasks and all-tasks views with filters, sorting and completion history. Overdue work is highlighted and counted in the header.

05

Reports

Pipeline-by-stage and win/loss, with charts and CSV export, so you can answer “where is revenue actually stuck?” and take the numbers to a meeting.

06

Search

One box, grouped results across contacts, accounts and opportunities, so finding a record takes seconds rather than a filter exercise.

07

CSV import

An admin wizard that maps your existing columns, handles duplicates, and runs a dry run before anything is written. Leaving a spreadsheet behind is a guided job, not a script you write.

08

Access control

Email/password sign-in with database-backed sessions, server-side roles, and owner-scoped visibility — a representative sees their book, not everyone else’s.

09

Recovery

A 30-day trash with admin restore and purge. A deleted contact is recoverable, not gone — and the purge runs on a schedule you can read in the configuration.

10

Operations

Structured logs, /health probes, rate limiting, backup and purge scripts, and a documented restore runbook — the operator’s surface is written down, including the work the MVP does not automate yet.

And who it is not for. If you need marketing automation, a service desk, CPQ or native mobile apps, this is the wrong tool — the roadmap (opens in a new tab) lists what is out of scope on purpose, and why.

04 How it is built

Narrow by design.
Open by default.

Custotal v1 is an MVP: the core workflows are implemented, covered by automated tests and usable today. What is deferred is recorded, not promised — the gaps are listed in the operations notes, in the open.

Who it is for

A B2B sales team of three to fifteen people that already runs its own infrastructure — and that either cannot or will not hand its customer list to a SaaS vendor, whether for contractual, regulatory or philosophical reasons.

What you get

One workspace covering the working surface of a sales team: contacts and accounts, interactions, one deal pipeline, tasks and reporting, behind email/password sign-in with server-side roles.

Who it is not for

Teams that need marketing automation, a service desk, CPQ or native mobile apps. Custotal is not a platform, not a marketing suite and not a service you sign up for.

Apache-2.0 Free to use, modify and self-host. The root package.json is private because Custotal is an application you deploy, not a library you install.
Quality gate Every change passes typecheck, ESLint, Stylelint, formatting and the test suites before it lands. The CI configuration is in the repository, not behind a dashboard.
Sessions & RBAC Opaque, database-backed sessions store only the token digest. HttpOnly cookies, bcrypt password hashing, server-side roles, CSRF origin checks and per-endpoint rate limiting.
No PII in logs Structured pino logs carry no personal data, and /health probes are there for whatever monitor you already run.
30-day recovery Nothing is destroyed on click. Deleted records stay in a trash for 30 days, with admin restore and a scheduled purge.
Backups you can open pg_dump-based backup and purge scripts plus a written restore procedure — separate processes, so they keep running when the application does not.

There are no customer quotes on this page, and none are published elsewhere: Custotal v1 is an MVP. The product ships no telemetry, no sign-up wall and no customer roster — what it offers instead is source you can read and notes it keeps in the open.

05 Deployment

Stand it up this afternoon.

There is no sign-up page, by design. Clone the repository, apply the migration, provision one administrator, and the workspace is yours — no trial, no seat count, no vendor between you and your customer list. Then leave it alone: this is a system built to still be running, unchanged, in three years.

Two paths, one result. Docker with Compose v2.24 or newer is the only prerequisite on the host you deploy to. Running from source instead needs Node ^24.19 and pnpm ^11.21. PostgreSQL 18+ either way · Apache-2.0 throughout · the commands below use the pnpm wrappers, and raw docker compose works just as well.

The demo build is a static bundle of the same UI running on a seeded mock workspace: there is no backend behind it, and nothing you type leaves the browser.

The whole stack is two images and a database you own.
Pinned by tag, with no latest floating underneath it.

One instance, by design. Rate-limit counters live in memory and the soft-delete purge runs on an in-process timer, so Custotal runs as a single container and scales vertically. A second replica is recorded in the operations notes as deferred work, not promised here.

docker · compose stack

# 1 · set POSTGRES_PASSWORD in the copy, then build and start the stack $ cp .env.docker.example .env.docker $ pnpm docker:up # 2 · there is no registration flow — create the first administrator $ pnpm docker:create-admin # The workspace comes up at http://localhost:8080
git clone https://github.com/orbivort/custotal.git; cd custotal; pnpm install; cp .env.docker.example .env.docker; pnpm docker:up