Tutoriel

Un vrai LAMP sur Mac : sortir de MAMP Pro avec Homebrew

Apache, PHP-FPM, MySQL, vhosts en .test, HTTPS local et MailHog : le tout installé avec Homebrew et piloté par une commande unique. Le tutoriel complet pour sortir de MAMP Pro, écrit pour mes étudiants.

Pressé ? Si vous ne voulez pas faire l’installation étape par étape, le prompt entier à donner à l’IA est en fin d’article. Le pas-à-pas qui suit reste la version où l’on comprend ce qu’on installe.

J’ai utilisé MAMP, puis MAMP Pro, pendant des années. Fin mars 2026, lassé de diagnostiquer mes pannes à l’aveugle, j’ai demandé à Claude Code de reconstruire la même chose en natif : Apache, PHP-FPM et MySQL installés avec Homebrew, 98 vhosts migrés, HTTPS local et une commande unique pour tout piloter. Voici le tutoriel complet, écrit pour mes étudiants qui développent en PHP sur Mac.

Pourquoi j’ai fini par quitter MAMP Pro

MAMP a un vrai mérite : il démarre. On installe une application, on clique sur un bouton, et un serveur Apache avec PHP et MySQL répond sur le port 8888. Pour un premier cours de PHP, c’est parfait. J’ai fonctionné comme ça pendant des années, en passant à MAMP Pro pour débloquer les hôtes virtuels.

Puis les problèmes se sont accumulés. Pas un bug spectaculaire : une friction permanente.

  • Des versions figĂ©es - mon installation MAMP Pro 6.8.1 plafonnait Ă  PHP 8.2.0, sorti en dĂ©cembre 2022. Pour suivre les versions rĂ©centes, il faut acheter la mise Ă  jour majeure de l’application.
  • Une configuration opaque - MAMP Pro rĂ©gĂ©nère les fichiers de configuration d’Apache et de PHP depuis ses propres gabarits Ă  chaque dĂ©marrage des serveurs. Toute modification manuelle finit Ă©crasĂ©e : la configuration ne vous appartient pas.
  • Un diagnostic impossible - quand un site ne rĂ©pond plus, l’interface n’offre qu’une rĂ©ponse : tout redĂ©marrer et espĂ©rer. Aucun moyen simple de savoir quelle brique est en cause.
  • Rien n’est scriptable - impossible d’automatiser, de versionner ou de documenter proprement une configuration enfermĂ©e dans une application graphique. Pour transmettre un environnement Ă  des Ă©tudiants, c’est rĂ©dhibitoire.

Fin mars 2026, j’ai arrêté de me battre. J’ai ouvert Claude Code et je lui ai demandé de reconstruire mon environnement en natif, brique par brique, avec Homebrew. MAMP est toujours installé sur ma machine, par prudence. Je ne l’ai plus jamais ouvert.

Homebrew, le gestionnaire de paquets qui manque Ă  macOS

Homebrew est un gestionnaire de paquets : un outil en ligne de commande qui installe, met à jour et désinstalle des logiciels libres sur macOS. Là où Linux a apt ou dnf, macOS n’a rien en standard. Homebrew comble ce vide depuis 2009 et s’est imposé comme l’outil par défaut de tout développeur sur Mac.

Trois notions suffisent pour suivre ce tutoriel :

  • La formule - la recette d’installation d’un logiciel. brew install php tĂ©lĂ©charge et installe PHP avec toutes ses dĂ©pendances.
  • Le Cellar - le dossier oĂą tout s’installe : /opt/homebrew sur les Mac Apple Silicon. Rien ne se disperse dans le système, tout se dĂ©sinstalle proprement.
  • Les services - brew services start mysql enregistre MySQL comme service qui dĂ©marre avec votre session, via le launchd de macOS.
