WordPress + apache + varnish + frontal nginx

Hoy os traigo un post completito sobre la parte de sistemas de WordPress.

Hace ya demasiados días que tenía pendiente la actualización de las debian que alojaban mi wordpress multisite y la base de datos mysql (que las tengo en dos contenedores separados). No digo las versiones porqué se me cae la cara de vergüenza :P

El wordpress que tengo en La Mar de Bits tiene por delante 2 frontales haciendo de proxy http con nginx (donde además hago la gestión de los certificados de letsencrypt y redirección de puerto 80 a 443). Éstos apuntan al puerto expuesto de Varnish (servicio de cache) dentro del contenedor donde está el wordpress (puerto 6081). El varnish apunta en el apache y el apache sirve en el puerto 80 las páginas web de wordpress.

Vamos un cristo para llegar al wordpress que no veas :)

Voy a ir detallando las configuraciones que tengo en cada una de las partes de esta máquina

nginx (frontales)

Estas dos maquinas son las que están expuestas a internet y comparten el directorio de configuración gracias a glusterfs.

Para exponer ambas maquinas en internet en bind lo hago así:

@                               IN      A       109.69.10.251
@                               IN      A       109.69.10.241
@                               IN      AAAA    2a00:1508:6000:501::a1
@                               IN      AAAA    2a00:1508:6000:501::a2

frontal                 1H      IN      A       109.69.10.241
frontal                 1H      IN      A       109.69.10.251
frontal                 1H      IN      AAAA    2a00:1508:6000:501::a1
frontal                 1H      IN      AAAA    2a00:1508:6000:501::a2

www                     1H      IN      CNAME   frontal

A continuación, en nginx para cada sitio del wordpress tengo un fichero de configuración similar a éste de lamardebits.org:

# Redireccionem tots els noms de domini:80 a
# https://lamardebits.org
server {
    listen 80;
    server_name
        marsupi.org
        www.marsupi.org
        www.lamardebits.org
        lamardebits.org;

    include snippets/certbot.conf;

    return 301 https://lamardebits.org$request_uri;
    #root /var/www/html;
}

# Responem les consultes de https://lamardebits.org
server {
    server_name
        lamardebits.org;

    include snippets/certbot.conf;
    include snippets/lmdb-error-pages.conf;
    include snippets/wordpress.conf;

    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    ssl_certificate /etc/letsencrypt/live/lamardebits.org/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/lamardebits.org/privkey.pem;
    include /etc/letsencrypt/options-ssl-nginx.conf;
    ssl_trusted_certificate /etc/letsencrypt/live/lamardebits.org/chain.pem;
}

Destaco el snippet wordpress.conf donde pongo la configuración común de los sitios de wordpress

location / {
    proxy_pass http://172.31.0.146:80;
    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 https;
    proxy_set_header X-Forwarded-Port 443;
    proxy_set_header Host $host;
}

La ip del contenedor donde se encuentra el wordpress es la 172.31.0.146.

Ahora nos posicionamos ya en la máquina de wordpress y vamos a revisar la configuración de cada uno de los elementos.

varnish cache
Pues siguiendo los servicios por el que pasa el usuario al llegar a mis wordpress, ahora sería el turno de varnish. Varnish lo tengo escuchando en el puerto 6081 y recoge la información del apache que está sirviendo en el puerto 80

Varnish es muy importante porque nos permite reducir la carga del servidor (wordpress cada vez es mas tocho), además, varnish hace que el usuario se le carguen las páginas mucho mas rápido.

# vi /etc/default/varnish
START=yes
NFILES=131072
MEMLOCK=82000
DAEMON_OPTS="-a :6081 \
             -T localhost:6082 \
             -f /etc/varnish/default.vcl \
             -S /etc/varnish/secret \
             -s malloc,256m"
# vi /etc/varnish/default.vcl
#
# This is an example VCL file for Varnish.
#
# It does not do anything by default, delegating control to the
# builtin VCL. The builtin VCL is called when there is no explicit
# return statement.
#
# See the VCL chapters in the Users Guide at https://www.varnish-cache.org/docs/
# and https://www.varnish-cache.org/trac/wiki/VCLExamples for more examples.

# Marker to tell the VCL compiler that this VCL has been adapted to the
# new 4.0 format.
vcl 4.0;

# Default backend definition. Set this to point to your content server.

backend default {
  .host = "127.0.0.1";
  .port = "80";
}

