Desterrrado de GNOME Shell... Mi triste historia u.u


Me gusta mi computadora principal. No es la gran cosa, una HP Pavilion Slimline s5120la con algunas modificaciones y (claro cómo no) Fedora Linux instalado. A lo largo de su vida le he hecho diferentes modificaciones según he necesitado: Mayormente a nivel Software, poco a poco con el paso de los años me ha tocado meterle mano al hardware también. Empecé con una nueva PSU y una nueva tarjeta gráfica. Compré también (aún no llega pero está en camino) un nuevo procesador compatible, el "tope de gama" que la motherboard acepta. Un SSD para mi partición raíz también es prioridad y pienso adquirirlo en la misma tienda que el procesador si todo resulta bien con el primer envío.

¿El problema? La RAM.

La computadora trae por defecto 4GB de RAM, de los cuales (tras reemplazar la gráfica integrada de fábrica por la dedicada que le puse) el sistema tiene acceso a un total de 3.9 (antes del cambio eran 3.4 aprox). Obviamente conforme avanza la tecnología los entornos de escritorio y los programas van necesitando más y más recursos, siendo la RAM el más solicitado. Mi plan era (tras revisar mis consumos actuales de RAM) hacer el upgrade a 8GB cuando de pronto me di cuenta de algo espantoso: La motherboard no admite más de 4GB de RAM aún con un sistema de 64 Bits instalado. Esto es un problema porque para el uso cotidiano que le doy a GNOME Shell 4GB se me van viendo cortos y además si compré el nuevo procesador es porque tengo intenciones de virtualizar sistemas pesados a 64 bits dentro de la misma máquina...

De querer hacer esto último, el usar GNOME Shell queda totalmente descartado del panorama puesto que en sí dicho escritorio en fedora 20 de 64 bits (la versión más actual al momento que escribo esto) consume de 600 a 700 MB (base) y conforme pasa el tiempo debido a procesos como el tracker (lo que permite que encuentres archivos y apps en un chasquido desde su dash) termina operando regularmente en algo bastante próximo a los 2GB con cargas de trabajo medias, dejando la posibilidad de virtualizar totalmente fuera de la ecuación.

Más allá de todo esto (pues si estudiamos mi problema con una mirada objetiva nada que no sea un gestor de ventanas simple me va a dejar virtualizar tranquilamente) Esta computadora ha caído víctima de la obsolencia programada y para "rescatarla" sin tener que volverla servidor y/o cambiar completamente la motherboard, de momento lo único que queda es migrar a un entorno de escritorio ligero y quedarse ahí, cosa que efectivamente hice migrando a XFCE:


Bien pude haber migrado a una distro más ligera (Antergos por ejemplo tiene un gnome-shell que presume de estar en el rango de los 200MB de RAM base) en lugar de seguir usando fedora pero de momento no tengo ni el tiempo ni las ganas de hacer dicha maniobra, ya que en ese caso mejor compro otro equipo o le actualizo la motherboard a este e instalo fedora con GNOME Shell en cualquiera de los casos, así que prefiero confiar en que XFCE se mantendrá ligero el suficiente tiempo como para dejarme usar esta computadora (que de verdad me agrada) sin batallar con los recursos. De momento en mis pruebas sí he notado un cambio en el consumo de recursos que es notable. A lo largo de los días XFCE se ha comportado bastante bien en cargas altas de trabajo y la gestión de recursos es bastante buena. Incluso pude virtualizar un ubuntu con 2GB de RAM asignados y cambiar entre el host y el guest sin mayor problema, mientras los recursos se consumían de manera periódica y no "de jalón" en la máquina virtual.

Lo que sí tengo que destacar es que hay una que otra cosa que me molesta de XFCE en fedora: Para empezar, aunque hice todo el proceso de instalación de mi iOS device como es debido, Thunar no lo monta y tampoco lo hace ningún gestor de archivos, a la fecha no sé porqué (pero sí se que algo tiene que ver con gvfs). Cosas tan simples como cambiar la foto del usuario para el login manager se vuelven algo complejo (al no tener GUI para ello como en otros escritorios o bien, como en otras distros con XFCE como Xubuntu 14.04) y a veces el equipo simplemente no apaga. Por otro lado, aunque tengo deshabilitado el "recordar la sesión" por alguna razón XFCE la recuerda a veces, (contrario a lo que yo he solicitado) abriendo los programas que tenía previamente abiertos al iniciar una nueva sesión en blanco. El sonido fue otro de los problemas que tuve que solucionar ya que a veces no sonaban las bocinas y a veces no sonaban los audífonos, pero deshabilitando el sonido HDMI por el análogo estándar fue todo lo que se necesitaba al final... Las apps predeterminadas del menú de aplicaciones funcionan todas, excepto la de navegador web, que no permite hacer un setting permanente al que esté usando en turno si éste no es Midori.

Fuera de estos glitches, XFCE es un buen entorno de escritorio (aunque en fedora esté demasiado "vanilla") y con un poco de personalización y paciencia se puede lograr tener un workflow muy eficiente, digno de cualquier otro escritorio (de eso no me cabe duda); Lo que sí me entristece un poco es que el XFCE 4.10 de fedora no esté a la altura de digamos, el de xubuntu en el apartado de funcionalidad (dejando del lado el aspecto gráfico que es lo que menos importa) cuando se trata del mismo escritorio. Eeeen fin, veremos lo que el destino nos depara de ahora en adelante usando XFCE y si éste, (en algún momento) se vuelve relevante como alternativa para la comunidad fedoriana de manera que "le echen más ganas" en mejorar la experiencia de usuario en futuras versiones.

¿Qué hacer después de instalar CentOS/RHEL 7.x?


Atención: ¿Quieres probar esta guía en CentOS 7.x x86_64 dentro de un servidor real? Haz click aquí y utiliza los cupones ALLSSD10 y/o DODROPLET al crear tu cuenta en DigitalOcean para conseguir $10 USD de regalo que te servirán para montar un VPS por hasta 2 meses completamente gratis (con costo de $5 USD/mo después si te lo decides quedar).

CentOS es el clon libre del famoso Red Hat Enterprise Linux, un excelente sistema operativo para servidores. Contrario a fedora, (una derivada de RHEL para uso general) CentOS es un sistema más enfocado al uso empresarial con pocos cambios bruscos de versión en versión y soporte por largos periodos de tiempo, además de un kernel especializado para uso en servidores.

En la versión 7.x RHEL (y por lo tanto CentOS) vienen cargados de interesantes novedades entre las que destacan el kernel 3.10.x de serie, XFS como sistema de archivos por defecto, el completo abandono a la arquitectura individual de los 32 bits, Docker, SystemD, MariaDB (en lugar de MySQL por defecto) GNOME 3.8, Firewalld y muchas otras cosas más que pueden resultar bastante interesantes para todos los que manejamos servidores físicos, VPS o de cualquier tipo.

¿Conviene actualizar a CentOS 7.x?

Esta pregunta es algo subjetiva y la respuesta es depende. Depende de varias cosas: ¿Te generará downtime? ¿Es VITAL para ti alguna de las nuevas características? ¿Tienes hardware de 32 bits? Responder a estas preguntas te permitirá darte una idea de si debes o no actualizar a la nueva versión.

Guía de post instalación

Si decidiste instalar CentOS 7.x en tu servidor aquí hay algunas cosas que te podría interesar hacer justo después:

NOTA: Estas instrucciones también son válidas para deployments de Red Hat Enterprise Linux 7.x

1) Instalar nano y wget

Personalmente me hallo más con éstos 2 que con vi y curl; Si también es tu caso, ejecuta:

1. su -
2. yum -y install nano wget

2) Repositorios Extra (Necesarios)

EPEL & Remi:

1. su -
2. wget http://dl.fedoraproject.org/pub/epel/beta/7/x86_64/epel-release-7-0.2.noarch.rpm
3. wget http://rpms.famillecollet.com/enterprise/remi-release-7.rpm
4. sudo rpm -Uvh remi-release-7*.rpm epel-release-7*.rpm

ElRepo:

1. su -
2. rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org
3. rpm -Uvh http://www.elrepo.org/elrepo-release-7.0-2.el7.elrepo.noarch.rpm

