Deploy TrailBase

Single-executable app backend with SQLite, REST APIs and auth

Deploy TrailBase

Just deployed

Just deployed

/app/traildepot

Just deployed

/data

trailbase-files

Bucket

Just deployed

Deploy and Host TrailBase on Railway

TrailBase is an open-source application backend that ships as a single executable: a SQLite database, type-safe REST APIs generated from your own tables, realtime subscriptions, email-and-password plus OAuth authentication, a WebAssembly runtime for custom endpoints, and an admin dashboard. It is the Firebase idea reduced to one process — reach for it when you want a backend for a web, mobile or desktop app without running a five-container stack, and when sub-millisecond query latency matters more than write scaling.

Deploy TrailBase on Railway and the whole backend comes up configured. This template runs three services: trailbase holds the application and its SQLite depot on a persistent volume, gateway is a Caddy reverse proxy owning the public URL that hands TrailBase a correct client IP, and mailpit captures the verification and password-reset mail the auth flows send. Uploaded files go to a Railway object-storage bucket rather than the volume, so the disk keeps only databases, config, signing keys and backups. Every browser request enters through the gateway; TrailBase stays on the private network.

Railway diagram of the TrailBase, gateway and mailpit services

Getting Started with TrailBase on Railway

Set ADMIN_PASSWORD when you deploy — that, plus an optional ADMIN_EMAIL, is the only input the template needs. When the deployment goes green, open /_/admin/ on the gateway's public URL and sign in as admin@localhost with the password you chose; the container applies it to the first admin account before the server accepts a request, and records that it has, so a password you change later in the dashboard survives the next deploy. The dashboard opens on a summary of users, tables and database size. Create a table under Tables, or write the CREATE TABLE in the SQL editor, then use the API toggle to expose a record API with world and authenticated access lists. A GET on /api/records/v1/ should now return rows — the quickest confirmation the deployment works. A TEXT column with a CHECK(jsonschema('std.FileUpload', )) constraint accepts uploads into the bucket. To exercise sign-up, register at /_/auth/register, open the mailpit URL — user admin, password from MP_UI_AUTH — and follow the verification link.

TrailBase admin dashboard showing user, table and size counts TrailBase table browser listing notes rows with an uploaded attachment Running a SQL query against the notes table in TrailBase's editor

About Hosting TrailBase

TrailBase collapses the backend-as-a-service stack into one Rust binary over SQLite. The database is in-process, so a query costs no network hop — that is where its sub-millisecond read numbers come from. Self-host it when the app is read-heavy, when the data belongs on infrastructure you control, or when a Postgres-plus-auth-plus-storage stack is out of proportion to the product.

  • Record APIs generated from your tables, with per-operation access rules as SQL expressions
  • Realtime subscriptions to row changes over SSE
  • Auth: email/password, usernames, OAuth, anonymous accounts, TOTP, PKCE for native apps
  • A WebAssembly runtime for custom HTTP handlers, scheduled jobs and SQLite functions
  • Admin dashboard: table browser, arbitrary SQL, an ER diagram, request logs, user registry
  • Typed clients for TypeScript, Dart, Rust, Python, Go, Kotlin, Swift, .NET

trailbase is the app; its volume at /app/traildepot holds main.db, the JWT signing keys and backups, so it must not be removed. gateway owns the public origin: TrailBase reads the last X-Forwarded-For entry, which behind any edge proxy is that proxy's own rotating address, so the gateway rewrites the header to the true client — which is what makes request logs, GeoIP and the per-IP auth rate limit meaningful. mailpit is an SMTP sink with a web inbox, since registration fails when verification mail cannot be sent.

Why Deploy TrailBase on Railway

Railway removes the setup between a single-binary backend and a working URL.

  • Volume, object-storage bucket, HTTPS domain and private networking provisioned with the template
  • Admin credentials applied before the first request, so no default password is live
  • Health checks, restart policies and the reverse proxy pre-wired
  • Uploads land in durable object storage, not a fixed-size disk
  • Push to the source repository to rebuild and redeploy

Common Use Cases for Self-Hosted TrailBase

  • A backend for a mobile or Flutter app needing auth, a typed API and uploads, without a cloud vendor
  • An internal CRUD or admin tool where SQLite is ample and latency invisible
  • The API layer for a local-first client that syncs on reconnect

