Complete stage 7
This commit is contained in:
parent
3e7b89bcad
commit
1f88e291a9
9 changed files with 784 additions and 26 deletions
326
docs/PRODUCTION.md
Normal file
326
docs/PRODUCTION.md
Normal file
|
|
@ -0,0 +1,326 @@
|
|||
# Production Deployment Guide
|
||||
|
||||
This guide provides instructions for deploying Kaboot to a production environment. It covers security, persistence, and configuration for a robust setup.
|
||||
|
||||
## 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).
|
||||
- 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.
|
||||
- **Kaboot Backend**: Express server for quiz logic and SQLite storage.
|
||||
- **Kaboot Frontend**: Static assets served via Nginx or a dedicated service.
|
||||
- **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
|
||||
|
||||
```env
|
||||
# Database Passwords (Generate strong secrets)
|
||||
PG_PASS=your_strong_postgres_password
|
||||
AUTHENTIK_SECRET_KEY=your_strong_authentik_secret
|
||||
|
||||
# Infrastructure
|
||||
AUTHENTIK_PORT_HTTP=9000
|
||||
KABOOT_BACKEND_PORT=3001
|
||||
|
||||
# AI Configuration
|
||||
GEMINI_API_KEY=your_gemini_api_key
|
||||
|
||||
# OIDC Production Settings
|
||||
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 Production Example
|
||||
|
||||
Create a `docker-compose.prod.yml` for your production environment:
|
||||
|
||||
```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
|
||||
|
||||
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
|
||||
```
|
||||
|
||||
## HTTPS and Reverse Proxy
|
||||
|
||||
Choose one of the following reverse proxy options. Caddy is recommended for its simplicity and automatic HTTPS.
|
||||
|
||||
### Option 1: Caddy (Recommended)
|
||||
|
||||
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:
|
||||
|
||||
```bash
|
||||
cp Caddyfile.example Caddyfile
|
||||
```
|
||||
|
||||
Edit `Caddyfile` and replace `kaboot.example.com` and `auth.example.com` with your actual domains:
|
||||
|
||||
```caddyfile
|
||||
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
|
||||
}
|
||||
```
|
||||
|
||||
**Step 2: Build the Frontend**
|
||||
|
||||
```bash
|
||||
npm run build
|
||||
```
|
||||
|
||||
This creates the `dist/` directory with production assets.
|
||||
|
||||
**Step 3: Start with Caddy**
|
||||
|
||||
Use both compose files together:
|
||||
|
||||
```bash
|
||||
docker compose -f docker-compose.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:
|
||||
|
||||
```bash
|
||||
docker compose -f docker-compose.yml -f docker-compose.caddy.yml ps
|
||||
```
|
||||
|
||||
View Caddy logs:
|
||||
|
||||
```bash
|
||||
docker logs kaboot-caddy
|
||||
```
|
||||
|
||||
**Stopping the Stack**
|
||||
|
||||
```bash
|
||||
docker compose -f docker-compose.yml -f docker-compose.caddy.yml down
|
||||
```
|
||||
|
||||
### Option 2: Nginx
|
||||
|
||||
Use Nginx as a reverse proxy with manual SSL certificate management.
|
||||
|
||||
```nginx
|
||||
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
|
||||
|
||||
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.
|
||||
- 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:
|
||||
```bash
|
||||
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:
|
||||
```bash
|
||||
docker exec kaboot-postgresql pg_dump -U authentik authentik > authentik_backup_$(date +%F).sql
|
||||
```
|
||||
|
||||
## Security Checklist
|
||||
|
||||
- [ ] Change all default passwords (`PG_PASS`, `AUTHENTIK_SECRET_KEY`).
|
||||
- [ ] Ensure `NODE_ENV` is set to `production`.
|
||||
- [ ] Use HTTPS for all connections.
|
||||
- [ ] Set `CORS_ORIGIN` to your specific frontend domain.
|
||||
- [ ] 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.
|
||||
Loading…
Add table
Add a link
Reference in a new issue