Installation
Draftila is designed to be self-hosted. The easiest way to get started is with Docker Compose. By default, Draftila uses SQLite — no external database required.
Requirements
- Docker and Docker Compose
Quick Start
Create a
.env file:ENV
BETTER_AUTH_SECRET=your-secret-key-at-least-32-charactersGenerate a secure secret with:
Shell
openssl rand -base64 32Create a
docker-compose.yml file:YAML
services:
app:
image: draftila/draftila:latest
ports:
- '3001:3001'
environment:
BETTER_AUTH_SECRET: '${BETTER_AUTH_SECRET}'
BETTER_AUTH_URL: 'http://localhost:3001'
FRONTEND_URL: 'http://localhost:3001'
ADMIN_EMAIL: 'admin@example.com'
ADMIN_PASSWORD: 'change-me-please'
volumes:
- draftila_data:/app/data
restart: unless-stopped
volumes:
draftila_data:Then start the service:
Shell
docker compose up -dThat's it. Draftila is now running at
http://localhost:3001 with SQLite, and your admin account is ready to use.Admin Setup
The first admin user is created automatically when you set the
ADMIN_EMAIL and ADMIN_PASSWORD environment variables. These are checked on every container start — if the admin already exists, it's a no-op.You can also create admin users manually:
Shell
docker exec <container> bun run --filter @draftila/api db:create-admin -- \
--email admin@example.com \
--password your-password \
--name "Admin Name"Using PostgreSQL
By default, Draftila uses SQLite which stores everything in a single file. This is great for small teams and simple deployments.
For larger deployments or when you need concurrent access from multiple instances, switch to PostgreSQL:
YAML
services:
app:
image: draftila/draftila:latest
ports:
- '3001:3001'
environment:
DB_DRIVER: 'postgresql'
DATABASE_URL: 'postgresql://draftila:secret@db:5432/draftila'
BETTER_AUTH_SECRET: '${BETTER_AUTH_SECRET}'
BETTER_AUTH_URL: 'http://localhost:3001'
FRONTEND_URL: 'http://localhost:3001'
ADMIN_EMAIL: 'admin@example.com'
ADMIN_PASSWORD: 'change-me-please'
depends_on:
- db
restart: unless-stopped
db:
image: postgres:17
environment:
POSTGRES_USER: draftila
POSTGRES_PASSWORD: secret
POSTGRES_DB: draftila
volumes:
- pgdata:/var/lib/postgresql/data
restart: unless-stopped
volumes:
pgdata:Data Persistence
The
draftila_data volume stores both the SQLite database and uploaded files. Make sure this volume is backed up regularly.The default paths inside the container:
- SQLite database:
/app/data/draftila.sqlite - Uploaded files:
/app/data/storage/
Reverse Proxy
For production, put Draftila behind a reverse proxy with SSL. Here's an example with Nginx:
Nginx
server {
listen 443 ssl;
server_name draftila.example.com;
ssl_certificate /etc/ssl/certs/draftila.pem;
ssl_certificate_key /etc/ssl/private/draftila.key;
location / {
proxy_pass http://localhost:3001;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}WebSocket support is required for real-time collaboration. Make sure your reverse proxy passes the
Upgrade and Connection headers.When behind a reverse proxy, set
TRUSTED_PROXY_IPS so rate limiting uses the real client IP:ENV
TRUSTED_PROXY_IPS=127.0.0.1Set it to
* to trust all proxies (e.g., when Nginx runs in the same Docker network).