kaboot/docs/PRODUCTION.md
Joey Yakimowich-Payne 1506210a2e
Add Authentik blueprints for automated OAuth2/OIDC setup
Automate the manual Authentik configuration process using native YAML blueprints
that are applied on container startup.

Changes:
- Add kaboot-setup.yaml blueprint for local development
- Add kaboot-setup-production.yaml.example for production with configurable domains
- Update docker-compose.yml and docker-compose.prod.yml to mount blueprints
- Add AUTHENTIK_BOOTSTRAP_PASSWORD/TOKEN env vars for automated admin setup
- Update setup.sh to generate bootstrap credentials and display admin password
- Update Caddyfile.example with proper proxy headers for Authentik
- Add Caddyfile to .gitignore (user-specific config)
- Update docs with Quick Start sections for automated setup

The blueprints create:
- OAuth2/OIDC provider (public client, client_id: kaboot-spa)
- Kaboot application with redirect URIs
- kaboot-users group with application binding
- Enrollment flow with sign-up capability
- Password complexity policy
- Test user and service account (passwords set manually)
2026-01-14 16:20:10 -07:00

8.7 KiB

Production Deployment Guide

This guide provides instructions for deploying Kaboot to a production environment with Caddy reverse proxy and automatic HTTPS.

Quick Start (Caddy + Automated Authentik Setup)

# 1. Generate secrets
./scripts/setup.sh

# 2. Configure production blueprint
cp authentik/blueprints/kaboot-setup-production.yaml.example \
   authentik/blueprints/kaboot-setup-production.yaml

# Edit the blueprint - update domains in the 'context' section:
#   kaboot_domain: your-app.com
#   auth_domain: auth.your-app.com

# Remove dev blueprint to avoid conflicts
rm authentik/blueprints/kaboot-setup.yaml

# 3. Configure Caddyfile
cp Caddyfile.example Caddyfile
# Edit Caddyfile - replace example.com with your domains

# 4. Update .env with production values
#    - OIDC_ISSUER=https://auth.your-app.com/application/o/kaboot/
#    - OIDC_JWKS_URI=https://auth.your-app.com/application/o/kaboot/jwks/
#    - CORS_ORIGIN=https://your-app.com

# 5. Build frontend with production URLs
VITE_API_URL=https://your-app.com/api \
VITE_OIDC_AUTHORITY=https://auth.your-app.com/application/o/kaboot/ \
npm run build

# 6. Start the stack
docker compose -f docker-compose.prod.yml -f docker-compose.caddy.yml up -d

# 7. Verify
docker compose -f docker-compose.prod.yml -f docker-compose.caddy.yml ps

Prerequisites

  • A Linux server with Docker and Docker Compose installed.
  • Two registered domain names (e.g., kaboot.example.com and auth.example.com).
  • DNS A records pointing both domains to your server.
  • A Google Gemini API key.

Architecture Overview

In production, the stack consists of:

  • Caddy: Reverse proxy with automatic HTTPS via Let's Encrypt.
  • Authentik: Identity Provider for OAuth2/OIDC authentication.
  • Kaboot Backend: Express server for quiz logic and SQLite storage.
  • Kaboot Frontend: Static assets served via Caddy.
  • PostgreSQL: Database for Authentik.
  • Redis: Cache and task queue for Authentik.

Environment Variables

Create a production .env file. Do not commit this file to version control.

Backend & Authentik Configuration

# Database Passwords (Generated by setup.sh)
PG_PASS=your_strong_postgres_password
AUTHENTIK_SECRET_KEY=your_strong_authentik_secret

# Bootstrap credentials (Generated by setup.sh)
AUTHENTIK_BOOTSTRAP_PASSWORD=your_admin_password
AUTHENTIK_BOOTSTRAP_TOKEN=your_api_token

# OIDC Production Settings (update with your domains)
OIDC_ISSUER=https://auth.example.com/application/o/kaboot/
OIDC_JWKS_URI=https://auth.example.com/application/o/kaboot/jwks/

# Security
CORS_ORIGIN=https://kaboot.example.com
LOG_REQUESTS=true

Frontend Configuration

The frontend requires environment variables at build time:

  • VITE_API_URL: https://kaboot.example.com/api
  • VITE_OIDC_AUTHORITY: https://auth.example.com/application/o/kaboot/

Docker Compose Files

The project includes pre-configured compose files:

  • docker-compose.prod.yml - Production services (Authentik, Backend, PostgreSQL, Redis)
  • docker-compose.caddy.yml - Caddy reverse proxy overlay

These files are ready to use - no need to create your own.

HTTPS and Reverse Proxy

Choose one of the following reverse proxy options. Caddy is recommended for its simplicity and automatic HTTPS.

Caddy automatically obtains and renews SSL certificates from Let's Encrypt.

