Introduction
Vous avez déployé une excellente app Laravel sur une instance EC2. Nginx tourne, PHP-FPM est chaud, et puis — bam — vos logs explosent avec :
SQLSTATE[08006] [7] connection to server at "127.0.0.1", port 5432 failed: Connection refusedFATAL: role "ec2-user" does not existSQLSTATE[42501]: Insufficient privilege: permission denied for schema publicClass "Redis" not foundouConnection refused [tcp://127.0.0.1:6379]
Si cela vous semble familier, ce guide est pour vous.
Dans ce tutoriel premium de bout en bout, je vous montrerai comment installer et configurer PostgreSQL et Redis localement sur la même machine AWS EC2 qui exécute Laravel — et comment diagnostiquer et corriger les erreurs les plus courantes que vous rencontrerez en chemin. Vous obtiendrez un plan réutilisable pour chaque projet : léger, sécurisé et rapide.
Ce que vous aurez à la fin :
- Un stack PostgreSQL 15 et Redis fonctionnel sur Amazon Linux (ou similaire) avec des services systemd et la persistance.
- Un Laravel .env renforcé qui utilise Redis pour le cache/sessions/files d'attente et PostgreSQL pour la base de données.
- Une section rapide de dépannage qui résout les erreurs de connexion refusée, rôles manquants, permissions et problèmes d'extension PHP Redis.
- Des conseils pratiques de performance et fiabilité : tuning de petites instances, vérification des logs et hygiène de production.
C'est parti.
Ce Dont Vous Aurez Besoin
- Une instance AWS EC2 (t3.micro ou plus). Amazon Linux 2023 est parfait ; les commandes correspondent étroitement à RHEL/CentOS avec
dnf. - Un security group autorisant le trafic entrant sur 80/443 (HTTP/HTTPS) depuis internet et 22 (SSH) depuis votre IP. N'ouvrez pas PostgreSQL (5432) ou Redis (6379) à l'internet public.
- Une codebase Laravel déployée (Nginx + PHP-FPM) avec un accès SSH en tant que
ec2-user(ou similaire).
Installer les Paquets Requis par Laravel + Stack DB
Les commandes ci-dessous ciblent Amazon Linux 2023. Pour Ubuntu, remplacez
dnfparapt.
# Toujours commencer ici
sudo dnf -y update
# PHP & extensions courantes (ajuster les versions si nécessaire)
sudo dnf -y install php-cli php-fpm php-common php-opcache php-mbstring php-xml php-curl php-zip php-gd php-intl
# Client Postgres + extension PHP
sudo dnf -y install postgresql postgresql15 postgresql15-server php-pgsql
# Serveur Redis + extension PHP Redis
# Sur Amazon Linux 2023, redis est typiquement fourni comme redis6 dans amazon-linux-extras.
sudo dnf -y install redis || true
sudo amazon-linux-extras enable redis6 || true
sudo dnf -y install redis
sudo dnf -y install php-pecl-redis || sudo dnf -y install php-redis
# Git & outils
sudo dnf -y install git unzip
Pourquoi à la fois postgresql et postgresql15* ?
Sur AL2023, postgresql15 est le serveur que vous voulez. Le paquet générique postgresql fournit les utilitaires client. Si postgresql15 n'est pas trouvé, activez le bon dépôt ou utilisez la version majeure de PostgreSQL fournie par l'OS.
Redémarrez PHP-FPM après l'installation des extensions PHP :
sudo systemctl restart php-fpm
Initialiser et Démarrer PostgreSQL 15
Initialisez le répertoire de données en tant qu'utilisateur système postgres :
# Initialiser le cluster
sudo -u postgres /usr/bin/initdb -D /var/lib/pgsql/15/data
# (Si initdb n'est pas trouvé, localisez-le)
# sudo find / -type f -name initdb 2>/dev/null
# Créez un service systemd pour PG15 si votre image n'a pas l'unité :
cat <<'EOF' | sudo tee /etc/systemd/system/postgresql-15.service
[Unit]
Description=PostgreSQL 15 database server
After=network.target
[Service]
Type=notify
User=postgres
ExecStart=/usr/bin/pg_ctl -D /var/lib/pgsql/15/data -l /var/lib/pgsql/15/data/serverlog start
ExecStop=/usr/bin/pg_ctl -D /var/lib/pgsql/15/data stop
ExecReload=/usr/bin/pg_ctl -D /var/lib/pgsql/15/data reload
KillMode=mixed
[Install]
WantedBy=multi-user.target
EOF
sudo systemctl daemon-reload
sudo systemctl enable postgresql-15
sudo systemctl start postgresql-15
sudo systemctl status postgresql-15 --no-pager
Si le statut affiche active (running), vous êtes prêt.
Créer la Base de Données, l'Utilisateur et Sécuriser l'Auth Locale
Entrez dans le shell Postgres :
sudo -u postgres psql
Créez une base de données/utilisateur dédié et accordez la propriété (cela évite le redouté "permission denied for schema public") :
-- dans psql
CREATE DATABASE writeflow;
CREATE USER writeflow_user WITH ENCRYPTED PASSWORD 'StrongPassword123!';
GRANT ALL PRIVILEGES ON DATABASE writeflow TO writeflow_user;
\c writeflow
ALTER SCHEMA public OWNER TO writeflow_user;
-- optionnel : assurez que les futurs objets appartiennent à l'utilisateur de l'app
ALTER DATABASE writeflow OWNER TO writeflow_user;
Renforcez l'authentification locale pour utiliser MD5 pour les connexions TCP locales (ou peer/ident si vous préférez les sockets) :
sudo nano /var/lib/pgsql/15/data/pg_hba.conf
Ajoutez ou assurez que ces lignes sont présentes en haut :
# TYPE DATABASE USER ADDRESS METHOD
local all all peer
host all all 127.0.0.1/32 md5
host all all ::1/128 md5
Rechargez PostgreSQL :
sudo systemctl restart postgresql-15
Tests rapides :
PGPASSWORD='StrongPassword123!' psql -U writeflow_user -d writeflow -h 127.0.0.1 -c "select now();"
Si cela retourne un horodatage, votre authentification DB est correcte.
Installer et Démarrer Redis (et le Rendre Persistant)
# Installer (déjà fait ci-dessus) ; démarrer et activer
sudo systemctl enable redis
sudo systemctl start redis
sudo systemctl status redis --no-pager
# Test de fumée
redis-cli ping
# Attendu : PONG
Si votre image fournit Redis 6 sous un nom d'unité différent (ex. redis6), adaptez simplement :
sudo systemctl enable redis6
sudo systemctl start redis6
sudo systemctl status redis6 --no-pager
Bind + Sécurité : Pour un usage local uniquement, liez à 127.0.0.1 et gardez le mode protégé activé.
sudo sed -i 's/^#\?bind .*/bind 127.0.0.1/' /etc/redis/redis.conf || true
sudo sed -i 's/^protected-mode .*/protected-mode yes/' /etc/redis/redis.conf || true
sudo systemctl restart redis || sudo systemctl restart redis6
Configurer le .env de Laravel
Dans la racine de votre app :
nano /var/www/your-app/.env
Utilisez cette configuration de base propre pour DB et Redis :
APP_ENV=production
APP_DEBUG=false
APP_URL=https://your-domain.com
# --- Base de Données (PostgreSQL)
DB_CONNECTION=pgsql
DB_HOST=127.0.0.1
DB_PORT=5432
DB_DATABASE=writeflow
DB_USERNAME=writeflow_user
DB_PASSWORD=
# --- Cache/Session/Queue via Redis
CACHE_DRIVER=redis
SESSION_DRIVER=redis
QUEUE_CONNECTION=redis
REDIS_CLIENT=phpredis
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379
Important : assurez-vous que l'extension Redis de PHP est chargée. Après l'installation de php-pecl-redis, un redémarrage de PHP-FPM la détecte généralement :
php -m | grep -i redis # devrait afficher : redis
sudo systemctl restart php-fpm
Migrer et Optimiser l'App Laravel
Depuis votre répertoire d'app :
php artisan key:generate
php artisan config:clear
php artisan cache:clear
php artisan view:clear
# Exécutez fresh ou standard migrate selon les besoins
php artisan migrate --force
Si vous obtenez permission denied for schema public, réexécutez les grants Postgres (voir Section 3). Assurez-vous également que le propriétaire de la base de données est votre utilisateur d'app et non postgres.
Corriger Chaque Erreur Courante (Coffre de Dépannage)
A) SQLSTATE[08006] [7] connection to server at "127.0.0.1", port 5432 failed: Connection refused
Signification : Le serveur PG n'écoute pas, a planté ou est bloqué.
Liste de vérification :
sudo systemctl status postgresql-15 --no-pager
journalctl -xeu postgresql-15 --no-pager
ss -ltnp | grep 5432
- Si l'unité est inactive/en échec, vérifiez
serverlogdans/var/lib/pgsql/15/data/. - Vérifiez
pg_hba.confetpostgresql.conf(listen_addresses). Pour le TCP local, assurezlisten_addresses = 'localhost'ou'*'(local uniquement est correct). - Assurez-vous que votre
.envutilise le bon nom de DB, utilisateur et mot de passe.
B) FATAL: role "ec2-user" does not exist
Signification : Laravel a essayé de s'authentifier avec un nom d'utilisateur Linux (arrive souvent si .env n'est pas chargé ou le cache env est obsolète).
Correction :
- Vérifiez les valeurs
.envetphp artisan config:clear. - Confirmez que les identifiants DB dans
config/database.phputilisentenv()et non des fallbacks codés en dur pointant versec2-user.
C) SQLSTATE[42501]: Insufficient privilege: permission denied for schema public
Signification : Votre utilisateur d'app ne possède pas le schéma ou manque de permissions.
Correction dans psql :
\c writeflow
ALTER SCHEMA public OWNER TO writeflow_user;
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO writeflow_user;
GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA public TO writeflow_user;
ALTER DATABASE writeflow OWNER TO writeflow_user;
D) Class "Redis" not found
Signification : Extension PHP Redis non chargée.
Correction :
sudo dnf -y install php-pecl-redis || sudo dnf -y install php-redis
php -m | grep -i redis
sudo systemctl restart php-fpm
Assurez-vous que .env utilise REDIS_CLIENT=phpredis.
E) Redis connection refused [tcp://127.0.0.1:6379]
Signification : Le service Redis ne tourne pas ou est lié à une autre IP.
Correction :
sudo systemctl status redis --no-pager || sudo systemctl status redis6 --no-pager
redis-cli ping
ss -ltnp | grep 6379
- Si l'unité est arrêtée,
sudo systemctl start redisetsudo systemctl enable redis. - Assurez
bind 127.0.0.1dans/etc/redis/redis.conf, puis redémarrez.
F) migrations table does not exist (alors que vous savez qu'elle existe)
Signification : Le cache de config pointe vers la mauvaise DB, ou .env n'est pas lu.
Correction :
php artisan config:clear
php artisan cache:clear
php artisan migrate --force
Gains de Performance pour Petites Instances
Vous n'avez pas besoin d'un DBA pour éviter les erreurs de mémoire insuffisante.
PostgreSQL (sur t3.micro/t3.small) :
- Gardez
max_connectionsmodeste (ex. 100 ou moins). - Utilisez des shared buffers raisonnables :
shared_buffers = 128MB. - Définissez
effective_cache_size = 1GBsur les petites machines (si la mémoire le permet).
PHP-FPM :
- Réduisez
pm.max_childrenpour correspondre à la RAM. Sur les petites machines, 5–10 est souvent suffisant.
Redis :
- Gardez-le local uniquement avec
bind 127.0.0.1et la persistance par défaut pour les sessions/files d'attente.
Hygiène de Sécurité et Fiabilité
-
Security Groups : N'exposez jamais 5432 ou 6379 publiquement. Gardez-les liés uniquement à 127.0.0.1.
-
Sauvegardes :
pg_dumpnocturne vers S3 :# /usr/local/bin/pg-backup.sh #!/usr/bin/env bash set -e TS=$(date +%F-%H%M) PGPASSWORD='StrongPassword123!' pg_dump -U writeflow_user -h 127.0.0.1 writeflow \ | gzip > /tmp/writeflow-$TS.sql.gz aws s3 cp /tmp/writeflow-$TS.sql.gz s3://your-db-backups/ rm -f /tmp/writeflow-$TS.sql.gzPuis planifiez avec cron :
sudo crontab -e 0 3 * * * /usr/local/bin/pg-backup.sh >> /var/log/pg-backup.log 2>&1 -
Logs :
- PostgreSQL :
/var/lib/pgsql/15/data/serverlog - Redis :
journalctl -xeu redis - Nginx/PHP :
/var/log/nginx/access.log,/var/log/nginx/error.log,journalctl -xeu php-fpm
- PostgreSQL :
Checklist de Test de Fumée End-to-End
sudo systemctl status postgresql-15→ active (running)PGPASSWORD='StrongPassword123!' psql -U writeflow_user -d writeflow -h 127.0.0.1 -c "select version();"→ retourne la versionsudo systemctl status redis(ouredis6) → active (running)redis-cli ping→ PONGphp -m | grep -i redis→ redisphp artisan migrate --force→ DONE- Les flux de connexion/inscription fonctionnent ; les sessions persistent ; les caches se réchauffent.
Points Clés / Résumé Rapide
- N'exposez jamais DB/Redis à internet. Liez à
127.0.0.1, sécurisez via les security groups. - Corrigez "role does not exist" en vous assurant que
.envest chargé et que le bon utilisateur DB est créé. - Corrigez "permission denied for schema public" en transférant la propriété du schéma/base de données à votre utilisateur d'app.
- Corrigez Redis "Class not found" en installant
php-pecl-rediset en redémarrant PHP-FPM. - Corrigez Redis "Connection refused" en activant et démarrant le service Redis, puis en confirmant qu'il écoute sur 127.0.0.1:6379.
- Assurez la fiabilité : vérifiez avec
systemctletjournalctl, et sauvegardez chaque nuit vers S3.
Appel à l'Action (CTA)
Vous voulez une checklist de déploiement éprouvée (Nginx, PHP-FPM, SSL, Postgres, Redis) que vous pouvez coller dans votre terminal ? Vous en avez besoin rapidement et bien fait ? 👉 Achetez mon gig Fiverr : https://www.fiverr.com/s/DBjDz4a
FAQ (Questions Fréquentes)
Q1) Dois-je utiliser PostgreSQL/Redis local ou des services managés (RDS/ElastiCache) ? Si vous êtes en phase initiale ou soucieux des coûts, le local est léger et rapide à mettre en place. Quand votre trafic augmente ou que vous avez besoin d'un failover multi-AZ, passez à RDS + ElastiCache pour une fiabilité et une mise à l'échelle gérées.
Q2) Dois-je ouvrir le port 5432 ou 6379 en externe ? Non. Votre app Laravel se connecte localement. Gardez les deux fermés à internet et liés à 127.0.0.1.
Q3) Comment corriger "SQLSTATE[08006] connection refused" alors que PostgreSQL tourne ?
Vérifiez qu'il écoute sur 127.0.0.1:5432 (ss -ltnp | grep 5432), confirmez les identifiants .env, et vérifiez pg_hba.conf pour les règles md5 locales. Enfin, php artisan config:clear pour vider le cache env obsolète.
Q4) Redis tourne mais les sessions échouent toujours — pourquoi ?
Confirmez que php -m | grep -i redis affiche l'extension. Assurez-vous que .env a REDIS_CLIENT=phpredis et redémarrez php-fpm. Vérifiez aussi que storage/framework/sessions n'est pas utilisé par erreur (vérifiez SESSION_DRIVER).
Q5) Comment éviter "permission denied for schema public" sur les nouvelles tables ? Après avoir créé la DB, définissez le propriétaire comme votre utilisateur d'app et exécutez :
ALTER SCHEMA public OWNER TO writeflow_user;
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO writeflow_user;
GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA public TO writeflow_user;
Cela corrige les objets actuels et futurs.
Q6) Et le SSL/TLS vers la base de données ? Pour les connexions sur le même hôte (127.0.0.1), SSL n'est pas nécessaire. Si vous déplacez plus tard la DB vers une instance séparée ou RDS, activez SSL et restreignez les connexions via les security groups.
Mot Final
Vous n'avez pas besoin d'un énorme budget DevOps pour exécuter des apps Laravel rapides et stables sur AWS. Avec ce guide, vous avez :
- Mis en place PostgreSQL 15 + Redis localement,
- Connecté Laravel pour la performance (Redis cache/sessions/files d'attente),
- Résolu les erreurs frustrantes qui bloquent la plupart des équipes le premier jour.
Gardez ce guide. Réutilisez-le au prochain lancement. Et quand vous serez prêt à passer à l'échelle, vous serez déjà prêt pour la production.