Skip to main content
The trail CLI provides commands for managing your TrailBase server, users, migrations, and more.

Installation

The trail binary is included in TrailBase releases:
# Download from GitHub releases
curl -L https://github.com/trailbaseio/trailbase/releases/latest/download/trailbase-linux-x86_64.tar.gz | tar xz

# Make executable
chmod +x trail

# Move to PATH (optional)
sudo mv trail /usr/local/bin/

Global Options

These options work with all commands:
# Specify data directory (default: ./traildepot)
trail --data-dir /var/lib/trailbase run

# Set public URL for OAuth and emails
trail --public-url https://example.com run

# Show version
trail --version

Server Commands

Start Server

Start the HTTP server:
# Start with defaults (localhost:4000)
trail run

# Custom address
trail run --address 0.0.0.0:8080

# Separate admin interface
trail run --admin-address localhost:4001

# Serve static files
trail run --public-dir ./web/dist

# Enable SPA fallback (serve index.html for routes)
trail run --public-dir ./web/dist --spa

# Development mode (permissive CORS)
trail run --dev

# Custom number of WASM workers
trail run --runtime-threads 8
First Run: On first startup, TrailBase creates admin credentials and displays them in the terminal. Save these to access the admin UI at http://localhost:4000/_/admin.

Server Options

OptionDescriptionDefault
--addressServer bind addresslocalhost:4000
--admin-addressSeparate admin interface addressSame as --address
--public-dirStatic file directoryNone
--spaEnable SPA fallbackfalse
--runtime-root-fsWASM sandboxed filesystem rootNone
--geoip-db-pathMaxMind GeoIP database pathNone
--devDevelopment mode (permissive CORS)false
--demoRedact PII from logsfalse
--cors-allowed-originsAllowed CORS origins*
--runtime-threadsNumber of WASM isolatesCPU count
--stderr-loggingLog to stderr instead of filesfalse

Migration Commands

Create Migration

Generate a new migration file:
# Create migration for main database
trail migration create_table_posts

# Output:
# Created: traildepot/migrations/main/U1234567890__create_table_posts.sql

# Create migration for attached database
trail migration add_analytics_table --db analytics
The generated file is ready to edit:
traildepot/migrations/main/U1234567890__create_table_posts.sql
-- Add your SQL statements here
CREATE TABLE posts (
  id INTEGER PRIMARY KEY,
  title TEXT NOT NULL
) STRICT;
Migrations run automatically when TrailBase starts. No separate apply command is needed.

View Applied Migrations

Check which migrations have been applied:
# Using SQLite directly
sqlite3 traildepot/data/main.db "SELECT * FROM _schema_history ORDER BY version;"

User Management

Create User

Add a new verified user:
trail user add [email protected] SecurePassword123
Users created via CLI are automatically verified and can log in immediately.

Change Password

trail user change-password [email protected] NewPassword123

Change Email

trail user change-email [email protected] [email protected]

Verify Email

Manually verify a user’s email:
# Verify user
trail user verify [email protected] true

# Unverify user
trail user verify [email protected] false

Delete User

trail user delete [email protected]
Deleting a user cascades to all records with foreign keys to _user.id. This cannot be undone.

Invalidate Session

Force a user to re-login:
trail user invalidate-session [email protected]
This increments the user’s session version, making existing auth tokens invalid.

Mint Auth Token

Generate an auth token for a user (useful for automation):
trail user mint-token [email protected]

# Output:
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...
Use the token for API requests:
curl -H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9..." \
  http://localhost:4000/api/records/todos

Import Users

Import users from Auth0 or other providers:
# Dry run (validate without importing)
trail user import --dry-run --auth0-json users.ndjson

# Actually import
trail user import --auth0-json users.ndjson

Admin Management

List Admins

trail admin list

# Output:
admin@localhost
[email protected]

Promote User to Admin

trail admin promote [email protected]

Demote Admin to User

trail admin demote [email protected]
You cannot demote yourself. Use another admin account or direct database access.

Schema Commands

Export JSON Schema

Generate JSON Schema for a table:
# Generate schema for SELECT operations
trail schema todos

# Generate schema for INSERT operations
trail schema todos --mode insert

# Generate schema for UPDATE operations
trail schema todos --mode update
Output:
{
  "title": "todos",
  "type": "object",
  "properties": {
    "id": { "type": "integer" },
    "text": { "type": "string" },
    "completed": { "type": "integer" }
  },
  "required": ["id", "text", "completed"]
}
Pipe to a file for code generation:
trail schema todos > schema/todos.json
npx json-schema-to-typescript schema/todos.json > src/types/todos.ts

Export OpenAPI Spec

Generate OpenAPI specification:
# Print to stdout
trail openapi print

# Save to file
trail openapi print > openapi.yaml

# Run Swagger UI (requires swagger feature)
trail openapi run
# Opens http://localhost:4004

Email Commands

Send emails programmatically:
trail email \
  --to [email protected] \
  --subject "Test Email" \
  --body "This is a test message."
Email settings must be configured in traildepot/config.textproto or via environment variables.

Component Management

List Available Components

Show first-party WASM components:
trail components list

# Output:
Available first-party components:
- trailbase-guest-ts (TypeScript/JavaScript runtime)
- trailbase-guest-rust (Rust runtime)

Install Component

# Install from registry
trail components add trailbase-guest-ts

# Install from local file
trail components add ./component.wasm

# Install from URL
trail components add https://example.com/component.wasm

List Installed Components

trail components installed

# Output:
Installed components:
- trailbase-guest-ts (v1.0.0)

Update Components

Update all installed first-party components:
trail components update

Remove Component

trail components remove trailbase-guest-ts

Common Workflows

Development Setup

1

