reconversion informatique

Reconversion en informatique

Qui suis je?

Je suis le fondateur du centre de formation Yvonh.com, un centre de formation certifié Qualiopi, dédié à l’apprentissage du développement web. Mon objectif est d’aider les personnes qui souhaitent apprendre à créer des sites web, développer des applications et comprendre les technologies qui font fonctionner internet aujourd’hui.

Les points différenciant de mon organisme de formation

Le développement web est devenu une compétence très recherchée. Aujourd’hui, presque toutes les entreprises ont besoin d’une présence en ligne, que ce soit à travers un site internet, une application web ou des services numériques. C’est pour répondre à cette demande croissante que j’ai créé Yvonh.com : un centre de formation qui permet d’apprendre le développement web de manière claire, progressive et surtout pratique.

Dans mes formations, je commence toujours par les bases fondamentales du web. J’accompagne les apprenants dans la découverte du HTML, qui permet de structurer les pages web, et du CSS, qui sert à mettre en forme les sites internet. Ces deux technologies sont indispensables pour comprendre comment un site web est construit. L’accompagnement est personnalisé.

L’un des points les plus importants dans ma pédagogie est la pratique. Je privilégie toujours l’apprentissage par projets. Les apprenants réalisent des exercices concrets et développent progressivement leurs propres projets web. Cette approche leur permet non seulement de mieux comprendre les concepts, mais aussi de développer leur autonomie et leur capacité à résoudre des problèmes. Vous disposez d’un Discord pour l’aide.

Je transfère mon savoir faire de 12 ans dans le code

Au-delà des langages et des technologies, je mets également l’accent sur les bonnes pratiques du développement web. J’enseigne comment organiser son code, utiliser des outils professionnels, gérer les versions d’un projet ou encore sécuriser une application web. Ces compétences sont essentielles pour travailler efficacement dans un environnement professionnel.

Avec Yvonh.com, mon ambition est de rendre le développement web accessible à tous : étudiants, professionnels en reconversion ou simples passionnés de technologie. Je souhaite transmettre non seulement des compétences techniques, mais aussi une manière de penser et de construire des projets numériques.

Et l’IA?

L’IA n’est pas oublié, je vous apprendrai tirer profit de l’IA dans votre apprentissage. Dans le monde de l’entreprise également vous serez demandé à utiliser l’IA, les nouveaux outils comme Antigravity ou Claude Code (le plus puissant au moment où j’écris ces lignes)

Certificat Qualiopi :

La Certification Qualiopi a été délivrée au titre de la catégorie d’action suivante : Actions de formation

Certaines formations proposées peuvent faire l’objet d’une prise en charge par des dispositifs de financement (CPF, OPCO, France Travail…), selon les conditions définies par les organismes financeurs.
Pour plus d’informations, veuillez nous contacter. (Mettre un lien vers la page Contact).

Enregistré sous le numéro de déclaration d’activité  76310966431 auprès de la DREETS Occitanie (cet enregistrement ne vaut pas agrément de l’Etat)

Siret : 510 776 529 00040 , l’avis de situation est téléchargeable sur le site de l’Insee.

Certificat Qualiopi :

Formation au vibe coding développez avec l’IA

Pourquoi apprendre le vibecoding?

Le vibecoding, qui consiste à parler à une IA pour générer du code fonctionnel, a transformé l’équilibre des forces entre les sachants et les non sachant coder. En effet le développement d’application était réservé à une minorité de personnes qui ont mis des années à parfaire leurs connaissances en code. L’arrivée des LLM (modèle larges de données) a permis à tout un chacun de développer des application web sans vraiment avoir passsé des années à apprendre et pratiquer le code.

Est ce à dire qu’il n’est plus besoin de savoir lire du code basique ou d’écrire du code basique pour développer une application? Rien n’et moins sûr, en effet, ce que vous voyez dans les réseaux sociaux montre des petites applications simples développée à partir de zéro.

Le jeu se complique lorsque l’application grandit. Or vous ne pouvez pas ignorer votre oeuvre, il faut au moins en maitriser les grandes lignes. au fur et à msur qu’il grandit, que vous ajoutez des fonctionnalité, il faut pouvoir suivre son évolution, comme un enfant qui grandit il faut savoir l’appréhender sinon il va mal finir !

Public cible :

Porteur de projet à la recherche de prototype fonctionnel, SEO, Marketeur, curieux passionné mais ne sachant pas encore coder, créateur d’entreprise, indépendants. Chef de projet, product Owner,développeur, chef d’entreprise TPE/PME

Objectif de la formation : à l’issue de la formation, vous saurez comment fonctionne un LLM, la génération de code, comment prompter un LLM pour générer une application sécurisée. Vous saurez déployer cette application en ligne. La maintenir et la faire évoluer.

Programme de formation

Comprendre les LLM et le prompting

Maitriser les outils de vibecoding : Lovable pour les interfaces, Antigravity, Cursor, Windsurf,Claude Code

Générer tester et corriger du code

construire un mini projet fonctionnel

intégrer le workflow avec Git et tests

Déployer l’application en ligne

Pourquoi utiliser rsync entre deux serveurs Linux ?

Quand on administre deux serveurs Linux, il y a vite un besoin très concret qui revient: copier des fichiers sans tout retransférer à chaque fois. C’est là que rsync devient vraiment utile. L’outil existe depuis longtemps, il n’a rien de spectaculaire dans sa forme, mais il rend des services énormes dès qu’on doit synchroniser un répertoire web, répliquer des sauvegardes ou envoyer des fichiers de logs vers une autre machine.

Son intérêt principal tient dans sa manière de travailler. Rsync compare la source et la destination, puis n’envoie que ce qui a changé. Sur un gros volume de données, la différence est immédiate. On gagne du temps, de la bande passante et, franchement, pas mal de tranquillité quand on doit automatiser ça la nuit avec cron ou systemd timers.

Si vous gérez aussi des accès distants et des transferts sécurisés, vous pouvez prolonger le sujet avec cet article sur la copie de fichiers entre machines Linux. Et pour rester dans les usages concrets côté administration, ce billet sur les commandes Linux utiles au quotidien complète bien la logique.

À quoi sert rsync au quotidien

# synchroniser un dossier vers un autre serveur
rsync -avz /var/www/ user@serveur2:/var/www/

# sauvegarde avec suppression des fichiers effacés côté source
rsync -av --delete /data/ backup@serveur2:/backups/data/

Dans la vraie vie, rsync sert rarement pour faire joli. On l’utilise parce qu’on a un besoin simple: garder deux emplacements cohérents sans recopier bêtement l’ensemble. Typiquement, un serveur de production envoie chaque nuit une sauvegarde vers un second serveur. Autre cas classique, un développeur pousse un répertoire d’application vers une machine distante en excluant les fichiers temporaires. On le voit aussi dans les migrations, par exemple pour déplacer un site volumineux sans couper le service trop longtemps.

La commande de base ressemble à ceci:

  • rsync -avz /source/ user@serveur-distant:/destination/

Le -a conserve les permissions, dates et liens symboliques. Le -v affiche le détail des opérations. Le -z compresse les données pendant le transfert, ce qui peut être utile sur un lien lent. Dans la plupart des environnements, on l’associe à SSH pour éviter de transférer des données en clair.

Comment synchroniser des fichiers entre deux serveurs

Le plus simple consiste à lancer rsync depuis le serveur source vers le serveur cible. Par exemple, pour synchroniser un dossier de sauvegarde:

  • rsync -av /var/backups/ admin@192.0.2.10:/srv/backups/

Le slash final a son importance. /var/backups/ signifie qu’on copie le contenu du dossier. Sans ce slash, on copie le dossier lui-même dans la destination. C’est un détail qui semble mineur jusqu’au jour où l’arborescence d’arrivée n’est plus celle qu’on attendait.

Pour passer par SSH avec une clé précise ou un port non standard, on peut faire:

  • rsync -av -e "ssh -p 2222 -i /root/.ssh/id_rsa" /data/ backup@serveur2:/data/

Cette approche est propre pour les scripts automatisés. Elle évite les mots de passe interactifs et s’intègre bien dans une routine de sauvegarde. Si vous devez d’abord tester sans rien modifier, ajoutez --dry-run. C’est probablement l’option la plus rassurante de tout l’outil, parce qu’elle montre ce que rsync ferait sans toucher aux fichiers.

Les options qui font vraiment la différence

# simulation avant exécution réelle
rsync -avzn --delete /data/ backup@serveur2:/backups/data/

Au-delà de la base, quelques options changent clairement la manière de travailler. --progress permet de suivre l’avancement, ce qui est appréciable sur un gros transfert. --exclude évite d’embarquer des caches, des dossiers Git ou des fichiers temporaires. --bwlimit limite la bande passante si vous ne voulez pas saturer un lien partagé avec d’autres services.

Pour une sauvegarde plus fidèle, beaucoup utilisent aussi --numeric-ids quand les UID et GID doivent rester strictement identiques entre les deux serveurs. Dans certains contextes, --delete entre également en jeu, mais c’est une option qui mérite un minimum de respect. J’y reviens juste après, parce qu’elle peut rendre service aussi vite qu’elle peut faire disparaître des fichiers.

Il y a aussi un duo très pratique pour les sauvegardes incrémentales artisanales: --link-dest et les liens matériels. Ce n’est pas toujours nécessaire, mais sur un serveur de backup, cela permet de conserver plusieurs états d’un répertoire sans dupliquer physiquement tous les fichiers inchangés.

Pourquoi il faut être prudent avec –delete

--delete indique à rsync de supprimer, côté destination, les fichiers qui n’existent plus côté source. Sur le papier, c’est logique: si l’on veut une vraie synchronisation, la destination doit refléter la source. En pratique, c’est aussi la meilleure façon d’effacer un contenu utile si l’on s’est trompé de répertoire ou si la source n’est pas dans l’état attendu.

Un exemple simple: vous pensez synchroniser /var/www/site/, mais vous pointez par erreur vers un dossier vide. Avec --delete, rsync peut très bien nettoyer la destination pour la rendre conforme à ce dossier vide. Ce n’est pas un bug, c’est exactement ce qu’on lui a demandé.

La bonne habitude consiste à tester d’abord avec --dry-run, à relire la source et la destination, puis à activer --delete seulement quand le scénario est clair. Beaucoup d’admins préfèrent aussi journaliser les exécutions pour garder une trace des suppressions et repérer immédiatement un comportement anormal.

Des usages réels en administration Linux

Rsync est très à l’aise dans plusieurs situations concrètes. Pour un serveur web, il peut envoyer chaque nuit une copie des fichiers statiques vers une machine de secours. Pour une base de fichiers utilisateurs, il permet de répliquer régulièrement les documents sur un stockage distant. Dans un contexte de supervision, il peut aussi centraliser des logs ou des exports générés par différents serveurs.

On le croise souvent dans des scripts simples mais robustes. Un cron lance une synchronisation à 2 h du matin, écrit le résultat dans un fichier log, puis envoie une alerte seulement en cas d’erreur. Ce n’est pas l’outil le plus moderne du monde, mais il reste très bon pour faire un travail précis sans complexité inutile.

Autre usage intéressant, la préparation d’une migration. On lance un premier rsync plusieurs jours avant le basculement, puis un second juste avant la coupure pour transférer uniquement les derniers changements. Cela réduit fortement la fenêtre d’interruption et évite de recopier plusieurs centaines de gigaoctets au dernier moment.

Quand un outil dure aussi longtemps dans les environnements Linux, ce n’est généralement pas un hasard. Rsync reste là parce qu’il répond à un besoin concret, avec une logique simple: transférer seulement ce qui doit l’être, garder la main sur les options, et pouvoir automatiser le tout sans transformer une tâche banale en usine à gaz.

Comment organiser ses fichiers sous Linux sans se compliquer la vie ?

On utilise souvent Linux pour sa souplesse, mais cette liberté a un revers: si on manipule ses fichiers sans méthode, on finit vite avec des dossiers en vrac, des copies en double et un terminal qui devient plus risqué qu’utile. L’idée de ce mémento n’est pas d’aligner des commandes comme dans une fiche de révision. Le but est plutôt de garder sous la main les gestes qui servent vraiment quand on trie, déplace, cherche ou nettoie des fichiers au quotidien.

Si vous aimez avoir une base claire avant d’aller plus loin, vous pouvez aussi jeter un oeil à cet autre repère pratique. Et pour compléter avec une lecture qui aide à mieux prendre ses marques dans l’environnement Linux, ce contenu lié s’intègre naturellement à la même logique d’apprentissage concret.

Voir ce qu’il y a vraiment dans un dossier

ls -lah
find . -type f | wc -l
find . -type f -name "*.log"

La commande ls paraît banale, pourtant c’est souvent elle qui donne le ton. Utilisée seule, elle affiche une liste brute. Utilisée avec un peu plus d’attention, elle permet déjà d’éviter pas mal d’erreurs. ls -lah, par exemple, montre les fichiers cachés, les tailles lisibles et les droits. Quand on revient sur un vieux projet ou sur un répertoire système, ce simple réflexe évite de déplacer ou supprimer quelque chose sans avoir vu qu’il s’agissait d’un fichier caché ou d’un lien symbolique.

Dans la pratique, je conseille de ne pas regarder seulement les noms. Regardez aussi la taille, la date et le propriétaire. Un dossier rempli de sauvegardes oubliées saute vite aux yeux. Un fichier de configuration modifié récemment aussi. Linux donne beaucoup d’informations d’un coup, à condition de prendre deux secondes pour les lire.

Exemple utile: pour inspecter un dossier de téléchargements devenu illisible, un ls -lah ~/Téléchargements permet déjà de repérer les archives lourdes, les doublons nommés (1) ou final-final, et les fichiers cachés laissés par certains logiciels.

Copier et déplacer sans créer de désordre

cp -a projet projet.backup
mv ancien.txt archive/ancien.txt
rm -i fichier.txt

cp et mv font partie des commandes qu’on croit maîtriser trop vite. Copier un fichier, c’est simple. Copier un dossier entier demande en revanche un peu d’attention. Avec cp -r dossier source dossier-copie, on recopie l’arborescence. Avec cp -a, on conserve en plus les permissions, les dates et la structure de façon plus fidèle. C’est souvent le bon choix pour archiver un projet ou dupliquer un répertoire de configuration.

mv, lui, ne sert pas seulement à déplacer. Il sert aussi à renommer proprement. C’est pratique quand on veut remettre de l’ordre sans ouvrir d’interface graphique. Renommer rapport-v2-bon.docx en rapport-client-avril.docx avec mv prend une seconde et impose au passage une vraie discipline de nommage.

Le piège classique, c’est l’écrasement silencieux. Selon le contexte, une copie ou un déplacement peut remplacer un fichier existant. Pour garder la main, beaucoup préfèrent cp -i et mv -i, qui demandent confirmation avant d’écraser. Ce n’est pas spectaculaire, mais c’est exactement le genre d’habitude qui évite une perte bête un lundi matin.

  • cp -a projet/ sauvegarde-projet/ pour cloner un dossier en gardant ses attributs
  • mv facture.txt archives/ pour ranger un fichier
  • mv notes.txt notes-reunion.txt pour renommer sans ambiguïté

Supprimer avec prudence, surtout avec rm

rm est rapide, direct et parfois trop direct. Sous Linux, supprimer avec rm ne passe pas par une corbeille classique. Une fois parti, le fichier n’est pas censé revenir facilement. C’est pour ça qu’il vaut mieux considérer rm comme un outil de finition, pas comme une gomme qu’on utilise à la légère.

Pour un fichier isolé, rm -i reste une bonne ceinture de sécurité. Pour un dossier, rm -r enlève tout le contenu récursivement. C’est précisément là que les erreurs coûtent cher. Une mauvaise complétion automatique, un espace mal placé ou une variable vide dans un script, et on peut effacer bien plus que prévu.

