Automatizamos la instalación de WordPress con NGINX Unit y Ubuntu

Automatizamos la instalación de WordPress con NGINX Unit y Ubuntu

Hay una gran cantidad de materiales sobre la instalación de WordPress; una búsqueda en Google con las palabras clave "instalación de WordPress" arrojará alrededor de medio millón de resultados. Sin embargo, entre ellos realmente hay muy pocas guías adecuadas que permitan instalar y configurar WordPress y el sistema operativo subyacente de tal manera que puedan mantenerse durante un período prolongado. Es posible que la configuración adecuada dependa en gran medida de las necesidades específicas, o que se deba a que una explicación detallada hace que el artículo sea difícil de leer.

En este artículo, intentaremos combinar lo mejor de ambos enfoques, proporcionando un script en bash para la instalación automática de WordPress en Ubuntu, y lo revisaremos, explicando qué hace cada parte, así como los compromisos que asumimos durante su desarrollo. Si eres un usuario experimentado, puedes saltarte el texto del artículo y simplemente tomar el script para modificarlo y usarlo en tus entornos. El script produce una instalación personalizable de WordPress con soporte para Let's Encrypt, funcionando sobre NGINX Unit y apta para aplicaciones industriales.

La arquitectura diseñada para desplegar WordPress usando NGINX Unit está descrita en un artículo anterior, ahora también configuraremos adicionalmente aspectos que no fueron abordados allí (como en muchas otras guías):

  • WordPress CLI
  • Let's Encrypt y certificados TLS/SSL
  • Actualización automática de certificados
  • Caching de NGINX
  • Compresión de NGINX
  • Soporte para HTTPS y HTTP/2
  • Automatización del proceso

El artículo describirá la instalación en un solo servidor, donde se alojarán simultáneamente un servidor de procesamiento de estáticos, un servidor de procesamiento PHP y una base de datos. La instalación con soporte para múltiples hosts virtuales y servicios es un tema potencial para el futuro. Si deseas que escribamos sobre algo que no esté en estos artículos, déjanos un comentario.

Requisitos

  • Contenedor de servidor (LXC o LXD), máquina virtual o un servidor físico normal, con no menos de 512 MB de RAM y con Ubuntu 18.04 o superior instalado.
  • Puertos 80 y 443 accesibles desde internet
  • Nombre de dominio asociado a la dirección IP pública de este servidor
  • Acceso con privilegios de root (sudo).

Resumen de la arquitectura

La arquitectura es la misma que se describió anteriormente, una aplicación web de tres niveles. Consiste en scripts PHP que se ejecutan en un manejador PHP y archivos estáticos procesados por un servidor web.

Automatizamos la instalación de WordPress con NGINX Unit y Ubuntu

El diseño de la red de oficina, por supuesto, debe satisfacer los requisitos generales que se han tratado.

  • Muchos comandos de configuración en el script están envueltos en condiciones (if) para la idempotencia: se puede ejecutar el script varias veces sin riesgo de cambiar configuraciones que ya están listas.
  • El script trata de instalar el software desde repositorios, por lo que puede aplicar actualizaciones del sistema en un solo comando (apt upgrade para Ubuntu).
  • Los comandos intentan detectar que se están ejecutando en un contenedor para modificar sus configuraciones en consecuencia.
  • Para especificar el número de procesos/hilos que se ejecutan en la configuración, el script intenta adivinar los parámetros de configuración automatizados para trabajar en contenedores, máquinas virtuales y servidores físicos.
  • Al describir las configuraciones, siempre pensamos primero en la automatización, que, con suerte, se convertirá en la base para crear tu propia infraestructura como código.
  • Todos los comandos se ejecutan desde el usuario root, porque modifican configuraciones del sistema principales, pero WordPress mismo se ejecuta desde un usuario normal.

Configuración de variables de entorno

Establezca las siguientes variables de entorno antes de ejecutar el script:

  • WORDPRESS_DB_PASSWORD — la contraseña de la base de datos de WordPress
  • WORDPRESS_ADMIN_USER — el nombre del administrador de WordPress
  • WORDPRESS_ADMIN_PASSWORD — la contraseña del administrador de WordPress
  • WORDPRESS_ADMIN_EMAIL — el correo electrónico del administrador de WordPress
  • WORDPRESS_URL — la URL completa del sitio de WordPress, comenzando con https://.
  • LETS_ENCRYPT_STAGING — vacío por defecto, pero al establecerlo en 1, utilizará los servidores de pruebas de Let’s Encrypt, necesarios para solicitar certificados con frecuencia al probar tus configuraciones; de lo contrario, Let’s Encrypt puede bloquear temporalmente tu dirección IP debido a una alta cantidad de solicitudes.

