Install via docker compose

# docker-compose.yml
services:
  nocodb:
    image: nocodb/nocodb:latest
    container_name: nocodb
    restart: unless-stopped
    ports:
      - "127.0.0.1:8080:8080"
    environment:
      NC_DB: "pg://nc-db:5432?u=nocodb&p=${DB_PASSWORD}&d=nocodb"
      NC_AUTH_JWT_SECRET: ${JWT_SECRET}
      NC_PUBLIC_URL: https://noco.example.com
    volumes:
      - nc-data:/usr/app/data
    depends_on: [ nc-db ]

  nc-db:
    image: postgres:16-alpine
    container_name: nc-db
    restart: unless-stopped
    environment:
      POSTGRES_USER: nocodb
      POSTGRES_PASSWORD: ${DB_PASSWORD}
      POSTGRES_DB: nocodb
    volumes:
      - pg-data:/var/lib/postgresql/data

volumes:
  nc-data:
  pg-data:

.env:

DB_PASSWORD=$(openssl rand -base64 36 | tr -d '\n')
JWT_SECRET=$(openssl rand -base64 48 | tr -d '\n')
docker compose up -d

Browse to http://<host>:8080, register the first user (auto-becomes super-admin), then the dashboard opens.

Reverse proxy

# Caddy
noco.example.com {
    reverse_proxy 127.0.0.1:8080
}

Set NC_PUBLIC_URL in the env so generated share links use the public URL.

Connect to an existing database

In NocoDB: New Project → Connect to an External Database. Provide host, port, user, password, database name. NocoDB introspects the schema — every table becomes a "table" in NocoDB's view; foreign keys become relations.

This is the most powerful pattern: an existing production Postgres becomes a no-code interface without any data migration. Add views, forms, automation on top of data the app team already manages.

For a fresh database, NocoDB can create one inside its own internal DB or use the connected external DB — pick external for portability.

Views: spreadsheet, kanban, gallery, calendar, form

Each table can have multiple views with their own filters / sorts / hidden fields. The view types:

  • Grid — the default spreadsheet. Add/edit/delete rows like Airtable.
  • Form — a public-shareable form that writes a row to the table. Great for surveys, registration, request intake.
  • Kanban — cards grouped by a single-select column. Drag between columns updates the underlying value.
  • Calendar — rows positioned by a date column.
  • Gallery — image-first cards for visual data (product catalogs, photo collections).

Auto-generated API

Every table is automatically a REST endpoint:

# List
curl -H "xc-token: <api-token>" \
    'https://noco.example.com/api/v2/tables/<table-id>/records'

# Filter
curl '...?where=(status,eq,active)&sort=-created_at&limit=20'

# Create
curl -X POST -H "xc-token: ..." -H "Content-Type: application/json" \
    -d '{"title": "New task", "status": "open"}' \
    'https://noco.example.com/api/v2/tables/<table-id>/records'

GraphQL endpoint at /api/v2/graphql with the same schema. API tokens are generated under Account → Tokens; scope them per workspace / per role.

Webhooks & automation

Per table: on create / update / delete, fire a webhook (HTTP POST), send an email, run a JavaScript snippet, or call a stored procedure. Combined with n8n (see that tutorial), this becomes "row inserted → trigger workflow that does the actual work elsewhere."

Roles & permissions

Per workspace: Creator, Editor, Commenter, Viewer. Per project, the same shape. Per view, individual cell-level read/write rules are possible (Pro feature for very granular RBAC; the OSS version covers role-based access on the whole table).

Formulas & computed fields

Add a formula column with an Airtable-like syntax:

// Sum two numeric columns
{Price} * {Quantity}

// Conditional
IF({Status} = "shipped", "Done", "Pending")

// Date math
DATEADD({Created}, 7, "days")

// Lookups / rollups across linked tables
SUM({Orders.Total})

Formulas are evaluated at query time; results aren't stored. For very large tables with expensive formulas, this matters — precompute via a webhook + a stored field if performance is an issue.

Import from Airtable / CSV / JSON / Excel

Project actions → Import. NocoDB walks through an Airtable-to-NocoDB conversion (paste API key + Workspace ID), and bulk CSV/Excel import for arbitrary tabular data. For most "we're leaving Airtable" cases the import is one-click and preserves single-select / multi-select / attachments / linked records.

Where NocoDB shines

  • The "we need to expose this database table to non-engineers" use case — better than building a one-off Rails admin or Django admin.
  • The "we need a form that writes to our database" use case — better than a hand-rolled HTML form + endpoint.
  • The "we need a kanban for project X, our team is small, Jira is overkill" use case — quick, owned, exportable.

Where it isn't the right tool

  • For complex multi-step business workflows with stateful logic, build an actual app. NocoDB can't replace a real backend.
  • For analytics / dashboards, Metabase / Superset are better optimized. NocoDB shows individual rows; analytics tools aggregate.
  • For very-high-traffic public-facing apps, the auto-generated API has performance limits; treat it as the admin / collaboration layer, not the production hot path.

Backups

If you connected to an external database, that database is the data — back it up the way you back up Postgres normally. NocoDB's own state (workspaces, views, formulas, API tokens) lives in its internal database (the nocodb Postgres in the compose above); back that up too.