Vous êtes sur un Mac Intel ? Le tutoriel reste valable, à un détail près : Homebrew s’y installe dans /usr/local, pas dans /opt/homebrew. Remplacez ce préfixe dans tous les chemins de l’article, ou mieux : demandez-le à Homebrew lui-même avec brew --prefix. Les derniers portables Mac Intel ont été vendus en 2021, il peut donc encore y en avoir dans une classe.

L’installation tient en une commande, à coller dans le Terminal :

/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

Le script demande votre mot de passe et installe au passage les Command Line Tools d’Apple si nécessaire. Vérifiez ensuite que tout est en ordre :

brew --version
brew doctor

Pour mes étudiants, l’argument décisif n’est pas technique : une installation Homebrew se documente. Chaque étape de ce tutoriel est une commande qu’on peut lire, rejouer et corriger. Un clic dans une interface, non.

La stack cible

Voici ce qu’on va monter. Chaque brique est un paquet Homebrew indépendant, avec son fichier de configuration et son log :

Navigateur
    |
    v
Apache 2.4 ................. :80 / :443
    |    fichiers statiques servis en direct
    |    *.php transmis a PHP-FPM (proxy fcgi)
    v
PHP-FPM 8.4 ................ 127.0.0.1:9000
    |
    v
MySQL 9.6 .................. 127.0.0.1:3306
                             (socket /tmp/mysql.sock)

mail() PHP -> msmtp -> MailHog :1025 (SMTP)
                               :8025 (interface web)

Deux choix de conception comptent. Apache tourne sous votre utilisateur macOS (directives User et Group) : fini les conflits de permissions entre le serveur et vos fichiers. Et PHP ne vit pas dans Apache : il tourne en service séparé, PHP-FPM, auquel Apache transmet les fichiers .php par le protocole FastCGI. C’est l’architecture des serveurs de production modernes.

Les versions au moment où j’écris : Apache 2.4.66, PHP 8.4.12, MySQL 9.6.0, mkcert 1.4.4, MailHog 1.0.1. Les vôtres seront peut-être plus récentes, les commandes ne changent pas.

L’installation, brique par brique

Tout ce qui suit vient de ma machine réelle, pas d’un tutoriel théorique : les chemins, les ports et les blocs de configuration sont ceux qui tournent chez moi aujourd’hui. Comptez une petite heure la première fois.

Installer Apache

brew install httpd

Homebrew livre Apache configuré sur le port 8080, pour éviter de réclamer des privilèges. On veut les vrais ports. Ouvrez /opt/homebrew/etc/httpd/httpd.conf et ajustez ces directives :

Listen 80
User votrenom     # votre nom d'utilisateur macOS
Group staff
DirectoryIndex index.php index.html

Dans le même fichier, décommentez les modules dont la stack a besoin :

LoadModule proxy_module lib/httpd/modules/mod_proxy.so
LoadModule proxy_fcgi_module lib/httpd/modules/mod_proxy_fcgi.so
LoadModule ssl_module lib/httpd/modules/mod_ssl.so
LoadModule rewrite_module lib/httpd/modules/mod_rewrite.so

Le port 80 étant privilégié, Apache se lance avec sudo /opt/homebrew/bin/httpd -k start. C’est le seul service de la stack qui exige sudo ; tous les autres tournent en simple utilisateur.

Créez ensuite le dossier qui contiendra tous vos projets, avec cette commande dans le Terminal :

mkdir -p ~/htdocs

Puis rouvrez httpd.conf et collez le bloc suivant tel quel, à la fin du fichier, en remplaçant votrenom. Attention : il se place bien dans httpd.conf, pas dans un fichier .htaccess. C’est même l’inverse : sa ligne AllowOverride All autorise vos futurs projets à utiliser leurs propres fichiers .htaccess, indispensables à WordPress. Vous n’avez aucun .htaccess à créer ici.

<Directory "/Users/votrenom/htdocs">
    Options Indexes FollowSymLinks
    AllowOverride All
    Require all granted
</Directory>