El script verifica que estas variables relacionadas con WordPress estén establecidas y se detiene si no lo están.
Las líneas del script 572-576 verifican el valor LETS_ENCRYPT_STAGING.

Configuración de variables de entorno derivadas

El script en las líneas 55-61 establece las siguientes variables de entorno, ya sea en un valor fijo o utilizando el valor obtenido de las variables establecidas en la sección anterior:

  • DEBIAN_FRONTEND="noninteractive" — informa a las aplicaciones que se están ejecutando en un script y no hay posibilidad de interacción con el usuario.
  • WORDPRESS_CLI_VERSION="2.4.0" — versión de la aplicación WordPress CLI.
  • WORDPRESS_CLI_MD5= "dedd5a662b80cda66e9e25d44c23b25c" — suma de verificación del archivo ejecutable de WordPress CLI 2.4.0 (la versión se indica en la variable WORDPRESS_CLI_VERSION). El script en la línea 162 utiliza este valor para verificar que se ha descargado el archivo correcto de WordPress CLI.
  • UPLOAD_MAX_FILESIZE="16M" — tamaño máximo del archivo que se puede subir a WordPress. Esta configuración se utiliza en varios lugares, por lo que es más sencillo definirla en un solo lugar.
  • TLS_HOSTNAME= "$(echo ${WORDPRESS_URL} | cut -d'\/' -f3)" — nombre de host del sistema, extraído de la variable WORDPRESS_URL. Se utiliza para obtener los certificados TLS/SSL correspondientes de Let's Encrypt, así como para la verificación interna de WordPress.
  • NGINX_CONF_DIR="\/etc\/nginx" — ruta al directorio con la configuración de NGINX, incluido el archivo principal nginx.conf.
  • CERT_DIR="\/etc\/letsencrypt\/live\/${TLS_HOSTNAME}" — ruta a los certificados de Let's Encrypt para el sitio de WordPress, obtenida de la variable TLS_HOSTNAME.

Asignación del nombre de host al servidor de WordPress

El script establece el nombre de host del servidor para que el valor coincida con el nombre de dominio del sitio. No es obligatorio, pero facilita el envío de correo saliente a través de SMTP cuando se configura un único servidor, como lo hace el script.

código del script

# Change the hostname to be the same as the WordPress hostname
if [ ! "$(hostname)" == "${TLS_HOSTNAME}" ]; then
  echo " Changing hostname to ${TLS_HOSTNAME}"
  hostnamectl set-hostname "${TLS_HOSTNAME}"
fi

Añadiendo el nombre de host en \/etc\/hosts

Suplemento WP‑Cron se utiliza para ejecutar tareas periódicas, requiere que WordPress pueda acceder a sí mismo a través de HTTP. Para asegurarse de que WP-Cron funciona correctamente en todos los entornos, el script añade una línea al archivo /etc/hosts, de modo que WordPress pueda acceder a sí mismo a través de la interfaz loopback:

código del script

# Add the hostname to /etc/hosts
if [ "$(grep -m1 "${TLS_HOSTNAME}" /etc/hosts)" = "" ]; then
  echo " Adding hostname ${TLS_HOSTNAME} to /etc/hosts so that WordPress can ping itself"
  printf "::1 %sn127.0.0.1 %sn" "${TLS_HOSTNAME}" "${TLS_HOSTNAME}" >> /etc/hosts
fi

Instalación de herramientas requeridas para los siguientes pasos

El resto del script requiere algunos programas y supone que los repositorios están actualizados. Actualizamos la lista de repositorios y luego instalamos las herramientas necesarias:

código del script

# Make sure tools needed for install are present
echo " Installing prerequisite tools"
apt-get -qq update
apt-get -qq install -y 
  bc 
  ca-certificates 
  coreutils 
  curl 
  gnupg2 
  lsb-release

Añadiendo los repositorios de NGINX Unit y NGINX

El script instala NGINX Unit y NGINX de código abierto desde los repositorios oficiales de NGINX, para asegurarse de que se utilizan versiones con las últimas actualizaciones de seguridad y correcciones de errores.

El script añade el repositorio de NGINX Unit, y luego el repositorio de NGINX, añadiendo la clave de los repositorios y los archivos de configuración apt, que establecen el acceso a los repositorios a través de Internet.