A separate docker-compose.caddy.yml is provided to add Caddy to your stack.

Step 1: Create the Caddyfile

Copy and customize the example Caddyfile:

cp Caddyfile.example Caddyfile

Edit Caddyfile and replace kaboot.example.com and auth.example.com with your actual domains:

kaboot.example.com {
    root * /srv/frontend
    file_server
    try_files {path} /index.html

    handle /api/* {
        reverse_proxy kaboot-backend:3001
    }

    handle /health {
        reverse_proxy kaboot-backend:3001
    }
}

auth.example.com {
    reverse_proxy authentik-server:9000 {
        header_up X-Forwarded-Proto {scheme}
        header_up X-Forwarded-Host {host}
        transport http {
            keepalive 30s
        }
    }
}

Step 2: Build the Frontend

npm run build

This creates the dist/ directory with production assets.

Step 3: Start with Caddy

Use both compose files together:

docker compose -f docker-compose.prod.yml -f docker-compose.caddy.yml up -d

This will:

  • Start all Kaboot services (backend, Authentik, PostgreSQL, Redis)
  • Start Caddy as a reverse proxy on ports 80 and 443
  • Automatically obtain SSL certificates from Let's Encrypt

Step 4: Verify

Check that all services are running:

docker compose -f docker-compose.prod.yml -f docker-compose.caddy.yml ps

View Caddy logs:

docker logs kaboot-caddy

Check Authentik blueprint was applied:

docker compose -f docker-compose.prod.yml logs authentik-server | grep -i blueprint

Stopping the Stack

docker compose -f docker-compose.prod.yml -f docker-compose.caddy.yml down

Option 2: Nginx

Use Nginx as a reverse proxy with manual SSL certificate management.

server {
    listen 443 ssl;
    server_name kaboot.example.com;

    ssl_certificate /etc/letsencrypt/live/kaboot.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/kaboot.example.com/privkey.pem;

    location / {
        root /var/www/kaboot/frontend;
        try_files $uri $uri/ /index.html;
    }

    location /api/ {
        proxy_pass http://localhost:3001/;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }

    location /health {
        proxy_pass http://localhost:3001/health;
    }
}

server {
    listen 443 ssl;
    server_name auth.example.com;

    ssl_certificate /etc/letsencrypt/live/auth.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/auth.example.com/privkey.pem;

    location / {
        proxy_pass http://localhost:9000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

Authentik Configuration for Production

Use the production blueprint for automated configuration:

# 1. Copy and configure the production blueprint
cp authentik/blueprints/kaboot-setup-production.yaml.example \
   authentik/blueprints/kaboot-setup-production.yaml

# 2. Edit the blueprint and update the domains
#    Find the 'context' section and change:
#    - kaboot_domain: kaboot.example.com  -> your-app.com
#    - auth_domain: auth.example.com      -> auth.your-app.com

# 3. Remove the development blueprint (prevents conflicts)
rm authentik/blueprints/kaboot-setup.yaml

# 4. Start the stack - blueprint applies automatically
docker compose -f docker-compose.prod.yml up -d

Option B: Manual Configuration

  1. Update Redirect URIs: In the Authentik Admin interface, go to Applications > Providers > Kaboot OAuth2. Update the Redirect URIs to use your production domain:
    • https://kaboot.example.com/callback
    • https://kaboot.example.com/silent-renew.html
    • https://kaboot.example.com

Email Configuration

To enable password recovery, configure SMTP settings in Authentik. In the Admin interface, go to System > Settings and update the Email section. - Host: your SMTP server - Port: 587 or 465 - Username/Password: your credentials - Use TLS/SSL: Enabled

Database Backup Strategy

Kaboot uses SQLite, making backups straightforward.

SQLite (Kaboot Data)

The database file is located in the kaboot-data volume at /data/kaboot.db. To back it up:

docker exec kaboot-backend sqlite3 /data/kaboot.db ".backup '/data/backup_$(date +%F).db'"

Then, copy the backup file from the volume to a secure location.

PostgreSQL (Authentik Data)

For Authentik's metadata:

docker exec kaboot-postgresql pg_dump -U authentik authentik > authentik_backup_$(date +%F).sql

Security Checklist

  • Run ./scripts/setup.sh to generate strong secrets (don't use defaults).
  • Ensure NODE_ENV is set to production.
  • Use HTTPS for all connections (Caddy handles this automatically).
  • Set CORS_ORIGIN to your specific frontend domain (e.g., https://kaboot.example.com).
  • Update OIDC_ISSUER and OIDC_JWKS_URI to use your auth domain with HTTPS.
  • Regularly back up the kaboot.db and PostgreSQL data.
  • Monitor logs by setting LOG_REQUESTS=true.
  • Keep Docker images updated to the latest stable versions.
  • Configure firewall to only allow ports 80 and 443 from the internet.