Une méthode saine consiste à vérifier d’abord avec ls ou find, puis à supprimer ensuite. Autre bonne habitude: tester sa commande sur un petit sous-ensemble avant de lancer un nettoyage massif. Si vous voulez supprimer tous les fichiers .tmp d’un dossier de travail, commencez par les lister. Le terminal n’aime pas l’improvisation.

Trouver le bon fichier au bon moment

Quand l’arborescence grossit, find devient vite plus utile qu’un navigateur de fichiers. C’est la commande qui sauve du temps quand on sait à peu près ce qu’on cherche sans savoir où ça se trouve. Un find . -name "*.pdf" dans un répertoire parent permet de remonter toute une série de documents éparpillés. Un find . -type f -mtime -7 aide à voir ce qui a changé récemment.

Ce qui rend find vraiment pratique, c’est qu’il ne sert pas seulement à chercher. Il aide à préparer une action propre. On peut repérer les gros fichiers, les fichiers vieux, les extensions oubliées, ou les dossiers vides avant de décider quoi faire. Cela change tout: on arrête de nettoyer à l’aveugle.

Exemple concret: dans un dossier de projet, find . -type f -size +100M mettra rapidement en évidence une vidéo de test, une archive exportée ou un binaire oublié qui gonfle inutilement l’espace disque.

Comprendre les permissions pour éviter les blocages absurdes

Les permissions semblent techniques au départ, puis elles deviennent très concrètes. Quand un fichier refuse de s’ouvrir, de se modifier ou de s’exécuter, le problème vient souvent de là. Dans un ls -l, la suite de lettres comme rwxr-xr-- indique qui peut lire, écrire ou exécuter.

Avec chmod, on ajuste les droits. Avec chown, on change le propriétaire. Il ne s’agit pas de mémoriser toutes les combinaisons d’un coup. Il suffit de comprendre l’essentiel: un script sans droit d’exécution ne se lance pas, un fichier appartenant à un autre utilisateur peut résister à l’édition, et un dossier sans droit d’écriture empêche d’y créer quoi que ce soit.

Un cas fréquent: vous récupérez un script shell, vous essayez de le lancer, et Linux répond que l’accès est refusé. Dans bien des cas, chmod +x script.sh règle simplement le souci. Là encore, la logique compte plus que la récitation.

Les habitudes qui rendent tout ça vraiment sûr

Les bonnes commandes ne suffisent pas. Ce qui fait la différence, ce sont les habitudes. Vérifier le chemin courant avec pwd avant une suppression importante. Utiliser l’autocomplétion, mais sans lui faire une confiance aveugle. Nommer ses fichiers clairement, avec des dates cohérentes et sans variantes floues. Éviter d’agir en superutilisateur quand ce n’est pas nécessaire.

J’ajouterais une règle simple: avant toute commande destructive, pouvoir expliquer en une phrase ce qu’elle va toucher. Si ce n’est pas clair, mieux vaut s’arrêter dix secondes. C’est souvent ce petit temps mort qui évite les grosses erreurs.

Au fond, gérer ses fichiers sous Linux revient moins à connaître cent commandes qu’à bien utiliser six ou sept outils de base. ls pour voir, cp pour dupliquer, mv pour ranger, rm pour nettoyer, find pour retrouver, et un minimum de compréhension des permissions pour ne pas subir le système. Avec ça, on travaille plus vite, mais surtout plus proprement.

Quand un serveur Apache devient lent, quels réglages faut-il regarder en premier ?

Un Apache qui rame ne demande pas toujours une grosse opération de tuning. Dans beaucoup de cas, le problème vient de quelques réglages très concrets qu’on oublie parce qu’ils tournent en arrière-plan depuis longtemps. On pense tout de suite au CPU, à la RAM ou au réseau, alors que le vrai frein se cache parfois dans le mode de gestion des processus, un KeepAlive trop généreux, un module chargé pour rien ou des logs qui racontent depuis des jours ce qui ne va pas.

Le plus important, c’est d’éviter l’optimisation à l’aveugle. Changer dix paramètres d’un coup donne rarement un bon résultat, et ça rend le diagnostic presque impossible. Mieux vaut partir d’une lecture simple du comportement du serveur, puis corriger ce qui coûte vraiment du temps de réponse.

Si vous voulez déjà remettre à plat quelques bases côté pile web et hébergement, vous pouvez aussi jeter un œil à cet article. Et pour compléter avec une approche plus large sur la stabilité d’un site quand la charge monte, cette ressource apporte un bon contrepoint.

Commencer par le mode de fonctionnement d’Apache

# vérifier la configuration Apache
apachectl -t
apachectl -M
apachectl -S

Le premier réflexe utile consiste à regarder comment Apache gère ses processus ou ses threads. Beaucoup de lenteurs viennent d’un MPM mal adapté au type de trafic reçu. Entre prefork, worker et event, le comportement n’a rien d’anodin. Un serveur encore en prefork avec une charge dynamique importante peut consommer beaucoup plus de mémoire que nécessaire, surtout si PHP est encore branché d’une façon ancienne.

En pratique, il faut vérifier combien de processus sont lancés, s’ils restent occupés longtemps et si la machine commence à échanger sur le disque faute de mémoire libre. Un Apache lent n’est pas toujours saturé au sens spectaculaire du terme. Il peut simplement être engorgé par trop de workers ouverts, ou au contraire être trop court en capacité et mettre les requêtes en file d’attente.

Les directives comme StartServers, MinSpareServers, MaxSpareServers, MaxRequestWorkers ou ServerLimit méritent donc une vraie lecture. Le bon réglage dépend du volume de connexions, du poids de l’application servie et de la mémoire réellement disponible. Copier une configuration trouvée sur un forum n’a pas beaucoup de sens si votre trafic, vos modules et votre version de PHP n’ont rien à voir.

KeepAlive, utile mais parfois trop coûteux

# quelques réglages souvent regardés
KeepAlive On
MaxKeepAliveRequests 100
KeepAliveTimeout 2

<IfModule mpm_event_module>
    StartServers             2
    ThreadsPerChild         25
    MaxRequestWorkers      150
</IfModule>

KeepAlive est souvent un bon allié, parce qu’il évite d’ouvrir une nouvelle connexion TCP pour chaque ressource. Sur un site avec plusieurs fichiers statiques, c’est utile. Le problème arrive quand la durée d’attente est trop longue. Avec un KeepAliveTimeout élevé, des processus restent accrochés à des clients inactifs au lieu de traiter de nouvelles requêtes.

Sur un serveur peu chargé, cela passe inaperçu. Sous montée en charge, c’est souvent l’un des premiers points à vérifier. Un timeout court, cohérent avec le comportement du site, libère plus vite les ressources. Il faut aussi regarder MaxKeepAliveRequests. Une valeur trop basse casse l’intérêt de la persistance, une valeur trop large ne sert pas toujours davantage.

Le bon réglage n’est pas théorique. Il se mesure. Si vos visiteurs chargent des pages courtes et repartent vite, garder des connexions ouvertes trop longtemps n’apporte presque rien. Si le front sert encore beaucoup d’assets via Apache, l’effet peut être différent. C’est précisément pour ça qu’il vaut mieux observer les temps de réponse et le nombre de connexions actives avant de toucher au fichier de configuration.

Faire le tri dans les modules et la compression

Un autre classique, c’est l’empilement de modules activés “au cas où”. Avec le temps, on laisse mod_status, mod_autoindex, des réécritures complexes, des filtres de sortie ou des briques de compatibilité qui ne rendent plus vraiment service. Chaque module n’a pas le même coût, mais plus la pile est chargée, plus le chemin de traitement peut devenir lourd.

Il ne s’agit pas de désactiver tout ce qui bouge. Il faut repérer ce qui est réellement utilisé. Les modules de compression, par exemple, sont très utiles pour réduire le poids des réponses, mais ils peuvent aussi ajouter de la charge CPU si le serveur compresse trop agressivement ou compresse des contenus qui le sont déjà. Gzip ou Brotli doivent être réglés avec un peu de bon sens. Compresser du HTML, du CSS ou du JavaScript est souvent rentable. Compresser à nouveau des images ou des archives ne l’est généralement pas.

Il faut aussi regarder si Apache sert des fichiers statiques qui pourraient être déportés vers un cache, un proxy ou un CDN. Quand le serveur principal fait tout lui-même, la lenteur perçue n’est pas toujours liée à une seule page dynamique. Elle peut venir de centaines de petites réponses statiques délivrées dans des conditions pas idéales.

Lire les logs avant de toucher aux curseurs

Les logs restent la source la plus sous-exploitée quand un serveur commence à ralentir. L’access log permet déjà de voir des motifs simples, comme une explosion de requêtes sur une URL, un bot agressif, ou une ressource appelée beaucoup plus que prévu. L’error log, lui, montre souvent des signaux ignorés pendant des semaines : délais d’exécution, backend qui répond mal, problèmes de proxy, modules qui génèrent des erreurs répétées.

Activer une mesure plus fine pendant un créneau court peut aussi aider. Le but n’est pas de noyer la machine sous du debug permanent, mais d’obtenir des indices propres. Quand on voit qu’une poignée de routes concentre la majorité du temps passé, la suite devient plus claire. On sait si le problème est Apache lui-même, PHP-FPM, la base de données, un reverse proxy, ou simplement une application trop bavarde.

Les logs évitent surtout un piège courant : accuser le serveur web alors que le ralentissement vient d’ailleurs. Apache sert de façade, donc il donne l’impression d’être responsable. En réalité, il est souvent seulement l’endroit où la lenteur devient visible.

Adopter une méthode pragmatique au lieu d’optimiser au hasard

Quand un serveur Apache devient lent, il vaut mieux avancer dans un ordre simple. D’abord mesurer : charge système, mémoire, nombre de workers occupés, temps de réponse, volume de connexions. Ensuite identifier le goulot réel. Puis changer un paramètre à la fois et vérifier l’effet. Cette discipline paraît un peu lente, mais elle fait gagner du temps, justement parce qu’elle évite les faux remèdes.

Une bonne séquence consiste souvent à vérifier d’abord le MPM, ensuite KeepAlive, puis la liste des modules, la compression, et enfin les logs applicatifs ou proxy si rien n’explique encore les symptômes. À chaque étape, il faut noter l’état initial, le changement appliqué et le résultat observé. C’est basique, mais c’est ce qui permet de revenir en arrière proprement si le réglage aggrave la situation.

Le vrai objectif n’est pas d’obtenir une configuration “parfaite” sur le papier. C’est d’avoir un Apache cohérent avec le trafic réel, la machine réelle et l’application réelle. Entre un serveur vitrine, un WordPress chargé en plugins, une API sous reverse proxy ou un intranet peu fréquenté, les priorités ne sont pas les mêmes. Les premiers réglages à regarder sont toujours ceux qui bloquent la capacité immédiate du serveur à répondre sans attendre inutilement.

À quoi sert PAM sous Linux et pourquoi on en entend si souvent parler ?

Quand on administre une machine Linux ou Unix, on croise vite le mot PAM sans toujours comprendre ce qu’il fait réellement. Pourtant, il est là dans des moments très concrets: une connexion SSH, un changement de mot de passe, une ouverture de session locale, parfois même un accès à sudo. PAM, pour Pluggable Authentication Modules, n’est pas un service de plus qu’on lance en arrière-plan. C’est plutôt une couche d’intermédiaire, un cadre commun qui permet aux applications de déléguer l’authentification, la gestion de compte ou des règles de session sans réinventer le sujet à chaque fois.

Dit autrement, PAM évite qu’OpenSSH, login, su, sudo ou un gestionnaire d’affichage aient chacun leur propre logique maison pour vérifier qui a le droit d’entrer. Ce principe paraît discret, mais il simplifie énormément l’administration d’un système et rend les politiques de sécurité plus cohérentes d’un service à l’autre.

Pourquoi PAM existe-t-il au juste ?

# exemple courant: pile PAM pour sshd
cat /etc/pam.d/sshd

# tester un service lié à l'authentification
sudo pam-auth-update

Avant PAM, chaque programme pouvait embarquer sa propre façon d’authentifier un utilisateur. C’était pénible à maintenir, difficile à harmoniser et source d’écarts de sécurité. Avec PAM, les développeurs d’applications n’ont plus besoin de coder eux-mêmes toutes les variantes possibles de l’authentification. Ils appellent une interface standard, puis le système décide quels modules appliquer.

C’est ce qui permet, par exemple, de demander un mot de passe classique sur une machine, d’imposer des règles supplémentaires sur une autre, ou encore d’intégrer une authentification centralisée via LDAP, Kerberos ou un second facteur, sans remplacer tous les services un par un. On adapte la politique, pas toute l’architecture.

Si vous vous intéressez plus largement aux mécanismes de sécurité sous Unix, vous pouvez aussi jeter un œil à cet article sur la gestion des accès et des droits, qui complète bien la logique de PAM dans un environnement multi-utilisateur.

Comment PAM s’insère-t-il entre les services et l’authentification ?

Le point clé, c’est que PAM se place entre l’application et la méthode d’authentification. Un service comme SSH ne va pas directement lire /etc/shadow et décider seul du résultat. Il appelle PAM. Ensuite, PAM consulte sa configuration et exécute les modules prévus pour ce service.

En pratique, la chaîne ressemble souvent à ceci: un utilisateur tente de se connecter, le service transmet la demande à PAM, PAM applique une pile de modules, puis renvoie une réponse au service. Cette réponse peut être “oui”, “non”, ou parfois “oui, mais avec des conditions” comme des restrictions horaires, un mot de passe expiré ou l’ouverture d’une session avec certains montages et variables d’environnement.

Les fichiers de configuration se trouvent généralement dans /etc/pam.d/. Chaque service y possède souvent son propre fichier, par exemple sshd, sudo ou login. On y voit des types comme auth, account, password et session. Ce découpage est très utile:

  • auth vérifie l’identité de l’utilisateur
  • account contrôle si le compte est autorisé à accéder au service
  • password gère le changement de mot de passe
  • session prépare et ferme le contexte de session

Ce fonctionnement modulaire explique pourquoi PAM est si présent dans l’écosystème Unix: il sert de point d’assemblage entre les services et les règles de sécurité réelles.

Quels sont les cas d’usage les plus courants ?

# extrait typique d'une règle PAM
auth    required    pam_unix.so
account required    pam_unix.so
session required    pam_limits.so

Le cas le plus évident reste l’authentification par mot de passe local, mais PAM va beaucoup plus loin. Il peut refuser une connexion si le compte est verrouillé, limiter l’accès à certains groupes, empêcher un mot de passe trop faible, exécuter un montage automatique à l’ouverture de session ou afficher un message légal avant connexion.

Dans une entreprise, PAM est souvent impliqué lorsqu’on relie des machines Linux à un annuaire central. L’utilisateur garde une expérience relativement uniforme, tandis que l’équipe système applique une politique commune. Sur un poste autonome, PAM peut aussi servir à durcir sudo, imposer des règles de complexité de mot de passe ou journaliser plus finement certaines ouvertures de session.

Pour replacer cela dans l’administration quotidienne, on peut faire le lien avec cette ressource sur les bases de l’authentification sous Linux, utile pour comprendre où PAM intervient et où il laisse la main aux autres composants du système.

Quelles précautions prendre avant de modifier sa configuration PAM ?

C’est le point où il faut rester calme. PAM est puissant, mais une mauvaise ligne peut vous bloquer hors de la machine, surtout si vous modifiez l’authentification distante sur un serveur que vous administrez en SSH. Le vrai risque n’est pas seulement de casser une connexion, c’est de casser toutes les suivantes.

La première précaution consiste à garder une session root déjà ouverte avant tout changement. Ainsi, si la nouvelle configuration empêche les connexions normales, vous avez encore une porte de sortie. La deuxième est de sauvegarder les fichiers PAM concernés avant édition. La troisième, souvent négligée, est de tester petit à petit au lieu de réécrire tout un empilement de modules d’un coup.

