An open API service indexing awesome lists of open source software.

https://github.com/pjiaquan/nocodb-postgres-boilerplate

Schema-first NocoDB + PostgreSQL boilerplate with automatic bootstrap
https://github.com/pjiaquan/nocodb-postgres-boilerplate

boilerplate docker-compose nocodb postgresql schema-first

Last synced: 5 days ago
JSON representation

Schema-first NocoDB + PostgreSQL boilerplate with automatic bootstrap

Awesome Lists containing this project

README

          

# NocoDB PostgreSQL Boilerplate

Schema-first boilerplate for teams that want PostgreSQL as the source of truth and NocoDB as the UI layer, without manual NocoDB bootstrap steps.

This template gives you:

- PostgreSQL + Redis + NocoDB via Docker Compose
- SQL migrations as the only approved schema path
- automatic base creation, PostgreSQL integration, source binding, and metadata sync
- hard-fail startup when `.env` or required variables are missing
- bind-mounted local data directories under `./data`

It does not generate custom NocoDB UI metadata such as forms, views, or shared links.

## What Happens On Startup

On `docker compose up -d --build`, the stack automatically:

1. starts PostgreSQL and Redis
2. runs SQL migrations
3. starts NocoDB
4. signs in with the admin account from `.env`
5. creates or reuses the NocoDB base
6. creates or reuses the PostgreSQL integration
7. binds the base source to `APP_SCHEMA`
8. clears NocoDB metadata cache
9. triggers metadata sync

You do not need to click `Create Base`, `Connect External Data`, or `Meta Sync`.

## Use This Template

Recommended flow for a new project:

1. Create a new repository from this boilerplate, or copy it into a new repo.
2. Rename the project-level settings in `.env`, especially:
- `COMPOSE_PROJECT_NAME`
- `APP_SCHEMA`
- `NOCODB_BASE_TITLE`
- `NOCODB_INTEGRATION_TITLE`
- `NC_PUBLIC_URL`
3. Replace `db/migrations/0001_init_app.sql` with your real initial schema.
4. Start the stack and confirm the example bootstrap works in your new repo.
5. Make your first project-specific commit before adding business logic or extra services.

## Quick Start

1. Copy the env template.

```bash
cp .env.example .env
```

2. Change at least:

- `POSTGRES_PASSWORD`
- `REDIS_PASSWORD`
- `NC_AUTH_JWT_SECRET`
- `NC_ADMIN_EMAIL`
- `NC_ADMIN_PASSWORD`
- `NC_PUBLIC_URL`

3. Start the stack.

```bash
docker compose up -d --build
```

4. Check status.

```bash
docker compose ps
docker compose logs migrate
docker compose logs bootstrap
```

5. Open NocoDB and sign in with `NC_ADMIN_EMAIL` and `NC_ADMIN_PASSWORD`.

The base should already exist, and the example table should already be visible.

If `bootstrap` exits early, check `docker compose logs bootstrap` first. The most common cause is that NocoDB accepted TCP connections later than Compose marked the service as started. This boilerplate now waits for a NocoDB healthcheck and keeps retrying sign-in until timeout.

## What You Replace First

Before using this as a real project, replace or adjust:

1. `db/migrations/0001_init_app.sql`
2. `APP_SCHEMA` in `.env`
3. `NOCODB_BASE_TITLE`
4. `NOCODB_INTEGRATION_TITLE`
5. `NC_PUBLIC_URL`
6. any example tables or views you do not want

## Repository layout

- `.env.example`: required environment variables
- `docker-compose.yml`: stack definition
- `bootstrap/Dockerfile`: bootstrap image
- `scripts/bootstrap_nocodb.sh`: NocoDB bootstrap flow
- `scripts/update_schema_snapshot.sh`: refresh schema snapshot
- `scripts/check_schema_drift.sh`: compare live schema with snapshot
- `db/migrations`: SQL migrations
- `data/postgres`: PostgreSQL data
- `data/redis`: Redis data
- `data/nocodb`: NocoDB local data

PostgreSQL uses `PGDATA=/var/lib/postgresql/data/pgdata`, so the bind-mounted `data/postgres` root can safely contain mount-point metadata or a tracked `.gitkeep`. If you previously saw `initdb: error: directory "/var/lib/postgresql/data" exists but is not empty`, clear `data/postgres` and start again.

## Current defaults

The boilerplate ships with:

- `APP_SCHEMA=app`
- base title `App Data`
- integration title `App PostgreSQL`
- one example table: `example_records`
- one example view: `v_example_record_counts`

The example migration is intentionally small. Replace it with your real domain schema.

## Why this boilerplate uses a dedicated schema

NocoDB stores its own metadata tables in PostgreSQL. If your business tables live in the same scanned schema, NocoDB can import its own `nc_*` tables during metadata sync.

This boilerplate avoids that by keeping business tables in a dedicated schema, defaulting to `app`.

## Why the bootstrap script touches NocoDB metadata tables

The current bootstrap flow uses a mix of:

- NocoDB API calls for auth, workspace lookup, base creation, and integration creation
- direct PostgreSQL updates to `nc_integrations_v2` and `nc_sources_v2` for deterministic source rebinding

That choice is deliberate. It avoids the manual UI flow and worked more reliably than relying on the source-binding API flow alone.

If a future NocoDB release changes these metadata tables, the bootstrap script may need adjustment.

## Hard-fail behavior

If `.env` is missing, or required variables are missing, `docker compose` fails immediately with a clear interpolation error such as:

```text
required variable DATABASE_URL is missing a value
```

It does not continue with blank values.

## Common commands

Start:

```bash
docker compose up -d --build
```

Stop:

```bash
docker compose down
```

Re-run migrations:

```bash
docker compose run --rm migrate --wait --wait-timeout 120s --migrations-dir /db/migrations --no-dump-schema up
```

Re-run bootstrap:

```bash
docker compose run --rm bootstrap
```

Update schema snapshot:

```bash
bash scripts/update_schema_snapshot.sh
```

Check schema drift:

```bash
bash scripts/check_schema_drift.sh
```

## Reset a disposable local environment

This boilerplate uses bind mounts under `./data`.

To reset local state:

1. stop the stack
2. delete `data/postgres`, `data/redis`, and `data/nocodb`
3. run `docker compose up -d --build` again

## Suggested next step

After cloning this boilerplate for a real project, make your first commit with:

- renamed base title
- renamed schema if needed
- replaced initial migrations
- updated README