Skip to main content

Self-Host Budibase: Open Source Retool Alternative 2026

·OSSAlt Team
budibaseinternal-toolsself-hostingdockerlow-code
Share:

How to Self-Host Budibase: The Open Source Retool Alternative in 2026

TL;DR

Retool charges $10–$50/user/month for internal tools. Budibase is the open source alternative — a low-code platform for building data-backed apps, CRUD interfaces, and internal dashboards, self-hosted for the price of a VPS. It connects to PostgreSQL, MySQL, MongoDB, REST APIs, Airtable, S3, and more. Unlike Retool which runs in Retool's cloud by default, Budibase can run entirely on your infrastructure — your data never leaves your servers. The self-hosted community edition is free; the Business tier ($125/month for 25 users) adds advanced RBAC and SSO.

Key Takeaways

  • Open source Retool alternative: drag-and-drop UI builder for internal tools, connected to your databases
  • Self-hostable: Docker Compose or Kubernetes, data stays on your infra
  • Data sources: PostgreSQL, MySQL, MSSQL, MongoDB, CouchDB, Oracle, Elasticsearch, Redis, S3, REST APIs, GraphQL, Google Sheets
  • Automation: built-in workflow engine (cron, webhooks, database triggers)
  • RBAC: role-based access control — not just read/write but per-table, per-row policies
  • GitHub stars: 22,000+ (one of the most-starred internal tools projects)
  • License: GPL v3 (community) / commercial (premium features)

Why Budibase Over AppSmith or ToolJet?

FeatureBudibaseAppSmithToolJet
Built-in DBCouchDB-based BudiBase DBPostgreSQL
Automation/Workflows✅ built-inLimited
Public apps
Self-host difficultyEasyEasyEasy
UI Components~50~45~45
Best forFull-stack internal appsData-heavy dashboardsAutomation-heavy tools

Budibase's differentiator is its built-in database (BudiBase DB, backed by CouchDB) — you can build full CRUD apps without connecting an external database. Combined with its automation engine, it's the most "complete" self-hosted option for building internal tools from scratch.


Self-Hosting with Docker Compose

Prerequisites

  • Docker and Docker Compose
  • 2GB RAM minimum (4GB recommended)
  • Domain with DNS pointing to your server (for production)

docker-compose.yml

version: "3"

services:
  minio-service:
    container_name: budi-minio
    image: minio/minio
    volumes:
      - minio_data:/data
    environment:
      MINIO_ACCESS_KEY: ${MINIO_ACCESS_KEY}
      MINIO_SECRET_KEY: ${MINIO_SECRET_KEY}
    command: server /data --console-address ":9001"
    restart: unless-stopped

  couch-init:
    container_name: budibase-couchdb-init
    image: ibmcom/couchdb3
    environment:
      COUCHDB_USER: ${COUCHDB_USER}
      COUCHDB_PASSWORD: ${COUCHDB_PASSWORD}
    command: curl -X PUT http://${COUCHDB_USER}:${COUCHDB_PASSWORD}@couchdb-service:5984/_users
    depends_on:
      - couchdb-service

  couchdb-service:
    container_name: budibase-couchdb
    image: budibase/couchdb
    environment:
      COUCHDB_USER: ${COUCHDB_USER}
      COUCHDB_PASSWORD: ${COUCHDB_PASSWORD}
    volumes:
      - couchdb_data:/opt/couchdb/data
    restart: unless-stopped

  redis-service:
    container_name: budibase-redis
    image: redis
    command: redis-server --requirepass ${REDIS_PASSWORD}
    volumes:
      - redis_data:/data
    restart: unless-stopped

  app-service:
    container_name: budibase-app
    image: budibase/apps:latest
    environment:
      SELF_HOSTED: 1
      COUCH_DB_URL: http://${COUCHDB_USER}:${COUCHDB_PASSWORD}@couchdb-service:5984
      REDIS_URL: redis-service:6379
      REDIS_PASSWORD: ${REDIS_PASSWORD}
      MINIO_URL: http://minio-service:9000
      MINIO_ACCESS_KEY: ${MINIO_ACCESS_KEY}
      MINIO_SECRET_KEY: ${MINIO_SECRET_KEY}
      JWT_SECRET: ${JWT_SECRET}
      APP_PORT: 4002
      WORKER_URL: http://worker-service:4003
      BUDIBASE_ENVIRONMENT: PRODUCTION
    depends_on:
      - couchdb-service
      - redis-service
      - minio-service
    restart: unless-stopped

  worker-service:
    container_name: budibase-worker
    image: budibase/worker:latest
    environment:
      SELF_HOSTED: 1
      PORT: 4003
      REDIS_URL: redis-service:6379
      REDIS_PASSWORD: ${REDIS_PASSWORD}
      JWT_SECRET: ${JWT_SECRET}
      COUCH_DB_URL: http://${COUCHDB_USER}:${COUCHDB_PASSWORD}@couchdb-service:5984
      MINIO_URL: http://minio-service:9000
      MINIO_ACCESS_KEY: ${MINIO_ACCESS_KEY}
      MINIO_SECRET_KEY: ${MINIO_SECRET_KEY}
    depends_on:
      - redis-service
      - minio-service
    restart: unless-stopped

  proxy-service:
    container_name: budibase-nginx
    image: budibase/proxy:latest
    environment:
      PROXY_RATE_LIMIT_WEBHOOKS_PER_SECOND: 10
      PROXY_RATE_LIMIT_API_PER_SECOND: 20
    depends_on:
      - app-service
      - worker-service
      - minio-service
    ports:
      - "80:10000"
    restart: unless-stopped

