---
title: "Deploy TrailBase | (Just Updated) Rust Firebase Alternative, Admin Login Set From Boot, Data Survives Redeploys"
description: "TrailBase backend, admin login set from boot, data on a volume"
category: "Storage"
url: https://railway.com/deploy/trailbase-or-just-updated-rust-firebase-
---

# Deploy TrailBase | (Just Updated) Rust Firebase Alternative, Admin Login Set From Boot, Data Survives Redeploys

TrailBase backend, admin login set from boot, data on a volume

**[Deploy TrailBase | (Just Updated) Rust Firebase Alternative, Admin Login Set From Boot, Data Survives Redeploys on Railway](https://railway.com/template/trailbase-or-just-updated-rust-firebase-)**

Machine-readable deploy manifest (JSON, validated by TemplateCI): https://railway.com/deploy/trailbase-or-just-updated-rust-firebase-/manifest.json

- **Creator:** SuperSlowSloth
- **Category:** Storage

## Template content

### trailbase

- **Image:** trailbase/trailbase:0.34.4@sha256:ccf9179006e13f0f4c7816a01d3420042af5de050e0c0214c5261420888f2785
- **Start command:** `/bin/sh -c 'set -e; D=/app/traildepot; mkdir -p "$D"; if [ -z "$TRAILBASE_ADMIN_PASSWORD" ]; then echo "FATAL: TRAILBASE_ADMIN_PASSWORD must be set before TrailBase will start"; exit 1; fi; if [ "$(stat -c %u "$D")" != 1000 ]; then chown -R 1000:1000 "$D"; fi; echo "[railway] trailbase port=${PORT:-4000} depot_owner=$(stat -c %u:%g "$D") writable=$(su -s /bin/sh trailbase -c "test -w $D" && echo yes || echo NO)"; exec su -s /bin/sh trailbase -c '\''T="/app/trail --depot /app/traildepot"; L=/app/traildepot/.railway-init.log; $T run --address 127.0.0.1:4999 >$L 2>&1 & P=$!; for i in $(seq 1 90); do curl -sf http://127.0.0.1:4999/api/healthcheck >/dev/null 2>&1 && break; sleep 1; done; if $T user change-password admin@localhost "$TRAILBASE_ADMIN_PASSWORD" >/dev/null 2>&1; then echo "[railway] admin@localhost password set from TRAILBASE_ADMIN_PASSWORD"; else echo "[railway] admin@localhost not found (already replaced), password left alone"; fi; kill $P; wait $P 2>/dev/null || true; exec $T run --address "0.0.0.0:${PORT:-4000}"'\'''`
- **Health check:** /api/healthcheck
- **Public domain:** Yes

## Documentation

# Deploy and Host TrailBase on Railway

TrailBase is an open-source application server in a single Rust binary: SQLite with auth, record
APIs, realtime subscriptions, file storage, an admin UI and WASM or JS extensions. It is the
self-hosted alternative to Firebase or Supabase for apps that want one small process and one
database file.

This template runs TrailBase as a single service from a digest-pinned official image: the API and
admin UI on a Railway domain, an admin login whose password exists from the first boot, and the
whole depot (database, uploads, config) on a Railway volume.

## About Hosting TrailBase

TrailBase serves a REST and realtime API, authentication and an admin dashboard from one Rust process backed by SQLite. It runs as one container with its data on a Railway volume.

## Why Deploy TrailBase on Railway

TrailBase on Railway needs a few things handled for you, and this template does them:

- **The admin password is set from boot.** On first start TrailBase creates `admin@localhost` with a
  random password and prints it once in the logs. This template starts the server privately,
  replaces that password with the generated `TRAILBASE_ADMIN_PASSWORD` variable, and only then opens
  the public port, so the printed default never works on your domain. The old default is refused
  (measured).
- **Data survives redeploys.** The depot is the Railway volume at `/app/traildepot`. A user
  registered before a redeploy was still there afterwards (measured).
- **The volume is writable.** Railway mounts volumes owned by root while the image runs as an
  unprivileged user. The start command fixes the ownership and then drops privileges, and logs the
  result so the deploy log shows it.
- **It passes the health check.** `/api/healthcheck` answers on the port Railway injects, so the
  deploy goes healthy without a manual port setting.
- **Nothing to fill in.** The deploy form has no required fields; the admin password is generated
  for you.

## Common Use Cases

- Backend for a web or mobile app: auth, records and realtime without running several services
- Self-hosted Firebase or Supabase replacement for small projects and prototypes
- Internal tools that need a database, an admin UI and an API from one process
- A SQLite-backed API where the whole state is one volume you can back up

## Dependencies for TrailBase Hosting

- One Railway volume for the depot (created by the template)

### Deployment Dependencies

- TrailBase documentation: https://trailbase.io/documentation
- Official image: https://hub.docker.com/r/trailbase/trailbase

### Implementation Details

| Variable | Purpose |
| --- | --- |
| `TRAILBASE_ADMIN_PASSWORD` | Password of `admin@localhost`, generated per deploy. Re-applied on every boot. |
| `PUBLIC_URL` | Public address of the service, for links in auth emails. |
| `TRAILBASE_PRIVATE_URL` | Address for services in the same Railway project. |

Open `https:///_/admin/` and sign in as `admin@localhost` with the value of
`TRAILBASE_ADMIN_PASSWORD`. Changing the variable and redeploying changes the password. If you
rename or delete the `admin@localhost` account, the start command leaves your accounts alone.


## Similar templates

- [Garage S3 Storage](https://railway.com/deploy/garage-s3-storage) — Ultra-light S3 server: fast, open-source, plug-and-play.
- [Redis](https://railway.com/deploy/redis-1) — Self Host Latest Redis with Railway
- [EasyImg](https://railway.com/deploy/easyimg) — Simple self-hostable Nuxt.js personal image hosting system.

Open this page in a browser: https://railway.com/deploy/trailbase-or-just-updated-rust-firebase-
