Portail
Le portail parent du module crèche permet aux parents de communiquer avec les structures. Il est divisé en deux modules indépendant activables par configuration. Les deux modules sont :
Préinscriptionqui concerne la partie permettant au parent de déclarer un nouvel enfant et ses besoinsCommunicationqui permet au parent de gérer son profil et l’activité de ses enfants
Toutes ces actions sont accessibles par un unique portail lié à une ou plusieurs sociétés SAINet. L’objectif de cette documentation, dédiée aux utilisateurs de type Super-administrateurs est d’exprimer les étapes pour déployer ce portail et configurer les éléments initiaux.
La partie configuration des fonctionnalités SAINet se trouve dans la documentation pré-inscription et la documentation portail de communication.
Dans SYS01, créer une nouvelle société. Par convention, les sociétés avec un seul portail global sur le serveur utilisent l’identifiant POR.
Dans les modules de la société, sélectionner la configuration de modules qui contient le module creche_portal. Cette configuration est généralement appellée également creche_portal par convention.
Une autre étape nécessaire est la déclaration de la société qui contiendra la configuration de toutes les fonctionnalités du portail. Il n’est pas nécessaire à ce point de configurer les fonctionnalités mais il est obligatoire d’en définir la base.
Le paramétrage des fonctionnalités disponibles dans le portail parents s’effectue dans la chaîne UNI de SAINet. Il est donc nécessaire de créer une nouvelle entrée POR (si la société du portail est POR) dans UNI91. Afin de pouvoir faire cette saisie, l’utilisateur courant doit avoir accès à la société POR dans SYS02.
Il est important que le domaine du portail (POR) soit déclaré au niveau des différentes tâches 01 (SAL01, CRM01, GTP01 et DEB01).
Pour se connecter à SAINet, il est nécessaire de créer un compte de service sous la forme d’un utilisateur dans SYS02 dont les informations seront fournies à la configuration du portail parents. Ce compte, de type USER et appartenant au groupe PORTAIL, doit pouvoir accéder à toutes les sociétés qui concernent les enfants et qui seront disponibles à travers le portail.
Ce compte doit impérativement avoir la coche Compte système activée dans SYS02. Sans cette coche, SAINet refuse les requêtes du portail dès que celui-ci agit au nom d’un parent ou d’un collaborateur.
Un compte système ne peut pas avoir le rôle SUPERADMIN. Veillez également à ce que son mot de passe soit à jour (non marqué comme devant être changé), sans quoi la connexion du portail échoue.
Afin d’éviter tout problème lié à l’expiration du mot de passe, il est conseillé de mettre une date de fin de validité suffisamment grande. Cette opération nécessite un accès direct à la base de données.
Il est conseillé de créer un groupe PORTAIL en SYS03 afin d’y attacher l’utilisateur et de créer ensuite les droits nécessaires pour ce groupe via les tâches SYS04 et SYS07. L’utilisateur doit avoir les accès suivants:
| Tâche | Accès | Remarques |
|---|---|---|
SYS00 |
Accès en lecture et exécution. | Accès obligatoire pour la connexion des utilisateurs portail. |
UNI91 |
Accès en lecture. | Accès obligatoire. |
SAL01 |
Accès en lecture. | Accès obligatoire. |
CRM06 |
Accès en lecture/écriture. | Accès obligatoire. |
CRM07 |
Accès en lecture/écriture. | Accès obligatoire. |
CRML6 |
Accès en lecture. | Uniquement si le portail permet aux parents d’accéder à la fonctionnalité “Résiliations”. |
CRMLK |
Accès en lecture. | Uniquement si le portail permet aux parents d’accéder à la fonctionnalité “Bon à savoir”. |
CRM40 |
Accès en lecture/écriture. | Accès obligatoire. |
GTP01 |
Accès en lecture. | Accès obligatoire pour lire les configurations. |
GTP11 |
Accès en lecture/écriture. | Accès obligatoire. |
GTP12 |
Accès en lecture/écriture. | Accès obligatoire. |
GTP18 |
Accès en lecture. | Uniquement si le portail permet aux parents d’accéder à la fonctionnalité “Absences”. |
GTP40 |
Accès en lecture. | Uniquement si le portail permet aux parents d’accéder à la fonctionnalité “Agenda”. |
GTPPI |
Accès en lecture. | Uniquement si le portail permet aux parents d’accéder à la fonctionnalité “Saisie des irréguliers”. |
UNI42 |
Accès en lecture/écriture. | Accès obligatoire. |
DEB02 |
Accès en lecture. | Uniquement si le portail permet aux parents d’accéder à leur factures. |
DEBED |
Accès en lecture. | Nécessaire si accès au DEB02. |
DEBOF |
Accès en lecture. | Nécessaire si accès au DEB02. |
DEB54 |
Accès en lecture. | Nécessaire si accès au DEB02. |
DEB65 |
Accès en lecture. | Nécessaire si accès au DEB02. |
Afin de simplifier le déploiement, une image docker est disponible permettant en quelques lignes d’avoir un portail opérationnel
facilement maintenable. Cette image s’appelle saierp/portal. La version de l’image dépend du serveur pointé. Par exemple,
pour un serveur en version 4.10, l’image sera saierp/portal:4.10.
Afin de pouvoir déployer l’image, il est nécessaire d’avoir docker installé sur la machine.
Afin de déployer l’image, créer un fichier docker-compose.yml avec le contenu suivant :
version: "3.0"
services:
sainet_portal:
restart: always
image: saierp/portal:4.12
environment:
- <variable>=<valeur>
- ...
volumes:
- "./portal/app:/usr/src/app"
- "./portal/update:/usr/src/update"
ports:
- "<port>:3001"
Le <port> correspond au port externe d’écoute de l’image docker. En interne, le port 3001 est utilisé. Il peut être changé dans les variables d’environnement ce qui n’est pas utile dans le cadre d’un déploiement docker.
Il est également nécessaire de configurer les deux volumes persistants sur /usr/src/app et /usr/src/update afin que les mises à jour automatiques puissent être appliquées.
La liste des variables principales se trouve ci-dessous:
| Variable | Requis | Valeur | Définition |
|---|---|---|---|
SAINET_URL |
oui | https://<host>/SNV4SRV-mobile-war/ |
Le lien vers l’interface mobile d’un serveur SAINet. |
SAINET_USER |
oui | string |
L’utilisateur du compte de service pour le lien avec SAINet. |
SAINET_PASS |
oui | string |
Le mot de passe du compte de service. |
SAINET_DOMAIN |
oui | string |
L’identifiant du domaine du portail qui sera utilisé pour la gestion. |
SAINET_MODULE |
string |
Type de portail (MRH,REG,CRE). Par défaut CRE. |
|
SAINET_APP_NAME |
string |
Intitulé du portail. Par défaut ‘SAINet’. | |
SAINET_NPM_AUTH_TOKEN |
oui | string |
Token d’authentification pour que le portail puisse être compilé (également lors des mises à jour). Cette valeur est fournie par SAI ERP. |
SAINET_SUB_SITE_KEY |
* | string |
La clé pour le captcha de google dans le cas où l’inscription est disponible. |
SAINET_SUB_SECRET_KEY |
* | string |
La clé secrète pour vérifier le catpcha dans le cas où l’inscription est disponible. |
Les variables SAINET_SUB_SITE_KEY et SAINET_SUB_SECRET_KEY peuvent être récupérées sur Google reCAPTCHA v2 (voir ici). Ces variables
sont obligatoires lorsqu’un utilisateur peut s’enregistrer par lui-même.
Le portail s’attend à des requêtes HTTP. En cas de redirection HTTPS vers HTTP en amont (via Apache ou Traefik), il est nécessaire d’insérer le header X-Forwarded-Proto avec la valeur https sinon le mode NODE_ENV=production ne fonctionnera pas.
Les variables complémentaires suivantes sont également disponibles:
| Variable | Type | Définition |
|---|---|---|
SAINET_ROOT_DIR |
string |
Chemin d’installation du portail SAINet. Par défaut /usr/src en Docker. Sous Windows (service.bat), cette variable est obligatoire et n’a pas de valeur par défaut. |
SAINET_AUTOUPDATE_COOLDOWN |
integer |
Temps d’attente (en ms) avant de vérifier l’existence d’une mise à jour au (re)démarrage du service. Par défaut, 1h. |
SAINET_RELATIVE_PATH |
string |
URL relative du portail lorsque ce dernier ne se trouve pas à la racine du site. |
SAINET_LOGOUT_URL |
string |
URL de logout par un service externe. Utilisé en lien avec SAINET_SESSION_TYPE=F5. |
SAINET_SESSION_TYPE |
string |
Type de session. Peut prendre la valeur F5 dans le cas d’une authentification gérée par un service spécial. En mode F5, l’option « Utiliser un identifiant externe » de la configuration de connexion du portail doit être activée, sinon les connexions par identifiant externe sont refusées. |
SAINET_DOWNLOAD_FOLDER |
string |
Dossier de téléchargement des mises à jour. |
SAINET_DISPLAY_ENDPOINT |
boolean |
Affichage de l’endpoint dans les logs lors du démarrage et quitte le processus. |
SAINET_PORT |
integer |
Le port interne d’écoute du portail. Par défaut 3001. |
SAINET_AUTO_UPDATE |
0 ou 1 |
Permet d’activer ou désactiver la mise à jour automatique. Par défaut 1. |
SAINET_CSRF_CHECK |
0 ou 1 |
Permet d’activer le contrôle d’origine de la protection CSRF (1). Par défaut 0 (désactivé). Voir Protection CSRF. |
SAINET_LOG_LEVEL |
1 à 6 |
Logging pour node. Par défaut à 6 (DEBUG). |
SAINET_SERVER_LOG_LEVEL |
1 à 6 |
Logging pour les appels serveurs. Par défaut à 2 (WARNING). |
SAINET_CONFIG_LOG_LEVEL |
1 à 6 |
Logging pour la gestion de la configuration. Par défaut à 2 (WARNING). |
SAINET_SESSION_KEY |
string |
Secret servant à signer les cookies de session et à chiffrer le mot de passe en attente lors d’une double authentification (MFA). Recommandé pour tout déploiement, et indispensable dès que plusieurs instances du portail tournent sans Redis. Doit être une chaîne aléatoire d’au moins 32 caractères. Si la variable est absente, un secret aléatoire est généré au démarrage : partagé entre les instances via Redis si SAINET_REDIS_HOST est défini, propre au processus sinon (les sessions sont alors perdues à chaque redémarrage). Un avertissement est écrit dans les logs. Avec Redis, ce secret généré est stocké dans le même Redis que les sessions (et que les données MFA en attente, chiffrées) : toute personne pouvant lire Redis peut alors forger des cookies de session, d’où la recommandation de définir SAINET_SESSION_KEY. Le premier déploiement de cette version, ainsi que tout changement de cette valeur, déconnecte une fois tous les utilisateurs. |
SAINET_REDIS_HOST |
string |
Host du service Redis. Si pas spécifié, un cache local sera utilisé. |
SAINET_REDIS_PORT |
integer |
Port du service Redis. Par défaut 6379. |
SAINET_REDIS_PASSWORD |
string |
Mot de passe pour le service redis. |
SAINET_NODE_OPTIONS |
options | Liste d’options à passer à la commande node. Par défaut, seule l’option –max-old-space-size est mise à 512. |
NODE_ENV |
development,production |
Définit le mode d’exécution du portail en terme d’optimisation. Par défaut production (nécessite un accès en HTTPS). |
NODE_TLS_REJECT_UNAUTHORIZED |
0 ou 1 |
Permet d’ignorer les erreurs de certificat lors de tests https en serveur local. Par défaut à 0 (<=3.0.2) et 1 (>=3.0.3). |
Le portail doit être placé derrière exactement un reverse proxy de confiance (trust proxy à 1) : c’est à cette condition que la limitation des tentatives de connexion par adresse IP est fiable. Les compteurs de cette limitation sont conservés en mémoire, par instance du portail.
Voici un exemple de docker-compose.yml minimal dans le cadre d’un déploiement avec une partie pré-inscription. L’image Docker du portail
est déployée sur Docker Hub.
Cette exemple montre une configuration du serveur SAINet avec son compte de service et la mise en place du captcha google pour la pré-inscription.
version: "3.0"
services:
sainet_portal:
restart: always
image: saierp/portal:4.12
environment:
- SAINET_APP_NAME=MyPortal
- SAINET_URL=https://my-sainet-server.ch/SNV4SRV-mobile-war
- SAINET_MODULE=CRE
- SAINET_USER=portal
- SAINET_PASS=example
- SAINET_DOMAIN=POR
- SAINET_NPM_AUTH_TOKEN=123456789=
- SAINET_REDIS_HOST=sainet_redis
- SAINET_SUB_SITE_KEY=123456789abcd
- SAINET_SUB_SECRET_KEY=987654321dcba
volumes:
- "./portal/app:/usr/src/app"
- "./portal/update:/usr/src/update"
ports:
- "3001:3001"
sainet_redis:
restart: always
image: redis:7-alpine
command: redis-server --maxmemory 512m
Il est important de pouvoir accéder en https à l’URL de login (car des cookies sécurisés sont utilisées). Si cela n’est pas le cas, alors il
est nécessaire de définir NODE_ENV=development afin de pouvoir se connecter. Dans le cas contraire, le header HTTP X-Forwarded-Proto
doit être inséré dans la redirection avec la valeur “https” afin que l’utilisateur puisse être authentifié.
En utilisant Traefik pour réceptionner les requêtes https, il n’y a pas de configuration spéciale à effectuer car les headers nécessaires sont
déjà inclus dans la requête transférée (x-forwarded-for, x-forwarded-host, x-forwarded-port, x-forwarded-proto, x-forwarded-server et x-real-ip).
Dans le cas d’une configuration Apache2 (dans une configuration VirtualHost), il est nécessaire d’activer le mode headers:
a2enmod headers
Il suffit ensuite d’ajouter la ligne ci-dessous dans le VirtualHost pour que le header soit ajouté lors de la redirection.
RequestHeader set "X-Forwarded-Proto" "https"
Lorsque la protection est activée (SAINET_CSRF_CHECK=1), le portail refuse en HTTP 403 toute requête dont la méthode n’est pas GET, HEAD ou OPTIONS provenant d’un autre site que lui-même. Le contrôle s’effectue dans l’ordre suivant :
- Si l’en-tête
Sec-Fetch-Siteest présent, seules les valeurssame-originetnonesont acceptées. Toute autre valeur, y comprissame-site, est refusée : un formulaire hébergé sur un sous-domaine voisin est donc rejeté. - Sinon, si l’en-tête
Originest présent, son hôte (port compris) doit être identique à l’hôte de la requête. Le schéma n’est pas comparé. - Si aucun de ces deux en-têtes n’est présent (clients non navigateurs), la requête est acceptée.
Les requêtes GET, HEAD et OPTIONS ne sont pas contrôlées.
Le reverse proxy doit respecter les points suivants :
- ne pas retirer ni réécrire les en-têtes
OriginetSec-Fetch-*; - transmettre l’hôte d’origine de la requête : soit en le conservant dans l’en-tête
Host(sous Apache, en activant la directiveProxyPreserveHost), soit en renseignant l’en-têteX-Forwarded-Host. Le portail utiliseX-Forwarded-Hosts’il est présent, sinonHost. L’en-têteX-Forwarded-Hostn’est pris en compte que si la requête provient du proxy de confiance (réglagetrust proxydu portail, limité à un saut).
Si le proxy réécrit l’hôte (par exemple en le remplaçant par le nom interne du portail) sans transmettre l’hôte d’origine, et que le navigateur n’envoie pas Sec-Fetch-Site, l’hôte de l’en-tête Origin ne correspond plus et toutes les actions sont refusées en 403.
Le contrôle est désactivé par défaut, par compatibilité avec les installations existantes. La variable d’environnement SAINET_CSRF_CHECK=1, lue une seule fois au démarrage du portail, l’active. L’activation est recommandée, une fois vérifié que le reverse proxy conserve l’en-tête Host ou transmet X-Forwarded-Host, et qu’il ne retire pas les en-têtes Sec-Fetch-* et Origin. Seule la valeur exacte 1 active le contrôle : toute autre valeur, ou l’absence de la variable, le laisse désactivé et les requêtes sont acceptées quelle que soit leur origine.
La variable se pose à l’un des emplacements suivants :
- sous Docker, dans la section
environment:du fichier compose (ou avec l’option-ededocker run), qui prend le pas sur la valeur par défaut de l’image ; - sous Windows, dans le fichier
env.bat, appelé parservice.bataprès les valeurs par défaut.
Sous Windows, aucun espace ne doit suivre la valeur dans SET SAINET_CSRF_CHECK=1 : l’espace ferait partie de la valeur et le contrôle resterait désactivé.
Un avertissement est écrit dans les logs au démarrage, que le contrôle soit activé ou non.
Indépendamment de cette variable, les actions à effet de bord (déconnexion, acceptation des conditions d’utilisation, fonctions d’administration /features/**) n’acceptent que la méthode POST : une requête GET sur ces adresses n’exécute rien (au plus, une page de confirmation ou de présentation est affichée).
Pour la configuration Apache, voir la installation Apache.
Il est possible de mettre le portail derrière un service traefik afin de gérer le certificat SSL. La configuration ci-dessous est un exemple (basé sur cette documentation) qui sert un certificat statique.
services:
sainet_portal:
...
labels:
- "traefik.http.routers.sainet_portal.rule=PathPrefix(`/`)"
- "traefik.http.routers.sainet_portal.entrypoints=websecure"
- "traefik.http.services.sainet_portal.loadbalancer.server.port=3001"
- "traefik.http.routers.sainet_portal.tls=true"
sainet_traefik:
restart: always
image: traefik:v3.6
depends_on:
- sainet_portal
command:
- --providers.docker
- --providers.file.directory=/certificates/config
- --entrypoints.web.address=:80
- --entrypoints.web.http.redirections.entrypoint.to=websecure
- --entrypoints.web.http.redirections.entrypoint.scheme=https
- --entrypoints.web.http.redirections.entrypoint.permanent=true
- --entrypoints.websecure.address=:443
volumes:
- "/var/run/docker.sock:/var/run/docker.sock"
- "./certificates:/certificates"
ports:
- "443:443"
Redis permet de garder certaines données en cache, notamment au niveau des sessions utilisateurs. Par conséquent, il est utile que ces données soient persistentes afin que les utilisateurs ne se retrouvent pas déconnectés si le service de portail venait à redémarrer (typiquement lorsqu’un administrateur applique une mise à jour).
En cas de problème, la valeur des variables SAINET_LOG_LEVEL, SAINET_SERVER_LOG_LEVEL et SAINET_CONFIG_LOG_LEVEL peut prendre une valeur de 1 à 6 avec les définitions suivantes:
SEVEREWARNINGFINEFINERFINESTDEBUG
La procédure pour installer le portail en tant que service sur Windows:
- Installer le serveur Apache en changeant le
portpour 3001 dans la configuration. - Installer la dernière version LTS de NodeJS (
npmetnodedoivent être disponibles dans la variable d’environnementPATH). - Installer sevenzip (
7zdoit être disponible dans la variable d’environnementPATH). - Télécharger l’artifact du portail.
- Extraire les fichiers dans un sous-dossier
app(par exempleD:/sainet/portal/app). - Copier les fichiers
app/windows/env.batetapp/windows/service.batau même niveau que le répertoireapp(ils doivent être dehors du répertoire). - Mettre à jour les variables dans
env.bat. - Créer un service en redémarrage automatique avec nssm (voir ici) en pointant le fichier
<portal>/service.bat. - Le dossier d’exécution (« Startup directory ») du service doit être
<portal>(mettre le chemin complet), c’est-à-dire le dossier qui contientenv.batetservice.bat.
service.bat appelle env.bat par un chemin relatif, avant tout changement de répertoire : sans le réglage du dossier d’exécution indiqué ci-dessus, le service démarre par défaut dans System32, où env.bat n’est pas trouvé, ce qui fait échouer le démarrage. L’exemple de dossier fourni pour le service SAINet principal ne s’applique pas au portail.
Il est possible de tester le démarrage du portail en lancant la commande suivante dans une console:
cd <portal>
service.bat
Lorsque la mise à jour automatique est active (SAINET_AUTO_UPDATE=1), le portail va contrôler chaque nuit si une nouvelle version du portail
est disponible à travers SAINet. Au besoin, la nouvelle version est téléchargée et le container se relance pour appliquer la mise à jour.
A noter également que lorsque le container est (re)démarré, le portail va directement vérifier la disponibilité d’une mise à jour et
l’installer le cas échéant. Un timestamp local évite que cela se fasse à chaque (re)démarrage si celui-ci intervient moins d’une heure
avant la dernière mise à jour. Cela peut-être forcé en supprimant le fichier <update>/update.time et en redémarrant le container.
Une page d’administration est également disponible sur https://<url-portal>/admin-login. Il est nécessaire de fournir un utilisateur/mot de passe
SAINet ayant le rôle SUPERADMIN afin de s’y connecter.
Un utilisateur SUPERADMIN connecté avec la double authentification peut ouvrir le portail tel que le voit un utilisateur du portail (pour le support, avec un motif obligatoire, une durée limitée à 30 minutes et une trace d’audit). Cette fonctionnalité est décrite dans le guide d’aide « Impersonation d’un utilisateur du portail » (chaîne SYS). Elle est indisponible avec SAINET_SESSION_TYPE=F5, et la définition de SAINET_SESSION_KEY ainsi que le reverse proxy unique (trust proxy à 1, afin que l’adresse IP enregistrée dans l’audit soit celle du navigateur) sont recommandés (voir les variables d’environnement).
Afin de vérifier que la connexion du portail à SAINet se fait correctement, il est possible d’exécuter la commande suivante:
curl -H 'X-Auth-User:<portal>' -H 'X-Auth-Pass:<password>' 'https://portal-bes.reg.sai-erp.net/clearcache?type=configuration'
Il est possible d’effectuer du suivi de l’utilisation du portail de manière anonyme via Google Analytics. Ce service permet d’obtenir des informations sur les pages du portail qui ont été visitées par les utilisateur.
Pour mettre en place ce suivi, il suffit de générer un nouveau Stream pour le portail dans Google Analystics et de récupérer la clé (Mesurement ID).
Dans le domaine du portail, créer un page Paramètres divers dans UNI91 et renseigner la clé.
Certains navigateurs ou extensions (bloqueur de publicité, protections intégrées comme Brave Shields, proxy d’entreprise, cookies refusés) empêchent le chargement d’une partie du portail. Pour éviter qu’un utilisateur reste devant une page inutilisable sans explication, un contrôle s’exécute dans le navigateur sur les pages d’entrée du portail : connexion, connexion administrateur, activation et réinitialisation du mot de passe, politique de confidentialité et préinscription (crèches).
Lorsqu’un blocage est détecté (cookies refusés, bibliothèque externe non chargée ou script de page interrompu), un panneau
explique la marche à suivre et affiche un code de diagnostic au format <navigateur>-<causes>, par exemple BR-JQJS
(BR Brave, ED Edge, FF Firefox, CH Chrome, SF Safari, OT autre ; CK cookies, ST stockage du site,
JQ/LD/MO bibliothèques manquantes, JS script interrompu). L’utilisateur peut fermer le panneau et continuer.
Le rapport du navigateur est envoyé au portail (POST /diag/client) et journalisé en niveau WARN avec le préfixe [client-preflight]
(code, utilisateur, page, état des cookies et du stockage, ressources bloquées, erreurs, User-Agent). Il suffit de rechercher le
code communiqué par l’utilisateur dans les logs du portail.
Les coordonnées de l’administration affichées à côté du code se renseignent dans UNI91, page Paramètres divers, champ Contact de l'administration
(texte libre sur une ligne, affiché tel quel). Si le champ est vide, seul le message générique est affiché. La valeur est mise en cache
avec la configuration du portail : elle n’est prise en compte qu’après un rechargement de la configuration (voir
Commandes utiles, commande clearcache?type=configuration).
Sur un serveur virtualisé, cette exception peut survenir au démarrage (voir cette issue):
sainet_portal_1 | Error: Could not load the "sharp" module using the linux-x64 runtime
sainet_portal_1 | Unsupported CPU: Prebuilt binaries for linux-x64 require v2 microarchitecture
sainet_portal_1 | Possible solutions:
sainet_portal_1 | - Ensure optional dependencies can be installed:
sainet_portal_1 | npm install --include=optional sharp
sainet_portal_1 | - Ensure your package manager supports multi-platform installation:
sainet_portal_1 | See https://sharp.pixelplumbing.com/install#cross-platform
sainet_portal_1 | - Add platform-specific dependencies:
sainet_portal_1 | npm install --os=linux --cpu=x64 sharp
sainet_portal_1 | - Consult the installation documentation:
sainet_portal_1 | See https://sharp.pixelplumbing.com/install
sainet_portal_1 | at Object.<anonymous> (/usr/src/app/node_modules/sharp/lib/sharp.js:121:9)
sainet_portal_1 | at Module._compile (node:internal/modules/cjs/loader:1730:14)
sainet_portal_1 | at Object..js (node:internal/modules/cjs/loader:1895:10)
sainet_portal_1 | at Module.load (node:internal/modules/cjs/loader:1465:32)
sainet_portal_1 | at Function._load (node:internal/modules/cjs/loader:1282:12)
sainet_portal_1 | at TracingChannel.traceSync (node:diagnostics_channel:322:14)
sainet_portal_1 | at wrapModuleLoad (node:internal/modules/cjs/loader:235:24)
sainet_portal_1 | at Module.require (node:internal/modules/cjs/loader:1487:12)
sainet_portal_1 | at require (node:internal/modules/helpers:135:16)
sainet_portal_1 | at Object.<anonymous> (/usr/src/app/node_modules/sharp/lib/constructor.js:10:1)
Pour corriger cela, une solution est de changer le type de CPU au niveau de PVE pour utiliser x86-64-v2 au lieu de Common KVM processor.
Si le service est directement installé sur la machine, dans ce cas simplement lancer la commande npm install --os=win32 --cpu=x64 sharp et relancer le service.