sub vcl_recv {
  # Set the X-Forwarded-For header so the backend can see the original
  # IP address. If one is already set by an upstream proxy, we'll just re-use that.

  #return(pass);

  if (req.method == "PURGE") {
     return (purge);
  }

  if (req.method == "XCGFULLBAN") {
     ban("req.http.host ~ .*");
     return (synth(200, "Full cache cleared"));
  }

  if (req.http.X-Requested-With == "XMLHttpRequest") {
     return(pass);
  }

  if (req.http.Authorization || req.method == "POST") {
     return (pass);
  }

  if (req.method != "GET" && req.method != "HEAD") {
     return (pass);
  }

  if (req.url ~ "(wp-admin|post\.php|edit\.php|wp-login|wp-json)") {
     return(pass);
  }

  if (req.url ~ "/wp-cron.php" || req.url ~ "preview=true") {
     return (pass);
  }

  if ((req.http.host ~ "my_domain.com" && req.url ~ "^some_specific_filename\.(css|js)")) {
     return (pass);
  }

  set req.http.Cookie = regsuball(req.http.Cookie, "has_js=[^;]+(; )?", "");
  
  # Remove the wp-settings-1 cookie
  set req.http.Cookie = regsuball(req.http.Cookie, "wp-settings-1=[^;]+(; )?", "");

  # Remove the wp-settings-time-1 cookie
  set req.http.Cookie = regsuball(req.http.Cookie, "wp-settings-time-1=[^;]+(; )?", "");

  # Remove the wp test cookie
  set req.http.Cookie = regsuball(req.http.Cookie, "wordpress_test_cookie=[^;]+(; )?", "");

  # Remove the PHPSESSID in members area cookie
  set req.http.Cookie = regsuball(req.http.Cookie, "PHPSESSID=[^;]+(; )?", "");

  unset req.http.Cookie;  
}

sub vcl_purge {
    set req.method = "GET";
    set req.http.X-Purger = "Purged";

    #return (synth(200, "Purged"));
    return (restart);
}

sub vcl_backend_response {
    # Happens after we have read the response headers from the backend.
    # 
    # Here you clean the response headers, removing silly Set-Cookie headers
    # and other mistakes your backend does.

    set beresp.grace = 12h;
    set beresp.ttl = 12h;
}

sub vcl_deliver {
    # Happens when we have all the pieces we need, and are about to send the
    # response to the client.
    #
    # You can do accounting or modifying the final object here.
}

apache

La configuración de apache entonces es:

# vi /etc/apache2/sites-enabled/wordpress.conf

        ServerAdmin administradors@lamardebits.org

        DocumentRoot /var/www/wp/


        # This helps applications behind a proxy know that the pages
        # were originally requested over https
        # Prevents browser blocking content because of MIXED CONTENT
        SetEnvIf X-Forwarded-Proto https HTTPS=on

        
                AllowOverride None
        < /LocationMatch>
        
                Options -Indexes
                AllowOverride All
        < /Directory>

        ErrorLog ${APACHE_LOG_DIR}/wp.lmdb.error.log
        # Possible values include: debug, info, notice, warn, error, crit,
        # alert, emerg.
        LogLevel warn
        #CustomLog ${APACHE_LOG_DIR}/wp.lmdb.access.log combined
        #CustomLog "| nc -u -j 172.31.0.114 515" combined
        CustomLog ${APACHE_LOG_DIR}/wp.lmdb.access.log proxy

        RewriteEngine On
        RewriteOptions inherit
< /VirtualHost>

WordPress

En el wordpress tendremos que modificar el fichero wp-config.php

if (strpos($_SERVER['HTTP_X_FORWARDED_PROTO'], 'https') !== false) {
   $_SERVER['HTTPS']='on';
}

Si sigue fallando wordpress, jetpack o alguna cosa prueba de añadir éstas otras configuraciones

$_SERVER['SERVER_PORT'] = 80;

# IN HTTPS
define( 'JETPACK_SIGNATURE__HTTPS_PORT', 80 );

# OUT HTTPS
define( 'JETPACK_CLIENT__HTTPS', 'NEVER' );



Finalmente tendremos que activar algún plugin de cache. Antes tenía otro, requería configurar cada sitio manualmente y era un rollo, así que el que tengo ahora es “Proxy Cache Purge” de “Mika Epstein”. Que basicamente lo que hace es hacer un PURGE de las páginas que actualicemos cada vez que hagamos un cambio.

De momento con esto tiene pinta que el wordpress va mucho mas suelto y por fin no se cuelgan las páginas al hacer cambios! además he pasado de 8 errores a 2 en la verificación que hace wordpress del estado del sitio que corresponden a noseque del jetpack.

Seguiremos investigando y probando de afinar mucho mas el sistema.

Cualquier propuesta de mejora y de seguridad será bienvenida :D

Fuente: Setting Up Varnish-Cache 4 for WordPress

Deixa un comentari

L'adreça electrònica no es publicarà. Els camps necessaris estan marcats amb *

Aquest lloc utilitza Akismet per reduir els comentaris brossa. Apreneu com es processen les dades dels comentaris.