Skip to content

How to Deploy Baserow on a VPS

Updated Sep 2026

verified on Ubuntu 26.04 · Sep 2026
We earn commissions when you shop through the links below. Full disclosure →

Self-host Baserow, the open-core Airtable alternative, on your own VPS. One all-in-one container behind Caddy, with the backup command that captures everything.

Before you start
  • A VPS with at least 2 GB RAM (the all-in-one container idles around 1.2 GB)
  • A fresh Ubuntu 24.04 or 26.04 server with root/sudo SSH access
  • A domain you can point at the server
  • Docker Engine + Compose installed (see the base guide below)
Need a box for this guide? Kamatera's free tier lets you spin one up now.Start free on Kamatera → (opens in new tab)

What Baserow is

Baserow is an open-core no-code database built on Django and PostgreSQL. Your data sits in tables that look like spreadsheets. Every table gets a REST API that documents itself. The same install also includes an application builder, dashboards and automations. It is licensed MIT, with premium features sold on top.

Most readers are choosing between it and NocoDB. NocoDB vs Baserow goes through the differences. In deployment terms, the main one is that Baserow ships as one all-in-one image. The Baserow backend, the web frontend, PostgreSQL, Redis, the Celery workers and an internal Caddy all run in a single container with a single data volume. That makes it one of the easiest stateful apps on this site to run and back up.

Server sizing

On our test box (GCP e2-standard-2, Ubuntu 26.04, Docker), the all-in-one container idled at about 1,167 MB of RAM and used about 2.3 GB of disk. The catalog's minimum is 2 GB RAM:

  • 2 GB RAM / 1–2 vCPU: one person or a small team. Add swap as a safety margin.
  • 4 GB RAM / 2 vCPU: the comfortable choice. Imports, exports and snapshots run on background workers inside the container and need headroom.
  • Disk: 20–40 GB. Uploaded files are stored in the data volume unless you configure S3-compatible storage.

If memory is tight, upstream documents a smaller mode. Setting BASEROW_RUN_MINIMAL=yes together with BASEROW_AMOUNT_OF_WORKERS=1 starts fewer internal processes. The cost is that slow background jobs can then hold up real-time updates.

Prepare the server

This guide assumes Docker Engine and the Compose plugin are installed. If not, work through Docker & Compose on Ubuntu first. Open SSH and the web ports:

sudo ufw allow OpenSSH
sudo ufw allow 80
sudo ufw allow 443
sudo ufw --force enable
sudo ufw status verbose

Baserow's own docs point out a trap here. Ports that Docker publishes on 0.0.0.0 bypass ufw, so the firewall rules above would not protect them. The install below publishes Baserow on 127.0.0.1 only, which avoids the problem.

Where to host itaffiliate disclosure
Hetzner Cloudrun it on
2 vCPU · 4 GB RAM · 80 GB SSD · $23.59/mo
Get Hetzner Cloud (opens in new tab)
Kamaterafree trial
1 vCPU · 1 GB RAM · 20 GB SSD · $4.00/mo
Start free on Kamatera → (opens in new tab)
DigitalOceanalso works on
1 vCPU · 1 GB RAM · 25 GB SSD · $6.00/mo
Deploy on DigitalOcean → (opens in new tab)

Paid link — we earn a commission if you shop through it.

Install Baserow (Docker Compose)

Upstream documents three ways to run the image: a quick-start docker run, automatic HTTPS through the embedded Caddy, and "behind a reverse proxy already handling SSL". This guide uses the third, written as a Compose file. Your host's Caddy handles TLS, and Baserow listens on a loopback port.

mkdir -p ~/baserow && cd ~/baserow
cat > docker-compose.yml <<'YAML'
services:
  baserow:
    image: baserow/baserow:2.3.4
    container_name: baserow
    restart: unless-stopped
    environment:
      # Must match the address you type in the browser, scheme included.
      BASEROW_PUBLIC_URL: https://baserow.example.com
    volumes:
      - baserow_data:/baserow/data
    ports:
      # Loopback only: Caddy on the host is the public entry point.
      - "127.0.0.1:8080:80"

volumes:
  baserow_data:
YAML

Replace baserow.example.com with your hostname. BASEROW_PUBLIC_URL is the setting that matters most. Baserow treats any other address as a published application, so a mismatch shows up as confusing 404s and broken links, not as a clear error.

Start it:

cd ~/baserow
docker compose up -d

The first start migrates the internal database and can take a few minutes. Wait until the container reports healthy:

cd ~/baserow
for i in $(seq 1 60); do
  status=$(docker inspect -f '{{.State.Health.Status}}' baserow 2>/dev/null)
  echo "health: $status"; [ "$status" = "healthy" ] && break; sleep 10