Il vaut aussi mieux comprendre les indicateurs de contrôle comme required, requisite, sufficient et optional. Ils changent complètement le comportement de la pile. Un module correct au mauvais endroit, avec le mauvais drapeau, peut produire un résultat très différent de celui attendu.

Sur une machine sensible, le bon réflexe est simple: documenter chaque changement, tester depuis une seconde session, prévoir un retour arrière rapide et éviter les modifications “à chaud” sans filet. PAM n’est pas compliqué parce qu’il serait obscur par nature. Il devient délicat parce qu’il est placé exactement à l’endroit où une erreur coupe l’accès.

Une fois qu’on l’a compris comme une couche d’orchestration entre services, comptes et politiques de sécurité, PAM devient beaucoup moins intimidant. On voit mieux pourquoi il est partout, pourquoi il reste central sur les systèmes Unix modernes, et pourquoi les administrateurs le manipulent avec autant de respect.

Pourquoi Git worktree change la vie quand vous jonglez avec plusieurs branches ?

Pendant longtemps, beaucoup de développeurs utilisent Git de la même manière. Un dépôt, un dossier, une branche active à la fois. On change de branche, on stash, on revient, on oublie parfois ce qu’on avait laissé derrière. Ça marche, jusqu’au jour où le rythme se complique. Une feature en cours, un correctif urgent à sortir, une revue à reprendre après déjeuner, et tout à coup votre répertoire devient une salle d’attente pleine.

C’est là que git worktree commence à faire sens. L’idée est presque décevante de simplicité. Au lieu de faire vivre toutes vos branches dans le même dossier de travail, Git vous autorise à attacher plusieurs répertoires au même dépôt. Chaque répertoire peut pointer vers sa propre branche. Vous n’avez plus besoin de démonter votre contexte chaque fois qu’un autre sujet arrive.

Pourquoi changer de branche dans le même dossier finit par fatiguer

Le problème n’est pas seulement technique. Il est mental. Quand vous changez souvent de branche dans un même répertoire, vous devez sans arrêt vérifier l’état des fichiers, penser à stash ce qui traîne, vous rappeler sur quoi vous étiez, puis restaurer le bon contexte plus tard. Sur le papier, Git sait gérer. Dans la vraie vie, ça use l’attention.

Avec un worktree, vous gardez un dossier par sujet actif. Votre branche de correctif peut vivre dans un répertoire propre, votre feature dans un autre, votre branche de revue dans un troisième. Vous ouvrez simplement le bon dossier et vous retrouvez tout de suite le bon état mental. C’est bête à dire, mais ce confort change vraiment la fluidité de la journée.

Les cas où worktree devient immédiatement utile

Le premier cas, c’est l’urgence. Vous êtes en plein milieu d’un développement et on vous demande de corriger un bug en production. Sans worktree, vous commencez à jongler avec vos changements locaux. Avec worktree, vous créez un nouveau dossier lié à une branche de correctif, vous traitez le problème, puis vous revenez à votre travail initial sans avoir tout déplacé entre-temps.

Le deuxième cas, c’est la revue. Vous voulez tester une branche d’un collègue sans salir votre espace courant. Un worktree dédié règle le problème proprement. Le troisième cas, c’est le multi sujet classique d’une semaine normale, où plusieurs branches avancent en parallèle et où vous en avez assez de perdre le fil.

Dans ce type d’organisation, bien comprendre aussi la différence entre git fetch et git pull reste très utile, parce que chaque worktree continue à vivre avec ses remotes et ses mises à jour. Le confort vient du découpage des répertoires, pas d’une disparition magique des bonnes pratiques.

Ce que worktree ne fait pas à votre place

Il faut être honnête. git worktree ne remplace pas une méthode de travail. Si vos branches sont floues, elles resteront floues. Si vous ouvrez des sujets trop gros, vous aurez toujours des revues pénibles et des merges pénibles. Worktree enlève surtout la friction liée au changement de contexte.

Il ne faut pas non plus le voir comme un gadget réservé aux experts Git. La commande est plus simple qu’elle n’en a l’air. Une fois qu’on a créé deux ou trois worktrees, on comprend très vite le principe. Le plus dur, finalement, c’est souvent d’accepter qu’on peut arrêter de tout faire dans un seul dossier par habitude.

Pourquoi cette commande reste sous utilisée

Je pense qu’elle reste discrète pour une raison simple. Beaucoup de développeurs survivent très bien sans elle pendant des années. Donc ils ne vont pas spontanément chercher mieux. Ils ont appris à stasher, à changer de branche, à revenir en arrière, à recoller les morceaux. Ils se sont adaptés à la friction au lieu de la supprimer.

Pourtant, dès qu’on touche à des contributions parallèles ou à des remotes multiples, on sent vite l’intérêt. Si vous passez aussi par un dépôt personnel pour contribuer ou tester vos changements, vous croiserez tôt ou tard des situations où un fork Git est plus pratique qu’un simple clone. Là encore, worktree ne remplace pas le fork, mais il se combine très bien avec lui pour garder plusieurs contextes ouverts sans désordre.

Le déclic arrive souvent la première semaine d’usage. On ne gagne pas seulement quelques commandes. On récupère surtout une manière plus calme de passer d’un sujet à l’autre. Et quand un outil vous rend ce calme là, vous commencez vite à vous demander pourquoi vous avez attendu si longtemps avant de l’adopter.

Comment organiser une revue de code avec Git sans ralentir l équipe ?

Dès qu’on parle de revue de code, il y a deux excès qui arrivent vite. Le premier, c’est l’absence totale de cadre. Chacun pousse sur la branche principale et on espère que tout ira bien. Le second, c’est l’usine à gaz où chaque petit changement attend trois validations, deux cérémonies et une lune favorable. Entre les deux, il existe une façon très simple de travailler avec Git sans transformer la revue en punition.

Le point le plus important à comprendre, c’est que la revue n’a pas vocation à bloquer chaque geste du développeur. Elle intervient avant l’intégration dans la branche partagée, pas avant chaque sauvegarde de code ni avant chaque commit local. Cette précision change déjà beaucoup de malentendus.

La bonne unité de revue, ce n’est pas le commit isolé

Un commit peut être utile pour raconter l’avancée du travail, mais il n’est pas toujours la meilleure unité pour demander un avis. Ce qu’on relit vraiment, c’est un ensemble cohérent de modifications liées à un besoin, un bug ou une fonctionnalité. D’où l’intérêt de travailler sur une branche dédiée, puis d’ouvrir une pull request quand le sujet commence à ressembler à quelque chose de lisible.

Ça paraît banal, mais ça évite beaucoup de discussions stériles. Si vous demandez une revue sur un paquet de changements clair, avec un objectif compréhensible, les retours deviennent meilleurs. Si vous demandez une revue sur un amas de commits mal regroupés, même un bon collègue aura du mal à vous aider.

Une branche courte vaut mieux qu’une branche héroïque

Le vrai ennemi d’une revue fluide, ce n’est pas Git. C’est la branche qui reste ouverte trois semaines et accumule tout. À la fin, personne n’a envie de relire huit cents lignes touchant à la fois au backend, au CSS, à la config et aux tests. La revue devient lourde, donc elle traîne, donc elle agace, donc on cherche à la contourner.

Mieux vaut ouvrir des branches plus courtes, plus nettes, plus fréquentes. Une petite pull request reçoit plus vite un vrai retour. Elle se fusionne plus facilement. Elle produit aussi moins de conflits quand la branche principale bouge entre-temps.

Si votre équipe se mélange un peu dans les mises à jour distantes, ça vaut le coup de clarifier aussi ce qui change vraiment entre git fetch et git pull. Une revue se passe mieux quand chacun sait remettre sa branche à jour sans créer du bruit inutile.

Ce qu’on attend vraiment d’une revue utile

Une bonne revue ne sert pas à jouer au professeur sévère. Elle sert à repérer ce que l’auteur ne voit plus, à vérifier l’intention et à partager un peu de contexte. Ça peut être un bug potentiel, une convention oubliée, un nom trompeur, une complexité évitable, ou simplement une question honnête sur le choix technique.

Le ton compte énormément. Une remarque agressive transforme très vite la revue en sport de défense. Une remarque précise et calme aide tout le monde. Dire « je ne comprends pas cette condition, tu peux expliquer le cas métier ? » est souvent plus utile que lâcher un verdict sec sur la qualité du code.

On oublie aussi que la revue a une valeur collective. Elle diffuse les habitudes du projet. Elle montre comment les autres résolvent un problème. Avec le temps, elle évite que la connaissance reste coincée dans la tête de deux personnes.

Le fork, les droits et le bon niveau d’isolation

Selon le contexte, la revue peut se faire dans le dépôt principal ou à travers un fork. Dans une équipe interne, un simple workflow par branches suffit souvent. Sur des contributions externes, ou quand vous voulez isoler proprement le travail avant de le proposer, le fork rend la mécanique plus propre.

Si ce sujet vous parle, j’ai détaillé ici quand il vaut mieux utiliser un fork Git plutôt qu’un simple clone. Le choix du workflow influe directement sur la façon dont la revue se passe et sur le confort des personnes qui contribuent.

Le meilleur cadre, au fond, n’est pas le plus rigide. C’est celui qui rend la revue normale. Ouvrir une branche claire, écrire une demande relisible, répondre vite aux remarques utiles, fusionner sans drame et passer au sujet suivant. Quand une équipe arrive à ce rythme, Git cesse d’être un gardien et redevient ce qu’il aurait toujours dû rester, un outil de coordination assez simple pour laisser la place au vrai travail.

Quand faut il utiliser un fork Git plutôt qu un simple clone ?

Le fork a longtemps eu une réputation un peu intimidante. On l’associe aux gros projets open source, aux pull requests publiques, à des workflows qui semblent réservés aux équipes bien rodées. Pourtant, l’idée est beaucoup plus simple que ça. Un fork, c’est une copie du dépôt sur votre propre espace distant. Un clone, lui, c’est juste une copie locale sur votre machine. Les deux servent à travailler. Ils ne servent pas à travailler dans la même relation avec le projet d’origine.

Quand on comprend cette nuance, on arrête de choisir entre fork et clone par imitation. On choisit selon le niveau d’autonomie qu’on veut garder et selon la façon dont on compte proposer ses modifications.

Le clone suffit très souvent

Si vous travaillez dans votre propre dépôt, ou dans celui de votre équipe avec les bons droits d’écriture, un clone suffit largement. Vous récupérez le projet sur votre machine, vous créez des branches, vous poussez vos changements et la journée continue. Pas besoin d’ajouter une couche de complexité pour le plaisir.

Le clone est aussi idéal quand la relation est directe. Vous appartenez à l’organisation, vous avez le droit de pousser, et la revue de code passe par des branches internes. Dans ce cas, multiplier les remotes avec un fork ne vous apporte pas grand-chose.

Ce qui compte ici, c’est de ne pas transformer Git en rituel. Si un clone répond au besoin, gardez le clone.

Le fork devient intéressant quand vous voulez une vraie zone à vous

Le fork prend tout son sens quand vous n’avez pas de droits d’écriture sur le dépôt source, ou quand vous préférez isoler votre travail sur votre propre dépôt distant. C’est le cas le plus connu dans l’open source. Vous créez votre fork sur GitHub ou GitLab, vous clonez ce fork sur votre machine, puis vous proposez vos changements au projet d’origine avec une pull request.

Cette approche a un autre avantage, moins spectaculaire mais très pratique. Votre fork vous appartient. Vous pouvez y pousser des branches de test, y garder des expérimentations, y faire le ménage à votre rythme sans salir le dépôt principal. C’est une vraie zone tampon.

Quand on découvre les bases de synchronisation distante, il vaut aussi la peine de bien distinguer ce que fait git fetch et ce que fait git pull. Si le sujet vous a déjà créé des surprises, vous pouvez lire aussi la différence entre git pull et git fetch. Dans un workflow avec fork, cette différence devient vite concrète.

Le rôle du remote upstream que beaucoup oublient

Le piège classique avec un fork, c’est de croire qu’une fois la copie créée, tout va se synchroniser magiquement. En réalité, votre fork peut vieillir très vite si le projet d’origine bouge tous les jours. C’est pour ça qu’on ajoute souvent un remote upstream qui pointe vers le dépôt source.

À partir de là, le schéma devient simple. origin désigne votre fork. upstream désigne le projet d’origine. Vous pouvez alors faire un git fetch upstream, récupérer les nouveautés du dépôt principal, puis remettre votre branche locale à niveau avant de pousser vers votre propre fork.

Dit autrement, le fork ne remplace pas la discipline Git. Il ajoute un étage de séparation entre votre espace et l’espace du projet principal. C’est utile, mais ça suppose de comprendre qui parle à qui.

Le fork et la revue de code vont très bien ensemble

Le fork est aussi confortable quand vous voulez proposer une contribution proprement empaquetée. Vous travaillez chez vous, vous poussez sur votre fork, puis vous ouvrez une demande de fusion. Le dépôt principal reste calme jusqu’au moment où quelqu’un décide d’intégrer votre travail. Cette logique est saine, surtout sur des projets où la qualité compte vraiment.

Si vous cherchez à mettre un peu de méthode dans les validations sans transformer l’équipe en administration, j’ai aussi détaillé comment organiser une revue de code avec Git sans ralentir l’équipe. Le fork n’est pas obligatoire pour relire du code, mais il se marie très bien avec une logique d’approbation claire.

Ce qui aide le plus, au fond, c’est de poser une question très simple avant de commencer. Est-ce que je travaille directement dans le dépôt principal, ou est-ce que j’ai intérêt à garder mon propre espace distant entre le projet et moi ? Si la réponse est la deuxième, le fork devient une évidence. Sinon, le clone fera très bien le travail, sans posture et sans bruit.

Git pull ou git fetch, quelle différence change vraiment votre façon de travailler ?

On voit souvent ces deux commandes comme des cousines tellement proches qu’on finit par les confondre. Dans les faits, elles n’ont pas le même effet psychologique sur votre journée. git fetch vous montre ce qui a bougé sans toucher à votre branche courante. git pull ramène les changements et essaye tout de suite de les intégrer. Dit comme ça, la différence a l’air minime. En réalité, elle change votre niveau de contrôle.

Le problème, ce n’est pas la syntaxe. Le problème, c’est le moment où vous découvrez qu’un collègue a poussé quelque chose qui entre en collision avec ce que vous faisiez depuis deux heures. Si vous utilisez Git tous les jours, ce détail finit par compter plus que la définition officielle.

Pourquoi ces deux commandes sont si souvent mélangées

La confusion vient d’un raccourci très humain. On veut simplement récupérer la dernière version du dépôt. Comme les deux commandes parlent au serveur et ramènent des nouveautés, beaucoup de développeurs se disent qu’elles font la même chose avec un emballage différent. Ce n’est pas faux, mais ce n’est pas suffisant pour travailler proprement.

Avec git fetch, Git met à jour vos références distantes. En clair, il télécharge l’état récent de origin/main, origin/dev ou d’autres branches distantes, mais il ne mélange rien dans votre branche locale. Vous pouvez regarder, comparer, respirer et décider.

Avec git pull, Git fait d’abord ce téléchargement, puis enchaîne avec une intégration. Selon votre configuration, ce sera souvent un merge, parfois un rebase. C’est pratique quand vous savez exactement ce que vous attendez. C’est moins confortable quand vous préférez inspecter avant de laisser Git toucher à votre branche.

Pourquoi git fetch est souvent le meilleur réflexe

J’aime bien git fetch pour une raison simple. Il n’impose rien. Il me laisse voir le delta avant de le subir. Après un fetch, je peux lancer un git log HEAD..origin/main, un git diff main origin/main ou juste vérifier si la branche distante a avancé plus que prévu.