Habilitando Remi:

1. su -
2. nano /etc/yum.repos.d/remi.repo


3) Actualizar

Para actualizar todo tu sistema, corre:

su -c 'yum -y update'

4) Configurar Firewall

Primero necesitamos obtener la(s) zona(s) activas:

su -c 'firewall-cmd --get-active-zones'

Este comando nos devolverá el nombre de la(s) zona(s) activa(s) (ej. public) y las interfaces de red que están ligadas a ella(s) como podrían ser eth0, p16p1, wlan0 etc.

Es recomendable también listar los puertos y servicios permitidos en la(s) zona(s) activas para hacer personalizaciones, esto se hace con:

su -c 'firewall-cmd --zone=myzone --list-all'

Obviamente usando el nombre de la zona indicada en lugar de myzone.

Luego para abrir y cerrar puertos podemos usar:

1. su -c 'firewall-cmd --zone=public --add-port=xxxx/tcp'
2. su -c 'firewall-cmd --zone=public --remove-port=xxxx/udp'

Respectivamente, cambiando xxxx por el número de puerto deseado y especificando el protocolo (tcp/udp) según corresponda.

5) Tweaks para rendimiento

Habilitar Tuned:

1. su -
2. yum -y install tuned
3. tuned-adm profile selected_profile

Más información sobre los perfiles disponibles acá: http://red.ht/1ppyozF

Habilitar ZRAM:

1. su -
2. yum -y install bc
3. wget https://spideroak.com/share/PBSW433EMVZXS43UMVWXG/78656e6f6465/srv/CDN/xenodecdn/zram -O /etc/init.d/zram
4. chmod 755 /etc/init.d/zram
5. chkconfig --add zram && chkconfig zram on

Reiniciamos y luego podremos checar que zRAM está corriendo con:

su -c 'service zram status'

Puedes checar más tips para mejora de rendimiento en: http://bit.ly/1hoo5XR

Habilitar Ksplice:

Ksplice es un gestor de paquetes de seguridad del que ya hablamos anteriormente y básicamente permite instalar actualizaciones de seguridad en tu servidor sin necesidad de reiniciar. La versión para RHEL se puede probar por 30 días (con una acces key de trial) y luego se requiere pagar aprox 4 USD/mo por usar el producto (con hasta 20 servidores, a partir de 20 en adelante el costo reduce a 3 USD/mo).

1. su -
2. wget https://www.ksplice.com/yum/uptrack/centos/ksplice-uptrack.repo -O /etc/yum.repos.d/ksplice-uptrack.repo
3. sudo yum -y install uptrack ksplice-uptrack-release
4. nano /etc/uptrack/uptrack.conf

En el archivo del comando #4, requeriremos insertar nuestra clave de acceso como nos lo pide:


Configurar IP Virtual única:

Si esto te interesa, acá nuestro tutorial

SELinux Permisivo:

SELinux es una buena utilidad de seguridad para sistemas CentOS/RHEL, sin embargo su activación puede traer problemas al momento de implementar ciertas cosas en tu servidor. Es por esto que, (al menos en algunos CentOS 7.x de VPS) SELinux viene deshabilitado por defecto y en instalaciones normales viene activado. Personalmente prefiero "algo en medio" y suelo ponerlo en modo "permisivo" esto quiere decir que seguirá funcionando sin conflictuar con otras cosas y en lugar de proteger como tal únicamente nos mostrará advertencias relevantes para que nosotros nos encarguemos de la situación. Poner entonces a SELinux en modo permisivo se hace con:

1. su -
2. nano /etc/selinux/config

Y en el archivo que abrirá cambiamos el status de disabled y/o enforcing a permissive. Guardamos los cambios, reiniciamos y listo.

¿Qué hacer después de instalar CentOS/RHEL 6.x?


Atención: ¿Quieres probar esta guía en CentOS 6.x dentro de un servidor real? Haz click aquí y utiliza los cupones ALLSSD10 y/o DODROPLET al crear tu cuenta en DigitalOcean para conseguir $10 USD de regalo que te servirán para montar un VPS por hasta 2 meses completamente gratis (con costo de $5 USD/mo después si te lo decides quedar).

CentOS 6.5 es el clon libre del famoso Red Hat Enterprise Linux, un excelente sistema operativo para servidores. Contrario a fedora, (una derivada de RHEL para uso general) CentOS es un sistema más enfocado al uso empresarial con pocos cambios bruscos de versión en versión y soporte por largos periodos de tiempo, además de un kernel especializado para uso en servidores.

Si decidiste instalar CentOS en tu servidor aquí hay algunas cosas que te podría interesar hacer justo después:

NOTA: Estas instrucciones también son válidas para deployments de Red Hat Enterprise Linux

1) Instalar nano y wget

Personalmente me hallo más con éstos 2 que con vi y curl; Si también es tu caso, ejecuta:

1. su -
2. yum -y install nano wget

2) Repositorios Extra (Necesarios)

EPEL & Remi:

1. su -
2. wget http://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm
3. wget http://rpms.famillecollet.com/enterprise/remi-release-6.rpm
4. sudo rpm -Uvh remi-release-6*.rpm epel-release-6*.rpm

RPMForge:

32 Bits:

1. su -
2. wget http://packages.sw.be/rpmforge-release/rpmforge-release-0.5.2-2.el6.rf.i686.rpm
3. rpm -Uvh rpmforge-release-0.5.2-2.el6.rf.i686.rpm

64 Bits:

1. su -
2. wget http://packages.sw.be/rpmforge-release/rpmforge-release-0.5.2-2.el6.rf.x86_64.rpm
3. rpm -Uvh rpmforge-release-0.5.2-2.el6.rf.x86_64.rpm

Habilitando Remi:

1. su -
2. nano /etc/yum.repos.d/remi.repo


3) Actualizar

Para actualizar todo tu sistema, corre:

su -c 'yum -y update'

4) Configurar Firewall

NOTA: El comando #5 se debe repetir tantas veces como puertos quieras abiertos, reemplazando xx por el número de puerto que quieres abierto y xxx por "tcp" o bien, "udp" según corresponda.

1. su -
2. iptables -F
3. iptables -L -n
4. iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
5. iptables -A INPUT -p xxx --dport xx -j ACCEPT
6. iptables -A INPUT -j DROP
7. iptables -I INPUT 1 -i lo -j ACCEPT
8. service iptables save

5) Tweaks para rendimiento

Habilitar Tuned:

1. su -
2. yum -y install tuned
3. tuned-adm profile selected_profile

Más información sobre los perfiles disponibles acá: http://red.ht/1ppyozF

Habilitar ZRAM:

1. su -
2. yum -y install bc
3. wget https://spideroak.com/share/PBSW433EMVZXS43UMVWXG/78656e6f6465/srv/CDN/xenodecdn/zram -O /etc/init.d/zram
4. chmod 755 /etc/init.d/zram
5. chkconfig --add zram && chkconfig zram on

Reiniciamos y luego podremos checar que zRAM está corriendo con:

su -c 'service zram status'

Puedes checar más tips para mejora de rendimiento en: http://bit.ly/1hoo5XR

Habilitar Ksplice:

Ksplice es un gestor de paquetes de seguridad del que ya hablamos anteriormente y básicamente permite instalar actualizaciones de seguridad en tu servidor sin necesidad de reiniciar. La versión para RHEL se puede probar por 30 días (con una acces key de trial) y luego se requiere pagar aprox 4 USD/mo por usar el producto (con hasta 20 servidores, a partir de 20 en adelante el costo reduce a 3 USD/mo).

1. su -
2. wget https://www.ksplice.com/yum/uptrack/centos/ksplice-uptrack.repo -O /etc/yum.repos.d/ksplice-uptrack.repo
3. sudo yum -y install uptrack ksplice-uptrack-release
4. nano /etc/uptrack/uptrack.conf

En el archivo del comando #4, requeriremos insertar nuestra clave de acceso como nos lo pide:


Configurar IP Virtual única:

Si esto te interesa, acá nuestro tutorial

SELinux Permisivo:

SELinux es una buena utilidad de seguridad para sistemas CentOS/RHEL, sin embargo su activación puede traer problemas al momento de implementar ciertas cosas en tu servidor. Es por esto que, (al menos en CentOS 6.x de VPS) SELinux viene deshabilitado por defecto y en instalaciones normales viene activado. Personalmente prefiero "algo en medio" y suelo ponerlo en modo "permisivo" esto quiere decir que seguirá funcionando sin conflictuar con otras cosas y en lugar de proteger como tal únicamente nos mostrará advertencias relevantes para que nosotros nos encarguemos de la situación. Poner entonces a SELinux en modo permisivo se hace con:

1. su -
2. nano /etc/selinux/config

Y en el archivo que abrirá cambiamos el status de disabled a permissive. Guardamos los cambios, reiniciamos y listo.

Proteger acceso SSH con Google Authenticator en Linux


Hace tiempo en mi artículo sobre los 6 pasos fundamentales para montar un VPS  les hablaba de la autenticación SSH sin contraseña vía llave RSA como método de seguridad para nuestros servidores. Aunque esta suele ser una muy buena medida de seguridad en contra de atacantes externos y otras amenazas, he aquí una más que les puede resultar interesante para combinarla con la ya antes mencionada: Autenticación SSH a 2 pasos con el Google Authenticator.

El otro día les hablé ya del Google Authenticator y cómo implementarlo en su sitio web y/o app. Básicamente se trata de una aplicación móvil OpenSource que nos facilita la implementación de autenticación a 2 pasos (two factor auth) en una variedad de appliances que queramos lanzar. Para implementarla en nuestro servidor SSH entonces, necesitaremos:


  • Un smartphone: Android, iOS y/o Blackberry
  • El Google Authenticator instalado en dicho smartphone (está en las app stores)
  • libpam-google-authenticator en el servidor


El proceso de autenticación y/o generación de claves (totp tokens) se mantiene en sandbox privado entre tu teléfono y tu servidor sin pasar por servidores externos o algo parecido. Es por esto que a continuación veremos cómo libpam-google-authenticator nos proveerá incluso códigos de rescate en caso de perder acceso a nuestro teléfono para acceder a nuestro servidor.

NOTA: Para este tutorial, usaré Fedora/CentOS/RHEL y Ubuntu como distro(s) de referencia. Para cualquier otra distro el proceso debería ser el mismo mientras se instalen los paquetes equivalentes con el gestor de paquetes correcto según el caso. Los comandos que verán a continuación se deben ejecutar (obviamente) en el servidor deseado.

1) Instalando dependencias

Fedora/CentOS/RHEL

sudo yum install pam-devel make gcc-c++ wget

Ubuntu y Derivados

sudo apt-get install libpam0g-dev make gcc-c++ wget

2) Instalar el Módulo PAM para Google Authenticator

1. cd ~
2. wget https://google-authenticator.googlecode.com/files/libpam-google-authenticator-1.0-source.tar.bz2
3. tar -xvf libpam-google-authenticator-1.0-source.tar.bz2
4. cd libpam-google-authenticator-1.0
5. make
6. sudo make install

3) Configuración TOTP

Esta es la parte un tanto más compleja de la situación porque debe hacerse en base a cómo esté configurado tu servidor SSH (más que nada con qué usuario piensas acceder). En mi tutorial de los 6 tips fundamentales para lanzar un VPS les enseñé que el acceso SSH de root siempre debe mantenerse deshabilitado y únicamente debemos permitir el acceso remoto a un usuario estándar específico. Siguiendo esa lógica de seguridad, nos basaremos en la idea de que ese usuario se llama user en nuestro ejemplo para continuar con este paso... Corremos entonces:

su - 'user' -c '/usr/local/bin/google-authenticator'

Este comando nos pedirá una contraseña (la del usuario en cuestión), preguntará si queremos que los tokens se basen en tiempo (respondemos que sí), nos mostrará un QR o bien, un enlace HTTPS a un QR (que debemos escanear con el Google Authenticator para añadir la computadora) dándonos también acceso a una serie de códigos de rescate que debemos anotar (preferentemente en papel) y almacenar en algún lugar seguro. Finalmente hará varias preguntas de seguridad importantes... Responder a todas ellas con un y (Sí) nos dejará el setup más confiable posible:


4) Configuración SSH

Ahora necesitamos que la computadora haga uso de nuestro módulo PAM para autorizar/verificar el acceso SSH. Para habilitar dicho comportamiento corremos:

sudo nano /etc/pam.d/sshd

Y en el archivo que nos saldrá añadimos la siguiente línea como primer parámetro:

auth       required     pam_google_authenticator.so

He aquí un ejemplo:


Guardamos con Ctrl+O y luego Ctrl+X para después correr:

sudo nano /etc/ssh/sshd_config

Y en el archivo que nos saldrá, cambiamos la variable ChallengeResponseAuthentication de no a yes. Ejemplo:


Guardamos, salimos y finalmente reiniciamos nuestro servicio de SSH con:

sudo service sshd restart y/o sudo /etc/init.d/sshd restart

Y a partir de hoy cada que queramos loguearnos vía SSH a esta máquina, se nos pedirá nuestro token generado por el Google Authenticator (aparte de cualquier otro elemento de autorización que hayamos establecido previamente):


Habilitar el Google Authenticator (two-factor auth) en tu sitio web


El Google authenticator es una aplicación móvil disponible para iOS, Android y al parecer hasta Blackberry que nos auxilia en la implementación de autenticación a 2 pasos en nuestros sitios web. Varios sitios/apps como Evernote, Outlook y Dropbox (por sólo citar algunos ejemplos) lo tienen implementado para permitirle a sus usuarios proteger con una capa extra de seguridad sus preciadas cuentas. La preguna es: ¿Cómo implementarlo en nuestros propios sitios y apps? Sencillo:

1) Generar user_tokens

El Google Authenticator requiere que tengamos a la mano (por cada usuario en nuestro sitio/app) un token individual único. Este token deberá ser generado a partir de una entropía de 10 bits digeridos en formato hexadecimal y después codificados bajo base32, de dicho proceso lo que nos importa es retornar una string de 16 caracteres que podamos almacenar y utilizar como token perteneciente al usuario. Dicha string deberá ser presentada al usuario en formato de código QR después de generada para que pueda "activar" el enlace entre su cuenta en nuestro sitio y el Google Authenticator utilizando su teléfono. Si tenemos por ejemplo una app/sitio MEAN, dicho requerimiento se puede lograr con el siguiente código:


Nótese que este código está hecho para correr en consola únicamente y en una implementación real querríamos asociar el token con algún usuario de nuestro sitio a nivel base de datos (asegurándonos de que el token generado sea único con respecto al de otros usuarios) y mostrarle el QR con la URL generada en alguna vista para que lo pudiera escanear con el Google Authenticator. Si corremos este código en una consola (después de instalar vía npm los módulos crypto y thirty-two en caso de que no los tengamos), veremos que nos devuelve algo como lo siguiente:


El primer parámetro devuelto es el token del usuario y el segundo es la URL del QR que le mostraremos para que lo escanee con su Google Authenticator. Tomamos nota del token y visitamos la URL generada, abrimos Google Authenticator y añadimos un nuevo sitio mediante QR (lo que nos pedirá escanear el código de la URL), una vez hecho esto el resultado será el siguiente (en el móvil):


El totp_token generado (código de 6 dígitos) expirará cada 30 segundos y se seguirá generando uno nuevo para el usuario mientras tenga la aplicación abierta.

2) Validar accesos

Ahora necesitamos una manera de obtener dicho número a partir del token de usuario que nosotros tenemos para después poder implementar algún tipo de validación de acceso en base al google authenticator... Hacer esto es muy sencillo, sólo necesitamos instalar el módulo notp vía npm y nuestro código resultante (de pruebas) se vería así:


Que al ejecutarlo tras proveer el user_token correcto sacado del output del primer script (teniendo el Google Authenticator abierto para verificar), nos debería soltar un output como este:


Donde el código mostrado debería ser mismo en la pantalla del Google Authenticator en dicho momento.

LiveStream de tu webcam con AngularJS

Preámbulo

