WP-CLI para mantenimiento y seguridad

Si utilizas WordPress y tienes la posibilidad de gestionar el acceso por Shell, sin duda has de tener disponible WP-CLI. Y si utilizas WP-CLI entonces ya sabes que existen una decena de comandos que te facilitan la vida.

En general tengo puesto en mi agenda hacer al menos una revisión semanal de todos los WordPress que tengo, y eso incluye cierto mantenimiento y, de paso, darle una ojeada a los distintos elementos para que, de un vistazo, no se haya colado nada que no tenga que estar…

Esta es una pequeña lista de comandos que uso en este orden para revisar, verificar y actualizar el sistema.

$ reviso la versión de la instalación de WP-CLI
wp cli version
$ compruebo si hay actualizaciones disponibles de WP-CLI
wp cli check-update
$ actualizo WP-CLI a su última versión
wp cli update

$ entro en la carpeta de la instalación que quiero analizar
cd /carpeta/de/instalacion/wordpress/

$ verifico que no haya nada "raro" instalado en el core
wp core verify-checksums
$ listo la configuración del wp-config
wp config get
$ listo la lista de usuarios
wp user list

$ reviso la versión del WordPress
wp core version
$ compruebo si hay una nueva versión del WordPress
wp core check-update
$ actualizo a la última versión del WordPress
wp core update --path="/carpeta/de/instalacion/wordpress/"
$ verifico que no haya nada "raro" instalado en el core
wp core verify-checksums

$ hago una lista de todos los plugins instalados
wp plugin list --path="/carpeta/de/instalacion/wordpress/"
$ listo todos los plugins que tienen actualizaciones
wp plugin update --dry-run --all --path="/carpeta/de/instalacion/wordpress/"
$ actualizo todos los plugins que tienen actualizaciones
wp plugin update --all --path="/carpeta/de/instalacion/wordpress/"

$ hago una lista de todas las plantillas instaladas
wp theme list --path="/carpeta/de/instalacion/wordpress/"
$ listo todas las plantillas que tienen actualizaciones
wp theme update --dry-run --all --path="/carpeta/de/instalacion/wordpress/"
$ actualizo todas las plantillas que tienen actualizaciones
wp theme update --all --path="/carpeta/de/instalacion/wordpress/"

$ hago una lista de todos los idiomas instalados
wp language core list --status=installed
$ listo todos los idiomas que tienen actualizaciones
wp language core update --dry-run --path="/carpeta/de/instalacion/wordpress/"
$ actualizo todos los idiomas que tienen actualizaciones
wp language core update --path="/carpeta/de/instalacion/wordpress/"

$ elimino todos los transients caducados
wp transient delete --expired
$ compruebo el prefijo del WordPress
wp db prefix
$ verifico el tamaño de la base de datos del WordPress
wp db size
$ optimizo la base de datos del WordPress
wp db optimize
$ verifico el tamaño de la base de datos del WordPress
wp db size

Obviamente este listado de comandos tiene algunos “inútiles” pero que son válidos para comprobar por enésima vez que todo es correcto y que nada se descuadra de lo que ha de ser. De la misma forma hay varios comandos que revisa y re compruebas elementos que no son necesarios comprobar. Pero aún así, con este listado, poco a poco, salen las cosas bien.

Generador de contraseñas en PHP

En PHP hay muchas formas de generar contraseñas, algunas propias del sistema. En ocasiones se usan sistemas sólo números. Con este sistema tienes disponible todos los caracteres que quieres como disponibles (mayúsculas, minúsculas, números, símbolos…) y la longitud (24, que en este caso la convierte en segura). Así que si necesitas restaurar la clave a un usuario, con esto le ofrecerás una clave segura.

<?php
$caracteres = '0123456789abcdefghijklmnpqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$#@!?=%-+*.[]{}_,;:<>|';
$caractereslong = strlen($caracteres);
$clave = '';
for($i = 0; $i < 24; $i++) {
  $clave .= $caracteres[rand(0, $caractereslong - 1)];
}
echo $clave;
?>

WordPress SEO: ¿Yoast o más sencillo?

En muchas ocasiones cuando instalamos un WordPress vamos con nuestra lista predefinida de plugins, y habitualmente incorporamos uno de SEO. Estos plugins de SEO en realidad hacen poco, ya que es cierto que WordPress no permite de serie gestionar cómo queremos los títulos, pero él es capaz de generar automáticamente el meta-description si se hace bien.

Es por esto que mucha gente utiliza Yoast como plugin de SEO, que además de llevar muchas herramientas que te dicen cómo escribir (algo que nunca he usado ni usaría), te corrigen (en cierta manera) el formato de título y snippet que se muestra en los resultados de búsqueda.

Hace poco me puse a buscar una solución que fuera extremadamente simple para el tema de eso: título, descripción y palabras clave. Estos tres viejos elementos son en el fondo lo único que necesitaba, el resto ya lo hace bien la plantilla. Y acabé encontrando un plugin que no está en el repositorio oficial pero que está gestionado como tal: WP SEO: A simple, straightforward SEO plugin for WordPress. Just the facts, Jack. Para aquellos que quieran, descarga la versión 0.13.0.

Este plugin lo que hace es añadir estos campos:

Y hace simplemente eso… aunque se pueden usar los distintos códigos de sustitución:

#archive_date#
#author#
#categories#
#date_modified#
#date_published#
#excerpt#
#post_type_plural_name#
#post_type_singular_name#
#search_term#
#site_description#
#site_name#
#tags#
#term_description#
#term_name#
#thumbnail_url#
#title#

Con estos códigos te puedes hacer la configuración personalizada para todos los tipos de página que tengas en tu sitio:

En la última opción, que te permite crear tus propios “metas”, podrías por ejemplo configurar uno para Google Search Console, de forma que el nombre sea google-site-verification y el content, el identificador que Google proporciona.

Lo siguiente es… si hasta ahora he estado utilizando Yoast ¿puedo migrar los datos de Yoast a este sistema? La respuesta es sí, se puede hacer, aunque no tengo ningún plugin ni nada parecido. Aún así, con 2 consultas SQL se hace muy rápido:

UPDATE wp_postmeta SET meta_key = '_meta_title' WHERE meta_key = '_yoast_wpseo_title';
UPDATE wp_postmeta SET meta_key = '_meta_description' WHERE meta_key = '_yoast_wpseo_metadesc';

Y si quieres hacer limpieza una vez desinstalado Yoast, puedes borrar “los restos”:

DELETE FROM wp_postmeta WHERE meta_key LIKE '_yoast%';

A partir de aquí tendrás una forma sencilla de añadir el título, descripción y keyworks que quieras sin necesidad de instalar un plugin pesado como son generalmente los de SEO.

Youtube Live: una experiencia de casi 6 horas

No sé si aún estoy despierto después de la paliza que nos dimos anoche para hacer el directo. Sin duda es de esas fechas que tendré que marcar en mi agenda de hitos en Internet: haber hecho junto a un grupo de buenos amigos un programa en directo en Youtube Live de casi 6 horas (5:45). Y podríamos haber seguido.

La historia no está muy clara de cómo comenzó, pero creo que empezó entre la primera visita al Late Show y el programa del verano, donde nos reímos muchísimo (como sobre todo se puede ver en las tomas falsas), y estaba ya decidido cuando cuando estuve hablando sobre socios, sin querer, en el Evento.

La propuesta que nos hicimos el equipo del MOLS fue la de hacer una maratón de 8 horas (que quedaron en 6) para hablar de Marketing Online. Salieron temas de todo tipo, comenzando por SEO, pasando por analítica, redes sociales, negocios, impuestos, logística, test A/B y un sinfín de temas. Obviamente en algunos momentos se nos iba la olla y acabábamos hablando de otros temas relacionados pero tangenciales. Por suerte, estaba Joan Boluda y, posteriormente, Joan Artés, para complementar todos los puntos de vista.

Por supuesto pude hablar largo y tendido de MAM Originals (proyecto en el que soy socio y trabajo actualmente) y del que pude llevar algunos regalos navideños al equipo, y a todos los que quieran un descuento, entre el 1 y el 8 de diciembre (2017) tenéis un código de descuento del 20% utilizando el código BOLUDA. Sin duda MAM me dio pie a hablar de muchos temas ya que se basa en muchos de los asuntos tratados en el programa, y es que no deja de ser un e-Commerce.

Algo que surgió durante muchas veces en el programa fue la separación que aún existe entre los equipos de tecnología y de marketing, porque unos “no hablan el mismo idioma” que los otros. En este caso la única solución que se me ocurre es la de tener un perfil puente que consiga que la parte digital del proyecto, se pegue de alguna forma y todos se entiendan.

Obviamente, os diría que veáis el vídeo (aunque sea en varios días), que saquéis vuestras propias conclusiones, y que estoy contento de que Joan se esté animando a hacer más directos, aunque sean de menos de una hora 🙂 porque es cierto, cansa.

Por cierto, al final, hicimos un poco de Inception con “directos dentro de los directos“.

Cómo evitar que un gobierno (el español, por ejemplo) cierre una web…

…o cómo ponerlo más difícil, y por lo menos no moriri en el intento.

Estos días estamos viendo como el Tribunal Constitucional español está solicitando el cierre de determinados sitios web (debido al Referéndum), y me gustaría hacer un planteamiento, desde el punto de vista técnico, de cómo se podría conseguir hacer esto algo más difícil.

Para comenzar lo primero hay que establecer son una serie de reglas: Internet está hecha para ser un sistema distribuido, por lo que cerrar un sitio web debe ser algo complicado desde el punto de vista técnico. Lo siguiente es establecer que , de la misma forma que Internet está hecho para ser distribuido, su funcionamiento ha de ser simple (y muy complejo) para que todos sigamos una serie de reglas.

Cuando lanzas un sitio web informativo, como puede ser el del referendum.cat, y que ahora lanza un mensaje como el que podemos ver a continuación…

…hemos de tener presentes tres puntos débiles del sistema: el dominio, las DNS y el servidor web.

Comenzando por el dominio, en este caso se están usando dominios .CAT que dependen de la Fundación punt Cat y formado por el Patronato, lo primero es analizar en qué registrador oficial se registra el dominio. Partiendo de la base de que los dominios no son caros da igual dónde los registres, yo me iría a registrarlos por ejemplo a 101domain, o tal vez a blacknight al estar la sede social fuera de España. Obviamente la gran diferencia es que la Guardia Civil no va a ir a tus oficinas, y van a ordenarte, de cuerpo presente, que des de baja el asunto. Esto ya te dará unos días.

Segundo punto, las DNS. En este caso hay fórmulas muy sencillas, como por ejemplo tener las DNS en un servidor DNS abierto. Hace unos días escribí una entrada sobre NS, que tampoco es 100% para esto que comento, pero nos puede dar una primera idea. El objetivo es tener un proveedor de DNS que esté fuera de Europa (o de países amigos, a ser posible) y utilizar varios servidores web (con varias cpias de la web) y que por sistemas de Round-Robin mandar a los usuarios a varios servidores en distintos países. ¿Te cierran un servidor web? No pasa nada, quitas esa entrada DNS y añades otra.

Para acabar, el servidor web. Una web como estas que comentamos son principalmente informativas y no suelen requerir una infraestructura compleja, ya que aunque tengan una pequeña base de datos son webs muy cacheables. Esto significa que con máquinas muy pequeñas, podrías tener muchas en muchos ISP lo que requeriría muchos requerimientos. En la misma línea, hace poco hablé de los VPS para desarrolladores que podrían servir para este caso (máquinas de 5-10 euros/mes, que total, sólo hace falta un mes).

Si sumamos todo esto, estamos hablando de que por 10 euros del dominio + 2 euros de DNS + 50 euros en 5 alojamientos web, tendrías una infraestructura distribuida sencilla, fácil de mantener, escalable incluso, extensible y a la que la acción judicial de un único país tendría ligeramente difícil de poder cerrar. Teniendo esto en cuenta, mi duda es is la gente que ha montado la web del referendum.cat tenía todo pensado para montar algo “razonable” o simplemente alguien estaba esperando que llegasen los jueces a cerrarla.

Mejora la página de mantenimiento de WordPress

Cuando actualizamos el núcleo de WordPress, sus plantillas o los plugins, en ese fragmento de tiempo pequeño, suele aparecer un breve mensaje de texto en cualquier pantalla de navegación en la que nos encontramos. Esa pantalla suele ser una pantalla fría, blanca con el mensaje de texto Briefly unavailable for scheduled maintenance. Check back in a minute. Sin duda no es la pantalla más bonita que podemos mostrarle a nuestros usuarios, es útil, pero no tiene gracia.