Installer PHP et PHP-FPM

brew install php
brew services start php

La formule installe PHP 8.4 avec PHP-FPM, son gestionnaire de processus. Il écoute sur le port 9000, comme le confirme /opt/homebrew/etc/php/8.4/php-fpm.d/www.conf :

listen = 127.0.0.1:9000

Côté Apache, un bloc suffit pour transmettre chaque fichier .php à PHP-FPM. C’est le pont entre les deux briques, à ajouter en fin de httpd.conf :

# === PHP-FPM Handler ===
Timeout 30
ProxyTimeout 30
<FilesMatch \.php$>
    SetHandler "proxy:fcgi://127.0.0.1:9000"
</FilesMatch>

Les deux directives Timeout fixent la patience d’Apache à 30 secondes. Retenez ce chiffre : il expliquera plus loin un piège classique.

Installer MySQL

brew install mysql
brew services start mysql

MySQL écoute en TCP sur 127.0.0.1:3306 et sur un socket UNIX, /tmp/mysql.sock. À l’installation, root n’a pas de mot de passe : donnez-lui-en un.

mysql -u root
ALTER USER 'root'@'localhost' IDENTIFIED BY 'root';

Oui, root/root. Un mot de passe fort n’a aucun intérêt sur une base locale qui n’écoute que votre machine ; la simplicité, si. Toutes les commandes du quotidien deviennent mysql -u root -proot.

Créer un vhost par projet

Un hôte virtuel associe un nom de domaine local à un dossier. Chaque projet reçoit son domaine en .test, un TLD réservé qui n’existera jamais sur Internet. Trois fichiers à toucher.

D’abord, déclarer le domaine dans /etc/hosts :

127.0.0.1    nomduprojet.test

Ensuite, le vhost HTTP dans /opt/homebrew/etc/httpd/extra/httpd-vhosts.conf :

<VirtualHost *:80>
    ServerName nomduprojet.test
    DocumentRoot "/Users/votrenom/htdocs/nomduprojet"
</VirtualHost>

Enfin son jumeau HTTPS dans httpd-ssl.conf, qui pointe vers le certificat commun (on le génère juste après) :

<VirtualHost *:443>
    ServerName nomduprojet.test
    DocumentRoot "/Users/votrenom/htdocs/nomduprojet"
    SSLEngine on
    SSLCertificateFile "/opt/homebrew/etc/httpd/ssl/local-dev.pem"
    SSLCertificateKeyFile "/opt/homebrew/etc/httpd/ssl/local-dev-key.pem"
</VirtualHost>

Redémarrez Apache (sudo /opt/homebrew/bin/httpd -k restart) et testez avec une page de diagnostic :

echo '<?php phpinfo();' > ~/htdocs/nomduprojet/index.php

Ma configuration compte aujourd’hui 98 vhosts construits sur ce modèle. Je n’en ai écrit aucun à la main : Claude Code a lu la configuration de MAMP Pro et généré les deux fichiers d’un coup. L’en-tête « Auto-generated from MAMP Pro configuration » est encore visible en haut du fichier.

Passer en HTTPS avec mkcert

mkcert crée une autorité de certification locale, l’installe dans le trousseau macOS, puis émet des certificats que votre navigateur accepte sans avertissement.

brew install mkcert
mkcert -install

Je génère un certificat unique pour tous mes domaines locaux, stocké à côté de la configuration Apache :

mkdir -p /opt/homebrew/etc/httpd/ssl
cd /opt/homebrew/etc/httpd/ssl
mkcert -cert-file local-dev.pem -key-file local-dev-key.pem \
  localhost nomduprojet.test autreprojet.test

Tous les vhosts SSL pointent vers cette même paire de fichiers. Quand un projet arrive, on ajoute son domaine à la liste et on régénère : le mien couvre aujourd’hui 104 domaines. Un wildcard *.test ferait aussi l’affaire si vous préférez ne plus jamais y retoucher.