Cette petite étape évite beaucoup de friction. Quand on travaille sur un dépôt un peu vivant, avec plusieurs merges dans la journée, faire un fetch revient à jeter un coup d’oeil avant d’ouvrir la porte. Vous savez si la maison est calme ou si quelqu’un a déplacé tous les meubles.

Si vous travaillez aussi avec des forks, cette habitude devient encore plus utile. Le jour où vous devez resynchroniser votre copie avec le dépôt d’origine, le mécanisme est le même. J’en parle plus en détail ici : quand utiliser un fork Git plutôt qu’un simple clone. Comprendre fetch dans ce contexte évite de bricoler à l’aveugle avec un remote upstream.

Quand git pull reste le bon outil

Il ne faut pas diaboliser git pull. Quand vous êtes sur une branche locale très simple, que vous savez qu’elle suit une branche distante précise et que vous voulez juste vous remettre à jour rapidement, c’est efficace. Beaucoup de gens commencent leur journée avec un pull sur main et ça se passe très bien.

Le vrai piège apparaît quand on lance git pull comme un réflexe nerveux au milieu d’un travail en cours. C’est là qu’on se retrouve avec un merge surprise, un conflit qu’on n’avait pas anticipé, ou pire, une branche locale modifiée qu’on comprend de moins en moins. Le souci n’est pas la commande. Le souci, c’est le manque de contexte au moment où on l’exécute.

Si votre équipe alterne entre plusieurs tâches, correctifs et revues, le besoin de contrôle devient encore plus visible. Dans ce cas, travailler avec des répertoires séparés peut faire gagner un temps fou. C’est exactement là que Git worktree devient très pratique quand une branche ne suffit plus, parce qu’on évite les allers-retours brouillons entre des états locaux différents.

Une routine simple pour ne plus subir

Une routine saine peut rester très légère. Sur une branche importante, commencez par un fetch. Regardez ce qui a changé. Si tout est propre et que vous voulez intégrer, choisissez ensuite votre geste, merge ou rebase selon vos habitudes. Cette séquence prend à peine plus de temps qu’un pull direct, mais elle vous rend beaucoup plus lucide.

Pour une branche personnelle courte, un pull peut suffire. Pour une branche exposée, surtout si d’autres personnes poussent régulièrement, fetch puis inspection reste souvent la voie la plus calme. Vous n’avez pas besoin d’un cérémonial compliqué. Vous avez juste besoin d’une pause de cinq secondes avant de demander à Git de combiner des histoires qui n’ont peut-être pas avancé au même rythme.

Au fond, git fetch répond à la question « qu’est-ce qui a changé là-bas ? ». git pull répond à « mets-moi à jour maintenant ». Quand on formule les choses comme ça, on choisit beaucoup mieux. Et dès qu’on choisit mieux, Git paraît soudain beaucoup moins capricieux.

Mettre en place le wake on LAN sur votre ordinateur PC

Le Wake On LAN qu’est ce que c’est?

C’est la possibilité d’allumer son ordinateur sans pousser le bouton, de façon distante.

Le prérequis est que votre ordinateur soit compatible, en gros avoir une carte Ethernet qui reste allumée même si l’ordinateur est éteint, c’est la partie difficile du réglage. Il faut toucher au BIOS et aux paramétrages de Windows.

Réglage dans le BIOS

Moi j’ai une carte mère B760M GAMING PLUS WIFI (MS-7D99) 3.0.

SETTINGS
└── Advanced
    └── Power Management Setup
        └── ErP Ready = Disabled

ErP Ready est le réglage important: lorsqu’il est activé, la carte mère coupe l’alimentation de la carte Ethernet à l’arrêt.

ensuite :

SETTINGS
└── Advanced
    └── Wake Up Event Setup
        ├── Wake Up Event By = BIOS
        └── Resume By PCI-E/Networking Device = Enabled

Sauvegarder les réglages.Parfois il faut taper sur la touche F10 et indiquer « Yes » pour quitter et sauvegarder les paramétrages.

Manipulation à faire dans Windows

Du côté de Windows il y a beaucoup plus de paramètres à faire.

Il faut désactiver le démarrage rapide.

Panneau de configuration
→ Matériel et audio
→ Options d’alimentation
→ Choisir l’action des boutons d’alimentation
→ Modifier des paramètres actuellement non disponibles
→ décocher « Activer le démarrage rapide »

Ensuite il faut ouvrir le gestionnaire de périphériques pour tweaker les propriétés de la carte Ethernet.Moi j’ai une Realtek.

Donc, aller dans gestionnaire de périphériques, puis carte réseau, sélectionner la carte et aller dans les propriétés.

Allez dans l’onglet avancé.Vous devriez voir, (je suis sur Windows 11) :

  • Wake on Magic Packet
  • Shutdown Wake-On-Lan
  • Wake From Shutdown

Désactiver :

  • Energy Efficient Ethernet
  • green Ethernet

Dans la gestion de l’alimentation à faire, même si vous n’êtes pas sur un PC portable,il faut cocher :

  • Autoriser ce périphérique à sortir l’ordinateur du mode veille
  • Autoriser uniquement un paquet magique à sortir l’ordinateur du mode veille

Ensuite on redémarre Windows complètement une fois.

Désactiver le démarrage rapide

shutdown /s /f /t 0

Quand c’est éteint, regardez les voyants de la prise Ethernet.Si les voyants sont allumés ou clignotants, la carte réseau reste alimentée. Le WAKE on LAN devrait fonctionner. Si c’est éteint, il faut retourner dans le bios vérifier ErP Ready = Disabled

Les deux réglages sur la carte MSI sont

ErP Ready                         = Disabled
Resume By PCI-E/Networking Device = Enabled

Comment envoyer le paquet magique?

Depuis Android

Installer une application comme Wake On LAN. Il vous faut connaître l’adresse MAC de votre carte Ethernet.(pas celle du WIFI)

Get-NetAdapter |
  Format-Table Name, InterfaceDescription, MacAddress, Status

Depuis un autre PC Windows du réseau LAN :

Dans PowerShell il faut d’abord installer un module.

Get-NetAdapter |
  Format-Table Name, InterfaceDescription, MacAddress, Status

Puis envoyez le paquet magique.

Send-WOL -mac "AA-BB-CC-DD-EE-FF" << remplacer par l'adresse MAC

Si la commande n’existe pas après installation :

Import-Module WakeOnLan
Get-Command -Module WakeOnLan

Depuis Linux ou WSL

Installer wakeonlan :

sudo apt update
sudo apt install wakeonlan

puis 
wakeonlan AA:BB:CC:DD:EE:FF  << remarquez un différent séparateur

Gestionnaire de paquet Python 4/4

python -m pip download package -d downloads/

Télécharger uniquement une wheel :

python -m pip download --only-binary=:all: package -d downloads/

Afficher les informations :

python -m pip index versions package

Installer avec davantage de détails :

python -m pip install -vvv package

68. Hashes

Un fichier de dépendances peut inclure des hashes :

requests==2.32.3 \
    --hash=sha256:...

Installation stricte :

python -m pip install --require-hashes -r requirements.txt

Cela permet de vérifier que les fichiers téléchargés correspondent exactement aux artefacts attendus.

Partie 20 — Workflow professionnel recommandé

69. Workflow minimal avec venv et pip

Windows

mkdir mon-projet
cd mon-projet

py -3.12 -m venv .venv
.venv\Scripts\Activate.ps1

python -m pip install --upgrade pip
python -m pip install fastapi uvicorn

python -m pip freeze > requirements.txt

Pour recréer :

py -3.12 -m venv .venv
.venv\Scripts\Activate.ps1
python -m pip install -r requirements.txt

70. Workflow recommandé avec uv

uv init mon-projet
cd mon-projet

uv python pin 3.12
uv add fastapi uvicorn
uv add --dev pytest ruff

uv run pytest
uv run uvicorn main:app --reload

Fichiers à versionner :

pyproject.toml
uv.lock
.python-version
src/
tests/

À ignorer :

.venv/
__pycache__/
.pytest_cache/
.ruff_cache/

71. Exemple de projet complet

mon-api/
├── .gitignore
├── .python-version
├── pyproject.toml
├── uv.lock
├── src/
│   └── mon_api/
│       ├── __init__.py
│       └── main.py
└── tests/
    └── test_main.py

pyproject.toml :

[project]
name = "mon-api"
version = "0.1.0"
requires-python = ">=3.12,<3.13"

dependencies = [
    "fastapi>=0.115,<1",
    "uvicorn[standard]>=0.34,<1",
]

[dependency-groups]
dev = [
    "pytest>=8,<9",
    "ruff>=0.12,<1",
]

Commandes :

uv sync
uv run uvicorn mon_api.main:app --reload
uv run pytest
uv run ruff check .

Partie 21 — Procédure universelle de diagnostic

72. Étape 1 : identifier le Python

python --version
python -c "import sys; print(sys.executable)"

Sous Windows :

py --list
where python

Sous Linux :

type -a python
type -a python3

73. Étape 2 : identifier pip

python -m pip --version

Comparer son chemin avec :

python -c "import sys; print(sys.executable)"

74. Étape 3 : identifier l’environnement

python -c "import sys; print('prefix:', sys.prefix); print('base:', sys.base_prefix); print('venv:', sys.prefix != sys.base_prefix)"

75. Étape 4 : vérifier la compatibilité

python -m pip index versions nom-du-paquet
python -m pip install -vvv nom-du-paquet

Lire notamment :

  • Requires-Python ;
  • les versions candidates ignorées ;
  • les wheels rejetées ;
  • les conflits de dépendances.

76. Étape 5 : tester la disponibilité d’une wheel

python -m pip install --only-binary=:all: nom-du-paquet

Si cela échoue mais que l’installation normale tente de compiler, aucune wheel compatible n’est probablement disponible.

77. Étape 6 : inspecter les tags

python -m pip debug --verbose

Comparer avec le fichier téléchargé :

cp312-cp312-win_amd64

78. Étape 7 : repartir proprement

deactivate

Supprimer .venv, puis :

python-version-voulue -m venv .venv

Réinstaller depuis le fichier de dépendances.

Partie 22 — Les règles à retenir

79. Les dix règles essentielles

Règle 1

Un environnement virtuel ne télécharge pas automatiquement une autre version de Python.

Il utilise le Python qui le crée.

Règle 2

Toujours préférer :

python -m pip

à :

pip

Règle 3

Un environnement virtuel par projet.

Règle 4

Ne pas installer les dépendances de projet dans le Python global.

Règle 5

Ne pas utiliser sudo pip install.

Règle 6

Une wheel doit correspondre :

  • à l’implémentation Python ;
  • à la version Python ;
  • à l’ABI ;
  • au système ;
  • à l’architecture.

Règle 7

Une compilation déclenchée par pip signifie souvent qu’aucune wheel compatible n’a été trouvée.

Règle 8

Ne pas copier .venv entre machines.

Le recréer à partir des métadonnées.

Règle 9

Versionner :

pyproject.toml
fichier de lock
.python-version

mais pas :

.venv

Règle 10

Pour un nouveau projet, uv constitue aujourd’hui une solution très cohérente pour gérer simultanément Python, les environnements, les dépendances et le verrouillage.

Partie 23 — Arbre de décision rapide

Je veux commencer un projet

Ai-je une version Python imposée ?
│
├── Oui
│   └── Installer ou sélectionner cette version
│
└── Non
    └── Choisir une version stable supportée par les bibliothèques

Puis :

Projet moderne ?
│
├── Oui → uv + pyproject.toml + uv.lock
│
└── Non → venv + pip + requirements.txt

Une installation échoue

L’erreur parle de Requires-Python ?
│
├── Oui → mauvaise version de Python
│
└── Non
    │
    ├── ResolutionImpossible ?
    │   └── conflit de versions
    │
    ├── Failed building wheel ?
    │   └── compilation native ou absence de wheel
    │
    ├── unsupported wheel ?
    │   └── mauvais Python, OS ou architecture
    │
    └── ModuleNotFoundError après installation ?
        └── pip et python ne visent pas le même environnement

Commande de diagnostic finale

Sous Windows PowerShell :

Write-Host "=== Python ==="
python --version
python -c "import sys, platform; print('Executable:', sys.executable); print('Prefix:', sys.prefix); print('Base prefix:', sys.base_prefix); print('Virtual env:', sys.prefix != sys.base_prefix); print('Implementation:', platform.python_implementation()); print('Machine:', platform.machine())"

Write-Host "`n=== pip ==="
python -m pip --version

Write-Host "`n=== Paths ==="
where.exe python
where.exe pip

Write-Host "`n=== Packages ==="
python -m pip list

Sous Linux ou macOS :

echo "=== Python ==="
python --version
python -c "import sys, platform; print('Executable:', sys.executable); print('Prefix:', sys.prefix); print('Base prefix:', sys.base_prefix); print('Virtual env:', sys.prefix != sys.base_prefix); print('Implementation:', platform.python_implementation()); print('Machine:', platform.machine())"

echo
echo "=== pip ==="
python -m pip --version

echo
echo "=== Paths ==="
type -a python
type -a pip

echo
echo "=== Packages ==="
python -m pip list

La sortie de ces commandes permet de résoudre la majorité des problèmes de gestion de paquets Python.

Gestionnaire de paquet Python 3/4

Partie 10 — pyproject.toml

38. Le fichier central des projets modernes

Exemple :

[project]
name = "mon-projet"
version = "0.1.0"
description = "Exemple"
requires-python = ">=3.12,<3.13"

dependencies = [
    "fastapi>=0.115,<1",
    "sqlalchemy>=2,<3",
    "psycopg[binary]>=3.2,<4",
]

[project.optional-dependencies]
dev = [
    "pytest>=8",
    "ruff>=0.12",
    "mypy>=1.16",
]

Installation du projet :

python -m pip install .

Installation en mode éditable :

python -m pip install -e .

Avec les dépendances de développement :

python -m pip install -e ".[dev]"

39. Mode éditable

Avec :

python -m pip install -e .

le projet local est installé de manière à ce que les changements de code soient immédiatement visibles sans réinstallation complète.

C’est le mode habituel pour développer une bibliothèque ou une application structurée comme un paquet Python.

40. Build backend

Exemple utilisant setuptools :

[build-system]
requires = ["setuptools>=75", "wheel"]
build-backend = "setuptools.build_meta"

Exemple avec Hatchling :

