Skip to main content

How to Self-Host Baserow: Open Source Airtable Alternative 2026

·OSSAlt Team
baserowairtable-alternativeself-hostingdockerdatabase

How to Self-Host Baserow: The Open Source Airtable Alternative in 2026

TL;DR

Airtable charges $20–$45/user/month and restricts records per base. Baserow is the open source alternative — a no-code database platform with a spreadsheet-like UI, built on PostgreSQL, self-hostable for the price of a VPS. It supports formula fields, gallery/kanban/calendar/grid views, file attachments, row-level permissions, and a full REST API that auto-generates from your table schema. The self-hosted version is free forever with no record limits. The community is active with 9,500+ GitHub stars and the project is actively maintained by a commercial company (Baserow BV) that monetizes through their hosted cloud offering, ensuring sustained development.

Key Takeaways

  • Free self-hosted: unlimited rows, tables, and workspaces on self-hosted instances
  • Multiple views: Grid, Gallery, Kanban, Calendar, and Form views on every table
  • Auto-generated REST API: every table gets a full CRUD API instantly, with OpenAPI spec
  • Formula fields: 100+ functions, cell references, and computed values
  • Real-time collaboration: multiple users editing simultaneously, no page refreshes
  • GitHub stars: 9,500+ with active weekly releases
  • License: MIT (open source) for the core; premium features require a license key

Why Baserow Over NocoDB or Grist?

FeatureBaserowNocoDBGrist
LicenseMITAGPLAGPL
Row limits (self-hosted)NoneNoneNone
Built onPostgreSQLMySQL/PostgreSQL/SQLitePython/SQLite
Formula engine100+ functionsBasicAdvanced (Python-like)
Kanban view
Calendar view
Gallery view
Form builderLimited
Real-time collab
API qualityExcellent (OpenAPI)GoodGood

Baserow's differentiator is polish and UI quality — it feels the closest to the Airtable experience. NocoDB is stronger if you need to connect to an existing database (MySQL, MSSQL). Grist excels at Python-style formulas and spreadsheet power users. Baserow wins for teams wanting a clean Airtable drop-in.


Self-Hosting with Docker Compose

Prerequisites

  • Docker and Docker Compose
  • 2GB RAM minimum (4GB recommended for teams)
  • Domain with SSL (for production)

docker-compose.yml

version: "3.4"

services:
  # Caddy for reverse proxy + automatic TLS
  caddy:
    image: caddy:2
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile
      - caddy_data:/data
      - caddy_config:/config

  backend:
    image: baserow/backend:latest
    restart: unless-stopped
    environment:
      DATABASE_HOST: db
      DATABASE_NAME: baserow
      DATABASE_USER: baserow
      DATABASE_PASSWORD: ${DATABASE_PASSWORD}
      DATABASE_PORT: 5432
      REDIS_URL: redis://redis:6379
      SECRET_KEY: ${SECRET_KEY}
      BASEROW_PUBLIC_URL: https://baserow.yourdomain.com
      EMAIL_SMTP_HOST: ${EMAIL_HOST}
      EMAIL_SMTP_PORT: 587
      EMAIL_SMTP_USER: ${EMAIL_USER}
      EMAIL_SMTP_PASSWORD: ${EMAIL_PASSWORD}
      EMAIL_SMTP_USE_TLS: "true"
      FROM_EMAIL: baserow@yourdomain.com
    volumes:
      - baserow_media:/baserow/media
    depends_on:
      - db
      - redis

  web-frontend:
    image: baserow/web-frontend:latest
    restart: unless-stopped
    environment:
      BASEROW_PUBLIC_URL: https://baserow.yourdomain.com
      NUXT_PUBLIC_BASEROW_URL: https://baserow.yourdomain.com
    depends_on:
      - backend

  celery:
    image: baserow/backend:latest
    restart: unless-stopped
    command: celery-worker
    environment:
      DATABASE_HOST: db
      DATABASE_NAME: baserow
      DATABASE_USER: baserow
      DATABASE_PASSWORD: ${DATABASE_PASSWORD}
      DATABASE_PORT: 5432
      REDIS_URL: redis://redis:6379
      SECRET_KEY: ${SECRET_KEY}
    depends_on:
      - db
      - redis

  db:
    image: postgres:15
    restart: unless-stopped
    environment:
      POSTGRES_DB: baserow
      POSTGRES_USER: baserow
      POSTGRES_PASSWORD: ${DATABASE_PASSWORD}
    volumes:
      - postgres_data:/var/lib/postgresql/data

  redis:
    image: redis:7-alpine
    restart: unless-stopped
    volumes:
      - redis_data:/data

volumes:
  postgres_data:
  baserow_media:
  caddy_data:
  caddy_config:
  redis_data:

.env File

# .env
DATABASE_PASSWORD=change-this-strong-database-password
SECRET_KEY=change-this-secret-key-at-least-32-chars
EMAIL_HOST=smtp.youremail.com
EMAIL_USER=baserow@yourdomain.com
EMAIL_PASSWORD=your-email-password

Generate the secret key:

openssl rand -hex 32

Caddyfile for Automatic TLS

baserow.yourdomain.com {
    # Frontend
    reverse_proxy /api/* backend:8000
    reverse_proxy /ws/* backend:8000
    reverse_proxy /media/* backend:8000
    reverse_proxy web-frontend:3000
}

Start Baserow

docker compose up -d

# Check status
docker compose ps

# Access at https://baserow.yourdomain.com
# Create your admin account on first visit

The first user to register becomes the admin. Baserow initializes the PostgreSQL database automatically on first startup.


Creating Your First Database

Once logged in:

Create workspace → "My Team"
Create database → "Project Tracker"
Create table → "Tasks"

Baserow auto-creates a grid view with default fields. Add fields by clicking the + button:

Field TypeUse Case
TextNames, descriptions, notes
Long textDetailed descriptions, markdown
NumberQuantities, prices, scores
DateDeadlines, created dates
Single selectStatus (Todo, In Progress, Done)
Multiple selectTags, categories
CheckboxBoolean flags
FileAttachments, images, PDFs
URLLinks to external resources
FormulaComputed values from other fields
Link to tableRelationships between tables
LookupPull data from linked records
CountCount linked records
RollupAggregate linked record values (sum, avg, min, max)

Each table can have multiple views — the same underlying data, displayed differently.

Kanban View

Perfect for task management:

Create view → Kanban
Group by: Status field (Todo, In Progress, Review, Done)

Cards show up in columns by status. Drag to move between stages. Click a card to open the full record editor.

Calendar View

For deadline tracking:

Create view → Calendar
Date field: Due Date

Records appear on their due date. Drag to reschedule. Month, week, and day views available.

For image-heavy data (product catalogs, portfolios):

Create view → Gallery
Cover image: Photo field
Visible fields: Name, Price, Category

Form View

Generate embeddable forms that create new records:

Create view → Form
→ Customize: hide internal fields, set required fields
→ Share: public link or embed code
→ Submissions appear as new rows in the grid

Forms work without login — share with clients to collect data without exposing your database.


The Auto-Generated REST API

Every Baserow table gets a full CRUD REST API automatically. No configuration needed.

Get Your API Token

Settings → API Tokens → Create Token
Name: My Integration
Permissions: Read, Create, Update, Delete
Database: Project Tracker

API Endpoints

# List all rows in a table
curl -X GET "https://baserow.yourdomain.com/api/database/rows/table/TABLE_ID/?user_field_names=true" \
  -H "Authorization: Token YOUR_API_TOKEN"

# Response:
{
  "count": 150,
  "next": "...?page=2",
  "results": [
    {
      "id": 1,
      "Name": "Build landing page",
      "Status": "In Progress",
      "Due Date": "2026-03-15",
      "Assignee": "Alice"
    },
    ...
  ]
}

# Create a new row
curl -X POST "https://baserow.yourdomain.com/api/database/rows/table/TABLE_ID/?user_field_names=true" \
  -H "Authorization: Token YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "Name": "New task",
    "Status": "Todo",
    "Due Date": "2026-03-20"
  }'

# Update a row
curl -X PATCH "https://baserow.yourdomain.com/api/database/rows/table/TABLE_ID/ROW_ID/?user_field_names=true" \
  -H "Authorization: Token YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "Status": "Done" }'

# Filter rows
curl "https://baserow.yourdomain.com/api/database/rows/table/TABLE_ID/?user_field_names=true&filters=\
[{\"field\":\"Status\",\"type\":\"equal\",\"value\":\"In Progress\"}]" \
  -H "Authorization: Token YOUR_API_TOKEN"

Baserow also exposes an OpenAPI spec at /api/schema/ — import it into Postman or Insomnia for full API exploration.


Automations: Webhooks and Zapier

Baserow supports webhooks on row events — connect to any external service:

Table → Settings → Webhooks → Create Webhook
Name: Notify Slack on Task Completion
URL: https://hooks.slack.com/services/YOUR/SLACK/WEBHOOK
Events: Row updated
Request body:
{
  "text": "Task completed: {{ row.Name }} ({{ row.Status }})"
}

Webhooks fire when rows are created, updated, or deleted. Combine with:

  • Zapier: Baserow has a native Zapier integration — trigger zaps on new rows, update rows from other apps
  • Make (Integromat): Visual workflow builder, native Baserow module
  • n8n: Open source automation — Baserow HTTP node for custom workflows

Formula Field Examples

Baserow's formula engine supports 100+ functions:

# Days until due date
toDate(field('Due Date'), 'YYYY-MM-DD') - now()

# Status badge with conditional logic
if(field('Status') = 'Overdue', '🔴 URGENT',
   if(field('Status') = 'In Progress', '🟡 Active', '🟢 OK'))

# Concatenate first and last name
concat(field('First Name'), ' ', field('Last Name'))

# Parse URL domain
regex_extract(field('Website'), 'https?://([^/]+)', 1)

# Calculate project budget remaining
field('Budget') - field('Spent')

# Text length check
if(length(field('Description')) < 50,
   'Too short - please expand',
   'Good')

Formulas reference other fields with field('Field Name') and can chain functions. The formula editor provides autocomplete and real-time error checking.


Team Collaboration and Permissions

Baserow's premium tier adds row-level permissions; the free community tier has workspace-level roles:

Workspace Roles

RolePermissions
AdminFull access: create databases, manage members, delete workspace
BuilderCreate and edit tables, views, fields; cannot manage members
ViewerRead-only access to all databases in the workspace
EditorRead + write rows, cannot modify table structure

Inviting Team Members

Workspace Settings → Members → Invite by email
Role: Builder
→ User receives email invitation, creates account, gets instant access

For external collaborators who don't need full database access, use Form views — they submit data without seeing the underlying table.


Backup and Restore

#!/bin/bash
# backup-baserow.sh
DATE=$(date +%Y%m%d_%H%M)
BACKUP_DIR=/backups/baserow/$DATE
mkdir -p $BACKUP_DIR

# PostgreSQL backup
docker compose exec -T db pg_dump \
  -U baserow baserow \
  | gzip > $BACKUP_DIR/baserow_db.sql.gz

# Media files (attachments, images)
tar -czf $BACKUP_DIR/baserow_media.tar.gz \
  -C /var/lib/docker/volumes baserow_baserow_media

# Upload to S3-compatible storage
rclone copy $BACKUP_DIR b2:my-backups/baserow/$DATE

# Keep only last 14 days locally
find /backups/baserow -type d -mtime +14 -exec rm -rf {} +

echo "Baserow backup complete: $DATE"

Restore

# Restore database
gunzip < /backups/baserow/20260301/baserow_db.sql.gz | \
  docker compose exec -T db psql -U baserow baserow

# Restore media
tar -xzf /backups/baserow/20260301/baserow_media.tar.gz \
  -C /var/lib/docker/volumes

Upgrading Baserow

cd /opt/baserow

# Pull latest images
docker compose pull

# Restart services
docker compose up -d

# Database migrations run automatically on startup
# Check logs for any migration issues
docker compose logs backend | grep -i "migration"

Baserow uses Django database migrations — they run automatically when the backend container starts. Always back up before major version upgrades.


Connecting to an Existing PostgreSQL Database

One of Baserow's most powerful features is connecting to an existing database — making your production data accessible through a spreadsheet UI without writing code:

Settings → Database Connections → Connect to External Database
Type: PostgreSQL
Host: your-prod-db.internal
Port: 5432
Database: your_database
Username: baserow_readonly    (use a read-only user!)
Password: ***
Schema: public

Baserow reads your table schema and displays data in the grid UI. You can create views, filter, sort, and export — without touching SQL. Important: Use a read-only database user for this connection to prevent accidental data modification.


Cost Comparison: Airtable vs Baserow Self-Hosted

PlanAirtableBaserow Self-Hosted
Free tier1,000 rows/baseUnlimited
Team (5 users)$100/month~$10/month (VPS)
Business (25 users)$1,125/month~$20/month (VPS)
Record limitPer-planNone
Automations25K runs/monthUnlimited (webhooks)
Data locationAirtable's cloudYour server

For a 10-person team, switching from Airtable Business to self-hosted Baserow saves over $800/month. The trade-off is operational responsibility — updates, backups, and uptime are yours to manage.


Methodology

  • GitHub data from github.com/bram2w/baserow, March 2026
  • Pricing comparisons from Airtable pricing page, March 2026
  • Setup guide based on Baserow official Docker documentation (baserow.io/docs/installation/install-with-docker)
  • Version: Baserow 1.x (check GitHub releases for latest)

Compare open source Airtable alternatives on OSSAlt — self-hosting difficulty, feature coverage, and community health.

Related: NocoDB vs Baserow vs Grist: Open Source Airtable Alternatives 2026 · How to Self-Host NocoDB: Connect to Your Existing Database 2026 · Best Open Source No-Code Database Tools in 2026

Comments