Capturer les emails avec MailHog

Dernier angle mort du dev local : les emails. Un site cloné qui envoie de vrais messages à de vrais utilisateurs pendant vos tests, c’est l’accident bête par excellence. MailHog intercepte tout : il écoute en SMTP sur le port 1025 et affiche les messages capturés dans une interface web sur le port 8025.

brew install mailhog msmtp
brew services start mailhog

Le pont avec PHP se fait par msmtp, un client SMTP minimal. Une ligne dans /opt/homebrew/etc/php/8.4/php.ini redirige la fonction mail() :

sendmail_path = "/opt/homebrew/bin/msmtp --host=127.0.0.1 --port=1025 --from=dev@localhost -t"

Chaque mail() de vos projets atterrit désormais sur http://localhost:8025. Aucun email ne quitte jamais la machine.

devstack : toute la stack en une commande

Quatre services, quatre façons de démarrer : c’est exactement le genre de friction qui ramène vers MAMP. Claude Code a donc écrit devstack, un script bash de 440 lignes posé dans /usr/local/bin, qui pilote l’ensemble :

devstack start        # demarre MySQL, PHP-FPM, MailHog, Apache
devstack stop         # arrete tout
devstack restart      # redemarrage dur (tue les workers PHP-FPM satures)
devstack status       # teste la connectivite reelle de chaque brique
devstack doctor site  # diagnostique un projet precis
devstack fix          # debloque les workers PHP-FPM coinces

La subtilité est dans status : il ne vérifie pas que les processus existent, il teste que chaque service répond vraiment. Un curl sur le port 80, un SELECT 1 sur MySQL, un lsof sur le port 9000. Un processus zombie est détecté, pas masqué.

=== Ports ===
  :80   -> httpd     (Apache)
  :443  -> httpd     (Apache)
  :3306 -> mysqld    (MySQL)
  :9000 -> php-fpm   (pool www)
  :1025 -> MailHog   (SMTP)
  :8025 -> MailHog   (interface web)

devstack doctor nomduprojet.test va plus loin : il détecte un WordPress, lit les identifiants dans wp-config.php, teste la connexion à la base, vérifie siteurl et home, compte les feuilles de style chargées et remonte les dernières erreurs PHP du log Apache. Le genre de vérifications qu’on fait à la main, dans le désordre, un soir de panne : le script les fait dans l’ordre, à chaque fois.

La règle d’or : un environnement de dev doit pouvoir se diagnostiquer en une commande. S’il ne sait pas dire ce qui ne va pas, vous ne le possédez pas : vous le subissez.

Les pièges à connaître

localhost n’est pas 127.0.0.1

Le piège le plus vicieux de la migration. Pour MySQL, localhost signifie « passe par le socket UNIX » et 127.0.0.1 « passe par TCP ». Un site configuré sous un autre environnement, MAMP par exemple, cherchera le socket au mauvais endroit et échouera avec un « can’t connect » incompréhensible, alors que MySQL tourne parfaitement. Sur cette stack, la règle est simple : 127.0.0.1 partout.

define('DB_HOST', '127.0.0.1');   // jamais 'localhost' en local

Le Gateway Timeout des WordPress clonés

Vous clonez un WordPress depuis la production, et tout répond 504 au bout de 30 secondes, même wp-login. Souvenez-vous des directives Timeout : Apache attend PHP-FPM 30 secondes, pas plus. Le coupable habituel est un plugin de sécurité comme Wordfence, qui tente des appels sortants vers son API au chargement de chaque page. En local, l’appel traîne, le worker PHP-FPM reste occupé, Apache abandonne.

Le remède : désactiver le plugin directement, sans passer par l’admin, qui est elle-même en timeout :

wp plugin deactivate wordfence --path=/Users/votrenom/htdocs/nomduprojet

brew services affiche httpd en erreur