El mantenimiento de WordPress se gestiona por la creación de un fichero en la carpeta raíz (donde está el index.php principal) llamado .maintenance. El hecho de que exista este fichero con un pequeño codigo hace que todo el sitio quede bloqueado hasta que acaben de actualizarse todos los complementos.

¿Te gustaría darle un formato un poco más elegante a la página? Se puede hacer, creando un fichero en PHP que haga lo mismo que hace el sistema por defecto, pero con cierto contenido. Para ello deberás incluir el fichero maintenance.php dentro de la carpeta /wp-content/.

Ese fichero ha de tener una cabecera que devuelva un código 503 (conforme la página no está accesible temporalmente) y el tiempo en el que se debe volver a revisar. Como habitualmente las actualizaciones de WordPress son rápidas, pondremos que el reintento se haga en 1 minuto.

<?php
wp_load_translations_early();
$protocol = wp_get_server_protocol();
header($protocol.' 503 Service Unavailable', true, 503);
header('Retry-After: 60');
header('Content-Type: text/html; charset=utf-8');
?>

Teniendo esto en cuenta, podemos crear diseños que tengan al menos alguna animación:

<?php
wp_load_translations_early();
$protocol = wp_get_server_protocol();
header($protocol.' 503 Service Unavailable', true, 503);
header('Retry-After: 60');
header('Content-Type: text/html; charset=utf-8');
?>
<!DOCTYPE html>
<html>
<head>
  <title><?php _e('Maintenance'); ?></title>
  <style>.container{width:200px;height:100px;padding-top:100px;margin:0 auto}.ball{width:10px;height:10px;margin:10px auto;border-radius:50px}.ball:nth-child(1){background:#ff005d;-webkit-animation:right 1s infinite ease-in-out;-moz-animation:right 1s infinite ease-in-out;animation:right 1s infinite ease-in-out}.ball:nth-child(2){background:#35ff99;-webkit-animation:left 1.1s infinite ease-in-out;-moz-animation:left 1.1s infinite ease-in-out;animation:left 1.1s infinite ease-in-out}.ball:nth-child(3){background:#008597;-webkit-animation:right 1.05s infinite ease-in-out;-moz-animation:right 1.05s infinite ease-in-out;animation:right 1.05s infinite ease-in-out}.ball:nth-child(4){background:#fc0;-webkit-animation:left 1.15s infinite ease-in-out;-moz-animation:left 1.15s infinite ease-in-out;animation:left 1.15s infinite ease-in-out}.ball:nth-child(5){background:#2d3443;-webkit-animation:right 1.1s infinite ease-in-out;-moz-animation:right 1.1s infinite ease-in-out;animation:right 1.1s infinite ease-in-out}.ball:nth-child(6){background:#ff7c35;-webkit-animation:left 1.05s infinite ease-in-out;-moz-animation:left 1.05s infinite ease-in-out;animation:left 1.05s infinite ease-in-out}.ball:nth-child(7){background:#4d407c;-webkit-animation:right 1s infinite ease-in-out;-moz-animation:right 1s infinite ease-in-out;animation:right 1s infinite ease-in-out}@-webkit-keyframes right{0%,100%{-webkit-transform:translate(-15px)}50%{-webkit-transform:translate(15px)}}@-webkit-keyframes left{0%,100%{-webkit-transform:translate(15px)}50%{-webkit-transform:translate(-15px)}}@-moz-keyframes right{0%,100%{-moz-transform:translate(-15px)}50%{-moz-transform:translate(15px)}}@-moz-keyframes left{0%,100%{-moz-transform:translate(15px)}50%{-moz-transform:translate(-15px)}}@keyframes right{0%,100%{transform:translate(-15px)}50%{transform:translate(15px)}}@keyframes left{0%,100%{transform:translate(15px)}50%{transform:translate(-15px)}}</style>
</head>
<body>
  <center><h1><?php _e('Maintenance'); ?></h1></center>
  <p align="center"><?php _e('Briefly unavailable for scheduled maintenance. Check back in a minute.'); ?></p>
  <div class="container"><div class="ball"></div><div class="ball"></div><div class="ball"></div><div class="ball"></div><div class="ball"></div><div class="ball"></div><div class="ball"></div></div>
  <script>var maintenance_check=function(){var n=new XMLHttpRequest;n.open("HEAD",window.location,!0),n.onload=function(){this.status>=200&&this.status<400?window.location.reload():setTimeout(maintenance_check,5000)},n.onerror=function(){setTimeout(maintenance_check,5000)},n.send()};maintenance_check();</script>
</body>
</html>

Aunque si ese, que es sencillo y con un poco de formato te ha gustado, este tampoco se queda atrás.

<?php
wp_load_translations_early();
$protocol = wp_get_server_protocol();
header($protocol.' 503 Service Unavailable', true, 503);
header('Retry-After: 60');
header('Content-Type: text/html; charset=utf-8');
?>
<!DOCTYPE html>
<html>
<head>
  <title><?php _e('Maintenance'); ?></title>
  <style>body{background-color:#012;background-image:url(https://cssanimation.rocks/demo/starwars/images/bg.jpg);background-size:33%;background-repeat:repeat;min-height:2025px;color:#fff}.system{position:relative;top:0;left:0;width:100%;height:100%;-webkit-transform:scale(.75);transform:scale(.75)}.sun{width:144px;height:144px;border-radius:72px;position:absolute;top:1066.67px;left:50%;margin:-72px;background-image:url(https://sdo.gsfc.nasa.gov/assets/img/latest/latest_256_HMIIF.jpg);background-size:144px;background-repeat:no-repeat}.mer,.mer-path{border-radius:50%;position:absolute;top:1066.67px;left:50%}@-webkit-keyframes rot-mer{from{-webkit-transform:rotate(0) translatey(-84px) rotate(0)}to{-webkit-transform:rotate(360deg) translatey(-84px) rotate(-360deg)}}@-keyframes rot-mer{from{-webkit-transform:rotate(0) translatey(-84px) rotate(0);transform:rotate(0) translatey(-84px) rotate(0)}to{-webkit-transform:rotate(360deg) translatey(-84px) rotate(-360deg);transform:rotate(360deg) translatey(-84px) rotate(-360deg)}}.mer{width:3.5px;height:3.5px;background-color:#888;margin:-1.75px;-webkit-animation:rot-mer .88s infinite linear;animation:rot-mer .88s infinite linear;z-index:200}.mer-path{width:168px;height:168px;z-index:100;margin:-84px;border:1px solid #444}.ven,.ven-path{border-radius:50%;position:absolute;top:1066.67px;left:50%}@-webkit-keyframes rot-ven{from{-webkit-transform:rotate(0) translatey(-90px) rotate(0)}to{-webkit-transform:rotate(360deg) translatey(-90px) rotate(-360deg)}}@-keyframes rot-ven{from{-webkit-transform:rotate(0) translatey(-90px) rotate(0);transform:rotate(0) translatey(-90px) rotate(0)}to{-webkit-transform:rotate(360deg) translatey(-90px) rotate(-360deg);transform:rotate(360deg) translatey(-90px) rotate(-360deg)}}.ven{width:5.5px;height:5.5px;background-color:#f5f9be;margin:-2.75px;-webkit-animation:rot-ven 2.25s infinite linear;animation:rot-ven 2.25s infinite linear;z-index:200}.ven-path{width:180px;height:180px;z-index:100;margin:-90px;border:1px solid #444}.ear,.ear-path{border-radius:50%;position:absolute;top:1066.67px;left:50%}@-webkit-keyframes rot-ear{from{-webkit-transform:rotate(0) translatey(-102px) rotate(0)}to{-webkit-transform:rotate(360deg) translatey(-102px) rotate(-360deg)}}@-keyframes rot-ear{from{-webkit-transform:rotate(0) translatey(-102px) rotate(0);transform:rotate(0) translatey(-102px) rotate(0)}to{-webkit-transform:rotate(360deg) translatey(-102px) rotate(-360deg);transform:rotate(360deg) translatey(-102px) rotate(-360deg)}}.ear{width:7px;height:7px;background-color:#4b94f9;margin:-3.5px;-webkit-animation:rot-ear 3.65s infinite linear;animation:rot-ear 3.65s infinite linear;z-index:200}.ear-path{width:204px;height:204px;z-index:100;margin:-102px;border:1px solid #444}.mar,.mar-path{border-radius:50%;position:absolute;top:1066.67px;left:50%}@-webkit-keyframes rot-mar{from{-webkit-transform:rotate(0) translatey(-118px) rotate(0)}to{-webkit-transform:rotate(360deg) translatey(-118px) rotate(-360deg)}}@-keyframes rot-mar{from{-webkit-transform:rotate(0) translatey(-118px) rotate(0);transform:rotate(0) translatey(-118px) rotate(0)}to{-webkit-transform:rotate(360deg) translatey(-118px) rotate(-360deg);transform:rotate(360deg) translatey(-118px) rotate(-360deg)}}.mar{width:6px;height:6px;background-color:#dd411a;margin:-3px;-webkit-animation:rot-mar 6.87s infinite linear;animation:rot-mar 6.87s infinite linear;z-index:200;background-image:-webkit-repeating-linear-gradient(top,#fff,#fff 1px,transparent 1px,transparent 5px);background-image:repeating-linear-gradient(to bottom,#fff,#fff 1px,transparent 1px,transparent 5px)}.mar-path{width:236px;height:236px;z-index:100;margin:-118px;border:1px solid #444}.jup,.jup-path{border-radius:50%;position:absolute;top:1066.67px;left:50%}@-webkit-keyframes rot-jup{from{-webkit-transform:rotate(0) translatey(-228px) rotate(0)}to{-webkit-transform:rotate(360deg) translatey(-228px) rotate(-360deg)}}@-keyframes rot-jup{from{-webkit-transform:rotate(0) translatey(-228px) rotate(0);transform:rotate(0) translatey(-228px) rotate(0)}to{-webkit-transform:rotate(360deg) translatey(-228px) rotate(-360deg);transform:rotate(360deg) translatey(-228px) rotate(-360deg)}}.jup{width:70px;height:70px;background-color:#eaad3b;margin:-35px;-webkit-animation:rot-jup 43.32s infinite linear;animation:rot-jup 43.32s infinite linear;z-index:200;background-image:-webkit-repeating-linear-gradient(84deg,#797663 22px,#e1dcde 16px,#c3a992 30px,#e9ece2 30px);background-image:repeating-linear-gradient(6deg,#797663 22px,#e1dcde 16px,#c3a992 30px,#e9ece2 30px)}.jup-path{width:456px;height:456px;z-index:100;margin:-228px;border:1px solid #444}.sat,.sat-path{border-radius:50%;position:absolute;top:1066.67px;left:50%}@-webkit-keyframes rot-sat{from{-webkit-transform:rotate(0) translatey(-362px) rotate(0)}to{-webkit-transform:rotate(360deg) translatey(-362px) rotate(-360deg)}}@-keyframes rot-sat{from{-webkit-transform:rotate(0) translatey(-362px) rotate(0);transform:rotate(0) translatey(-362px) rotate(0)}to{-webkit-transform:rotate(360deg) translatey(-362px) rotate(-360deg);transform:rotate(360deg) translatey(-362px) rotate(-360deg)}}.sat{width:58px;height:58px;background-color:#d6cd93;margin:-29px;-webkit-animation:rot-sat 107.59s infinite linear;animation:rot-sat 107.59s infinite linear;z-index:200}.sat-path{width:724px;height:724px;z-index:100;margin:-362px;border:1px solid #444}.ura,.ura-path{border-radius:50%;position:absolute;top:1066.67px;left:50%}@-webkit-keyframes rot-ura{from{-webkit-transform:rotate(0) translatey(-648px) rotate(0)}to{-webkit-transform:rotate(360deg) translatey(-648px) rotate(-360deg)}}@-keyframes rot-ura{from{-webkit-transform:rotate(0) translatey(-648px) rotate(0);transform:rotate(0) translatey(-648px) rotate(0)}to{-webkit-transform:rotate(360deg) translatey(-648px) rotate(-360deg);transform:rotate(360deg) translatey(-648px) rotate(-360deg)}}.ura{width:26px;height:26px;background-color:#bfeef2;margin:-13px;-webkit-animation:rot-ura 306.87s infinite linear;animation:rot-ura 306.87s infinite linear;z-index:200}.ura-path{width:1296px;height:1296px;z-index:100;margin:-648px;border:1px solid #444}.nep,.nep-path{border-radius:50%;position:absolute;top:1066.67px;left:50%}@-webkit-keyframes rot-nep{from{-webkit-transform:rotate(0) translatey(-972px) rotate(0)}to{-webkit-transform:rotate(360deg) translatey(-972px) rotate(-360deg)}}@-keyframes rot-nep{from{-webkit-transform:rotate(0) translatey(-972px) rotate(0);transform:rotate(0) translatey(-972px) rotate(0)}to{-webkit-transform:rotate(360deg) translatey(-972px) rotate(-360deg);transform:rotate(360deg) translatey(-972px) rotate(-360deg)}}.nep{width:24px;height:24px;background-color:#363ed7;margin:-12px;-webkit-animation:rot-nep 601.9s infinite linear;animation:rot-nep 601.9s infinite linear;z-index:200}.nep-path{width:1944px;height:1944px;z-index:100;margin:-972px;border:1px solid #444}.plu,.plu-path{border-radius:50%}@-webkit-keyframes rot-plu{from{-webkit-transform:rotate(0) translatey(-1246px) rotate(0)}to{-webkit-transform:rotate(360deg) translatey(-1246px) rotate(-360deg)}}@-keyframes rot-plu{from{-webkit-transform:rotate(0) translatey(-1246px) rotate(0);transform:rotate(0) translatey(-1246px) rotate(0)}to{-webkit-transform:rotate(360deg) translatey(-1246px) rotate(-360deg);transform:rotate(360deg) translatey(-1246px) rotate(-360deg)}}.plu{width:3px;height:3px;background-color:#963;position:absolute;left:50%;margin:-1.5px;-webkit-animation:rot-plu 904.65s infinite linear;animation:rot-plu 904.65s infinite linear;z-index:200}.dem,.jove,.lune,.pho{background-color:#fff;left:50%;position:absolute}.plu-path{width:2492px;height:2492px;z-index:100;position:absolute;left:50%;margin:-1246px;border:1px solid #444}@-webkit-keyframes rot-lune{from{-webkit-transform:rotate(0) translatey(-7px) rotate(0)}to{-webkit-transform:rotate(360deg) translatey(-7px) rotate(-360deg)}}@-keyframes rot-lune{from{-webkit-transform:rotate(0) translatey(-7px) rotate(0);transform:rotate(0) translatey(-7px) rotate(0)}to{-webkit-transform:rotate(360deg) translatey(-7px) rotate(-360deg);transform:rotate(360deg) translatey(-7px) rotate(-360deg)}}.lune{width:2px;height:2px;top:50%;margin:-1.5px;-webkit-animation:rot-lune .27s infinite linear;animation:rot-lune .27s infinite linear}.dem,.pho{margin:-1px}@-webkit-keyframes rot-pho{from{-webkit-transform:rotate(0) translatey(-7px) rotate(0)}to{-webkit-transform:rotate(360deg) translatey(-7px) rotate(-360deg)}}@-keyframes rot-pho{from{-webkit-transform:rotate(0) translatey(-7px) rotate(0);transform:rotate(0) translatey(-7px) rotate(0)}to{-webkit-transform:rotate(360deg) translatey(-7px) rotate(-360deg);transform:rotate(360deg) translatey(-7px) rotate(-360deg)}}@-webkit-keyframes rot-dem{from{-webkit-transform:rotate(0) translatey(-9px) rotate(0)}to{-webkit-transform:rotate(360deg) translatey(-9px) rotate(-360deg)}}@-keyframes rot-dem{from{-webkit-transform:rotate(0) translatey(-9px) rotate(0);transform:rotate(0) translatey(-9px) rotate(0)}to{-webkit-transform:rotate(360deg) translatey(-9px) rotate(-360deg);transform:rotate(360deg) translatey(-9px) rotate(-360deg)}}.dem,.pho{width:1px;height:1px;top:50%}.pho{-webkit-animation:rot-pho .15s infinite linear;animation:rot-pho .15s infinite linear}.dem{-webkit-animation:rot-dem .2s infinite linear;animation:rot-dem .2s infinite linear}.jove{width:2px;height:2px;top:35px}@-webkit-keyframes rot-io{from{-webkit-transform:rotate(0) translatey(-39px) rotate(0)}to{-webkit-transform:rotate(360deg) translatey(-39px) rotate(-360deg)}}@-keyframes rot-io{from{-webkit-transform:rotate(0) translatey(-39px) rotate(0);transform:rotate(0) translatey(-39px) rotate(0)}to{-webkit-transform:rotate(360deg) translatey(-39px) rotate(-360deg);transform:rotate(360deg) translatey(-39px) rotate(-360deg)}}@-webkit-keyframes rot-eur{from{-webkit-transform:rotate(0) translatey(-41px) rotate(0)}to{-webkit-transform:rotate(360deg) translatey(-41px) rotate(-360deg)}}@-keyframes rot-eur{from{-webkit-transform:rotate(0) translatey(-41px) rotate(0);transform:rotate(0) translatey(-41px) rotate(0)}to{-webkit-transform:rotate(360deg) translatey(-41px) rotate(-360deg);transform:rotate(360deg) translatey(-41px) rotate(-360deg)}}@-webkit-keyframes rot-gan{from{-webkit-transform:rotate(0) translatey(-45px) rotate(0)}to{-webkit-transform:rotate(360deg) translatey(-45px) rotate(-360deg)}}@-keyframes rot-gan{from{-webkit-transform:rotate(0) translatey(-45px) rotate(0);transform:rotate(0) translatey(-45px) rotate(0)}to{-webkit-transform:rotate(360deg) translatey(-45px) rotate(-360deg);transform:rotate(360deg) translatey(-45px) rotate(-360deg)}}@-webkit-keyframes rot-cal{from{-webkit-transform:rotate(0) translatey(-53px) rotate(0)}to{-webkit-transform:rotate(360deg) translatey(-53px) rotate(-360deg)}}@-keyframes rot-cal{from{-webkit-transform:rotate(0) translatey(-53px) rotate(0);transform:rotate(0) translatey(-53px) rotate(0)}to{-webkit-transform:rotate(360deg) translatey(-53px) rotate(-360deg);transform:rotate(360deg) translatey(-53px) rotate(-360deg)}}.io{-webkit-animation:rot-io .2s infinite linear;animation:rot-io .2s infinite linear}.eur{-webkit-animation:rot-eur .35s infinite linear;animation:rot-eur .35s infinite linear}.gan{-webkit-animation:rot-gan .7s infinite linear;animation:rot-gan .7s infinite linear}.cal{-webkit-animation:rot-cal 1.65s infinite linear;animation:rot-cal 1.65s infinite linear}.spot{position:absolute;width:16px;height:12px;border-radius:8px/6px;top:45px;left:50%;background-color:#bc833b;box-shadow:0 0 5px #e1dcde;border:1px solid #e1dcde;box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;z-index:300}.nep .spot{background-color:#29319d;border:0;box-shadow:none;top:50%;left:45%;width:10px;height:6px;margin:-2px;border-radius:5px/3px;border-left:solid 1px #7ed6fe}div[class$="-ring"]{border-radius:50%;position:absolute;top:50%;left:50%;opacity:.7;-webkit-transform:rotatex(45deg);transform:rotatex(45deg)}.a-ring{border:5px solid #96866f;width:119px;height:119px;margin:-64.5px}.b-ring{border:10px solid #554c3c;width:104px;height:104px;margin:-62px}.c-ring{border:9px solid #574f4a;width:95px;height:95px;margin:-56.5px}.f-ring{border:2px solid #908e8d;width:133px;height:133px;margin:-68.5px}.e-ring{border:7px solid #908e8d;width:76px;height:76px;margin:-45px;-webkit-transform:rotatex(0) rotatey(89deg)!important;transform:rotatex(0) rotatey(89deg)!important}.plu,.plu-path{top:1354.07px}</style>
</head>
<body>
  <center><h1><?php _e('Maintenance'); ?></h1></center>
  <p align="center"><?php _e('Briefly unavailable for scheduled maintenance. Check back in a minute.'); ?></p>
  <div class="system"><div class="sun"></div><div class="mer-path"></div><div class="mer"></div><div class="ven-path"></div><div class="ven"></div><div class="ear-path"></div><div class="ear"><div class="lune"></div></div><div class="mar-path"></div><div class="mar"><div class="pho"></div><div class="dem"></div></div><div class="jup-path"></div><div class="jup"><div class="spot"></div><div class="jove io"></div><div class="jove eur"></div><div class="jove gan"></div><div class="jove cal"></div></div><div class="sat-path"></div><div class="sat"><div class="f-ring"></div><div class="a-ring"></div><div class="b-ring"></div><div class="c-ring"></div></div><div class="ura-path"></div><div class="ura"><div class="e-ring"></div></div><div class="nep-path"></div><div class="nep"><div class="spot"></div></div><div class="plu-path"></div><div class="plu"></div></div>
  <script>var maintenance_check=function(){var n=new XMLHttpRequest;n.open("HEAD",window.location,!0),n.onload=function(){this.status>=200&&this.status<400?window.location.reload():setTimeout(maintenance_check,5000)},n.onerror=function(){setTimeout(maintenance_check,5000)},n.send()};maintenance_check();</script>
</body>
</html>

Ahora ya tienes unas primeras plantillas para optimizar tu WordPress cuando esté en mantenimiento y tus usuarios no vean un feo texto.

Qué App de mensajería elegir por seguridad

Elegir una App de mensajería instantánea para tu dispositivo móvil no debería se runa elección que se tome a la ligera. Al menos no si quieres estar seguro. Y es que aunque hoy en día la mayoría de las Apps utilizan cifrados punto a punto, hay una ligera diferencia en dónde se almacenan los datos.

Y es que una cosa que me explicaron hace muchos años sobre el correo electrónico es que daba igual que estuviera cifrado, porque las cabeceras no lo están, y eso implica que se sepa cuándo, de y para, cuántos mensajes se envían… lo que significa que puedes saber si hablas mucho con determinadas personas y con qué frecuencia, independientemente de la información de los mensajes. “Los grandes” siempre decían que eso era lo importante (por ejemplo, para Facebook sería suficiente esa información para relacionarte con otras personas).

Con la mensajería instantánea también pasa lo mismo… Lo importante es saber qué métodos de validación se usan y dónde se guardan los mensajes. No voy a hacer un análisis muy profundo de las cosas, pero sí que me voy a fijar en un par de elementos que deberían ser importantes a la hora de elegir.

Lo primero a tener en cuenta: ¿cuál es el sistema de identificación de usuarios? Hay sistemas de mensajería en que has de tener un número de teléfono y se centra todo en el número (por ejemplo a la hora de buscar contactos relacionados). Es lo que hace por ejemplo WhatsApp o Facebook Messenger y es lo que permite a Facebook relacionar personas. Otros como Signal lo usan pero sólo para verificar el dispositivo y a partir de ahí va siempre hasheado. En Threema ni eso (aunque puedes verificarlo posteriormente), simplemente te das de alta y listos.

Lo segundo a tener en cuenta: ¿dónde se guardan los mensajes? Hay dos modelos de mensajería, los que van de punto a punto o los que usan la nube como salto intermedio (y se guarda el mensaje ahí). Obviamente la mejor opción es la primera, ya que aunque se supone que nadie tiene tus claves y que las claves son “ultra seguras”, en realidad con un poco de ingeniería, es posible que la cosa no lo sea tanto y que esos mensajes almacenados puedan llegar a ser desencriptados (no digo que sea fácil).

Haciendo un repaso de estas opciones, si he de quedarme con Apps de mensajería, ¿con cuál me quedo? Sin hacer una investigación muy extensa, me quedaría con Signal o Threema, seguidamente de Telegram (con matices). Los dos primeros casos funciona de forma similar, aunque Threema sin duda es mucho más bestia, ya que te das de alta y te genera un identificador que no tienes porqué asociar ni con teléfono ni con correo (sólo lo haces si quieres) y la relación entre personas se puede hacer en persona, verificando tu relación leyendo un QR delsde el teléfono del otro. Signal en este caso sí que verifica el teléfono y es el sistema que usa para relacionar personas, aunque lo usa hasheado, de forma que sí que saben que se generan mensajes entre usuarios aunque se supone que son anónimos. n ambos casos, los mensajes nunca se almacenan en sus servidorfes sino que es mensajería cliente-cliente.

Telegram tiene una opción que es la de los chats privados que, en ese caso, sí que la mensajería es cliente-cliente, pero si es la normal (o los grupos) se usa mensajería cliente-servidor-cliente, lo que haría que se pierda eficacia.

Cuando alguien me dice eso de “pues instálate WhatsApp porque es lo que todo el mundo tiene”… bueno pues molt bé pues adiós.

#NoTincPor, una tarde por Barcelona

Hace poco más de una semana, estaba revisando Twitter cuando de repente me encontré con la noticia; los primeros tweets que hablaban y hacían trending topic a Les Rambles. Minutos después tenía que poner TV3 en directo vía web para comnenzar a informarme sobre lo ocurrido y sentir un nudo en la garganta.

Hoy sábado he ido a mi primera manifestación desde 1998. Ha habido momentos graves en los que seguramente tendría que haber salido a la calle, pero desde que a mediados de semana supe de ella, y aún estando fuera de Catalunya, sin duda ya comencé a escribir a conocidos para saber si alguien iba. Esta tarde me he venido con mi hermana al centro de mi ciudad, Barcelona, a expresar mi respeto con mis compañeros de geolocalización.

A sabiendas de que los transportes públicos iban a estar congestionados, ha sido una decisión correcta la de ir en moto y aparcar a varias calles (al límite de la jaula que se ha creado alrededor del centro de la ciudad).

A partir del momento en que hemos llegado a Passeig de Gràcia la cosa se animaba, aunque aún era muy pronto, ya que faltaba una hora y media para comenzar. Justo antes de venir, viendo las noticias, hemos sabido que se iban a entregar 70.000 rosas a los asistentes.

Y no eran sólo rosas, sino que algunas organizaciones han decidido hacer algunos carteles con mensajes directos a algunos de nuestros representantes políticos.

Según nos hemos ido acercando al centro de la ciudad nos hemos encontrado con más y más encierro, con más seguridad y más dificultades para caminar. Las calles se habían convertido en los límites de seguridad de Plaça de Catalunya, lo que te llevaba a tener que caminar una manzana más allá para poder cruzar.

Como decía, hemos ido con tiempo por lo que hemos decidido ir a Les Rambles. Según nos acercábamos, se notaba un ambiente distinto. Quizá no tanto en la parte superior, pero según ibas bajando la cosa cambiaba y el silencio se recogía en las zonas donde habían pequeñas zonas de recogida.

Por el camino un grupo de la Guardia Urbana ha ido a hacer una ofrenda floral y al volver a la cabecera de Les Rambles según pasaban la gente se paraba y les aplaudía. Probablemente el lugar más icónico y más silencioso y respetuoso es la zona del mural de Joan Miró, ahora tapado por miles de flores, centenares de mensajes y decenas de peluches.

Sin duda, se escuchaba un run-rún, pero el momento era bastante extraño y te hacía pensar.

A la vuelta a Plaça de catalunya, los medios comenzaban a hacer su trabajo y a emitir en directo para todo el planeta.

Los primeros políticos llegaban y, obviamente, los primeros aplausos y gritos…

Cuando se ha acabado todo, volviendo, nos hemos encontrado con unos “bolardos” gigantes, en forma de autobús.

Como conclusión saco que esta manifestación se ha politizado; creo que si no hubiera venido ningún político se hubiera acercado aún más gente, hubiera habido muchísimos más aplausos y menos pitidos, y en general todo el mundo hubiera quedado mucho más contento. No digo que los políticos no hubieran venido, pero que lo hubieran hecho entre la multitud y no de forma separada como ha acabado pasando. Ha sido muy obvio que primero se aplaudiría, luego se pitaría y luego se volvería a aplaudir, según pasaban los cuerpos de seguridad y emergencias, posteriormente los políticos y finalmente la ciudadanía.

Ley de cookies en Europa

Llevaba tiempo queriéndote decir esto: estás usando incorrectamente los mensajes de la Ley de Cookies. La primera pregunta que te quiero hacer es: ¿te has leido la ley? ¡Venga ya! Aceptaría que te hayas molestado en visitar la página simplificada de la Unión Europea en la que se explica la parte de cookies y si has de poner ese mensaje y cómo.

Primero vamos a situarnos rápido: una cookie no es una galleta, es un pequeño bloque de información que se guarda en tu navegador de Internet y que ayuda a los sitios webs por los que navegas a saber que eres tú y qué preferencias tienes en un sitio (por ejemplo, cuando seleccionas el idioma del menú de la página y cuando vuelves aparece ese mismo idioma).

Cookies hay de dos tipos, las de sesión (cuando cierras el navegador, se eliminan) y las permanentes (duran hasta la fecha final que se le indica). Por otro lado hay las de first-party (que son las cookies propias, las que genera el sitio por el que navegas) y las third-party (que las genera un servicio externo sobre el que no tienes control). Para acabar tienes la posibilidad de permitir solicitar cookies de forma implícita o explícita.

¿Cuándo NO hay que pedir permiso para las cookies? Cuando las cookies las provee el propio sitio web (first-party) y son para que el sitio funcione correctamente o tenga datos de configuración. Tampoco lo serían aquellas cookies de sesión o las que, como máximo, están un año.

¿Cuándo SÍ hay que pedir permiso para usar cookies? Cuando las cookies las provee un servicio externo que simplemente utiliza esas cookies para almacenar datos de uso o análisis. Ejemplos son Google Analytics, Hotjar y cosas de ese estilo. En definitiva, cosas que si no tuvieras, tu sitio funcionaría y que sólo pones para recopilar datos que se almaenan “por ahí”.

Existe una excepción y son las cookies de “redes sociales”. Por ejemplo, las cookies que Facebook, Google, Twitter ponen en tu sitio para identificar a los usuarios que han accedido a sus redes desde estos sitios.

Entonces ¿he de poner el mensajito que toca los webs en todos mis sitios? Depende. Sólo has de ponerlo cuando utilizas esas cookies de terceros que comentaba. En caso de ponerlo, y aquí es cuando decía al principio “que lo estás haciendo mal”. Voy a internet explicarme muy claramente:

Cuando pones el mensaje de las cookies ha de haber siempre dos opciones: Aceptar o Rechazar. El aceptar permite que incluyas esas cookies de terceros que trackean al usuario, pero el rechazar no puede sacarte de la web y mandarte a Google o Disney (si no dejas acceder a un usuario por no usar cookies loe stás discriminando, y eso es delito), te ha de permitir usar el sitio web, pero como propietario del sitio no puedes incluir los scripts de terceros.

Eso sí, ten presente que además de mostrar ese mensajito “flotante”, cuando lo aceptes o rechaces, igualmente y durante toda la visita del usuario, en cualquier momento el usuario puede decidor aceptar o rechazar de nuevo esto, y ha de estar visible de nuevo. Un ejemplo de este caso es el que se muestra en los puntos 1 y 3 de la imagen siguiente:

¿Cuál es la mejor manera de gestionar todo esto? Usando el sistema de Do Not Track que es una herramienta de los navegadores que automatiza la solicitud de este mensaje de las cookies. Si tu utilizas un sistema que detecte las cabeceras del sitio buscando la DNT y en caso de que esté activo no muestras los scripts de terceros, ya estarías cumpliendo en no tener que mostrar el mensaje de “aceptar las cookies”, ya que al estar activo y tú no mostrarlo, no hay que aceptar nada (ya que no muestras nada).

Eso sí, no olvides que independientemente de lo que hagas con la aceptación o no de las cookies, sí que hay que incluir en los sitios una zona en la que se explique qué tipo de cookies usas (ya sean first o third-party) y qué información almacenas en ellas. Ahora toca ponerse manos a la obra y arreglar lo que tengas mal en tus sitios (que es lo que voy a hacer yo ahora mismo).

WPdanger, análisis de seguridad para WordPress

Un clásico de los sitios web que usan un CMS de fondo es la falta de actualización de los mismos. Esto hace que si en un par de meses tu sitio está sin actualizar sea objetivo de cualquier ataque, ya que todos los problemas que puedan haber, estarán.

Si a esta preocupación personal le sumamos que en verano suelo hacer “cositas por entretenerme”, salen proyectos como WPdanger, un sitio web en el que pones la dirección de tu sitio en WordPress y te da algunas vulnerabilidades o te puede servir para encontrar problemas que puedas tener y que todos pueden verificar.

Al principio comencé usando WPscan para hacer algunas pruebas, pero aunque en particular funcionaba, a lo grande ya no era tan simple. Así que monté un primer sistema que mostraba los resultados por pantalla web, posteriormente comené a procesarlos y al final ha salido una web en la que analiza más de lo que hacía al principio (que era puramente reactivo) a algo un poco más decente y que da más datos, además de mostrar enlaces a todos aquellos problemas que pueden aparecer.

Pero esto era poco… si cualquiera tiene acceso a este tipo de herramientas ¿cómo evitar que los datos que aparecen sean útiles para prevenir ataques? Obviamente la primera fase era evitar enseñar lo que no se tiene que enseñar, es decir, que la herramienta crea que lo que realmente hay no esté. Así, si un hacker usa estas herramientas, y ve que aparentemente no hay mucho que hacer en el sitio, pase de él. Esto me ha llevado durante algunos días a hacer y hacer análisis hasta poder ir bloqueando aquellos elementos que bloqueasen ataques pero hiciesen que la web siguiera funcionando. Tras varias horas revisando y analizando y probando con mi sitio, llegué a varias conclusiones.

La primera de ellas es que WordPress funciona mejor con nginx que con Apache HTTPD. En principio debería dar igual, pero a la hora de configurar elementos ys eguridad, ya no tanto. Entre uno y otro, me quedo con nginx. Lo segundo es que hay que montar PHP 7, principalmente por temas de rendimiento. A partir de esta combinación, podemos comenzar a trabajar.

La segunda es que hay plugins (muy utilizados) que no piensan en la seguridad, no permiten desactivar determinados elementos y que ponen en riesgo todo t sitio. El principal que me he encontrado es el Yoast SEO. Me gusta, no me importa que tenga código que ponga que lo usas, pero por favor, no indiquemos la versión, o al menos que la versión sea un eleemnto que se pueda desactivar. Como digo, es el plugin más inseguro (desde ese punto de vista) que he encontrado.

La tercera es que el hecho de que WordPress sea tan estándar y tan sencillo, hace que se puedan detectar versiones de plugins y plantillas de forma extremadamente sencilla (y sobre todo, de forma automática). Obviamente hay que encontrar un mix entre funcionalidad y seguridad. Me ha costado, pero he acabado encontrándolo.

El cuarto es que las configuraciones de seguridad que hay por Internet sobre WordPress se quedan extremadamente cortos. Es obvio que hay que informar, siempre lo primero, en que tu WordPress esté actualizado, obvio ye s así, pero por ejemplo, en todos los manuales se habla del famoso “usuario admin” que desde hace muchísimas versiones ya no viene por defecto. Está bien decir que no se use, pero han pasado años de que sea el mayor problema de seguridad de los usuarios. Lo que más me molesta es que no se explique esto, que es un tema histórico y que una instalación nueva no debería preocuparse en exceso por este asunto.

El quinto es que me ha parecido extraño que los grandes proveedores de hosting especializados en WordPress no den soluciones de seguridad sencillas más avanzadas, sobre todo en la parte preventiva.

Obviamente, no hay sitios 100% seguros, ni pretendo que los haya, pero sí que la prevención de la que siempre se habla en seguridad, se aplique. No tiene sentido decir que tienes un Firewall si luego puedo saber la lista de plugins que tienes instalados, o qué plantillas usas, y mucho menos saber qué versiones son y si están al día o no, incluyendo al núcleo.

¿Qué he aprendido con todo esto? A mejorar la ocultaciónd e información de la manera más simple posible que he encontrado, y principalmente poner difícil a los demás saber qué uso o dejo de usar. Un ejemplo, ahora mismo, es que si lanzo un análisis contra mi sitio, hace unos días me decía qué versión de WordPress tenía (exactamente), toda la lista de plugins, con sus versiones y sabiendo sie staban actualizados o no, y lo mismo con las plantillas… Ahora me dice una versión casi exacta de la que tengo en realidad de WordPress, pero ya no me dice qué plugins o plantilla tengo.

Esto no significa que si te miras un poco el código no se pueda saber, pero el hecho de que “de forma automática nos e sepa” me hace sentir un poco mejor, porque mucha gente que quiera hacer maldades lo tendrá ligeramente más difícil o, como mínimo, tendrá que dedicarle tiempo humano (y no tiempo máquina) para hacer maldades (a alguien que, la verdad, dudo que le aporte o vaya a conseguir nada útil).

Para acabar, tengo escrito un ¿folleto? de 15 páginas sobre seguridad de WordPress en el que explico con pelos y señales cómo solventar prácticamente todos estos problemas. La cuestión es si debería publicarlo por completo o parcialmente y plantear como vía de negocio / modelo de vida (y más ahora que no estoy trabajando en ningún proyecto y he vuelto al autonomismo) y de esa forma, ofreciendo uns ervicio barato, ofrecer la posibilidad de montar WordPress de forma segura a quien no sepa qué hacer con su sitio web. Aún así, como siempre, si alguien necesita ayuda con algo, parcialmente como parte de la comunidad, parcialmente como modelo de vida, estoy aquí para ayudar.