Start Server

trail run --dev
2

Create Admin User

trail user add admin@localhost AdminPass123
trail admin promote admin@localhost
3

Create Schema

trail migration create_initial_schema
# Edit the migration file
# Restart server to apply
4

Generate Types

trail schema todos > schema/todos.json
npx json-schema-to-typescript schema/todos.json > src/types/todos.ts

Production Deployment

1

Set Environment Variables

export PUBLIC_URL=https://example.com
export OBJECT_STORE_TYPE=s3
export OBJECT_STORE_BUCKET=my-bucket
export OBJECT_STORE_ACCESS_KEY_ID=...
export OBJECT_STORE_SECRET_ACCESS_KEY=...
2

Run Server

trail run \
  --data-dir /var/lib/trailbase \
  --address 0.0.0.0:4000 \
  --public-dir /var/www/app
3

Configure Reverse Proxy

Use nginx, Caddy, or similar to handle:
  • TLS termination
  • Request compression
  • Static file caching
  • Rate limiting

Database Backup

# Manual backup
cp traildepot/data/main.db backups/main-$(date +%Y%m%d).db

# Automated backup script
#!/bin/bash
DATE=$(date +%Y%m%d-%H%M%S)
cp traildepot/data/main.db backups/main-$DATE.db

# Keep only last 7 days
find backups/ -name "main-*.db" -mtime +7 -delete
TrailBase automatically creates backups in traildepot/backups/. These are SQLite database files that can be restored by copying them to traildepot/data/.

Reset Admin Password

If you lose admin credentials:
# Create new admin user
trail user add newadmin@localhost SecurePass123
trail admin promote newadmin@localhost

# Or change existing admin password
trail user change-password admin@localhost NewSecurePass123

Test Configuration

# Validate config by starting server
trail run

# Check logs for errors
tail -f traildepot/logs/trailbase.log

# Test with cURL
curl http://localhost:4000/_/health

Environment Variables

Override CLI options with environment variables:
# Data directory
export DATA_DIR=/var/lib/trailbase

# Public URL
export PUBLIC_URL=https://example.com

# Server address
export ADDRESS=0.0.0.0:4000

# WASM runtime threads
export RUNTIME_THREADS=8

# Run server
trail run

Configuration File

Main configuration file: traildepot/config.textproto Example configuration:
traildepot/config.textproto
server {
  application_name: "My App"
  site_url: "https://example.com"
}

auth {
  disable_password_auth: false
  require_email_verification: true
  
  password_policy {
    min_length: 8
    require_uppercase: true
    require_lowercase: true
    require_number: true
  }
  
  oauth_providers: [
    {
      key: "github"
      value {
        client_id: "your-client-id"
        client_secret: "your-client-secret"
        provider_id: GITHUB
      }
    }
  ]
}

email {
  smtp_host: "smtp.gmail.com"
  smtp_port: 587
  smtp_username: "[email protected]"
  smtp_password: "your-app-password"
  from_address: "[email protected]"
}

record_apis: [
  {
    name: "todos"
    table_name: "todos"
    acl_authenticated: [CREATE, READ, UPDATE, DELETE]
  }
]

Logging

TrailBase logs to:
  • traildepot/logs/trailbase.log - Main application log
  • traildepot/logs/access.log - HTTP access log
  • stderr - With --stderr-logging flag
View logs:
# Tail main log
tail -f traildepot/logs/trailbase.log

# View access log
tail -f traildepot/logs/access.log

# Search logs
grep ERROR traildepot/logs/trailbase.log

Debugging

Verbose Logging

# Set log level via environment
export RUST_LOG=debug
trail run

Test Database Queries

# Open database
sqlite3 traildepot/data/main.db

# List tables
.tables

# Describe table
.schema todos

# Query data
SELECT * FROM todos;

# Check migrations
SELECT * FROM _schema_history;

Health Check

# Check if server is running
curl http://localhost:4000/_/health

# Output:
{"status":"ok"}

Systemd Service

Run TrailBase as a systemd service:
/etc/systemd/system/trailbase.service
[Unit]
Description=TrailBase Server
After=network.target

[Service]
Type=simple
User=trailbase
Group=trailbase
WorkingDirectory=/var/lib/trailbase
Environment="DATA_DIR=/var/lib/trailbase"
Environment="PUBLIC_URL=https://example.com"
ExecStart=/usr/local/bin/trail run --address 0.0.0.0:4000
Restart=always
RestartSec=10

[Install]
WantedBy=multi-user.target
Manage the service:
# Enable and start
sudo systemctl enable trailbase
sudo systemctl start trailbase

# Check status
sudo systemctl status trailbase

# View logs
sudo journalctl -u trailbase -f

# Restart
sudo systemctl restart trailbase

Docker

Run TrailBase in Docker:
# Pull image
docker pull trailbase/trailbase:latest

# Run container
docker run -d \
  --name trailbase \
  -p 4000:4000 \
  -v $(pwd)/traildepot:/data \
  -e PUBLIC_URL=http://localhost:4000 \
  trailbase/trailbase:latest

# View logs
docker logs -f trailbase

# Execute commands
docker exec trailbase trail admin list
Docker Compose:
docker-compose.yml
version: '3.8'

services:
  trailbase:
    image: trailbase/trailbase:latest
    ports:
      - "4000:4000"
    volumes:
      - ./traildepot:/data
    environment:
      - DATA_DIR=/data
      - PUBLIC_URL=https://example.com
    command: run --address 0.0.0.0:4000
    restart: unless-stopped

Next Steps

First App

Build your first application

Migrations

Learn about database migrations

Authentication

Manage users and auth

WASM Runtime

Extend with WebAssembly

Reference

Build docs developers (and LLMs) love