Normal. Apache est le seul service lancé hors de brew services, en sudo, à cause du port 80. La colonne d’état de brew services list ne fait pas foi pour lui ; devstack status, si.

Le prompt Ă  donner Ă  Claude Code

Mes étudiants utilisent tous Claude Code. La tentation est donc grande de lui déléguer ce tutoriel entier, et elle est légitime : c’est exactement ce que j’ai fait. Voici le prompt que je leur donne, à coller tel quel dans une session :

Installe-moi un environnement LAMP complet sur ce Mac avec Homebrew,
sans MAMP ni application graphique :

1. Apache (formule httpd) sur les ports 80 et 443, tournant sous mon
   utilisateur macOS, avec les modules proxy_fcgi, ssl et rewrite.
2. PHP, dernière version stable, en PHP-FPM sur 127.0.0.1:9000,
   relié à Apache par un bloc FilesMatch.
3. MySQL en service brew, avec root/root en local.
4. Un dossier ~/htdocs pour tous mes projets (AllowOverride All).
5. Un vhost HTTP et un vhost HTTPS par projet, en .test,
   déclarés dans /etc/hosts.
6. HTTPS local avec mkcert (autorité installée dans le trousseau).
7. MailHog et msmtp pour capturer la fonction mail() de PHP.
8. Un script devstack start|stop|restart|status dans /usr/local/bin.

Règles : explique-moi chaque étape avant de l’exécuter, demande ma
validation avant toute commande sudo, et termine par un test complet :
une page phpinfo() servie en HTTPS sur monprojet.test, et un mail()
visible dans MailHog sur localhost:8025.

Les règles de la fin ne sont pas décoratives. L’IA installera tout, mais l’environnement reste le vôtre : chaque étape validée est une étape comprise. Je recommanderais de suivre ce tutoriel à la main une première fois, puis de laisser Claude Code le rejouer sur les machines suivantes. Dans cet ordre-là.

Ce que ça change au quotidien

  • La transparence bat le confort. Un fichier de configuration qu’on lit vaut mieux qu’une interface qui le cache. Mes pannes n’ont pas disparu : elles sont devenues diagnosticables.
  • Scriptable veut dire transmissible. Ce tutoriel existe parce que la stack est du texte : des commandes, des fichiers de conf, un script bash. Une configuration MAMP ne s’enseigne pas, elle se montre.
  • Le coĂ»t est nul. Toutes les briques sont libres et gratuites. La licence MAMP Pro finançait surtout le confort de ne pas apprendre.
  • L’IA a changĂ© le calcul. Monter cette stack Ă  la main demandait une journĂ©e de documentation Ă©parse ; c’est ce qui rendait MAMP attractif. Claude Code me l’a montĂ©e fin mars 2026, migration des 98 vhosts comprise, pendant que je faisais autre chose.
Un environnement de développement n’est pas une application qu’on subit : c’est un outillage qu’on possède. MAMP m’a rendu service en masquant la complexité. La stack Homebrew me rend un meilleur service en me la montrant.

Qui fait quoi ? Le rappel

Six briques, six rôles. À garder sous la main :

  • Homebrew - le gestionnaire de paquets : il installe, met Ă  jour et dĂ©sinstalle toutes les briques ci-dessous. brew.sh
  • Apache - le serveur web : il reçoit les requĂŞtes du navigateur et sert vos sites, un vhost par projet. httpd.apache.org
  • PHP et PHP-FPM - le langage qui exĂ©cute votre code ; FPM, son gestionnaire de processus, rĂ©pond Ă  Apache sur le port 9000. php.net
  • MySQL - la base de donnĂ©es : elle stocke les contenus de vos applications, en TCP sur le port 3306. mysql.com
  • mkcert - la fabrique de certificats : elle rend le HTTPS local acceptĂ© par votre navigateur. GitHub
  • MailHog - le filet Ă  emails : il intercepte tout ce que PHP envoie et l’affiche sur le port 8025. GitHub