La instalación real de NGINX Unit y NGINX se lleva a cabo en la siguiente sección. Añadimos previamente los repositorios para no actualizar los metadatos varias veces, lo que hace que la instalación sea más rápida.

código del script

# Install the NGINX Unit repository
if [ ! -f /etc/apt/sources.list.d/unit.list ]; then
  echo " Installing NGINX Unit repository"
  curl -fsSL https://nginx.org/keys/nginx_signing.key | apt-key add -
  echo "deb https://packages.nginx.org/unit/ubuntu/ $(lsb_release -cs) unit" > /etc/apt/sources.list.d/unit.list
fi

# Install the NGINX repository
if [ ! -f /etc/apt/sources.list.d/nginx.list ]; then
  echo " Installing NGINX repository"
  curl -fsSL https://nginx.org/keys/nginx_signing.key | apt-key add -
  echo "deb https://nginx.org/packages/mainline/ubuntu $(lsb_release -cs) nginx" > /etc/apt/sources.list.d/nginx.list
fi

Instalación de NGINX, NGINX Unit, PHP MariaDB, Certbot (Let’s Encrypt) y sus dependencias

Una vez que se han agregado todos los repositorios, actualizamos los metadatos e instalamos las aplicaciones. Los paquetes que se instalan mediante el script también incluyen las extensiones PHP recomendadas al iniciar WordPress.org

código del script

echo " Actualizando metadatos del repositorio"
apt-get -qq update

# Instalar PHP con dependencias y NGINX Unit
echo " Instalando PHP, NGINX Unit, NGINX, Certbot y MariaDB"
apt-get -qq install -y --no-install-recommends 
  certbot 
  python3-certbot-nginx 
  php-cli 
  php-common 
  php-bcmath 
  php-curl 
  php-gd 
  php-imagick 
  php-mbstring 
  php-mysql 
  php-opcache 
  php-xml 
  php-zip 
  ghostscript 
  nginx 
  unit 
  unit-php 
  mariadb-server

Configuración de PHP para su uso con NGINX Unit y WordPress

El script crea un archivo de configuración en el directorio conf.d. Aquí se establece el tamaño máximo de los archivos que se pueden cargar para PHP, se habilita la salida de errores de PHP en STDERR, de modo que se registren en el registro de NGINX Unit, y también se reinicia NGINX Unit.

código del script

# Find the major and minor PHP version so that we can write to its conf.d directory
PHP_MAJOR_MINOR_VERSION="$(php -v | head -n1 | cut -d' ' -f2 | cut -d'.' -f1,2)"

if [ ! -f "/etc/php/${PHP_MAJOR_MINOR_VERSION}/embed/conf.d/30-wordpress-overrides.ini" ]; then
  echo " Configuring PHP for use with NGINX Unit and WordPress"
  # Add PHP configuration overrides
  cat > "/etc/php/${PHP_MAJOR_MINOR_VERSION}/embed/conf.d/30-wordpress-overrides.ini" << EOM
; Set a larger maximum upload size so that WordPress can handle
; bigger media files.
upload_max_filesize=${UPLOAD_MAX_FILESIZE}
post_max_size=${UPLOAD_MAX_FILESIZE}
; Write error log to STDERR so that error messages show up in the NGINX Unit log
error_log=/dev/stderr
EOM
fi

# Restart NGINX Unit because we have reconfigured PHP
echo " Restarting NGINX Unit"
service unit restart

Configuración de la base de datos MariaDB para WordPress

Elegimos MariaDB en lugar de MySQL, ya que cuenta con una comunidad más activa, además puede ofrecer un rendimiento más alto por defecto (probablemente, aquí todo es más sencillo: para instalar MySQL, hay que agregar otro repositorio, nota del traductor).

El script crea una nueva base de datos y genera credenciales de acceso para WordPress a través de la interfaz loopback:

código del script

# Set up the WordPress database
echo " Configuring MariaDB for WordPress"
mysqladmin create wordpress || echo "Ignoring above error because database may already exist"
mysql -e "GRANT ALL PRIVILEGES ON wordpress.* TO "wordpress"@"localhost" IDENTIFIED BY "$WORDPRESS_DB_PASSWORD"; FLUSH PRIVILEGES;"

Instalación de la herramienta WordPress CLI

En este paso, el script instala la herramienta WP-CLI. Con ella, se puede instalar y gestionar la configuración de WordPress sin necesidad de editar archivos manualmente, actualizar la base de datos o acceder al panel de control. También permite instalar temas y complementos, así como realizar actualizaciones de WordPress.