[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

Exemple avec uv_build :

[build-system]
requires = ["uv_build"]
build-backend = "uv_build"

Le backend est l’outil chargé de construire la distribution du projet.

Partie 11 — Installer plusieurs versions de Python

41. Sous Windows : utiliser le lanceur py

Lister les versions :

py --list

Créer un environnement en Python 3.11 :

py -3.11 -m venv .venv

Créer un environnement en Python 3.12 :

py -3.12 -m venv .venv

Exécuter un script avec une version précise :

py -3.11 script.py

Installer un paquet dans le Python global 3.12 :

py -3.12 -m pip install package

Mais pour un projet, on préférera :

py -3.12 -m venv .venv
.venv\Scripts\Activate.ps1
python -m pip install package

42. Sous Linux : ne pas remplacer le Python système

Éviter de modifier manuellement :

/usr/bin/python3

Éviter également de supprimer le Python installé par la distribution.

Les outils système peuvent dépendre d’une version précise.

Approches recommandées :

  • paquets officiels de la distribution ;
  • pyenv ;
  • uv ;
  • conteneurs Docker ;
  • compilation dans /opt ou dans le dossier utilisateur ;
  • environnements virtuels.

43. pyenv

pyenv permet de gérer plusieurs interpréteurs Python.

Commandes typiques :

pyenv install 3.11.11
pyenv install 3.12.10
pyenv versions
pyenv local 3.12.10

Le fichier :

.python-version

peut contenir :

3.12.10

pyenv sélectionne alors cette version dans le répertoire du projet.

Important : pyenv choisit l’interpréteur, mais ne gère pas à lui seul toutes les dépendances du projet.

On peut l’associer à venv :

pyenv local 3.12.10
python -m venv .venv

Partie 12 — uv, approche moderne recommandée

44. Qu’est-ce que uv ?

uv est un gestionnaire Python et de projets écrit en Rust. Il peut notamment :

  • installer plusieurs versions de Python ;
  • créer les environnements virtuels ;
  • résoudre les dépendances ;
  • installer les paquets ;
  • créer un fichier de verrouillage ;
  • lancer des commandes ;
  • gérer des outils CLI isolés.

La documentation officielle le présente comme un gestionnaire de paquets et de projets Python rapide.

45. Gérer Python avec uv

Lister les versions :

uv python list

Installer Python 3.12 :

uv python install 3.12

Trouver l’interpréteur :

uv python find 3.12

Fixer la version du projet :

uv python pin 3.12

Cela crée généralement :

.python-version

uv sait installer, lister, trouver, fixer et désinstaller des versions de Python.

46. Créer un projet avec uv

uv init mon-projet
cd mon-projet
uv python pin 3.12
uv add fastapi
uv add sqlalchemy
uv add --dev pytest ruff

Structure possible :

mon-projet/
├── .python-version
├── .venv/
├── pyproject.toml
├── uv.lock
└── src/

Le fichier .python-version indique la version Python par défaut du projet, tandis que .venv contient son environnement isolé.

47. Synchroniser l’environnement

uv sync

Cette commande crée ou met à jour .venv selon :

pyproject.toml
uv.lock

Lancer le projet :

uv run python main.py

Lancer les tests :

uv run pytest

Il n’est pas obligatoire d’activer manuellement .venv.

48. Ajouter et retirer des dépendances

uv add requests
uv add "django>=5,<6"
uv add --dev pytest
uv remove requests

uv met à jour :

  • pyproject.toml ;
  • uv.lock ;
  • l’environnement.

49. Pourquoi uv simplifie le problème

Avec la méthode historique, on doit coordonner :

installation Python
+ venv
+ pip
+ requirements.txt
+ éventuellement pip-tools
+ éventuellement pipx

Avec uv, on peut coordonner :

version Python
+ environnement
+ dépendances
+ lockfile
+ commandes

Workflow recommandé :

uv init
uv python pin 3.12
uv add fastapi
uv add --dev pytest
uv run pytest

Partie 13 — pipx et outils en ligne de commande

50. Pourquoi ne pas installer les CLI globalement ?

Des outils comme :

  • black ;
  • ruff ;
  • poetry ;
  • httpie ;
  • cookiecutter ;
  • ansible ;

sont des applications Python, pas forcément des dépendances d’un projet.

Les installer globalement peut provoquer des conflits.

pipx installe chaque outil dans son propre environnement virtuel tout en exposant sa commande dans le PATH.

Exemple :

pipx install poetry
pipx install httpie
pipx list
pipx upgrade-all

Avec uv :

uv tool install ruff
uv tool install httpie
uvx ruff check .

Chaque outil géré par uv est lié à une version précise de Python et dispose de son environnement isolé.

Partie 14 — Erreurs fréquentes et diagnostic

51. ModuleNotFoundError

Erreur :

ModuleNotFoundError: No module named 'requests'

Vérifications :

python -c "import sys; print(sys.executable)"
python -m pip show requests
python -m pip list

Puis :

python -m pip install requests

Ne pas se contenter de :

pip install requests

car ce pip peut appartenir à un autre Python.

52. pip n’est pas reconnu

Sous Windows :

py -m pip --version

Si cela fonctionne, utiliser :

py -m pip install package

Dans un environnement virtuel :

python -m pip install package

Si pip manque :

python -m ensurepip --upgrade

Puis :

python -m pip install --upgrade pip

53. Mauvaise version de Python

Erreur :

Package requires Python >=3.11

Diagnostic :

python --version
python -c "import sys; print(sys.executable)"

Solution Windows :

py -3.12 -m venv .venv

Solution Linux avec un Python déjà installé :

python3.12 -m venv .venv

Un environnement existant en Python 3.10 ne peut pas être transformé proprement en environnement Python 3.12.

Il faut le recréer.

54. No matching distribution found

Exemple :

ERROR: Could not find a version that satisfies the requirement package
ERROR: No matching distribution found

Causes possibles :

  • nom du paquet incorrect ;
  • version inexistante ;
  • Python trop ancien ;
  • Python trop récent ;
  • architecture non supportée ;
  • absence de wheel et source indisponible ;
  • index privé mal configuré ;
  • préversion ignorée ;
  • paquet retiré ;
  • contraintes incompatibles.

Diagnostic :

python --version
python -m pip index versions package
python -m pip install -vvv package

Pour autoriser une préversion :

python -m pip install --pre package

55. ResolutionImpossible

Lancer :

python -m pip install -vvv -r requirements.txt

Puis rechercher les contraintes contradictoires.

Exemple :

A demande urllib3<2
B demande urllib3>=2

Solutions possibles :

  • mettre à jour A ;
  • mettre à jour B ;
  • rétrograder l’un des paquets ;
  • remplacer une bibliothèque ;
  • utiliser une version de Python plus adaptée ;
  • corriger une contrainte trop stricte.

Éviter de contourner aveuglément avec :

--no-deps

Cette option installe le paquet sans ses dépendances et peut créer un environnement incohérent.

56. Failed building wheel

Diagnostic :

python -m pip install -vvv package

Tester l’existence d’un binaire :

python -m pip install --only-binary=:all: package

Si aucune distribution n’est trouvée, il n’existe probablement pas de wheel compatible.

Choix possibles :

  • installer les outils de compilation ;
  • utiliser une autre version de Python ;
  • utiliser une autre architecture ;
  • attendre une wheel ;
  • utiliser une version antérieure du paquet ;
  • utiliser Conda pour les bibliothèques scientifiques complexes ;
  • construire une wheel sur une machine de build.

57. externally-managed-environment

Sur certaines distributions Linux :

error: externally-managed-environment

Cela signifie que le Python système est administré par le gestionnaire de paquets de la distribution.

Bonne solution :

python3 -m venv .venv
source .venv/bin/activate
python -m pip install package

Pour une application CLI :

pipx install outil

ou :

uv tool install outil

Éviter :

sudo pip install ...

et éviter autant que possible :

--break-system-packages

car cette option autorise précisément la modification risquée de l’environnement système.

58. Le paquet est installé mais VS Code ne le voit pas

VS Code utilise peut-être un autre interpréteur.

Dans VS Code :

Ctrl + Shift + P
Python: Select Interpreter

Choisir :

...\projet\.venv\Scripts\python.exe

ou :

.../projet/.venv/bin/python

Vérification dans le terminal intégré :

python -c "import sys; print(sys.executable)"

Le terminal, le débogueur, les notebooks Jupyter et l’analyseur de code peuvent chacun utiliser un interpréteur différent.

Partie 15 — Jupyter et environnements

59. Le piège des kernels

Un notebook peut afficher un environnement différent du terminal.

Dans une cellule :

import sys
print(sys.executable)

Pour enregistrer l’environnement comme kernel :

python -m pip install ipykernel
python -m ipykernel install --user --name mon-projet --display-name "Python - mon-projet"

Dans Jupyter, sélectionner ensuite :

Python - mon-projet

Pour installer depuis le notebook, préférer :

import sys
!{sys.executable} -m pip install requests

ou, dans les environnements Jupyter compatibles :

%pip install requests

plutôt que :

!pip install requests

qui peut appeler un autre pip.

Partie 16 — Paquets, modules, distributions : trois notions différentes

60. Distribution PyPI versus module importé

Le nom installé et le nom importé peuvent différer.

Exemples :

python -m pip install pillow

Puis :

from PIL import Image

Autre exemple :

python -m pip install beautifulsoup4

Puis :

from bs4 import BeautifulSoup

Autre exemple :

python -m pip install scikit-learn

Puis :

import sklearn

Il faut distinguer :

  • le nom de distribution ;
  • le nom du module ;
  • le nom du paquet Python ;
  • le nom de la commande CLI.

61. Vérifier à quelle distribution appartient un module

python -m pip show pillow

En Python :

import PIL
print(PIL.__file__)

Pour lire les métadonnées :

from importlib.metadata import version

print(version("pillow"))

Partie 17 — Architecture et système d’exploitation

62. Vérifier l’architecture

python -c "import platform; print(platform.machine())"

Sous Windows :

python -c "import struct; print(struct.calcsize('P') * 8)"

Résultat :

64

indique un Python 64 bits.

Il est possible d’avoir :

  • Windows 64 bits ;
  • mais Python 32 bits.

Dans ce cas, seules les wheels win32 seront acceptées, pas les wheels win_amd64.

63. ARM contre x86-64

Architectures courantes :

x86_64
AMD64
aarch64
arm64

Exemples :

  • PC Intel/AMD Windows : généralement AMD64 ;
  • serveur DigitalOcean classique : souvent x86_64 ;
  • Mac Apple Silicon : arm64 ;
  • Raspberry Pi 64 bits : aarch64.

Une wheel x86-64 ne s’installe pas nativement sur ARM64.

64. Linux glibc contre musl

De nombreuses distributions Linux utilisent glibc.

Alpine Linux utilise généralement musl.

Une wheel :

manylinux_2_17_x86_64

vise un environnement Linux compatible glibc.

Une wheel :

musllinux_1_2_x86_64

vise musl.

C’est pourquoi les images Docker Alpine provoquent parfois davantage de compilations natives que les images Debian slim.

Pour des projets Python contenant beaucoup de dépendances natives, cette image est souvent plus simple :

FROM python:3.12-slim

qu’une image :

FROM python:3.12-alpine

Partie 18 — Conda et bibliothèques scientifiques

65. Quand utiliser Conda ?

pip installe principalement des distributions Python.

Conda peut gérer :

  • Python ;
  • les paquets Python ;
  • les bibliothèques système ;
  • des outils natifs ;
  • CUDA ;
  • BLAS ;
  • certains compilateurs.

Conda peut être pertinent pour :

  • data science ;
  • calcul scientifique ;
  • géospatial ;
  • bio-informatique ;
  • environnements CUDA complexes ;
  • dépendances natives difficiles.

Exemple :

conda create -n projet python=3.12
conda activate projet
conda install numpy pandas scipy

Éviter de mélanger sans stratégie :

conda install
pip install

Approche prudente :

  1. installer d’abord les dépendances Conda ;
  2. installer ensuite avec pip uniquement les paquets absents de Conda ;
  3. éviter de réinstaller via pip une bibliothèque native déjà gérée par Conda.

Gestion des paquets en Python 2/4

Partie 6 — Comprendre les wheels

20. Qu’est-ce qu’une wheel ?

Une wheel est un format de distribution construit, portant l’extension :

.whl

Elle peut contenir :

  • du code Python ;
  • des métadonnées ;
  • des ressources ;
  • des bibliothèques compilées ;
  • des extensions natives.

L’intérêt principal est d’éviter de compiler le logiciel pendant l’installation.

On peut comparer :

sdist  = code source à construire
wheel  = paquet déjà construit

21. Anatomie d’un nom de wheel

Exemple :

numpy-2.1.0-cp312-cp312-win_amd64.whl

Décomposition :

numpy       nom du paquet
2.1.0       version
cp312       interpréteur Python
cp312       ABI
win_amd64   plateforme

Autre exemple :

requests-2.32.3-py3-none-any.whl

Décomposition :

py3    compatible avec Python 3
none   aucune ABI native spécifique
any    n’importe quelle plateforme

Cette seconde wheel est dite « pure Python ».

22. Les trois tags d’une wheel

Une wheel utilise généralement cette structure :

{python tag}-{ABI tag}-{platform tag}

Python tag

Exemples :

py3
cp311
cp312
cp313

cp312 signifie CPython 3.12.

ABI tag

L’ABI est l’interface binaire entre le code compilé et Python.

Exemples :

none
cp312
abi3

Une extension utilisant l’ABI stable peut porter :

abi3

Elle peut alors fonctionner sur plusieurs versions de CPython.

Platform tag

Exemples :

win_amd64
win32
macosx_11_0_arm64
manylinux2014_x86_64
manylinux_2_17_aarch64
musllinux_1_2_x86_64
any

23. Pourquoi une wheel est refusée

Exemple :

ERROR: package.whl is not a supported wheel on this platform

Causes possibles :

  • wheel Python 3.11 utilisée avec Python 3.12 ;
  • wheel Windows utilisée sous Linux ;
  • wheel x86-64 utilisée sur ARM ;
  • wheel ARM utilisée sur x86-64 ;
  • wheel CPython utilisée avec PyPy ;
  • ABI incompatible ;
  • version de pip trop ancienne pour reconnaître les tags ;
  • système Linux incompatible avec le niveau manylinux.

Exemple incompatible :

torch-2.4.0-cp312-cp312-manylinux2014_aarch64.whl

Cette wheel cible CPython 3.12, Linux et l’architecture ARM64. Elle ne conviendra pas à un Windows x86-64. Les tags de wheels peuvent encoder la version Python, l’implémentation, le système d’exploitation et l’architecture.

24. Voir les tags acceptés par son environnement

python -m pip debug --verbose

La sortie contient une liste de tags compatibles, par exemple :

cp312-cp312-win_amd64
cp312-abi3-win_amd64
cp311-abi3-win_amd64
py3-none-any

Cela permet de comparer directement l’environnement avec le nom de la wheel.

Partie 7 — Archives source et compilation

25. Qu’est-ce qu’une sdist ?

Une source distribution utilise souvent :

.tar.gz

Exemple :

package-1.2.0.tar.gz

Elle contient le code source et les informations permettant de construire le paquet.

Lorsque aucune wheel compatible n’est disponible, pip peut télécharger la sdist puis tenter de construire une wheel localement.

On voit alors des messages comme :

Building wheel for package...

ou :

Failed building wheel for package

26. Pourquoi une compilation échoue

Un paquet peut contenir du :

  • C ;
  • C++ ;
  • Rust ;
  • Fortran ;
  • Cython.

Il peut donc nécessiter :

  • un compilateur ;
  • un linker ;
  • des fichiers d’en-tête ;
  • le SDK du système ;
  • des bibliothèques natives ;
  • Rust et Cargo ;
  • CMake ;
  • Ninja ;
  • pkg-config.

Sous Windows

Selon le paquet :

  • Microsoft C++ Build Tools ;
  • Windows SDK ;
  • CMake ;
  • Rust.

Sous Debian ou Ubuntu

Exemple générique :

sudo apt update
sudo apt install build-essential python3-dev

Selon le paquet :

sudo apt install libpq-dev
sudo apt install libssl-dev
sudo apt install libffi-dev
sudo apt install libxml2-dev libxslt1-dev

Exemple PostgreSQL

Le paquet psycopg ou certaines variantes de psycopg2 peuvent nécessiter les bibliothèques PostgreSQL de développement.

Erreur typique :

pg_config executable not found

Solution Debian/Ubuntu :

sudo apt install libpq-dev

27. Forcer l’utilisation de wheels

Pour refuser toute compilation :

python -m pip install --only-binary=:all: package

Exemple :

python -m pip install --only-binary=:all: numpy

Si aucune wheel compatible n’existe, l’installation échoue immédiatement.

C’est utile pour savoir si le problème vient de la compilation.

Préférer les wheels mais autoriser les sources :

python -m pip install --prefer-binary package

Refuser les wheels :

python -m pip install --no-binary=:all: package

Cette dernière commande force une compilation depuis les sources.

28. Construire ses propres wheels

python -m pip wheel -r requirements.txt -w wheels/

Puis installation locale :

python -m pip install --no-index --find-links=wheels -r requirements.txt

Cas d’usage :

  • déploiement hors ligne ;
  • CI/CD ;
  • serveurs sans compilateur ;
  • accélération des déploiements ;
  • contrôle des artefacts installés.

Partie 8 — Résolution des dépendances

29. Dépendances directes et transitives

Supposons :

mon-projet
└── fastapi
    ├── starlette
    ├── pydantic
    └── typing-extensions

fastapi est une dépendance directe.

starlette, pydantic et typing-extensions sont des dépendances transitives.

Lorsqu’on demande :

python -m pip install fastapi

pip doit chercher un ensemble de versions compatibles pour toutes ces bibliothèques.

Le processus qui détermine les versions à installer est appelé résolution des dépendances.

30. Exemple de conflit

Un projet demande :

package-a dépend de common-lib >=2,<3
package-b dépend de common-lib >=3,<4

Aucune version de common-lib ne peut satisfaire les deux contraintes.

pip peut afficher :

ResolutionImpossible

Ce message ne signifie pas nécessairement que pip est cassé.

Il signifie souvent que les contraintes sont mathématiquement incompatibles.

Les versions récentes du résolveur sont volontairement plus strictes face aux dépendances contradictoires.

31. Syntaxe des contraintes de versions

requests==2.32.3
requests>=2.30
requests>=2.30,<3
requests~=2.32.0
requests!=2.32.1

Version exacte

requests==2.32.3

Version minimale

requests>=2.30

Intervalle

requests>=2.30,<3

Version compatible

requests~=2.32.0

Cela signifie approximativement :

>=2.32.0,<2.33.0

Alors que :

requests~=2.32

signifie approximativement :

>=2.32,<3.0

32. Version de Python dans pyproject.toml

[project]
requires-python = ">=3.11,<3.13"

Cela indique que le projet accepte :

Python 3.11
Python 3.12

mais pas :

Python 3.10
Python 3.13

Ce champ est essentiel pour empêcher l’installation du projet avec une version incompatible.

33. Environment markers

Une dépendance peut être conditionnelle :

dependencies = [
    "importlib-metadata; python_version < '3.10'",
    "colorama; sys_platform == 'win32'",
]

Ainsi :

  • colorama sera installé sous Windows ;
  • importlib-metadata ne sera installé que pour certaines versions de Python.

Les résolveurs prennent en compte :

  • python_version ;
  • python_full_version ;
  • sys_platform ;
  • platform_machine ;
  • platform_python_implementation.

Partie 9 — requirements.txt, contraintes et verrouillage

34. Le fichier requirements.txt

Exemple simple :

fastapi
uvicorn
sqlalchemy
psycopg

Installation :

python -m pip install -r requirements.txt

Mais ce fichier ne garantit pas nécessairement une reproduction exacte.

Aujourd’hui, il peut installer :

fastapi 0.x
pydantic 2.x

Dans six mois, il peut choisir d’autres versions.

35. Versions figées

fastapi==0.116.1
uvicorn==0.35.0
sqlalchemy==2.0.41

Cela améliore la reproductibilité.

Pour exporter l’environnement actuel :

python -m pip freeze > requirements.txt

Mais pip freeze exporte généralement tout ce qui est installé, y compris les dépendances transitives.

Exemple :

fastapi==...
pydantic==...
pydantic-core==...
starlette==...
typing-extensions==...

Ce n’est pas toujours un bon fichier à maintenir manuellement.

36. Différence entre dépendances directes et environnement figé

Il est utile de distinguer :

Dépendances voulues

fastapi
sqlalchemy
psycopg

Résultat exact de la résolution

fastapi==...
starlette==...
pydantic==...
sqlalchemy==...
psycopg==...
typing-extensions==...

Le premier fichier décrit l’intention.

Le second décrit l’environnement résolu.

Les outils modernes comme uv, Poetry ou PDM maintiennent cette distinction avec :

  • pyproject.toml ;
  • un fichier de verrouillage.

37. Fichier de contraintes

Exemple constraints.txt :

urllib3<2.3
pydantic==2.11.7

Installation :

python -m pip install -r requirements.txt -c constraints.txt

Une contrainte ne demande pas nécessairement l’installation du paquet.

Elle limite la version si ce paquet doit être installé.

Gestion des paquets en Python 1/4

Gestion des versions et des paquets en Python

1. Le modèle mental indispensable

Les difficultés viennent souvent du fait que l’on confond plusieurs éléments indépendants :

  1. la version de Python ;
  2. l’interpréteur Python réellement exécuté ;
  3. l’environnement Python actif ;
  4. l’outil d’installation des paquets ;
  5. les versions des bibliothèques ;
  6. les formats de distribution comme les wheels ;
  7. le système d’exploitation et l’architecture du processeur.

Lorsqu’on exécute :

pip install pandas

la vraie question n’est pas seulement :

Quelle version de pandas sera installée ?

Il faut aussi demander :

Quel pip est exécuté, à quel interpréteur Python appartient-il, dans quel environnement installe-t-il, et existe-t-il un fichier binaire compatible avec mon système ?

Partie 1 — Une installation Python n’est pas un simple exécutable

2. Qu’est-ce qu’une version de Python ?

Une installation Python contient notamment :

  • un interpréteur ;
  • la bibliothèque standard ;
  • des fichiers de configuration ;
  • un répertoire destiné aux paquets externes ;
  • éventuellement pip ;
  • parfois des bibliothèques natives ;
  • des en-têtes C pour compiler des extensions.

L’exécutable peut porter différents noms :

python
python3
python3.11
python3.12
python.exe

Sous Windows, on peut également disposer du lanceur Python :

py

Le lanceur py est particulièrement utile lorsque plusieurs versions sont installées.

Exemples :

py --list
py -3.11 --version
py -3.12 --version
py -3.11 script.py

Une version Python est constituée de l’interpréteur, de la bibliothèque standard et de ses fichiers associés.

3. Version majeure, mineure et corrective

Dans :

Python 3.12.7

on distingue :

3      version majeure
12     version mineure
7      version corrective

Les incompatibilités de paquets concernent principalement la version mineure.

Par exemple :

Python 3.10
Python 3.11
Python 3.12
Python 3.13

ne doivent pas être considérés comme quatre mises à jour parfaitement interchangeables.

Une bibliothèque peut déclarer :

Requires-Python >=3.10,<3.13

Elle acceptera Python 3.10, 3.11 et 3.12, mais refusera Python 3.13.

À l’inverse, les versions correctives sont normalement compatibles entre elles :

3.12.1
3.12.7
3.12.10

Un environnement virtuel créé avec Python 3.12.1 reste généralement utilisable avec les correctifs de la branche 3.12, même s’il est souvent préférable de le recréer après un changement important de l’installation système.

4. CPython n’est pas l’unique implémentation de Python

L’implémentation utilisée dans l’immense majorité des projets est CPython.

Il existe cependant d’autres implémentations :

  • PyPy ;
  • GraalPy ;
  • MicroPython ;
  • Jython ;
  • IronPython.

Lorsqu’une wheel contient le tag :

cp312

cela signifie généralement :

CPython 3.12

Une wheel cp312 ne vise pas nécessairement PyPy 3.12.

Vérification :

python -c "import platform; print(platform.python_implementation())"

Résultat typique :

CPython

Partie 2 — Pourquoi plusieurs commandes Python coexistent

5. Le problème du PATH

Lorsque l’on tape :

python

le système cherche un exécutable dans les répertoires inscrits dans la variable PATH.

Sous Windows :

where python
where pip

Sous Linux ou macOS :

which python
which python3
which pip
type -a python
type -a pip

Il est fréquent d’obtenir plusieurs installations :

C:\Users\yvon\AppData\Local\Programs\Python\Python311\python.exe
C:\Users\yvon\AppData\Local\Programs\Python\Python312\python.exe
C:\Windows\py.exe

Le premier chemin trouvé dans PATH est généralement utilisé.

Ainsi, il est possible que :

python

désigne Python 3.12, alors que :

pip

appartienne à Python 3.11.

C’est l’une des causes les plus fréquentes de ce problème :

pip install requests

réussit, mais :

import requests

échoue avec :

ModuleNotFoundError: No module named 'requests'

6. La règle d’or : utiliser python -m pip

Au lieu de :

pip install requests

utiliser :

python -m pip install requests

Ou, sous Windows :

py -3.12 -m pip install requests

Cette syntaxe signifie :

Exécute le module pip avec cet interpréteur Python précis.

Elle garantit que le pip utilisé appartient au Python indiqué.

Commandes de diagnostic :

python --version
python -c "import sys; print(sys.executable)"
python -m pip --version

Exemple :

Python 3.12.7
C:\Python312\python.exe
pip 25.x from C:\Python312\Lib\site-packages\pip

Les trois chemins doivent être cohérents.

7. Diagnostic complet de l’interpréteur actif

Cette commande est particulièrement utile :

python -c "import sys, platform; print('Executable:', sys.executable); print('Version:', sys.version); print('Prefix:', sys.prefix); print('Base prefix:', sys.base_prefix); print('Architecture:', platform.machine())"

Informations importantes :

sys.executable

Chemin de l’interpréteur exécuté :

import sys
print(sys.executable)

sys.version

Version détaillée :

print(sys.version)

sys.prefix

Racine de l’environnement actif.

sys.base_prefix

Racine de l’installation Python d’origine.

Dans un environnement virtuel :

sys.prefix != sys.base_prefix

Test :

python -c "import sys; print(sys.prefix != sys.base_prefix)"

Résultat :

True

signifie généralement qu’un environnement virtuel est actif.

Partie 3 — Installation globale, utilisateur et virtuelle

8. Les trois emplacements principaux

Un paquet peut être installé :

  1. globalement ;
  2. dans le répertoire utilisateur ;
  3. dans un environnement virtuel.

9. Installation globale

Exemple :

python -m pip install requests

sans environnement virtuel.

Le paquet est installé dans le site-packages associé à l’interpréteur global.

Sous Windows :

C:\Python312\Lib\site-packages

Sous Linux :

/usr/local/lib/python3.12/site-packages

ou :

/usr/lib/python3/dist-packages

Pourquoi l’installation globale est problématique

Deux projets peuvent demander des versions différentes :

Projet A : Django 4.2
Projet B : Django 5.2

Un environnement global ne peut généralement contenir qu’une version de Django pour un même interpréteur.

Installer Django 5.2 pour le projet B peut donc casser le projet A.

Autre problème : sur Linux, le Python global peut être utilisé par le système d’exploitation.

Modifier ses paquets peut casser :

  • un gestionnaire de paquets ;
  • des scripts d’administration ;
  • des outils système ;
  • des composants installés par la distribution.

Les distributions modernes peuvent déclarer l’environnement Python système comme « externally managed », afin d’empêcher pip de le modifier directement.

10. Installation utilisateur

Commande :

python -m pip install --user requests

Le paquet est installé dans un répertoire appartenant à l’utilisateur.

Exemple Windows :

C:\Users\yvon\AppData\Roaming\Python\Python312\site-packages

Exemple Linux :

~/.local/lib/python3.12/site-packages

Cette méthode évite les droits administrateur, mais elle n’isole pas les projets.

Tous les projets utilisant ce Python peuvent voir ces paquets.

Elle est donc utile dans certains cas ponctuels, mais elle ne remplace pas un environnement virtuel.

11. Installation dans un environnement virtuel

Un environnement virtuel possède notamment :

  • son propre exécutable Python ou un lien vers celui-ci ;
  • son propre site-packages ;
  • son propre pip ;
  • un fichier pyvenv.cfg.

Dans sa forme minimale, un environnement virtuel contient un exécutable ou lien vers Python, un répertoire site-packages et un fichier pyvenv.cfg.

Création :

python -m venv .venv

Le module venv crée l’environnement avec la version de Python utilisée pour lancer la commande.

Ainsi :

python3.11 -m venv .venv

crée un environnement en Python 3.11.

Alors que :

python3.12 -m venv .venv

crée un environnement en Python 3.12.

Un environnement virtuel ne choisit pas lui-même une version de Python.

Il hérite de l’interpréteur qui l’a créé.

Partie 4 — Utilisation correcte de venv

12. Création sous Windows

Avec le lanceur Python :

py -3.12 -m venv .venv

Activation dans PowerShell :

.venv\Scripts\Activate.ps1

Activation dans cmd.exe :

.venv\Scripts\activate.bat

Désactivation :

deactivate

13. Création sous Linux ou macOS

python3.12 -m venv .venv

Activation :

source .venv/bin/activate

Désactivation :

deactivate

14. Ce que fait réellement l’activation

L’activation ne démarre pas une machine virtuelle.

Elle modifie principalement la variable PATH afin que :

python
pip

désignent en priorité les exécutables situés dans .venv.

Sous Windows :

.venv\Scripts\python.exe
.venv\Scripts\pip.exe

Sous Linux :

.venv/bin/python
.venv/bin/pip

Il est possible d’utiliser un environnement virtuel sans l’activer :

Sous Windows :

.venv\Scripts\python.exe script.py
.venv\Scripts\python.exe -m pip install requests

Sous Linux :

.venv/bin/python script.py
.venv/bin/python -m pip install requests

L’activation est donc un confort, pas une obligation technique.

15. Vérifier l’environnement actif

Sous Windows :

where python
python -c "import sys; print(sys.executable)"
python -m pip --version

Sous Linux :

which python
python -c "import sys; print(sys.executable)"
python -m pip --version

Résultat attendu :

...\mon-projet\.venv\Scripts\python.exe

ou :

.../mon-projet/.venv/bin/python

16. Ne jamais versionner .venv

Dans .gitignore :

.venv/
venv/
env/
__pycache__/
*.pyc

Un environnement virtuel :

  • contient des chemins absolus ;
  • dépend du système d’exploitation ;
  • dépend de l’architecture ;
  • peut contenir des binaires natifs ;
  • peut devenir très volumineux.

Il ne doit donc pas être copié entre machines ni ajouté à Git.

On versionne les fichiers décrivant les dépendances, pas l’environnement lui-même.

17. Recréer un environnement propre

Lorsqu’un environnement devient incohérent, le réparer paquet par paquet est souvent une mauvaise stratégie.

Approche propre :

Sous PowerShell :

deactivate
Remove-Item -Recurse -Force .venv
py -3.12 -m venv .venv
.venv\Scripts\Activate.ps1
python -m pip install --upgrade pip
python -m pip install -r requirements.txt

Sous Linux :

deactivate
rm -rf .venv
python3.12 -m venv .venv
source .venv/bin/activate
python -m pip install --upgrade pip
python -m pip install -r requirements.txt

Partie 5 — Que fait réellement pip install ?

18. Les grandes étapes

Lorsqu’on lance :

python -m pip install pandas

pip doit notamment :

  1. identifier la demande ;
  2. lire les métadonnées du projet ;
  3. vérifier la version de Python ;
  4. résoudre les dépendances ;
  5. choisir les versions compatibles ;
  6. sélectionner un fichier de distribution ;
  7. télécharger une wheel ou une archive source ;
  8. éventuellement compiler le paquet ;
  9. installer les fichiers ;
  10. créer les scripts exécutables ;
  11. enregistrer les métadonnées d’installation.

La documentation de pip install décrit notamment les étapes d’identification des exigences, de résolution des dépendances, de construction des wheels puis d’installation.

19. PyPI

PyPI, Python Package Index, est le dépôt public principal de paquets Python. Les auteurs y publient leurs distributions et pip peut y rechercher les fichiers adaptés.

Une page PyPI peut proposer plusieurs fichiers pour une seule version :

package-1.0.0.tar.gz
package-1.0.0-py3-none-any.whl
package-1.0.0-cp312-cp312-win_amd64.whl
package-1.0.0-cp312-cp312-manylinux_2_17_x86_64.whl

Ces fichiers ne sont pas interchangeables.

La raison est que le même paquet doit pouvoir fonctionner dans des contextes très différents. Chaque fichier correspond à un cas précis :

  • le fichier .tar.gz est le code source, utilisé quand aucune version précompilée n’est disponible ;
  • le fichier py3-none-any.whl est une version pure Python, compatible avec tous les systèmes ;
  • les fichiers cp312-... sont des versions compilées pour une version précise de Python (ici CPython 3.12) ;
  • les suffixes win_amd64 ou manylinux_2_17_x86_64 indiquent le système d’exploitation et l’architecture.

En résumé, plusieurs versions existent pour garantir que pip puisse installer le bon fichier selon :

  • ta version de Python,
  • ton système d’exploitation,
  • ton architecture matérielle,
  • et la présence ou non de code compilé.

C’est ce mécanisme qui permet à un même paquet d’être utilisable sur presque toutes les machines, sans modification manuelle.

Git cloner avec le personal access token PAT pour un repo privé

Avec un repository publique, c’est facile de cloner, c’est accessible à tout le monde. Mais quand il s’agit de repository privé,et c’est souvent le cas pour les projet d’entreprise et vos saas, c’est devenu plus compliqué.

Avant il suffisait d’entre le nom etmot de passe, masi aujourd’hui cette méthode est dépréciée, pour plus de sécurité.

Il vous faudré générer un PAT (personal access token). Et pour rendre encore plus compliqué, il y a le PAT classique (qu’on va utiliser) et le PAT avec gestion fine des accès (Fine grained token).

git clone https://refschool:ghp_TON_PAT@github.com/refschool/team-of.git .

Comment installer n8n sur O2switch (afin de ne pas payer)

J’ai eu confirmation que n8n ne peut s’installer sur O2switch. Du coup je vais le faire avec une instance DigitalOcean, vous pouvez aller sur l’offre KVM de Hostinger à 6€/mois à l’heure où j’écris ces lignes. O2Switch est vraiment taillé pour l’hébergement PHP/Mysql, hélas, si vous sortez de ce setup, comme pour NodeJs ou Python, c’est moins pratique. Notamment Phusion Passenger, qui est loin d’être aussi flexible qu’un reverse proxy Nginx.

Créez votre instance VPS, vous devez avoir accès à Linux en ligne de commande, en général ce sera un Ubuntu. Je ne détaille pas le process ici car la page n’est pas consacrée à l’hébergement.

Installation de NodeJS

sudo apt update
sudo apt install node

installer n8n avec node et npm

npm install -g n8n

// Mais il est conseillé de faire tourner n8n dans un docker, aussi, il faut d'abord installer Docker Engine. Chez DigitalOcean, vous pouvez réserver un VPS avec Docker déjà installé (avec Ubuntu)

Installation en local sur votre ordinateur

npm install -g n8n

// pour lancer
n8n

ensuite (sous Windows) appuyer sur la touche 'o' pour lancer l'application web.
Laissez la fenêtre ouverte pour faire tourner n8n.

Nginx serveur cache pour WordPress

Prérequis : vous devez avoir à minima un VPS et la liberté d’installer ce que vous voulez (ce qui n’est pas le cas de O2switch). hostinger propose un VPS de ce calibre, DigitalOcean propose des instances à la demande.

Installer Nginx et PHP-FPM

# Mettre à jour le système
sudo apt update && sudo apt upgrade -y

# Installer Nginx
sudo apt install nginx -y

# Installer PHP-FPM et extensions nécessaires pour WordPress
sudo apt install php-fpm php-mysql php-curl php-gd php-mbstring php-xml php-xmlrpc php-soap php-intl -y

Créer un dossier pour le cache Nginx

sudo mkdir -p /var/cache/nginx
sudo chown -R www-data:www-data /var/cache/nginx
sudo chmod -R 700 /var/cache/nginx

Configurer Nginx pour le cache

Éditer le fichier de site WordPress. Supposons que le site est dans /etc/nginx/sites-available/wordpress.conf.

server {
    listen 80;
    server_name ton-domaine.com www.ton-domaine.com;

    root /var/www/wordpress;
    index index.php index.html index.htm;

    # Cache configuration
    proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=WORDPRESS:100m inactive=60m use_temp_path=off;

    # Log files
    access_log /var/log/nginx/wordpress.access.log;
    error_log /var/log/nginx/wordpress.error.log;

    # Main location
    location / {
        try_files $uri $uri/ /index.php?$args;

        # Enable caching
        proxy_cache WORDPRESS;
        proxy_cache_valid 200 60m;  # Cache 200 responses 60 minutes
        proxy_cache_valid 301 302 10m;  # Cache redirects 10 minutes
        proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504;
    }

    # PHP-FPM handling
    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/run/php/php8.2-fpm.sock; # Adapte selon ta version de PHP
    }

    # Disable caching for admin and login
    location ~* /(wp-admin|wp-login\.php) {
        proxy_cache off;
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/run/php/php8.2-fpm.sock;
    }

    # Static files caching
    location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|webp)$ {
        expires 30d;
        access_log off;
    }
}