volumes:
  couchdb_data:
  minio_data:
  redis_data:

.env file

# .env — copy and customize
COUCHDB_USER=admin
COUCHDB_PASSWORD=change-this-strong-password
REDIS_PASSWORD=change-this-redis-password
MINIO_ACCESS_KEY=change-this-minio-access
MINIO_SECRET_KEY=change-this-minio-secret
JWT_SECRET=change-this-jwt-secret-32-chars-min

Generate secrets:

openssl rand -hex 32  # Run 3x for each secret

Start and Configure

git clone https://github.com/Budibase/budibase.git
cd budibase/hosting
cp .env.example .env
# Edit .env with your secrets
docker compose up -d

# Check status
docker compose ps
# Access at http://localhost:80

On first launch, Budibase walks you through creating your admin account.


Connecting Data Sources

PostgreSQL Connection

1. Open your Budibase app
2. Click "Data" tab
3. "Add Source" → PostgreSQL
4. Fill in:
   - Host: your-postgres-host.internal
   - Port: 5432
   - Database: mydb
   - User: app_readonly  (use a read-only user for safety)
   - Password: ***
5. Click "Fetch Tables" — Budibase lists all tables
6. Click each table you want to use → "Fetch"

Budibase auto-generates a CRUD interface for each table. You can immediately build a data grid that reads, filters, sorts, creates, and deletes rows without writing any code.

REST API Connection