código del script

if [ ! -f /usr/local/bin/wp ]; then
  # Instalar la herramienta WordPress CLI
  echo " Instalando la herramienta WordPress CLI"
  curl --retry 6 -Ls "https://github.com/wp-cli/wp-cli/releases/download/v${WORDPRESS_CLI_VERSION}/wp-cli-${WORDPRESS_CLI_VERSION}.phar" > /usr/local/bin/wp
  echo "$WORDPRESS_CLI_MD5 /usr/local/bin/wp" | md5sum -c -
  chmod +x /usr/local/bin/wp
fi

Instalación y configuración de WordPress

El script instala la última versión de WordPress en el directorio /var/www/wordpress, y además modifica la configuración:

  • La conexión a la base de datos se realiza a través de un socket de dominio unix en lugar de TCP en loopback para reducir el tráfico TCP.
  • WordPress agrega un prefijo https:// al URL si los clientes se conectan a NGINX a través del protocolo HTTPS, y también envía el hostname remoto (como lo proporciona NGINX) a PHP. Aplicamos un fragmento de código para configurar esto.
  • WordPress necesita HTTPS para iniciar sesión
  • La estructura de URL por defecto se basa en los recursos
  • Se establecen los permisos correctos en el sistema de archivos para el directorio de WordPress.

código del script

if [ ! -d /var/www/wordpress ]; then
  # Crear directorios de WordPress
  mkdir -p /var/www/wordpress
  chown -R www-data:www-data /var/www

  # Descargar WordPress usando la CLI de WordPress
  echo " Instalando WordPress"
  su -s /bin/sh -c 'wp --path=/var/www/wordpress core download' www-data

  WP_CONFIG_CREATE_CMD="wp --path=/var/www/wordpress config create --extra-php --dbname=wordpress --dbuser=wordpress --dbhost="localhost:/var/run/mysqld/mysqld.sock" --dbpass="${WORDPRESS_DB_PASSWORD}""

  # Este fragmento se inyecta en el archivo wp-config.php cuando se crea;
  # informa a WordPress que estamos detrás de un proxy inverso y, por lo tanto,
  # le permite generar enlaces usando HTTPS
  cat > /tmp/wp_forwarded_for.php << 'EOM'
/* Activa HTTPS 'on' si HTTP_X_FORWARDED_PROTO coincide con 'https' */
if (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && strpos($_SERVER['HTTP_X_FORWARDED_PROTO'], 'https') !== false) {
    $_SERVER['HTTPS'] = 'on';
}
if (isset($_SERVER['HTTP_X_FORWARDED_HOST'])) {
    $_SERVER['HTTP_HOST'] = $_SERVER['HTTP_X_FORWARDED_HOST'];
}
EOM

  # Crear configuración de WordPress
  su -s /bin/sh -p -c "cat /tmp/wp_forwarded_for.php | ${WP_CONFIG_CREATE_CMD}" www-data
  rm /tmp/wp_forwarded_for.php
  su -s /bin/sh -p -c "wp --path=/var/www/wordpress config set 'FORCE_SSL_ADMIN' 'true'" www-data

  # Instalar WordPress
  WP_SITE_INSTALL_CMD="wp --path=/var/www/wordpress core install --url="${WORDPRESS_URL}" --title="${WORDPRESS_SITE_TITLE}" --admin_user="${WORDPRESS_ADMIN_USER}" --admin_password="${WORDPRESS_ADMIN_PASSWORD}" --admin_email="${WORDPRESS_ADMIN_EMAIL}" --skip-email"
  su -s /bin/sh -p -c "${WP_SITE_INSTALL_CMD}" www-data

  # Establecer la estructura de enlaces permanentes a un valor predeterminado razonable que no está en la interfaz
  su -s /bin/sh -p -c "wp --path=/var/www/wordpress option update permalink_structure '/%year%/%monthnum%/%postname%/'" www-data

  # Eliminar el archivo de muestra porque es innecesario y podría ser un problema de seguridad
  rm /var/www/wordpress/wp-config-sample.php

  # Asegurar que los permisos de WordPress sean correctos
  find /var/www/wordpress -type d -exec chmod g+s {} ;
  chmod g+w /var/www/wordpress/wp-content
  chmod -R g+w /var/www/wordpress/wp-content/themes
  chmod -R g+w /var/www/wordpress/wp-content/plugins
fi