done
docker compose ps

Watch progress with docker compose logs -f baserow if you like. It runs forever, so press Ctrl+C to leave it.

The container generates its own internal secrets (the Django secret key and the database password) on first start and keeps them in /baserow/data. That means the data volume is the whole installation, secrets included. Back it up as a unit.

HTTPS + domain

Point an A record for baserow.example.com at the server, then proxy to the loopback port with Caddy. The steps are in Automatic HTTPS with Caddy:

baserow.example.com {
    reverse_proxy 127.0.0.1:8080
}

Caddy passes WebSocket upgrades through without extra configuration. Baserow needs them for real-time collaboration. If you use a different proxy, make sure it forwards the Upgrade and Connection headers.

You could instead let Baserow's embedded Caddy get certificates by itself (BASEROW_CADDY_ADDRESSES=:443 and publishing ports 80 and 443). That is the option on the Baserow page. It is fine on a box that runs only Baserow. A host-level Caddy is the better choice once you run more than one app.

First login and securing it

Open https://baserow.example.com and create your account straight away. On a fresh instance, the first account to sign up gets staff (admin) rights. Baserow sets that when there are no other users. After that:

  • Decide who may sign up. The admin settings page controls whether new accounts can be created. Turn sign-ups off if the instance is private, and invite people into workspaces instead.
  • Keep port 8080 on loopback. Publishing it on 0.0.0.0 would bypass ufw, as described above.
  • Set up SMTP if you want invitations and password resets to arrive. The email variables are listed in Baserow's configuration reference.
  • Consider an external PostgreSQL for production. Upstream recommends it. The all-in-one image accepts DATABASE_URL=postgresql://user:pwd@host:port/db, and REDIS_URL for Redis.

Backups

Everything, including PostgreSQL, uploaded files and the generated secrets, is in the baserow_data volume. Upstream's full backup is a tar of that volume with Baserow stopped. Compose prefixes the volume with the project directory, so check the real name with docker volume ls:

cd ~/baserow
mkdir -p backups
docker compose stop
docker run --rm -v baserow_baserow_data:/baserow/data:ro -v "$PWD/backups":/backup ubuntu \
  tar czf /backup/baserow-data-$(date +%F).tar.gz /baserow/data
docker compose start
ls -lh backups/

Upstream also documents a database-only backup through the image's own CLI. It also needs the instance stopped. Write the file into the volume's own backups folder: the CLI runs as Baserow's internal user, which cannot write to a host directory owned by you. Then copy it out with docker cp, which works on a stopped container too:

cd ~/baserow
docker compose stop
docker run --rm -v baserow_baserow_data:/baserow/data baserow/baserow:2.3.4 \
  backend-cmd-with-db backup -f /baserow/data/backups/baserow-db-$(date +%F).tar.gz
docker cp baserow:/baserow/data/backups/baserow-db-$(date +%F).tar.gz backups/
docker compose start
ls -lh backups/

To restore, run the matching backend-cmd-with-db restore -f … against a new, empty data volume. For the full tar, unpack it into a fresh volume and point the Compose file at that volume. Copy backups/ off the server. A backup that only exists on the machine it protects doesn't help when that machine fails.

Upgrades

Baserow upgrades itself on startup. Upstream's procedure is: back up, stop, change the image tag, start, and watch the logs.

cd ~/baserow
docker compose pull
docker compose up -d

To move to a new release, change baserow/baserow:2.3.4 in docker-compose.yml to the new tag first, then run the two commands above. Take the full volume backup before every version change. A pinned tag means nothing changes until you decide it should.

Troubleshooting

Links and pages 404, or the app says the domain isn't found. BASEROW_PUBLIC_URL doesn't match the address in the browser. Check the scheme, the host and any port. Fix it and run docker compose up -d.

The first start seems stuck, or shows unhealthy. Initial migrations take a while on a small box. In our test the container needed about four minutes and reported unhealthy for a short time before it turned healthy. Follow docker compose logs -f baserow and give it time before you intervene.

Real-time updates don't appear until you refresh. WebSocket upgrades are being removed between the browser and Baserow. Caddy passes them by default, so look at any CDN or custom proxy in the path.

The box runs out of memory during an import. The container idles around 1.2 GB and background jobs push it higher. Move to 4 GB, add swap, or try BASEROW_RUN_MINIMAL=yes with BASEROW_AMOUNT_OF_WORKERS=1.

Verification + next steps

You're done when:

  • https://baserow.example.com loads over a valid certificate;
  • your account is the staff admin and sign-ups are set the way you want;
  • a test table survives docker compose restart;
  • a dated volume backup exists somewhere other than this server.