Ici, proxy_cache_path définit le cache, sa taille (100m) et l’endroit où il est stocké. On active le cache pour les pages publiques, et on le désactive pour les pages d’administration ou login.

Tester la configuration Nginx

sudo nginx -t
sudo systemctl reload nginx

Activer le log de cache

tail -f /var/log/nginx/wordpress.access.log
  1. On devrait voir des en-têtes comme :
  • HIT → la page vient du cache.
  • MISS → la page vient du serveur PHP (premier chargement ou cache expiré).

Pour ajouter un en-tête qui montre si une page est en cache :

proxy_set_header X-Cache $upstream_cache_status;

Placez-le dans la section location /.

Conseils pour WordPress

  • Installe un plugin de cache léger (comme LiteSpeed Cache ou WP Super Cache) si tu veux contrôler le purging automatique, sinon Nginx ne sait pas quand le contenu change.
  • Les images et fichiers statiques (CSS/JS) peuvent être directement servis avec expires pour ne pas passer par PHP.
  • Configure un cron ou purge Nginx pour vider le cache si tu changes beaucoup de contenu.

Version sans plugin Cache côté WordPress

Il n’est pas obligé d’avoir un WP CACHE pour dire à Nginx quand c’est invalidé. La version sans WP CACHE est disponible sur cette page.