Configuración de NGINX Unit

El script configura NGINX Unit para ejecutar PHP y manejar rutas de WordPress, aislando el espacio de nombres de los procesos de PHP y optimizando la configuración del rendimiento. Hay tres funciones que vale la pena mencionar:

  • El soporte para espacios de nombres se determina por una condición, basada en la verificación de que el script se está ejecutando en un contenedor. Esto es necesario, ya que la mayoría de las configuraciones de contenedores no admiten ejecuciones de contenedores anidados.
  • Si hay soporte para espacios de nombres, se desactiva el espacio de nombres network. Esto es necesario para permitir que WordPress se conecte simultáneamente a los endpoints y sea accesible en Internet.
  • El número máximo de procesos se determina de la siguiente manera: (Memoria disponible para MariaDB y NGINX Unit en ejecución) / (límite de memoria en PHP + 5)
    Este valor se establece en la configuración de NGINX Unit.

Esto también significa que siempre hay al menos dos procesos PHP en funcionamiento, lo cual es importante, ya que WordPress realiza muchas solicitudes asincrónicas a sí mismo, y sin procesos adicionales, la ejecución de, por ejemplo, WP-Cron, fallará. Es posible que desee aumentar o disminuir estos límites, basado en su configuración local, porque los ajustes creados aquí son conservadores. En la mayoría de los sistemas de producción, los ajustes están entre 10 y 100.

código del script

if [ "${container:-unknown}" != "lxc" ] && [ "$(grep -m1 -a container=lxc /proc/1/environ | tr -d ' ')" == "" ]; then
  NAMESPACES='"namespaces": {
        "cgroup": true,
        "credential": true,
        "mount": true,
        "network": false,
        "pid": true,
        "uname": true
    }'
else
  NAMESPACES='"namespaces": {}'
fi

PHP_MEM_LIMIT="$(grep 'memory_limit' /etc/php/7.4/embed/php.ini | tr -d ' ' | cut -f2 -d= | numfmt --from=iec)"
AVAIL_MEM="$(grep MemAvailable /proc/meminfo | tr -d ' kB' | cut -f2 -d: | numfmt --from-unit=K)"
MAX_PHP_PROCESSES="$(echo "${AVAIL_MEM}/${PHP_MEM_LIMIT}+5" | bc)"
echo " Calculado el número máximo de procesos PHP como ${MAX_PHP_PROCESSES}. Es recomendable ajustar este valor debido a variaciones en su configuración. No es inusual ver valores entre 10-100 en configuraciones de producción."

echo " Configurando NGINX Unit para usar PHP y WordPress"
cat > /tmp/wordpress.json << EOM
{
  "settings": {
    "http": {
      "header_read_timeout": 30,
      "body_read_timeout": 30,
      "send_timeout": 30,
      "idle_timeout": 180,
      "max_body_size": $(numfmt --from=iec ${UPLOAD_MAX_FILESIZE})
    }
  },
  "listeners": {
    "127.0.0.1:8080": {
      "pass": "routes/wordpress"
    }
  },
  "routes": {
    "wordpress": [
      {
        "match": {
          "uri": [
            "*.php",
            "*.php/*",
            "/wp-admin/"
          ]
        },
        "action": {
          "pass": "applications/wordpress/direct"
        }
      },
      {
        "action": {
          "share": "/var/www/wordpress",
          "fallback": {
            "pass": "applications/wordpress/index"
          }
        }
      }
    ]
  },
  "applications": {
    "wordpress": {
      "type": "php",
      "user": "www-data",
      "group": "www-data",
      "processes": {
        "max": ${MAX_PHP_PROCESSES},
        "spare": 1
      },
      "isolation": {
        ${NAMESPACES}
      },
      "targets": {
        "direct": {
          "root": "/var/www/wordpress/"
        },
        "index": {
          "root": "/var/www/wordpress/",
          "script": "index.php"
        }
      }
    }
  }
}
EOM

curl -X PUT --data-binary @/tmp/wordpress.json --unix-socket /run/control.unit.sock http://localhost/config

Configuración de NGINX

Configuración de los parámetros principales de NGINX

El script crea un directorio para la caché de NGINX y luego crea el archivo principal de configuración nginx.conf. Tenga en cuenta el número de procesos manejadores y la asignación del tamaño máximo de archivo para cargas. También hay una línea que conecta el archivo de configuración de compresión, que se definirá en la siguiente sección, seguida de configuraciones de caché.

código del script

