feat(deploy): update .env.example and Authentik blueprints for improved configuration
Some checks are pending
CI / Go tests (push) Waiting to run
CI / Integration tests (push) Waiting to run
CI / DB migrations (push) Waiting to run

- Enhanced .env.example with new variables for PUBLIC_HOST, SECURE, and SUITE_ORIGIN to streamline environment setup.
- Updated Authentik blueprints to utilize the new configuration variables for redirect URIs and launch URLs.
- Introduced a new script to render Authentik blueprint templates dynamically based on environment variables.
- Modified docker-compose files to reference the updated environment variables for better maintainability.
- Improved expose.sh script to derive public URLs from the new configuration, ensuring consistency across deployments.
This commit is contained in:
R3D347HR4Y 2026-06-18 08:14:02 +02:00
parent f97988b51f
commit 125169edee
16 changed files with 260 additions and 45 deletions

View File

@ -28,17 +28,29 @@ JITSI_INTERNAL_AUTH_PASSWORD=changeme
KEYDB_PASSWORD=
MEILISEARCH_API_KEY=changeme
TYPESENSE_API_KEY=changeme
# Cloudflare Tunnel — dev local exposé publiquement (npm run expose)
# Cloudflare Tunnel — dev local exposé publiquement (./deploy/expose.sh)
# CLOUDFLARE_TUNNEL_TOKEN=
# CLOUDFLARE_TUNNEL_PUBLIC_URL=https://dev.ultispace.fr
# CLOUDFLARE_TUNNEL_PUBLIC_URL dérivé de SUITE_ORIGIN (voir section Public suite URL)
# -----------------------------------------------------------------------------
# Public suite URL — modifier PUBLIC_HOST + SECURE pour changer de domaine
# -----------------------------------------------------------------------------
# Nom d'hôte public uniquement (sans schéma) : dev.example.com ou localhost
PUBLIC_HOST=localhost
# "s" → https/wss (tunnel Cloudflare, prod) ; vide → http/ws (nginx local :80)
SECURE=
# Alias nginx / compose (expansion {{PUBLIC_HOST}})
DOMAIN={{PUBLIC_HOST}}
# Origine publique dérivée (http:// ou https:// + hôte)
SUITE_ORIGIN=http{{SECURE}}://{{PUBLIC_HOST}}
CLOUDFLARE_TUNNEL_PUBLIC_URL={{SUITE_ORIGIN}}
# -----------------------------------------------------------------------------
# General
# -----------------------------------------------------------------------------
DOMAIN=localhost
ULTID_PORT=8080
# Origines navigateur autorisees (web app sur autre port/origine que l'API).
# Vide = auto : localhost/127.0.0.1/LAN prive en dev ; http(s)://${DOMAIN} en prod.
# Vide = auto : localhost/127.0.0.1/LAN prive en dev ; SUITE_ORIGIN en prod.
# Exemple dev explicite : ULTID_CORS_ALLOWED_ORIGINS=http://localhost:3004,http://127.0.0.1:3004
# ULTID_CORS_ALLOWED_ORIGINS=
@ -108,7 +120,9 @@ AUTHENTIK_POSTGRESQL__NAME=authentik
AUTHENTIK_REDIS__HOST=keydb
AUTHENTIK_WEB__PATH=/auth/
# URL publique affichee dans les redirects OIDC (navigateur)
AUTHENTIK_HOST=http://{{DOMAIN}}
AUTHENTIK_HOST=http{{SECURE}}://{{PUBLIC_HOST}}
# Authentik provisioning : true quand SECURE=s (sinon déduit de AUTHENTIK_HOST)
# AUTHENTIK_PUBLIC_HTTPS=true
# API interne (ultid → authentik-server) pour provisionner les apps OIDC au demarrage
AUTHENTIK_API_URL=http://authentik-server:9000
# Token admin Authentik (Flows & Stages → Tokens) — active le provisioning API ultid
@ -122,8 +136,8 @@ AUTHENTIK_API_URL=http://authentik-server:9000
# URL interne (ultid → nginx Nextcloud, racine WebDAV)
NEXTCLOUD_URL=http://nextcloud:80
# URL publique UI (edge nginx /cloud/) — aussi base Destination WebDAV MOVE/COPY
NC_PUBLIC_URL=http://{{DOMAIN}}/cloud
NC_OVERWRITE_PROTOCOL=http
NC_PUBLIC_URL=http{{SECURE}}://{{PUBLIC_HOST}}/cloud
NC_OVERWRITE_PROTOCOL=http{{SECURE}}
NC_ADMIN_USER=admin
# NC_ADMIN_PASSWORD — defini dans la section Secrets
# Exemple externe :
@ -150,7 +164,7 @@ NC_S3_SSL=false
# -----------------------------------------------------------------------------
ONLYOFFICE_ENABLED=false
ONLYOFFICE_URL=http://onlyoffice
ONLYOFFICE_PUBLIC_URL=http://{{DOMAIN}}/office
ONLYOFFICE_PUBLIC_URL=http{{SECURE}}://{{PUBLIC_HOST}}/office
# URL ultid joignable depuis le conteneur OnlyOffice (fetch doc + callback)
ONLYOFFICE_API_INTERNAL_URL=http://ultid:8080
# URL Nextcloud joignable depuis OnlyOffice (host nginx Docker). Nginx route /index.php/* → Nextcloud.
@ -159,15 +173,15 @@ ONLYOFFICE_API_INTERNAL_URL=http://ultid:8080
ONLYOFFICE_JWT_SECRET=changeme-onlyoffice-jwt
ONLYOFFICE_OIDC_CLIENT_ID=ulti-onlyoffice
# ONLYOFFICE_OIDC_CLIENT_SECRET — defini dans la section Secrets
ULTID_PUBLIC_URL=http://{{DOMAIN}}
ULTID_PUBLIC_URL=http{{SECURE}}://{{PUBLIC_HOST}}
# Base URL for public share links (default: {ULTID_PUBLIC_URL}/drive → /drive/s/{token})
# DRIVE_PUBLIC_URL=http://{{DOMAIN}}/drive
# DRIVE_PUBLIC_URL=http{{SECURE}}://{{PUBLIC_HOST}}/drive
# -----------------------------------------------------------------------------
# Rich text editor (TipTap + Hocuspocus)
# -----------------------------------------------------------------------------
RICHTEXT_ENABLED=true
HOCUSPOCUS_PUBLIC_URL=ws://{{DOMAIN}}/collab
HOCUSPOCUS_PUBLIC_URL=ws{{SECURE}}://{{PUBLIC_HOST}}/collab
HOCUSPOCUS_SECRET=changeme-hocuspocus-secret
RICHTEXT_STORAGE_MODE=sidecar
# RICHTEXT_EXPORT_MIRROR=docx
@ -183,6 +197,7 @@ AI_GATEWAY_API_KEY=ulti-gateway
BYPASS_MODEL_ACCESS_CONTROL=true
WEBUI_NAME=UltiAI
AI_ASSISTANT_PUBLIC_PATH=/ai
OPENWEBUI_PUBLIC_URL=http{{SECURE}}://{{PUBLIC_HOST}}/ai
ULTIMAIL_MCP_URL=http://ultimail-mcp:3100
# Public MCP endpoint (nginx → ultid → ultimail-mcp): /api/v1/ai/mcp
# OpenWebUI uses AI_GATEWAY_API_KEY + forwarded X-OpenWebUI-User-* headers for per-user tokens.
@ -202,7 +217,7 @@ JITSI_ENABLED=true
JITSI_DOMAIN=meet.jitsi
JITSI_APP_ID=ulti
# JITSI_APP_SECRET — defini dans la section Secrets
JITSI_PUBLIC_URL=https://{{DOMAIN}}/meet
JITSI_PUBLIC_URL=http{{SECURE}}://{{PUBLIC_HOST}}/meet
# Secret partagé avec Jigasi pour POST /api/v1/meet/transcripts
MEET_TRANSCRIPT_WEBHOOK_SECRET=changeme-meet-transcript-secret
# Modèle Faster Whisper (Skynet) : tiny, base, small…
@ -238,7 +253,7 @@ IMMICH_ML_URL=http://immich-ml:3003
HEALTH_NEXTCLOUD_URL={{NEXTCLOUD_URL}}/status.php
HEALTH_IMMICH_URL={{IMMICH_API_URL}}/server-info/ping
# Stack Docker locale : probe interne jitsi-web
# Déploiement externe : https://{{DOMAIN}}/about/health (ou JITSI_PUBLIC_URL sans /meet + /about/health)
# Déploiement externe : {{SUITE_ORIGIN}}/about/health (ou JITSI_PUBLIC_URL sans /meet + /about/health)
HEALTH_JITSI_URL=http://jitsi-web:80/about/health
HEALTH_HTTP_TIMEOUT=3s
# Grafana local (monitoring)
@ -274,7 +289,7 @@ MAIL_MICROSOFT_OAUTH_CLIENT_ID=
MAIL_MICROSOFT_OAUTH_CLIENT_SECRET=
MAIL_MICROSOFT_OAUTH_TENANT=common
MAIL_OAUTH_REDIRECT_URL=
MAIL_APP_URL=http://localhost/mail
MAIL_APP_URL=http{{SECURE}}://{{PUBLIC_HOST}}/mail
# Cible nginx → suite frontend unifié mail+drive (dev: Next sur l'hôte :3004 ; prod: suite-frontend:3000)
# -----------------------------------------------------------------------------

