@@ -306,21 +306,100 @@ bin/dev
306306
307307## Production Deployment
308308
309- ### Docker
309+ ### Docker Compose (Recommended)
310+
311+ Create a ` docker-compose.yml ` file:
312+
313+ ``` yaml
314+ services :
315+ clinch :
316+ image : ghcr.io/dkam/clinch:latest
317+ ports :
318+ - " 127.0.0.1:3000:3000" # Bind to localhost only (reverse proxy on same host)
319+ # Use "3000:3000" if reverse proxy is in Docker network or different host
320+ environment :
321+ # Rails Configuration
322+ RAILS_ENV : production
323+ SECRET_KEY_BASE : ${SECRET_KEY_BASE}
324+
325+ # Application Configuration
326+ CLINCH_HOST : ${CLINCH_HOST}
327+ CLINCH_FROM_EMAIL : ${CLINCH_FROM_EMAIL:-noreply@example.com}
328+
329+ # SMTP Configuration
330+ SMTP_ADDRESS : ${SMTP_ADDRESS}
331+ SMTP_PORT : ${SMTP_PORT}
332+ SMTP_DOMAIN : ${SMTP_DOMAIN}
333+ SMTP_USERNAME : ${SMTP_USERNAME}
334+ SMTP_PASSWORD : ${SMTP_PASSWORD}
335+ SMTP_AUTHENTICATION : ${SMTP_AUTHENTICATION:-plain}
336+ SMTP_ENABLE_STARTTLS : ${SMTP_ENABLE_STARTTLS:-true}
337+
338+ # OIDC Configuration (optional - generates temporary key if not provided)
339+ OIDC_PRIVATE_KEY : ${OIDC_PRIVATE_KEY}
340+
341+ # Optional Configuration
342+ FORCE_SSL : ${FORCE_SSL:-false}
343+ volumes :
344+ - ./storage:/rails/storage
345+ restart : unless-stopped
346+ ` ` `
347+
348+ Create a ` .env` file in the same directory:
310349
311350` ` ` bash
312- # Build image
313- docker build -t clinch .
314-
315- # Run container
316- docker run -p 3000:3000 \
317- -v clinch-storage:/rails/storage \
318- -e SECRET_KEY_BASE=your-secret-key \
319- -e SMTP_ADDRESS=smtp.example.com \
320- -e SMTP_PORT=587 \
321- -e SMTP_USERNAME=your-username \
322- -e SMTP_PASSWORD=your-password \
323- clinch
351+ # Generate with: openssl rand -hex 64
352+ SECRET_KEY_BASE=your-secret-key-here
353+
354+ # Application URLs
355+ CLINCH_HOST=https://auth.yourdomain.com
356+ CLINCH_FROM_EMAIL=noreply@yourdomain.com
357+
358+ # SMTP Settings
359+ SMTP_ADDRESS=smtp.example.com
360+ SMTP_PORT=587
361+ SMTP_DOMAIN=yourdomain.com
362+ SMTP_USERNAME=your-smtp-username
363+ SMTP_PASSWORD=your-smtp-password
364+
365+ # OIDC (optional - generates temporary key if not set)
366+ # Generate with: openssl genpkey -algorithm RSA -out private_key.pem -pkeyopt rsa_keygen_bits:2048
367+ # Then: OIDC_PRIVATE_KEY=$(cat private_key.pem)
368+ OIDC_PRIVATE_KEY=
369+
370+ # Optional: Force SSL redirects (if not behind a reverse proxy handling SSL)
371+ FORCE_SSL=false
372+ ` ` `
373+
374+ Start Clinch :
375+
376+ ` ` ` bash
377+ docker compose up -d
378+ ` ` `
379+
380+ **First Run:**
381+ 1. Visit `http://localhost:3000` (or your configured domain)
382+ 2. Complete the first-run wizard to create your admin account
383+ 3. Configure applications and invite users
384+
385+ **Upgrading:**
386+
387+ ` ` ` bash
388+ # Pull latest image
389+ docker compose pull
390+
391+ # Restart with new image (migrations run automatically)
392+ docker compose up -d
393+ ` ` `
394+
395+ **Logs:**
396+
397+ ` ` ` bash
398+ # View logs
399+ docker compose logs -f clinch
400+
401+ # View last 100 lines
402+ docker compose logs --tail=100 clinch
324403` ` `
325404
326405# ## Backup & Restore
@@ -351,9 +430,9 @@ sqlite3 storage/production.sqlite3 "VACUUM INTO 'backup-$(date +%Y%m%d).sqlite3'
351430# 2. Backup uploaded files (ActiveStorage files are immutable)
352431tar -czf uploads-backup-$(date +%Y%m%d).tar.gz storage/uploads/
353432
354- # Docker equivalent
355- docker exec clinch sqlite3 /rails/storage/production.sqlite3 " VACUUM INTO '/rails/storage/backup-$( date +%Y%m%d) .sqlite3';"
356- docker exec clinch tar -czf /rails/storage/uploads-backup-$( date +%Y%m%d) .tar.gz /rails/storage/uploads/
433+ # Docker Compose equivalent
434+ docker compose exec clinch sqlite3 /rails/storage/production.sqlite3 "VACUUM INTO '/rails/storage/backup-$(date +%Y%m%d).sqlite3';"
435+ docker compose exec clinch tar -czf /rails/storage/uploads-backup-$(date +%Y%m%d).tar.gz /rails/storage/uploads/
357436` ` `
358437
359438**Restore:**
@@ -380,13 +459,13 @@ sqlite3 /host/path/production.sqlite3 "VACUUM INTO '/host/path/backup-$(date +%Y
380459rsync -av /host/path/backup-*.sqlite3 /host/path/uploads/ remote:/backups/clinch/
381460` ` `
382461
383- b) ** Docker volumes** (e.g., ` -v clinch_storage:/rails/storage ` ):
462+ b) **Docker volumes** (e.g., using named volumes in compose ) :
384463` ` ` bash
385464# Database backup (safe while running)
386- docker exec clinch sqlite3 /rails/storage/production.sqlite3 " VACUUM INTO '/rails/storage/backup.sqlite3';"
465+ docker compose exec clinch sqlite3 /rails/storage/production.sqlite3 "VACUUM INTO '/rails/storage/backup.sqlite3';"
387466
388467# Copy out of container
389- docker cp clinch:/rails/storage/backup.sqlite3 ./backup-$( date +%Y%m%d) .sqlite3
468+ docker compose cp clinch:/rails/storage/backup.sqlite3 ./backup-$(date +%Y%m%d).sqlite3
390469` ` `
391470
392471**Option 2: While Stopped (Offline Backup)**
@@ -411,35 +490,7 @@ docker compose up -d
411490
412491# # Configuration
413492
414- ### Environment Variables
415-
416- Create a ` .env ` file (see ` .env.example ` ):
417-
418- ``` bash
419- # Rails
420- SECRET_KEY_BASE=generate-with-bin-rails-secret
421- RAILS_ENV=production
422-
423- # Database
424- # SQLite database stored in storage/ directory (Docker volume mount point)
425-
426- # SMTP (for sending emails)
427- SMTP_ADDRESS=smtp.example.com
428- SMTP_PORT=587
429- SMTP_DOMAIN=example.com
430- SMTP_USERNAME=your-username
431- SMTP_PASSWORD=your-password
432- SMTP_AUTHENTICATION=plain
433- SMTP_ENABLE_STARTTLS=true
434-
435- # Application
436- CLINCH_HOST=https://auth.example.com
437- CLINCH_FROM_EMAIL=noreply@example.com
438-
439- # OIDC (optional - generates temporary key in development)
440- # Generate with: openssl genpkey -algorithm RSA -out private_key.pem -pkeyopt rsa_keygen_bits:2048
441- OIDC_PRIVATE_KEY=< contents-of-private-key.pem>
442- ```
493+ All configuration is handled via environment variables (see the `.env` file in the Docker Compose section above).
443494
444495# ## First Run
4454961. Visit Clinch at `http://localhost:3000` (or your configured domain)
0 commit comments