ultisuite-backend/.env.example
R3D347HR4Y 20c4fef3c6
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
docxi import lol
2026-06-10 00:27:21 +02:00

272 lines
12 KiB
Plaintext

# =============================================================================
# Ulti Backend — Configuration
# =============================================================================
# Secrets : definir UNE FOIS dans la section ci-dessous.
# Le reste du fichier utilise {{NOM_VARIABLE}} — expansion au lancement
# (docker compose, go run, migrate) via cmd/envexpand → .env.resolved
#
# Chaque brique peut etre en mode "local" (stack Docker) ou "external".
# =============================================================================
# -----------------------------------------------------------------------------
# Secrets — source unique (rotation ici uniquement)
# -----------------------------------------------------------------------------
POSTGRES_PASSWORD=changeme
RUSTFS_ACCESS_KEY=ultiadmin
RUSTFS_SECRET_KEY=changeme123
AUTHENTIK_SECRET_KEY=changeme-generate-a-long-random-string
ULTID_OIDC_CLIENT_SECRET=changeme
MAIL_CREDENTIAL_KEYS=v1:MDEyMzQ1Njc4OWFiY2RlZjAxMjM0NTY3ODlhYmNkZWY=
MAIL_ACTIVE_CREDENTIAL_KEY_ID=v1
MAIL_WEBHOOK_SHARED_SECRET=changeme-webhook-signing-secret
NC_ADMIN_PASSWORD=changeme
NC_OIDC_CLIENT_SECRET=changeme
ONLYOFFICE_OIDC_CLIENT_SECRET=changeme
IMMICH_OIDC_CLIENT_SECRET=changeme
JITSI_APP_SECRET=changeme-jwt-secret
JITSI_INTERNAL_AUTH_PASSWORD=changeme
KEYDB_PASSWORD=
MEILISEARCH_API_KEY=changeme
TYPESENSE_API_KEY=changeme
# -----------------------------------------------------------------------------
# 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.
# Exemple dev explicite : ULTID_CORS_ALLOWED_ORIGINS=http://localhost:3004,http://127.0.0.1:3004
# ULTID_CORS_ALLOWED_ORIGINS=
# -----------------------------------------------------------------------------
# PostgreSQL
# Mode local : deploye dans la stack Docker (deploy/docker-compose.yml)
# Mode externe : pointer vers une instance existante
# -----------------------------------------------------------------------------
POSTGRES_USER=ulti
POSTGRES_DB=ultidb
POSTGRES_MULTIPLE_DATABASES=ultidb,authentik,nextcloud,immich
# Connection utilisee par ultid (changer host pour instance externe)
ULTID_DB_URL=postgres://{{POSTGRES_USER}}:{{POSTGRES_PASSWORD}}@postgres:5432/{{POSTGRES_DB}}?sslmode=disable
# Exemple externe :
# ULTID_DB_URL=postgres://user:{{POSTGRES_PASSWORD}}@db.example.com:5432/ultidb?sslmode=require
# -----------------------------------------------------------------------------
# KeyDB (Redis-compatible)
# Mode local : deploye dans la stack
# Mode externe : pointer vers un Redis/KeyDB/Valkey existant
# -----------------------------------------------------------------------------
ULTID_KEYDB_URL=keydb:6379
ULTID_KEYDB_PASSWORD={{KEYDB_PASSWORD}}
ULTID_KEYDB_DB=0
# Exemple externe : ULTID_KEYDB_URL=redis.example.com:6379
KEYDB_HOST=keydb
KEYDB_PORT=6379
# -----------------------------------------------------------------------------
# Object Storage (S3-compatible : RustFS, MinIO, AWS S3, Backblaze, etc.)
# Mode local : RustFS deploye dans la stack
# Mode externe : n'importe quel endpoint S3-compatible
# -----------------------------------------------------------------------------
ULTID_RUSTFS_ENDPOINT=rustfs:9000
ULTID_RUSTFS_ACCESS_KEY={{RUSTFS_ACCESS_KEY}}
ULTID_RUSTFS_SECRET_KEY={{RUSTFS_SECRET_KEY}}
ULTID_RUSTFS_USE_SSL=false
ULTID_RUSTFS_REGION=us-east-1
# Exemple AWS S3 :
# ULTID_RUSTFS_ENDPOINT=s3.amazonaws.com
# ULTID_RUSTFS_USE_SSL=true
# ULTID_RUSTFS_REGION=eu-west-1
# -----------------------------------------------------------------------------
# Auth / OIDC (Authentik, Keycloak, ou tout provider OIDC)
# Mode local : Authentik deploye dans la stack
# Mode externe : n'importe quel provider OIDC existant
# -----------------------------------------------------------------------------
# Issuer vu par ultid (via nginx interne Docker). DOMAIN sert de Host header pour discovery
# afin que l'issuer attendu = iss des tokens navigateur (http://localhost/auth/application/o/ulti/).
ULTID_OIDC_ISSUER=http://nginx/auth/application/o/ulti/
ULTID_OIDC_CLIENT_ID=ulti-backend
# ULTID_OIDC_CLIENT_SECRET — defini dans la section Secrets (doit matcher blueprint Authentik)
ULTID_AUTO_MIGRATE=true
# Exemple Keycloak externe :
# ULTID_OIDC_ISSUER=https://auth.example.com/realms/ulti
# ULTID_OIDC_CLIENT_ID=ulti-backend
# Config du container Authentik local (ignoree si provider externe)
# AUTHENTIK_SECRET_KEY — defini dans la section Secrets
AUTHENTIK_POSTGRESQL__HOST=postgres
AUTHENTIK_POSTGRESQL__USER={{POSTGRES_USER}}
AUTHENTIK_POSTGRESQL__PASSWORD={{POSTGRES_PASSWORD}}
AUTHENTIK_POSTGRESQL__NAME=authentik
AUTHENTIK_REDIS__HOST=keydb
AUTHENTIK_WEB__PATH=/auth/
# URL publique affichee dans les redirects OIDC (navigateur)
AUTHENTIK_HOST=http://{{DOMAIN}}
# 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
# AUTHENTIK_API_TOKEN — defini dans la section Secrets (optionnel ; sinon blueprints seuls)
# -----------------------------------------------------------------------------
# Nextcloud (Drive / Calendar / Contacts)
# Mode local : Nextcloud FPM deploye dans la stack
# Mode externe : instance Nextcloud existante
# -----------------------------------------------------------------------------
# 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_ADMIN_USER=admin
# NC_ADMIN_PASSWORD — defini dans la section Secrets
# Exemple externe :
# NEXTCLOUD_URL=https://cloud.example.com
# NC_ADMIN_USER=ulti-service
# Desactiver (pas de Drive/Cal/Contacts) : NEXTCLOUD_ENABLED=false
NEXTCLOUD_ENABLED=true
# Ce flag pilote aussi le lancement Docker via ./deploy/compose-up.sh
NC_OIDC_CLIENT_ID=ulti-nextcloud
# NC_OIDC_CLIENT_SECRET — defini dans la section Secrets
NC_OIDC_DISCOVERY_URL=http://nginx/auth/application/o/nextcloud/.well-known/openid-configuration
NC_S3_BUCKET=nextcloud
NC_S3_HOST=rustfs
NC_S3_PORT=9000
NC_S3_KEY={{RUSTFS_ACCESS_KEY}}
NC_S3_SECRET={{RUSTFS_SECRET_KEY}}
NC_S3_SSL=false
# -----------------------------------------------------------------------------
# OnlyOffice (Docs / Sheets / Slides)
# -----------------------------------------------------------------------------
ONLYOFFICE_ENABLED=false
ONLYOFFICE_URL=http://onlyoffice
ONLYOFFICE_PUBLIC_URL=http://{{DOMAIN}}/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.
# NC_ONLYOFFICE_STORAGE_URL=http://nginx
# Docker compose OnlyOffice also sets ALLOW_PRIVATE_IP_ADDRESS=true (required for internal URLs)
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}}
# Base URL for public share links (default: {ULTID_PUBLIC_URL}/drive → /drive/s/{token})
# DRIVE_PUBLIC_URL=http://{{DOMAIN}}/drive
# -----------------------------------------------------------------------------
# Rich text editor (TipTap + Hocuspocus)
# -----------------------------------------------------------------------------
RICHTEXT_ENABLED=true
HOCUSPOCUS_PUBLIC_URL=ws://{{DOMAIN}}/collab
HOCUSPOCUS_SECRET=changeme-hocuspocus-secret
RICHTEXT_STORAGE_MODE=sidecar
# RICHTEXT_EXPORT_MIRROR=docx
# -----------------------------------------------------------------------------
# Jitsi Meet (Visioconference)
# Mode local : Jitsi deploye dans la stack
# Mode externe : instance Jitsi existante avec JWT configure
# -----------------------------------------------------------------------------
JITSI_ENABLED=true
# Ce flag pilote aussi le lancement Docker via ./deploy/compose-up.sh
JITSI_DOMAIN=meet.jitsi
JITSI_APP_ID=ulti
# JITSI_APP_SECRET — defini dans la section Secrets
JITSI_PUBLIC_URL=https://{{DOMAIN}}/meet
JICOFO_AUTH_PASSWORD={{JITSI_INTERNAL_AUTH_PASSWORD}}
JVB_AUTH_PASSWORD={{JITSI_INTERNAL_AUTH_PASSWORD}}
JVB_STUN_SERVERS=stun.l.google.com:19302
# -----------------------------------------------------------------------------
# Immich (Photos)
# Mode local : Immich deploye dans la stack
# Mode externe : instance Immich existante
# -----------------------------------------------------------------------------
IMMICH_ENABLED=true
# Ce flag pilote aussi le lancement Docker via ./deploy/compose-up.sh
# Immich utilise son propre Postgres (pgvecto.rs) via immich-postgres
IMMICH_API_URL=http://immich-server:2283/api
# Quota photos partagé avec Ultidrive (0 = désactivé)
ULTID_PHOTOS_MAX_UPLOAD_BYTES=0
ULTID_PHOTOS_QUOTA_RESERVED_BYTES=0
IMMICH_DB_NAME=immich
IMMICH_UPLOAD_LOCATION=/upload
IMMICH_ML_URL=http://immich-ml:3003
# -----------------------------------------------------------------------------
# Health checks / Observability
# -----------------------------------------------------------------------------
# Endpoints vérifiés par /healthz (surchargables pour déploiements externes)
HEALTH_NEXTCLOUD_URL={{NEXTCLOUD_URL}}/status.php
HEALTH_IMMICH_URL={{IMMICH_API_URL}}/server-info/ping
# Par défaut on retire /meet de JITSI_PUBLIC_URL pour viser /about/health
HEALTH_JITSI_URL=https://{{DOMAIN}}/about/health
HEALTH_HTTP_TIMEOUT=3s
# Grafana local (monitoring)
GRAFANA_ADMIN_USER=admin
GRAFANA_ADMIN_PASSWORD=admin
# -----------------------------------------------------------------------------
# Mail (Ultimail) — toujours gere par ultid
# -----------------------------------------------------------------------------
MAIL_ATTACHMENTS_BUCKET=mail-attachments
MAIL_SYNC_INTERVAL=2m
MAIL_OUTBOX_INTERVAL=10s
MAIL_OUTBOX_MAX_RETRIES=8
MAIL_SEND_RATE_PER_MINUTE=30
MAIL_SEND_BURST=10
MAIL_SMTP_CIRCUIT_FAILURES=5
MAIL_SMTP_CIRCUIT_COOLDOWN=5m
# Credentials IMAP/SMTP chiffrés AES-GCM (format keyring: key_id:base64key,key_id2:base64key2)
# Rotation: ajouter nouvelle clé dans MAIL_CREDENTIAL_KEYS puis basculer MAIL_ACTIVE_CREDENTIAL_KEY_ID.
# Les anciennes clés restent présentes temporairement pour déchiffrement.
# Runtime secrets possibles via *_FILE (ex: MAIL_CREDENTIAL_KEYS_FILE=/run/secrets/mail_keys)
# Politique rotation secrets (RFC3339 + durée)
SECRET_ROTATION_MAX_AGE=2160h
ULTID_OIDC_CLIENT_SECRET_ROTATED_AT=2026-01-01T00:00:00Z
MAIL_CREDENTIAL_KEY_ROTATED_AT=2026-01-01T00:00:00Z
# Mail provider OAuth (Gmail / Microsoft 365) — optional
# Redirect URI must match Google/Azure app config, e.g. https://api.example.com/api/v1/mail/accounts/oauth/callback
MAIL_GOOGLE_OAUTH_CLIENT_ID=
MAIL_GOOGLE_OAUTH_CLIENT_SECRET=
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
# Cible nginx → suite frontend unifié mail+drive (dev: Next sur l'hôte :3004 ; prod: suite-frontend:3000)
MAIL_FRONTEND_UPSTREAM=host.docker.internal:3004
MAIL_WEBHOOK_SHARED_SECRET_ROTATED_AT=2026-01-01T00:00:00Z
# -----------------------------------------------------------------------------
# Recherche
# SEARCH_ENGINE: postgres (defaut) | meilisearch | typesense
# -----------------------------------------------------------------------------
SEARCH_ENGINE=postgres
# --- Meilisearch (SEARCH_ENGINE=meilisearch) ---
# MEILISEARCH_URL=http://meilisearch:7700
# MEILISEARCH_API_KEY={{MEILISEARCH_API_KEY}}
# MEILISEARCH_INDEX=ulti
# --- Typesense (SEARCH_ENGINE=typesense) ---
# TYPESENSE_URL=http://typesense:8108
# TYPESENSE_API_KEY={{TYPESENSE_API_KEY}}
# TYPESENSE_COLLECTION=ulti
# -----------------------------------------------------------------------------
# VirusTotal (optional env fallback; prefer admin Settings > File policies)
# -----------------------------------------------------------------------------
# VIRUSTOTAL_API_KEY=