1. Nginx en mode cache simple (proxy_cache)

  • Nginx cache les réponses HTTP qu’il reçoit de ton backend (PHP-FPM pour WordPress).
  • Il ne connaît pas la logique métier de WordPress : il ne sait pas si un post a été édité, si un commentaire est ajouté, etc.
  • Donc, par défaut, Nginx utilise un TTL (proxy_cache_valid 200 60m) pour déterminer combien de temps garder la page.
  • Après expiration, il refait une requête à PHP-FPM.

💡 En résumé : Nginx “voit” seulement les codes HTTP et les headers, pas l’état de WordPress.

2. Comment invalider intelligemment le cache ?

Pour qu’un cache Nginx soit “intelligent” et se purge automatiquement quand WordPress change quelque chose :

  1. Plugins WordPress dédiés :
    • LiteSpeed Cache ou WP Rocket peuvent envoyer des commandes de purge au serveur Nginx via HTTP ou socket quand un post/page est mis à jour.
    • Le plugin sait quand une page devient “obsolète” et demande à Nginx de la supprimer du cache.
  2. Purge manuel via Nginx :
    • On peut créer une URL spéciale comme /purge/some-path que WordPress appelle via un hook save_post.
    • Cette URL est configurée pour supprimer les fichiers du cache correspondants.
  3. Cache-Control et ETag :
    • Si WordPress envoie les headers Cache-Control et ETag, Nginx peut les respecter pour savoir quand revalider une page.
    • Cela permet un cache plus dynamique sans toucher au filesystem.

En pratique : Nginx est très rapide pour servir le cache, mais il a besoin d’un signal externe pour savoir quand le contenu est obsolète. WordPress côté PHP ou un plugin fournit ce signal.

Cloner avec Git partiellement votre projet

Saviez vosu que vous pouvez ne cloner qu’un répertoire ou plusieurs répertoire de votre repository Git? Ainsi vous économiserez de la place ! Ceci est particulièrement pertinent dans les monorepos, un monorepo est un repository unique mais avec plein de projets à l’intérieur. Google par exemple travaille en monorepo.

Vous savez alors qu’on ne peut pas cloner tous les projets de Google dsur son ordinateur, telle la volumétrie est grande. Il faut cloner ce dont on a besoin.

Comment fait on alors pour ne cloner ue partiellement un repository?

Vient la commande sparse checkout

Imaginez que vous êtes sur votre ordinateur et que vous vouliez cloner partiellement un repository, en ligne de commande voilà ce que l’on va faire

# Initialiser un nouveau dépôt Git
git clone --filter=blob:none --no-checkout https://github.com/vous/ledepot.git
cd ledepot

# Activer sparse-checkout
git sparse-checkout init --cone

# Spécifier le dossier à récupérer
git sparse-checkout set htdocs/todolist.com

# Récupérer les fichiers
git checkout main

Cette méthode vous permet néanmoins d’avoir l’historique des commits complet. Vous n’avez peut être pas besoin des commit précédents (on a rarement besoin), donc il est plus léger de n’avoir que le dernier commit.

Clonage encore plus light

git clone --depth 1 --filter=blob:none --sparse https://github.com/vous/ledepot.git
cd ledepot
git sparse-checkout set htdocs/todolist.com

  • --depth 1 = télécharge uniquement le dernier commit (pas d’historique)
  • Parfait si vous voulez juste travailler sur la version actuelle

Les blob sont des fichiers binaire, on a avec commande éviter des les télécharger.

Cette méthode télécharge uniquement les fichiers du dossier spécifié au lieu de tout le repository. L’option --cone optimise les performances pour les grandes arborescences, et --filter=blob:none évite de télécharger les blobs inutiles initialement.

Si vous voulez modifier le sparse-checkout plus tard pour ajouter d’autres dossiers :

git sparse-checkout add htdocs/autre-dossier

Un mot à propos du flag –cone

--cone fait référence au mode « cone » du sparse-checkout, qui est une approche optimisée pour gérer les patterns de fichiers.

Sans --cone (mode pattern traditionnel) :

  • Vous pouvez spécifier des patterns complexes comme *.js, src/**/test
  • Plus flexible mais plus lent sur les gros repositories
  • Git doit vérifier chaque fichier individuellement

Avec --cone (mode cone) :

  • Vous ne pouvez spécifier que des dossiers entiers (pas de wildcards)
  • Beaucoup plus rapide et performant
  • Git optimise en travaillant par « cônes » de répertoires
  • C’est le mode recommandé par défaut depuis Git 2.26

Donc le flag –cone permet d’être plus rapide quand vous avez un vraiment gros repository

Comment exposer votre site local au réseau local avec Laragon ou Apache

Pour exposer votre site local au réseau local (LAN) avec Laragon ou Apache, le processus est similaire à celui d’autres serveurs locaux comme Node.js. Cependant, il y a quelques ajustements spécifiques à faire selon que vous utilisez le serveur intégré de Laragon ou une installation Apache autonome.

Exposer Laragon au LAN

Laragon est un environnement de développement populaire sous Windows, incluant Apache, MySQL, PHP, etc. Voici comment vous pouvez exposer un site Laragon à votre réseau local.

Étape 1 : Modifier la configuration Apache de Laragon

Par défaut, Laragon est configuré pour n’écouter que sur localhost. Vous devez modifier la configuration d’Apache pour qu’il écoute sur toutes les interfaces (0.0.0.0), permettant ainsi l’accès depuis le réseau local. Ouvrez le fichier de configuration Apache dans Laragon : Allez dans Menu > Apache > httpd.conf. Recherchez la ligne suivante (généralement définie sur localhost)

Listen 127.0.0.1:80
Changez 127.0.0.1 en 0.0.0.0 pour qu'Apache écoute sur toutes les interfaces :

Listen 0.0.0.0:80

Étape 2 : Permettre aux hôtes virtuels de fonctionner sur le LAN

Si vous utilisez des hôtes virtuels avec Laragon (par exemple, monsite.test), vous devez également modifier la configuration des hôtes virtuels :
Ouvrez votre fichier de configuration des hôtes virtuels (Menu > Apache > sites-enabled > 00-default.conf ou httpd-vhosts.conf).
Trouvez la directive VirtualHost, qui ressemble à ceci :

<VirtualHost 127.0.0.1:80>
Changez 127.0.0.1 en 0.0.0.0 :

<VirtualHost 0.0.0.0:80>

Étape 3 : Trouver votre adresse IP locale

Vous devez maintenant trouver l’adresse IP locale de votre machine. Sous Windows, exécutez la commande ipconfig. Sous Linux ou Mac, utilisez ifconfig ou ip a. Une fois que vous avez votre adresse IP (par exemple, 192.168.1.100), les autres appareils du réseau local peuvent accéder à votre site hébergé sur Laragon en allant à l’adresse suivante :

http://192.168.1.100
Si vous utilisez un hôte virtuel comme monsite.test, vous y accéderez avec cette adresse :


http://192.168.1.100

Étape 4 : Configurer le pare-feu (si nécessaire)

Assurez-vous que votre pare-feu ne bloque pas l’accès au port (généralement 80 pour HTTP) :

Sous Windows :
Allez dans Panneau de configuration > Système et sécurité > Pare-feu Windows Defender > Autoriser une application ou une fonctionnalité via le pare-feu Windows Defender.
Ajoutez une règle pour Apache HTTP Server ou autorisez les connexions entrantes sur le port 80.

Étape 5 : Accéder depuis des appareils sur le LAN

Depuis n’importe quel appareil sur le même réseau local, accédez à votre site Laragon local en saisissant l’adresse IP de votre machine dans le navigateur, comme décrit ci-dessus.

Exposer un Apache autonome au LAN

Si vous utilisez une installation Apache autonome, le processus est similaire, mais implique la modification directe des fichiers de configuration Apache.

Étape 1 : Modifier la configuration Apache

Ouvrez votre fichier de configuration Apache. Il est généralement situé à :

Sous Windows (XAMPP/WAMP) : C:\xampp\apache\conf\httpd.conf ou C:\wamp\bin\apache\apache2.x.x\conf\httpd.conf
Sous Linux/Mac : /etc/httpd/httpd.conf ou /etc/apache2/apache2.conf
Recherchez la directive Listen, qui ressemble à ceci :

Listen 127.0.0.1:80
Modifiez-la pour écouter sur toutes les interfaces (0.0.0.0) :


Listen 0.0.0.0:80

Étape 2 : Mettre à jour les hôtes virtuels (si applicable)

Si vous utilisez des hôtes virtuels, ouvrez votre fichier d’hôtes virtuels (par exemple, httpd-vhosts.conf) et changez l’hôte virtuel de 127.0.0.1 à 0.0.0.0 :

<VirtualHost 0.0.0.0:80>
  DocumentRoot "C:/xampp/htdocs/monsite"
  ServerName monsite.local
</VirtualHost>

Cela garantit que les hôtes virtuels sont accessibles sur le réseau local.

Étape 3 : Configuration du pare-feu

Assurez-vous que votre pare-feu permet les connexions entrantes sur le port 80 :

Sous Linux (avec ufw) :

sudo ufw allow 80/tcp
Sous Windows : Suivez les étapes mentionnées plus haut pour autoriser le trafic via le port 80.

Étape 4 : Accéder depuis des appareils sur le LAN

Une fois votre serveur Apache configuré pour écouter sur 0.0.0.0, vous pouvez y accéder depuis d’autres appareils sur le LAN en utilisant l’adresse IP locale de votre machine :

http://192.168.1.x
Si vous avez configuré un hôte virtuel, cela fonctionnera de manière similaire.

En conclusion

  • Pour Laragon : Modifiez Listen 127.0.0.1:80 en Listen 0.0.0.0:80 dans le fichier httpd.conf ainsi que dans les fichiers des hôtes virtuels si nécessaire.
  • Pour Apache autonome : Suivez un processus similaire en modifiant la configuration pour qu’Apache écoute sur 0.0.0.0 et mettez à jour les hôtes virtuels.

Après avoir configuré votre serveur, accédez au site via l’adresse IP locale de votre machine (192.168.x.x) depuis d’autres appareils sur le réseau local.
De cette manière, vous pouvez exposer votre environnement de développement local, que ce soit avec Laragon ou Apache, à votre réseau local (LAN)

