Journal indexDockup / field note
Note / self-host-baserow

How to Self-Host Baserow in 2026: All-in-One Data, URLs and Backups

A practical Baserow self-hosting guide covering Docker, ports, persistent data, TLS, security, backups and the failures that block production use. Step by step.

A Baserow container can be green while the job users care about is broken. For Baserow, that hidden failure is usually that the public URL changes after users have generated share and callback links. This guide treats “create a database and view, import a CSV, edit rows from two sessions and upload a file before restarting the all-in-one stack” as the acceptance test and builds the deployment backward from that result.

Baserow has a specific role in the stack: Airtable-style databases backed by Postgres and Redis. The production question is therefore not whether port 80 answers once, but whether state, dependencies and the public address continue to agree after a restart, update and restore.

What Baserow depends on

Process health and product health are separate for Baserow. Port 80 may answer while the user-facing transaction still fails. The local runtime requirement is sufficient memory for bundled Postgres, Redis, backend and workers. Keep its lifecycle explicit so moving Baserow between hosts does not silently change behavior.

Use this readiness exercise after meaningful configuration changes: create a database and view, import a CSV, edit rows from two sessions and upload a file before restarting the all-in-one stack. Keep expensive external checks out of liveness probes so a provider outage does not cause a restart loop. Capacity work should track bundled Postgres, Redis, Celery workers, row count, import size and simultaneous editors, which is closer to Baserow's real pressure than page requests.

A Docker baseline for Baserow

The following command makes the container boundary visible without pretending to provision every external service.

docker run -d \
  --name baserow \
  --restart unless-stopped \
  -p 127.0.0.1:80:80 \
  -v baserow-data:/baserow/data \
  -e SECRET_KEY=replace-with-a-long-random-value \
  baserow/baserow:latest

Before opening ingress, inspect the resolved environment, mounts and listener. Confirm the local requirement before exposure: sufficient memory for bundled Postgres, Redis, backend and workers. A successful launch ends when you can create a database and view, import a CSV, edit rows from two sessions and upload a file before restarting the all-in-one stack, not when docker ps prints Up.

Domains, proxy headers and port 80

Expose one HTTPS hostname for Baserow; keep raw port 80 private. Set BASEROW_PUBLIC_URL to the exact external origin. This prevents browsers and API clients from learning two competing addresses.

From a clean client, run the known-good transaction and inspect the first failing request. Use the custom-domain guide when DNS or TLS is wrong. Treat “the public URL changes after users have generated share and callback links” as a separate application diagnosis once the route is proven.

Back up the state Baserow cannot recreate

Define recovery point and recovery time for Baserow in terms of the whole /baserow/data tree and periodic logical database exports. Mount /baserow/data before bootstrap, write harmless sample data and replace the container to prove that path is actually persistent. A named volume solves redeploy persistence; it does not solve compromise or server loss.

Build a clean restore environment, use the same pinned application version and prove that tables, views, users, automations and files return from the complete /baserow/data backup. Record commands, ownership fixes and elapsed time. The backup guide is a useful standard: a backup is trusted after restoration, not after upload.

Do not give Baserow the whole host

Threat-model the action Baserow performs, not just its login form. Here the high-risk mistake is using the all-in-one image without a backup plan for its bundled services. Implement this boundary: close registration when appropriate, preserve SECRET_KEY and limit public shared views to intended data.

Generate SECRET_KEY once, keep it out of Git and preserve it with the recovery manifest because changing it can invalidate encrypted or signed application state. Do not solve a permission error by running the container as root or mounting the host broadly. Resource limits also belong to the security design when bundled Postgres, Redis, Celery workers, row count, import size and simultaneous editors can be triggered by users.

Logs that answer the next question

An idle health check says little about Baserow. Watch bundled Postgres, Redis, Celery workers, row count, import size and simultaneous editors, then alert on the symptom users experience: failure of the action “create a database and view, import a CSV, edit rows from two sessions and upload a file before restarting the all-in-one stack”. Keep liveness local and cheap; let readiness report migrations or initialization without causing a restart storm.

The risky upgrade area is that the all-in-one image moves several services together, so database and application migrations need snapshot-based rehearsal. Read release notes, snapshot state, deploy the target version against a restored copy and repeat the acceptance action. If the public URL changes after users have generated share and callback links, correlate the client request with the first relevant application log rather than deleting state or adding redirects blindly.

Five checks stronger than container health

Before real users arrive, make a release worksheet for Baserow. It must name the pinned image, port 80, canonical origin, persistent paths and the owner of sufficient memory for bundled Postgres, Redis, backend and workers. Attach the expected result of this transaction: create a database and view, import a CSV, edit rows from two sessions and upload a file before restarting the all-in-one stack.

Use the worksheet after a normal replacement and after a clean restore. Recovery is accepted only if tables, views, users, automations and files return from the complete /baserow/data backup. Also collect a short resource trace covering bundled Postgres, Redis, Celery workers, row count, import size and simultaneous editors; keep it beside the release so future capacity changes are compared with the same workload.

Include one controlled failure: submit harmless input near the resource or format limit associated with this boundary: the public URL changes after users have generated share and callback links. Confirm Baserow reports the problem at the correct boundary, put the valid condition back and rerun the transaction. This checks error visibility, not merely success, and prevents a healthy-looking interface from concealing a broken worker, callback or database connection.

Attach Baserow to Dockup's lifecycle

Dockup's one-click Baserow deployment should make replacement safe: the route continues to target 80, secrets are not baked into the image and persistent paths return on the new container. The same deployment can run on Dockup compute or an attached machine.

Complete the app-specific work by confirming the local requirement — sufficient memory for bundled Postgres, Redis, backend and workers, applying the canonical public address and running this acceptance check: create a database and view, import a CSV, edit rows from two sessions and upload a file before restarting the all-in-one stack. Add the restore result to the runbook before real users arrive.

Frequently asked questions

What does Baserow need for a production deployment?

Route the Baserow container on port 80 through one HTTPS origin. The local runtime requirement is sufficient memory for bundled Postgres, Redis, backend and workers. Do not call Baserow ready until you can create a database and view, import a CSV, edit rows from two sessions and upload a file before restarting the all-in-one stack.

Which Baserow data belongs in a backup?

Persist /baserow/data and include the whole /baserow/data tree and periodic logical database exports in the same recovery manifest. A clean Baserow restore passes only when tables, views, users, automations and files return from the complete /baserow/data backup.

Does Baserow require HTTPS behind a reverse proxy?

Use HTTPS for the public Baserow origin and keep port 80 on the internal route. Apply the Baserow setting correctly: set BASEROW_PUBLIC_URL to the exact external origin. For Baserow, HTTPS protects credentials or user content in transit and keeps origin-sensitive client behavior consistent.

How should a Baserow upgrade be tested?

Restore current Baserow state into an isolated deployment, apply the candidate version and repeat its acceptance transaction. Pay particular attention because the all-in-one image moves several services together, so database and application migrations need snapshot-based rehearsal. Keep the previous Baserow image until its data-migration and rollback boundary are understood.