Skip to content

Project Deployment with Nginx and SSL

  • Acceso SSH al servidor
  • Deployer instalado y configurado localmente
  • DNS del Dominio apuntando al servidor
  • Certbot instalado en el servidor
Terminal window
ssh user@ip_server

🔝 Volver al índice

  • Crear carpeta sudo mkdir -p /var/www/{mi_proyecto}
  • Asignar permisos y propietario:
Terminal window
# Asignar propietario (reemplaza 'tu_usuario' con tu usuario SSH)
sudo chown -R tu_usuario:www-data /var/www/{mi_proyecto}
# Establecer permisos adecuados
sudo chmod -R 755 /var/www/{mi_proyecto}

Nota: Usar www-data como grupo permite que Nginx lea los archivos correctamente.

🔝 Volver al índice

  • En tu proyecto local, configurar archivos .env.production y .env.development
Terminal window
DEPLOY_REPOSITORY=repository_path
DEPLOY_BRANCH=main
DEPLOY_HOST=ip_server
DEPLOY_USER=user_server
DEPLOY_PROJECT_PATH=/var/www/{mi_proyecto}
  • Verifica que estos archivos estén en .gitignore

🔝 Volver al índice

  • Ejecutar desde el proyecto local dep deploy production

Verifica que:

  • ✅ El despliegue se complete sin errores
  • ✅ La carpeta current se haya creado en /var/www/{mi_proyecto}/
  • ✅ Los archivos estén en /var/www/{mi_proyecto}/current/dist/

🔝 Volver al índice

  • Crear archivo de configuración sudo nano /etc/nginx/sites-available/{mi_proyecto}
  • Configuración nginx:
# HTTP to HTTPS redirect
server {
listen 80;
listen [::]:80;
server_name {mi_proyecto} www.{mi_proyecto};
# Permitir validación de Certbot
location ^~ /.well-known/acme-challenge/ {
default_type "text/plain";
root /var/www/{mi_proyecto}/current/dist;
}
location / {
return 301 https://{mi_proyecto}$request_uri;
}
}
# HTTPS www to non-www redirect
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name www.{mi_proyecto};
ssl_certificate /etc/letsencrypt/live/{mi_proyecto}/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/{mi_proyecto}/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
return 301 https://{mi_proyecto}$request_uri;
}
# Main HTTPS server
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name {mi_proyecto};
# SSL Configuration
ssl_certificate /etc/letsencrypt/live/{mi_proyecto}/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/{mi_proyecto}/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
# Directorio del build de Astro
root /var/www/{mi_proyecto}/current/dist;
index index.html;
# Logs
access_log /var/log/nginx/{mi_proyecto}.access.log;
error_log /var/log/nginx/{mi_proyecto}.error.log;
# Compresión Gzip
gzip on;
gzip_vary on;
gzip_types text/plain text/css text/xml text/javascript application/javascript application/json application/xml+rss application/rss+xml font/truetype font/opentype application/vnd.ms-fontobject image/svg+xml;
gzip_min_length 1000;
# Configuración para sitio estático (Astro)
location / {
try_files $uri $uri/ $uri.html /404.html =404;
}
# Caché agresivo para assets estáticos
location ~* \.(css|js|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot|webp|avif)$ {
expires 1y;
add_header Cache-Control "public, immutable";
access_log off;
}
# Bloquear archivos ocultos
location ~ /\. {
deny all;
access_log off;
log_not_found off;
}
# Headers 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 Referrer-Policy "strict-origin-when-cross-origin" always;
# CSP básico (ajustar según necesidades)
add_header Content-Security-Policy "default-src 'self' https: data: 'unsafe-inline' 'unsafe-eval'; img-src 'self' data: blob: https:; connect-src 'self' https: wss:; script-src 'self' 'unsafe-inline' 'unsafe-eval' https:;" always;
}

Importante: Solo un servidor puede tener la directiva default_server. Si encuentras otro, remuévela de tu configuración.

🔝 Volver al índice

  • Crear enlace simbólico sudo ln -s /etc/nginx/sites-available/{mi_proyecto} /etc/nginx/sites-enabled/{mi_proyecto}

🔝 Volver al índice

  • Comentar TODAS las líneas que empiezan con ssl_ en los bloques HTTPS (puerto 443, incluyendo ssl_certificate e include) Ejemplo de qué comentar:
# ssl_certificate /etc/letsencrypt/live/{mi_proyecto}/fullchain.pem;
# ssl_certificate_key /etc/letsencrypt/live/{mi_proyecto}/privkey.pem;
# include /etc/letsencrypt/options-ssl-nginx.conf;
# ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
  • Ejecutar sudo nginx -t
  • Resultado esperado:
Terminal window
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

Si hay errores:

  • Revisa la sintaxis del archivo
  • Verifica que las rutas existan
  • Comprueba los permisos

🔝 Volver al índice

  • Recarga nginx sudo systemctl reload nginx
  • Genera el certificado sudo certbot --nginx certonly -d {mi_proyecto} -d www.{mi_proyecto}
  • Configurar renovación automática
Terminal window
# Verificar que el timer esté activo
sudo systemctl status certbot.timer
# Probar renovación
sudo certbot renew --dry-run

🔝 Volver al índice

  • Descomenta las líneas SSL si las comentaste antes sudo nano /etc/nginx/sites-available/{mi_proyecto}
  • Verifica la configuración sudo nginx -t
  • Recarga Nginx sudo systemctl reload nginx
Terminal window
# Descomenta las líneas ssl_ si las comentaste antes
sudo nano /etc/nginx/sites-available/{mi_proyecto}
# Verifica la configuración
sudo nginx -t
# Recarga Nginx
sudo systemctl reload nginx

🔝 Volver al índice

Comprobar que el sitio funciona

Terminal window
# Estado de Nginx
sudo systemctl status nginx
# Ver logs en tiempo real
sudo tail -f /var/log/nginx/{mi_proyecto}.access.log
sudo tail -f /var/log/nginx/{mi_proyecto}.error.log

Pruebas desde navegador:

  • ✅ http://{mi_proyecto} → redirige a https
  • https://www.{mi_proyecto} → redirige a https://{mi_proyecto}
  • ✅ https://{mi_proyecto} → muestra el sitio
  • ✅ Certificado SSL válido (candado verde)

🔝 Volver al índice