Installation
Self-host Draftila on your own server with Docker in minutes.
Quick Start
The fastest way to get Draftila running. This uses SQLite and local file storage — no external dependencies needed.
1. Generate an auth secret:
openssl rand -base64 322. Start with a single command:
docker run -d \
--name draftila \
-p 3001:3001 \
-e BETTER_AUTH_SECRET="your-generated-secret" \
-e ADMIN_EMAIL="admin@example.com" \
-e ADMIN_PASSWORD="your-admin-password" \
-e STORAGE_DRIVER="local" \
-e STORAGE_PATH="./storage" \
-v draftila_data:/app/data \
-v draftila_storage:/app/data/storage \
--restart unless-stopped \
draftila/draftila:latestOpen http://localhost:3001 to get started.
Docker Compose
For production, use Docker Compose for easier management and updates.
Create a docker-compose.yml:
services:
draftila:
image: draftila/draftila:latest
ports:
- '3001:3001'
environment:
BETTER_AUTH_SECRET: '${BETTER_AUTH_SECRET}'
BETTER_AUTH_URL: 'https://draftila.example.com'
FRONTEND_URL: 'https://draftila.example.com'
ADMIN_EMAIL: 'admin@example.com'
ADMIN_PASSWORD: '${ADMIN_PASSWORD}'
STORAGE_DRIVER: 'local'
STORAGE_PATH: './storage'
volumes:
- draftila_data:/app/data
- draftila_storage:/app/data/storage
restart: unless-stopped
volumes:
draftila_data:
draftila_storage:Start it:
docker compose up -dPostgreSQL
For teams or high-availability setups, use PostgreSQL instead of SQLite.
services:
draftila:
image: draftila/draftila:latest
ports:
- '3001:3001'
environment:
BETTER_AUTH_SECRET: '${BETTER_AUTH_SECRET}'
BETTER_AUTH_URL: 'https://draftila.example.com'
FRONTEND_URL: 'https://draftila.example.com'
ADMIN_EMAIL: 'admin@example.com'
ADMIN_PASSWORD: '${ADMIN_PASSWORD}'
DB_DRIVER: 'postgres'
DATABASE_URL: 'postgres://draftila:password@db:5432/draftila'
STORAGE_DRIVER: 'local'
STORAGE_PATH: './storage'
volumes:
- draftila_storage:/app/data/storage
depends_on:
db:
condition: service_healthy
restart: unless-stopped
db:
image: postgres:17-alpine
environment:
POSTGRES_USER: draftila
POSTGRES_PASSWORD: password
POSTGRES_DB: draftila
volumes:
- draftila_db:/var/lib/postgresql/data
healthcheck:
test: ['CMD-SHELL', 'pg_isready -U draftila']
interval: 5s
timeout: 5s
retries: 5
restart: unless-stopped
volumes:
draftila_storage:
draftila_db:Environment Variables
All available configuration options.
| Variable | Default | Description |
|---|---|---|
BETTER_AUTH_SECRETrequired | — | A random secret used for signing auth tokens. Generate with: openssl rand -base64 32 |
ADMIN_EMAILrequired | — | Email address for the initial admin account created on first startup. |
ADMIN_PASSWORDrequired | — | Password for the initial admin account. Change this to a strong password. |
BETTER_AUTH_URL | http://localhost:3001 | The public URL of your Draftila instance. Used for auth callbacks. |
FRONTEND_URL | http://localhost:3001 | The public URL for the frontend. Usually the same as BETTER_AUTH_URL. |
PORT | 3001 | The port the server listens on inside the container. |
DB_DRIVER | sqlite | Database driver. Use "sqlite" for single-server or "postgres" for production. |
DATABASE_URL | file:/app/data/draftila.sqlite | Database connection string. For PostgreSQL: postgres://user:pass@host:5432/draftila |
STORAGE_DRIVER | local | File storage driver. "local" stores files on disk. |
STORAGE_PATH | /app/data/storage | Path for local file storage inside the container. |
TRUSTED_PROXY_IPS | — | Comma-separated list of trusted reverse proxy IPs for X-Forwarded-For. |
SKIP_DB_MIGRATE | 0 | Set to "1" to skip automatic database migrations on startup. |
Reverse Proxy
When running behind a reverse proxy (Nginx, Caddy, Traefik), make sure to:
- Set
BETTER_AUTH_URLandFRONTEND_URLto your public domain - Forward WebSocket connections (needed for real-time collaboration)
- Add your proxy IP to
TRUSTED_PROXY_IPS
Caddy example:
draftila.example.com {
reverse_proxy localhost:3001
}Updating
Pull the latest image and restart:
docker compose pull
docker compose up -dDatabase migrations run automatically on startup. Set SKIP_DB_MIGRATE=1 to disable.