Self-Hosting NocoDB with Docker Compose

What Is NocoDB?

NocoDB turns any database into a smart spreadsheet interface. Think Airtable, but running on your own server with your own data. It connects to PostgreSQL, MySQL, SQLite, or SQL Server and gives you views, forms, automations, and a REST API — all without writing code. It replaces Airtable and similar no-code database tools.

Prerequisites

  • A Linux server (Ubuntu 22.04+ recommended)
  • Docker and Docker Compose installed (guide)
  • 2 GB of free RAM (1 GB minimum for small deployments)
  • 5 GB of free disk space
  • A domain name (optional, for remote access)

Docker Compose Configuration

This setup uses PostgreSQL as the database backend, which is recommended for production. NocoDB can use SQLite by default, but PostgreSQL handles concurrent users and larger datasets better.

Create a docker-compose.yml:

services:
  nocodb:
    image: nocodb/nocodb:0.301.2
    container_name: nocodb
    depends_on:
      db:
        condition: service_healthy
    environment:
      NC_DB: "pg://db:5432?u=nocodb&p=changeme_strong_password&d=nocodb"  # CHANGE password
      NC_AUTH_JWT_SECRET: "changeme_generate_with_openssl_rand"  # CHANGE — run: openssl rand -base64 32
      NC_PUBLIC_URL: "http://localhost:8080"  # Set to your actual URL for email links and API docs
      NC_DISABLE_TELE: "true"                 # Disable anonymous telemetry
      NC_DISABLE_ERR_REPORTS: "true"          # Disable Sentry error reporting
    volumes:
      - nocodb-data:/usr/app/data   # Application data, uploads, metadata
    ports:
      - "8080:8080"                 # Web UI and API
    restart: unless-stopped

  db:
    image: postgres:16.6
    container_name: nocodb-db
    environment:
      POSTGRES_DB: nocodb
      POSTGRES_USER: nocodb
      POSTGRES_PASSWORD: changeme_strong_password  # CHANGE — must match NC_DB above
    volumes:
      - nocodb-db-data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U nocodb"]
      interval: 10s
      timeout: 5s
      retries: 10
    restart: unless-stopped

volumes:
  nocodb-data:
  nocodb-db-data:

Before starting: Generate a JWT secret and set a strong database password:

# Generate JWT secret
openssl rand -base64 32

# Generate database password (avoid special characters — NocoDB limitation)
openssl rand -hex 16

Replace both changeme values in the compose file, and update NC_PUBLIC_URL to your actual access URL.

Start the stack:

docker compose up -d

Initial Setup

  1. Open http://your-server-ip:8080 in your browser
  2. Create your admin account (email + password)
  3. You’ll land on the dashboard — create your first base (NocoDB’s term for a database project)
  4. Choose “Create from scratch” or import from Airtable (NocoDB has a built-in Airtable importer)

Feature Overview

FeatureDetails
ViewsGrid, Gallery, Kanban, Form, Calendar
Field types22+ including Links, Lookup, Rollup, Formula, Barcode, QR Code
APIAuto-generated REST API for every table
AutomationsWebhook triggers, email notifications, Slack/Discord/Teams integration
RolesOwner, Creator, Editor, Commenter, Viewer
Import/ExportCSV, Excel, Airtable, JSON
Shared viewsPublic links with optional password protection
Audit logFull change history per record

Configuration

Connect to an Existing Database

NocoDB can sit on top of an existing PostgreSQL or MySQL database. Instead of creating tables from scratch, it reads your existing schema and provides a spreadsheet interface:

NC_DB: "pg://your-existing-db-host:5432?u=readonly_user&p=password&d=your_database"

This is NocoDB’s killer feature — turn any legacy database into a collaborative spreadsheet without migrating data.

Email Notifications

Add SMTP configuration to enable email notifications and invites:

