Compare commits

..
4 Commits
Author SHA1 Message Date
knoflook 124e6825ff broken commit for testing purposes 2025-10-07 15:23:40 +02:00
knoflook 44fae6db11 spell fixes and disable email password secret 2025-09-11 13:37:59 +02:00
knoflook 5ce5e557a3 fix: typo 2025-09-09 17:41:32 +02:00
knoflook 3fbc6fb2a1 WIP: move secrets away 2025-09-09 17:27:09 +02:00
19 changed files with 364 additions and 629 deletions
+24 -83
View File
@@ -10,27 +10,18 @@ LETS_ENCRYPT_ENV=production
############################################################################## ##############################################################################
# SECRETS # SECRETS
############################################################################## ##############################################################################
# abbreviations are to fit abra 12 char secret recommendation SECRET_MINIO_ROOT_PASSWORD_VERSION=v1
# DJANGO_SECRET_KEY SECRET_COLLABORATION_SERVER_SECRET_VERSION=v1
SECRET_DJANGO_SK_VERSION=v1 SECRET_POSTGRES_PASSWORD_VERSION=v1
# ODIC_RP_CLIENT_SECRET SECRET_AWS_S3_SECRET_ACCESS_KEY_VERSION=v1
SECRET_OIDC_RPCS_VERSION=v1 SECRET_OIDC_RP_CLIENT_SECRET_VERSION=v1
# DJANGO_SUPERUSER_PASSWORD SECRET_DJANGO_SECRET_KEY_VERSION=v1
SECRET_DJANGO_SP_VERSION=v1 SECRET_DJANGO_SUPERUSER_PASSWORD_VERSION=v1
# MINIO_ROOT_PASSWORD SECRET_DJANGO_EMAIL_HOST_PASSWORD_VERSION=v1
SECRET_MINIO_RP_VERSION=v1
# MINIO_ROOT_USER ##############################################################################
SECRET_MINIO_RU_VERSION=v1 # BASIC SETTINGS
# POSTGRES_PASSWORD ##############################################################################
SECRET_POSTGRES_P_VERSION=v1
# Y_PROVIDER_API_KEY
SECRET_Y_API_KEY_VERSION=v1
# DJANGO_HOST_EMAIL_PASSWORD
SECRET_EMAIL_PASS_VERSION=v1
# JWT_PRIVATE_KEY of the backend (RSA PEM, must be inserted manually, see README)
SECRET_JWT_PK_VERSION=v1 # generate=false
# YHUB_JWT_PRIVATE_KEY of the collaboration server (RSA PEM, must be inserted manually, see README)
SECRET_YHUB_JWT_PK_VERSION=v1 # generate=false
############################################################################## ##############################################################################
# EMAIL # EMAIL
@@ -39,28 +30,28 @@ DJANGO_EMAIL_BRAND_NAME="La Suite Numérique"
DJANGO_EMAIL_HOST="mail.example.com" DJANGO_EMAIL_HOST="mail.example.com"
DJANGO_EMAIL_LOGO_IMG="http://$DOMAIN/assets/logo-suite-numerique.png" DJANGO_EMAIL_LOGO_IMG="http://$DOMAIN/assets/logo-suite-numerique.png"
DJANGO_EMAIL_PORT=1025 DJANGO_EMAIL_PORT=1025
DJANGO_EMAIL_USE_SSL=True
DJANGO_EMAIL_USE_TLS=False
DJANGO_EMAIL_FROM=mail@example.com
############################################################################## ##############################################################################
# SINGLE SIGN ON # SINGLE SIGN ON
############################################################################## ##############################################################################
# NOTE: OpenID Connect (OIDC) single sign-on is **required**, see recipe README # NOTE: OpenID Connect (OIDC) single sign-on is **required**, see recipe README
OIDC_REALM=yourkeycloakrealm ## Set those according to your needs
AUTH_DOMAIN=yourkeycloakdomain OIDC_RP_CLIENT_ID=docs
OIDC_OP_JWKS_ENDPOINT=https://${AUTH_DOMAIN}/realms/${OIDC_REALM}/protocol/openid-connect/certs REALM_NAME=
OIDC_OP_AUTHORIZATION_ENDPOINT=https://${AUTH_DOMAIN}/realms/${OIDC_REALM}/protocol/openid-connect/auth SSO_DOMAIN=
OIDC_OP_TOKEN_ENDPOINT=https://${AUTH_DOMAIN}/realms/${OIDC_REALM}/protocol/openid-connect/token
OIDC_OP_USER_ENDPOINT=https://${AUTH_DOMAIN}/realms/${OIDC_REALM}/protocol/openid-connect/userinfo ## These can probably be left as-is
OIDC_RP_CLIENT_ID=yourkeycloakclientid OIDC_OP_JWKS_ENDPOINT=https://${SSO_DOMAIN}/realms/${REALM_NAME}/protocol/openid-connect/certs
OIDC_OP_AUTHORIZATION_ENDPOINT=https://${SSO_DOMAIN}/realms/${REALM_NAME}/protocol/openid-connect/auth
OIDC_OP_TOKEN_ENDPOINT=https://${SSO_DOMAIN}/realms/${REALM_NAME}/protocol/openid-connect/token
OIDC_OP_USER_ENDPOINT=https://${SSO_DOMAIN}/realms/${REALM_NAME}/protocol/openid-connect/userinfo
OIDC_RP_SIGN_ALGO=RS256 OIDC_RP_SIGN_ALGO=RS256
OIDC_RP_SCOPES="openid email" OIDC_RP_SCOPES="openid email"
LOGIN_REDIRECT_URL=https://${DOMAIN} LOGIN_REDIRECT_URL=https://${DOMAIN}
LOGIN_REDIRECT_URL_FAILURE=https://${DOMAIN} LOGIN_REDIRECT_URL_FAILURE=https://${DOMAIN}
LOGOUT_REDIRECT_URL=https://${DOMAIN} LOGOUT_REDIRECT_URL=https://${DOMAIN}
OIDC_REDIRECT_ALLOWED_HOSTS='["https://auth.${DOMAIN}", "https://${DOMAIN}"]' OIDC_REDIRECT_ALLOWED_HOSTS='["https://id.docs.coop", "https://${DOMAIN}"]'
OIDC_AUTH_REQUEST_EXTRA_PARAMS='{"acr_values": "eidas1"}' #OIDC_AUTH_REQUEST_EXTRA_PARAMS="{'acr_values'='eidas1'}"
############################################################################## ##############################################################################
# LOGGING # LOGGING
@@ -68,53 +59,3 @@ OIDC_AUTH_REQUEST_EXTRA_PARAMS='{"acr_values": "eidas1"}'
LOGGING_LEVEL_HANDLERS_CONSOLE=INFO LOGGING_LEVEL_HANDLERS_CONSOLE=INFO
LOGGING_LEVEL_LOGGERS_ROOT=INFO LOGGING_LEVEL_LOGGERS_ROOT=INFO
LOGGING_LEVEL_LOGGERS_APP=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
##############################################################################
# COLLABORATION SERVER (yhub) - SOFT MIGRATION
##############################################################################
# Since v6 the document content lives in the collaboration server, not in the
# media bucket. With SOFT_MIGRATION, a pre-v6 document is copied over the first
# time it is opened. Only set to false once
# `abra app cmd <app-name> backend migrate_documents` has covered all documents
# (or on a fresh v6 install); unmigrated documents would otherwise open empty.
# SOFT_MIGRATION=true
-30
View File
@@ -1,30 +0,0 @@
# Lasuite-Docs Recipe Maintenance
All contributions should be made via pull requests.
## Pull Requests
A pull request can be merged directly into `main` by any maintainer.
No approval is needed, but pull requests should be tested as working before merge.
## Dependency Updates
- patch updates proposed from renovate bot are merged directly -
if there is a CVE, also release a new patch version of this recipe
- minor updates proposed from renovate bot are tested by one maintainer
and merged if they don't break, then a new minor version of the recipe
is released
- major updates proposed form renovate bot are tested by two maintainers
and merged if they don't break, then a major version of the recipe is
released.
If the renovate bot PR is older than one week, one maintainer can decide
to merge it anyway.
## Become a maintainer
Everyone can apply to be a recipe maintainer:
1. Watch the repository to get updates.
2. Add yourself to the list in [README.md](./README.md) and open a pull request with the change.
3. Once the pull request is merged, you will be added to the
[La Suite maintainers team](https://git.coopcloud.tech/org/coop-cloud/teams/lasuite-maintainers).
+6 -80
View File
@@ -4,7 +4,6 @@
<!-- metadata --> <!-- metadata -->
* **Maintainer**: [@trav](https://git.coopcloud.tech/trav), [@notplants](https://git.coopcloud.tech/notplants), [@ineiti](https://git.coopcloud.tech/ineiti)
* **Category**: Apps * **Category**: Apps
* **Status**: 2 * **Status**: 2
* **Image**: [`lasuite/docs`](https://hub.docker.com/r/lasuite/docs), 4, upstream * **Image**: [`lasuite/docs`](https://hub.docker.com/r/lasuite/docs), 4, upstream
@@ -18,88 +17,15 @@
## Quick start ## Quick start
* Deploy Single Sign On (see [Authentication](#authentication) below)
* `abra app new lasuite-docs --secrets` * `abra app new lasuite-docs --secrets`
* Insert the two RSA keys, which abra cannot generate (see below)
* `abra app config <app-name>` * `abra app config <app-name>`
* `abra app deploy <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). For more, see [`docs.coopcloud.tech`](https://docs.coopcloud.tech).
* Migrations run automatically on backend startup. To trigger manually: `abra app cmd <app-name> backend migrate` ## Authentication
* Minio buckets are created automatically on first deploy. To manually trigger: `abra app cmd <app-name> minio minio_initialize`
## RSA keys Docs **requires** an OpenID Connect (OIDC) single sign-on provider; we recommend [Authentik](https://git.coopcloud.tech/coop-cloud/authentik) or [Keycloak](https://git.coopcloud.tech/coop-cloud/keycloak), both of which are installable using Co-op Cloud.
Since v6, the backend and the collaboration server (`yhub`) authenticate each other with signed tokens. Each needs its own RSA private key, never the same one:
```
openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 -out jwt.pem
openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 -out yhub-jwt.pem
abra app secret insert <app-name> jwt_pk v1 jwt.pem -f
abra app secret insert <app-name> yhub_jwt_pk v1 yhub-jwt.pem -f
rm jwt.pem yhub-jwt.pem
```
## Upgrading from v5 to v6
v6 replaces the collaboration server. Document content moves from the minio bucket to the new `yhub` service, which stores it in its own `yhub` database. If you skip the migration, every existing document opens **empty**. See [UPGRADE.md](https://github.com/suitenumerique/docs/blob/main/UPGRADE.md) upstream for details.
1. Insert the two RSA keys (see "RSA keys" above). The `collab_ss` secret is no longer used.
2. Leave `SOFT_MIGRATION` at its default (`true`) and deploy. The `yhub` schema is created on startup. A document is copied to yhub the first time someone opens it.
3. Copy all remaining documents: `abra app cmd <app-name> backend migrate_documents`. You can pass arguments, e.g. `abra app cmd <app-name> backend migrate_documents -- --dry-run`. Re-run it with `--retry-failed` if some documents failed.
4. Only after that, you may set `SOFT_MIGRATION=false`. Keep the minio bucket and its object versions: they hold the document history from before v6.
## Configure Authentication
lasuite-docs **requires** an OpenID Connect (OIDC) single sign-on provider; deployment has been tested with [Keycloak](https://git.coopcloud.tech/coop-cloud/keycloak), which we recommend, or you could also try [Authentik](https://git.coopcloud.tech/coop-cloud/authentik), both of which are installable using Co-op Cloud.
Instructions for integrating keycloak with docs after deploying it, are below.
* In keycloak, create a realm (save the name of this realm, you will need it later)
* Within that realm, create a client
* during client creation, ensure:
- Standard flow: True
- Direct access grants: True
- Authorization: True
- Client authentication: True
- PKCE method: none
* Within the client tab, for your client, click on "Credentials". Click on the the copy button to copy "Client Secret" so you can insert this into your coop cloud deployment in the next step.
* `abra app secret insert <app-name> oidc_rpcs v2 <yoursecret>`
* `abra app config <app-name>` # set SECRET_OIDC_RPCS_VERSION=v2
* Now create a user for this client within keycloak. Within the Users tab, click "Add User". Any username and password works. Save this info.
You then additionally need to modify the config of docs to point to your keycloak deployment.
* `abra app config <app-name>`
```
OIDC_REALM=<the realm you configured in keycloak>
AUTH_DOMAIN=<the domain of your keycloak instance>
OIDC_RP_CLIENT_ID=<yourkeycloakclientid>
```
then redeploy docs:
`abra app deploy <app-name> --force`
at this point, when you go to your docs url, you shoud then be able to click "login" and login with the username and password for the user you created in keycloak.
you can make additional users in keycloak for this "client" and they will all be able to login to docs and collaborate.
## Configure E-Mail
Using `abra app config <app-name>` you need to set the following for your smtp server:
```
DJANGO_EMAIL_HOST="yourmailserver.com"
DJANGO_EMAIL_PORT=1025
DJANGO_EMAIL_FROM=noreply@example.com
```
You then need to insert the password for your smtp server as a secret:
* `abra app secret insert <app-name> email_pass v2 <youremailpass>`
* `abra app config <app-name>` # set SECRET_EMAIL_PASS_VERSION=v2
Then redeploy the app, and automated e-mail sending should work:
`abra app deploy <app-name> --force`
-16
View File
@@ -1,16 +0,0 @@
#!/bin/sh
set -e
[ -f /run/secrets/postgres_p ] && export DB_PASSWORD="$(cat /run/secrets/postgres_p)"
[ -f /run/secrets/django_sk ] && export DJANGO_SECRET_KEY="$(cat /run/secrets/django_sk)"
[ -f /run/secrets/minio_rp ] && export AWS_S3_SECRET_ACCESS_KEY="$(cat /run/secrets/minio_rp)"
[ -f /run/secrets/minio_ru ] && export AWS_S3_ACCESS_KEY_ID="$(cat /run/secrets/minio_ru)"
[ -f /run/secrets/django_sp ] && export DJANGO_SUPERUSER_PASSWORD="$(cat /run/secrets/django_sp)"
[ -f /run/secrets/oidc_rpcs ] && export OIDC_RP_CLIENT_SECRET="$(cat /run/secrets/oidc_rpcs)"
[ -f /run/secrets/y_api_key ] && export Y_PROVIDER_API_KEY="$(cat /run/secrets/y_api_key)"
[ -f /run/secrets/email_pass ] && export DJANGO_EMAIL_HOST_PASSWORD="$(cat /run/secrets/email_pass)"
# if not in "env" mode, then execute the original entrypoint and command
if [ ! "$1" = "-e" ]; then
exec "$@"
fi
+12 -22
View File
@@ -1,28 +1,18 @@
# Set any config versions here # Set any config versions here
# Docs: https://docs.coopcloud.tech/maintainers/handbook/#manage-configs # Docs: https://docs.coopcloud.tech/maintainers/handbook/#manage-configs
export ABRA_ENTRYPOINT_VERSION=v6 export NGINX_CONF_VERSION=v2
export NGINX_CONF_VERSION=v4 export PG_BACKUP_VERSION=v3
export PG_BACKUP_VERSION=v5
export MINIO_INITIALIZE_VERSION=v2
export MIGRATE_VERSION=v1
environment() { export MINIO_ENTRYPOINT_VERSION=v1
# this exports all the secrets as environment variables export MINIO_BOOTSTRAP_ENTRYPOINT_VERSION=v8
source /abra-entrypoint.sh -e export YPROVIDER_ENTRYPOINT_VERSION=v1
} export BACKEND_ENTRYPOINT_VERSION=v1
export CELERY_ENTRYPOINT_VERSION=v1
# environment() {
# # TODO: Add file_env here
# }
migrate() { migrate() {
/migrate.sh python manage.py migrate --noinput
}
minio_initialize() {
/minio-initialize.sh
}
# Hand all pre-v6 documents from the media bucket over to the collaboration
# server (yhub). Resumable and safe to re-run; extra args are passed through,
# e.g. --dry-run, --retry-failed, --concurrency N
migrate_documents() {
source /abra-entrypoint.sh -e
python manage.py migrate_documents "$@"
} }
+112 -253
View File
@@ -1,14 +1,13 @@
---
# NOTE: based on https://github.com/suitenumerique/docs/pull/855/ and https://github.com/suitenumerique/docs/pull/583/ # NOTE: based on https://github.com/suitenumerique/docs/pull/855/ and https://github.com/suitenumerique/docs/pull/583/
x-common-env: &common-env x-common-env: &common-env
DJANGO_CONFIGURATION: Production DJANGO_CONFIGURATION: Production
DJANGO_ALLOWED_HOSTS: "*" DJANGO_ALLOWED_HOSTS: "*"
# DJANGO_SECRET_KEY supplied via secrets DJANGO_SECRET_KEY_FILE: /run/secrets/django_secret_key
DJANGO_SETTINGS_MODULE: impress.settings DJANGO_SETTINGS_MODULE: impress.settings
# DJANGO_SUPERUSER_PASSWORD supplied via secrets DJANGO_SUPERUSER_PASSWORD_FILE: /run/secrets/django_superuser_password
# Logging # Logging
# Set to DEBUG level for dev only # Set to DEBUG level for dev only
LOGGING_LEVEL_HANDLERS_CONSOLE: LOGGING_LEVEL_HANDLERS_CONSOLE:
@@ -22,17 +21,14 @@ x-common-env: &common-env
DJANGO_EMAIL_LOGO_IMG: DJANGO_EMAIL_LOGO_IMG:
DJANGO_EMAIL_PORT: DJANGO_EMAIL_PORT:
DJANGO_EMAIL_HOST_USER: DJANGO_EMAIL_HOST_USER:
# DJANGO_EMAIL_HOST_PASSWORD supplied via secret DJANGO_EMAIL_HOST_PASSWORD_FILE: /run/secrets/django_email_host_password
DJANGO_EMAIL_USE_SSL:
DJANGO_EMAIL_USE_TLS:
DJANGO_EMAIL_FROM:
# Backend url # Backend url
IMPRESS_BASE_URL: "https://${DOMAIN}" IMPRESS_BASE_URL: "https://${DOMAIN}"
# Media # Media
STORAGES_STATICFILES_BACKEND: django.contrib.staticfiles.storage.StaticFilesStorage STORAGES_STATICFILES_BACKEND: django.contrib.staticfiles.storage.StaticFilesStorage
AWS_S3_ENDPOINT_URL: http://minio:9000 AWS_S3_ENDPOINT_URL: http://minio:9000
# AWS_S3_ACCESS_KEY_ID supplied via secret (this is same MINIO_ROOT_USER) AWS_S3_ACCESS_KEY_ID: user
# AWS_S3_SECRET_ACCESS_KEY supplied via secret (this is same as MINIO_ROOT_PASSWORD) AWS_S3_SECRET_ACCESS_KEY_FILE: /run/secrets/aws_s3_secret_access_key
MEDIA_BASE_URL: https://${DOMAIN} MEDIA_BASE_URL: https://${DOMAIN}
AWS_STORAGE_BUCKET_NAME: docs-media-storage AWS_STORAGE_BUCKET_NAME: docs-media-storage
# OIDC - settings from .env, see .env.sample # OIDC - settings from .env, see .env.sample
@@ -41,7 +37,7 @@ x-common-env: &common-env
OIDC_OP_TOKEN_ENDPOINT: OIDC_OP_TOKEN_ENDPOINT:
OIDC_OP_USER_ENDPOINT: OIDC_OP_USER_ENDPOINT:
OIDC_RP_CLIENT_ID: OIDC_RP_CLIENT_ID:
# OIDC_RP_CLIENT_SECRET supplied via secrets OIDC_RP_CLIENT_SECRET_FILE: /run/secrets/oidc_rp_client_secret
OIDC_RP_SIGN_ALGO: OIDC_RP_SIGN_ALGO:
OIDC_RP_SCOPES: OIDC_RP_SCOPES:
LOGIN_REDIRECT_URL: LOGIN_REDIRECT_URL:
@@ -51,84 +47,43 @@ x-common-env: &common-env
OIDC_AUTH_REQUEST_EXTRA_PARAMS: OIDC_AUTH_REQUEST_EXTRA_PARAMS:
# AI # AI
AI_FEATURE_ENABLED: "false" AI_FEATURE_ENABLED: "false"
OPENAI_SDK_BASE_URL: https://openaiendpoint.com AI_BASE_URL: https://openaiendpoint.com
OPENAI_SDK_API_KEY: password AI_API_KEY: password
AI_MODEL: llama AI_MODEL: llama
# Collaboration server (yhub), reached in-stack # Collaboration
YHUB_API_BASE_URL: http://yhub:3002 COLLABORATION_API_URL: https://$DOMAIN/collaboration/api/
# RSA key signing the tokens the backend presents to yhub and y-provider
JWT_PRIVATE_KEY_FILE: /run/secrets/jwt_pk
# 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 x-postgres-env: &postgres-env
# Postgresql db container configuration # Postgresql db container configuration
POSTGRES_DB: docs POSTGRES_DB: docs
POSTGRES_USER: docs POSTGRES_USER: docs
POSTGRES_PASSWORD_FILE: /run/secrets/postgres_p POSTGRES_PASSWORD_FILE: /run/secrets/postgres_password
# App database configuration # App database configuration
DB_HOST: db DB_HOST: db
DB_NAME: docs DB_NAME: docs
DB_USER: docs DB_USER: docs
DB_PASSWORD_FILE: /run/secrets/postgres_password
DB_PORT: 5432 DB_PORT: 5432
# DB_PASSWORD supplied via secrets (this is same as POSTGRES_PASSWORD)
x-yprovider-env: &yprovider-env x-yprovider-env: &yprovider-env
COLLABORATION_LOGGING: "true" COLLABORATION_LOGGING: "true"
# Y_PROVIDER_API_KEY supplied via secrets Y_PROVIDER_API_KEY: foobar
COLLABORATION_API_URL: http://y-provider:4444/api/
COLLABORATION_SERVER_ORIGIN: https://${DOMAIN} COLLABORATION_SERVER_ORIGIN: https://${DOMAIN}
COLLABORATION_SERVER_SECRET_FILE: /run/secrets/collaboration_server_secret
COLLABORATION_BACKEND_BASE_URL: https://${DOMAIN} COLLABORATION_BACKEND_BASE_URL: https://${DOMAIN}
# The last segment is YHUB_ORG (default: docs) COLLABORATION_WS_URL: wss://${DOMAIN}/collaboration/ws/
COLLABORATION_WS_URL: wss://${DOMAIN}/collaboration/ws/v1/docs
x-yhub-env: &yhub-env
PORT: 3002
REDIS: redis://yhub-valkey:6379
# POSTGRES is built from the postgres_p secret in the entrypoint
COLLABORATION_BACKEND_BASE_URL: https://${DOMAIN}
COLLABORATION_SERVER_ORIGIN: https://${DOMAIN}
Y_PROVIDER_API_KEY_FILE: /run/secrets/y_api_key
YHUB_JWT_PRIVATE_KEY_FILE: /run/secrets/yhub_jwt_pk
# Seed documents from the pre-v6 media bucket the first time they are opened.
# Only turn off once `abra app cmd <app> backend migrate_documents` covered all documents.
SOFT_MIGRATION: "${SOFT_MIGRATION:-true}"
LEGACY_S3_ENDPOINT_URL: http://minio:9000
LEGACY_S3_ACCESS_KEY_ID_FILE: /run/secrets/minio_ru
LEGACY_S3_SECRET_ACCESS_KEY_FILE: /run/secrets/minio_rp
LEGACY_S3_BUCKET_NAME: docs-media-storage
x-minio-env: &minio-env
MINIO_ROOT_USER_FILE: /run/secrets/minio_ru
MINIO_ROOT_PASSWORD_FILE: /run/secrets/minio_rp
services: services:
app: app:
image: lasuite/impress-frontend:v6.0.1 image: lasuite/impress-frontend:v3.6.0
networks: networks:
- backend - backend
deploy: deploy:
labels: labels:
- "traefik.enable=false" - "traefik.enable=false"
- "coop-cloud.${STACK_NAME}.timeout=${TIMEOUT:-120}" - "coop-cloud.${STACK_NAME}.timeout=${TIMEOUT:-120}"
- "coop-cloud.${STACK_NAME}.version=0.4.4+v5.6.1" - "coop-cloud.${STACK_NAME}.version=0.3.0+v3.6.0"
user: "${DOCKER_USER:-1000}"
healthcheck: healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080"] test: ["CMD", "curl", "-f", "http://localhost:8080"]
interval: 15s interval: 15s
@@ -137,145 +92,53 @@ services:
start_period: 10s start_period: 10s
backend: backend:
image: lasuite/impress-backend:v6.0.1 image: lasuite/impress-backend:v3.6.0
networks: networks:
- backend - backend
environment: environment:
<<: [*common-env, *postgres-env, *yprovider-env] <<: [*common-env, *postgres-env, *yprovider-env]
AUTO_MIGRATIONS: "${AUTO_MIGRATIONS:-true}" secrets:
- collaboration_server_secret
- postgres_password
- aws_s3_secret_access_key
- oidc_rp_client_secret
- django_secret_key
- django_superuser_password
- django_email_host_password
healthcheck: healthcheck:
test: ["CMD", "/abra-entrypoint.sh", "python", "manage.py", "check"] test: ["CMD", "python", "manage.py", "check"]
interval: 15s interval: 15s
timeout: 30s timeout: 30s
retries: 20 retries: 20
start_period: 10s start_period: 10s
user: "${DOCKER_USER:-1000}"
command: ["gunicorn", "-c", "/usr/local/etc/gunicorn/impress.py", "impress.wsgi:application"]
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
- oidc_rpcs
- minio_rp
- minio_ru
- postgres_p
- y_api_key
- email_pass
- jwt_pk
celery: celery:
image: lasuite/impress-backend:v6.0.1 image: lasuite/impress-backend:v3.6.0
networks: networks:
- backend - 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"] command: ["celery", "-A", "impress.celery_app", "worker", "-l", "INFO"]
environment: environment:
<<: [*common-env, *postgres-env, *yprovider-env] <<: [*common-env, *postgres-env, *yprovider-env]
entrypoint: ["/abra-entrypoint.sh", "/usr/local/bin/entrypoint"]
configs:
- source: abra_entrypoint
target: /abra-entrypoint.sh
mode: 0555
secrets: secrets:
- django_sk - collaboration_server_secret
- django_sp - django_superuser_password
- oidc_rpcs - postgres_password
- minio_rp - aws_s3_secret_access_key
- minio_ru - oidc_rp_client_secret
- postgres_p - django_secret_key
- y_api_key - django_email_host_password
- email_pass
- jwt_pk
# Collaboration server: serves the websocket and holds the document content
yhub:
image: lasuite/impress-yhub:v6.0.1
networks:
- backend
environment: *yhub-env
user: "${DOCKER_USER:-1000}"
healthcheck:
test: ["CMD", "node", "-e", "fetch('http://localhost:3002/collaboration/ready/v1').then(r=>process.exit(r.ok?0:1),()=>process.exit(1))"]
interval: 15s
timeout: 5s
retries: 20
start_period: 30s
# The server never creates its schema: run the idempotent init-db before every start
entrypoint: >
sh -c "export POSTGRES=\"postgres://docs:$$(node -e 'process.stdout.write(encodeURIComponent(require(\"fs\").readFileSync(\"/run/secrets/postgres_p\",\"utf8\").trim()))')@db:5432/yhub\" && node node_modules/@y/hub/bin/init-db.js && exec /usr/local/bin/entrypoint \"$$@\"" --
command: ["node", "--import", "./dist/sentry.js", "dist/server.js"]
secrets:
- postgres_p
- y_api_key
- yhub_jwt_pk
- minio_ru
- minio_rp
# Valkey of yhub: holds updates not yet persisted to postgres, so it is a store, not a cache
yhub-valkey:
image: valkey/valkey:8.1.10-alpine
command: ["valkey-server", "--maxmemory-policy", "volatile-lru", "--appendonly", "yes", "--appendfsync", "everysec"]
healthcheck:
test: ["CMD", "valkey-cli", "ping"]
interval: 15s
timeout: 5s
retries: 3
networks:
- backend
volumes:
- yhub_valkey:/data
deploy:
labels:
backupbot.backup: "${ENABLE_BACKUPS:-true}"
# Conversion service only since v6 (no longer serves the collaboration)
y-provider: y-provider:
image: lasuite/impress-y-provider:v6.0.1 image: lasuite/impress-y-provider:v3.6.0
networks: 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"]
secrets: secrets:
- y_api_key - collaboration_server_secret
environment: *yprovider-env
docspec: # NOTE: healthcheck - `wget` is available in the container, but `wget http://localhost:4444` gives a 403
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: db:
image: pgautoupgrade/pgautoupgrade:18-debian image: postgres:16
networks: networks:
- backend - backend
healthcheck: healthcheck:
@@ -285,82 +148,73 @@ services:
retries: 300 retries: 300
environment: environment:
<<: *postgres-env <<: *postgres-env
PGDATA: /var/lib/postgresql/data/pgdata PGDATA: var/lib/postgresql/data/pgdata
volumes: volumes:
- postgres:/var/lib/postgresql/data/pgdata - postgres:/var/lib/postgresql/data/pgdata
secrets:
- postgres_password
deploy: deploy:
labels: labels:
backupbot.backup: "${ENABLE_BACKUPS:-true}" backupbot.backup: "${ENABLE_BACKUPS:-true}"
backupbot.backup.pre-hook: "/pg_backup.sh backup" backupbot.backup.pre-hook: "/pg_backup.sh backup"
backupbot.backup.volumes.postgres.path: "backup.sql,backup-yhub.sql" backupbot.backup.volumes.postgres.path: "backup.sql"
backupbot.restore.post-hook: '/pg_backup.sh restore' backupbot.restore.post-hook: '/pg_backup.sh restore'
configs: configs:
- source: pg_backup - source: pg_backup
target: /pg_backup.sh target: /pg_backup.sh
mode: 0555 mode: 0555
secrets:
- postgres_p
redis: redis:
image: redis:8.10.2 image: redis:8
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 15s
timeout: 5s
retries: 3
networks: networks:
- backend - backend
minio-bootstrap:
# NOTE: Not started by default, only run with a manual `abra app restart` / `docker service scale`
image: minio/mc:RELEASE.2025-08-13T08-35-41Z
environment:
- MINIO_ROOT_USER=minio
- MINIO_ROOT_PASSWORD_FILE=/run/secrets/minio_root_password
networks:
- backend
secrets:
- minio_root_password
deploy:
mode: replicated
replicas: 0
restart_policy:
condition: none
minio: minio:
image: bitnamilegacy/minio:2025.7.23-debian-12-r5 image: minio/minio:RELEASE.2025-09-07T16-13-09Z
user: root environment:
environment: *minio-env - MINIO_ROOT_USER=minio
- MINIO_ROOT_PASSWORD_FILE=/run/secrets/minio_root_password
secrets:
- minio_root_password
healthcheck: healthcheck:
test: ["CMD", "mc", "ready", "local"] test: ["CMD", "mc", "ready", "local"]
interval: 1s interval: 1s
timeout: 20s timeout: 20s
retries: 300 retries: 300
entrypoint: ""
networks: networks:
- backend - backend
command: /opt/bitnami/scripts/minio/run.sh command: minio server /data
entrypoint: >
sh -c "/minio-initialize.sh & exec /opt/bitnami/scripts/minio/entrypoint.sh \"$$@\"" --
volumes: volumes:
- minio:/bitnami/minio/data - minio:/data
deploy: deploy:
labels: labels:
backupbot.backup: "${ENABLE_BACKUPS:-true}" backupbot.backup: "${ENABLE_BACKUPS:-true}"
entrypoint: /abra-entrypoint.sh
configs:
- source: abra_entrypoint
target: /abra-entrypoint.sh
mode: 0555
- source: minio_initialize
target: /minio-initialize.sh
mode: 0555
secrets:
- minio_rp
- minio_ru
web: web:
image: nginx:1.31.7 image: nginx:1.29
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8083"]
interval: 15s
timeout: 5s
retries: 3
start_period: 10s
configs: configs:
- source: nginx_conf - source: nginx_conf
target: /etc/nginx/conf.d/default.conf target: /etc/nginx/conf.d/default.conf
networks: networks:
proxy: proxy:
backend: backend:
depends_on:
- backend
- app
environment:
- STACK_NAME
deploy: deploy:
labels: labels:
- "traefik.enable=true" - "traefik.enable=true"
@@ -379,54 +233,59 @@ networks:
volumes: volumes:
postgres: postgres:
minio: minio:
yhub_valkey:
configs: configs:
nginx_conf: nginx_conf:
name: ${STACK_NAME}_nginx_conf_${NGINX_CONF_VERSION} name: ${STACK_NAME}_nginx_conf_${NGINX_CONF_VERSION}
file: nginx.conf.tmpl file: nginx.conf
template_driver: golang
pg_backup: pg_backup:
name: ${STACK_NAME}_pg_backup_${PG_BACKUP_VERSION} name: ${STACK_NAME}_pg_backup_${PG_BACKUP_VERSION}
file: pg_backup.sh file: pg_backup.sh
abra_entrypoint: minio_entrypoint:
name: ${STACK_NAME}_entrypoint_${ABRA_ENTRYPOINT_VERSION} name: ${STACK_NAME}_minio_entrypoint_${MINIO_ENTRYPOINT_VERSION}
file: abra-entrypoint.sh file: entrypoint-minio.sh.tmpl
minio_initialize: template_driver: golang
name: ${STACK_NAME}_minio_initialize_${MINIO_INITIALIZE_VERSION} minio_bootstrap_entrypoint:
file: minio-initialize.sh name: ${STACK_NAME}_minio_bootstrap_entrypoint_${MINIO_BOOTSTRAP_ENTRYPOINT_VERSION}
migrate: file: entrypoint-minio-bootstrap.sh.tmpl
name: ${STACK_NAME}_migrate_${MIGRATE_VERSION} template_driver: golang
file: migrate.sh yprovider_entrypoint:
name: ${STACK_NAME}_yprovider_entrypoint_${YPROVIDER_ENTRYPOINT_VERSION}
file: entrypoint-yprovider.sh.tmpl
template_driver: golang
backend_entrypoint:
name: ${STACK_NAME}_backend_entrypoint_${BACKEND_ENTRYPOINT_VERSION}
file: entrypoint-backend.sh.tmpl
template_driver: golang
celery_entrypoint:
name: ${STACK_NAME}_celery_entrypoint_${CELERY_ENTRYPOINT_VERSION}
file: entrypoint-celery.sh.tmpl
template_driver: golang
secrets: secrets:
django_sk: minio_root_password:
name: ${STACK_NAME}_minio_root_password_${SECRET_MINIO_ROOT_PASSWORD_VERSION}
external: true external: true
name: ${STACK_NAME}_django_sk_${SECRET_DJANGO_SK_VERSION} collaboration_server_secret:
oidc_rpcs: name: ${STACK_NAME}_collaboration_server_secret_${SECRET_COLLABORATION_SERVER_SECRET_VERSION}
external: true external: true
name: ${STACK_NAME}_oidc_rpcs_${SECRET_OIDC_RPCS_VERSION} postgres_password:
django_sp: name: ${STACK_NAME}_postgres_password_${SECRET_POSTGRES_PASSWORD_VERSION}
external: true external: true
name: ${STACK_NAME}_django_sp_${SECRET_DJANGO_SP_VERSION} aws_s3_secret_access_key:
postgres_p: name: ${STACK_NAME}_aws_s3_secret_access_key_${SECRET_AWS_S3_SECRET_ACCESS_KEY_VERSION}
external: true external: true
name: ${STACK_NAME}_postgres_p_${SECRET_POSTGRES_P_VERSION} oidc_rp_client_secret:
jwt_pk: name: ${STACK_NAME}_oidc_rp_client_secret_${SECRET_OIDC_RP_CLIENT_SECRET_VERSION}
external: true external: true
name: ${STACK_NAME}_jwt_pk_${SECRET_JWT_PK_VERSION} django_secret_key:
yhub_jwt_pk: name: ${STACK_NAME}_django_secret_key_${SECRET_DJANGO_SECRET_KEY_VERSION}
external: true external: true
name: ${STACK_NAME}_yhub_jwt_pk_${SECRET_YHUB_JWT_PK_VERSION} django_superuser_password:
minio_rp: name: ${STACK_NAME}_django_superuser_password_${SECRET_DJANGO_SUPERUSER_PASSWORD_VERSION}
external: true external: true
name: ${STACK_NAME}_minio_rp_${SECRET_MINIO_RP_VERSION} django_email_host_password:
minio_ru: name: ${STACK_NAME}_django_email_host_passsword_${SECRET_DJANGO_EMAIL_HOST_PASSWORD_VERSION}
external: true external: true
name: ${STACK_NAME}_minio_ru_${SECRET_MINIO_RP_VERSION}
y_api_key:
external: true
name: ${STACK_NAME}_y_api_key_${SECRET_Y_API_KEY_VERSION}
email_pass:
external: true
name: ${STACK_NAME}_email_pass_${SECRET_EMAIL_PASS_VERSION}
+40
View File
@@ -0,0 +1,40 @@
#!/usr/bin/env bash
file_env() {
# 3wc: Load $VAR_FILE into $VAR - useful for secrets. See
# https://medium.com/@adrian.gheorghe.dev/using-docker-secrets-in-your-environment-variables-7a0609659aab
local var="$1"
local fileVar="${var}_FILE"
local def="${2:-}"
if [ "${!var:-}" ] && [ "${!fileVar:-}" ]; then
echo >&2 "error: both $var and $fileVar are set (but are exclusive)"
exit 1
fi
local val="$def"
if [ "${!var:-}" ]; then
val="${!var}"
elif [ "${!fileVar:-}" ]; then
val="$(< "${!fileVar}")"
fi
export "$var"="$val"
unset "$fileVar"
}
load_vars() {
file_env "COLLABORATION_SERVER_SECRET"
file_env "POSTGRES_PASSWORD"
file_env "AWS_S3_SECRET_ACCESS_KEY"
file_env "OIDC_RP_CLIENT_SECRET"
file_env "DJANGO_SECRET_KEY"
file_env "DJANGO_EMAIL_HOST_PASSWORD"
file_env "DJANGO_SUPERUSER_PASSWORD"
}
set -eu
load_vars
set +eu
/usr/local/bin/entrypoint
+39
View File
@@ -0,0 +1,39 @@
#!/usr/bin/env bash
file_env() {
# 3wc: Load $VAR_FILE into $VAR - useful for secrets. See
# https://medium.com/@adrian.gheorghe.dev/using-docker-secrets-in-your-environment-variables-7a0609659aab
local var="$1"
local fileVar="${var}_FILE"
local def="${2:-}"
if [ "${!var:-}" ] && [ "${!fileVar:-}" ]; then
echo >&2 "error: both $var and $fileVar are set (but are exclusive)"
exit 1
fi
local val="$def"
if [ "${!var:-}" ]; then
val="${!var}"
elif [ "${!fileVar:-}" ]; then
val="$(< "${!fileVar}")"
fi
export "$var"="$val"
unset "$fileVar"
}
load_vars() {
file_env "COLLABORATION_SERVER_SECRET"
file_env "POSTGRES_PASSWORD"
file_env "AWS_S3_SECRET_ACCESS_KEY"
file_env "OIDC_RP_CLIENT_SECRET"
file_env "DJANGO_SECRET_KEY"
file_env "DJANGO_EMAIL_HOST_PASSWORD"
file_env "DJANGO_SUPERUSER_PASSWORD"
}
set -eu
load_vars
set +eu
celery -A impress.celery_app worker -l INFO
+39
View File
@@ -0,0 +1,39 @@
#!/usr/bin/env bash
file_env() {
# 3wc: Load $VAR_FILE into $VAR - useful for secrets. See
# https://medium.com/@adrian.gheorghe.dev/using-docker-secrets-in-your-environment-variables-7a0609659aab
local var="$1"
local fileVar="${var}_FILE"
local def="${2:-}"
if [ "${!var:-}" ] && [ "${!fileVar:-}" ]; then
echo >&2 "error: both $var and $fileVar are set (but are exclusive)"
exit 1
fi
local val="$def"
if [ "${!var:-}" ]; then
val="${!var}"
elif [ "${!fileVar:-}" ]; then
val="$(< "${!fileVar}")"
fi
export "$var"="$val"
unset "$fileVar"
}
load_vars() {
file_env "MINIO_ROOT_PASSWORD"
}
set -eu
load_vars
set +eu
set -x
/usr/bin/mc alias set docs http://minio:9000 $MINIO_ROOT_USER $MINIO_ROOT_PASSWORD --api S3v4
/usr/bin/mc mb --ignore-existing docs/docs-media-storage
/usr/bin/mc mb version enable docs/docs-media-storage
exit 0
+34
View File
@@ -0,0 +1,34 @@
#!/usr/bin/env bash
file_env() {
# 3wc: Load $VAR_FILE into $VAR - useful for secrets. See
# https://medium.com/@adrian.gheorghe.dev/using-docker-secrets-in-your-environment-variables-7a0609659aab
local var="$1"
local fileVar="${var}_FILE"
local def="${2:-}"
if [ "${!var:-}" ] && [ "${!fileVar:-}" ]; then
echo >&2 "error: both $var and $fileVar are set (but are exclusive)"
exit 1
fi
local val="$def"
if [ "${!var:-}" ]; then
val="${!var}"
elif [ "${!fileVar:-}" ]; then
val="$(< "${!fileVar}")"
fi
export "$var"="$val"
unset "$fileVar"
}
load_vars() {
file_env "MINIO_ROOT_PASSWORD"
}
set -eu
load_vars
set +eu
minio server data
+33
View File
@@ -0,0 +1,33 @@
#!/usr/bin/env bash
file_env() {
# 3wc: Load $VAR_FILE into $VAR - useful for secrets. See
# https://medium.com/@adrian.gheorghe.dev/using-docker-secrets-in-your-environment-variables-7a0609659aab
local var="$1"
local fileVar="${var}_FILE"
local def="${2:-}"
if [ "${!var:-}" ] && [ "${!fileVar:-}" ]; then
echo >&2 "error: both $var and $fileVar are set (but are exclusive)"
exit 1
fi
local val="$def"
if [ "${!var:-}" ]; then
val="${!var}"
elif [ "${!fileVar:-}" ]; then
val="$(< "${!fileVar}")"
fi
export "$var"="$val"
unset "$fileVar"
}
load_vars() {
file_env "COLLABORATION_SERVER_SECRET"
}
set -eu
load_vars
set +eu
/usr/local/bin/entrypoint
-26
View File
@@ -1,26 +0,0 @@
#!/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"
-34
View File
@@ -1,34 +0,0 @@
#!/bin/sh
set -e
# Use an isolated mc config dir: the bundled Bitnami image runs its own
# internal mc client (as the "minio" user) against the default /.mc path,
# which collides with this script running as root against the same path.
export MC_CONFIG_DIR=/tmp/mc-docs-init
# 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"
+7 -16
View File
@@ -1,9 +1,9 @@
upstream docs_backend { upstream docs_backend {
server {{ env "STACK_NAME" }}_backend:8000 fail_timeout=0; server backend:8000 fail_timeout=0;
} }
upstream docs_frontend { upstream docs_frontend {
server {{ env "STACK_NAME" }}_app:8080 fail_timeout=0; server app:8080 fail_timeout=0;
} }
server { server {
@@ -47,14 +47,7 @@ server {
try_files $uri @proxy_to_docs_backend; try_files $uri @proxy_to_docs_backend;
} }
location /external_api { # Proxy auth for collaboration server
try_files $uri @proxy_to_docs_backend;
}
# Collaboration server (yhub). Only the routes below are published: it also
# serves prune, create-ydoc, reset-connections, migrate, restore-ydoc and
# reset-ydoc, which the backend calls in-stack and which must not be
# reachable from the outside.
location /collaboration/ws/ { location /collaboration/ws/ {
# Ensure WebSocket upgrade # Ensure WebSocket upgrade
proxy_http_version 1.1; proxy_http_version 1.1;
@@ -62,7 +55,7 @@ server {
proxy_set_header Connection "Upgrade"; proxy_set_header Connection "Upgrade";
# Collaboration server # Collaboration server
proxy_pass http://{{ env "STACK_NAME" }}_yhub:3002; proxy_pass http://y-provider:4444;
# Set appropriate timeout for WebSocket # Set appropriate timeout for WebSocket
proxy_read_timeout 86400; proxy_read_timeout 86400;
@@ -74,11 +67,9 @@ server {
proxy_set_header Host $host; proxy_set_header Host $host;
} }
# Document routes (http fallback, history) and the public keys of yhub location /collaboration/api/ {
location ~ ^/collaboration/(ydoc|activity|changeset|rollback|jwks)/ { # Collaboration server
proxy_pass http://{{ env "STACK_NAME" }}_yhub:3002; proxy_pass http://y-provider:4444;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header Origin $http_origin;
proxy_set_header Host $host; proxy_set_header Host $host;
} }
+3 -14
View File
@@ -3,20 +3,15 @@
set -e set -e
BACKUP_FILE='/var/lib/postgresql/data/pgdata/backup.sql' BACKUP_FILE='/var/lib/postgresql/data/pgdata/backup.sql'
# database of the collaboration server (yhub), since v6
YHUB_DB='yhub'
YHUB_BACKUP_FILE='/var/lib/postgresql/data/pgdata/backup-yhub.sql'
function backup { function backup {
export PGPASSWORD=$(cat $POSTGRES_PASSWORD_FILE) # export PGPASSWORD=$(cat $POSTGRES_PASSWORD_FILE)
export PGPASSWORD="$POSTGRES_PASSWORD"
pg_dump -U ${POSTGRES_USER} ${POSTGRES_DB} > $BACKUP_FILE pg_dump -U ${POSTGRES_USER} ${POSTGRES_DB} > $BACKUP_FILE
if psql -U ${POSTGRES_USER} -d postgres -tAc "SELECT 1 FROM pg_database WHERE datname='${YHUB_DB}'" | grep -q 1; then
pg_dump -U ${POSTGRES_USER} ${YHUB_DB} > $YHUB_BACKUP_FILE
fi
} }
function restore { function restore {
cd /var/lib/postgresql/data/pgdata/ cd /var/lib/postgresql/data/
restore_config(){ restore_config(){
# Restore allowed connections # Restore allowed connections
cat pg_hba.conf.bak > pg_hba.conf cat pg_hba.conf.bak > pg_hba.conf
@@ -33,12 +28,6 @@ function restore {
createdb -U ${POSTGRES_USER} ${POSTGRES_DB} createdb -U ${POSTGRES_USER} ${POSTGRES_DB}
psql -U ${POSTGRES_USER} -d ${POSTGRES_DB} -1 -f $BACKUP_FILE psql -U ${POSTGRES_USER} -d ${POSTGRES_DB} -1 -f $BACKUP_FILE
if [ -f $YHUB_BACKUP_FILE ]; then
psql -U ${POSTGRES_USER} -d postgres -c "DROP DATABASE IF EXISTS ${YHUB_DB} WITH (FORCE);"
createdb -U ${POSTGRES_USER} ${YHUB_DB}
psql -U ${POSTGRES_USER} -d ${YHUB_DB} -1 -f $YHUB_BACKUP_FILE
fi
trap - EXIT INT TERM trap - EXIT INT TERM
restore_config restore_config
} }
-8
View File
@@ -1,8 +0,0 @@
after upgrading to this version, its necessary to run the data migration again, via:
`abra app cmd <app-name> backend migrate`
this release updates to a new version that fixes a security vulnerability,
in addition to adding new features
-4
View File
@@ -1,4 +0,0 @@
upgraded to v4.5.0, and also switched from postgres:16 to pgautoupgrade/pgautoupgrade:18-bookworm
for automatic major version upgrades
no actions by operator should be necessary
-22
View File
@@ -1,22 +0,0 @@
⚠️ Major upgrade to Docs v6: the collaboration server is replaced by the new `yhub`
service, and existing documents have to be migrated to it, or they open EMPTY.
Before deploying, generate and insert two RSA keys:
openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 -out jwt.pem
openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 -out yhub-jwt.pem
abra app secret insert <app-name> jwt_pk v1 jwt.pem -f
abra app secret insert <app-name> yhub_jwt_pk v1 yhub-jwt.pem -f
and add to your app config:
SECRET_JWT_PK_VERSION=v1 # generate=false
SECRET_YHUB_JWT_PK_VERSION=v1 # generate=false
`SECRET_COLLAB_SS_VERSION` and the `collab_ss` secret are no longer used.
After deploying (SOFT_MIGRATION is on by default), migrate all documents:
abra app cmd <app-name> backend migrate_documents
Only then may you set SOFT_MIGRATION=false. See the README for details.
-6
View File
@@ -1,6 +0,0 @@
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": [
"config:recommended"
]
}