El otro día fui al banco a activar la banca electrónica para la nueva cuenta que recientemente abrí. Cuando uno hace eso en el banco en el que tengo mi cuenta actualmente (Banorte) se le provee con un token ya sea físico o en el celular (smartphone app) para tener un método de autenticación a 2 pasos y así asegurar (reforzar la seguridad de) el acceso electrónico a las cuentas y su manejo.

El único beneficio real (al menos a mi manera de ver) del token en el celular vs el físico es la posibilidad de tener acceso a tu banca electrónica desde donde sea mientras traigas el móvil contigo. Sin embargo usar el token celular conlleva uno que otro problema de los que no hablaré para no alargar esto... El punto es que terminé pidiendo un token físico para la nueva cuenta y para tener el beneficio de la obicuidad del token celular en mi token físico sin moverlo del escritorio se me ocurrió montar una tokenCam que pudiera revisar desde donde sea cuando así lo necesitara. Hay varias maneras de hacer esto, (transmitir una webcam en vivo de forma semi-privada) de las más conocidas:

El método con VLC es la elección por excelencia de muchos, pero requiere una computadora razonablemente potente con un sistema operativo razonablemente nuevo (Lo que significa que mi servidor CentOS 6 de 32 bits desde donde quiero servir la LiveCam queda descartado por ejemplo).

El método con FFmpeg es más amigable con el hardware usado, pero al necesitar una cantidad fija de banda ancha por cliente, termina consumiendo todo el Internet disponible con pocas conexiones a la LiveCam rápidamente, no es escalable ni rentable por lo tanto.

El método con HTML5 Websockets funciona muy bien en localhost, pero al exponerlo al Internet, el consumo de banda ancha vuelve a ser un problema haciendo que haya una mala experiencia de uso generalmente al tratar de ver el streaming desde un cliente externo.

El software especializado para cámaras IP (como podrían ser motion o bien, zoneminder por ejemplo) resultó ser por demás complejo de configurar y abarcaba muchas más cosas aparte del objetivo que quería cumplir, además de proveer de resultados malos (pésima calidad de streaming, con bastante lag encima).

Intentar con WebRTC era otra opción, pero implementar algo con dicha tecnología quedó fuera de mis opciones al ver que (al menos de momento) sigue muy verde del lado de los móviles. En mi caso específico es importante poder acceder la tokenCam desde mi iPhone sin mayor problema.

Entonces, ¿Cómo haremos nuestro streaming?

Para empezar, necesito que todos estemos en la misma página: Hacer un Livestreaming directo es "carísimo" (hablando de banda ancha e incluso recursos de hardware) es por esto que las plataformas y/o servicios que ofrecen esta funcionalidad delegan la carga de la transcodificación y el streaming como tal por medio de plugins propietarios del lado del cliente (Flash, Silverlight, Complemento de Google Hangouts) evitando gastar demás en recursos propios y/o del servidor. Para mi implementación no quise depender de un plugin externo con la finalidad de asegurar la máxima compatibilidad multiplataforma del lado de los clientes; Sin embargo los problemas de recursos seguían siendo los mismos: Para que se hagan una idea, un streaming de baja resolución (VGA) a 320Kbps (por ejemplo) representa un gasto de banda ancha de más o menos 3GB diarios en transferencia sin que nadie lo vea. Cada 24 horas de alguien viéndolo (incluso si es únicamente un solo cliente atendiendo al streaming sin parar) añade otros 3GB de banda ancha en transferencia a los previos tres ¡Demasiado! La solución con la que ataqué este problema fue muy sencilla y creo que a más de un lector le va a parecer incluso gracioso... Continúa leyendo para conocer los detalles.

NOTA: Para este tutorial usaré Fedora Linux como sistema operativo de referencia, pero estas mismas instrucciones aplican para otras distros linux e incluso otras plataformas (como Windows u OS X) mientras instales los programas/dependencias utilizados según el método correcto para tu sistema con algunas pequeñas modificaciones en los pasos citados según corresponda.

Primero: Instalar dependencias

1. sudo yum -y install python ffmpeg git git-core

Segundo: El servidor y la webapp

Ahora necesitarás descargar la aplicación de AjaxCam (que yo hice) desde Github con la finalidad de ahorrarte varios pasos extra:

1. cd ~
2. git clone https://github.com/Jmlevick/ajaxcam.git
3. cd ajaxcam
4. python pythonserverGzip.py 9229

Esto debería iniciar la interfaz web de nuestra livecam en el puerto 9229 de nuestro localhost, ahora sólo nos falta el streaming para transmitir:



Tercero: Comenzar Streaming

¿Recuerdan la solución de la que les hablaba? Se trata de lo siguiente: Tomaremos una fotografía de 1 a 15 fotogramas según nuestro setup (sí, por raro que esto suene) cada segundo con nuestra cámara web vía ffmpeg y la imagen resultante de la captura será guardada a 1 solo contenedor JPEG que refrescaremos en tiempo real sobreescribiéndolo. Luego vía ajax (gracias a AngularJS en este caso) lo que hace la interfaz que descargaste y estás corriendo en tu localhost en estos momentos es refrescar la imagen en vivo cada segundo también, dando la ilusión de estar emitiendo un "feed de video en vivo" o bien, Livefeed. Lo mejor de este enfoque es que no sólo es "amigable con el hardware" al no consumir demasiados recursos sino que también es amistoso con tu banda ancha, al no consumirla a menos que un cliente accese al streaming per sé, en cuyo caso consumirá (según el peso de tus imágenes) alrededor de 3+ veces menos (gracias al setup montado y al servidor Python con compresión Gzip que utilizaremos) que un livefeed real (con calidad equivalente) asumiendo 24 horas continuas de estar enganchado al stream. La única "pega" que podría encontrarle a este enfoque es que tiene un poco de lag sí o sí, pero a final de cuentas todos los métodos de streaming directo lo tienen en mayor o menor cantidad. En cuanto al audio, si es algo que te interesa no es difícil de implementar y si lo necesitas estás más que invitado a implementarlo y hacer una pull request al proyecto en Github de la AjaxCam (yo no lo he implementado porque no lo necesito en mi setup para la tokenCam).

Una vez explicado esto, prosigamos:

Posiciona tu cámara donde la vayas a dejar haciendo streaming. Puedes "calibrar" la posición con cualquier app de cámara que tengas a la mano, (en Linux está Cheese por ejemplo) y después correremos los siguientes comandos en otra pestaña de nuestra consola:

1. cd ~/ajaxcam
2. ffmpeg -y -f v4l2 -s 320x240 -i /dev/video0 -update 1 -r 15 -threads 0 -qscale:v 2 output.jpeg

Del segundo comando lo que nos importa en parámetros es lo siguiente:

  • -s 320x240: De qué tamaño queremos las imágenes
  • -i /dev/video0: El dispositivo de captura. En Linux todas las webcam se "localizan" como /dev/videoX si sólo tienes una conectada y/o disponible, es la 0 (como en mi caso), la segunda sería la 1 y así.
  • -r 15: Número de fotogramas por segundo. Si el lag es un problema, déjalo en un rango de los 15 a los 30 para evitar lo más posible la latencia (o intenta incrementarlo incluso) Si la disponibilidad se ve afectada (que la imagen desaparezca de pronto y/o muy seguido) reduce este número. Puedes dejarlo hasta en 1 para obtener la mayor disponibilidad a costa de unos segundos extra de latencia. En equipos poco potentes es recomendable dejar este parámetro en 15.

NOTA: El comando de ffmpeg para otras plataformas puede variar un poco, te recomiendo pedir asesoría en sus listas de correo o en sus foros para hallar el comando correcto de captura según tu caso... Los parámetros sin embargo, deberían ser los mismos en todos los casos.

En mi caso tengo una (algo antigua) cámara VGA que usaré para mi setup, so el comando que se ve arriba es perfecto para mi situación específica (además cada segundo cuenta cuando hablamos de un token, estos parámetros garantizan también poco lag). Ahora nos vamos a http://lvh.me:9229 o bien http://localhost:9229 y deberíamos ver nuestra LiveCam activa en la interfaz web. Si esto no es así, trata cortando el streaming de ffmpeg y reiniciándolo o bien, cambiando el parámetro de los FPS (de 15 a 25 por ejemplo) y volviéndolo a iniciar.