From there, try the auto-generated REST API with a database token, or set up the application builder on top of your tables. For a comparison, see NocoDB on a VPS. For ranked hosts, see Best VPS for databases.

Next steps

How to self-host Baserow →More self-hosted no-code database tools →Automatic HTTPS with Caddy →Run Claude Code with Ollama on Your Own VPS →Deploy Coolify on a VPS →How to Deploy Actual Budget on a VPS →How to Deploy AnythingLLM on a VPS →How to Deploy Appwrite on a VPS →How to Deploy Audiobookshelf on a VPS →How to Deploy Authelia on a VPS →How to Deploy authentik on a VPS →How to Deploy Beszel on a VPS →How to Deploy Bitwarden on a VPS →How to Deploy BookStack on a VPS →How to Deploy CapRover on a VPS →How to Deploy Checkmate on a VPS →How to Deploy Directus on a VPS →How to Deploy docker-mailserver on a VPS →How to Deploy Docmost on a VPS →How to Deploy Dokku on a VPS →How to Deploy Dokploy on a VPS →How to Deploy Firefly III on a VPS →How to Deploy Forgejo on a VPS →How to Deploy Gatus on a VPS →How to Deploy Ghostfolio on a VPS →How to Deploy Gitea on a VPS →How to Deploy GitLab on a VPS →How to Deploy GlitchTip on a VPS →How to Deploy Grafana on a VPS →How to Deploy Graylog on a VPS →How to Deploy Headscale on a VPS →How to Deploy Healthchecks on a VPS →How to Deploy Home Assistant on a VPS →How to Deploy Immich on a VPS →How to Deploy Jan on a VPS →How to Deploy Jellyfin on a VPS →How to Deploy Karakeep on a VPS →How to Deploy Keycloak on a VPS →How to Deploy Leantime on a VPS →How to Deploy LibreChat on a VPS →How to Deploy Linkwarden on a VPS →How to Deploy LocalAI on a VPS →How to Deploy Mailcow on a VPS →How to Deploy Mailu on a VPS →How to Deploy Matomo on a VPS →How to Deploy Mattermost on a VPS →How to Deploy Meilisearch on a VPS →How to Deploy Memos on a VPS →How to Deploy n8n on a VPS →How to Deploy Navidrome on a VPS →How to Deploy NetBird on a VPS →How to Deploy Netdata on a VPS →How to Deploy Nextcloud on a VPS →How to Deploy Next.js to a VPS →How to Deploy Nginx Proxy Manager on a VPS →How to Deploy NocoDB on a VPS →How to Deploy ntfy on a VPS →How to Deploy Ollama on a VPS →How to Deploy Open WebUI on a VPS →How to Deploy OpenHands on a VPS →How to Deploy OpenObserve on a VPS →How to Deploy OpenProject on a VPS →How to Deploy Outline on a VPS →How to Deploy Pangolin on a VPS →How to Deploy Paperless-ngx on a VPS →How to Deploy Passbolt on a VPS →How to Deploy Plane on a VPS →How to Deploy Plausible Analytics on a VPS →How to Deploy Pocket ID on a VPS →How to Deploy PocketBase on a VPS →How to Deploy Prometheus on a VPS →How to Deploy Psono on a VPS →How to Deploy Radarr on a VPS →How to Deploy Rocket.Chat on a VPS →How to Deploy SigNoz on a VPS →How to Deploy Sonarr on a VPS →How to Deploy Stalwart on a VPS →How to Deploy Stirling-PDF on a VPS →How to Deploy Supabase on a VPS →How to Deploy Synapse on a VPS →How to Deploy Taiga on a VPS →How to Deploy TeamPass on a VPS →How to Deploy Tinyauth on a VPS →How to Deploy Traefik on a VPS →How to Deploy Trilium on a VPS →How to Deploy Twenty CRM on a VPS →How to Deploy Umami on a VPS →How to Deploy Uptime Kuma on a VPS →How to Deploy Vaultwarden on a VPS →How to Deploy Vikunja on a VPS →How to Deploy wg-easy on a VPS →How to Deploy Wiki.js on a VPS →How to Deploy Zabbix on a VPS →How to Deploy Zitadel on a VPS →How to Deploy Zulip on a VPS →Docker & Compose on Ubuntu 26.04 →Building AI Workflows with n8n →Install Open WebUI with Ollama →Adding AI-Powered Insights to Plausible Analytics →Building AI-Powered Apps with Supabase and pgvector →

We use analytics cookies (Google Analytics, PostHog) to see which guides are useful. No ad networks, no cross-site tracking. See our privacy policy.