Chapitre 11.1 — Installer PostgreSQL
⏱️ TL;DR — Un
apt install postgresqlet le serveur de base de données tourne déjà, en local, sous un utilisateur système dédié nommépostgres. Le geste fondateur : ne pas faire tourner ton app avec le super-utilisateur de la base. Tu vas créer un rôle applicatif (formacampus) avec un mot de passe fort, une base dont il est propriétaire, puis t’y connecter — au terminal avecpsql, et depuis ton app avec une chaîne de connexionDATABASE_URL. Ce chapitre pose les fondations ; la sécurité de l’accès, c’est le chapitre suivant.
🎯 Objectifs
- Installer PostgreSQL et vérifier que le service tourne.
- Comprendre le rôle de l’utilisateur système
postgreset desudo -u postgres psql. - Créer un rôle applicatif dédié, une base, et lui donner les droits.
- Te connecter avec
psqlet maîtriser les commandes de base (\l,\c,\dt,\du,\q). - Construire la chaîne de connexion que ton app utilisera.
Installer le serveur
PostgreSQL est dans les dépôts d’Ubuntu et Debian. On rafraîchit l’index puis on installe.
🐚 Au terminal — Installer PostgreSQL et vérifier le service :
sudo apt update # rafraîchit l'index des paquets
sudo apt install postgresql # installe le serveur (et le client psql)
systemctl status postgresql # le service doit être "active"Le paquet postgresql installe le serveur, le client psql, et démarre le service, configuré pour redémarrer au boot. La version fournie est la version stable de ta distribution (ne cherche pas à mémoriser un numéro : psql --version te la dira le jour venu). Par défaut, PostgreSQL écoute uniquement en local — bonne nouvelle, c’est exactement ce qu’on veut. On verrouillera ça finement au chapitre 11.2.
💡 Réflexe — Après toute installation de service, deux vérifications immédiates :
systemctl status <service>(il tourne ?) etsystemctl is-enabled <service>(il redémarrera au reboot ?). Un service installé mais qui ne remonte pas après un redémarrage, c’est la panne « inexplicable » du lundi matin.
L’utilisateur système postgres
L’installation crée un utilisateur système Linux nommé postgres. C’est lui qui possède les fichiers de données et sous lequel tourne le serveur. PostgreSQL fait par défaut correspondre cet utilisateur Linux à un super-utilisateur de base du même nom : c’est le mécanisme d’authentification peer (l’identité Linux fait foi, sans mot de passe).
Concrètement, pour ouvrir une console d’administration, tu empruntes l’identité postgres le temps d’une commande :
sudo -u postgres psql
# ouvre psql en tant que super-utilisateur "postgres"
# l'invite devient : postgres=#Ici, sudo -u postgres exécute la commande suivante en tant que l’utilisateur postgres, et psql est le client en ligne de commande. Comme l’identité Linux correspond, aucun mot de passe n’est demandé. Tu es maintenant admin de la base : c’est de là qu’on crée rôles et bases.
⚠️ Piège — Ne fais jamais tourner ton application avec le super-utilisateur
postgres. Il peut tout : supprimer n’importe quelle base, lire toutes les données, créer d’autres rôles. Une faille dans l’app deviendrait une compromission totale du serveur de base. On crée toujours un rôle dédié, aux droits limités à sa base.
Créer le rôle applicatif et la base
Le principe : un rôle par application, propriétaire de sa base et de rien d’autre. Dans la console ouverte via sudo -u postgres psql, on tape du SQL.
-- 1. Créer un rôle applicatif avec un mot de passe FORT
CREATE USER formacampus WITH PASSWORD 'REMPLACE-par-un-secret-long-et-aleatoire';
-- 2. Créer une base dont ce rôle est propriétaire
CREATE DATABASE formacampus OWNER formacampus;
-- 3. (ceinture et bretelles) lui accorder tous les droits sur cette base
GRANT ALL PRIVILEGES ON DATABASE formacampus TO formacampus;Décortiquons. CREATE USER crée un rôle capable de se connecter (dans PostgreSQL, « user » est un rôle avec le droit de login). Le WITH PASSWORD fixe son mot de passe — c’est ce secret que ton app présentera. CREATE DATABASE ... OWNER formacampus crée la base et en fait formacampus le propriétaire : il pourra créer ses tables, migrer son schéma, sans jamais toucher aux autres bases. Le GRANT est une sécurité explicite qui confirme les droits sur cette base précise.
🔒 Sécurité — Le mot de passe de ce rôle doit être fort : long (24+ caractères), aléatoire, généré par une machine (
openssl rand -base64 24fait très bien l’affaire), jamais un mot du dictionnaire ni réutilisé. Ce secret finit dans ton fichier.envsur le serveur — jamais dans git. C’est la clé de toutes les données de tes utilisateurs ; traite-le comme tel.
Vérifie ton travail sans quitter psql :
\du -- liste les rôles : tu dois voir "formacampus"
\l -- liste les bases : tu dois voir la base "formacampus"
\q -- quitte psqlSe connecter en tant que rôle applicatif
Jusqu’ici tu étais postgres (admin). Vérifions maintenant que le rôle applicatif peut se connecter à sa base, exactement comme le fera l’app :
psql -U formacampus -h localhost -d formacampus
# -U : le rôle -h localhost : force une connexion réseau locale (TCP)
# -d : la base un mot de passe sera demandéPourquoi -h localhost alors qu’on est sur la même machine ? Sans -h, psql tente une connexion par socket Unix, souvent réglée en peer (elle exigerait un utilisateur Linux formacampus). Avec -h localhost, tu passes en TCP local sur 127.0.0.1, la méthode par mot de passe — celle que ton app utilisera. Si la connexion aboutit et affiche l’invite formacampus=>, ta base applicative est prête. (Le détail de ces méthodes d’authentification, c’est tout le chapitre 11.2.)
Les commandes psql à connaître
psql est un client complet. Les méta-commandes commencent par un antislash et ne sont pas du SQL — elles inspectent la base. Le minimum vital :
| Commande | Ce qu’elle fait |
|---|---|
\l | Liste toutes les bases (list databases). |
\c formacampus | Se connecte à une autre base (connect). |
\dt | Liste les tables de la base courante (describe tables). |
\du | Liste les rôles/utilisateurs (describe users). |
\d nom_table | Décrit une table (colonnes, types, index). |
\q | Quitte psql. |
Tout ce qui ne commence pas par un antislash est du SQL et doit finir par un point-virgule (SELECT now();). Oublier le ; est l’erreur numéro un du débutant : psql attend alors la suite de ta requête au lieu de l’exécuter.
📚 La doc — Les méta-commandes psql sont listées par
\?dans la console, et parman psqlau terminal. La référence SQL complète (CREATE USER,GRANT,CREATE DATABASE…) est sur la doc officielle PostgreSQL, section « SQL Commands » — la source qui fait autorité, versionnée.
La chaîne de connexion, côté application
Ton app ne tape pas de commandes psql : elle lit une chaîne de connexion, généralement dans une variable d’environnement. Le format standard :
# fichier .env sur le serveur (jamais commité dans git)
DATABASE_URL=postgres://formacampus:LE-MOT-DE-PASSE@localhost:5432/formacampusOn lit cette URL de gauche à droite : le protocole postgres://, puis formacampus (le rôle), : le mot de passe, @localhost l’hôte, :5432 le port par défaut de PostgreSQL, et /formacampus la base. Cette même chaîne alimente aussi bien un ORM Node (Prisma, Drizzle) que Doctrine côté Symfony. Le point crucial : l’hôte est localhost — l’app et la base sont sur le même VPS, la connexion ne quitte jamais la machine.
🧭 Sur FormaCampus — L’équipe installe PostgreSQL sur le même VPS Ubuntu LTS que l’API Symfony. Elle crée le rôle
formacampus(mot de passe généré paropenssl rand), la baseformacampusdont il est propriétaire, et poseDATABASE_URL=postgres://formacampus:...@localhost:5432/formacampusdans le.envde l’API. La base contient des données personnelles d’apprenants : la connexion enlocalhostgarantit qu’elle ne transite jamais par le réseau public, première brique de leur conformité (voir le cours RGPD).
✏️ Exercices
Exercice 1 — Crée une base pour un projet. Tu déploies une app boutique. Écris la séquence SQL (dans sudo -u postgres psql) qui crée un rôle boutique avec mot de passe, une base boutique dont il est propriétaire, et lui donne les droits. Puis la commande psql pour t’y connecter en tant que ce rôle.
✅ Solution
Dans la console admin :
CREATE USER boutique WITH PASSWORD 'un-secret-long-et-aleatoire';
CREATE DATABASE boutique OWNER boutique;
GRANT ALL PRIVILEGES ON DATABASE boutique TO boutique;Puis, au terminal :
psql -U boutique -h localhost -d boutiqueLe -h localhost est indispensable pour passer par TCP (mot de passe) plutôt que par socket Unix (peer).
Exercice 2 — Décode la chaîne. Un collègue te donne postgres://app:s3cr3t@localhost:5432/prod. Nomme chaque composant, et dis ce qui te dérange dans cet exemple du point de vue sécurité.
✅ Solution
Composants : protocole postgres://, rôle app, mot de passe s3cr3t, hôte localhost, port 5432, base prod. Ce qui dérange : le mot de passe s3cr3t est beaucoup trop faible (court, devinable). En prod on veut un secret long et aléatoire (openssl rand -base64 24). Bon point en revanche : l’hôte est localhost, donc pas d’exposition réseau.
🧠 Quiz de révision
1. Que fait sudo -u postgres psql et pourquoi ça marche sans mot de passe ?
sudo -u postgres psql et pourquoi ça marche sans mot de passe ?Ça ouvre la console psql en empruntant l’identité de l’utilisateur système postgres, qui correspond au super-utilisateur de base du même nom. L’authentification peer fait confiance à l’identité Linux : comme tu es bien postgres (via sudo -u), aucun mot de passe n’est demandé.
2. Pourquoi ne pas faire tourner l’app avec le rôle postgres ?
postgres ?Parce que postgres est super-utilisateur : il peut tout lire, tout supprimer, créer d’autres rôles. Une faille dans l’app deviendrait une compromission totale. On crée un rôle dédié, propriétaire de sa seule base, aux droits limités.
3. À quoi sert le -h localhost dans la commande de connexion ?
-h localhost dans la commande de connexion ?Il force une connexion TCP locale sur 127.0.0.1 (méthode par mot de passe), au lieu de la socket Unix (souvent en peer, qui exigerait un utilisateur Linux du même nom). C’est la méthode qu’utilisera l’application.
4. Que liste \du et que liste \l dans psql ?
\du et que liste \l dans psql ?\du liste les rôles/utilisateurs de l’instance (describe users). \l liste les bases de données (list databases). Ce sont des méta-commandes psql (préfixées d’un antislash), pas du SQL.
5. Dans postgres://formacampus:pass@localhost:5432/formacampus, que représente localhost et pourquoi est-ce important ?
postgres://formacampus:pass@localhost:5432/formacampus, que représente localhost et pourquoi est-ce important ?localhost est l’hôte de la base : ici l’app et la base sont sur la même machine, donc la connexion ne quitte jamais le VPS. C’est la configuration la plus sûre : aucune donnée ne transite par le réseau public.
Chapitre suivant : Accès & pg_hba — comment PostgreSQL décide qui a le droit de se connecter, et pourquoi le port ne doit jamais toucher Internet.