Self-hosting

Docker Compose

The repository ships a docker-compose.yml that brings up everything an instance needs: a Postgres database and the app, wired together. It pulls the published image, so there is nothing to build, and the app applies its own database migrations on startup.

Prerequisites

  • Docker 24+ with the Compose plugin (docker compose, not the legacy docker-compose)
  • Git
  • A host with 1 vCPU and 1 GB RAM is enough to start

One command

git clone https://github.com/PunterDigital/Clerq.git
cd Clerq
docker compose up -d

That command pulls ghcr.io/punterdigital/clerq, starts Postgres, waits for it to become healthy, then starts the app - which migrates the database and serves on http://localhost:3000. Open it, create your account, set up your business, and you are in.

What is in the compose file

ServiceRole
postgresThe database. Data persists in the postgres-data named volume. Its port is bound to 127.0.0.1 only, so it is never exposed to the network.
appThe Clerq image. It runs any pending migrations on startup, then serves on port 3000.

Configure it with a .env file next to the compose file rather than editing the YAML.

Configure with a .env file

Compose reads a .env file in the project root. The defaults work for a local trial, but you must set a real database password and auth secret before exposing the instance anywhere:

# .env - next to docker-compose.yml
POSTGRES_PASSWORD=a-strong-random-password
BETTER_AUTH_SECRET=generate-with-openssl-rand-base64-32
BETTER_AUTH_URL=https://clerq.example.com

# Optional: pin a released version instead of latest
CLERQ_TAG=0.1.0

The compose file assembles DATABASE_URL for you from the POSTGRES_* values and points it at the internal postgres service - you do not set DATABASE_URL yourself here. See Environment variables for the full reference, and Going to production to put it behind HTTPS safely.

Updating

docker compose pull      # fetch the newer image
docker compose up -d     # recreate the app; migrations run on boot

Pin CLERQ_TAG in production so updates are deliberate. See Backups & upgrades.

Build from source instead

To run a local build of the code rather than the published image - for contributors, or to try local changes - layer on the build override:

docker compose -f docker-compose.yml -f docker-compose.build.yml up -d --build

Seed demo data (optional)

To explore a populated instance, seed demo data from a checkout against the running database (the compose Postgres is published on 127.0.0.1:5432):

pnpm install
DATABASE_URL=postgresql://clerq:clerq@localhost:5432/clerq pnpm db:seed

It creates a sample business with clients, projects, a week of tracked time, and a login of [email protected] / clerq-demo. The seed is idempotent. Do not seed a production instance.

Stopping and resetting

docker compose down            # stop the stack, keep the data
docker compose down -v         # stop and DELETE the database volume

down -v removes the postgres-data volume and everything in it. Only use it when you genuinely want a clean slate.

Want the database managed elsewhere, or a single container? See Docker for the bare docker run against your own Postgres.