Configuración de Nginx
Guía completa de configuración de Nginx para FeedbackPulse SaaS.
Requisitos Previos
- Nginx 1.18+
- PHP-FPM 8.4+
- Certificado SSL (recomendado)
Bloque de Servidor Básico
Crea una nueva configuración de Nginx:
sudo nano /etc/nginx/sites-available/feedbackpulse
Pega lo siguiente:
server {
listen 80;
listen [::]:80;
server_name yourdomain.com www.yourdomain.com;
root /var/www/feedbackpulse-saas/public;
index index.php index.html;
charset utf-8;
# Reescritura de URL de Laravel
location / {
try_files $uri $uri/ /index.php?$query_string;
}
# Procesamiento PHP
location ~ \.php$ {
fastcgi_pass unix:/var/run/php/php8.4-fpm.sock;
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
include fastcgi_params;
fastcgi_hide_header X-Powered-By;
}
# Denegar acceso a archivos ocultos
location ~ /\.(?!well-known).* {
deny all;
}
# Caché de archivos estáticos
location ~* \.(jpg|jpeg|png|gif|ico|css|js|svg|woff|woff2|ttf|eot)$ {
expires 30d;
add_header Cache-Control "public, immutable";
}
# Tamaño máximo de subida (para fotos, logos)
client_max_body_size 20M;
# Registros
access_log /var/log/nginx/feedbackpulse-access.log;
error_log /var/log/nginx/feedbackpulse-error.log;
}
Habilita el sitio:
sudo ln -s /etc/nginx/sites-available/feedbackpulse /etc/nginx/sites-enabled/
sudo rm /etc/nginx/sites-enabled/default # Eliminar sitio predeterminado (opcional)
sudo nginx -t # Probar configuración
sudo systemctl restart nginx
Bloque de Servidor HTTPS (con Let's Encrypt)
# Redirigir HTTP a HTTPS
server {
listen 80;
listen [::]:80;
server_name yourdomain.com www.yourdomain.com;
return 301 https://yourdomain.com$request_uri;
}
# Servidor HTTPS principal
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name yourdomain.com www.yourdomain.com;
root /var/www/feedbackpulse-saas/public;
index index.php index.html;
charset utf-8;
# Configuración SSL
ssl_certificate /etc/letsencrypt/live/yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/yourdomain.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers off;
# Cabeceras de Seguridad
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
# Reescritura de URL de Laravel
location / {
try_files $uri $uri/ /index.php?$query_string;
}
# Procesamiento PHP
location ~ \.php$ {
fastcgi_pass unix:/var/run/php/php8.4-fpm.sock;
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
include fastcgi_params;
fastcgi_hide_header X-Powered-By;
fastcgi_read_timeout 300;
}
# Denegar acceso a archivos ocultos (excepto .well-known para ACME)
location ~ /\.(?!well-known).* {
deny all;
}
# Caché de archivos estáticos
location ~* \.(jpg|jpeg|png|gif|ico|css|js|svg|woff|woff2|ttf|eot)$ {
expires 30d;
add_header Cache-Control "public, immutable";
}
client_max_body_size 20M;
access_log /var/log/nginx/feedbackpulse-access.log;
error_log /var/log/nginx/feedbackpulse-error.log;
}
Soporte de Subdominios con Comodín
Para subdominios de inquilino como acme.yourdomain.com:
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name yourdomain.com *.yourdomain.com;
root /var/www/feedbackpulse-saas/public;
# Usar un certificado SSL con comodín
ssl_certificate /etc/letsencrypt/live/yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/yourdomain.com/privkey.pem;
# ... el resto de la configuración es igual al bloque HTTPS anterior ...
index index.php index.html;
charset utf-8;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
fastcgi_pass unix:/var/run/php/php8.4-fpm.sock;
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
include fastcgi_params;
fastcgi_hide_header X-Powered-By;
}
location ~ /\.(?!well-known).* {
deny all;
}
client_max_body_size 20M;
}
Requisitos: Registro DNS con comodín + certificado SSL con comodín. Consulta Configuración de DNS con Comodín.
Configuración de PHP-FPM
Optimiza PHP-FPM para FeedbackPulse:
sudo nano /etc/php/8.4/fpm/pool.d/www.conf
Ajustes clave:
; Gestión de procesos
pm = dynamic
pm.max_children = 20
pm.start_servers = 5
pm.min_spare_servers = 3
pm.max_spare_servers = 10
pm.max_requests = 500
; Tiempos de espera
request_terminate_timeout = 300
; Límites de subida
php_admin_value[upload_max_filesize] = 20M
php_admin_value[post_max_size] = 25M
php_admin_value[memory_limit] = 256M
Reinicia PHP-FPM:
sudo systemctl restart php8.4-fpm
Laravel Forge / Ploi / RunCloud
Si usas un proveedor de servidor administrado:
Laravel Forge
- Crea un nuevo sitio con el dominio
yourdomain.com - Establece el Directorio Web en
/public - Despliega tu código (Git o subida)
- Forge configura Nginx correctamente de forma automática
- Habilita SSL mediante la pestaña "SSL" (Let's Encrypt)
Ploi
- Agrega un nuevo sitio → introduce tu dominio
- Establece la raíz en
/public - Despliega el código
- El SSL se configura automáticamente
RunCloud
- Crea una aplicación web → selecciona "PHP" → introduce el dominio
- Establece la ruta pública en
public - Despliega mediante Git o el administrador de archivos
- Habilita SSL
Verificar la Configuración de Nginx
# Probar sintaxis
sudo nginx -t
# Verificar si PHP-FPM está funcionando
sudo systemctl status php8.4-fpm
# Verificar si Nginx está funcionando
sudo systemctl status nginx
# Ver qué socket PHP-FPM está en uso
ls /var/run/php/
# Reiniciar todo
sudo systemctl restart php8.4-fpm nginx
Problemas Comunes de Nginx
| Problema | Solución |
|---|---|
| 502 Bad Gateway | PHP-FPM no está funcionando o la ruta del socket es incorrecta. Verifica que fastcgi_pass coincida con tu socket PHP-FPM. |
| 404 en todas las rutas | Falta try_files $uri $uri/ /index.php?$query_string; en el bloque de ubicación. |
| 413 Request Entity Too Large | Aumenta client_max_body_size (el valor predeterminado es 1M). |
| "File not found" | Verifica que root apunte al directorio public/ y que $realpath_root se use en SCRIPT_FILENAME. |
| Página en blanco | Revisa storage/logs/laravel.log y /var/log/nginx/feedbackpulse-error.log. |