Premiere commit - Omika
This commit is contained in:
@@ -0,0 +1,596 @@
|
||||
# Mise à jour production — Omika Diagnostics (SRV-OMIKA)
|
||||
|
||||
> **Objet** : procédure de mise à jour d'une installation déjà existante
|
||||
> (première version de `DiagnosticsWorker` + `DiagnosticsWeb` déjà déployée) vers la
|
||||
> nouvelle version (code + base de données).
|
||||
>
|
||||
> **Cible** : Windows Server 2025 `SRV-OMIKA`, PowerShell **administrateur**,
|
||||
> PostgreSQL 18, runtime .NET 10 (framework-dependent).
|
||||
>
|
||||
> **Style** : chaque composant suit le même schéma que la documentation Omika.Api
|
||||
> existante → **Publier → Backup → Arrêter/Mettre à jour → Redémarrer → Vérifier**.
|
||||
|
||||
---
|
||||
|
||||
## 0. Vue d'ensemble des composants à mettre à jour
|
||||
|
||||
| # | Composant | Projet | Service Windows | Exécutable | Santé |
|
||||
|---|---|---|---|---|---|
|
||||
| 1 | API métier/mobile (+ forwarder diagnostics) | `src\Omika.Api` | `OmikaApi` | `Omika.Api.exe` | `GET /health` |
|
||||
| 2 | Worker de synchronisation métier | `src\Omika.Worker` | `OmikaWorker` | `Omika.Worker.exe` | service `Running` + logs |
|
||||
| 3 | Import JSONL → PostgreSQL | `src\Omika.Diagnostics.Worker` | `OmikaDiagnosticsWorker` | `Omika.Diagnostics.Worker.exe` | service `Running` + checkpoint |
|
||||
| 4 | Interface Diagnostic Center | `src\Omika.Diagnostics.Web` | `OmikaDiagnosticsWeb` | `Omika.Diagnostics.Web.exe` | `GET /Login` (200) |
|
||||
| 5 | API centrale diagnostics *(optionnel, multi-serveur)* | `src\Omika.Diagnostics.Api` | `OmikaDiagnosticsApi` | `Omika.Diagnostics.Api.exe` | `GET /` (200) |
|
||||
| — | Base PostgreSQL `omika_diagnostics` | `infra\postgresql\*.sql` | — | migrations `001 → 011` | `SELECT count(*)` |
|
||||
|
||||
**Ordre global de la mise à jour** (les étapes 4 à 7 sont détaillées plus bas) :
|
||||
|
||||
```
|
||||
1. Publier (poste DEV) §2
|
||||
2. Transférer + backup §3
|
||||
3. Arrêter les services §4
|
||||
4. Migrer la base §5 ← TOUJOURS AVANT les nouveaux binaires
|
||||
5. Copier les binaires §6
|
||||
6. Redémarrer §7
|
||||
7. Vérifier §8
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 1. Prérequis
|
||||
|
||||
### Poste DEV
|
||||
- SDK .NET 10 (`global.json` épingle `10.0.302`).
|
||||
- Dépôt à jour (`git pull`), branche qui contient les derniers changements.
|
||||
|
||||
### SRV-OMIKA (PowerShell administrateur)
|
||||
```powershell
|
||||
net session # doit réussir, sinon STOP (droits)
|
||||
dotnet --list-runtimes # Microsoft.AspNetCore.App 10.x présent
|
||||
Get-Service postgresql* # Running
|
||||
Test-Path 'C:\Program Files\PostgreSQL\18\bin\psql.exe'
|
||||
Test-Path 'C:\Program Files\PostgreSQL\18\bin\pg_dump.exe'
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 2. Publier sur le poste DEV
|
||||
|
||||
Depuis `D:\Avalonia\Omika`, publier les **4 composants réellement utilisés**
|
||||
sur SRV-OMIKA. Le composant `Omika.Diagnostics.Api` (§6.5) n'est publié que si le
|
||||
mode multi-serveur (clients distants) est activé.
|
||||
|
||||
> **Script prêt à l'emploi** : `scripts\publish-diagnostics.ps1` effectue
|
||||
> exactement ceci (publish + vérification des EXE). Lancer depuis la racine :
|
||||
> `.\scripts\publish-diagnostics.ps1` (ajouter `-IncludeCentralApi` pour l'API
|
||||
> centrale). Les commandes manuelles équivalentes sont ci-dessous.
|
||||
|
||||
```powershell
|
||||
cd D:\Avalonia\Omika
|
||||
|
||||
# 1. Omika.Api
|
||||
dotnet publish src\Omika.Api\Omika.Api.csproj `
|
||||
-c Release -r win-x64 --self-contained false `
|
||||
-o C:\Omika\Deploy\OmikaApi-next
|
||||
|
||||
# 2. Omika.Worker
|
||||
dotnet publish src\Omika.Worker\Omika.Worker.csproj `
|
||||
-c Release -r win-x64 --self-contained false `
|
||||
-o C:\Omika\Deploy\OmikaWorker-next
|
||||
|
||||
# 3. Omika.Diagnostics.Worker (EnableWindowsService=true est le défaut : ne pas le désactiver)
|
||||
dotnet publish src\Omika.Diagnostics.Worker\Omika.Diagnostics.Worker.csproj `
|
||||
-c Release -r win-x64 --self-contained false `
|
||||
-o C:\Omika\Deploy\DiagnosticsWorker-next
|
||||
|
||||
# 4. Omika.Diagnostics.Web
|
||||
dotnet publish src\Omika.Diagnostics.Web\Omika.Diagnostics.Web.csproj `
|
||||
-c Release -r win-x64 --self-contained false `
|
||||
-o C:\Omika\Deploy\DiagnosticsWeb-next
|
||||
|
||||
# 5. (optionnel) Omika.Diagnostics.Api
|
||||
dotnet publish src\Omika.Diagnostics.Api\Omika.Diagnostics.Api.csproj `
|
||||
-c Release -r win-x64 --self-contained false `
|
||||
-o C:\Omika\Deploy\DiagnosticsApi-next
|
||||
```
|
||||
|
||||
### Vérification des sorties
|
||||
|
||||
```powershell
|
||||
Get-ChildItem C:\Omika\Deploy\OmikaApi-next # Omika.Api.exe + Omika.Api.dll + Omika.Core.dll + Omika.Data.dll + Omika.Observability.External.dll
|
||||
Get-ChildItem C:\Omika\Deploy\OmikaWorker-next # Omika.Worker.exe + Omika.Worker.dll + Omika.Core.dll + Omika.Data.dll + Omika.Observability.External.dll
|
||||
Get-ChildItem C:\Omika\Deploy\DiagnosticsWorker-next # Omika.Diagnostics.Worker.exe + Omika.Diagnostics.Worker.dll + Omika.Diagnostics.Core.dll + Omika.Diagnostics.Data.dll + Npgsql.dll
|
||||
Get-ChildItem C:\Omika\Deploy\DiagnosticsWeb-next # Omika.Diagnostics.Web.exe + Omika.Diagnostics.Web.dll + wwwroot\ + Omika.Diagnostics.Core.dll + Omika.Diagnostics.Data.dll + Npgsql.dll
|
||||
```
|
||||
|
||||
> ⚠️ Ne jamais livrer de secret Dev en Prod. Vérifier l'absence de valeur de test
|
||||
> dans les publications, et que le serveur garde **`ASPNETCORE_ENVIRONMENT=Production`**.
|
||||
> (`appsettings.Development.json`, s'il est présent dans une publication, n'est chargé
|
||||
> que si l'environnement est `Development` — il ne doit donc jamais l'être sur SRV-OMIKA.)
|
||||
|
||||
Transférer ensuite les dossiers `*-next` vers `SRV-OMIKA` dans
|
||||
`C:\Omika\Deploy\`.
|
||||
|
||||
---
|
||||
|
||||
## 3. Backup sur le serveur
|
||||
|
||||
### 3.1 Base PostgreSQL (AVANT toute migration)
|
||||
|
||||
```powershell
|
||||
$env:PGPASSWORD = '<SECRET_POSTGRES_ADMIN>'
|
||||
$stamp = Get-Date -Format 'yyyyMMdd_HHmm'
|
||||
$out = "C:\Omika\Backups\omika_diagnostics_${stamp}_before_upgrade.backup"
|
||||
& 'C:\Program Files\PostgreSQL\18\bin\pg_dump.exe' `
|
||||
-h 127.0.0.1 -p 5432 -U postgres -d omika_diagnostics -F c -v -f $out
|
||||
Remove-Item Env:PGPASSWORD
|
||||
|
||||
$f = Get-Item $out
|
||||
$f.Exists -and $f.Length -gt 0 # doit être True, sinon NO-GO
|
||||
```
|
||||
|
||||
### 3.2 Binaires (AVANT remplacement)
|
||||
|
||||
```powershell
|
||||
$stamp = Get-Date -Format 'yyyyMMdd-HHmmss'
|
||||
$root = 'C:\Omika\Backups'
|
||||
Copy-Item 'C:\Omika\Apps\OmikaApi' -Destination "$root\OmikaApi_${stamp}" -Recurse -Force
|
||||
Copy-Item 'C:\Omika\Apps\OmikaWorker' -Destination "$root\OmikaWorker_${stamp}" -Recurse -Force
|
||||
Copy-Item 'C:\Omika\Apps\DiagnosticsWorker' -Destination "$root\DiagnosticsWorker_${stamp}" -Recurse -Force
|
||||
Copy-Item 'C:\Omika\Apps\DiagnosticsWeb' -Destination "$root\DiagnosticsWeb_${stamp}" -Recurse -Force
|
||||
```
|
||||
|
||||
> Le script `infra\deploy\Install-OmikaServerFiles.ps1` fait déjà cette sauvegarde
|
||||
> horodatée + copie + préservation de la config, si vous préférez l'automatiser.
|
||||
|
||||
---
|
||||
|
||||
## 4. Arrêter les services (ordre)
|
||||
|
||||
L'ordre fige d'abord la lecture (Web), puis les écrivains, et draine le Worker en dernier.
|
||||
|
||||
```powershell
|
||||
Stop-Service OmikaDiagnosticsWeb -Force
|
||||
Stop-Service OmikaApi -Force
|
||||
Stop-Service OmikaWorker -Force
|
||||
Stop-Service OmikaDiagnosticsWorker -Force
|
||||
|
||||
Get-Service OmikaApi,OmikaWorker,OmikaDiagnosticsWorker,OmikaDiagnosticsWeb | Select-Object Name,Status
|
||||
# Attendu : les 4 = Stopped
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. Mettre à jour la base de données (migrations)
|
||||
|
||||
### 5.1 Auditer l'état actuel (lecture seule)
|
||||
|
||||
```powershell
|
||||
$env:PGPASSWORD = '<SECRET_POSTGRES_ADMIN>'
|
||||
$psql = 'C:\Program Files\PostgreSQL\18\bin\psql.exe'
|
||||
|
||||
& $psql -h 127.0.0.1 -p 5432 -U postgres -d omika_diagnostics -c `
|
||||
"SELECT table_name FROM information_schema.tables WHERE table_schema='public' AND table_name LIKE 'diagnostics%' ORDER BY 1;"
|
||||
|
||||
& $psql -h 127.0.0.1 -p 5432 -U postgres -d omika_diagnostics -c `
|
||||
"SELECT column_name FROM information_schema.columns WHERE table_name='diagnostic_event' ORDER BY ordinal_position;"
|
||||
|
||||
& $psql -h 127.0.0.1 -p 5432 -U postgres -d omika_diagnostics -c `
|
||||
"SELECT rolname FROM pg_roles ORDER BY rolname;"
|
||||
|
||||
Remove-Item Env:PGPASSWORD
|
||||
```
|
||||
|
||||
Cela permet de déterminer **quelles migrations sont déjà appliquées** :
|
||||
|
||||
| Repère observé | Migration déjà appliquée |
|
||||
|---|---|
|
||||
| `diagnostic_event` présent | `001` |
|
||||
| colonnes `actor_key` / `actor_key_version` | `002` |
|
||||
| rôles `omika_diagnostics_owner/worker/web` | `003` |
|
||||
| `SELECT`+`DELETE` worker sur `diagnostic_event` | `004` |
|
||||
| colonnes `client_code`/`server_instance`/`environment` | `005` |
|
||||
| colonnes appareil/licence | `006` |
|
||||
| colonnes `screen_code`/`feature_code` | `007` |
|
||||
| table `diagnostics_clients` | `008` |
|
||||
| rôle `omika_diagnostics_api` + grants clients | `009` |
|
||||
| table `diagnostics_users` | `010` |
|
||||
| table `diagnostics_reference` | `011` |
|
||||
|
||||
### 5.2 Appliquer UNIQUEMENT les migrations manquantes, dans l'ordre
|
||||
|
||||
Migrations `001 → 011`, toutes **idempotentes** (`CREATE/ADD IF NOT EXISTS`,
|
||||
`ON CONFLICT DO NOTHING`, `GRANT`). Les appliquer avec `ON_ERROR_STOP=1`, en
|
||||
compte **superuser** (`postgres`), car `003/009/010/011` font du `CREATE ROLE` /
|
||||
`ALTER TABLE OWNER` / `GRANT`.
|
||||
|
||||
```powershell
|
||||
$env:PGPASSWORD = '<SECRET_POSTGRES_ADMIN>'
|
||||
$psql = 'C:\Program Files\PostgreSQL\18\bin\psql.exe'
|
||||
$db = 'C:\Omika\Deploy\DiagnosticsDatabase' # dossier contenant les .sql livrés
|
||||
|
||||
$migrations = @(
|
||||
'001_diagnostics_schema.sql',
|
||||
'002_actor_key.sql',
|
||||
'003_diagnostics_roles.sql',
|
||||
'004_diagnostics_retention.sql',
|
||||
'005_diagnostics_client_context.sql',
|
||||
'006_diagnostics_device_license.sql',
|
||||
'007_diagnostics_usage.sql',
|
||||
'008_diagnostics_clients.sql',
|
||||
'009_diagnostics_clients_grants.sql',
|
||||
'010_diagnostics_web_users.sql',
|
||||
'011_diagnostics_reference.sql'
|
||||
)
|
||||
|
||||
foreach ($m in $migrations) {
|
||||
$f = Join-Path $db $m
|
||||
if (-not (Test-Path $f)) { Write-Host "ABSENT : $m" ; continue }
|
||||
Write-Host "Application : $m ..."
|
||||
& $psql -h 127.0.0.1 -p 5432 -U postgres -d omika_diagnostics -v ON_ERROR_STOP=1 -f $f
|
||||
if ($LASTEXITCODE -ne 0) { throw "ÉCHEC sur $m (exit $LASTEXITCODE). STOP." }
|
||||
}
|
||||
Remove-Item Env:PGPASSWORD
|
||||
```
|
||||
|
||||
> **Règle d'ordre migration ↔ binaires** : les migrations doivent être appliquées
|
||||
> **AVANT** la copie des nouveaux binaires (§6). Les colonnes/tables ajoutées sont
|
||||
> additives ; les anciens binaires restent compatibles, mais les nouveaux binaires
|
||||
> échoueraient sur un schéma trop ancien.
|
||||
|
||||
### 5.3 Ce qui est nouveau dans cette mise à jour
|
||||
|
||||
- **`011_diagnostics_reference.sql`** (dernière livraison) : table
|
||||
`diagnostics_reference` (référentiel administrable `ScreenCode`/`FeatureCode`),
|
||||
ownership `omika_diagnostics_owner`, grants `omika_diagnostics_web`
|
||||
(`SELECT`/`INSERT`/`UPDATE` colonnes ciblées + `USAGE` séquence), et **seed
|
||||
idempotent** des 29 `ScreenCode` + 3 `FeatureCode`. Aucun droit accordé aux rôles
|
||||
`omika_diagnostics_api` / `omika_diagnostics_worker`.
|
||||
- `003_diagnostics_roles_preprod.sql` ne concerne **que** la préproduction : ne
|
||||
**jamais** l'appliquer en Production.
|
||||
|
||||
### 5.4 Après `003` / `009` (rôles LOGIN) — mots de passe manuels
|
||||
|
||||
Les rôles LOGIN créés sans mot de passe doivent être positionnés manuellement,
|
||||
jamais dans un script/log :
|
||||
|
||||
```
|
||||
\password omika_diagnostics_worker
|
||||
\password omika_diagnostics_web
|
||||
\password omika_diagnostics_api # seulement si l'API centrale est activée
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. Mettre à jour chaque composant
|
||||
|
||||
Pour chaque composant, la copie **préserve** la configuration serveur existante
|
||||
(secrets) : on exclut `appsettings.json` et `appsettings.Production.json`.
|
||||
|
||||
> ⚠️ Ne **jamais** supprimer :
|
||||
> - `C:\Omika\Data\Api\Diagnostics\Jsonl\**` (JSONL en attente d'import)
|
||||
> - `C:\Omika\Data\DiagnosticsWorker\Checkpoint\import-checkpoint.json`
|
||||
> - `C:\Omika\Config\**`, les certificats TLS, les variables d'environnement MACHINE.
|
||||
|
||||
### 6.1 Omika.Api (service `OmikaApi`)
|
||||
|
||||
```powershell
|
||||
# Backup : déjà fait §3.2. Puis copie :
|
||||
robocopy 'C:\Omika\Deploy\OmikaApi-next' 'C:\Omika\Apps\OmikaApi' `
|
||||
/E /XF appsettings.json appsettings.Production.json
|
||||
```
|
||||
|
||||
Fichiers attendus après copie : `Omika.Api.exe`, `Omika.Api.dll`, `Omika.Core.dll`,
|
||||
`Omika.Data.dll`, `Omika.Observability.External.dll`.
|
||||
|
||||
Configuration Production à conserver (injectée sur le serveur) :
|
||||
`MobileAuth__SigningKey` (obligatoire, fail-fast), `DiagnosticsIdentity__HmacKey`,
|
||||
`ConnectionStrings__*` HFSQL / licence / sync, `Observability__Remote__Directory`
|
||||
(doit être **identique** au dossier JSONL lu par le Worker), et si le forwarding
|
||||
central est actif : `DiagnosticsForwarding__Enabled/Endpoint/ApiKey`.
|
||||
(Voir la table complète §6.6.)
|
||||
|
||||
Redémarrage et contrôle (port Kestrel = celui défini dans
|
||||
`appsettings.Production.json`, ex. `5080`) :
|
||||
|
||||
```powershell
|
||||
Start-Service OmikaApi
|
||||
Get-Service OmikaApi # Running
|
||||
Invoke-WebRequest 'http://127.0.0.1:5080/health' -UseBasicParsing
|
||||
Invoke-WebRequest 'https://omika.applilogik.fr/health' -UseBasicParsing
|
||||
# Attendu : 200 + "Healthy"
|
||||
```
|
||||
|
||||
### 6.2 Omika.Worker (service `OmikaWorker`)
|
||||
|
||||
```powershell
|
||||
robocopy 'C:\Omika\Deploy\OmikaWorker-next' 'C:\Omika\Apps\OmikaWorker' `
|
||||
/E /XF appsettings.json appsettings.Production.json
|
||||
```
|
||||
|
||||
Fichiers attendus : `Omika.Worker.exe`, `Omika.Worker.dll`, `Omika.Core.dll`,
|
||||
`Omika.Data.dll`, `Omika.Observability.External.dll`.
|
||||
|
||||
Pas de port HTTP (background service) : contrôle = service `Running` + absence de
|
||||
boucle d'erreur dans les logs (`C:\Omika\Logs\Worker`).
|
||||
|
||||
```powershell
|
||||
Start-Service OmikaWorker
|
||||
Get-Service OmikaWorker # Running
|
||||
Get-EventLog -LogName Application -Newest 50 | Where-Object { $_.Source -match 'Omika' }
|
||||
```
|
||||
|
||||
### 6.3 Omika.Diagnostics.Worker (service `OmikaDiagnosticsWorker`)
|
||||
|
||||
```powershell
|
||||
robocopy 'C:\Omika\Deploy\DiagnosticsWorker-next' 'C:\Omika\Apps\DiagnosticsWorker' `
|
||||
/E /XF appsettings.json appsettings.Production.json
|
||||
```
|
||||
|
||||
Fichiers attendus : `Omika.Diagnostics.Worker.exe`, `Omika.Diagnostics.Worker.dll`,
|
||||
`Omika.Diagnostics.Core.dll`, `Omika.Diagnostics.Data.dll`, `Npgsql.dll`.
|
||||
|
||||
Configuration Production à conserver :
|
||||
`ConnectionStrings__DiagnosticsDatabase`
|
||||
(`Host=127.0.0.1;Port=5432;Database=omika_diagnostics;Username=omika_diagnostics_worker;Password=…`),
|
||||
`Observability__Remote__Directory` (**identique** au dossier JSONL d'Omika.Api),
|
||||
`Diagnostics__Import__CheckpointDirectory/CheckpointFileName`, `Diagnostics__RetentionDays`.
|
||||
(Voir la table complète §6.6.)
|
||||
|
||||
```powershell
|
||||
Start-Service OmikaDiagnosticsWorker
|
||||
Get-Service OmikaDiagnosticsWorker # Running
|
||||
Get-Content 'C:\Omika\Data\DiagnosticsWorker\Checkpoint\import-checkpoint.json'
|
||||
# Attendu : checkpoint stable ou progressant ; aucun JSONL supprimé.
|
||||
```
|
||||
|
||||
### 6.4 Omika.Diagnostics.Web (service `OmikaDiagnosticsWeb`)
|
||||
|
||||
```powershell
|
||||
robocopy 'C:\Omika\Deploy\DiagnosticsWeb-next' 'C:\Omika\Apps\DiagnosticsWeb' `
|
||||
/E /XF appsettings.json appsettings.Production.json
|
||||
```
|
||||
|
||||
Fichiers attendus : `Omika.Diagnostics.Web.exe`, `Omika.Diagnostics.Web.dll`,
|
||||
`wwwroot\`, `Omika.Diagnostics.Core.dll`, `Omika.Diagnostics.Data.dll`, `Npgsql.dll`.
|
||||
|
||||
Configuration Production à conserver :
|
||||
`ConnectionStrings__DiagnosticsDatabase`
|
||||
(`…Username=omika_diagnostics_web;Password=…`), `DiagnosticsAuth__Operators`
|
||||
(bootstrap temporaire uniquement), `ASPNETCORE_ENVIRONMENT=Production`.
|
||||
(Voir la table complète §6.6.)
|
||||
|
||||
Contrôle (port Kestrel = celui de `appsettings.Production.json`) :
|
||||
|
||||
```powershell
|
||||
Start-Service OmikaDiagnosticsWeb
|
||||
Get-Service OmikaDiagnosticsWeb # Running
|
||||
Invoke-WebRequest 'http://127.0.0.1:<PORT_WEB_DIAG>/Login' -UseBasicParsing # 200
|
||||
```
|
||||
|
||||
> Le Web n'expose pas de `/health` : la page `/Login` (200) est le smoke test.
|
||||
> Le reste est derrière authentification (redirect `/Login`).
|
||||
|
||||
### 6.5 Omika.Diagnostics.Api (service `OmikaDiagnosticsApi`) — **optionnel**
|
||||
|
||||
À déployer **uniquement** si vous activez la réception de lots provenant de
|
||||
**serveurs clients distants**. Sur un SRV-OMIKA mono-serveur (Omika.Api écrit le
|
||||
JSONL localement), ce composant n'est **pas** nécessaire.
|
||||
|
||||
```powershell
|
||||
robocopy 'C:\Omika\Deploy\DiagnosticsApi-next' 'C:\Omika\Apps\DiagnosticsApi' `
|
||||
/E /XF appsettings.json appsettings.Production.json
|
||||
```
|
||||
|
||||
Fichiers attendus : `Omika.Diagnostics.Api.exe`, `Omika.Diagnostics.Api.dll`,
|
||||
`Omika.Core.dll`, `Omika.Diagnostics.Core.dll`, `Omika.Diagnostics.Data.dll`.
|
||||
|
||||
Configuration Production à conserver :
|
||||
`ConnectionStrings__DiagnosticsDatabase` (`Username=omika_diagnostics_api`),
|
||||
`Diagnostics__Central__Directory` (= spool central, ex.
|
||||
`C:\ProgramData\Omika\Diagnostics\Central`).
|
||||
|
||||
```powershell
|
||||
Start-Service OmikaDiagnosticsApi
|
||||
Get-Service OmikaDiagnosticsApi # Running
|
||||
Invoke-WebRequest 'http://127.0.0.1:<PORT_API_DIAG>/' -UseBasicParsing
|
||||
# Attendu : 200 + JSON { name: "Omika.Diagnostics.Api", status: "ok" }
|
||||
```
|
||||
|
||||
### 6.6 Référence — variables d'environnement / clés de configuration par service
|
||||
|
||||
**Règle de nommage** : en variable d'environnement, `:` devient `__`
|
||||
(`Diagnostics:Import:CheckpointDirectory` ⇔ `Diagnostics__Import__CheckpointDirectory`).
|
||||
**Précédence** : `ConnectionStrings:DiagnosticsDatabase` (env
|
||||
`ConnectionStrings__DiagnosticsDatabase`) **prime** sur `Diagnostics:ConnectionString`.
|
||||
Toute modification de variable d'environnement d'un service Windows nécessite un
|
||||
**redémarrage du service** pour être prise en compte.
|
||||
|
||||
#### Omika.Api (service `OmikaApi`)
|
||||
|
||||
| Variable d'environnement | Clé de configuration | Rôle |
|
||||
|---|---|---|
|
||||
| `ASPNETCORE_ENVIRONMENT` | — | `Production` obligatoire |
|
||||
| `MobileAuth__SigningKey` | `MobileAuth:SigningKey` | clé de signature tokens mobile (**fail-fast** en Prod) |
|
||||
| `DiagnosticsIdentity__HmacKey` | `DiagnosticsIdentity:HmacKey` | clé HMAC ActorKey/DeviceKey (≥ 256 bits Base64) |
|
||||
| `DiagnosticDeployment__ClientCode` | `DiagnosticDeployment:ClientCode` | override CodeClient (sinon fallback HFSQL) |
|
||||
| `DiagnosticDeployment__ServerInstanceId` | `DiagnosticDeployment:ServerInstanceId` | id d'instance (sinon `MachineName`) |
|
||||
| `Observability__Remote__Directory` | `Observability:Remote:Directory` | dossier JSONL (**identique** au Worker) |
|
||||
| `DiagnosticsForwarding__Enabled` | `DiagnosticsForwarding:Enabled` | kill switch du forwarder central (`true`/`false`) |
|
||||
| `DiagnosticsForwarding__Endpoint` | `DiagnosticsForwarding:Endpoint` | URL centrale **HTTPS** (si forwarding actif) |
|
||||
| `DiagnosticsForwarding__ApiKey` | `DiagnosticsForwarding:ApiKey` | clé d'accès centrale (**secret**) |
|
||||
| `LicenseConnection__*` / `SyncConnection__*` / HFSQL | — | secrets HFSQL existants (non touchés) |
|
||||
|
||||
#### Omika.Worker (service `OmikaWorker`)
|
||||
|
||||
| Variable d'environnement | Clé de configuration | Rôle |
|
||||
|---|---|---|
|
||||
| `ASPNETCORE_ENVIRONMENT` | — | `Production` obligatoire |
|
||||
| `DiagnosticDeployment__ClientCode` | `DiagnosticDeployment:ClientCode` | idem Omika.Api |
|
||||
| `DiagnosticDeployment__ServerInstanceId` | `DiagnosticDeployment:ServerInstanceId` | idem Omika.Api |
|
||||
| `SyncConnection__*` / HFSQL | — | secrets HFSQL existants (non touchés) |
|
||||
|
||||
#### Omika.Diagnostics.Worker (service `OmikaDiagnosticsWorker`)
|
||||
|
||||
| Variable d'environnement | Clé de configuration | Défaut | Rôle |
|
||||
|---|---|---|---|
|
||||
| `ConnectionStrings__DiagnosticsDatabase` | `ConnectionStrings:DiagnosticsDatabase` | — | Npgsql `Username=omika_diagnostics_worker` (prime sur ci-dessous) |
|
||||
| `Diagnostics__ConnectionString` | `Diagnostics:ConnectionString` | `""` | fallback si `ConnectionStrings` absent |
|
||||
| `Observability__Remote__Directory` | `Observability:Remote:Directory` | `""` | dossier JSONL (**identique** à Omika.Api) |
|
||||
| `Diagnostics__Import__CheckpointDirectory` | `Diagnostics:Import:CheckpointDirectory` | `""` | dossier checkpoint (sinon = dossier source) |
|
||||
| `Diagnostics__Import__CheckpointFileName` | `Diagnostics:Import:CheckpointFileName` | `import-checkpoint.json` | nom du checkpoint |
|
||||
| `Diagnostics__Import__BatchSize` | `Diagnostics:Import:BatchSize` | `100` | taille de lot d'insertion (borné 1..200) |
|
||||
| `Diagnostics__RetentionDays` | `Diagnostics:RetentionDays` | `60` | rétention en jours (`<=0` = purge désactivée) |
|
||||
| `Diagnostics__RetentionIntervalHours` | `Diagnostics:RetentionIntervalHours` | `24` | fréquence de purge |
|
||||
| `Diagnostics__RetentionBatchSize` | `Diagnostics:RetentionBatchSize` | `1000` | lot de suppression (borné) |
|
||||
| `Diagnostics__CommandTimeoutSeconds` | `Diagnostics:CommandTimeoutSeconds` | `10` | timeout court des commandes |
|
||||
|
||||
#### Omika.Diagnostics.Web (service `OmikaDiagnosticsWeb`)
|
||||
|
||||
| Variable d'environnement | Clé de configuration | Rôle |
|
||||
|---|---|---|
|
||||
| `ASPNETCORE_ENVIRONMENT` | — | `Production` obligatoire (default-deny) |
|
||||
| `ConnectionStrings__DiagnosticsDatabase` | `ConnectionStrings:DiagnosticsDatabase` | Npgsql `Username=omika_diagnostics_web` |
|
||||
| `DiagnosticsAuth__Operators__0__Username` | `DiagnosticsAuth:Operators:0:Username` | opérateur bootstrap (temporaire) |
|
||||
| `DiagnosticsAuth__Operators__0__PasswordHash` | `DiagnosticsAuth:Operators:0:PasswordHash` | **hash** bootstrap (jamais en clair) |
|
||||
| `DiagnosticsAuth__Operators__0__Roles__0` | `DiagnosticsAuth:Operators:0:Roles:0` | `Admin` / `Support` |
|
||||
| `Diagnostics__RetentionDays` | `Diagnostics:RetentionDays` | `60` (affiché dans l'UI) |
|
||||
|
||||
#### Omika.Diagnostics.Api (service `OmikaDiagnosticsApi`) — optionnel
|
||||
|
||||
| Variable d'environnement | Clé de configuration | Défaut | Rôle |
|
||||
|---|---|---|---|
|
||||
| `ConnectionStrings__DiagnosticsDatabase` | `ConnectionStrings:DiagnosticsDatabase` | — | Npgsql `Username=omika_diagnostics_api` |
|
||||
| `Diagnostics__Central__Directory` | `Diagnostics:Central:Directory` | `logs/diagnostics-central` | **spool central** (chemin explicite en Prod) |
|
||||
| `Diagnostics__Central__MaxRequestBodyBytes` | `Diagnostics:Central:MaxRequestBodyBytes` | `524288` | corps de requête borné |
|
||||
| `Diagnostics__Central__MaxEventsPerBatch` | `Diagnostics:Central:MaxEventsPerBatch` | `100` | événements max par lot |
|
||||
| `Diagnostics__Central__SchemaVersion` | `Diagnostics:Central:SchemaVersion` | `1` | version du schéma de transport |
|
||||
|
||||
**Ports Kestrel** : définis par `appsettings.Production.json` de chaque composant
|
||||
(`Kestrel:Endpoints:Http:Url` ou `ASPNETCORE_URLS`), en HTTP loopback derrière le
|
||||
reverse proxy Apache (`https://omika.applilogik.fr`). Aucun port n'est codé en dur
|
||||
dans le binaire.
|
||||
|
||||
---
|
||||
|
||||
## 7. Redémarrer (ordre)
|
||||
|
||||
Démarrer les **consommateurs avant les producteurs** :
|
||||
|
||||
```powershell
|
||||
Start-Service OmikaDiagnosticsWorker # 1. importeur (consommateur JSONL)
|
||||
Start-Service OmikaDiagnosticsWeb # 2. UI (lecture)
|
||||
Start-Service OmikaWorker # 3. sync métier (producteur #2)
|
||||
Start-Service OmikaApi # 4. API (producteur #1, dernier)
|
||||
|
||||
Get-Service OmikaApi,OmikaWorker,OmikaDiagnosticsWorker,OmikaDiagnosticsWeb | Select-Object Name,Status
|
||||
# Attendu : les 4 = Running
|
||||
```
|
||||
|
||||
> Si un service passe immédiatement en `Stopped`/`Failed`, ne pas démarrer les
|
||||
> suivants : diagnostiquer puis rollback si non résolu (§9).
|
||||
|
||||
---
|
||||
|
||||
## 8. Smoke tests (non destructifs)
|
||||
|
||||
```powershell
|
||||
# Services
|
||||
Get-Service OmikaApi,OmikaWorker,OmikaDiagnosticsWorker,OmikaDiagnosticsWeb | Select-Object Name,Status
|
||||
|
||||
# API métier
|
||||
Invoke-WebRequest 'http://127.0.0.1:5080/health' -UseBasicParsing # 200 "Healthy"
|
||||
|
||||
# Web Diagnostics (Login)
|
||||
Invoke-WebRequest 'http://127.0.0.1:<PORT_WEB_DIAG>/Login' -UseBasicParsing # 200
|
||||
```
|
||||
|
||||
Contrôles PostgreSQL après redémarrage :
|
||||
|
||||
```sql
|
||||
SELECT count(*) FROM diagnostic_event;
|
||||
SELECT max(ingested_at_utc) AS dernier_ingere FROM diagnostic_event;
|
||||
|
||||
-- Référentiel (011) :
|
||||
SELECT reference_type, count(*) FROM diagnostics_reference GROUP BY reference_type;
|
||||
-- Attendu : SCREEN_CODE = 29, FEATURE_CODE = 3
|
||||
```
|
||||
|
||||
Dans **Diagnostics.Web** : vérifier Dashboard, Diagnostics, Erreurs, Traces,
|
||||
Synchronisation, Telemetry, Versions, et **Référentiel** (nouvelle fonctionnalité
|
||||
`011`) ainsi que `/Clients` et `/Users` (Admin).
|
||||
|
||||
---
|
||||
|
||||
## 9. Rollback
|
||||
|
||||
### Binaires
|
||||
|
||||
```powershell
|
||||
Stop-Service OmikaApi,OmikaWorker,OmikaDiagnosticsWorker,OmikaDiagnosticsWeb -Force
|
||||
$stamp = '<horodatage_du_backup>' # ex. 20261002-160000
|
||||
|
||||
Remove-Item 'C:\Omika\Apps\OmikaApi' -Recurse -Force
|
||||
Copy-Item "C:\Omika\Backups\OmikaApi_${stamp}" 'C:\Omika\Apps\OmikaApi' -Recurse -Force
|
||||
Copy-Item "C:\Omika\Backups\OmikaWorker_${stamp}" 'C:\Omika\Apps\OmikaWorker' -Recurse -Force
|
||||
Copy-Item "C:\Omika\Backups\DiagnosticsWorker_${stamp}" 'C:\Omika\Apps\DiagnosticsWorker' -Recurse -Force
|
||||
Copy-Item "C:\Omika\Backups\DiagnosticsWeb_${stamp}" 'C:\Omika\Apps\DiagnosticsWeb' -Recurse -Force
|
||||
|
||||
Start-Service OmikaDiagnosticsWorker
|
||||
Start-Service OmikaDiagnosticsWeb
|
||||
Start-Service OmikaWorker
|
||||
Start-Service OmikaApi
|
||||
```
|
||||
|
||||
### Base de données
|
||||
|
||||
**Pas de rollback SQL automatique** : les migrations `001 → 011` sont **additives**
|
||||
et idempotentes ; les anciens binaires restent compatibles. Ne jamais `DROP` /
|
||||
`TRUNCATE` / `DELETE`. Restaurer via `pg_restore` (backup §3.1) uniquement sur
|
||||
décision humaine explicite et en dernier recours :
|
||||
|
||||
```powershell
|
||||
& 'C:\Program Files\PostgreSQL\18\bin\pg_restore.exe' `
|
||||
-h 127.0.0.1 -p 5432 -U postgres -d omika_diagnostics -c `
|
||||
'C:\Omika\Backups\omika_diagnostics_<stamp>_before_upgrade.backup'
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 10. Checklist finale
|
||||
|
||||
```text
|
||||
[ ] Publications DEV : 4 composants générés, EXE/DLL présents, pas de secret Dev
|
||||
[ ] Transfert vers SRV-OMIKA C:\Omika\Deploy\*-next
|
||||
[ ] pg_dump terminé + taille > 0
|
||||
[ ] Backup binaires (4 dossiers) présent + complet
|
||||
[ ] Services arrêtés (4 = Stopped)
|
||||
[ ] Migrations manquantes identifiées puis appliquées dans l'ordre (ON_ERROR_STOP=1)
|
||||
[ ] 011 (diagnostics_reference) appliquée ; seed 29 + 3 vérifié
|
||||
[ ] Mots de passe rôles LOGIN posés manuellement (\password)
|
||||
[ ] appsettings.json / appsettings.Production.json préservés sur les 4 composants
|
||||
[ ] JSONL + checkpoint intacts (jamais supprimés)
|
||||
[ ] Redémarrage dans l'ordre (Worker → Web → OmikaWorker → OmikaApi)
|
||||
[ ] 4 services Running
|
||||
[ ] /health Omika.Api = 200 "Healthy" ; /Login DiagnosticsWeb = 200
|
||||
[ ] Dashboard / Référentiel / Clients / Users fonctionnels
|
||||
[ ] Rollback prêt (backups binaires + décision DB additive)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Références internes
|
||||
|
||||
- `docs/DEPLOIEMENT_PRODUCTION_DIAGNOSTICS.md` — architecture, ports, comptes, secrets.
|
||||
- `docs/T15-RUNBOOK-DEPLOIEMENT-PRODUCTION.md` — runbook complet (phases détaillées).
|
||||
- `scripts/publish-diagnostics.ps1` — publication automatisée des composants (poste DEV).
|
||||
- `infra/deploy/Install-OmikaServerFiles.ps1` — copie statique + sauvegarde + SHA256.
|
||||
- `infra/deploy/Omika.Deploy.Common.psm1` — module commun (comptes, ACL contrôlées, services, ports).
|
||||
- `infra/deploy/Install-Omika<Service>.ps1` — **un script par déploiement**
|
||||
(`OmikaApi`, `OmikaWorker`, `OmikaDiagnosticsApi`, `OmikaDiagnosticsWorker`,
|
||||
`OmikaDiagnosticsWeb`, `OmikaLanguesApi`) : idempotents, `-WhatIf`, `-Desinstaller`.
|
||||
- `infra/deploy/Install-OmikaServices.ps1` — orchestrateur : enchaîne les scripts ci-dessus dans l'ordre.
|
||||
- `infra/deploy/Test-PortDisponible.ps1` — disponibilité d'un port loopback avant configuration.
|
||||
- `infra/deploy/Install-DatabaseSchema.ps1` — applique `001`+`002` (schéma).
|
||||
- `infra/deploy/Harden-DatabaseRoles.ps1` — applique `003` (rôles).
|
||||
- `infra/postgresql/001…011_diagnostics_*.sql` — migrations PostgreSQL.
|
||||
Reference in New Issue
Block a user