Connaitre la différence entre NodeList et HTMLCollection

Lorsque vous sélectionnez plusieurs éléments HTML en se basant sur le nom de la balise ou d’un nom de classe, vous recevez plusieurs éléments. Par exemple on a le code ci-dessous :

<ul>
    <li>1</li>
    <li>2</li>
    <li>3</li>
</ul>

let liste = document.querySelectorAll('li')

let liste2 = document.getElementsByTagName('li')

A priori liste 1 et liste2 sont pareil, mais si nous loggons chaque variable on a HTMLCollection pour liste2 et NodeList pour liste. Quelle est la différence entre les deux?

NodeList est plus général que HTMLCollection

En effet un node peut désigner un élément HTML certes, mais peut aussi désigner un commentaire HTML qui est on le sait pas un élément HTML. Le texte à l’intérieur d’un élément HTML est un node, mais pas un élément HTML

<div>
Je suis un texte
    <p>Une phrase</p>
    <p>une seconde phrase</p>
</div>

Dans l’exemple ci-dessus « Je suis un texte » n’est pas un élément HTML mais un Node.

Un HTMLCollection ou un Nodelist n’est pas un tableau mais un Iterable !

Vous connaissez sans doute la méthode map relative aux tableaux, si vous essayer d’appliquer map à une Nodelist ou un HTMLCollection, vous aurez une erreur.

liste.map( e=> e ) // erreur
for(let i=0;i< liste.length;i++){
    console.log(liste[i])
}

ça marchera aussi pour liste2.

Les index et la propriété length marchent mais c’est tout, ce n’est donc pas un tableau ! On peut boucler dessu, donc c’est un Itérable. Un tableau est un Iterable mais avec plus de propriété.

On peut cependant transformer ces Iterable en tableau avec la fonction Array.from.

HTMLCollection reflète le changement dans le DOM

Soit le HTML:

<p>Paragraph Un</p>
<p>Paragraph Deux</p>
<p>Paragraph Trois</p>


// returns an HTMLCollection
const paragraphs = document.getElementsByTagName('p')

console.log("BEFORE UPDATE: ", paragraphs)   // 3 paragraphes
  
const newParagraph = document.createElement('p')
document.body.appendChild(newParagraph)

console.log("AFTER UPDATE: ", paragraphs) // 4 paragraphes

NodeList quant à lui est généralement statique

Soit le HTML:

<p>Paragraph Un</p>
<p>Paragraph Deux</p>
<p>Paragraph Trois</p>


// returns an HTMLCollection
const paragraphs = document.querySelectorAll('p')

console.log("BEFORE UPDATE: ", paragraphs)   // 3 paragraphes
  
const newParagraph = document.createElement('p')
document.body.appendChild(newParagraph)

console.log("AFTER UPDATE: ", paragraphs) // 3 paragraphes

Exception avec getElementsByName

<body>
    <p name="toto">Paragraph Un</p>
    <p name="toto">Paragraph Deux</p>
    <p name="toto">Paragraph Trois</p>
</body>

    // returns an HTMLCollection
    const paragraphs = document.getElementsByName('toto')

    console.log("BEFORE UPDATE: ", paragraphs)   // 3 paragraphes

    const newParagraph = document.createElement('p')
    newParagraph.setAttribute('name', 'toto')
    document.body.appendChild(newParagraph)

    console.log("AFTER UPDATE: ", paragraphs) // 4 paragraphes

Mettre en place un serveur MCP en Python 3.13

Qu’est ce qu’un serveur MCP (Model Context Protocole?)

Un serveur MCP est un webservice qui fournit de la data, cette data va servir de contexte pour l’IA générative. A la différence du RAG (Retrieval Augmented Generation), il n’est pas besoin de base vectorielle pour stocker des informations.

Le workflow est le suivant, le client IA (Claude Desktop) va requêter le serveur MCP pour retirer les informations dont il a besoin pour envoyer au LLM.(chatGPT par exemple).

Cette technologie inventée par Anthropic (à l’origine de Claude) est devenue très populaire. Je pense que c’est dû au fait qu’il n’est besoin que de connaissances existantes (Webservice) par les développeurs pour pouvoir taquiner les IA afin d’éviter les hallucination.

Mais cela va au delà des hallucination, un serveur MCP est un webservice à destination non du programmeur mais de l’IA générative. Je pense que c’est une bonne comparaison, l’IA (ou plutôt l’agent IA) va pouvoir décider en autonomie de requêter un serveur MCP pour chercher les information dont il a besoin?

Donc un serveur MCP est un webservice pour agent IA, au même titre qu’un webservice est un …. webservice pour un programmeur. Dans notre cas on va utiliser Claude Desktop comme « agent IA » ou plutôt comme Client IA.

Mise en place du serveur MCP dans Pycharm

Création de mon environnement virtuel

On crée le répertoire MCP puis on fait la commande :

vous avez un répertoire appelé MCP rentrez dedans

$ python -m venv .venv

# activez l'environnement virtuel (sous powershell)
$ .\.venv\Scripts\Activate.ps1

#c'est activé (normalement) vous avez accès à la commande pip
$ pip --version

Installation de uv

uv est un gestionnaire de paquet nouvelle génération écrite en RUST.

pip install uv

puis avec uv on installe mcp 

uv add "mcp[cli]"

A partir de maintenant on va utiliser uv pour installer notre projet

uv init 

# la commande tree -L 2 nous donne la structure suivante
.
|-- README.md
|-- main.py
|-- .venv
|   |-- Include
|   |-- Lib
|   |-- Scripts
|   `-- pyvenv.cfg
|-- pyproject.toml
`-- uv.lock

Pour install tree dans Windows Gitbash, il faut télécharger l’EXE et le mettre dans C:\Program Files\Git\usr\bin, un tuto est accessible sur ce lien.

Le soucis c’est que mcp s’attends à ce que le dossier environnement virtuel soit nommé .venv, si vous faites la commande:

$ uv run mcp
warning: `VIRTUAL_ENV=mcpvenv` does not match the project environment path `.venv` and will be ignored; use `--active` to target the active environment instead


Désativez l'environnement avec 
$ deactivate
si un .venv est présent, exécutez le venv  de ce répertoire.

Exemple rapide de serveur MCP:

#server.py

from mcp.server.fastmcp import FastMCP

# Create an MCP server
mcp = FastMCP("Demo")


# Add an addition tool
@mcp.tool()
def add(a: int, b: int) -> int:
    """Add two numbers"""
    return a + b


# Add a dynamic greeting resource
@mcp.resource("greeting://{name}")
def get_greeting(name: str) -> str:
    """Get a personalized greeting"""
    return f"Hello, {name}!"


# Add a prompt
@mcp.prompt()
def greet_user(name: str, style: str = "friendly") -> str:
    """Generate a greeting prompt"""
    styles = {
        "friendly": "Please write a warm, friendly greeting",
        "formal": "Please write a formal, professional greeting",
        "casual": "Please write a casual, relaxed greeting",
    }

    return f"{styles.get(style, styles['friendly'])} for someone named {name}."

Pour le faire tourner

mcp dev server.py

#il vous sera demandé d'installer le paquet @modelcontextprotocol/inspector@0.17.0

Source: https://composio.dev/blog/mcp-server-step-by-step-guide-to-building-from-scrtch

Connaitre l’objet global Javascript Object et ses propriétés

L’objet de tous les objets

En Javascript vous avez dû sans doute croiser Object, c’est un peu l’origine de tous les objets e, Javascript.

const obj = new Object()
console.log(obj)
{}
[[Prototype]]:Object

Si on creuse un peu plus l’objet :

Vous voyez toutes les propriétés nombreuse de cet object même primitif. Tous les objet en Javascript héritent de cet objet (Date, String etc).

Méthodes statique d Object

Les méthodes static peuvent peuvent être invoquées depuis Object sans instanciation

Object.keys({a:1,b:2})  // ['a','b']

Object.assign(target,…sources)

Copie des prpriétés d’un objet à un autre

const user = { name: "John" };
const details = { age: 30, country: "France" };

const merged = Object.assign({}, user, details);
console.log(merged);
// { name: 'John', age: 30, country: 'France' }

Object.create(proto,[propertiesObject])

Crée un nouvel objet avec en paramètre un prototype

const person = { greet() { console.log("Hello"); } };
const user = Object.create(person);
user.greet(); // Hello

Object.keys(obj)

Retourne un tableau de clé de l’objet

Object.keys({a:1, b:2}); // ['a', 'b']

Object.values(obj)

Retourne un tableau de valeurs de l’objet

Object.values({a:1, b:2}); // [1, 2]

Object.entries(obj)

Retourne un tableau de clé / valeur

Object.entries({a:1, b:2});
// [['a',1], ['b',2]]
// avec destructuring
for (const [key, val] of Object.entries({a:1, b:2})) {
  console.log(key, val);
}

Object.freeze(obj)

Après un freeze, on ne peut plus ajouter,effacer ou modifier une propriété

const config = { debug: true };
Object.freeze(config);
config.debug = false; // inopérant

Intéressant pour un objet configuration que vous voulez rendre immuable

Object.seal(obj)

Empêche l’ajout ou suppression de propriété, mais autorise la modification

const user = { name: "John" };
Object.seal(user);
user.name = "Jane";  // Ok
user.age = 30;       //  ignoré

Object.getOwnPropertyNames(obj)

Retourne tous les noms des propriétés (énumérable et non énumérables)

const obj = Object.create({}, { hidden: { value: 42, enumerable: false } });
console.log(Object.getOwnPropertyNames(obj)); // ['hidden']

Ne donne que les nom de niveau 1

Object.getOwnPropertyDescriptors(obj)

Retourne les informations de chaque propriété

const obj = { a: 1 };
console.log(Object.getOwnPropertyDescriptors(obj));

Utile pour le clonage incluant getter et setters

Object.getPrototypeOf(obj)

Retourne le prototype (en gros le parent, ou parent du parent etc) d’un objet donné

const arr = [];
console.log(Object.getPrototypeOf(arr) === Array.prototype); // true

Object.setPrototypeOf(obj,prototype)

Sette le prototype à un objet

const animal = { speak() { console.log("hi"); } };
const dog = {};
Object.setPrototypeOf(dog, animal);
dog.speak(); // hi

C’est comme ça qu’on fait de l’orienté objet en Javascript et pas avec des classes, qui sont plus familières à la plupart des programmeurs.

Object.hasOwn(obj,prop)

(Ecmascript 2022 ) alternative plus safe pour hasOwnProperty

const user = { name: "Alice" };
console.log(Object.hasOwn(user, "name")); // true

Object.fromEntries(entries)

Convertit un tableau de [key,value] en un objet

const entries = [["name", "Bob"], ["age", 25]];
const user = Object.fromEntries(entries);
console.log(user); // { name: 'Bob', age: 25 }

Object.is(value1,value2)

Dit si deux objets sont les même (comme ===, mais dans le cas de NaN est plus safe

Object.is(NaN, NaN); // true
Object.is(0, -0);    // false

Object.defineProperty(obj,prop,descriptor)

Définit ou modifie une propriété avec descripteur.

const user = {};
Object.defineProperty(user, "name", {
  value: "Alice",
  writable: false,
  enumerable: true
});

Object.defineProperties(obj,props)

Définit de multiple propriétés

Méthodes d’instance

Les méthodes d’instance ne sont invocable que sur un objet instantié.

hasOwnProperty(prop)

Vérifie si la propriété existe directement dans l’objet.

const user = { name: "Alice" };
console.log(user.hasOwnProperty("name")); // true

isPrototypeOf(obj)

Vérifie si l’objet existe dans la chaine d eprototype d’un autre objet

function Animal() {}
function Dog() {}

Dog.prototype = Object.create(Animal.prototype);

const d = new Dog();
console.log(Animal.prototype.isPrototypeOf(d)); // true

propertyIsEnumerable(prop)

regarde si la propriété est énumérable

const obj = { x: 1 };
console.log(obj.propertyIsEnumerable("x")); // true

toString()

Retourne une représentation string de l’objet

console.log({}.toString()); // [object Object]

Utiliser Object.prototype.toString.call(value) pour détecter le type:

Object.prototype.toString.call([]);      // [object Array]
Object.prototype.toString.call(123);     // [object Number]

valueOf()

retourne la valeur primitive d’un objet (dans un contexte arithmétique)

const obj = { valueOf: () => 42 };
console.log(obj + 8); // 50

Applications pratiques de quelques méthodes

Clone an Object (shallow)

const copy = Object.assign({}, original);

Deep Clone (simple version)

const deepCopy = JSON.parse(JSON.stringify(original));

Merge Configurations

const defaultConfig = { debug: false, port: 8080 };
const userConfig = { debug: true };
const config = Object.assign({}, defaultConfig, userConfig);

Create Object from Key/Value Pairs

const pairs = [["id", 1], ["name", "John"]];
const obj = Object.fromEntries(pairs);

Immutable Constant Object

const roles = Object.freeze({ ADMIN: "admin", USER: "user" });

Installer et utiliser l’ORM Prisma avec NodeJS en Typescript

La base de données est MySQL

Installation de Prisma

npm init -y

npm install express @prisma/client

npx tsc --init   // va créer le fichier tsconfig.json

npx prisma --init  //


Fetching latest updates for this subcommand...

✔ Your Prisma schema was created at prisma/schema.prisma
  You can now open it in your favorite editor.
warn You already have a .gitignore file. Don't forget to add `.env` in it to not commit any private information.

Next steps:
1. Run prisma dev to start a local Prisma Postgres server.
2. Define models in the schema.prisma file.
3. Run prisma migrate dev to migrate your local Prisma Postgres database.
4. Tip: Explore how you can extend the ORM with scalable connection pooling, global caching, and a managed serverless Postgres database. Read: https://pris.ly/cli/beyond-orm

More information in our documentation:
https://pris.ly/d/getting-started

A ce stade un fichier .env et un répertoire prisma a été créé. Le .env contient la chaine de connexion, par défaut c’est pour du postgres, mais on va changer en mysql. Il faut créer la base prisma_demo_ts avant de faire les opérations de migration.

DATABASE_URL="mysql://root:password@localhost:3306/prisma_demo_ts"

Maintenant on va constituer un fichier de modèle pour créer les tables dans

Création des fichiers de migration et migration dans la même commande !

npx prisma migrate dev --name add-user-contact-table 


Environment variables loaded from .env
Prisma schema loaded from prisma\schema.prisma
Datasource "db": MySQL database "prisma_demo_ts" at "localhost:3306"

Applying migration `20251018092422_add_user_contact_table`

The following migration(s) have been created and applied from new schema changes:

prisma\migrations/
  └─ 20251018092422_add_user_contact_table/
    └─ migration.sql

Your database is now in sync with your schema.

Le script index.ts

import express from 'express'
import { PrismaClient } from '@prisma/client'

const app = express()
const prisma = new PrismaClient()

app.use(express.json())

// GET all users
app.get('/users', async (req, res) => {
    const users = await prisma.user.findMany()
    res.json(users)
})

// POST new user
app.post('/users', async (req, res) => {
    const { name, email } = req.body
    const user = await prisma.user.create({ data: { name, email } })
    res.json(user)
})

app.listen(3000, () => console.log('🚀 Serveur démarré sur http://localhost:3000'))

Si vous avez une erreur de type commonJS blabla, c’est que la syntaxe import n’est pas commonJs. Pour voir la différence entre commonJS et ESM voir cet article.

Si vous avez un message d’avertissement relatif à verbatimModuleSyntax, commentez la ligne dans tsconfig.json.

Pour lancer la compilation du fichier index.ts, désignez le répertoire de sortie des fichier JS, c’est dans tsconfig.json, la clé outDir doit être décommentée :  « outDir »: « ./dist »,

npx tsc

ensuite faites
node node dist/index.js
Retour en haut