Finalizando: ¡A transmitir!

Todo esto está muy bien, pero ¿cómo podemos (por ejemplo) acceder este live feed desde nuestro móvil o bien darle acceso a otros? Sencillo. Suponiendo que no tengamos una IP pública/fija, utilizaremos ngrok (clic en el enlace para conocer más y hacer el setup si no lo tienes en tu sistema); Iniciar un servidor accesible al público para nuestra LiveCam con esta herramienta es tan sencillo como correr:

ngrok 9229

Eso nos soltará una URL en la consola del tipo:

http://234ab123.ngrok.com

Que podemos utilizar/visitar desde cualquier cliente externo para revisar nuestra LiveCam cuando queramos. Cabe destacar que ngrok puede bajar (de manera notable) el rendimiento de nuestro streaming por razones totalmente ajenas a nuestra AjaxCam. Si realmente piensas servir esta LiveCam, no olvides añadir al inicio del sistema los siguientes comandos (que deben correr como tu usuario desde tu Home); Puedes establecer este comportamiento de muchas maneras: con autostart (aplicaciones al inicio del escritorio) un cronjob o bien, desde tu rc.local:

1. cd ajaxcam
2. nohup ffmpeg -y -f v4l2 -s 320x240 -i /dev/video0 -update 1 -r 15 -threads 0 -qscale:v 2 output.jpeg >/dev/null 2>&1 &
3. nohup python pythonserverGzip.py 9229 >/dev/null 2>&1 &
4. ngrok start mycam

NOTA: Como explicamos en nuestro tutorial de Ngrok, es posible personalizar la URL de nuestro túnel para evitar que ésta cambie aleatoriamente con el paso de los días, en este caso estoy iniciando el túnel mycam previamente establecido en la configuración de Ngrok directamente.

Y pues bueno, esto es todo... Si te gustó el post, no olvides compartirlo, darle like, recomendar este blog y demás; Cabe destacar que esto es sólo una implementación básica y cada quien puede "extenderla" según sus necesidades (control de acceso para mayor seguridad por ejemplo). Eeen fin, eso ya depende de cada uno.

Nos leemos en los comentarios.

Programación multi-hilo en NodeJS: ¡Castiga a ese procesador!


Ok, me emocioné... jaja

Para todos aquellos que no lo sepan, (en muchos casos) por defecto NodeJS sólo utiliza 1 sólo núcleo (y proceso) aún en una computadora con multi-cores disponibles. Esto quiere decir que (en algunos casos) si corres un programa/aplicación NodeJS en una computadora con 2 o más núcleos en procesador (o en un clúster con varios a la mano pues) NodeJS no aprovechará por defecto toda la capacidad de cómputo que tenga disponible.

Para la mayoría de aplicaciones e implementaciones esto no suele ser relevante, (sobretodo si hablamos de scripting donde en muchos casos aunque NodeJS inicie un sólo proceso éste puede llegar a usar todos los cores dependiendo de para qué esté diseñado el script en cuestión).

Sin embargo, si vas a procesar grandes cantidades de datos a través de un script/app de NodeJS, deberías considerar hacer programación multi-hilo (que aproveche todos los núcleos disponibles y lance diferentes procesos por núcleo) en dicho caso... Lo mismo si el rendimiento es importante para ti y ves que tu aplicación está corriendo actualmente a un sólo núcleo (como es común en servidores HTTP creados con NodeJS y respectivamente en web frameworks como ExpressJS por ejemplo).

Y a todo esto, ¿Cómo se hace?

Sencillo. Se utiliza el módulo cluster de NodeJS:

npm install cluster

Y su uso es bastante sencillo, veamos el ejemplo:

monocore.coffee

Este script funciona únicamente con un sólo núcleo, y el resultado de ejecutarlo es el siguiente:


Para hacerlo multi-hilo, tenemos que adaptarlo así:

multicore.coffee

Y el resultado de ejecutar la nueva versión sería:


Como verán, el primer script llena un sólo núcleo de nuestro procesador con la tarea a realizar mientras el otro se mantiene libre de presión alguna. En cuanto clusterizamos nuestro script el proceso se hace multi-hilo y entonces empezamos a usar todos los cores disponibles en la máquina (en el caso de mi ejemplo 2), abriendo un proceso nuevo de node por c/u también (más aparte uno extra que corresponde al proceso del clústering):

Kernel VM tunnings para mejorar rendimiento en Linux



NOTA: Un buen inicio antes de hacer los tunnings de este post para mejorar el rendimiento de tu linux es habilitar las mejoras de las que hablamos acá, una vez aplicadas puedes reforzar con los settings específicos de este post. Cabe destacar que éstos aplican para cualquier distro/sistema que utilice el kernel línux como su núcleo.

Prefacio

Ayer estuvimos todo el día probando (y considerando) la opción de migrar nuestro deployment a docker, el nuevo engine para containers linux (más de eso después). Sin embargo a final de cuentas no resultó algo factible por algunas razones y tras ver esto, simplemente se optó por darle una manita de gato a los servidores del setup actual "ya que estábamos en eso" jaja...

Hoy les hablaré de cómo mejorar el rendimiento de sus equipos y servidores linux con 4 perfiles especializados de VM Tunnings (virtual memory tunnings) para el kernel según el caso, sin embargo cabe destacar que lo primero que hemos de hacer para asegurar la máxima efectividad de dichos tunnings es establecer en nuestros equipos unix limits de grado empresarial como los que nos recomiendan los chicos de 10Gen (MongoDB), Oracle y/o Red Hat. Para aplicar estos ulimits simplemente añadimos el bloque de comandos mostrado a conitunación a nuestro rc.local:

ulimit -f unlimited
ulimit -t unlimited
ulimit -v unlimited
ulimit -n 64000
ulimit -m unlimited
ulimit -u 64000

A algunos les podrán parecer altos estos límites, pero ¡no se preocupen! son necesarios. Además, los settings que estableceremos a continuación asegurarán un óptimo funcionamiento de sus equipos/servidores, evitando condiciones "out of memory" y procesos erráticos entre otras cosas.

Swap y Swappiness

Hace tiempo les comentaba de los problemas de memoria que teníamos en nuestro droplet de 512MB dentro de DigitalOcean por un descuido en la alocación de swap para un VPS que estaba destinado a hacer las tareas que éste realizaba. Aunque la alocación de swap y swappiness (en las medidas adecuadas) son vitales para el correcto funcionamiento de un servidor/equipo linux, éstos no son los únicos settings que nos pueden ayudar a tener las cosas funcionando cual maquinaria de reloj suizo, pero sí son un inicio. Como bien nos lo dice la guía de Red Hat:

swappiness
A value from 0 to 100 which controls the degree to which the system swaps. A high value prioritizes system performance, aggressively swapping processes out of physical memory when they are not active. A low value prioritizes interactivity and avoids swapping processes out of physical memory for as long as possible, which decreases response latency. The default value is 60.

Aquí es recomendable aclarar que, (en desktop) si tienes un equipo con RAM limitada (=< 512MB por ejemplo) es buena idea establecer este parámetro a 90 o 100 y si tienes un equipo con bastante RAM (10 GB en adelante) puedes experimentar reduciéndolo a 10 siempre y cuando estés consciente de que tu RAM no se te ha llegado a saturar de manera notable en el pasado (de lo contrario deberías optar por dejar la opción por defecto). Para todos los que están en medio de los rangos citados, el valor predeterminado de 60 es una opción inteligente.

Ahora bien, este valor va muy de la mano con la cantidad de swap disponible en tu sistema, que se debe ajustar acorde a la siguiente tabla (cortesía de Red Hat):


Dirty ratio & Dirty background ratio

