Compare commits
22 Commits
0.2.6+v4.5
...
0.3.4+v5.1
| Author | SHA1 | Date | |
|---|---|---|---|
| 4c57b8f80d | |||
| 290a8ad72d | |||
| 148439f7cf | |||
| dd90697270 | |||
| 03db64341d | |||
| f31df0e83c | |||
| 9f68524046 | |||
| 74b61b1154 | |||
| c9ca51a3da | |||
| deac2ea2ab | |||
| 4714d13b47 | |||
| 781f3350c2 | |||
| c2f923d340 | |||
| 39287c2b87 | |||
| ea3d6df830 | |||
| 988662f2ca | |||
| 90d3e6ac69 | |||
| dcd91e6a6f | |||
| da526ffc3a | |||
| 3647245ea4 | |||
| 10d7a66c4a | |||
| 6b2e1f166e |
40
.env.sample
40
.env.sample
@ -66,3 +66,43 @@ OIDC_AUTH_REQUEST_EXTRA_PARAMS='{"acr_values": "eidas1"}'
|
||||
LOGGING_LEVEL_HANDLERS_CONSOLE=INFO
|
||||
LOGGING_LEVEL_LOGGERS_ROOT=INFO
|
||||
LOGGING_LEVEL_LOGGERS_APP=INFO
|
||||
|
||||
##############################################################################
|
||||
# MIGRATIONS
|
||||
##############################################################################
|
||||
# Set to false to disable automatic migrations on backend startup
|
||||
# AUTO_MIGRATIONS=true
|
||||
|
||||
##############################################################################
|
||||
# CONVERSION (file upload → Yjs via y-provider)
|
||||
##############################################################################
|
||||
# Allow uploading .docx/.md files for conversion to Yjs.
|
||||
# Recipe sets this to true (upstream default is false).
|
||||
# CONVERSION_UPLOAD_ENABLED=true
|
||||
# Upstream defaults (uncomment to override):
|
||||
# CONVERSION_FILE_MAX_SIZE=20971520
|
||||
# CONVERSION_FILE_EXTENSIONS_ALLOWED=.docx,.md
|
||||
# CONVERSION_API_ENDPOINT=convert
|
||||
# CONVERSION_API_CONTENT_FIELD=content
|
||||
# CONVERSION_API_TIMEOUT=30
|
||||
# CONVERSION_API_SECURE=false
|
||||
|
||||
##############################################################################
|
||||
# DATABASE CONNECTION POOL
|
||||
##############################################################################
|
||||
# Upstream default (uncomment to override):
|
||||
# DB_PSYCOPG_POOL_ENABLED=false
|
||||
|
||||
##############################################################################
|
||||
# EMAIL APP URL
|
||||
##############################################################################
|
||||
# DJANGO_EMAIL_URL_APP is set automatically in compose.yml to https://${DOMAIN}.
|
||||
# Override is not exposed via .env — edit compose.yml directly if needed.
|
||||
# (Upstream default falls back to Django's Site framework, not configured here.)
|
||||
|
||||
##############################################################################
|
||||
# MEDIA AUTH HEADER
|
||||
##############################################################################
|
||||
# Header the backend reads for media auth subrequests.
|
||||
# Upstream default matches the recipe's nginx config (X-Original-URL).
|
||||
# MEDIA_AUTH_ORIGINAL_URL_HEADER=HTTP_X_ORIGINAL_URL
|
||||
|
||||
@ -20,11 +20,11 @@
|
||||
* `abra app new lasuite-docs --secrets`
|
||||
* `abra app config <app-name>`
|
||||
* `abra app deploy <app-name>`
|
||||
* `abra app cmd <app-name> backend migrate`
|
||||
* `abra app restart <app-name> minio-bootstrap` (Note: this will appear to fail, but probably worked! Check `abra app logs <app-name> minio-bootstrap`)
|
||||
|
||||
You should then be able to visit the landing page of your app, but not yet to login. To login, you need to deploy and integrate single sign on (described below in the "Configure Authentication" section).
|
||||
You should then be able to visit the landing page of your app, but not yet to login. To login, you need to deploy and integrate single sign on (described below in the "Configure Authentication" section).
|
||||
|
||||
* Migrations run automatically on backend startup. To trigger manually: `abra app cmd <app-name> backend migrate`
|
||||
* Minio buckets are created automatically on first deploy. To manually trigger: `abra app cmd <app-name> minio minio_initialize`
|
||||
|
||||
## Configure Authentication
|
||||
|
||||
|
||||
9
abra.sh
9
abra.sh
@ -3,6 +3,8 @@
|
||||
export ABRA_ENTRYPOINT_VERSION=v5
|
||||
export NGINX_CONF_VERSION=v3
|
||||
export PG_BACKUP_VERSION=v3
|
||||
export MINIO_INITIALIZE_VERSION=v1
|
||||
export MIGRATE_VERSION=v1
|
||||
|
||||
environment() {
|
||||
# this exports all the secrets as environment variables
|
||||
@ -10,6 +12,9 @@ environment() {
|
||||
}
|
||||
|
||||
migrate() {
|
||||
environment
|
||||
python manage.py migrate --noinput
|
||||
/migrate.sh
|
||||
}
|
||||
|
||||
minio_initialize() {
|
||||
/minio-initialize.sh
|
||||
}
|
||||
|
||||
122
compose.yml
122
compose.yml
@ -49,13 +49,32 @@ x-common-env: &common-env
|
||||
LOGOUT_REDIRECT_URL:
|
||||
OIDC_REDIRECT_ALLOWED_HOSTS:
|
||||
OIDC_AUTH_REQUEST_EXTRA_PARAMS:
|
||||
# AI (Fixme: remove?)
|
||||
# AI
|
||||
AI_FEATURE_ENABLED: "false"
|
||||
AI_BASE_URL: https://openaiendpoint.com
|
||||
AI_API_KEY: password
|
||||
OPENAI_SDK_BASE_URL: https://openaiendpoint.com
|
||||
OPENAI_SDK_API_KEY: password
|
||||
AI_MODEL: llama
|
||||
# Collaboration
|
||||
COLLABORATION_API_URL: https://$DOMAIN/collaboration/api/
|
||||
# Email app URL (used in email templates; matches recipe DOMAIN)
|
||||
DJANGO_EMAIL_URL_APP: "https://${DOMAIN}"
|
||||
# Conversion (file upload → Yjs via y-provider)
|
||||
CONVERSION_UPLOAD_ENABLED: "${CONVERSION_UPLOAD_ENABLED:-true}"
|
||||
CONVERSION_FILE_MAX_SIZE:
|
||||
CONVERSION_FILE_EXTENSIONS_ALLOWED:
|
||||
CONVERSION_API_ENDPOINT:
|
||||
CONVERSION_API_CONTENT_FIELD:
|
||||
CONVERSION_API_TIMEOUT:
|
||||
CONVERSION_API_SECURE:
|
||||
# Y-Provider base URL + API key (needed when CONVERSION_UPLOAD_ENABLED is true)
|
||||
Y_PROVIDER_API_BASE_URL: http://y-provider:4444/api/
|
||||
Y_PROVIDER_API_KEY_FILE: /run/secrets/y_api_key
|
||||
# DocSpec — converts .docx → BlockNote JSON, then y-provider turns that into Yjs
|
||||
DOCSPEC_API_URL: http://docspec:4000/conversion
|
||||
# Database connection pool
|
||||
DB_PSYCOPG_POOL_ENABLED:
|
||||
# Media auth header (matches recipe nginx by default)
|
||||
MEDIA_AUTH_ORIGINAL_URL_HEADER:
|
||||
|
||||
x-postgres-env: &postgres-env
|
||||
# Postgresql db container configuration
|
||||
@ -84,14 +103,14 @@ x-minio-env: &minio-env
|
||||
|
||||
services:
|
||||
app:
|
||||
image: lasuite/impress-frontend:v4.5.0
|
||||
image: lasuite/impress-frontend:v5.1.0
|
||||
networks:
|
||||
- backend
|
||||
deploy:
|
||||
labels:
|
||||
- "traefik.enable=false"
|
||||
- "coop-cloud.${STACK_NAME}.timeout=${TIMEOUT:-120}"
|
||||
- "coop-cloud.${STACK_NAME}.version=0.2.6+v4.5.0"
|
||||
- "coop-cloud.${STACK_NAME}.version=0.3.4+v5.1.0"
|
||||
user: "${DOCKER_USER:-1000}"
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "http://localhost:8080"]
|
||||
@ -101,11 +120,12 @@ services:
|
||||
start_period: 10s
|
||||
|
||||
backend:
|
||||
image: lasuite/impress-backend:v4.5.0
|
||||
image: lasuite/impress-backend:v5.1.0
|
||||
networks:
|
||||
- backend
|
||||
- backend
|
||||
environment:
|
||||
<<: [*common-env, *postgres-env, *yprovider-env]
|
||||
AUTO_MIGRATIONS: "${AUTO_MIGRATIONS:-true}"
|
||||
healthcheck:
|
||||
test: ["CMD", "/abra-entrypoint.sh", "python", "manage.py", "check"]
|
||||
interval: 15s
|
||||
@ -114,11 +134,15 @@ services:
|
||||
start_period: 10s
|
||||
user: "${DOCKER_USER:-1000}"
|
||||
command: ["gunicorn", "-c", "/usr/local/etc/gunicorn/impress.py", "impress.wsgi:application"]
|
||||
entrypoint: ["/abra-entrypoint.sh", "/usr/local/bin/entrypoint"]
|
||||
entrypoint: >
|
||||
sh -c "if [ \"$$AUTO_MIGRATIONS\" = \"true\" ]; then /migrate.sh; fi && exec /abra-entrypoint.sh /usr/local/bin/entrypoint \"$$@\"" --
|
||||
configs:
|
||||
- source: abra_entrypoint
|
||||
target: /abra-entrypoint.sh
|
||||
mode: 0555
|
||||
- source: migrate
|
||||
target: /migrate.sh
|
||||
mode: 0555
|
||||
secrets:
|
||||
- django_sk
|
||||
- django_sp
|
||||
@ -131,9 +155,15 @@ services:
|
||||
- email_pass
|
||||
|
||||
celery:
|
||||
image: lasuite/impress-backend:v4.5.0
|
||||
image: lasuite/impress-backend:v5.1.0
|
||||
networks:
|
||||
- backend
|
||||
healthcheck:
|
||||
test: ["CMD", "celery", "-A", "impress.celery_app", "inspect", "ping", "--timeout", "5"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
start_period: 30s
|
||||
user: "${DOCKER_USER:-1000}"
|
||||
command: ["celery", "-A", "impress.celery_app", "worker", "-l", "INFO"]
|
||||
environment:
|
||||
@ -155,18 +185,36 @@ services:
|
||||
|
||||
|
||||
y-provider:
|
||||
image: lasuite/impress-y-provider:v4.5.0
|
||||
image: lasuite/impress-y-provider:v5.1.0
|
||||
networks:
|
||||
- backend
|
||||
- backend
|
||||
healthcheck:
|
||||
# y-provider returns 403 on unauthenticated requests; wget exit 4 = network error (server down), anything else = server is responding
|
||||
test: ["CMD-SHELL", "wget -qO /dev/null http://localhost:4444/ 2>/dev/null; test $$? -ne 4"]
|
||||
interval: 15s
|
||||
timeout: 5s
|
||||
retries: 3
|
||||
start_period: 10s
|
||||
environment: *yprovider-env
|
||||
user: "${DOCKER_USER:-1000}"
|
||||
entrypoint: >
|
||||
sh -c "export Y_PROVIDER_API_KEY=\"$$(cat /run/secrets/y_api_key)\" && exec /usr/local/bin/entrypoint \"$$@\"" --
|
||||
command: ["yarn", "start"]
|
||||
# NOTE: healthcheck - `wget` is available in the container, but `wget http://localhost:4444` gives a 403
|
||||
secrets:
|
||||
- y_api_key
|
||||
|
||||
docspec:
|
||||
image: ghcr.io/docspecio/api:3.0.2
|
||||
networks:
|
||||
- backend
|
||||
healthcheck:
|
||||
# Use 127.0.0.1, which is required instead of localhost for this healtcheck because of elixir/busybox bindings
|
||||
test: ["CMD", "wget", "-q", "-O", "/dev/null", "http://127.0.0.1:4000/health"]
|
||||
interval: 15s
|
||||
timeout: 5s
|
||||
retries: 3
|
||||
start_period: 10s
|
||||
|
||||
db:
|
||||
image: pgautoupgrade/pgautoupgrade:18-debian
|
||||
networks:
|
||||
@ -195,32 +243,14 @@ services:
|
||||
- postgres_p
|
||||
|
||||
redis:
|
||||
image: redis:8
|
||||
networks:
|
||||
- backend
|
||||
|
||||
minio-bootstrap:
|
||||
# NOTE: Not started by default, only run with a manual `abra app restart` / `docker service scale`
|
||||
image: minio/mc:RELEASE.2025-05-21T01-59-54Z
|
||||
environment: *minio-env
|
||||
image: redis:8.8.0
|
||||
healthcheck:
|
||||
test: ["CMD", "redis-cli", "ping"]
|
||||
interval: 15s
|
||||
timeout: 5s
|
||||
retries: 3
|
||||
networks:
|
||||
- backend
|
||||
entrypoint: >
|
||||
sh -c "
|
||||
MINIO_ROOT_USER=\"\$$(cat /run/secrets/minio_ru)\" &&
|
||||
MINIO_ROOT_PASSWORD=\"\$$(cat /run/secrets/minio_rp)\" &&
|
||||
/usr/bin/mc alias set docs http://minio:9000 \$${MINIO_ROOT_USER} \"\$${MINIO_ROOT_PASSWORD}\" &&
|
||||
/usr/bin/mc mb --ignore-existing docs/docs-media-storage &&
|
||||
/usr/bin/mc version enable docs/docs-media-storage &&
|
||||
exit 0"
|
||||
deploy:
|
||||
mode: replicated
|
||||
replicas: 0
|
||||
restart_policy:
|
||||
condition: none
|
||||
secrets:
|
||||
- minio_rp
|
||||
- minio_ru
|
||||
|
||||
minio:
|
||||
image: minio/minio:RELEASE.2025-05-24T17-08-30Z
|
||||
@ -233,7 +263,8 @@ services:
|
||||
networks:
|
||||
- backend
|
||||
command: minio server /data
|
||||
entrypoint: ["/usr/bin/docker-entrypoint.sh"]
|
||||
entrypoint: >
|
||||
sh -c "/minio-initialize.sh & exec /usr/bin/docker-entrypoint.sh \"$$@\"" --
|
||||
volumes:
|
||||
- minio:/data
|
||||
deploy:
|
||||
@ -244,12 +275,21 @@ services:
|
||||
- source: abra_entrypoint
|
||||
target: /abra-entrypoint.sh
|
||||
mode: 0555
|
||||
- source: minio_initialize
|
||||
target: /minio-initialize.sh
|
||||
mode: 0555
|
||||
secrets:
|
||||
- minio_rp
|
||||
- minio_ru
|
||||
|
||||
web:
|
||||
image: nginx:1.29
|
||||
image: nginx:1.31.1
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "http://localhost:8083"]
|
||||
interval: 15s
|
||||
timeout: 5s
|
||||
retries: 3
|
||||
start_period: 10s
|
||||
configs:
|
||||
- source: nginx_conf
|
||||
target: /etc/nginx/conf.d/default.conf
|
||||
@ -291,6 +331,12 @@ configs:
|
||||
abra_entrypoint:
|
||||
name: ${STACK_NAME}_entrypoint_${ABRA_ENTRYPOINT_VERSION}
|
||||
file: abra-entrypoint.sh
|
||||
minio_initialize:
|
||||
name: ${STACK_NAME}_minio_initialize_${MINIO_INITIALIZE_VERSION}
|
||||
file: minio-initialize.sh
|
||||
migrate:
|
||||
name: ${STACK_NAME}_migrate_${MIGRATE_VERSION}
|
||||
file: migrate.sh
|
||||
|
||||
secrets:
|
||||
django_sk:
|
||||
|
||||
26
migrate.sh
Normal file
26
migrate.sh
Normal file
@ -0,0 +1,26 @@
|
||||
#!/bin/sh
|
||||
set -e
|
||||
|
||||
# Load secrets into environment
|
||||
source /abra-entrypoint.sh -e
|
||||
|
||||
# Wait for database to be ready (up to 30 seconds)
|
||||
i=0
|
||||
while ! python manage.py check --database default 2>/dev/null; do
|
||||
i=$((i+1))
|
||||
if [ "$i" -ge 30 ]; then
|
||||
echo "migrate: timed out waiting for database" >&2
|
||||
exit 1
|
||||
fi
|
||||
sleep 1
|
||||
done
|
||||
|
||||
# Idempotent: skip if no pending migrations
|
||||
if python manage.py migrate --check > /dev/null 2>&1; then
|
||||
echo "migrate: no pending migrations, skipping"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "migrate: applying pending migrations..."
|
||||
python manage.py migrate --noinput
|
||||
echo "migrate: done"
|
||||
29
minio-initialize.sh
Normal file
29
minio-initialize.sh
Normal file
@ -0,0 +1,29 @@
|
||||
#!/bin/sh
|
||||
set -e
|
||||
|
||||
# Wait for minio to be ready (up to 60 seconds)
|
||||
i=0
|
||||
while ! mc ready local 2>/dev/null; do
|
||||
i=$((i+1))
|
||||
if [ "$i" -ge 60 ]; then
|
||||
echo "minio-initialize: timed out waiting for minio to be ready" >&2
|
||||
exit 1
|
||||
fi
|
||||
sleep 1
|
||||
done
|
||||
|
||||
MINIO_ROOT_USER="$(cat /run/secrets/minio_ru)"
|
||||
MINIO_ROOT_PASSWORD="$(cat /run/secrets/minio_rp)"
|
||||
|
||||
mc alias set docs http://localhost:9000 "${MINIO_ROOT_USER}" "${MINIO_ROOT_PASSWORD}"
|
||||
|
||||
# Idempotent: skip if bucket already exists
|
||||
if mc ls docs/docs-media-storage > /dev/null 2>&1; then
|
||||
echo "minio-initialize: bucket 'docs-media-storage' already exists, skipping"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "minio-initialize: creating bucket 'docs-media-storage'..."
|
||||
mc mb docs/docs-media-storage
|
||||
mc version enable docs/docs-media-storage
|
||||
echo "minio-initialize: done"
|
||||
Reference in New Issue
Block a user