1. "Add Source" → REST API
2. Base URL: https://api.yourservice.com/v1
3. Headers:
   - Authorization: Bearer {{API_KEY}}
   (use Budibase's binding syntax {{}} to reference env variables)
4. Create queries:
   - GET /users → List users
   - POST /users → Create user
   - GET /users/{{userId}} → Get user by ID

Building Your First App: An Admin Dashboard

Step 1: Set Up the Data

Connect your PostgreSQL users table. Budibase fetches the schema and creates default CRUD queries.

Step 2: Create Screens

New Screen → Table → Select "users" table

Budibase generates a full data grid with pagination, sorting, filtering, create/edit/delete forms. Customize the columns shown, add conditional formatting (red for status = 'suspended'), and add action buttons.

Step 3: Add Custom Automation

Create an automation that fires when a new user signs up:

Automation → Create
Trigger: Database row created (users table, condition: created_at > NOW() - INTERVAL 1 MINUTE)
Step 1: Send email (built-in SMTP)
  To: admin@yourcompany.com
  Subject: New user signed up
  Body: {{trigger.row.email}} just registered
Step 2: Slack webhook
  URL: {{env.SLACK_WEBHOOK_URL}}
  Body: { "text": "New signup: {{trigger.row.email}}" }

Role-Based Access Control

Budibase has four built-in roles, customizable per-app:

RoleDefault Permissions
AdminFull access
Power UserCreate, edit, delete data
Basic UserRead + limited write
PublicUnauthenticated access

Configure per-screen:

Screen Settings → Access → Set minimum role to "Power User"

For row-level security:

Data Source → users table → Row Access
Filter: id = {{ currentUser.id }}
# Users can only see their own rows

Custom Components and Plugins

Budibase supports custom components built in Svelte — for use cases the built-in component library doesn't cover:

# Initialize a new plugin
npx @budibase/cli@latest component init my-chart-component
cd my-chart-component
npm install
npm run build

# Upload to your Budibase instance
npx @budibase/cli@latest upload plugin
# → Enter your Budibase URL and API key
# Component appears in the UI builder immediately

The plugin system also supports data source plugins for connecting to custom APIs or databases not in Budibase's built-in list.


Automation: Scheduled Tasks and Webhooks

Budibase's automation engine replaces simple Zapier/n8n workflows for internal use cases:

Daily Report Email

Automation → Create
Name: Daily Active Users Report
Trigger: Schedule → Daily at 8:00 AM

Step 1: Query data
  Data source: PostgreSQL
  Query: SELECT COUNT(*) as daily_users FROM users
         WHERE last_seen >= NOW() - INTERVAL 24 HOURS

Step 2: Send email
  Provider: SMTP (configure in settings)
  To: team@company.com
  Subject: Daily Active Users — {{steps.1.rows[0].daily_users}} users yesterday
  Body: |
    Hi team,

    Yesterday's active user count: {{steps.1.rows[0].daily_users}}

    View the full dashboard: https://budibase.company.com/app/dashboard

Step 3: Post to Slack
  Webhook URL: {{env.SLACK_WEBHOOK}}
  Body: { "text": "📊 {{steps.1.rows[0].daily_users}} active users yesterday" }

Webhook Trigger (External Events)

Automation → Create
Trigger: Webhook
  → Copy the webhook URL: https://budibase.company.com/api/v1/automations/xxx/trigger

Step 1: Update database
  Data source: PostgreSQL
  Query: UPDATE orders SET status = '{{trigger.body.status}}'
         WHERE id = '{{trigger.body.orderId}}'

Step 2: Send notification
  ...

Use the webhook URL in your payment processor, Stripe, or any external service to trigger Budibase automations on events.


Environment Variables and Secrets

Budibase has a built-in environment variable system for managing secrets across automations and queries:

Settings → Environment Variables
→ Add: STRIPE_API_KEY = sk_live_xxxx
→ Add: SLACK_WEBHOOK = https://hooks.slack.com/...
→ Add: INTERNAL_API_URL = https://api.company.internal

Reference them in queries and automations with {{env.STRIPE_API_KEY}}. Variables are encrypted at rest and never exposed to the frontend — they're server-side only.


Multi-App and Team Management

Budibase supports multiple apps per instance — organize by team or use case:

  • Customer Support app: connected to your helpdesk database
  • Finance app: connected to accounting PostgreSQL, restricted to finance team
  • DevOps app: connected to Kubernetes API, restricted to engineers
  • HR app: connected to HR system, restricted by department

Each app has independent RBAC, its own data sources, and separate publish/edit permissions. The admin panel shows all apps with their last modified date and access stats.


Scaling Budibase

The default Docker Compose setup is single-node. For higher availability:

# Scale app and worker services
docker compose up -d --scale app-service=3 --scale worker-service=2

For true HA, Budibase's enterprise documentation covers Kubernetes deployment with multiple replicas, shared CouchDB cluster, and Redis Sentinel. Most self-hosters don't need this — a single node handles hundreds of internal users comfortably.

Resource requirements by usage:

  • 1-25 users: 2 vCPU, 4GB RAM ($12/month on Hetzner)
  • 25-100 users: 4 vCPU, 8GB RAM ($25/month on Hetzner)
  • 100+ users: Consider the cloud offering or HA setup

Production Hardening

TLS with Certbot

# Install certbot on the host
certbot certonly --standalone -d budibase.yourdomain.com

# Update nginx config in budibase/hosting/proxy/nginx.conf
# Or put a Caddy/Traefik proxy in front

Regular Backups

#!/bin/bash
# backup-budibase.sh
DATE=$(date +%Y%m%d_%H%M)

# CouchDB backup (all databases)
docker exec budibase-couchdb \
  curl -X GET "http://admin:password@localhost:5984/_all_dbs" | \
  jq -r '.[]' | while read db; do
    curl -X GET "http://admin:password@localhost:5984/$db/_all_docs?include_docs=true" \
      > /backups/budibase/couch_${db}_${DATE}.json
  done

# MinIO backup (file attachments)
docker run --rm \
  -v /backups/budibase/minio:/backup \
  minio/mc mirror myminio/budibase /backup

echo "Budibase backup complete"

Upgrading Budibase

cd budibase/hosting
docker compose pull         # Pull latest images
docker compose up -d        # Restart with new images
docker compose logs -f      # Watch for migration logs

Budibase runs database migrations automatically on startup. Major version upgrades may require following the migration guide in the changelog.


Cost Comparison: Retool vs Budibase Self-Hosted

PlanRetoolBudibase Self-Hosted
5 users$250/month~$10/month (VPS)
25 users$1,250/month~$20/month (VPS)
50 users$2,500/month~$30/month (VPS)
SSO/SAML+$500/monthBusiness tier ($125/mo)
Audit logsEnterpriseBusiness tier
Data locationRetool's cloudYour server

For a 10-person startup, switching from Retool to self-hosted Budibase saves roughly $1,000-$2,500/month — meaningful for early-stage teams. The trade-off is operational overhead: you're responsible for updates, backups, and uptime.


Methodology

  • GitHub data from github.com/Budibase/budibase, March 2026
  • Pricing data from budibase.com/pricing, March 2026
  • Setup guide based on Budibase official documentation (docs.budibase.com)
  • Version: Budibase 3.x (check GitHub releases for current version)

Why Self-Host Budibase?

The case for self-hosting Budibase comes down to three practical factors: data ownership, cost at scale, and operational control.

Data ownership is the fundamental argument. When you use a SaaS version of any tool, your data lives on someone else's infrastructure subject to their terms of service, their security practices, and their business continuity. If the vendor raises prices, gets acquired, changes API limits, or shuts down, you're left scrambling. Self-hosting Budibase means your data and configuration stay on infrastructure you control — whether that's a VPS, a bare metal server, or a home lab.

Cost at scale matters once you move beyond individual use. Most SaaS equivalents charge per user or per data volume. A self-hosted instance on a $10-20/month VPS typically costs less than per-user SaaS pricing for teams of five or more — and the cost doesn't scale linearly with usage. One well-configured server handles dozens of users for a flat monthly fee.

Operational control is the third factor. The Docker Compose configuration above exposes every setting that commercial equivalents often hide behind enterprise plans: custom networking, environment variables, storage backends, and authentication integrations. You decide when to update, how to configure backups, and what access controls to apply.

The honest tradeoff: you're responsible for updates, backups, and availability. For teams running any production workloads, this is familiar territory. For individuals, the learning curve is real but the tooling (Docker, Caddy, automated backups) is well-documented and widely supported.

Server Requirements and Sizing

Before deploying Budibase, assess your server capacity against expected workload.

Minimum viable setup: A 1 vCPU, 1GB RAM VPS with 20GB SSD is sufficient for personal use or small teams. Most consumer VPS providers — Hetzner, DigitalOcean, Linode, Vultr — offer machines in this range for $5-10/month. Hetzner offers excellent price-to-performance for European and US regions.

Recommended production setup: 2 vCPUs with 4GB RAM and 40GB SSD handles most medium deployments without resource contention. This gives Budibase headroom for background tasks, caching, and concurrent users while leaving capacity for other services on the same host.

Storage planning: The Docker volumes in this docker-compose.yml store all persistent Budibase data. Estimate your storage growth rate early — for data-intensive tools, budget for 3-5x your initial estimate. Hetzner Cloud and Vultr both support online volume resizing without stopping your instance.

Operating system: Any modern 64-bit Linux distribution works. Ubuntu 22.04 LTS and Debian 12 are the most commonly tested configurations. Ensure Docker Engine 24.0+ and Docker Compose v2 are installed — verify with docker --version and docker compose version. Avoid Docker Desktop on production Linux servers; it adds virtualization overhead and behaves differently from Docker Engine in ways that cause subtle networking issues.

Network: Only ports 80 and 443 need to be publicly accessible when running behind a reverse proxy. Internal service ports should be bound to localhost only. A minimal UFW firewall that blocks all inbound traffic except SSH, HTTP, and HTTPS is the single most effective security measure for a self-hosted server.

Backup and Disaster Recovery

Running Budibase without a tested backup strategy is an unacceptable availability risk. Docker volumes are not automatically backed up — if you delete a volume or the host fails, data is gone with no recovery path.

What to back up: The named Docker volumes containing Budibase's data (database files, user uploads, application state), your docker-compose.yml and any customized configuration files, and .env files containing secrets.

Backup approach: For simple setups, stop the container, archive the volume contents, then restart. For production environments where stopping causes disruption, use filesystem snapshots or database dump commands (PostgreSQL pg_dump, SQLite .backup, MySQL mysqldump) that produce consistent backups without downtime.

For a complete automated backup workflow that ships snapshots to S3-compatible object storage, see the Restic + Rclone backup guide. Restic handles deduplication and encryption; Rclone handles multi-destination uploads. The same setup works for any Docker volume.

Backup cadence: Daily backups to remote storage are a reasonable baseline for actively used tools. Use a 30-day retention window minimum — long enough to recover from mistakes discovered weeks later. For critical data, extend to 90 days and use a secondary destination.

Restore testing: A backup that has never been restored is a backup you cannot trust. Once a month, restore your Budibase backup to a separate Docker Compose stack on different ports and verify the data is intact. This catches silent backup failures, script errors, and volume permission issues before they matter in a real recovery.

Security Hardening

Self-hosting means you are responsible for Budibase's security posture. The Docker Compose setup provides a functional base; production deployments need additional hardening.

Always use a reverse proxy: Never expose Budibase's internal port directly to the internet. The docker-compose.yml binds to localhost; Caddy or Nginx provides HTTPS termination. Direct HTTP access transmits credentials in plaintext. A reverse proxy also centralizes TLS management, rate limiting, and access logging.

Strong credentials: Change default passwords immediately after first login. For secrets in docker-compose environment variables, generate random values with openssl rand -base64 32 rather than reusing existing passwords.

Firewall configuration:

ufw default deny incoming
ufw allow 22/tcp
ufw allow 80/tcp
ufw allow 443/tcp
ufw enable

Internal service ports (databases, admin panels, internal APIs) should only be reachable from localhost or the Docker network, never directly from the internet.

Network isolation: Docker Compose named networks keep Budibase's services isolated from other containers on the same host. Database containers should not share networks with containers that don't need direct database access.

VPN access for sensitive services: For internal-only tools, restricting access to a VPN adds a strong second layer. Headscale is an open source Tailscale control server that puts your self-hosted stack behind a WireGuard mesh, eliminating public internet exposure for internal tools.

Update discipline: Subscribe to Budibase's GitHub releases page to receive security advisory notifications. Schedule a monthly maintenance window to pull updated images. Running outdated container images is the most common cause of self-hosted service compromises.

Troubleshooting Common Issues

Container exits immediately or won't start

Check logs first — they almost always explain the failure:

docker compose logs -f budibase

Common causes: a missing required environment variable, a port already in use, or a volume permission error. Port conflicts appear as bind: address already in use. Find the conflicting process with ss -tlpn | grep PORT and either stop it or change Budibase's port mapping in docker-compose.yml.

Cannot reach the web interface

Work through this checklist:

  1. Confirm the container is running: docker compose ps
  2. Test locally on the server: curl -I http://localhost:PORT
  3. If local access works but external doesn't, check your firewall: ufw status
  4. If using a reverse proxy, verify it's running and the config is valid: caddy validate --config /etc/caddy/Caddyfile

Permission errors on volume mounts

Some containers run as a non-root user. If the Docker volume is owned by root, the container process cannot write to it. Find the volume's host path with docker volume inspect VOLUME_NAME, check the tool's documentation for its expected UID, and apply correct ownership:

chown -R 1000:1000 /var/lib/docker/volumes/your_volume/_data

High resource usage over time

Memory or CPU growing continuously usually indicates unconfigured log rotation, an unbound cache, or accumulated data needing pruning. Check current usage with docker stats budibase. Add resource limits in docker-compose.yml to prevent one container from starving others. For ongoing visibility into resource trends, deploy Prometheus + Grafana or Netdata.

Data disappears after container restart

Data stored in the container's writable layer — rather than a named volume — is lost when the container is removed or recreated. This happens when the volume mount path in docker-compose.yml doesn't match where the application writes data. Verify mount paths against the tool's documentation and correct the mapping. Named volumes persist across container removal; only docker compose down -v deletes them.

Keeping Budibase Updated

Budibase follows a regular release cadence. Staying current matters for security patches and compatibility. The update process with Docker Compose is straightforward:

docker compose pull          # Download updated images
docker compose up -d         # Restart with new images
docker image prune -f        # Remove old image layers (optional)

Read the changelog before major version updates. Some releases include database migrations or breaking configuration changes. For major version bumps, test in a staging environment first — run a copy of the service on different ports with the same volume data to validate the migration before touching production.

Version pinning: For stability, pin to a specific image tag in docker-compose.yml instead of latest. Update deliberately after reviewing the changelog. This trades automatic patch delivery for predictable behavior — the right call for business-critical services.

Post-update verification: After updating, confirm Budibase is functioning correctly. Most services expose a /health endpoint that returns HTTP 200 — curl it from the server or monitor it with your uptime tool.


Find more open source Retool alternatives on OSSAlt — self-hosting guides, community ratings, and feature comparisons.

Related: How to Migrate from Retool to Appsmith 2026 · Best Open Source Alternatives to Retool 2026 · Best Open Source Developer Tools in 2026

The SaaS-to-Self-Hosted Migration Guide (Free PDF)

Step-by-step: infrastructure setup, data migration, backups, and security for 15+ common SaaS replacements. Used by 300+ developers.

Join 300+ self-hosters. Unsubscribe in one click.