environment:
  NC_SMTP_FROM: "[email protected]"
  NC_SMTP_HOST: "smtp.example.com"
  NC_SMTP_PORT: "587"
  NC_SMTP_USERNAME: "[email protected]"
  NC_SMTP_PASSWORD: "smtp-password"
  NC_SMTP_SECURE: "true"

Increase Upload Size

The default upload limit is 20 MB. Increase it for larger file attachments:

environment:
  NC_ATTACHMENT_FIELD_SIZE: 52428800  # 50 MB in bytes

Redis for Caching (Optional)

For better performance with multiple concurrent users, add Redis:

services:
  redis:
    image: redis:7.4
    container_name: nocodb-redis
    restart: unless-stopped
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 10s
      timeout: 5s
      retries: 5

  nocodb:
    environment:
      NC_REDIS_URL: "redis://redis:6379"
    depends_on:
      redis:
        condition: service_healthy

Reverse Proxy

Put NocoDB behind a reverse proxy for HTTPS. Caddy example:

nocodb.example.com {
    reverse_proxy localhost:8080
}

See our Reverse Proxy Guide for Nginx Proxy Manager and Traefik configurations.

Backup

Back up both the PostgreSQL database and NocoDB’s data volume:

# Database dump
docker exec nocodb-db pg_dump -U nocodb nocodb > nocodb-backup-$(date +%Y%m%d).sql

# Application data (uploads, metadata)
docker run --rm -v nocodb-data:/data -v $(pwd):/backup \
  alpine tar czf /backup/nocodb-data-$(date +%Y%m%d).tar.gz /data

Restore from backup:

# Restore database
cat nocodb-backup-20260224.sql | docker exec -i nocodb-db psql -U nocodb nocodb

# Restore data volume
docker run --rm -v nocodb-data:/data -v $(pwd):/backup \
  alpine tar xzf /backup/nocodb-data-20260224.tar.gz -C /

See our Backup Strategy Guide for automated approaches.

Troubleshooting

”Invalid JWT Secret” After Container Recreation

Symptom: All users are logged out after recreating the NocoDB container. API tokens stop working.

Fix: You didn’t set NC_AUTH_JWT_SECRET explicitly. NocoDB auto-generates a new secret on every container start if one isn’t provided. Set it permanently in your compose file and redeploy:

echo "NC_AUTH_JWT_SECRET=$(openssl rand -base64 32)" >> .env
docker compose up -d

Database Connection Refused

Symptom: NocoDB logs show “ECONNREFUSED” or “connection refused” for PostgreSQL.

Fix: The depends_on with service_healthy should prevent this, but if PostgreSQL is slow to start:

# Check if PostgreSQL is running
docker logs nocodb-db

# Restart NocoDB after PostgreSQL is healthy
docker compose restart nocodb

Airtable Import Fails

Symptom: Import stalls or returns errors for large Airtable bases.

Fix: Large imports (100+ tables or 100K+ records) may time out. Import in smaller batches by selecting fewer tables at a time. Also ensure NC_ATTACHMENT_FIELD_SIZE is large enough for any file attachments in the Airtable base.

Permission Errors on Volume

Symptom: NocoDB container fails to start with “EACCES” permission errors.

Fix: The NocoDB container runs as root by default, so this is rare. If using a bind mount instead of a named volume:

sudo chown -R 999:999 ./nocodb-data

Resource Requirements

MetricValue
RAM (idle)~200 MB (NocoDB) + ~100 MB (PostgreSQL)
RAM (active, 10+ users)500 MB - 1 GB
CPULow (spikes during imports and API calls)
Disk~300 MB for application + database storage

Verdict

NocoDB is the best self-hosted Airtable alternative for most people. The ability to connect to existing databases and instantly get a spreadsheet interface is genuinely useful — it’s not just an Airtable clone, it’s a database UI tool. The Docker setup is straightforward, resource usage is light, and the auto-generated REST API means you can build applications on top of it without writing backend code.

If you need more advanced automations or a more polished UI, check out Baserow as an alternative. But for most use cases, NocoDB delivers everything Airtable does without the per-seat pricing.