View File

@ -81,12 +81,17 @@ Si `AUTHENTIK_API_TOKEN` est défini, **ultid** provisionne au démarrage les ap
Sans token : les blueprints ci-dessus restent la source (worker Authentik au boot).
Les blueprints OIDC (`*-oidc.yaml`) sont **générés** depuis `*.yaml.template` au lancement de `./deploy/compose-up.sh`, avec les redirect URIs dérivés de `SUITE_ORIGIN` (`PUBLIC_HOST` + `SECURE`). Éditer les `.template`, pas les `.yaml` générés.
## Appliquer / vérifier
```bash
# Re-appliquer après modification
docker exec deploy-authentik-server-1 ak apply_blueprint /blueprints/custom/01-ulti-enrollment.yaml
docker exec deploy-authentik-server-1 ak apply_blueprint /blueprints/custom/02-ulti-brand.yaml
# Re-render + re-appliquer après changement de domaine
./deploy/compose-up.sh restart authentik-worker
# Ou manuellement :
./deploy/authentik/render-blueprints.sh # source .env.resolved d'abord
docker exec deploy-authentik-server-1 ak apply_blueprint /blueprints/custom/ulti-oidc.yaml
./deploy/compose-up.sh restart authentik-worker
# Vérifier OIDC Ultimail

View File

@ -1,4 +1,5 @@
# Authentik blueprint — Nextcloud OIDC (when NEXTCLOUD_ENABLED=true)
# Generated from nextcloud-oidc.yaml.template
# Client secret must match NC_OIDC_CLIENT_SECRET in .env
version: 1
metadata:
@ -22,6 +23,8 @@ entries:
client_id: ulti-nextcloud
client_secret: changeme
redirect_uris:
- matching_mode: strict
url: https://dev.ultispace.fr/cloud/apps/user_oidc/code
- matching_mode: strict
url: http://localhost/cloud/apps/user_oidc/code
- matching_mode: strict
@ -36,5 +39,5 @@ entries:
slug: nextcloud
group: Ulti Suite
provider: !KeyOf nc-oauth-provider
meta_launch_url: http://localhost/cloud/
meta_launch_url: https://dev.ultispace.fr/cloud/
policy_engine_mode: any

View File

@ -0,0 +1,43 @@
# Authentik blueprint — Nextcloud OIDC (when NEXTCLOUD_ENABLED=true)
# Generated from nextcloud-oidc.yaml.template
# Client secret must match NC_OIDC_CLIENT_SECRET in .env
version: 1
metadata:
name: Nextcloud OIDC
labels:
blueprints.goauthentik.io/instantiate: "true"
entries:
- model: authentik_providers_oauth2.oauth2provider
id: nc-oauth-provider
identifiers:
name: ulti-nextcloud-provider
attrs:
name: ulti-nextcloud-provider
authorization_flow: !Find [authentik_flows.flow, [slug, default-provider-authorization-implicit-consent]]
invalidation_flow: !Find [authentik_flows.flow, [slug, default-provider-invalidation-flow]]
property_mappings:
- !Find [authentik_providers_oauth2.scopemapping, [scope_name, openid]]
- !Find [authentik_providers_oauth2.scopemapping, [scope_name, email]]
- !Find [authentik_providers_oauth2.scopemapping, [scope_name, profile]]
client_type: confidential
client_id: ulti-nextcloud
client_secret: changeme
redirect_uris:
- matching_mode: strict
url: {{SUITE_ORIGIN}}/cloud/apps/user_oidc/code
- matching_mode: strict
url: http://localhost/cloud/apps/user_oidc/code
- matching_mode: strict
url: http://127.0.0.1/cloud/apps/user_oidc/code
signing_key: !Find [authentik_crypto.certificatekeypair, [name, authentik Self-signed Certificate]]
- model: authentik_core.application
identifiers:
slug: nextcloud
attrs:
name: Nextcloud
slug: nextcloud
group: Ulti Suite
provider: !KeyOf nc-oauth-provider
meta_launch_url: {{SUITE_ORIGIN}}/cloud/
policy_engine_mode: any

View File

@ -1,4 +1,5 @@
# Authentik blueprint — OnlyOffice OIDC (when ONLYOFFICE_ENABLED=true)
# Generated from onlyoffice-oidc.yaml.template
# Client secret must match ONLYOFFICE_OIDC_CLIENT_SECRET in .env
version: 1
metadata:
@ -22,6 +23,10 @@ entries:
client_id: ulti-onlyoffice
client_secret: changeme
redirect_uris:
- matching_mode: strict
url: https://dev.ultispace.fr/office/
- matching_mode: strict
url: https://dev.ultispace.fr/office/oauth2/callback
- matching_mode: strict
url: http://localhost/office/
- matching_mode: strict
@ -36,5 +41,5 @@ entries:
slug: onlyoffice
group: Ulti Suite
provider: !KeyOf oo-oauth-provider
meta_launch_url: http://localhost/office
meta_launch_url: https://dev.ultispace.fr/office
policy_engine_mode: any

View File

@ -0,0 +1,45 @@
# Authentik blueprint — OnlyOffice OIDC (when ONLYOFFICE_ENABLED=true)
# Generated from onlyoffice-oidc.yaml.template
# Client secret must match ONLYOFFICE_OIDC_CLIENT_SECRET in .env
version: 1
metadata:
name: OnlyOffice OIDC
labels:
blueprints.goauthentik.io/instantiate: "true"
entries:
- model: authentik_providers_oauth2.oauth2provider
id: oo-oauth-provider
identifiers:
name: ulti-onlyoffice-provider
attrs:
name: ulti-onlyoffice-provider
authorization_flow: !Find [authentik_flows.flow, [slug, default-provider-authorization-implicit-consent]]
invalidation_flow: !Find [authentik_flows.flow, [slug, default-provider-invalidation-flow]]
property_mappings:
- !Find [authentik_providers_oauth2.scopemapping, [scope_name, openid]]
- !Find [authentik_providers_oauth2.scopemapping, [scope_name, email]]
- !Find [authentik_providers_oauth2.scopemapping, [scope_name, profile]]
client_type: confidential
client_id: ulti-onlyoffice
client_secret: changeme
redirect_uris:
- matching_mode: strict
url: {{SUITE_ORIGIN}}/office/
- matching_mode: strict
url: {{SUITE_ORIGIN}}/office/oauth2/callback
- matching_mode: strict
url: http://localhost/office/
- matching_mode: strict
url: http://localhost/office/oauth2/callback
signing_key: !Find [authentik_crypto.certificatekeypair, [name, authentik Self-signed Certificate]]
- model: authentik_core.application
identifiers:
slug: onlyoffice
attrs:
name: OnlyOffice
slug: onlyoffice
group: Ulti Suite
provider: !KeyOf oo-oauth-provider
meta_launch_url: {{SUITE_ORIGIN}}/office
policy_engine_mode: any

View File

@ -1,4 +1,5 @@
# Authentik blueprint — Ultimail OIDC (auto-applied on worker startup)
# Generated from ulti-oidc.yaml.template — edit template, not this file directly.
# Client secret must match ULTID_OIDC_CLIENT_SECRET in .env
version: 1
metadata:
@ -25,6 +26,8 @@ entries:
client_id: ulti-backend
client_secret: changeme
redirect_uris:
- matching_mode: strict
url: https://dev.ultispace.fr/api/auth/callback
- matching_mode: strict
url: http://localhost/api/auth/callback
- matching_mode: strict
@ -43,5 +46,5 @@ entries:
slug: ulti
group: Ulti Suite
provider: !KeyOf ulti-oauth-provider
meta_launch_url: http://localhost/mail/inbox
meta_launch_url: https://dev.ultispace.fr/mail/inbox
policy_engine_mode: any

View File

@ -0,0 +1,50 @@
# Authentik blueprint — Ultimail OIDC (auto-applied on worker startup)
# Generated from ulti-oidc.yaml.template — edit template, not this file directly.
# Client secret must match ULTID_OIDC_CLIENT_SECRET in .env
version: 1
metadata:
name: Ultimail OIDC
labels:
blueprints.goauthentik.io/instantiate: "true"
entries:
- model: authentik_providers_oauth2.oauth2provider
id: ulti-oauth-provider
identifiers:
name: ulti-backend-provider
attrs:
name: ulti-backend-provider
authorization_flow: !Find [authentik_flows.flow, [slug, default-provider-authorization-implicit-consent]]
invalidation_flow: !Find [authentik_flows.flow, [slug, default-provider-invalidation-flow]]
access_token_validity: "hours=1"
refresh_token_validity: "days=365"
property_mappings:
- !Find [authentik_providers_oauth2.scopemapping, [scope_name, openid]]
- !Find [authentik_providers_oauth2.scopemapping, [scope_name, email]]
- !Find [authentik_providers_oauth2.scopemapping, [scope_name, profile]]
- !Find [authentik_providers_oauth2.scopemapping, [scope_name, offline_access]]
client_type: confidential
client_id: ulti-backend
client_secret: changeme
redirect_uris:
- matching_mode: strict
url: {{SUITE_ORIGIN}}/api/auth/callback
- matching_mode: strict
url: http://localhost/api/auth/callback
- matching_mode: strict
url: http://127.0.0.1/api/auth/callback
- matching_mode: strict
url: http://localhost:3004/api/auth/callback
- matching_mode: strict
url: http://127.0.0.1:3004/api/auth/callback
signing_key: !Find [authentik_crypto.certificatekeypair, [name, authentik Self-signed Certificate]]
- model: authentik_core.application
identifiers:
slug: ulti
attrs:
name: Ultimail
slug: ulti
group: Ulti Suite
provider: !KeyOf ulti-oauth-provider
meta_launch_url: {{SUITE_ORIGIN}}/mail/inbox
policy_engine_mode: any

View File

@ -0,0 +1,27 @@
#!/usr/bin/env bash
# Render Authentik blueprint templates using PUBLIC_HOST / SECURE / SUITE_ORIGIN from .env.resolved.
set -euo pipefail
ROOT="$(cd "$(dirname "$0")/../.." && pwd)"
BP_DIR="$ROOT/deploy/authentik/blueprints"
if [[ -z "${SUITE_ORIGIN:-}" || -z "${PUBLIC_HOST:-}" ]]; then
echo "render-blueprints: SUITE_ORIGIN and PUBLIC_HOST must be set (source .env.resolved first)" >&2
exit 1
fi
render_one() {
local tpl="$1"
local out="${tpl%.template}"
sed \
-e "s|{{SUITE_ORIGIN}}|${SUITE_ORIGIN}|g" \
-e "s|{{PUBLIC_HOST}}|${PUBLIC_HOST}|g" \
-e "s|{{SECURE}}|${SECURE:-}|g" \
"$tpl" > "$out"
echo "render-blueprints: ${out##*/}"
}
shopt -s nullglob
for tpl in "$BP_DIR"/*.yaml.template; do
render_one "$tpl"
done

View File

@ -34,6 +34,8 @@ set -a
source .env.resolved
set +a
"$ROOT/deploy/authentik/render-blueprints.sh"
compose_files=(
"-f" "deploy/docker-compose.yml"
)

View File

@ -105,7 +105,7 @@ services:
AUTHENTIK_POSTGRESQL__NAME: ${AUTHENTIK_POSTGRESQL__NAME:-authentik}
AUTHENTIK_REDIS__HOST: ${AUTHENTIK_REDIS__HOST:-keydb}
AUTHENTIK_WEB__PATH: /auth/
AUTHENTIK_HOST: http://${DOMAIN:-localhost}
AUTHENTIK_HOST: ${AUTHENTIK_HOST:-http://localhost}
env_file: ../.env.resolved
volumes:
- ./authentik/blueprints:/blueprints/custom:ro
@ -140,7 +140,7 @@ services:
AUTHENTIK_POSTGRESQL__NAME: ${AUTHENTIK_POSTGRESQL__NAME:-authentik}
AUTHENTIK_REDIS__HOST: ${AUTHENTIK_REDIS__HOST:-keydb}
AUTHENTIK_WEB__PATH: /auth/
AUTHENTIK_HOST: http://${DOMAIN:-localhost}
AUTHENTIK_HOST: ${AUTHENTIK_HOST:-http://localhost}
env_file: ../.env.resolved
volumes:
- ./authentik/blueprints:/blueprints/custom:ro
@ -207,15 +207,18 @@ services:
build:
context: ../../gmail-interface-clone
dockerfile: Dockerfile
args:
PUBLIC_HOST: ${PUBLIC_HOST:-localhost}
SECURE: ${SECURE:-}
restart: unless-stopped
environment:
- ULTI_PROXY_ORIGIN=http://nginx
- NEXT_PUBLIC_API_URL=/api/v1
- NEXT_PUBLIC_APP_URL=http://${DOMAIN:-localhost}
- PUBLIC_HOST=${PUBLIC_HOST:-localhost}
- SECURE=${SECURE:-}
- OIDC_CLIENT_SECRET=${ULTID_OIDC_CLIENT_SECRET:-changeme}
- NEXT_PUBLIC_OIDC_ISSUER=http://${DOMAIN:-localhost}/auth/application/o/ulti/
- NEXT_PUBLIC_OIDC_CLIENT_ID=${ULTID_OIDC_CLIENT_ID:-ulti-backend}
- NEXT_PUBLIC_ONLYOFFICE_URL=http://${DOMAIN:-localhost}/office
- NEXT_PUBLIC_AI_PUBLIC_PATH=/ai
networks:
- ulti-net
depends_on:

View File

@ -1,5 +1,5 @@
#!/usr/bin/env bash
# Expose local nginx (:80) via Cloudflare Tunnel (e.g. https://dev.ultispace.fr).
# Expose local nginx (:80) via Cloudflare Tunnel (public URL from SUITE_ORIGIN in .env).
set -euo pipefail
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
@ -10,9 +10,23 @@ if [[ ! -f .env ]]; then
exit 1
fi
RESOLVED="$(mktemp)"
trap 'rm -f "$RESOLVED"' EXIT
if command -v go >/dev/null 2>&1; then
go run ./cmd/envexpand -in .env -out "$RESOLVED"
else
if [[ -x ./bin/envexpand ]]; then
./bin/envexpand -in .env -out "$RESOLVED"
else
echo "Go not found — install Go or build: go build -o bin/envexpand ./cmd/envexpand" >&2
exit 1
fi
fi
set -a
# shellcheck disable=SC1091
source .env
source "$RESOLVED"
set +a
if [[ -z "${CLOUDFLARE_TUNNEL_TOKEN:-}" ]]; then
@ -20,7 +34,7 @@ if [[ -z "${CLOUDFLARE_TUNNEL_TOKEN:-}" ]]; then
exit 1
fi
PUBLIC_URL="${CLOUDFLARE_TUNNEL_PUBLIC_URL:-https://dev.ultispace.fr}"
PUBLIC_URL="${CLOUDFLARE_TUNNEL_PUBLIC_URL:-${SUITE_ORIGIN:-http://localhost}}"
echo "Cloudflare tunnel → local stack (nginx :80)"
echo "Public URL: ${PUBLIC_URL}"
echo "Start stack first: ./deploy/compose-up.sh up -d"

View File

@ -18,7 +18,7 @@ services:
AUTH_TYPE: jwt
JWT_ACCEPTED_ISSUERS: ulti
JWT_ACCEPTED_AUDIENCES: ulti
PUBLIC_URL: https://${DOMAIN:-localhost}/meet
PUBLIC_URL: ${JITSI_PUBLIC_URL:-http://localhost/meet}
XMPP_DOMAIN: meet.jitsi
XMPP_MUC_DOMAIN: muc.meet.jitsi
XMPP_BOSH_URL_BASE: http://jitsi-prosody:5280
@ -70,7 +70,7 @@ services:
XMPP_INTERNAL_MUC_DOMAIN: internal-muc.meet.jitsi
JVB_PORT: "10000"
JVB_STUN_SERVERS: stun.l.google.com:19302
PUBLIC_URL: https://${DOMAIN:-localhost}/meet
PUBLIC_URL: ${JITSI_PUBLIC_URL:-http://localhost/meet}
networks:
- ulti-net
depends_on:

View File

@ -17,7 +17,7 @@ services:
WEBUI_NAME: UltiAI
OPENAI_API_BASE_URL: http://ultid:8080/api/v1/ai
OPENAI_API_KEY: ${AI_GATEWAY_API_KEY:-ulti-gateway}
WEBUI_URL: http://${DOMAIN:-localhost}/ai
WEBUI_URL: ${OPENWEBUI_PUBLIC_URL:-http://localhost/ai}
WEBUI_SECRET_KEY: ${WEBUI_SECRET_KEY:-changeme-openwebui-dev-secret}
DATABASE_URL: postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@postgres:5432/openwebui
USER_PERMISSIONS_CHAT_TEMPORARY_ENFORCED: "false"

View File

@ -91,12 +91,20 @@ func EnsureSuiteApplications(ctx context.Context, pool *pgxpool.Pool, cfg *confi
launchURL = spec.LaunchURL(cfg)
}
// Sync redirect URIs for blueprint- or API-provisioned providers (domain/https changes).
if prov, found, err := client.FindOAuth2ProviderByName(ctx, spec.ProviderName); err != nil {
slog.Warn("authentik provider lookup failed", "app", spec.Key, "error", err)
} else if found && prov.PK != 0 {
if err := client.UpdateOAuth2ProviderRedirects(ctx, prov.PK, redirects); err != nil {
slog.Warn("authentik redirect sync failed", "app", spec.Key, "error", err)
} else {
slog.Info("authentik redirect URIs synced", "app", spec.Key, "count", len(redirects))
}
}
if provisioned, err := IsProvisioned(ctx, pool, spec.Key); err != nil {
return err
} else if provisioned {
if err := syncRedirects(ctx, pool, client, spec.Key, redirects); err != nil {
slog.Warn("authentik redirect sync failed", "app", spec.Key, "error", err)
}
continue
}
@ -122,17 +130,6 @@ func EnsureSuiteApplications(ctx context.Context, pool *pgxpool.Pool, cfg *confi
return nil
}
func syncRedirects(ctx context.Context, pool *pgxpool.Pool, client *Client, appKey string, redirects []string) error {
rec, err := GetProvisioned(ctx, pool, appKey)
if err != nil {
return err
}
if rec.ProviderID == nil || *rec.ProviderID == 0 {
return nil
}
return client.UpdateOAuth2ProviderRedirects(ctx, *rec.ProviderID, redirects)
}
func ensureApp(
ctx context.Context,
client *Client,

View File

@ -487,6 +487,9 @@ func authentikPublicHTTPS() bool {
if envBool("AUTHENTIK_PUBLIC_HTTPS", false) {
return true
}
if strings.TrimSpace(os.Getenv("SECURE")) == "s" {
return true
}
host := strings.TrimSpace(os.Getenv("AUTHENTIK_HOST"))
return strings.HasPrefix(strings.ToLower(host), "https://")
}