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
Option Description Default --addressServer bind address localhost:4000--admin-addressSeparate admin interface address Same as --address --public-dirStatic file directory None --spaEnable SPA fallback false--runtime-root-fsWASM sandboxed filesystem root None --geoip-db-pathMaxMind GeoIP database path None --devDevelopment mode (permissive CORS) false--demoRedact PII from logs false--cors-allowed-originsAllowed CORS origins *--runtime-threadsNumber of WASM isolates CPU count --stderr-loggingLog to stderr instead of files false
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:
Users created via CLI are automatically verified and can log in immediately.
Change Password
Change Email
Verify Email
Manually verify a user’s email:
Delete User
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:
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
Demote Admin to User
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:
Remove Component
trail components remove trailbase-guest-ts
Common Workflows
Development Setup
Create Admin User
trail user add admin@localhost AdminPass123
trail admin promote admin@localhost
Create Schema
trail migration create_initial_schema
# Edit the migration file
# Restart server to apply
Generate Types
trail schema todos > schema/todos.json
npx json-schema-to-typescript schema/todos.json > src/types/todos.ts
Production Deployment
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 = ...
Run Server
trail run \
--data-dir /var/lib/trailbase \
--address 0.0.0.0:4000 \
--public-dir /var/www/app
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:
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