La suite numérique souveraine et open source qui remplace vraiment les géants américains
@ultisuite/deploy (0.2.3)
Installation
@ultisuite:registry=https://gitea.reduav.eu/api/packages/UltiSuite/npm/npm install @ultisuite/deploy@0.2.3"@ultisuite/deploy": "0.2.3"About this package
@ultisuite/deploy
Installeur et orchestrateur en ligne de commande pour la Ultisuite — alternative souveraine à Google Workspace (mail, drive, agenda, contacts, visio, photos, IA). Le CLI tire les images Docker précompilées depuis le registry Gitea (pas de clone du code source app), génère la configuration, gère le TLS et pilote la stack Compose depuis une interface terminal (Ink).
Installation
Le package est publié sur le registry npm privé Gitea (org ultisuite), pas sur npmjs.org.
1. Configurer le registry @ultisuite
npm config set @ultisuite:registry https://gitea.reduav.eu/api/packages/ultisuite/npm/
npm config set -- '//gitea.reduav.eu/api/packages/ultisuite/npm/:_authToken' '<token-read:package>'
Le token est un PAT Gitea avec au minimum read:package (token pull d’instance / licence, ou compte robot dédié).
2. Installer le CLI
# Global
npm install -g @ultisuite/deploy@latest
# Ou sans install globale
npx @ultisuite/deploy --help
3. Lancer l’install (mode images)
export ULTI_LICENSE_KEY='ulti_…' # clé licence instance
# export ULTI_LICENSE_URL='https://license.example.com' # si hors défaut
ulti-deploy install -y \
--domain suite.example.com \
--tls managed-acme \
--acme-email admin@example.com \
--version v1.2.3 \
--license-key "$ULTI_LICENSE_KEY"
Le CLI échange la licence contre un token pull registry, télécharge le deploy-kit, fait docker login + compose pull + up — sans --build et sans déposer le source Go/Next sur le serveur.
Doc closed-source détaillée : docs/closed-source-deploy.md.
Mode interne (clone + build)
Réservé aux machines qui ont déjà accès aux repos source :
ulti-deploy install -y --dev-source --domain localhost.test --tls none
Prérequis
- Linux avec Docker + Docker Compose v2
- Accès réseau sortant vers
gitea.reduav.eu(registry container + npm + API licence) - Node ≥ 20 (pour
npx/ install globale) - Droits suffisants sur le répertoire de travail (par défaut
/opt/ultisuite) - Clé licence
ULTI_LICENSE_KEY(mode images)
Commandes
| Commande | Description |
|---|---|
ulti-deploy install |
Config, TLS, pull images registry, démarrage (ou --dev-source = clone+build) |
ulti-deploy doctor |
Diagnostic complet (Docker, disque, .env, conteneurs, santé backend, pare-feu) |
ulti-deploy verify |
Teste l'accessibilité externe des domaines publics (DNS, TLS, endpoints HTTP) |
ulti-deploy upgrade |
Met à jour images / kit (ou tags git en mode --dev-source) |
ulti-deploy migrate-to-images |
Passe une ancienne install clone+build vers images (supprime le source) |
ulti-deploy backup |
Exporte une archive chiffrée (config, overrides, état, dumps PostgreSQL, object storage) |
ulti-deploy restore <archive> |
Restaure une archive chiffrée puis redémarre la stack |
ulti-deploy start / stop / restart / status / logs |
Cycle de vie de la stack |
ulti-deploy privacy-check |
Smoke RGPD + contrôle anti-fuite source (mode images) |
Option globale -w, --workspace <dir> pour cibler un autre répertoire de travail.
Mode non-interactif & dry-run
install, upgrade, backup et restore acceptent un mode sans wizard Ink — obligatoire pour les agents et l'automatisation CI :
# Installation prod (ACME + images)
ulti-deploy install -y \
--domain suite.example.com \
--tls managed-acme --acme-email admin@example.com \
--hosts-mode subdomain \
--version v1.2.3 \
--license-key "$ULTI_LICENSE_KEY" \
--enable-module ai --enable-module stalwart
# Config JSON (partiel) + surcharges CLI
ulti-deploy install -y --config ./deploy.json --enable-module jitsi --license-key "$ULTI_LICENSE_KEY"
# Dry-run : génère .env + overrides, sans Docker
ulti-deploy install -y --dry-run --domain suite.example.com --tls none --license-key "$ULTI_LICENSE_KEY"
install
| Flag | Description |
|---|---|
-y, --non-interactive |
Sans wizard |
-c, --config <file> |
JSON partiel (voir ci-dessous) |
--dry-run |
Pas de démarrage Docker |
--version <tag> |
Tag images / deploy-kit (ex. v1.2.3) |
--license-key <key> |
Clé licence (ou env ULTI_LICENSE_KEY) |
--license-url <url> |
API licence (défaut / env ULTI_LICENSE_URL) |
--dev-source |
Clone git + build local (interne) |
--no-build |
Pas de rebuild (mode --dev-source) |
--domain, --tls, --acme-email, --cert, --key |
Domaine & TLS |
--hosts-mode path|subdomain |
URLs apex vs sous-domaines |
--cookie-domain |
Cookie SSO (ex. .example.com) |
--backend-ref, --client-ref |
Tag/branche git (--dev-source only) |
--enable-module, --disable-module |
Modules (répétables) : nextcloud, jitsi, immich, onlyoffice, ai, richtext, stalwart, sovereign |
upgrade
ulti-deploy upgrade --check-only # liste sans appliquer
ulti-deploy upgrade -y --yes --no-backup # applique sans prompt
| Flag | Description |
|---|---|
-y, --non-interactive |
Sans prompts |
--yes |
Applique (sinon exit 2 si MAJ dispo) |
--check-only |
Détection seule |
--backup-password / --backup-password-env |
Backup pré-upgrade |
--no-backup |
Saute le backup |
backup / restore
export ULTI_DEPLOY_BACKUP_PASSWORD='…'
ulti-deploy backup -y -o ./backups/manual.ultibak
export ULTI_DEPLOY_RESTORE_PASSWORD='…'
ulti-deploy restore -y --yes ./backups/manual.ultibak
| backup | restore |
|---|---|
--password / --password-env (ULTI_DEPLOY_BACKUP_PASSWORD) |
--password / --password-env (ULTI_DEPLOY_RESTORE_PASSWORD) |
--include env,overrides,state,database,objectStorage,… |
--yes requis (destructif) |
--no-restart |
Doc agents détaillée : .cursor/rules/ulti-deploy-cli.mdc (dans ce repo).
Exemple de deploy.json (tous les champs sont optionnels sauf domain) :
{
"domain": "suite.example.com",
"workspaceDir": "/opt/ultisuite",
"modules": { "ai": true, "stalwart": true },
"tls": { "mode": "managed-acme", "acmeEmail": "admin@example.com" },
"secrets": { "POSTGRES_PASSWORD": "mon-secret-impose" }
}
Les secrets non fournis sont générés aléatoirement ; ceux présents dans secrets sont conservés.
Répertoire de travail
Mode images (défaut prod) :
/opt/ultisuite/
├─ deploy-kit/ kit Compose (nginx, overlays, .env.example) — pas de source app
├─ overrides/ fichiers générés (compose TLS, nginx, certs)
├─ backups/ archives .ultibak
└─ state.json état (config + version images déployée)
Mode --dev-source (interne) :
/opt/ultisuite/
├─ ulti-backend/ clone backend (build context Docker)
├─ gmail-interface-clone/ clone frontend (sibling Compose)
├─ overrides/
├─ backups/
└─ state.json
Configuration & secrets
Le CLI lit le .env.example du backend et génère un .env en :
- remplaçant tous les secrets
changemepar des valeurs aléatoires fortes (chaque secret reste overridable dans l'assistant) ; - préservant les placeholders
{{VAR}}(expansés au runtime, comme le fait le backend) ; - basculant les URLs publiques en
https://<domaine>et le frontend sursuite-frontend:3000; - activant/désactivant les modules optionnels (Nextcloud, Jitsi, Immich, OnlyOffice, UltiAI, Stalwart…).
TLS / certificats
Quatre modes au choix dans l'assistant :
- Let's Encrypt redondant (
managed-acme) : terminateur TLStls-edge+ sidecaracme.shavec bascule automatique entre autorités (Let's Encrypt → ZeroSSL → Buypass). - Certificats custom (
managed-custom) : montage de voscert/key. - Greffe nginx existant (
graft) : génère un server-block pour votre nginx hôte (qui gère le TLS) et bind la stack sur127.0.0.1:<port>. - HTTP seul (
none) : pour le dev ou derrière un autre terminateur TLS.
Sauvegarde & restauration
Les archives .ultibak sont chiffrées en AES-256-GCM (clé dérivée par scrypt du mot de passe). L'assistant permet de choisir quoi inclure : configuration, overrides, état, dumps PostgreSQL (toutes bases), et optionnellement les volumes object storage.
Checklist RGPD (déploiement)
Après installation ou changement de modules :
- Région d'hébergement —
PRIVACY_HOSTING_PROVIDER(défaut OVH) +PRIVACY_DATA_REGION(ex.FR) pour la disclosure. - Contacts confidentialité — renseigner
NEXT_PUBLIC_PRIVACY_CONTACT_EMAILetNEXT_PUBLIC_DPO_EMAILdans le.envfrontend. - Matomo cookieless — si statistiques activées :
NEXT_PUBLIC_MATOMO_URL+NEXT_PUBLIC_MATOMO_SITE_ID(Matomo sur la même infra, pas de bandeau cookies). - Pages légales publiques — vérifier
/privacy,/gdpr,/terms,/subprocessors,/dpa(HTTP 200 sans login). - Sous-traitants dynamiques — après activation d'une intégration externe (IA, OAuth, Stripe, VirusTotal…), contrôler
/subprocessorsetGET /api/v1/privacy/disclosure. - Intégrations org — documenter les webhooks et services tiers configurés par l'organisation auprès des utilisateurs.
- Sauvegardes vs erasure — voir
ulti-backend/docs/compliance/backup-erasure.md: rétention.ultibak, destruction des archives hors délai ; une suppression utilisateur n'efface pas rétroactivement les backups existants. - Restore drill — exercice périodique :
ulti-backend/docs/compliance/restore-drill.md(jamais en prod avec une archive pré-erasure). - Registre incidents — Admin → Confidentialité → registre d'incidents (délai CNIL 72 h) ; procédure
docs/compliance/incident-response.md. - Smoke RGPD —
ulti-deploy privacy-check(pages légales +GET /api/v1/privacy/disclosure). - SOC2 evidence (optionnel B2B) —
ulti-backend/docs/compliance/soc2-evidence.md(export revue d'accès utilisateurs + audit).
SecNumCloud (composition OVH)
- Déployer sur une offre OVH qualifiée SecNumCloud (catalogue ANSSI).
- Activer le module
sovereign(--enable-module sovereign/SOVEREIGN_PROFILE=true) pour dépublier les ports RustFS. - Suivre
ulti-backend/docs/compliance/secnumcloud-3.2-gap.mdetnetwork-segmentation.md. - Accords OVH : checklist
ulti-backend/docs/compliance/ovh-accords-checklist.md. - HDS : guide
ulti-backend/docs/compliance/hds-deploy-ovh.md(profil santé org). - Ne pas revendiquer le Visa SecNumCloud tant que la qualification UltiSuite (composition) n'est pas obtenue.
Smoke test : ulti-deploy verify inclut les endpoints légaux dans PUBLIC_ENDPOINTS.
CDN (prod)
Pour placer un CDN (Cloudflare, Fastly, CloudFront, etc.) devant la suite sans compromettre l’auth :
- Doc complète :
docs/cdn.mddans le deploy-kit / backend ($workspace/deploy-kitou$workspace/ulti-backenden mode source). - Résumé :
NGINX_DEV_NO_CACHE=false,DRIVE_MEDIA_SIGNING_KEYdéfini, cache edge uniquement sur allowlist (/_next/static/*,/api/v1/drive/media/preview?…,/api/v1/fonts/*), bypass sur le reste de/api/v1/*et les pages/mail,/drive.
Développement
pnpm install
pnpm dev -- --help # lance le CLI via tsx
pnpm typecheck
pnpm build # dist/cli.js minifié, sans sourcemaps (tsup)
Publish CI (tag v*) → registry npm Gitea ultisuite (voir .gitea/workflows/publish.yml).
Licence
MIT
Dependencies
Dependencies
| ID | Version |
|---|---|
| commander | ^12.1.0 |
| execa | ^9.5.1 |
| ink | ^5.1.0 |
| ink-big-text | ^2.0.0 |
| ink-gradient | ^3.0.0 |
| ink-select-input | ^6.0.0 |
| ink-spinner | ^5.0.0 |
| ink-text-input | ^6.0.0 |
| react | ^18.3.1 |
| semver | ^7.6.3 |
| tar | ^7.4.3 |
| zod | ^3.23.8 |
Development Dependencies
| ID | Version |
|---|---|
| @types/node | ^22.9.0 |
| @types/react | ^18.3.12 |
| @types/semver | ^7.5.8 |
| tsup | ^8.3.5 |
| tsx | ^4.19.2 |
| typescript | ^5.7.2 |