Flootdocs
Self-hosted

Overview

Run a Floot backend on your own server from Supabase's official Docker setup: what differs from Cloud, the request path, and where each topic lives.

This group takes you from Supabase's official Docker setup to a production backend for a Floot app. Each topic states what any self-hosted stack needs first, then shows how Floot runs its own backend, api.floot.dev, as a worked example: its Caddy site, its compose overrides, its backup recipe. The facts were gathered on the self-hosted release self-hosted/v0.8.2 (Postgres 17, the Envoy gateway); check them again when you pin a newer one.

Read Going to production first: its four rules apply here unchanged. Self-hosting means you own everything Supabase Cloud does for you, from TLS to backups; if you have no reason to run your own server, Supabase Cloud is the shorter path.

The examples use api.myapp.com for your backend and app.myapp.com for your web app.

What differs from Cloud

TopicSupabase CloudSelf-hosted
SettingsThe dashboardEnvironment variables on each service; nothing reads supabase/config.toml
Exposed schemasData API → SettingsPGRST_DB_SCHEMAS and PGRST_DB_EXTRA_SEARCH_PATH
Deploying functionssupabase functions deployCopy the files, then recreate the functions container
Function secretsSet on the project, live without a redeployEnvironment on the functions service, applied by recreating it
JWT check on functionsPer function, from verify_jwt in config.tomlOne switch for every function, off; each function checks its caller in code
Send Email hookThe dashboardGOTRUE_HOOK_SEND_EMAIL_* on auth, with an https:// URI
Migrationsdb push to the linked projectdb push --db-url over an SSH tunnel, once Realtime is healthy
Vault rowsdb query --linkedpsql
Database WebhooksEnable webhooks in the dashboardNothing to do: the stack's init script creates supabase_functions
Per-IP auth rate limitsBuilt inOff until you set GOTRUE_RATE_LIMIT_HEADER and your proxy sends that header
TLS, proxy, firewallSupabase'sYours
BackupsOn paid plansYours; the stack ships none
UpgradesSupabase'sYours, pinned to a release tag
Outgoing mail ports25 and 587 blocked, use 465Whatever your host allows; many block 25 and 465

The request path

Only the API is public. Clients reach it through your TLS proxy, which forwards the API paths and nothing else; Studio and Postgres stay on the server's loopback, reached from your laptop through an SSH tunnel. Exposure sets out the rules behind each box.

In this group

Start with the step-by-step guide; the other pages are the reference behind its steps.

  • Step by step: from an empty Ubuntu server to a production backend, one checked step at a time, in the shape of Floot's own: SSH and the firewall, Docker, Caddy, the stack with your app's files, the first deploy, a reboot, backups and the smoke check, then your web app as a second site beside the API.
  • Shipping a release: the first start, migrations over the tunnel, reference data, the Vault rows, deploying the functions, Floot's release order and the smoke check.
  • Exposure: the paths your proxy forwards, the proxy rules, Docker bypassing ufw, the tunnel, Cloudflare, and Storage behind a CDN.
  • Configuration: the stack and your own compose file, the config.toml to environment mapping, function secrets, the JWT switch and the Send Email hook.
  • Backups: what holds state, Floot's recipe, and restoring onto a new server.
  • Watching: optional, Uptime Kuma beside Caddy, sending a Telegram message when the API, the certificate, the backups or the disk need you.
  • Upgrades: moving to a newer release tag on purpose.

On this page