# ============================================================ # Omika - Installation de TOUS les services Windows (orchestrateur) # ============================================================ # CIBLE : Windows Server 2025 (SRV-OMIKA), PowerShell ADMINISTRATEUR. # NE PAS executer depuis le poste de developpement. # # Ce script ne fait plus le travail lui-meme : il appelle, DANS L'ORDRE, un # script dedie par deploiement. Chaque service reste installable seul. # # 1. Install-OmikaApi.ps1 (spool JSONL de l'API) # 2. Install-OmikaWorker.ps1 # 3. Install-OmikaDiagnosticsApi.ps1 (spool central) [optionnel] # 4. Install-OmikaDiagnosticsWorker.ps1 (lit les 2 spools) # 5. Install-OmikaDiagnosticsWeb.ps1 # 6. Install-OmikaLanguesApi.ps1 [optionnel] # # POURQUOI CET ORDRE : les ACL inter-services (le Worker Diagnostics lit le # spool produit par l'API et celui produit par l'API centrale) ne peuvent etre # posees que si le dossier existe deja. L'ancien script monolithique posait les # ACL en bloc et IGNORAIT SILENCIEUSEMENT les dossiers absents ; ici, le # proprietaire du dossier est installe AVANT ses lecteurs. # # CE QUE CE SCRIPT NE FAIT PAS : # - AUCUN demarrage de service (doctrine : activation != demarrage). # - AUCUN secret ecrit, AUCUNE regle firewall, AUCUN IIS, AUCUNE base modifiee. # # PREREQUIS MANUELS : # - Comptes locaux dedies crees + droit « Ouvrir une session en tant que # service » (chaque script le verifie et avertit). # - Publications copiees dans \Apps (Install-OmikaServerFiles.ps1). # # IDEMPOTENT - prend en charge -WhatIf. # # EXEMPLES : # .\Install-OmikaServices.ps1 # .\Install-OmikaServices.ps1 -WhatIf # .\Install-OmikaServices.ps1 -InclureLangues -PortLangues 5099 # .\Install-OmikaServices.ps1 -SansDiagnosticsApi # serveur mono-serveur # .\Install-OmikaServices.ps1 -Desinstaller # ============================================================ [CmdletBinding(SupportsShouldProcess = $true)] param( [string]$InstallRoot = 'C:\Omika', # --- Noms de services ---------------------------------------------------- [string]$ApiServiceName = 'OmikaApi', [string]$WorkerServiceName = 'OmikaWorker', [string]$DiagServiceName = 'OmikaDiagnosticsWorker', [string]$DiagWebServiceName = 'OmikaDiagnosticsWeb', [string]$DiagApiServiceName = 'OmikaDiagnosticsApi', [string]$LanguesServiceName = 'OmikaLanguesApi', # --- Comptes de service (jamais LocalSystem, jamais un compte humain) ---- [string]$ApiAccount = '.\svc_omika_api', [string]$WorkerAccount = '.\svc_omika_worker', [string]$DiagAccount = '.\svc_omika_diag', [string]$DiagWebAccount = '.\svc_omika_diagweb', [string]$DiagApiAccount = '.\svc_omika_diagapi', [string]$LanguesAccount = '.\svc_omika_langues', [ValidateSet('Manual', 'Automatic', 'Disabled')] [string]$StartupType = 'Manual', # --- Perimetre ----------------------------------------------------------- # Le service Langues n'existe que si la traduction hors ligne mobile est deployee. [switch]$InclureLangues, # Sur un serveur MONO-SERVEUR, l'API centrale de diagnostics est inutile # (l'API metier ecrit son JSONL localement, sans forwarding). [switch]$SansDiagnosticsApi, # Port loopback a verifier avant de le fixer dans ASPNETCORE_URLS (§6bis). [ValidateRange(0, 65535)] [int]$PortLangues = 0, # --- Rollback ------------------------------------------------------------ [switch]$Desinstaller ) $ErrorActionPreference = 'Stop' Import-Module (Join-Path $PSScriptRoot 'Omika.Deploy.Common.psm1') -Force # Le module a son propre etat de session : $WhatIfPreference ne s'y propage pas. $Simulation = [bool]$WhatIfPreference try { Assert-OmikaAdmin Write-OmikaStep 'Perimetre du deploiement' # --- Composition de la sequence ----------------------------------------- $sequence = New-Object System.Collections.Generic.List[object] $sequence.Add(@{ Script = 'Install-OmikaApi.ps1' Libelle = 'OmikaApi' Parametres = @{ InstallRoot = $InstallRoot ServiceName = $ApiServiceName Account = $ApiAccount StartupType = $StartupType } }) $sequence.Add(@{ Script = 'Install-OmikaWorker.ps1' Libelle = 'OmikaWorker' Parametres = @{ InstallRoot = $InstallRoot ServiceName = $WorkerServiceName Account = $WorkerAccount StartupType = $StartupType } }) if (-not $SansDiagnosticsApi) { $sequence.Add(@{ Script = 'Install-OmikaDiagnosticsApi.ps1' Libelle = 'OmikaDiagnosticsApi' Parametres = @{ InstallRoot = $InstallRoot ServiceName = $DiagApiServiceName Account = $DiagApiAccount AccountWorker = $DiagAccount StartupType = $StartupType } }) } else { Write-OmikaInfo 'OmikaDiagnosticsApi EXCLU (-SansDiagnosticsApi).' } $sequence.Add(@{ Script = 'Install-OmikaDiagnosticsWorker.ps1' Libelle = 'OmikaDiagnosticsWorker' Parametres = @{ InstallRoot = $InstallRoot ServiceName = $DiagServiceName Account = $DiagAccount AccountApi = $ApiAccount AccountDiagApi = $DiagApiAccount StartupType = $StartupType } }) $sequence.Add(@{ Script = 'Install-OmikaDiagnosticsWeb.ps1' Libelle = 'OmikaDiagnosticsWeb' Parametres = @{ InstallRoot = $InstallRoot ServiceName = $DiagWebServiceName Account = $DiagWebAccount StartupType = $StartupType } }) if ($InclureLangues) { $parametresLangues = @{ InstallRoot = $InstallRoot ServiceName = $LanguesServiceName Account = $LanguesAccount StartupType = $StartupType } if ($PortLangues -gt 0) { $parametresLangues['Port'] = $PortLangues } $sequence.Add(@{ Script = 'Install-OmikaLanguesApi.ps1' Libelle = 'OmikaLanguesApi' Parametres = $parametresLangues }) } else { Write-OmikaInfo 'OmikaLanguesApi EXCLU (ajoutez -InclureLangues pour l''installer).' } $mode = 'INSTALLATION' if ($Desinstaller) { $mode = 'DESINSTALLATION' } if ($Simulation) { $mode += ' (SIMULATION -WhatIf)' } Write-OmikaInfo ("{0} - {1} service(s) dans la sequence" -f $mode, $sequence.Count) # --- Execution ----------------------------------------------------------- $resultats = @() foreach ($etape in $sequence) { $nomService = [string]$etape.Parametres['ServiceName'] $cheminScript = Join-Path $PSScriptRoot $etape.Script if (-not (Test-Path -LiteralPath $cheminScript)) { Write-OmikaFail ("Script introuvable : {0} (service {1} ignore)" -f $etape.Script, $nomService) $resultats += [pscustomobject]@{ Service = $nomService; Resultat = 'SCRIPT ABSENT' } continue } $parametres = $etape.Parametres.Clone() $parametres['WhatIf'] = $Simulation if ($Desinstaller) { $parametres['Desinstaller'] = $true } & $cheminScript @parametres $code = $LASTEXITCODE if ($code -eq 0) { $resultats += [pscustomobject]@{ Service = $nomService; Resultat = 'OK' } } else { $resultats += [pscustomobject]@{ Service = $nomService; Resultat = ("ECHEC (code $code)") } } } # --- Recapitulatif ------------------------------------------------------- Write-Host '' Write-Host '=== RECAPITULATIF ===' -ForegroundColor Cyan foreach ($ligne in $resultats) { $couleur = 'Red' if ($ligne.Resultat -eq 'OK') { $couleur = 'Green' } Write-Host (" {0,-26} {1}" -f $ligne.Service, $ligne.Resultat) -ForegroundColor $couleur } Write-Host '' Write-Host 'Etat reel des services :' -ForegroundColor Cyan $noms = @($sequence | ForEach-Object { [string]$_.Parametres['ServiceName'] }) Get-Service | Where-Object { $noms -contains $_.Name } | Select-Object Name, Status, StartType | Format-Table -AutoSize $echecs = @($resultats | Where-Object { $_.Resultat -ne 'OK' }) Write-Host '' if ($echecs.Count -eq 0) { Write-Host 'ACTIVATION TERMINEE (services MANUAL + STOPPED).' -ForegroundColor Green Write-Host 'AUCUN service demarre : le demarrage reste une action MANUELLE.' -ForegroundColor Yellow Write-Host '' Write-Host 'Ordre de demarrage (consommateurs avant producteurs) :' -ForegroundColor Yellow Write-Host ' OmikaDiagnosticsWorker -> OmikaDiagnosticsWeb -> OmikaDiagnosticsApi -> OmikaWorker -> OmikaApi' -ForegroundColor Yellow } else { Write-Host ("ACTIVATION INCOMPLETE : {0} etape(s) en echec." -f $echecs.Count) -ForegroundColor Red Write-Host 'Corrigez chaque echec, puis relancez ce script (idempotent).' -ForegroundColor Red } Write-Host '' Write-Host 'RAPPELS (jamais automatises ici) :' -ForegroundColor Yellow Write-Host ' - Injecter les secrets par service (voir les rappels de chaque script).' Write-Host ' - Verifier le provider OLE DB PCSOFT.HFSQL (64 bits) enregistre.' Write-Host ' - Installer LibreOffice si la generation PDF des rapports est utilisee.' Write-Host ' - Appliquer les migrations PostgreSQL 001 -> 010 (retention incluse) avant demarrage.' if ($echecs.Count -gt 0) { exit 1 } exit 0 } catch { Write-OmikaFail $_.Exception.Message exit 1 }