Dependencies for TrailBase

  • trailbasegridalpha/trailbase-railway, a startup script over trailbase/trailbase:latest that prepares the volume, the bundled auth-UI WebAssembly component, object storage and the first admin account before the server listens
  • gatewaycaddy:2-alpine, configured from a one-line JSON document in a variable
  • mailpitaxllent/mailpit:latest, SMTP on 1025 privately, authenticated inbox on 8025
  • Object storage — a Railway bucket holding every file uploaded through a record API

Environment Variables Reference

VariableServicePurpose
ADMIN_PASSWORDtrailbasePassword for the first admin account
ADMIN_EMAILtrailbaseAdmin identity; default admin@localhost
TRAIL_SERVER_SITE_URLtrailbasePublic URL for mail and OAuth redirects
TRAIL_SERVER_S3_STORAGE_CONFIG_*trailbaseBucket endpoint, region, name, credentials
CADDY_CONFIGgatewayProxy routes and header rewrites
MP_UI_AUTHmailpituser:password for the web inbox

Any scalar field of TrailBase's configuration schema is reachable as TRAIL_ plus the upper-snake path to it, so TRAIL_AUTH_DISABLE_PASSWORD_AUTH needs no config file. Enum fields take their numeric value.

Deployment Dependencies

Hardware Requirements for Self-Hosting TrailBase

MinimumRecommended
CPU1 vCPU2 vCPU
RAM256 MB1 GB
Storage1 GB volume5 GB volume plus object storage
RuntimeLinux containerLinux container

TrailBase is a static musl binary with an embedded database, so idle usage is tens of megabytes. Size RAM for your working set and the WebAssembly runtime, which starts one thread per CPU.

Self-Hosting TrailBase with Docker

The published image runs unmodified. This starts a server on port 4000 with its depot on a host directory.

docker run -p 4000:4000 \
  -v "$PWD/traildepot:/app/traildepot" \
  trailbase/trailbase:latest

The depot must be writable by the image's unprivileged trailbase user, and the first start prints a generated admin password. To set your own, run the CLI against the same depot first.

docker run --rm -v "$PWD/traildepot:/app/traildepot" \
  --entrypoint /app/trail trailbase/trailbase:latest \
  --depot /app/traildepot user change-password admin@localhost 'your-password'

Behind a proxy, set TRAIL_SERVER_SITE_URL so emailed links and OAuth callbacks point at the right host, and have the proxy send a single-entry X-Forwarded-For.

Is TrailBase Free?

TrailBase is free and open source under OSL-3.0, with no paid tier, seat count or feature gate — every capability in the dashboard is in the binary you run. Self-hosting costs only infrastructure: on Railway you pay for the container, the volume and the bucket, and nothing to the project. It is young software under fast development, so read the changelog before upgrading a deployment holding real data.

FAQ

What is TrailBase? An open-source backend-as-a-service in one executable: SQLite storage, generated REST APIs, realtime subscriptions, authentication, a WebAssembly runtime and an admin dashboard.

What does this Railway template deploy? Three services — TrailBase on a persistent volume, a Caddy gateway owning the public HTTPS URL, and Mailpit as an SMTP sink with a web inbox — plus a bucket for uploaded files.

Why does the template include a mail service? TrailBase stores a new account's address as unverified and rejects the registration if it cannot send the verification mail, and an unverified user cannot sign in. Mailpit makes sign-up work immediately; point MP_SMTP_RELAY_* at a real provider when mail should leave the deployment.

Why do uploaded files go to object storage instead of the volume? A volume is fixed-size and tied to one service, while a bucket grows on demand. TrailBase keeps only file metadata in SQLite and streams the bytes from storage, so the split is invisible to API clients.

How do I create a REST API from one of my tables? Create the table, open it in the dashboard and use the API toggle, then set its access lists. Rules are SQL expressions over _USER_, _ROW_ and _REQ_, so an ownership check such as _ROW_.owner = _USER_.id needs no application code.


Template Content

trailbase-files

Bucket

More templates in this category

View Template
Rocky Linux
Hosted Rocky Linux 9 workspace with SSH and persistent storage. 🚀

codestorm
47
View Template
Foundry Virtual Tabletop
A Self-Hosted & Modern Roleplaying Platform

Lucas
71
View Template
Letta Code Remote
Run a Letta Code agent 24/7. No inbound ports, just deploy.

Letta
51