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)
This commit is contained in:
Joey Yakimowich-Payne 2026-01-14 16:20:10 -07:00
commit 1506210a2e
No known key found for this signature in database
GPG key ID: DDF6AF5B21B407D4
11 changed files with 765 additions and 131 deletions

View file

@ -1,21 +1,59 @@
# Production Deployment Guide
This guide provides instructions for deploying Kaboot to a production environment. It covers security, persistence, and configuration for a robust setup.
This guide provides instructions for deploying Kaboot to a production environment with Caddy reverse proxy and automatic HTTPS.
## Quick Start (Caddy + Automated Authentik Setup)
```bash
# 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.
- A registered domain name (e.g., `kaboot.example.com`).
- SSL certificates (e.g., from Let's Encrypt).
- 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:
- **Nginx**: Reverse proxy handling HTTPS and routing.
- **Authentik**: Identity Provider for authentication.
- **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 Nginx or a dedicated service.
- **Kaboot Frontend**: Static assets served via Caddy.
- **PostgreSQL**: Database for Authentik.
- **Redis**: Cache and task queue for Authentik.
@ -26,18 +64,15 @@ Create a production `.env` file. Do not commit this file to version control.
### Backend & Authentik Configuration
```env
# Database Passwords (Generate strong secrets)
# Database Passwords (Generated by setup.sh)
PG_PASS=your_strong_postgres_password
AUTHENTIK_SECRET_KEY=your_strong_authentik_secret
# Infrastructure
AUTHENTIK_PORT_HTTP=9000
KABOOT_BACKEND_PORT=3001
# Bootstrap credentials (Generated by setup.sh)
AUTHENTIK_BOOTSTRAP_PASSWORD=your_admin_password
AUTHENTIK_BOOTSTRAP_TOKEN=your_api_token
# AI Configuration
GEMINI_API_KEY=your_gemini_api_key
# OIDC Production Settings
# 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/
@ -52,112 +87,14 @@ 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 Production Example
## Docker Compose Files
Create a `docker-compose.prod.yml` for your production environment:
The project includes pre-configured compose files:
```yaml
services:
postgresql:
image: docker.io/library/postgres:16-alpine
restart: unless-stopped
healthcheck:
test: ["CMD-SHELL", "pg_isready -d $${POSTGRES_DB} -U $${POSTGRES_USER}"]
interval: 30s
timeout: 5s
retries: 5
volumes:
- postgresql-data:/var/lib/postgresql/data
environment:
POSTGRES_PASSWORD: ${PG_PASS}
POSTGRES_USER: ${PG_USER:-authentik}
POSTGRES_DB: ${PG_DB:-authentik}
networks:
- kaboot-network
- **`docker-compose.prod.yml`** - Production services (Authentik, Backend, PostgreSQL, Redis)
- **`docker-compose.caddy.yml`** - Caddy reverse proxy overlay
redis:
image: docker.io/library/redis:alpine
restart: unless-stopped
command: --save 60 1 --loglevel warning
volumes:
- redis-data:/data
networks:
- kaboot-network
authentik-server:
image: ghcr.io/goauthentik/server:2025.2
restart: unless-stopped
command: server
environment:
AUTHENTIK_REDIS__HOST: redis
AUTHENTIK_POSTGRESQL__HOST: postgresql
AUTHENTIK_POSTGRESQL__USER: ${PG_USER:-authentik}
AUTHENTIK_POSTGRESQL__NAME: ${PG_DB:-authentik}
AUTHENTIK_POSTGRESQL__PASSWORD: ${PG_PASS}
AUTHENTIK_SECRET_KEY: ${AUTHENTIK_SECRET_KEY}
volumes:
- ./authentik/media:/media
- ./authentik/custom-templates:/templates
depends_on:
postgresql:
condition: service_healthy
redis:
condition: service_healthy
networks:
- kaboot-network
authentik-worker:
image: ghcr.io/goauthentik/server:2025.2
restart: unless-stopped
command: worker
environment:
AUTHENTIK_REDIS__HOST: redis
AUTHENTIK_POSTGRESQL__HOST: postgresql
AUTHENTIK_POSTGRESQL__USER: ${PG_USER:-authentik}
AUTHENTIK_POSTGRESQL__NAME: ${PG_DB:-authentik}
AUTHENTIK_POSTGRESQL__PASSWORD: ${PG_PASS}
AUTHENTIK_SECRET_KEY: ${AUTHENTIK_SECRET_KEY}
user: root
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- ./authentik/media:/media
- ./authentik/certs:/certs
- ./authentik/custom-templates:/templates
depends_on:
postgresql:
condition: service_healthy
redis:
condition: service_healthy
networks:
- kaboot-network
kaboot-backend:
build:
context: ./server
dockerfile: Dockerfile
restart: unless-stopped
environment:
NODE_ENV: production
PORT: 3001
DATABASE_PATH: /data/kaboot.db
OIDC_ISSUER: ${OIDC_ISSUER}
OIDC_JWKS_URI: ${OIDC_JWKS_URI}
CORS_ORIGIN: ${CORS_ORIGIN}
LOG_REQUESTS: ${LOG_REQUESTS}
volumes:
- kaboot-data:/data
networks:
- kaboot-network
volumes:
postgresql-data:
redis-data:
kaboot-data:
networks:
kaboot-network:
driver: bridge
```
These files are ready to use - no need to create your own.
## HTTPS and Reverse Proxy
@ -195,7 +132,13 @@ kaboot.example.com {
}
auth.example.com {
reverse_proxy authentik-server:9000
reverse_proxy authentik-server:9000 {
header_up X-Forwarded-Proto {scheme}
header_up X-Forwarded-Host {host}
transport http {
keepalive 30s
}
}
}
```
@ -212,7 +155,7 @@ This creates the `dist/` directory with production assets.
Use both compose files together:
```bash
docker compose -f docker-compose.yml -f docker-compose.caddy.yml up -d
docker compose -f docker-compose.prod.yml -f docker-compose.caddy.yml up -d
```
This will:
@ -225,7 +168,7 @@ This will:
Check that all services are running:
```bash
docker compose -f docker-compose.yml -f docker-compose.caddy.yml ps
docker compose -f docker-compose.prod.yml -f docker-compose.caddy.yml ps
```
View Caddy logs:
@ -234,10 +177,16 @@ View Caddy logs:
docker logs kaboot-caddy
```
Check Authentik blueprint was applied:
```bash
docker compose -f docker-compose.prod.yml logs authentik-server | grep -i blueprint
```
**Stopping the Stack**
```bash
docker compose -f docker-compose.yml -f docker-compose.caddy.yml down
docker compose -f docker-compose.prod.yml -f docker-compose.caddy.yml down
```
### Option 2: Nginx
@ -287,12 +236,37 @@ server {
## Authentik Configuration for Production
### Option A: Automated Setup with Blueprint (Recommended)
Use the production blueprint for automated configuration:
```bash
# 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`
2. **Email Configuration**: To enable password recovery, configure SMTP settings in Authentik. In the Admin interface, go to **System** > **Settings** and update the Email section.
### 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
@ -317,10 +291,12 @@ docker exec kaboot-postgresql pg_dump -U authentik authentik > authentik_backup_
## Security Checklist
- [ ] Change all default passwords (`PG_PASS`, `AUTHENTIK_SECRET_KEY`).
- [ ] Run `./scripts/setup.sh` to generate strong secrets (don't use defaults).
- [ ] Ensure `NODE_ENV` is set to `production`.
- [ ] Use HTTPS for all connections.
- [ ] Set `CORS_ORIGIN` to your specific frontend domain.
- [ ] 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.