|
Dynamic Collections Create collections with typed schemas at runtime. Auto-generated CRUD endpoints. |
JWT Authentication Register, login, and protect routes. HMAC-SHA256 signing with |
|
File Storage Upload files via multipart forms. Protected files with short-lived tokens. |
SQLite + Filesystem Self-contained database with WAL mode. Files on disk with metadata in SQLite. |
|
Tiny Footprint Small codebase, tiny binary, minimal Docker image. |
Pure Lua No external binaries. Cross-platform via LuaFileSystem. |
| Supabase | PocketBase | MoteBase | |
|---|---|---|---|
| Size | ~2GB+ | ~50MB | ~2MB |
| Boot time | >1s | ~1s | <100ms |
| Self-contained | No | Yes | Yes |
curl -fsSL https://raw.githubusercontent.com/owloops/motebase/main/install.sh | bashAvailable binaries: linux_x86_64, linux_arm64, darwin_x86_64, darwin_arm64
curl -L https://github.com/owloops/motebase/releases/latest/download/motebase-bin-linux_x86_64 -o motebase
chmod +x motebase
./motebasedocker pull ghcr.io/owloops/motebase:latestSee Deployment for docker-compose with automatic HTTPS.
# Install dependencies
luarocks --local install luasocket lsqlite3complete lua-cjson
eval "$(luarocks path --bin)"
# Run
./bin/motebase.lua# Start server
./motebase
# With options
./motebase --port 3000 --host 127.0.0.1 --db myapp.db --secret my-secret-key| Option | Description | Default |
|---|---|---|
-p, --port |
Port to listen on | 8080 |
-h, --host |
Host to bind to | 0.0.0.0 |
-d, --db |
Database file path | motebase.db |
-s, --secret |
JWT secret key | change-me-in-production |
--storage |
File storage directory | ./storage |
--help |
Show help message |
| Variable | Description |
|---|---|
MOTEBASE_SECRET |
JWT secret key |
MOTEBASE_DB |
Database file path |
MOTEBASE_STORAGE |
File storage directory |
MOTEBASE_LOG |
Enable logging (0 to disable) |
# Create collection with schema
curl -X POST http://localhost:8080/api/collections \
-H "Content-Type: application/json" \
-d '{"name":"posts","schema":{"title":{"type":"string","required":true},"body":{"type":"text"}}}'
# List collections
curl http://localhost:8080/api/collections
# Delete collection
curl -X DELETE http://localhost:8080/api/collections/posts# Create record
curl -X POST http://localhost:8080/api/collections/posts/records \
-H "Content-Type: application/json" \
-d '{"title":"Hello World","body":"My first post"}'
# List records
curl http://localhost:8080/api/collections/posts/records
# Get record
curl http://localhost:8080/api/collections/posts/records/1
# Update record
curl -X PATCH http://localhost:8080/api/collections/posts/records/1 \
-H "Content-Type: application/json" \
-d '{"title":"Updated Title"}'
# Delete record
curl -X DELETE http://localhost:8080/api/collections/posts/records/1# Register
curl -X POST http://localhost:8080/api/auth/register \
-H "Content-Type: application/json" \
-d '{"email":"user@example.com","password":"password123"}'
# Login (returns JWT token)
curl -X POST http://localhost:8080/api/auth/login \
-H "Content-Type: application/json" \
-d '{"email":"user@example.com","password":"password123"}'
# Get current user
curl http://localhost:8080/api/auth/me \
-H "Authorization: Bearer <token>"| Type | Description |
|---|---|
string |
Short text |
text |
Long text |
email |
Email with validation |
number |
Numeric value |
boolean |
True/false |
json |
JSON object |
file |
File upload (see File Storage) |
# Create collection with file field
curl -X POST http://localhost:8080/api/collections \
-H "Content-Type: application/json" \
-d '{"name":"docs","schema":{"title":{"type":"string"},"attachment":{"type":"file"}}}'
# Upload file with record
curl -X POST http://localhost:8080/api/collections/docs/records \
-F "title=My Document" \
-F "attachment=@document.pdf"
# Download file
curl http://localhost:8080/api/files/docs/1/document_abc123.pdf -o file.pdfMark file fields as protected to require token-based access:
# Create collection with protected file
curl -X POST http://localhost:8080/api/collections \
-H "Content-Type: application/json" \
-d '{"name":"private","schema":{"doc":{"type":"file","protected":true}}}'
# Get file token (requires auth)
curl -X POST http://localhost:8080/api/files/token \
-H "Authorization: Bearer <token>"
# Returns: {"token":"...","expires":120}
# Access protected file with token
curl "http://localhost:8080/api/files/private/1/doc_abc123.pdf?token=<file_token>"The included docker-compose.yml runs MoteBase with Caddy for automatic HTTPS:
# Development (self-signed cert for localhost)
docker compose up -d
# Production (auto Let's Encrypt cert)
DOMAIN=api.example.com MOTEBASE_SECRET=your-secret docker compose up -dMoteBase runs HTTP without TLS. For production, use a reverse proxy:
# Caddyfile
example.com {
reverse_proxy localhost:8080
}
./bin/motebase.lua # Run from source
busted # Run tests
luacheck . # Lint
stylua . # Format