diff --git a/lasuite/bin/README.md b/lasuite/bin/README.md new file mode 100644 index 0000000..5dacadf --- /dev/null +++ b/lasuite/bin/README.md @@ -0,0 +1 @@ +helper scripts go here diff --git a/lasuite/data/README.md b/lasuite/data/README.md new file mode 100644 index 0000000..4dbaded --- /dev/null +++ b/lasuite/data/README.md @@ -0,0 +1 @@ +service state and logs go here diff --git a/lasuite/docs/bin/README.md b/lasuite/docs/bin/README.md new file mode 100644 index 0000000..5dacadf --- /dev/null +++ b/lasuite/docs/bin/README.md @@ -0,0 +1 @@ +helper scripts go here diff --git a/lasuite/docs/data/README.md b/lasuite/docs/data/README.md new file mode 100644 index 0000000..4dbaded --- /dev/null +++ b/lasuite/docs/data/README.md @@ -0,0 +1 @@ +service state and logs go here diff --git a/lasuite/docs/docker-compose.yaml b/lasuite/docs/docker-compose.yaml new file mode 100644 index 0000000..f1dcbdc --- /dev/null +++ b/lasuite/docs/docker-compose.yaml @@ -0,0 +1,197 @@ +services: + postgresql: + image: postgres:16 + healthcheck: + test: ["CMD", "pg_isready", "-q", "-U", "docs", "-d", "docs"] + interval: 1s + timeout: 2s + retries: 300 + env_file: + - .env + environment: + - PGDATA=/var/lib/postgresql/data/pgdata + + # Postgresql db container configuration + - POSTGRES_DB=docs + - POSTGRES_USER=docs + - POSTGRES_PASSWORD=${DB_PASSWORD} + volumes: + - ./data/databases/backend:/var/lib/postgresql/data/pgdata + + redis: + image: redis:5 + restart: always + volumes: + - "redis-data:/data" + healthcheck: + test: + - CMD + - redis-cli + - ping + interval: 5s + timeout: 20s + retries: 10 + + backend: + image: lasuite/impress-backend:latest + user: ${DOCKER_USER:-1000} + restart: always + environment: + # - SERVICE_FQDN_BACKEND_8000 + # App database configuration + - DB_HOST=postgresql + - DB_NAME=docs + - DB_USER=docs + - DB_PASSWORD=${DB_PASSWORD} + - DB_PORT=5432 + # Common variables + - DOCS_HOST=${DOCS_HOST} + - S3_HOST=${S3_HOST} + - MINIO_HOST=${MINIO_HOST} + - BACKEND_HOST=${BACKEND_HOST} + - FRONTEND_HOST=${FRONTEND_HOST} + - BUCKET_NAME=docs-media-storage + - REALM_NAME=docs + # Backend variables## Django + - DJANGO_ALLOWED_HOSTS=${DOCS_HOST} + - DJANGO_SECRET_KEY=${DJANGO_SECRET_KEY} + - DJANGO_SETTINGS_MODULE=impress.settings + - DJANGO_CONFIGURATION=Production + + # Logging + # Set to DEBUG level for dev only + - LOGGING_LEVEL_HANDLERS_CONSOLE=ERROR + - LOGGING_LEVEL_LOGGERS_ROOT=INFO + - LOGGING_LEVEL_LOGGERS_APP=INFO + + # Python + - PYTHONPATH=/app + + # Mail + - DJANGO_EMAIL_HOST=${DJANGO_EMAIL_HOST} + - DJANGO_EMAIL_HOST_USER=${DJANGO_EMAIL_HOST_USER} + - DJANGO_EMAIL_HOST_PASSWORD=${DJANGO_EMAIL_HOST_PASSWORD} + - DJANGO_EMAIL_PORT=${DJANGO_EMAIL_PORT} + - DJANGO_EMAIL_FROM=${DJANGO_EMAIL_FROM} + + #DJANGO_EMAIL_USE_TLS=true # A flag to enable or disable TLS for email sending. + #DJANGO_EMAIL_USE_SSL=true # A flag to enable or disable SSL for email sending. + + - DJANGO_EMAIL_BRAND_NAME="Monadical" + # DJANGO_EMAIL_LOGO_IMG="https://${DOCS_HOST}/assets/logo-suite-numerique.png" + + # Media + - AWS_S3_ENDPOINT_URL=https://${S3_HOST} + - AWS_S3_ACCESS_KEY_ID=${AWS_S3_ACCESS_KEY_ID} + - AWS_S3_SECRET_ACCESS_KEY=${AWS_S3_SECRET_ACCESS_KEY} + - AWS_STORAGE_BUCKET_NAME=${BUCKET_NAME} + - MEDIA_BASE_URL=https://${DOCS_HOST} + + # OIDC + - OIDC_OP_JWKS_ENDPOINT=${OIDC_OP_JWKS_ENDPOINT} + - OIDC_OP_AUTHORIZATION_ENDPOINT=${OIDC_OP_AUTHORIZATION_ENDPOINT} + - OIDC_OP_TOKEN_ENDPOINT=${OIDC_OP_TOKEN_ENDPOINT} + - OIDC_OP_USER_ENDPOINT=${OIDC_OP_USER_ENDPOINT} + - OIDC_OP_LOGOUT_ENDPOINT=${OIDC_OP_LOGOUT_ENDPOINT} + - OIDC_RP_CLIENT_ID=${OIDC_RP_CLIENT_ID} + - OIDC_RP_CLIENT_SECRET=${OIDC_RP_CLIENT_SECRET} + - OIDC_RP_SIGN_ALGO=RS256 + - OIDC_RP_SCOPES=openid email profile + - OIDC_STORE_ID_TOKEN=True + - OIDC_STORE_ACCESS_TOKEN=True + #USER_OIDC_FIELD_TO_SHORTNAME + #USER_OIDC_FIELDS_TO_FULLNAME + + - LOGIN_REDIRECT_URL=https://${DOCS_HOST} + - LOGIN_REDIRECT_URL_FAILURE=https://${DOCS_HOST} + - LOGOUT_REDIRECT_URL=https://${DOCS_HOST} + - OIDC_REDIRECT_ALLOWED_HOSTS=["https://${DOCS_HOST}"] + + # AI + - AI_FEATURE_ENABLED=true # is false by default + - AI_BASE_URL=${AI_BASE_URL} + - AI_API_KEY=${AI_API_KEY} + - AI_MODEL=${AI_MODEL} # e.g. llama + # Frontend + #FRONTEND_THEME=mytheme + #FRONTEND_CSS_URL=https://storage.yourdomain.tld/themes/custom.css + #FRONTEND_FOOTER_FEATURE_ENABLED=true + #FRONTEND_URL_JSON_FOOTER=https://docs.domain.tld/contents/footer-demo.json + env_file: + - .env + # networks: + # - proxy-tier + healthcheck: + test: ["CMD", "python", "manage.py", "check"] + interval: 15s + timeout: 30s + retries: 20 + start_period: 10s + depends_on: + postgresql: + condition: service_healthy + restart: true + redis: + condition: service_started + + yprovider: + image: lasuite/impress-y-provider:latest + user: ${DOCKER_USER:-1000} + environment: + # - SERVICE_FQDN_YPROVIDER_4444 + - Y_PROVIDER_API_KEY=${Y_PROVIDER_API_KEY} + - COLLABORATION_SERVER_SECRET=${COLLABORATION_SERVER_SECRET} + - COLLABORATION_SERVER_ORIGIN=https://${DOCS_HOST} + - COLLABORATION_API_URL=https://${DOCS_HOST}/collaboration/api/ + - COLLABORATION_WS_URL=wss://${DOCS_HOST}/collaboration/ws/ + - COLLABORATION_BACKEND_BASE_URL=https://${DOCS_HOST} + - COLLABORATION_LOGGING=true + + minio: + image: minio/minio + env_file: + - .env + environment: + - MINIO_ROOT_USER=${MINIO_ROOT_USER} + - MINIO_ROOT_PASSWORD=${MINIO_ROOT_PASSWORD} + - MINIO_BROWSER_REDIRECT_URL=https://ui.${MINIO_HOST} + - SERVICE_FQDN_MINIO_9000 + # - SERVICE_FQDN_MINIO_9001 + healthcheck: + test: ["CMD", "mc", "ready", "local"] + interval: 1s + timeout: 20s + retries: 300 + entrypoint: "" + command: minio server /data + volumes: + - ./data/minio:/data + + frontend: + image: lasuite/impress-frontend:latest + user: "101" + # environment: + # - SERVICE_FQDN_FRONTEND_3000 + env_file: + - .env + depends_on: + backend: + condition: service_healthy + # networks: + # - proxy-tier + + nginx: + image: nginx + environment: + - SERVICE_FQDN_NGINX_80 + env_file: + - .env + volumes: + - html:/usr/share/nginx/html + - ./etc/nginx:/etc/nginx/conf.d + # - /var/run/docker.sock:/tmp/docker.sock:ro + # networks: + # - proxy-tier +# networks: +# proxy-tier: +# external: true diff --git a/lasuite/docs/env.d/backend b/lasuite/docs/env.d/backend new file mode 100644 index 0000000..70ae247 --- /dev/null +++ b/lasuite/docs/env.d/backend @@ -0,0 +1,65 @@ +## Django +DJANGO_ALLOWED_HOSTS=${DOCS_HOST} +DJANGO_SECRET_KEY= +DJANGO_SETTINGS_MODULE=impress.settings +DJANGO_CONFIGURATION=Production + +# Logging +# Set to DEBUG level for dev only +LOGGING_LEVEL_HANDLERS_CONSOLE=ERROR +LOGGING_LEVEL_LOGGERS_ROOT=INFO +LOGGING_LEVEL_LOGGERS_APP=INFO + +# Python +PYTHONPATH=/app + +# Mail +DJANGO_EMAIL_HOST= +DJANGO_EMAIL_HOST_USER= +DJANGO_EMAIL_HOST_PASSWORD= +DJANGO_EMAIL_PORT= +DJANGO_EMAIL_FROM= + +#DJANGO_EMAIL_USE_TLS=true # A flag to enable or disable TLS for email sending. +#DJANGO_EMAIL_USE_SSL=true # A flag to enable or disable SSL for email sending. + +DJANGO_EMAIL_BRAND_NAME="La Suite Numérique" +DJANGO_EMAIL_LOGO_IMG="https://${DOCS_HOST}/assets/logo-suite-numerique.png" + +# Media +AWS_S3_ENDPOINT_URL=https://${S3_HOST} +AWS_S3_ACCESS_KEY_ID= +AWS_S3_SECRET_ACCESS_KEY= +AWS_STORAGE_BUCKET_NAME=${BUCKET_NAME} +MEDIA_BASE_URL=https://${DOCS_HOST} + +# OIDC +OIDC_OP_JWKS_ENDPOINT=https://${KEYCLOAK_HOST}/realms/${REALM_NAME}/protocol/openid-connect/certs +OIDC_OP_AUTHORIZATION_ENDPOINT=https://${KEYCLOAK_HOST}/realms/${REALM_NAME}/protocol/openid-connect/auth +OIDC_OP_TOKEN_ENDPOINT=https://${KEYCLOAK_HOST}/realms/${REALM_NAME}/protocol/openid-connect/token +OIDC_OP_USER_ENDPOINT=https://${KEYCLOAK_HOST}/realms/${REALM_NAME}/protocol/openid-connect/userinfo +OIDC_OP_LOGOUT_ENDPOINT=https://${KEYCLOAK_HOST}/realms/${REALM_NAME}/protocol/openid-connect/logout +OIDC_RP_CLIENT_ID= +OIDC_RP_CLIENT_SECRET= +OIDC_RP_SIGN_ALGO=RS256 +OIDC_RP_SCOPES="openid email" +#USER_OIDC_FIELD_TO_SHORTNAME +#USER_OIDC_FIELDS_TO_FULLNAME + +LOGIN_REDIRECT_URL=https://${DOCS_HOST} +LOGIN_REDIRECT_URL_FAILURE=https://${DOCS_HOST} +LOGOUT_REDIRECT_URL=https://${DOCS_HOST} + +OIDC_REDIRECT_ALLOWED_HOSTS=["https://${DOCS_HOST}"] + +# AI +#AI_FEATURE_ENABLED=true # is false by default +#AI_BASE_URL=https://openaiendpoint.com +#AI_API_KEY= +#AI_MODEL= e.g. llama + +# Frontend +#FRONTEND_THEME=mytheme +#FRONTEND_CSS_URL=https://storage.yourdomain.tld/themes/custom.css +#FRONTEND_FOOTER_FEATURE_ENABLED=true +#FRONTEND_URL_JSON_FOOTER=https://docs.domain.tld/contents/footer-demo.json diff --git a/lasuite/docs/env.d/common b/lasuite/docs/env.d/common new file mode 100644 index 0000000..1660ad6 --- /dev/null +++ b/lasuite/docs/env.d/common @@ -0,0 +1,7 @@ +DOCS_HOST=docs.domain.tld +S3_HOST=storage.domain.tld +MINIO_HOST=storage.domain.tld +BACKEND_HOST=backend +FRONTEND_HOST=frontend +BUCKET_NAME=docs-media-storage +REALM_NAME=docs diff --git a/lasuite/docs/env.d/yprovider b/lasuite/docs/env.d/yprovider new file mode 100644 index 0000000..b2a3cbe --- /dev/null +++ b/lasuite/docs/env.d/yprovider @@ -0,0 +1,7 @@ +Y_PROVIDER_API_KEY= +COLLABORATION_SERVER_SECRET= +COLLABORATION_SERVER_ORIGIN=https://${DOCS_HOST} +COLLABORATION_API_URL=https://${DOCS_HOST}/collaboration/api/ +COLLABORATION_WS_URL=wss://${DOCS_HOST}/collaboration/ws/ +COLLABORATION_BACKEND_BASE_URL=https://${DOCS_HOST} +COLLABORATION_LOGGING=true diff --git a/lasuite/docs/etc/README.md b/lasuite/docs/etc/README.md new file mode 100644 index 0000000..68bb048 --- /dev/null +++ b/lasuite/docs/etc/README.md @@ -0,0 +1 @@ +config files go here diff --git a/lasuite/docs/etc/nginx/default.conf b/lasuite/docs/etc/nginx/default.conf new file mode 100644 index 0000000..cf19cac --- /dev/null +++ b/lasuite/docs/etc/nginx/default.conf @@ -0,0 +1,117 @@ +upstream docs_backend { + server backend:8000 fail_timeout=0; +} + +upstream docs_frontend { + server frontend:3000 fail_timeout=0; +} + +server { + listen 80; + server_name localhost; + charset utf-8; + + # Disables server version feedback on pages and in headers + server_tokens off; + + + location @proxy_to_docs_backend { + proxy_set_header Host $http_host; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + + proxy_redirect off; + proxy_pass http://docs_backend; + } + + location @proxy_to_docs_frontend { + proxy_set_header Host $http_host; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + + proxy_redirect off; + proxy_pass http://docs_frontend; + } + + location / { + try_files $uri @proxy_to_docs_frontend; + } + + location /api { + try_files $uri @proxy_to_docs_backend; + } + + location /admin { + try_files $uri @proxy_to_docs_backend; + } + + # Proxy auth for collaboration server + location /collaboration/ws/ { + # Ensure WebSocket upgrade + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "Upgrade"; + + # Collaboration server + proxy_pass http://yprovider:4444; + + # Set appropriate timeout for WebSocket + proxy_read_timeout 86400; + proxy_send_timeout 86400; + + # Preserve original host and additional headers + proxy_set_header X-Forwarded-Proto https; + proxy_set_header Origin $http_origin; + proxy_set_header Host $host; + } + + location /collaboration-auth { + proxy_pass http://docs_backend/api/v1.0/documents/collaboration-auth/; + proxy_set_header X-Forwarded-Proto https; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Original-URL $request_uri; + + # Prevent the body from being passed + proxy_pass_request_body off; + proxy_set_header Content-Length ""; + proxy_set_header X-Original-Method $request_method; + } + + location /collaboration/api/ { + # Collaboration server + proxy_pass http://yprovider:4444; + proxy_set_header Host $host; + } + # Proxy auth for media + location /media/ { + # Auth request configuration + auth_request /media-auth; + auth_request_set $authHeader $upstream_http_authorization; + auth_request_set $authDate $upstream_http_x_amz_date; + auth_request_set $authContentSha256 $upstream_http_x_amz_content_sha256; + + # Pass specific headers from the auth response + proxy_set_header Authorization $authHeader; + proxy_set_header X-Amz-Date $authDate; + proxy_set_header X-Amz-Content-SHA256 $authContentSha256; + + # Get resource from Minio + proxy_pass https://storage.app.monadical.io/docs-media-storage/; + proxy_set_header Host storage.app.monadical.io; + + add_header Content-Security-Policy "default-src 'none'" always; + } + + location /media-auth { + proxy_pass http://docs_backend/api/v1.0/documents/media-auth/; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Original-URL $request_uri; + + # Prevent the body from being passed + proxy_pass_request_body off; + proxy_set_header Content-Length ""; + proxy_set_header X-Original-Method $request_method; + } +} \ No newline at end of file diff --git a/lasuite/etc/README.md b/lasuite/etc/README.md new file mode 100644 index 0000000..68bb048 --- /dev/null +++ b/lasuite/etc/README.md @@ -0,0 +1 @@ +config files go here