Estos son 2 settings súper importantes, ya que determinan la cantidad de memoria (RAM) que un determinado proceso de paginado puede consumir antes de tener que ser "limpiado" hacia disco duro. Linus Torvalds nos da una excelente explicación de porqué estos parámetros se deberían de mantener bajos siempre; Esta "regla" aplica tanto para servidores como para equipos de escritorio con mucha (256GB) o poca (256MB) RAM. Básicamente, para que se entienda mejor, (según lo establecido en estos parámetros) la memoria de tu sistema se irá llenando poco a poco de pequeños pedazos de data que necesitan ser escritos a disco hasta que se alcance el porcentaje establecido en el dirty_ratio, para cuando entonces pdflush entrará en acción y empezará el "writeout" hasta balancear la "carga en la memoria" a la cantidad establecida en el dirty_background_ratio, liberando así esa parte para cosas más importantes. Los valores adecuados para estos 2 parámetros en todos los casos son:

dirty_ratio=10
dirty_background_ratio=5

Hablaremos sobre cómo establecerlos más adelante.

Overcommit Memmory & Overcommit Ratio

Estos 2 son prácticamente exclusivos de servidores (sobretodo aquellos con menos de 1GB de RAM) y funcionan así: Cuando activamos el overcommit_memory, el sistema impedirá que se llegue a un punto donde se consuma toda la SWAP + la cantidad de RAM establecida en el overcommit_ratio. Ésto evita que el sistema llegue a condiciones "fuera de memoria" por aplicaciones erráticas o procesos duplicados, entre otras cosas. No aplica para escritorio porque en escritorio no hay un control real de lo que se está ejecutando, así que establecer estos parámetros puede llevar a comportamientos no deseados (como por ejemplo una pestaña de Chrome "crasheando" para liberar la memoria establecida en los overcommits de pronto o un proceso determinado no ejecutándose porque éstos parámetros "caparon" el uso de la memoria); En escritorio vale más confiar en la swappiness y los valores de los que ya hablamos anteriormente (a menos que se tenga menos de 1GB de RAM, caso en el que se podría considerar activar estos parámetros también). Más sobre los valores adecuados para los overcommits (según el caso) al final; Cabe destacar que éstos settings van muy de la mano con los parámetros del OOM que veremos a continuación.

Settings del OOM

El Out of Memory Killer es un proceso de rescate en Linux que "sale a la carga" una vez que un proceso errático (o repentino) genera una condición Out of Memory (se come la memoria de pronto). Hay 2 settings especialmente útiles para este proceso (que igual sólo aplican en servidores, en este caso de cualquier tipo) y que nos permitirán evitar condiciones OOM y/o bien, malfuncionamiento/comportamiento errático. Éstos son panic_on_oomoom_kill_allocating_task. El primero (tras activarse) habilitará el comportamiento del OOM Killer haciendo que cuando el sistema se quede sin memoria este proceso pueda rescatarlo de una condición errática matando procesos "truhanes" (erráticos) para balancear la carga. El segundo sólo entrará en acción como failsafe si el primero fallara en su tarea de rescatar el sistema matando la tarea que provocó a final de cuentas la condición out of memory asegurándonos operabilidad en cualquier caso en lugar de un panic. Es importante aclarar que al igual que en el caso pasado, se puede considerar habilitar éstos parámetros en un equipo de escritorio con menos de 1GB de RAM también.

Más sobre los valores adecuados para éstos 2 parámetros (según el caso) al finalizar.

Finalizando...

A continuación les mostraré 4 perfiles distintos de éstos diferentes parámetros según el caso (y cómo aplicarlos) para tener un mejor rendimiento (y uptime) en sus equipos/servidores. Si quieren aprender más sobre lo que hacen estos parámetros (y qué otros existen) no olviden checar este enlace.

NOTA: para aplicar los settings que estableceremos en los siguientes perfiles dentro de nuestros equipos/servidores tenemos que editar como root el archivo /etc/sysctl.conf y poner el bloque del perfil deseado al final de dicho archivo, apagando los equipos optimizados después (y volviéndolos a encender) para hacer un flush real de la memoria y hacer efectivos nuestros nuevos ajustes desde cero.

Perfil 1: VPS pequeño y equipos con memoria limitada (=< 512MB RAM)

# Swappiness & Memory Tunning
vm.swappiness=100
vm.overcommit_memory=2
vm.overcommit_ratio=50
vm.oom_kill_allocating_task=1
vm.dirty_ratio=10
vm.dirty_background_ratio=5

Perfil 2: Servidor físico (>= 1GB RAM)

# Swappiness & Memory Tunning
vm.swappiness=60
vm.panic_on_oom=0
vm.oom_kill_allocating_task=1
vm.dirty_ratio=10
vm.dirty_background_ratio=5

Perfil 3: Equipo de escritorio (< 10GB RAM)

# Swappiness & Memory Tunning
vm.swappiness=60
vm.dirty_ratio=10
vm.dirty_background_ratio=5

Perfil 4: Equipo de escritorio (>=10GB RAM)

# Swappiness & Memory Tunning
vm.swappiness=10
vm.dirty_ratio=10
vm.dirty_background_ratio=5

Prueben los perfiles citados y tras un tiempo de uso dejen su experiencia en los comentarios.

[Clientes] Rockactivist: Escúchalo, Vívelo, Deséalo...


El día de hoy les voy a hablar del proyecto Rockactivist.com nuestros más recientes clientes. Rockactivist (acorde a sus creadores) se trata de lo siguiente:

Sitio web de Música, Entretenimiento y Estilo de vida. Entérate, escucha, observa, vive y desea lo mejor de la industria.

Si me lo preguntan a mi, describiría a rockactivist como una revista digital moderna en formato de blog con actualizaciones diarias sobre contenido fresco e interesante para los lectores hispanohablantes. Si te suscribes a su feed rss (¡es completamente gratis, háganlo!) encontrarás diariamente artículos interesantes sobre diversos temas que giran en torno a las 3 categorías principales ya citadas anteriormente; Dentro de este ecosistema entran todo tipo de notas relevantes sobre los eventos musicales del momento (lanzamientos de álbumes, conciertos, datos curiosos sobre tus bandas/artistas favorit@s y más) opiniones y anuncios sobre películas, obras de teatro e incluso uno que otro post geek sobre las últimas novedades en el mundo de la tecnología, los videojuegos, las redes sociales y el internet.

Con su polifacético abanico de autores, Rockactivist tiene un toque distintivo con respecto a otros sitios similares y ofrece publicaciones para todos los gustos. No importa en qué país te encuentres, si hablas español, dale una vuelta a rockactivist.com añadiéndolos a donde te sea más cómodo para estar al tanto de sus notas:




Aquí cabe destacar que si te quieres entretener un rato, darle like a su página de facebook es un must-do puesto que si algo saben hacer los chicos de rockactivist es contar historias y lo hacen de una manera genial a través de su facebook con cada una de sus publicaciones (además de que ponen unos memes buenísimos que no te puedes perder jajaja).

¿Qué se hizo con Rockactivist?

Los chicos de Rockactivist se encontraban hospedados en un hosting compartido que les estaba causando problemas de rendimiento y disponibilidad, así que tras hacer un estudio exhaustivo de su caso se les ofreció un paquete de servicios personalizado que incluyó (a grandes rasgos) los siguientes puntos:

Migración a VPS personalizado

Les montamos un VPS con CentOS 6.5 (Linux) de 32 Bits y 1GB de RAM (lo recomendable para su deployment específico), se optimizó cada centímetro de este VPS acorde a sus necesidades.


Optimización del Backend 

Implementación de Stack LEMP optimizado: Linux, Nginx, MariaDB, PHP y la obligatoria actualización de su versión de Wordpress pasada a la última disponible


Optimización del Frontend 

Minificación de assets, compresión y caché habilitados para los mismos, entre otras cosas. Todo lo que se realizó aquí fue siguiendo las guidelines oficiales de Google.

Seguridad

Habilitamos IP Spoofing para su VPS, protección contra ataques Dos/DDoS y un sistema de mirroring de contenido para alta disponibilidad aún en eventos de caída del servidor.

Social Media

Se les entregó un manual de procesos personalizado para ejecutar 3 campañas específicas en sus redes sociales más importantes según metas específicas que se esperan y/o necesitan cumplir.

SEO

Se les entregó un manal de procesos personalizado con 3 best practices específicas para su caso que se debían llevar a cabo para mejorar su posicionamiento en buscadores.