# Make directory for NGINX cache
mkdir -p /var/cache/nginx/proxy

echo " Configuring NGINX"
cat > ${NGINX_CONF_DIR}/nginx.conf << EOM
user nginx;
worker_processes auto;
error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;
events {
    worker_connections  1024;
}
http {
    include       ${NGINX_CONF_DIR}/mime.types;
    default_type  application/octet-stream;
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';
    access_log  /var/log/nginx/access.log  main;
    sendfile        on;
    client_max_body_size ${UPLOAD_MAX_FILESIZE};
    keepalive_timeout  65;
    # gzip settings
    include ${NGINX_CONF_DIR}/gzip_compression.conf;
    # Cache settings
    proxy_cache_path /var/cache/nginx/proxy
        levels=1:2
        keys_zone=wp_cache:10m
        max_size=10g
        inactive=60m
        use_temp_path=off;
    include ${NGINX_CONF_DIR}/conf.d/*.conf;
}
EOM

Configuración de la compresión de NGINX

La compresión de contenido en tiempo real antes de enviarlo a los clientes es una excelente manera de mejorar el rendimiento del sitio web, pero solo si la compresión está configurada correctamente. Esta sección del script se basa en la configuración desde aquí.

código del script

cat > ${NGINX_CONF_DIR}/gzip_compression.conf << 'EOM'
# Crédito: https://github.com/h5bp/server-configs-nginx/
# ----------------------------------------------------------------------
# | Compresión                                                        |
# ----------------------------------------------------------------------
# https://nginx.org/en/docs/http/ngx_http_gzip_module.html
# Habilitar la compresión gzip.
# Predeterminado: off
gzip on;
# Nivel de compresión (1-9).
# 5 es un compromiso perfecto entre tamaño y uso de CPU, ofreciendo alrededor del 75%
# de reducción para la mayoría de los archivos ASCII (casi idéntico al nivel 9).
# Predeterminado: 1
gzip_comp_level 6;
# No comprimir nada que ya sea pequeño y poco probable que se reduzca mucho, si es que
# (el predeterminado es 20 bytes, lo cual es malo ya que suele llevar a archivos más grandes
# después de aplicar gzip).
# Predeterminado: 20
gzip_min_length 256;
# Comprimir datos incluso para clientes que se conectan a nosotros a través de proxies,
# identificados por el encabezado "Via" (requerido para CloudFront).
# Predeterminado: off
gzip_proxied any;
# Indicar a los proxies que almacenen en caché tanto la versión gzipped como la regular de un recurso
# siempre que el encabezado de capacidades Accept-Encoding del cliente varíe;
# Evita el problema donde un cliente no capaz de gzip (que es extremadamente raro
# hoy en día) mostraría caracteres ilegibles si su proxy les da la versión gzipped.
# Predeterminado: off
gzip_vary on;
# Comprimir toda la salida etiquetada con uno de los siguientes tipos MIME.
# `text/html` siempre es comprimido por el módulo gzip.
# Predeterminado: text/html
gzip_types
  application/atom+xml
  application/geo+json
  application/javascript
  application/x-javascript
  application/json
  application/ld+json
  application/manifest+json
  application/rdf+xml
  application/rss+xml
  application/vnd.ms-fontobject
  application/wasm
  application/x-web-app-manifest+json
  application/xhtml+xml
  application/xml
  font/eot
  font/otf
  font/ttf
  image/bmp
  image/svg+xml
  text/cache-manifest
  text/calendar
  text/css
  text/javascript
  text/markdown
  text/plain
  text/xml
  text/vcard
  text/vnd.rim.location.xloc
  text/vtt
  text/x-component
  text/x-cross-domain-policy;
EOM

Configuración de NGINX para WordPress

A continuación, el script crea un archivo de configuración para WordPress default.conf en el directorio conf.d. Aquí se configuran:

  • Activación de certificados TLS obtenidos de Let’s Encrypt a través de Certbot (su configuración será en la siguiente sección)
  • Configuración de parámetros de seguridad TLS, basada en recomendaciones de Let’s Encrypt
  • Activación de almacenamiento en caché para solicitudes omitidas durante 1 hora por defecto
  • Desactivación del registro de acceso, así como del registro de errores, si no se encuentra el archivo, para dos archivos comúnmente solicitados: favicon.ico y robots.txt
  • Prohibición del acceso a archivos ocultos y ciertos archivos .php, para prevenir el acceso no autorizado o la ejecución involuntaria
  • Desactivación del registro de acceso para archivos estáticos y de fuentes
  • Establecer encabezado Access-Control-Allow-Origin para archivos de fuentes
  • Agregar enrutamiento para index.php y otros archivos estáticos.

código del script

cat > ${NGINX_CONF_DIR}/conf.d/default.conf << EOM
upstream unit_php_upstream {
    server 127.0.0.1:8080;
    keepalive 32;
}
server {
    listen 80;
    listen [::]:80;
    # ACME-challenge utilizado por Certbot para Let's Encrypt
    location ^~ /.well-known/acme-challenge/ {
      root /var/www/certbot;
    }
    location / {
      return 301 https://${TLS_HOSTNAME}$request_uri;
    }
}
server {
    listen      443 ssl http2;
    listen [::]:443 ssl http2;
    server_name ${TLS_HOSTNAME};
    root        /var/www/wordpress/;
    # Configuración de Let's Encrypt
    ssl_certificate         ${CERT_DIR}/fullchain.pem;
    ssl_certificate_key     ${CERT_DIR}/privkey.pem;
    ssl_trusted_certificate ${CERT_DIR}/chain.pem;
    include ${NGINX_CONF_DIR}/options-ssl-nginx.conf;
    ssl_dhparam ${NGINX_CONF_DIR}/ssl-dhparams.pem;
    # OCSP stapling
    ssl_stapling on;
    ssl_stapling_verify on;
    # Caching de proxy
    proxy_cache wp_cache;
    proxy_cache_valid 200 302 1h;
    proxy_cache_valid 404 1m;
    proxy_cache_revalidate on;
    proxy_cache_background_update on;
    proxy_cache_lock on;
    proxy_cache_use_stale error timeout http_500 http_502 http_503 http_504;
    location = /favicon.ico {
        log_not_found off;
        access_log off;
    }
    location = /robots.txt {
        allow all;
        log_not_found off;
        access_log off;
    }

    # Denegar todos los intentos de acceso a archivos ocultos como .htaccess, .htpasswd,
    # .DS_Store (Mac)
    # Mantener registros de las solicitudes para analizarlos después (o para pasarlos a utilidades de firewall
    # como fail2ban)
    location ~ /. {
        deny all;
    }
    # Denegar acceso a cualquier archivo con una extensión .php en el directorio de cargas;
    # funciona en instalaciones de subdirectorios y también en redes multi-sitio.
    # Mantener registros de las solicitudes para analizarlos después (o para pasarlos a utilidades de firewall
    # como fail2ban).
    location ~* /(?:uploads|files)/.*.php$ {
        deny all;
    }
    # WordPress: denegar acceso a archivos PHP en wp-content, wp-includes
    location ~* ^/(?:wp-content|wp-includes)/.*.php$ {
        deny all;
    }
    # Denegar acceso público a wp-config.php
    location ~* wp-config.php {
        deny all;
    }
    # No registrar acceso para activos estáticos, medios
    location ~* .(?:css(.map)?|js(.map)?|jpe?g|png|gif|ico|cur|heic|webp|tiff?|mp3|m4a|aac|ogg|midi?|wav|mp4|mov|webm|mpe?g|avi|ogv|flv|wmv)$ {
        access_log off;
    }
    location ~* .(?:svgz?|ttf|ttc|otf|eot|woff2?)$ {
        add_header Access-Control-Allow-Origin "*";
        access_log off;
    }
    location / {
        try_files $uri @index_php;
    }
    location @index_php {
        proxy_socket_keepalive on;
        proxy_http_version 1.1;
        proxy_set_header Connection "";
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header Host $host;
        proxy_pass       http://unit_php_upstream;
    }
    location ~* .php$ {
        proxy_socket_keepalive on;
        proxy_http_version 1.1;
        proxy_set_header Connection "";
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header Host $host;
        try_files        $uri =404;
        proxy_pass       http://unit_php_upstream;
    }
}
EOM

Configuración de Certbot para certificados de Let’s Encrypt y su renovación automática

Certbot — una herramienta gratuita de Electronic Frontier Foundation (EFF) que permite obtener y actualizar automáticamente certificados TLS de Let’s Encrypt. El script realiza las siguientes acciones para configurar Certbot para manejar certificados de Let’s Encrypt en NGINX:

  • Detiene NGINX
  • Descarga los parámetros TLS recomendados
  • Inicia Certbot para obtener certificados para el sitio
  • Reinicia NGINX para utilizar los certificados
  • Configura la ejecución diaria de Certbot a las 3:24 de la mañana para verificar la necesidad de actualizar certificados, así como, si es necesario, descargar nuevos certificados y reiniciar NGINX.

código del script

echo " Deteniendo NGINX para configurar Let's Encrypt"
service nginx stop

mkdir -p /var/www/certbot
chown www-data:www-data /var/www/certbot
chmod g+s /var/www/certbot

if [ ! -f ${NGINX_CONF_DIR}/options-ssl-nginx.conf ]; then
  echo " Descargando parámetros TLS recomendados"
  curl --retry 6 -Ls -z "Tue, 14 Apr 2020 16:36:07 GMT" 
    -o "${NGINX_CONF_DIR}/options-ssl-nginx.conf" 
    "https://raw.githubusercontent.com/certbot/certbot/master/certbot-nginx/certbot_nginx/_internal/tls_configs/options-ssl-nginx.conf" 
    || echo "No se pudo descargar la última options-ssl-nginx.conf"
fi

if [ ! -f ${NGINX_CONF_DIR}/ssl-dhparams.pem ]; then
  echo " Descargando parámetros DH TLS recomendados"
  curl --retry 6 -Ls -z "Tue, 14 Apr 2020 16:49:18 GMT" 
    -o "${NGINX_CONF_DIR}/ssl-dhparams.pem" 
    "https://raw.githubusercontent.com/certbot/certbot/master/certbot/certbot/ssl-dhparams.pem" 
    || echo "No se pudo descargar la última ssl-dhparams.pem"
fi

# Si tls_certs_init.sh no se ha ejecutado antes, eliminar los certificados autofirmados
if [ ! -d "/etc/letsencrypt/accounts" ]; then
  echo " Eliminando certificados autofirmados"
  rm -rf "${CERT_DIR}"
fi

if [ "" = "${LETS_ENCRYPT_STAGING:-}" ] || [ "0" = "${LETS_ENCRYPT_STAGING}" ]; then
  CERTBOT_STAGING_FLAG=""
else
  CERTBOT_STAGING_FLAG="--staging"
fi

if [ ! -f "${CERT_DIR}/fullchain.pem" ]; then
  echo " Generando certificados con Let's Encrypt"
  certbot certonly --standalone 
         -m "${WORDPRESS_ADMIN_EMAIL}" 
         ${CERTBOT_STAGING_FLAG} 
         --agree-tos --force-renewal --non-interactive 
         -d "${TLS_HOSTNAME}"
fi

echo " Iniciando NGINX para usar la nueva configuración"
service nginx start

# Escribir crontab para renovación periódica de certificados Let's Encrypt
if [ "$(crontab -l | grep -m1 'certbot renew')" == "" ]; then
  echo " Agregando certbot a crontab para renovación automática de Let's Encrypt"
  (crontab -l 2>/dev/null; echo "24 3 * * * certbot renew --nginx --post-hook 'service nginx reload' ") | crontab -
fi

Configuración adicional de su sitio

Ya hemos mencionado cómo nuestro script configura NGINX y NGINX Unit para servir un sitio listo para producción con TLS SSL habilitado. También puede, dependiendo de sus necesidades, agregar en el futuro:

  • Soporte Brotli, compresión mejorada en tiempo real a través de HTTPS
  • ModSecurity con reglas para WordPress, para prevenir ataques automáticos a su sitio
  • Copias de seguridad para WordPress, apropiado para usted
  • Protección usando AppArmor (en Ubuntu)
  • Postfix o msmtp, para que WordPress pueda enviar correo
  • Revisa tu sitio web para que entiendas cuánta tráfico puede soportar.

Para un rendimiento aún mejor del sitio, te recomendamos actualizar a NGINX Plus, nuestro producto comercial de nivel empresarial basado en código abierto de NGINX. Sus suscriptores recibirán un módulo de Brotli que se carga dinámicamente, así como (por un costo adicional) NGINX ModSecurity WAF. También ofrecemos NGINX App Protect, un módulo WAF para NGINX Plus, basado en tecnología líder en seguridad de F5.

N.B. Para el soporte de un sitio web de alta carga, puedes contactar a nuestros especialistas Southbridge. Aseguraremos un funcionamiento rápido y confiable de tu sitio o servicio bajo cualquier carga.

Fuente: habr.com

Compra un hosting fiable para sitios web con protección contra DDoS, servidores VPS VDS 🔥 Compra un hosting fiable para sitios web con protección contra DDoS, servidores VPS VDS | ProHoster