Regalos que se incluyeron


  • Todos los gastos de la migración fueron solventados por nosotros
  • 3 meses de renta pre-pagados para su nuevo VPS
  • Campaña personalizada con valor de $200 MXN en Adwords
  • Cupón de $200 MXN para campaña en Bing Ads
  • Estudio de mercadotecnia digital a 4 flancos + competencia
Si te interesa obtener un servicio así no dudes en contactarnos y pues no te olvides de entrar a rockactivist.com

Un Saludo. 

¿Porqué la #Swap es importante? Un ejemplo práctico


Hace días publicamos un artículo donde mencionábamos 7 tips para mantener tu linux rápido y responsivo con el tiempo. En el último punto, (el 8vo) se mencionaba algo sobre "los mitos de la swap" y las de alguna manera "falsas" afirmaciones que algunas personas hacen sobre "estar mejor sin swap" o "haciendo poco uso de ella".

En el artículo citado se explica a fondo porqué esto es más falso que cierto (así que si les interesa saber y no lo han leído háganlo) Pero citaré otro ejemplo práctico a continuación:

Y... Se nos cayó el clúster

Ayer, varias horas después de lanzar el deployment de alta disponibilidad para Xenode Systems de pronto alguien nos envió un tweet mencionando que encontró un error en la página. Esto no era normal puesto que todos los sistemas estaban operacionales según el sistema de alertas y de tener error, (al no ser fatal según un chequeo rápido puesto que como ya expliqué los sistemas supuestamente estaban operando de manera normal) éste debería repararse por sí solo antes de ser notado por alguna persona debido a la naturaleza failover del clúster.

Hice la revisión de la página y ¡sorpresa! Error 404 en la página principal... (NOTA: Este tipo de error se tiende a deber a un comportamiento errático dentro del replica set de MongoDB); El debugging me llevó tan solo unos minutos y logré rastrear el punto de origen hasta un reseteo no programado en nuestro VPS dentro de DigitalOcean (que detecté gracias al comando uptime). Al principio señalé culpables con el dedo:


  • Que si DigitalOcean ("seguro reiniciaron los VPS", me dije)
  • Que si MongoDB (No estoy seguro de la causa, pero igual tuve mis sospechas)


Así que abrí un ticket de soporte y en lo que me atendían seguí haciendo el debugging del sistema. Al final resultó que la falla no estaba ni en el replica set de MongoDB (per sé) ni era culpa del staff de DigitalOcean (per sé), sino a que el enlace con la VPN que comparten las máquinas del clúster se había roto y no podían "encontrarse" de regreso. Según un miembro del staff de soporte en DigitalOcean, lo más probable era que el rebooteo inesperado se haya debido a que de pronto el VPS consumió tanta RAM que se quedó sin memoria y decidió reiniciarse por sí solo (como pude verificar tras checar /var/log/messages efectivamente). Esto me pareció extraño puesto que aún cuando el droplet tiene poca memoria tampoco es como si hiciera mucho y además tiene una swap montada sobre un SSD (que debería ser rápida a comparación de la montada sobre un disco duro) como memoria de respaldo.

Después recordé que habilité tuned dentro de mi VPS pero no en el perfil que uso normalmente para mis servidores sino en el de virtual-guest (ya que un VPS es una máquina virtual en sí) mismo que decrementa el valor de vm.swappiness por defecto y lo deja en 10 en lugar de 60 (siendo este último lo normal), haciendo que el sistema use con menos frecuencia y/o con menor preferencia la swap y por ende se quede sin memoria más fácilmente al acabarse la RAM disponible, empezando a matar procesos importantes (y/o cayendo en panic) para "subsistir" causando (como ya vimos) comportamientos erráticos inesperados en algunos deployments.

Obviamente la solución radicaba en cambiar dicho comportamiento para que el sistema usara la memoria total disponible (RAM + SWAP) en la manera distribuida normal en lugar de discriminar el uso de swap en favor de "más velocidad" ya que para un VPS (aún siendo una máquina virtual) que hace lo que el que tenemos para el clúster dicha discriminación no tiene sentido y/o beneficio (sobretodo cuando la swap se monta sobre de un SSD y se tiene zRAM habilitado). Con dado conocimiento en mente, cambié el perfil de tuned al que uso normalmente en los servidores físicos (throughput-performance, mismo que mantiene el valor de vm.swapiness en el 60 convencional) y añadí más swap sobre SSD al VPS para evitar que estas cosas pasaran en el futuro.

Extra: ¿Cuánta swap necesito?

La tabla que verán a continuación (cortesía de Red Hat) es un buen punto de referencia al momento de decidir cuánta swap usar en un setup determinado:


Así que como verán, ¡la swap es importante! tanto que su falta o disposición puede significar MUCHO para el uptime de tu sitio web, sobretodo en entornos con RAM limitada.

MongoDB: bypass the 2GB limit on 32 Bits


If you have a 32-Bit server, you might have noticed that MongoDB by default doesn't allow you to store more than 2GB of data on a specific mongod process (because of the virtual addressable space available on such deployments) so, how can we bypass this limit? the answer is with sharding:

NOTE: I'll be using a Fedora Linux as main O.S. for my examples, these commands may also apply for CentOS/RHEL and with very little modifications, any *nix O.S. out there.

What is sharding?

Sharding is the process by which we split (replication included) a MongoDB database across multiple servers (or mongod processes running on a single machine like in this case). Let's see how to implement it:

First: Configure a Shard

We'll need to setup a shard on the machine so it can use two mongod instances (and sync between them) instead of one. You can initiate as many "nodes" as you need to increase your storage (in groups of three, as they're replica sets): Every usable mongod you add to the shard is going to increase database's total storage by 2GB; In this particular case, we're going to launch 2 usable mongod instances and one arbiter in one shard (usually for every shard we launch, we put in it only three nodes in a "replica set fashion" and if we need more nodes, we create another shard of three); But in this case as I said before I'll create one shard with two nodes in it (so in a 32-bit machine this setup will increase my storage up to 4GB):

1. su -
2. mkdir -p /data/shard0
3. chown user /data/shard0
4. cd /data/shard0
5. mkdir -p rs1 && mkdir -p rs2 && mkdir -p rs3
6. chown user rs1 && chown user rs2 && chown user rs3
7. service mongod stop && chkconfig mongod off
8. mongod --replSet myShrd --logpath "s0-r1.log" --dbpath /data/shard0/rs1 --port 37017 --fork --shardsvr
9. mongod --replSet myShrd --logpath "s0-r2.log" --dbpath /data/shard0/rs2 --port 37018 --fork --shardsvr
10. mongod --replSet myShrd --logpath "s0-r3.log" --dbpath /data/shard0/rs3 --port 37019 --fork --shardsvr

Here, you have to replace user with your standard username (not root) and myShrd with the name you want for your shard, then, we'll continue in a standard user terminal (not root):

1. mongo --port 37017
2. config = {_id: "myShrd", members: [{_id: 0, host: "Hostname.local:37017"}, {_id: 1, host: "Hostname.local:37018"}, {_id: 2, host: "Hostname.local:37019", arbiterOnly: "true"}]}
3. rs.initiate(config)

Second: Create ConfigServers

And that will fire up our Replica set ready for sharding... (Note that you need to change myShrd with the name of your shard in the above commands also); Then we exit the mongo shell with CTRL+D and we need to create a config-servers setup, normally for production we'll use three of these (no matter how many shards/nodes we have):

1. su -
2. mkdir -p /data/config
3. chown user /data/config
4. cd /data/config
5. mkdir -p config-a && mkdir -p config-b && mkdir -p config-c
6. chown user config-a && chown user config-b && chown user config-c
7. mongod --logpath "cfg-a.log" --dbpath /data/config/config-a --port 47017 --fork --configsvr
8. mongod --logpath "cfg-b.log" --dbpath /data/config/config-b --port 47018 --fork --configsvr
9. mongod --logpath "cfg-c.log" --dbpath /data/config/config-c --port 47019 --fork --configsvr

Same rules apply here, change user with your standard (non-root) username in the commands

Third: Tie-up Everything

Now we need to "connect the dots" with a mongos process:

1. su -
2. mongos --logpath "mongos-1.log" --configdb Hostname.local:47017,Hostname.local:47018,Hostname.local:47019 --fork

And finally (as a standard user, non-root) we "glue" everything with:

1. mongo
2. db.adminCommand({addshard: "myShrd/Hostname.local:37017"})
3. db.adminCommand({enableSharding: "myDB"})
4. db.adminCommand({shardCollection: "myDB.collection", key: {theKey: 1}})

Where:

  • myShrd is the name of your shard (selected in the first step)
  • myDB is the name of the DB where you want sharding enabled
  • myDB.collection is the the collection (in the DB) you wanna shard
  • theKey is the name of the indexed field you're going to use as a shard key

All of this might seem a little cumbersome at first but is easy to get used to it, just try it and you'll see...

Extra: Running all on boot

The best way I've found to make this setup work at boot, is with an autostart script runned via the nohup command (so we can keep a log). The script doesn't seem to work with other methods such as rc.local, just autostart... To implement this, just run the following commands to download the script and make it executable:

1. wget https://spideroak.com/share/PBSW433EMVZXS43UMVWXG/78656e6f6465/srv/CDN/xenodecdn/replSet.sh -O ~/replSet.sh
2. chmod +x ~/replSet.sh

Once downloaded, edit it according to your own setup (change the Hostname variable, the name of the shard, the paths, etc). If your server has a graphical desktop then adding this script won't be hard: for example in GNOME we just have to open the gnome-session-properties dialog (via Alt+F2) and add the following command there:

nohup path/to/the/script


And that's pretty much it, you're now bypassing MongoDB's limits by using sharding. Verify by rebooting your computer (so the script can run) and then enter the mongo shell in a terminal, you'll see something like:


¿Chrome congela tu máquina? 3 tips para hacer que consuma menos RAM/recursos


Últimamente he tenido un grave problema que me desespera bastante... Cuando estoy usando Google Chrome de modo heavy duty ocasionalmente termina congelando mi máquina. Tras mucho investigar (e incluso considerar el comprar más RAM (pues ahorita tengo 4GB solamente en mi máquina de escritorio), di con la combinación perfecta de tips que terminaron solventando el problema de raíz:

1) Comprimir RAM/Swap (sólo linux)

Si como yo usas un sistema operativo linux (yo uso fedora) el primer paso que te recomendaría seguir sería habilitar un optimizador de RAM/Swap como podrían ser zRAM (para ubuntu y derivadas) o Zswap (para el resto de distribuciones). En OS X a partir de la versión Mavericks ya tenemos una función similar por defecto en el sistema con AppNap y en Windows no hay manera realmente funcional de aplicar este tip, so si estás en Windows puedes obviar este paso.

2) Evitar la ejecución en segundo plano

Algunas apps de Chrome tienden a mantener su proceso abierto para siempre (como un daemon) aún cuando el navegador está cerrado, esto termina haciendo que aunque cierres chrome procesos atados al navegador se sigan ejecutando consumiendo tu RAM. En versiones recientes del navegador (con la inclusión de las apps standalone y otras mejoras) ya no hay una razón práctica para dejar esta función activa, por lo que para desactivarla nos iremos a Configuración>Mostrar Configuración Avanzada>Sistema y deshabilitaremos la opción pertinente:

Con tan sólo habilitar estos 2 tips, noté que los freezes causados por chrome se redujeron a la mitad, pero aún eran notorios... So, seguí optimizando.

3) Instalar The Great Suspender

The Great Suspender es una extensión que se encarga de suspender las pestañas abiertas inactivas automáticamente por nosotros. Instalamos la extensión, nos vamos a su menú de configuración y la adaptamos de la siguiente manera:



NOTA: Si te encuentras con que tus pestañas están siendo suspendidas muy seguido para tu gusto, cambia 5 mins por 15 mins, en mi caso los 15 fueron la medida justa y perfecta :)

Finalizando...

Una vez aplicando estos tips (y reiniciando chrome), veremos que nuestra PC deja de congelarse por culpa del navegador, así tengamos un buen puñado de pestañas abiertas como se acostumbra a usar hoy en día. Un tip extra que puedes aplicar para optimizar aún más el consumo de recursos por parte de Chrome es desactivar las extensiones (ojo: no apps) que no uses realmente o que no necesites a diario, activándolas sólo cuando te sean necesarias. Es importante mencionar que las extensiones son en parte las culpables del mayor consumo de recursos por parte de Chrome a lo largo del tiempo, so gestionarlas a voluntad es una buena práctica también.

Instalar MongoDB en CentOS/RHEL 6.x [Live 5/06/2014]


Para instalar MongoDB en CentOS/RHEL tenemos que hacer lo siguiente:

1) Agregar el repositorio oficial

1. su -
2. touch /etc/yum.repos.d/mongodb.repo
3. nano /etc/yum.repos.d/mongodb.repo

Y en el archivo que nos saldrá ponemos el código del repo acorde a nuestra arquitectura:

32/64 Bits (recuerda presionar en Raw):

https://gist.github.com/Jmlevick/ac8ecbff8b6dc0da91cf

2) Instalar Dependencias & MongoDB

sudo yum install gperftools-libs mongodb-org

3) Configurar

1. su -
2. mkdir -p /data
3. sudo chown user /data
4. service mongod start
5. chkconfig mongod on

NOTA: Reemplaza user por el nombre de tu usuario estándar en el sistema (no root); El último comando sólo se corre si quieres que MongoDB se inicie al arranque del sistema automáticamente con las opciones por defecto.

Instalar NodeJS & NPM en CentOS/RHEL 6.x [Live 5/06/2014]


Para instalar a éstos 2 dentro de tu sistema CentOS/RHEL 6.x sólo necesitarás agregar los repos de los que hablamos anteriormente en esta guía y después correr:

1. su -
2. yum -y install nodejs npm

Más tarde (como tu usuario estándar) puedes instalar paquetes como Coffeescript o ExpressJS con comandos como:

npm install coffee-script express

por ejemplo.

Instalar Ruby y Ruby on Rails en CentOS/RHEL 6.x [Live 5/06/2014]


Si quieres instalar el lenguaje de programación Ruby y su framework web más famoso Ruby on Rails dentro de Red Hat Enterprise Linux o CentOS 6.x esto es lo que tienes que hacer:

NOTA: Necesitarás tener agregados los repos de los que hablamos en esta guía

1) Instalar dependencias

1. su -
2. yum -y install git git-core mercurial subversion bzr nodejs curl wget

2) RVM

NOTA: La instalación de RVM, Ruby y Rails requiere hacerse desde un usuario estándar con privilegios de sudo

1. wget https://raw.github.com/wayneeseguin/rvm/master/binscripts/rvm-installer -O rvm.sh
2. umask g+w
3. source ~/.profile
4. rvm requirements

El último comando nos pedirá una contraseña y se pondrá a instalar más dependencias necesarias para la compilación de ruby y sus gemas en el sistema luego seguimos con:

sudo chown -R user:user /home/user/.rvm/

Reemplazando user por tu nombre de usuario... Más tarde necesitaremos descargar la versión de ruby que queramos usar. Yo generalmente me voy por la última versión estable disponible, misma que se puede checar desde acá.

3) Ruby

Al momento que escribo esto dicha versión es la 2.1.2, por lo que seguiré el tutorial basándome en ella (recuerda cambiar dicho número por el indicado para la última versión cuando sigas este tutorial):

rvm install 2.1.2

Ese comando descargará y compilará dicha versión en nuestro sistema. Luego corremos:

1. source "~/.rvm/scripts/rvm"
2. rvm --default use 2.1.2

Añadimos RVM a nuestro bashrc:

echo "source ~/.rvm/scripts/rvm" >> ~/.bashrc

(O bien, ~/.zshrc  si usas ZSH por ejemplo)

y proseguimos.

4) Rails

1. gem update --system
2. gem install rubygems-update
3. update_rubygems
4. gem install rails --no-ri --no-rdoc

¡Listo! Podemos verificar la instalación exitosa de Ruby y Ruby On Rails en nuestro sistema con:

1. ruby -v
2. rails -v