Archivo de la categoría: trucos de la abuela

Garimpeiros digitales

bitcoin1

Introducción

¿Qué es minar?, ¿como es eso de echar pico y pala en una red?, ¿por qué nace Bitcoin?, ¿debería estar minando?, sería interesante conocer para “al menos” estar informado y que no te agarre por sorpresa, aquí algunos conceptos previos:

Glosario:

Criptografía: Se trata de un ámbito de la criptología, dedicado a la construcción de reglas de cifrado o codificado de información para permitir su “ocultamiento” y transmisión, para hacerlo inentendible por ojos no autorizados; la criptografía además es todo un ámbito de las matemáticas científicas destinada a elaboración de técnicas de cifrado mediante algoritmos y pruebas matemáticas.

Hash (cadena): Se conoce como “hash” a la cadena generada por algún algoritmo criptográfico de suma resumen (o función hash), algunas sumas no pueden ser resueltas al valor inicial, por ejemplo:

“hola mundo” en SHA256 es: 41d85e0b52944ee2917adfd73a2b7ce3d3c8368533a75e54db881fac6c9ad176, la suma no puede ser “devuelta” a la forma “hola mundo”, en su defecto, ámbos lados de la operación (cliente y servidor) conocen la cadena “hola mundo” y se intercambian los hashes resultantes, así, comprueban que están usando la misma cadena origen.

Otros algoritmos de resumen, como “base64”, son deterministas, es decir, una cadena siempre devuelve la misma suma, por lo que la “reversión” es posible.

Entre los algoritmos de función hash más comunes estan:

* Base64
* CRC
* MD5
* SHA1
* SSHA
* SHA256
* SHA512
* Whirlpool

Cryptocurrency (cryptomoneda): Se trata de un concepto de pago entre 2 usuarios, utilizando una “moneda” común entre ámbos, la transacción es “cifrada” utilizando reglas matemáticas criptográficas de alta seguridad, para evitar que más nadie fuera de la red pueda alterar, falsificar o reversar la transacción, por utilizar reglas matemáticas tanto para su cifrado, como para su “demostración” (resolución) a dicha moneda se le conoce como criptomoneda; las criptomonedas más comunes hoy día son:

* Bitcoin
* Litecoin
* Dogecoin
* PeerCoin

Bitcoin: Criptomoneda de uso más común y más popular, su símbolo monetario es BTC, en la actualidad se cotiza alrededor de los 310US$ por Bitcoin, es una moneda multidecimal (a diferencia de los dólares o bolívares, que no tienen más de 2 decimales), con un valor mínimo de 1 Satoshi (igual a 0.00000001 ฿), llamado así por Satoshi Nakamoto, el *creador* de Bitcoin (coloco entre comillas, puesto que la verdadera identidad del creador del Bitcoin es un misterio).

Altcoin: Se conocen como altcoins a todas las monedas alternativas surgidas a raíz de bitcoin, diseñadas con propósitos especificos o como alternativas directas al bitcoin.

Red P2P: Una red P2P (Point-to-Point o “punto a punto”) es una red colectiva de usuarios, cada individuo de la red interactúa directamente con los otros individuos, evitando la existencia de un ente “central”, las emisiones en una red P2P son distribuidas (broadcast) por lo todos los usuarios reciben la información que generó cada uno de ellos.

Red de la cryptomoneda: La criptomoneda opera en una red distribuida (P2P) de usuarios, dicha red permite a todos los usuarios emitir o recibir pagos en la criptomoneda, mientras todo el conjunto de usuarios valida las transacciones para aumentar la seguridad de dicha red, como cada usuario auto-contiene el conjunto global de transacciones realizadas, la red se auto-protege contra fraudes (como por ejemplo el “doble gasto”, nadie puede gastar su dinero 2 veces, los usuarios de la red determinarán cual de las transacciones es la única correcta); además, es descentralizada, ya que no hay ente central (Banco Central) que dicte las normas o sea el contenedor de único de las transacciones de la red; además, al ser descentralizada y distribuida, todos los usuarios cuentan con los mismos derechos dentro de la red.

Dirección (address): es una dirección física que identifica a un usuario en la red de la cryptomoneda, tiene la forma de una larga secuencia de dígitos y letras, para mantener el anonimato de los usuarios, un usuario puede tener múltiples direcciones físicas asociadas a una billetera (wallet) y puede usar una dirección para una única transacción, por ejemplo VrV1WaEMBcQmK6e4w4ydU27M5WQG3bnP75 es mi dirección para pagos con Vertcoin.
Las transacciones son emitidas usando una “dirección” del usuario “A” hasta la dirección del usuario “B”.

Transacción: Es el proceso de enviar crytomoneda desde A hasta B, es un proceso sencillo en el cual, la dirección “A”, emite un conjunto de crytomonedas almacenadas en su billetera, para realizar un pago a “B”, cada transacción (o conjunto de transacciones) es almacenada en una estructura de datos conocida como “bloque”.

Wallet (Billetera): también conocida como “monedero”, es una cuenta dentro de la red de la cryptomoneda, dónde almacenas tus monedas y permite generar direcciones para realizar o aceptar pagos, el wallet es tu propio “banco central”, pues se sincroniza con la red de la cryptomoneda y almacena la cadena de bloques mostrando todas las monedas que están “a tu nombre”.

Bloque: Cada transacción (o varias) realizadas en cryptomoneda, son almacenadas en una estructura (registro o “record”) conocida como “bloque”, esta estructura contiene el tamaño total del conjunto de transacciones pendientes de ser permanentemente almacenadas, la información de las transacciones (las “direcciones” que realizaron la misma), el contador de la cantidad de transacciones contenidas, un número mágico (siempre el mismo para cada tipo de cryptomoneda) y obviamente el espacio de descripción de las transacciones, además de una referencia al bloque predecesor, el proceso de “capturar, identificar y resolver” dicho bloque, se conoce como “resolución de bloque”, el conjunto de todas las transacciones ya permanentemente almacenadas se conoce como “cadena de bloques”.

Resolución de bloque (solving block o “romper el bloque”): además de la información transaccional, cada bloque provee una “prueba de trabajo” (proof-of-work), que es única por cada bloque (por la alta aleatoriedad y la baja probabilidad de cada bloque), ningún bloque es registrado permanentemente en la cadena de bloques si no es “resuelta” esta prueba, luego de que algún “usuario” de la red “resuelve” el bloque (y se gana la “recompensa”), el resto de usuarios puede validar fácilmente que la solución que encontró es la correcta; al tratarse de de hashes, hay múltiples soluciones posibles, pero solo es necesaria que se encuentre una para determinar que el bloque es correcto y se registra en la cadena de bloques.

Confirmación de bloque: Cuando se captura, identifica y resuelve el bloque, se produce un proceso de “confirmación”, aunque alguien haya “resuelto” el bloque, no se espera sino hasta un número de confirmaciones (usuarios que indican que la resolución de bloque es correcta) para determinar que el bloque es “legal” y debe ser registrado en la cadena de bloques; con muchas confirmaciones se evita que alguien pueda “reversar” la transacción. La cantidad de confirmaciones depende de la cryptomoneda, en la red bitcoin se requiere de al menos 6 confirmaciones para la validez de un bloque.

Reward (recompensa): Cuando ocurre un conjunto de transacciones entre “A” y “B”, un tercer usuario “C” encuentra y “resuelve” el bloque para demostrar que la transacción entre A y B es válida, para “recompensar” a dicho usuario C, la red de la cryptomoneda emite “monedas nuevas” como gratificación (bounty) por su dedicación a resolver el bloque, es como un “coste de transacción” o fee, pero que no es pagado ni por A ni por B, sino con la emisión de monedas nuevas. El valor de dicha recompensa es fijo, pero decrece con el tiempo al aumentar la complejidad (y la cantidad total de clientes) de la red de la cryptomoneda, por ejemplo:

* Bitcoin: 25BTC por bloque
* Litecoin: 50LTC por bloque
* Dogecoin: 15mil DOGE por cada bloque

Por ejemplo, en bitcoin la recompensa se reduce a la mitad cada 210 mil bloques (que ocurre aproximadamente cada 4 años).

Mining (Minería): Se conoce como “minería” a la “competencia” que ocurre entre todos los usuarios de la red, de encontrar un bloque y “resolverlo” para ganarse la recompensa, el tiempo de resolución depende del algoritmo de la moneda, en Bitcoin es aproximadamente 60 segundos, en dogecoin son 70 segundos, si en el tiempo de resolución (confirmation time) quien “encontró” el bloque no resuelve el bloque, otro más podrá resolverlo.
Como la red de la cryptomoneda es “broadcast” (de difusión) la probabilidad de ser quien “encuentre” un bloque sin resolver es la misma para todos los nodos dentro de la red, pero la velocidad con la cual resuelves el bloque depende de tu poder de resolución (“hashing power”).

Miner (software|hardware): Consiste en un software o una pieza de hardware, diseñada para capturar los bloques y resolverlos, la resolución del mismo se basa en un algoritmo de prueba de trabajo (POW: Proof-of-Work) que determina la validez de la solución; para Bitcoin se han diseñado dispositivos FPGA (Compuertas lógicas programables) y más recientemente Circuitos programables de aplicación específica (ASIC) que computan la solución de la prueba de trabajo; en algunos casos la solución de la misma no es resoluta vía FPGA o ASIC (ASIC-Resistant), entonces se utiliza para minar algún software que usa trabajo del CPU o de la GPU.

Cadena de bloques (blockchain): Consiste en todo el conjunto de bloques (transacciones) generados durante la vida de la cryptomoneda (desde sus inicios), por ejemplo, la transacción cero (génesis) fue incorporada a la red Bitcoin por Satoshi Nakamoto en 2009. Para mantener la “descentralización” de la moneda, todo operario (cliente) debe mantener junto a él el bloque transaccional; esto es debido a la forma como se calcula cada bloque, como cada bloque contiene el bloque anterior, para cambiar un bloque, se requiere la re-generación de todos los predecesores, re-haciendo además todo el trabajo que ellos contienen (recalcular sus hashes), esto protege la cadena de bloques contra su manipulación, por ende, todos los usuarios de la cryptomoneda poseen la misma cadena de bloques (idéntica) evitando así que alguien pueda cambiarla.

El tamaño actual de la cadena de bloques es de:

Bitcoin: 33GB
Dogecoin: 6GB
LiteCoin: 4GB
Feathercoin: 800MB

Proof-of-work (POW): Una prueba de trabajo, es un pequeño pedazo de información que es muy difícil de obtener/generar (consume tiempo y trabajo por parte del cliente) y usualmente es calculado/generado por el computador del cliente, el POW (La prueba de trabajo) se usa para evitar ataques de denegación de servicio ya que para el cliente debe ser moderadamente difícil de generar (es un proceso aleatorio y de baja probabilidad de obtención de 2 resultados iguales), pero a su vez debe ser sumamente trivial para el servidor determinar la validez de la prueba de trabajo una vez resuelta y enviada por el cliente.

Algoritmos de prueba de trabajo: Para determinar que “en verdad” has trabajado en la resolución de un bloque, se realiza una prueba de trabajo, que consiste en calcular un hash correspondiente al bloque actual, combinado con el bloque anterior, dicho cálculo utiliza un tipo determinado de algoritmo (muchos de hechos diseñados específicamente por la criptomoneda en cuestión), por ejemplo:

* Hashcash de doble iteración: Bitcoin utiliza un algoritmo HASHCASH de doble iteración (doble cifrado) usando el algoritmo de función hash SHA256, es hashcash es difícil de obtener con CPU o con GPU, pero a dispositivos FPGA programados para ello se les hace trivial (y muy barato) resolver dicha función.

* Scrypt: En vista de que el algoritmo hashcash es fácilmente resoluto con equipos específicos de puerta lógica de baja memoria (FPGA) y con la alta proliferación de dichos equipos para la resolución de bloques Bitcoin, se diseñó Scrypt, que incorpora algoritmos que requieren el uso intensivo de memoria (al usar mucha memoria, reducen la eficiencia de los FPGA), para su resolución es más útil el uso de GPU (Graphic Process Unit, comunmente encontrados en tarjetas de video) con un buen ancho de banda de memoria (ejemplo, tarjetas AMD Radeon o NVIDIA). Dogecoin, Litecoin y otras cryptomonedas usan scrypt como algoritmo de prueba de trabajo.

* NeoScrypt: con el diseño de circuitos integrados de aplicación específica (ASIC) que resolvian muy fácilmente el algoritmo scrypt, se diseño neoscrypt, un combinado de algoritmos de cifrado (Salsa20/20, ChaCha20/20, Blake2, etc) con un uso altamente intensivo de memoria que lo hace resistente a su descifrado con dispositivos ASIC. Phoenixcoin y Feathercoin utilizan NeoScrypt.

* X11: Es un algoritmo de prueba de trabajo, que combina 11 algoritmos diferentes en cadena para la resolución de la prueba, haciendolo ASIC-resistant y GPU-oriented, Darkcoin y otro conjunto de criptomonedas usan dicho POW.

* Lyra2RE: Con el diseño de ASIC que resolvían Neoscrypt y scrypt, Vertcoin diseñó un algoritmo de prueba de trabajo conocido como Lyra2RE, al igual que neoScrypt y scrypt-N, Lyra2RE es realmente un combinado de cifrados que incluye NIST5, Blake-256, Lyra2 y Groestl-256, debido a su naturaleza, la paralelización y la optimización de Lyra2RE es prácticamente imposible, con lo cual, paralelización vía múltiples nodos con GPU u optimizaciones agresivas de la GPU son inútiles con el mismo, garantizando los mismos derechos a todos los usuarios de la red.

* M7M: Con el advenimiento de ASIC que minan scrypt y neoscrypt y con el hash-power de granjas de GPU, la criptomoneda MAGI (XMG) diseña M7M, es una POW que combina 7 algoritmos únicamente resolutos vía CPU (ASIC-Resistant, GPU-Resistant).

La razón del cambio de la prueba de trabajo, es para evitar la “centralización de minería” y evitar “que los ricos se hagan más ricos”, personas con gigantescas granjas paralelas de ASIC que pueden resolver cualquier bloque con facilidad, llevándose el máximo de las recompensas, por ejemplo, la distribución de la riqueza en la red bitcoin es:

Top 10 usuarios: 6.29%
Primeros 100 usuarios: 21.20%
Primeros 1000 usuarios: 40.03%
Resto: 63.41% Total

Como vemos, 10 usuarios concentran 6% de la riqueza bitcoin (unos 700 millones de US$), 1000 usuarios concentran el 40% de la riqueza, en cambio en la red vertcoin, hay solo 1 cuenta con más de 1 millón de vertcoins (unos 27 mil US$) y el 85% de la riqueza está distribuida en la mayoría de los usuarios.

Proof-of-Stake (prueba de participación): Nuevas monedas como Peercoin introducen la “prueba de participación”, es el sistema actual de las cuentas con intereses de los bancos, cada usuario gana por su participación en la red un “interes” y dicho interés es calculado en base a la cantidad de monedas con las que participe en la red, eso asegura que botnets (grandes robots minando día y noche) sin participación monetaria en la red, pudieran ganar algún interés.

Hash Power: Es la cantidad de hashes (resoluciones del algoritmo de cifrado) que puedes computar en un segundo, el Hash power requerido para resolver rápidamente un bloque depende enormemente de la complejidad inherente de la red, de la cantidad de usuarios compitiendo y de la cantidad de moneda disponible, la unidad de medida es el Hash/Segundo, mientras más Hashes/segundo puedas computar, más rápidamente obtendrás la resolución del bloque/segmento, algunas monedas requieren pocos KiloHashes/segundo mientras por ejemplo, Bitcoin requiere equipos que pueden estar rondando los varios GigaHashes/segundo (GH/s).

Velocidad Hash/Hash Rate: La tasa de hash o “hash rate” es la unidad de medida de la potencia total de la red de procesamiento de la criptomoneda, es la combinación de todo el poder encontrado en la red durante un momento en el tiempo, esto determina la dificultad con la cual se captura/procesa/resuelve cada bloque, en la actualidad el Network Hash rate de algunas monedas:

* Bitcoin: 290 PH/s (Petahashes sobre segundo)
* Litecoin: 1.3TH/s (Terahashes sobre segundo)
* Dogecoin: 1.2TH/s
* Darkcoin: 78 mil GH/s (Gigahashes sobre segundo)
* Vertcoin: 2500 GH/s

Solo mining (Minería en solitario): Consiste en conectarse a la red P2P de la criptomoneda y dedicar tu poder de procesamiento directamente a descubrir y resolver bloques, cuando minas solo, la totalidad de la recompensa recae en el usuario; sin embargo, debido a la aleatoriedad y alta complejidad de los bloques, se requiere una buena conexión y un alto poder de resolución de hashes (además de mucha suerte) para ser el primero en encontrar un bloque y resolverlo.

Pool Mining (Minería en grupo): Debido a que es una red P2P (distribuida), no importa si tienes un terahash/segundo de poder (eso sólo ayudará a que resuelvas más rápido un bloque, no a que te otorguen más bloques), como el otorgamiento de resolución de bloques es broadcast (distribuido) entonces cuando muchas personas de diferentes partes del mundo se juntan para resolver un único bloque, entonces se incrementa el chance no solo de resolver más rápido (el bloque total se divide en shares, que son resueltos por cada uno de los minadores) sino de además hay más nodos con probabilidades de capturar un nodo, así las ganancias se distribuyen entre todos los participantes del Pool.

Minería para no-mineros

bitcoin-miner

Conocidos algunos conceptos previos, entendamos el proceso de manera general y sin tanta jerga técnica, en el mundo real, todos compramos con dinero, el dinero es una representación o fracción de la “riqueza total” de una nación y solamente el banco central de un país puede emitirlo; “A” toma su riqueza (en oro y bienes) y las convierte en “dinero”, que usa para pagarle a “B” otros bienes, que su valor ha sido calculado con anterioridad en base a su proporción “riqueza-dinero”.

En el mundo digital, ocurre algo semejante, Sujeto “A” desea pagarle a Sujeto “B” una cierta cantidad de dinero, entonces, entre A y B ocurre una “transacción”, dónde “A” le pasa a “B” el dinero demandado por algún bien o servicio; para asegurar la transacción de ojos “curiosos”, “A” y “B” cifran su transacción con la lógica que la criptomoneda que estén usando ha diseñado; para validar que *en verdad* A y B movilizaron dinero, en vez de Bancos y Banco Central, están otros sujetos alrededor de la red P2P, que ven la transacción de “A” con “B” y sirven de testigos, le gritan al mundo “Si!, A le envió dinero a B!”, la transacción es confirmada y el dinero es debitado de la billetera de “A” y es confirmado en la billetera de “B”.

Para que sea “rentable” participar como testigo de dicha red P2P, cada transacción paga un fee (impuesto) que es otorgado a la primera persona que *aparece* como testigo de A->B, además, la propia red P2P (así como el Banco Central imprime más billetes cuando ha incrementado la riqueza del país) emite “monedas nuevas” que son otorgadas adicionalmente al término de cada transacción (recompensa), así, la riqueza de cada uno va incrementándose a medida que se incrementa la riqueza de la red P2P en general.

Adicionalmente, hay personas que toman dinero del mundo “real”, y compran monedas del mundo digital (a sujetos que ya tienen monedas en su poder) en casas de cambio (Stock Exchange), lo que incorpora más “nodos” a la red P2P, por ende más complejidad, más emisión de moneda y más “riqueza”.

En la actualidad la red Bitcoin cuenta con 4100 millones de US$ en dinero circulante mientras que la red litecoin cuenta con 75 millones de US$.

Garimpos del Bitcoin

Se conoce como Garimpeiro (palabra portuguesa que significa  “trabajador de los Garimpos”, sitio remoto de minería ilegal), a aquellos trabajadores que destinados a sitios de minería que realizan su explotació de manera manual, ineficiente, ilegal y a veces en condiciones infrahumanas, los Garimpeiros suelen “arriesgar su vida” dedicados a la minería ilegal en zonas muy alejadas, expuestos a venenos como mercurio o cianuro y a la destrucción ecológica.

En algunas regiones del mundo, pero por sobre todo en latinoamérica, han proliferado los que he descrito como “Garimpeiros digitales”, ¿por qué?, se dedican a minar sin un ápice del conocimiento arriba descrito, a veces simplemente colocan máquinas a minar y creen que la máquina está “haciendo plata solita” (como un Garimpeiro toma 2 toneladas de tierra, le inyecta mercurio y saca 2 gramos de oro y cree que le fue “bien”), sin entender los conceptos de resolución de bloque, transaction fee o bounty reward, tampoco entienden los algoritmos con los que están cifrados los bloques (algunos que he hablado con ellos, ni siquiera entienden el concepto de “bloque”), minando en condiciones “infrahumanas” (por decirlo de algún modo) con un profit (beneficio) ínfimo.

¿A qué se debe esto?, veamos …

La tragedia de los comunes

Aunque la tragedia de los comunes es un principio descrito por el ecologista Garret Hardin para describir el comportamiento de cómo individuos, incluso inocentes, todos motivados únicamente por un interés personal y de manera independiente uno del otro (con un comportamiento racional, desconociendo las intenciones de los demás) pueden llegar a acabar y/o destruir un bien común limitado, incluso con pleno conocimiento (como individuos y/o como conjunto) de que dicha destrucción no beneficiará a nadie en el largo plazo, (un ejemplo de ello es la contaminación, los individuos siguen contaminando porque consideran que su impacto individual es ínfimo, pero el proceso en conjunto terminará por destruir la atmósfera y acabar con la vida en el planeta a largo plazo); en la red bitcoin se hace uso de ese principio una y otra vez, ¿por qué cada vez más gente entra a minar aunque las transacciones para usarlo no crecen con la misma intensidad?, pues el beneficio intrínseco e individual de minar, ganar “como moneda” simplemente por el hecho de quedarse con el botín y venderlo para adquirir otra moneda (la moneda como mercancía, fábrica de la especulación), sin embargo, con la incorporación de más y más nodos (y su hash-power) matemáticamente la complejidad de la red bitcoin se irá incrementando, reduciendo a su vez el botín, acercándose cada vez más a nivel de recompensa “0” (cero), ¿qué significa esto?, que los usuarios minadores sólo obtendrán como recompensa los ínfimos transactions fees generados, convirtiendo a los minadores en individuos sub-pagados (margenes de ganancia efímeros comparados con el poder de procesamiento que tuvieron que invertir para resolver los bloques), haciendo que los minadores en esas condiciones se retiren y toda la red bitcoin dejaría de funcionar correctamente.

¿Por qué ocurre esto?, las condiciones son diferentes en varios países, aunque en Venezuela tiene una explicación lógica, CADIVI y la restricción cambiaria.

La moneda como mercancía

Durante siglos la moneda fue el instrumento de canje con el que se tasaban productos y servicios y permitía intercambiarlos, en un mercado convencional, individuo “A” siembra una mazorca de maíz, su coste de producción es tasada en 5 monedas, por lo que individuo “A” la vende (para ganarle algo) en 8 monedas al productor de harina “B”, que le suma sus costes de producción (2 monedas por mazorca) y de dicha mazorca obtiene 2 envases de harina de maíz que tienen un coste de 5 monedas por paquete, vendiéndolas al comprador “C” en 8 monedas cada una.

En la actualidad, ciertas monedas se convierten en mercancía, como el dólar, esto es debido a las restricciones cambiarias impuestas en Venezuela, que hacen imposible a ciertos individuos acceder a los dólares necesarios para realizar sus compras e importaciones; entonces, individuos inescrupulosos toman el dólar adquirido a precio “A” más bajo y lo venden con sobreprecio a precio “B” a los interesados, no hubo ni bienes ni servicios, sino exclusivamente un intercambio de una moneda de un valor “ficticio” (impuesto por una entidad cambiaria alejada de la realidad) a otro valor ficticio (impuesto por los especuladores de moneda, en base a la capacidad de compra de los clientes).

El Bitcoin (y otras criptomonedas) se han convertido entonces en monedas de intercambio (la gente “genera” bitcoins, compra con ellos dólares, y vende los dólares en el mercado paralelo), no estoy criticando su uso (aunque me parece controversial el concepto de moneda como mercancía) sin embargo, mucha gente se dedica a minar desde la ignorancia, afectando el desempeño general de la red; aunque ciertamente es complicado escribir “recomendaciones de minería” que pudieran verse como “intentos” de adquirir divisas por métodos no descritos en la legislación y cometer un ilícito cambiario.

Sería interesante saber, por ejemplo, si el “distinguido” empresario Venezolano que compró una empresa que fabricaba dispositivos ASIC de minería (ASIC-miners) y su inventario de equipos por 1.2 millones de US$, los usará para generar una red bitcoin y una estructura de pagos alrededor de él (tipo MercadoPago pero con bitcoins), o será otro “garimpeiro más” que se dedicará a generar bitcoins para luego comprar dólares y venderlos en el mercado paralelo.

Otra pregunta sin respuesta, pero eso es otra historia …

Wow!, mino 1US$ diario, le estoy ganando a CADIVI!

Fue la expresión de alguien hace algún tiempo, cuando dedicó su computador 24/7 a minar litecoins usando una combinación de CPU/GPU, esto representaba 365US$ anuales, ciertamente un poco más de lo que CADIVI asigna anualmente para gasto electrónico (300US$), sin embargo, con la complejidad del bloque Litecoin, una GPU decente (una AMD RADEON R9 290, por ejemplo) tiene un costo de entre 400 a 800US$, a menos que tengas muy muy bien refrigerado tu centro de datos, el quemar la GPU de tu tarjeta de video (muy probable con la alta tasa de computo a la que es sometida diariamente) te llevará 2 años de minería recuperarla.
Incluso adquirir ASIC destinados a resolver los algoritmos scrypt y neoscrypt (o scrypt-n) de ciertas altcoins, será una inversión “a mediano-largo” plazo, puesto que la velocidad de resolución contrastará con la siempre incremental complejidad de la red.
A este factor, se unen 2 factores más que no tienen nada que ver con el usuario, la pésima velocidad de la red en Venezuela y una mucho más pésima infraestructura de servicios; si, ciertamente la velocidad del Internet promedio deja mucho que desear cuando una red exige 60 segundos de respuesta a un bloque que mide aproximadamente 500Kb y que hay que procesar con una prueba de trabajo cada vez más compleja (en el transcurso de redactar este artículo, ABA de CANTV me ha dejado sin conexión 3 veces), además cuando el blockchain (cadena de bloques) de Bitcoin mide 33GB sincronizarlo (un usuario nuevo tardaría 40 horas en descargarlo completo), pero esto no es nada al enfrentar un apagón de vez en cuando que pudiera “freir” nuestros equipos sin la protección debida (y la inversión necesaria en protección eléctrica y UPS sería mayor que la tasa de rentabilidad -profitability- que pudieramos obtener, por ejemplo, en la red Bitcoin) o simplemente “dejarnos a oscuras” y fuera de la red por mucho tiempo.

¿Me quedo mirando mientras los demás se hacen ricos?

No, no estoy diciendo eso, pero vale la pena entender los recursos que tenemos y/o pudieramos tener y dedicarnos a la red que más se adecúe a nuestros recursos, con la complejidad de los algoritmos actuales, la minería en pool parece más rentable que la tentadora pero traicionera minería en solitario (en promedio, una red como Litecoin “pudiera” otorgarte un bloque cada 300 días, aunque esto como es aleatorio, pudiera darse en mucho menos tiempo).

Minar Bitcoins con CPU es absurdo hoy en día (y costoso incluso a los costos de la electricidad en Venezuela), a menos que se apueste por minería de CPU como VertCoin o Darkcoin, si aún *considera* que tendrá suerte minando bitcoins y uniéndose a un pool, sería recomendable hacer una inversión inicial en ASIC Miners modernos que soporten *al menos* el algoritmo Scrypt (para permitirle “cambiar” a minería de Litecoins o Dogecoins); si con lo que cuenta es con tarjetas de video (perfectamente refrigeradas para que no se quemen) entonces busque altcoins con algoritmos ASIC-Resistant pero que tengan una alta rentabilidad; en general, es un proceso “a futuro” y la minería de altcoins (exactamente igual como pasó con Bitcoin en un inicio) es un proceso a largo plazo, por ejemplo, un dogecoin vale solamente 0,00005 de BTC (y bajo las perspectivas actuales de uso, su precio se mantendrá estable por un largo tiempo), en cambio, los Darkcoin tienen una alta expectativa de crecimiento a mediano plazo, Los peercoin y Paycoin mantienen un precio estable, mientras que Litecoin pierde el interés de inversionistas frente a otras altcoins más modernas.

Yuppies de sillón

Minar, y en general trabajar con criptomonedas, es un proceso de conocimiento, tanto de economía de moneda, de mercado, como de matemáticas y computación, no es “puse mi portátil a minar litecoins porque un amigo de facebook me dijo que eso hace plata”, hay “yuppies” que pasan toda su vida en Wall Street y ganan lo necesario para vivir y otros que llegan con el conocimiento, las ganas de invertir y se hacen ricos en 30 días.

Sería interesante saber de cual tipo de yuppie quisieras considerarte …

 

Happy Mining!

[PostgreSQL] Crear triggers dinámicos con postgreSQL

¿Qué es un trigger dinámico?, es aquel trigger que la metadata de en cual tabla/campo va a operar es pasado de manera dinámica (parámetros) a la función de trigger (trigger function).

¿Y para qué sirve?, bueno, imaginen un sistema dónde cada operación debe ser por ejemplo, agregada a una tabla auditoría, o por ejemplo, que una operación en una tabla, causa una operación en otra tabla, que aunque el código sea *casi* el mismo, depende de la tabla que dispara el trigger, qué tabla va a operar.

La utilidad de esto es simplemente poder re-utilizar una única funcion trigger para diversas acciones a ser tomadas de acuerdo a los parámetros recibidos.

El ejemplo

Este ejemplo se construyó durante un taller de postgreSQL que estaba dictando, el criterio era el siguiente:

  • El trigger toma el valor insertado en una tabla
  • Busca dicho valor en otra tabla, usando otro campo como criterio
  • Si el valor no existe, retorna NULL
  • Si el valor existe, retorna el objeto NEW del disparador, con lo cual la inserción sí ocurre

Los campos TG_*

En los disparadores de postgreSQL se cuenta con un conjunto de variables muy útiles, como son:

  • TG_OP: define la operación realizada en la tabla (INSERT, UPDATE o DELETE)
  • TG_TABLE_SCHEMA: define el schema al que pertenece la tabla (ej: “public”)
  • TG_TABLE_NAME: define el nombre de la tabla que disparó este trigger
  • TG_ARGV: es un arreglo (array []) que contiene los parámetros enviados a una función de trigger.

Con esto podemos hacer cualquier tipo de condicional en la función de trigger, reduciendo el código a sólo una función que se usará, de acuerdo a los parámetros que se le pasen.

La Función

CREATE OR REPLACE FUNCTION permitir_insert() RETURNS trigger AS

Comenzamos con la definición, la llamaremos “permitir_insert()” y obviamente, retorna un trigger.

luego, en la sección de declaración, definimos las únicas variables que vamos a necesitar para este ejemplo:

 vrecord integer;
campo text;
tabla text;
id int;
rc int;

BEGIN

En el cuerpo de la función, preguntamos qué tabla y campo voy a consultar para verificar si permito o no el insert, esto se hace consultando a TG_ARGV:

 tabla := TG_ARGV[0];
campo := TG_ARGV[1];

Como ven, ya que podamos recibir cualquier cantidad de parámetros en el trigger, las opciones son infinitas.

Ahora, necesito saber que hay en el campo trigger (NEW.campo), en este caso, debo reemplazar “campo” con el nombre del campo de la tabla que disparó el trigger (y que voy a consultar en otra tabla), como en mi caso el valor de el “campo” en todas las “tablas” que usarán esta función de trigger es entero, he declarado “vrecord” integer, si su tipo será distinto, sería conveniente declararlo “anyelement”.

EXECUTE 'SELECT ($1).' || quote_ident(campo) || '::text' INTO vrecord USING NEW;

Lo que hace ese código, es ejecutar un $1.”campo”::text (dónde campo es una variable) y mete su valor en la variable “vrecord”, se usa el objeto NEW para la sustitución del $1.

Ejemplo, si el campo se llama “piezas“, ese “EXECUTE” quedaría “NEW.piezas” y entonces metería el valor de NEW.piezas en la variable “vrecord”.

¿sencillo, no?.

La consulta

Ahora, debo verificar que en el campo “campo”::text de la tabla tabla::text (variable) existe un valor con lo que está contenido en “vrecord”, de lo contrario retorno NULL y el trigger no se ejecuta (la operación de inserción no ocurre).

Sería algo como un “constraint” pero sin usar reglas de constraint, ¿entendido?.

IF TG_OP = 'INSERT' THEN

EXECUTE format('SELECT '||quote_ident(campo)||' FROM '||quote_ident(tabla)||' WHERE '||quote_ident(campo)||' =$1') USING vrecord INTO id;

En este caso, he ejecutado un SELECT (SELECT “campo”::text FROM “tabla”::text WHERE campo::text = vrecord), claro que haciendo las conversiones y los reemplazos respectivos.

El valor de esa ejecución lo agrego a la variable id.

Si adicionalmente se desea averiguar si esa consulta anterior retornó filas, colocamos seguidamente al EXECUTE:

GET DIAGNOSTICS rc = ROW_COUNT;

Si “rc” es igual a cero, entonces no existe el valor “vrecord” en el campo “campo” de la tabla “tabla”, caso contrario, se retorna NEW.

 IF rc = 0 THEN
    RAISE EXCEPTION 'no existe el valor % en el campo % de la tabla %', vrecord, campo, tabla;
    RETURN NULL;
END IF;
RETURN NEW;

Y listo!, definimos el cierre y que esta es una función VOLATILE:

END;
LANGUAGE plpgsql VOLATILE

Y ya podemos usarla.

Usando la función dinámica

Para usar la función dinámica, simplemente creamos un trigger en cada tabla que necesite convocarla, pasando como parámetros de la función trigger la tabla referencia y el campo que debe evaluar, ejemplo:

CREATE TRIGGER trg_insert_detalle_reportes
BEFORE INSERT
ON reportes
FOR EACH ROW
EXECUTE PROCEDURE permitir_insert('reportes', 'id_reporte');

Se insertará un detalle de reporte, solamente si el valor de “id_reporte” aparece en la tabla “reportes”.

Conclusiones

Sé que parece muy “rebuscado” un ejemplo que bien podría salir con una clave foránea, pero sirve para el hecho de demostrar la posibilidad de obtener e iterar sobre el objeto NEW, consultar metadata al “information_schema” o realizar cualquier operación de manera dinámica, pasando parámetros y consultando las variables mágicas TG_* de postgreSQL.

¿Se les ocurre alguna idea para estos triggers dinámicos? …

Desbloquear un Motorola Atrix 4G o ¿que consigo de menos de 100US$?

Los Motorola Atrix, a pesar de ser horrendos teléfonos (estéticamente hablando, por algo los Razr usan Kevlar para sus diseños, parecen un policía mal vestido), pasan a ser unos equipos dignos de cualquier “Geek” que se aprecie, con una relación precio/valor digna de considerar.

motorola-atrix-4g-mb860

Preámbulo

En las postrimerías de las elecciones de diciembre fui asaltado y despojado de mi viejito HTC Desire, que acababa de recibir una actualización CyanogenMod a 4.2 (Jelly Bean); pensando en el teléfono idóneo para adquirir pasé días analizando reviews, comparando dispositivos (haciendo uso de la herramienta comparativa de GSM-Arena):

comparativa-atrix-motog

 

Por ejemplo, me sorprendió que el más moderno (y popular) Moto G no tenga slot para SD y solo tenga una memoria interna de 16GB (exactamente igual que el Motorola Atrix que es 2 años más viejo); pero, lo que más me impulsó a adquirir este equipo fueron las siguientes:

  • Extraordinario bajo precio: lo adquirí en una subasta en ebay por algo más de 60US$, lo que me evitaba el pago de nacionalización excesiva y el pago por compras mayores a 100US$
  • CPU ARMx9 NVIDIA dual-core, con los tunnings adecuados, puede llevarse a 1.2Ghz y su GPU brinda un rendimiento claramente mejor que un GPU Adreno.
  • NO HAY DOLARES!, este es el gran suplicio de los venezolanos, no podemos andar por allí con un fajo de billetes diciendo “aja!, dame un Razr Maxx HD de 32GB y un Iphone 5C de respuesto”.
  • Super-hackeable!: Todos los dispositivos de la serie atrix traen algo conocido como “Webtop”, que permite correr un “mini-linux” cuando se conecta a un dispositivo conocido como lapdock:

Motorola Lapdock

Por ahora, me he comprometido a meterle Android o Kali Linux al Webtop, pero eso es otro artículo.

Preparativos

El equipo que adquirí es un equipo no desbloqueado de AT&T, la versión de Android “oficial” es la 2.3.6 (gingerbread) y el número de compilación de la SBF (ROM binaria oficial Motorola) es la 4.5.145 (tomen nota de esto, encontrarán muchas confusiones acerca de esto).

Al teléfono entonces hay que realizarle un conjunto de cosas en este orden:

  1. SIM-Unlock: o desbloqueo de SIM, AT&T y otros operadores no bloquean las radios de los equipos, sino las SIM-card, no es posible meterle una SIM de otro operador
  2. Desbloquear el bootloader (con esto, podemos instalar un sistema de recuperación -recovery- y una nueva ROM)
  3. Instalar un Android Recovery
  4. Instalar una ROM nueva
  5. Instalar las Google Apps

Necesitamos:

Recovery: http://forum.xda-developers.com/showthread.php?t=1204500
Custom CWM-based Recovery 5.0.2.7-atrix

Advertencia: ESTE PROCEDIMIENTO ELIMINA EL SISTEMA ANDROID DE FABRICA (STOCK), si desean simplemente darle “root” al teléfono y dejarlo con la ROM stock, este no es tu artículo, ¡go away!.

Paso 0: Cargar el teléfono

Esto parece un paso obvio, pero no lo es, algunos teléfonos Motorola tienen la “característica” de requerir más de lo 500 mili-amperios que proporcionan los cargadores USB-genéricos convencionales, sobre todo para la primera full-charge es necesario que la carga sea usando el cargador que viene oficialmente con el teléfono (o algún cargador de pared compatible).

Entonces, encendemos el equipo.

Paso 1: SIM-Lock

He cancelado 14US$ a una empresa que vende códigos de desbloqueo por SIM, hay varias, pero nota, no busquen las más “barateras”, porque te hacen perder tiempo (bueno, puede ser que tengas “suerte”), tardan como 3 ó 4 días en decirte que “no consiguieron el IMEI” y te devuelven el dinero, yo al final del día me he ido por “http://unlockthatphone.com/” y en cuestión de día y medio (pagué una noche y al mediodía del siguiente ya tenía el código) recibí el correo electrónico con el código de desbloqueo de la SIM.

Es un conjunto de números, simplemente encienden el equipo con la SIM-card de la operadora de su elección (en mi caso, Digitel), cuando les pida el código de desbloqueo, lo escriben y listo!.

Un tutorial con video, acá: http://imei24.net/Blog/2013/08/19/como-desbloquear-un-motorola-atrix-2-mb865-de-att/

Al terminar, apagamos el teléfono.

Paso 2: Arrancar en modo RSD Fastboot

El modo RSD (Remote Software Download) permite al usuario “cargar” software al teléfono, se usa por ejemplo, para cargar absolutamente TODO el firmware:

Listado de Firmware oficial disponible para Motorola Atrix 4G: http://sbf.droid-developers.org/phone.php?device=33

Bien, al poner el teléfono en modo RSD podemos “cargar” binarios de tipo SBF al teléfono, con ello podemos por ejemplo reemplazar el firmware de la radio o cargar todo el sistema completamente a su versión “stock”:

Si deseas descargar el último Firmware oficial de Motorola para Atrix 4G: http://sbf.droid-developers.org/download.php?device=33&file=742

NUNCA carguen ROM oficiales completas vía SBF, RSD tiene lectura directa sobre el dispositivo, un fallo en la carga generaría un HARD BRICK (tu teléfono se volvería inservible, y a diferencia de un “soft-brick” no hay manera humana de regresarlo de un hard brick).

Para iniciar el modo RSD Fastboot deberán presionar el botón de Volumen arriba (Volume Up) y el botón POWER a la vez:

y lo dejan presionado hasta que aparezca en la pantalla:

RSD Protocol Support

En este momento, conectamos al equipo vía USB.

Paso 3: Aplicar el SBF

Para permitir desbloquear el bootloader, tenemos primero que descargar el sbf_flash y el pudding en una carpeta de nuestro equipo, que ya debe tener por cierto ADB (Android Debug Bridge), aunque solamente necesitaremos fastboot.

Al estar en modo RSD el teléfono, abrimos una consola de root en nuestro GNU/Linux y nos vamos a la carpeta donde descargamos el sb_flash y el pudding, ejecutamos:

chmod +x sbf_flash

Y luego ejecutamos el “flash” del archivo SBF que estaba dentro del archivo pudding.zip:

./sbf_flash 4547-fix-try2.sbf

Verán en la consola algo como esto:

moto-sb1

El teléfono se pondrá en negro varias veces y luego se apagará, de no apagarse, caerá en modo fastboot.

NOTA: En este momento, si desconectan y apagan el equipo, al encenderlo dará un error “boot 0x001” y la gente entra en pánico (he visto hilos enteros en xda-developers), uno como linuxero, es normal, simplemente NO TIENES UN SISTEMA OPERATIVO, no hay nada que arranque, solo el fastboot!, si haces comentarios acerca de que tu teléfono “no arranca” luego de hacer este paso, estás advertido.

NOTA otra vez: ¡insisto!, el teléfono NO VA A ARRANCAR NADA SALVO FASTBOOT, ¡dejen el trauma!.

Si se llega a apagar y no logran encenderlo el truco es:

  • sacar la batería
  • esperar unos segundos
  • meter la batería nuevamente
  • Arrancar en modo fastboot (Volumen Abajo + botón de encendido) (Volume Down + Power Button)

Ahora, vamos a desbloquear el bootloader!

Paso 4: Desbloqueo del Bootloader

Si conectamos nuevamente el equipo vía USB a nuestro computador con ADB ya instalado, podrán ejecutar el comando “fastboot devices” y verán algo como esto:

./fastboot devices
TA207013NS fastboot

Ejecutamos entonces el comando para solicitar el desbloqueo del bootloader:

 ./fastboot oem unlock

Retornará lo siguiente:

...
(bootloader) Unlocking your device can permanently VOID your warranty.
(bootloader) This process cannot be reversed. If you wish to proceed,
(bootloader) reissue the unlock OEM command containing the unique ID
(bootloader) of your device: 027C108040A002D7
OKAY [ 0.001s]
finished. total time: 0.010s

Es importante hacer notar que el comando retorna un identificador único de equipo (acá en negrillas), con ese ID único repetimos el comando:

./fastboot oem unlock 027C108040A002D7

Y la respuesta será:

...
(bootloader) Device is now unlocked
OKAY [ 7.459s]
finished. total time: 7.459s

Y en la pantalla verán algo como esto:

Untitled-2

Y listo!, ya podemos instalar el recovery.

Paso 5: Instalar el CWM Recovery

He instalado una versión personalizada del CWM para el Atrix 4G, la he descargado (un archivo .img) y usando fastboot utilizo los comandos de borrar el recovery actual:

./fastboot erase recovery

Y luego cargar el recovery con:

./fastboot flash recovery “ruta y nombre del archivo .img”

En mi caso, quedó así:

./fastboot flash recovery /home/jesuslara/android/motorola/recovery-dark-green-atrix5.img
sending 'recovery' (4708 KB)...
OKAY [ 0.250s]
writing 'recovery'...
OKAY [ 0.462s]
finished. total time: 0.712s

Y ya tenemos CWM Recovery instalado.

Apagamos el equipo.

Paso 6: Inicio de instalación de ROM

Para arrancar en modo “Android Recovery”, presionan “volumen abajo” y botón de encendido (volume down+power button), encenderá con una frase “unlocked” abajo, esperen hasta que salga la palabra “fastboot”, cuando salga, podrán cambiar de “fastboot” a “android recovery” presionando varias veces volumen abajo hasta que salga la frase “android recovery”, en lo que esta frase salga, presionan volumen arriba “Volume Up” para confirmar e iniciar el Android Recovery.

Ya en el CWM, es sencillo, este recovery utiliza los botones de volumen para navegar arriba y abajo, el botón de búsqueda es ENTER (SELECT), atrás se logra con el atrás físico (BACK) y las teclas “Menú” y “Home” pueden usarse como arriba y abajo (si no se desea usar los botones de volumen).

Allí, ejecutan las siguientes tareas:

Advanced > Upgrade to ext4

* osh (webtop partition)
* /system
* /data

Luego, Advanced > Wipe Dalvik Cache

Y por último, instalamos la ROM:

Install Zip from SDCard > Choose Zip from SD Card, navegar y seleccionar la ROM (en mi caso, se llama “cm-10.1-20131211-UNOFFICIAL-epinter-olympus.zip”)

Al finalizar, le damos atrás 2 veces y presionamos sobre la opción “reboot now”, y habremos completado la instalación de la ROM.

Paso 7: pre-configuración de la ROM y Google Apps

Al iniciar por primera vez, si lo desean pueden crearse una cuenta CyanogenMod (prestan servicios como “buscar tu teléfono” y otras cosas que se encontraban con la aplicación “MotoBlur”), posteriormente, entran al menú de aplicaciones, buscan en “Configuración” > “Acerca del Dispositivo” y presionen varias veces y rápidamente en la opción “número de compilación”, eso activará un menú oculto conocido como “Rendimiento”, que permite modificar algunas cosas avanzadas de Android (lo veremos después).

Luego de finalizados estos pasos, es hora de instalar las Google Apps.

Simplemente, presionan el botón POWER unos segundos para que salga el menú, escogen “Apagar” y listo. Volvemos a iniciar en modo Android Recovery.

Igual, seleccionan “Install Zip from SDCard” > “Choose Zip from SDCard”, navegan por la SD hasta encontrar el archivo “gapps-jb-20131207-olympus.zip” y listo.

NOTA: esta versión de Google Apps para Motorola Atrix no posee ni Google Now ni Hangouts, deberán ser instalados a mano desde Google Play.

Al reiniciar el equipo (que tarda un poco más mientras se “asienta” la ROM) se iniciará el asistente para configurar la cuenta Google.

 

Conclusiones

Es un equipo modesto, de prestaciones decentes, con algunas características muy interesantes (como Webtop) que fue abandonada por Motorola, que me permitirá volver a la vida digital con un equipo del que estoy seguro, me dará más de una idea loca que publicaremos por acá.

Happy Hacking!

[apache] benchmark de diversas configuraciones de Apache+PHP

He estado configurando un load-balance de servidores Apache2; claro, usando nginx como proxy reverso, una de las dudas que me saltó durante las pruebas fue:
¿cómo lograr el máximo rendimiento en cada nodo?, y es que, cada nodo de apache2 se ejecuta en una máquina virtual con una ínfima cantidad de RAM, así que, manos a la obra, decidí tomar el control del asunto.

Apache y MPM

Los “módulos de multi-procesamiento” (“Multi-Processing Modules” ó MPM) es como llama apache a sus módulos que procesan las solicitudes.

mpm_prefork: el más antiguo y utilizado por usuarios de PHP, prefork genera procesos de apache con el interprete PHP imbuido (mod_php), es el más sencilo de configurar (apt-get install apache2-mpm-prefork libapache2-mod-php5); sin embargo, prefork tiene el inconveniente de tener que integrar un compilador de PHP en cada proceso, por consiguiente el consumo de recursos ante sitios con alta demanda, es excesivo.

mpm_worker: en worker no sólo se generan procesos, sino que cada proceso puede generar múltiples hilos, al procesar múltiples hilos de manera asincrónica a la vez, podemos consumir menos recursos que levantar un proceso de apache por cada solicitud

mpm_event: es una versión más reciente de worker, los procesos padre generan hilos “principales”, dichos hilos principales pueden “pasar” procesos a hilos hijos (creados por demanda) para asumir nuevas solicitudes, event tiene una característica de trabajo muy parecida al modo asíncrono multi-hilado de Nginx.

Las pruebas:

Hemos instalado el siguiente servidor (una máquina virtual) muy sencilla:

Servidor: Debian Wheezy 7.0
RAM: 512MB
Document Size: 70Kb
CPUs: 1

Usando apache benchmark, con una configuración muy simple:
ab -n 100 -c 50 http://web1.example.net/test.php

Donde test.php contiene un “loop” sencillo y un phpinfo().

He decidido probar las diferentes combinaciones tomando el mejor de 10 resultados.

Resultados (raw)

* apache mpm_prefork + mod_php:

la clásica combinación MPM_PREFORK+MOD_PHP.

Server API: Apache 2.0 Handler

Concurrency Level: 50
Time taken for tests: 37.756 seconds
Complete requests: 100
Failed requests: 14
 (Connect: 0, Receive: 0, Length: 14, Exceptions: 0)
Write errors: 0
Total transferred: 6701286 bytes
HTML transferred: 6674386 bytes
Requests per second: 2.65 [#/sec] (mean)
Time per request: 18877.780 [ms] (mean)
Time per request: 377.556 [ms] (mean, across all concurrent requests)
Transfer rate: 173.33 [Kbytes/sec] received

* apache mpm_worker + php5-fpm + fastcgi:

hemos combinado PHP5-FPM (vía socket, es unos 15% más rápido así que vía TCP, ya que te quitas unas cuantas capas del transporte TCP/IP) + fastcgi (el modo por defecto de configurar FPM, ya que fcgid no permite enviar solicitudes a procesos remotos).

Server API FPM/FastCGI

Concurrency Level: 50
Time taken for tests: 33.945 seconds
Complete requests: 100
Failed requests: 5
 (Connect: 0, Receive: 0, Length: 5, Exceptions: 0)
Write errors: 0
Total transferred: 7714795 bytes
HTML transferred: 7680695 bytes
Requests per second: 2.95 [#/sec] (mean)
Time per request: 16972.487 [ms] (mean)
Time per request: 339.450 [ms] (mean, across all concurrent requests)
Transfer rate: 221.95 [Kbytes/sec] received

Nota: el uso de RAM es muy eficiente usando php5-fpm, nunca consumiendo más de 140MB de RAM.

* apache mpm_worker + php5-cgi + mod_ fcgid:

combinamos mpm_worker con PHP5 en modo fastCGI pero usando fcgid

Server API CGI/FastCGI

Concurrency Level: 50
Time taken for tests: 32.200 seconds
Complete requests: 100
Failed requests: 8
 (Connect: 0, Receive: 0, Length: 8, Exceptions: 0)
Write errors: 0
Total transferred: 7641087 bytes
HTML transferred: 7606987 bytes
Requests per second: 3.11 [#/sec] (mean)
Time per request: 16099.806 [ms] (mean)
Time per request: 321.996 [ms] (mean, across all concurrent requests)
Transfer rate: 231.74 [Kbytes/sec] received

* apache mpm_event + php5-cgi + mod_fcgid:

realizamos la misma combinación, pero sustituyendo mpm_worker por mpm_event.

Server API CGI/FastCGI

Concurrency Level: 50
Time taken for tests: 46.755 seconds
Complete requests: 100
Failed requests: 8
 (Connect: 0, Receive: 0, Length: 8, Exceptions: 0)
Write errors: 0
Total transferred: 7641191 bytes
HTML transferred: 7607091 bytes
Requests per second: 2.14 [#/sec] (mean)
Time per request: 23377.675 [ms] (mean)
Time per request: 467.553 [ms] (mean, across all concurrent requests)
Transfer rate: 159.60 [Kbytes/sec] received

* apache mpm_event + fastcgi + php5-fpm:

La misma combinación de fastcgi + php5-fpm, pero usando mpm_event

Server API FPM/FastCGI

Concurrency Level: 50
Time taken for tests: 35.976 seconds
Complete requests: 100
Failed requests: 10
 (Connect: 0, Receive: 0, Length: 10, Exceptions: 0)
Write errors: 0
Total transferred: 7714787 bytes
HTML transferred: 7680687 bytes
Requests per second: 2.78 [#/sec] (mean)
Time per request: 17987.970 [ms] (mean)
Time per request: 359.759 [ms] (mean, across all concurrent requests)
Transfer rate: 209.42 [Kbytes/sec] received

Nota: se incrementó hasta 400 conexiones con 100 niveles de concurrencia, los valores de conexión y procesamiento se mantuvieron invariables.

 

Las gráficas

… y es que la gente le encanta un gráfico

conexion

El primero representa el tiempo que tarda Apache en recibir una conexión y procesarla, como vemos, aun con pocas solicitudes, prefork se va **adelante** (pues el servidor con solo 512MB de RAM estaba a punto de irse a la SWAP), mientras, mpm_event fue más diligente en conectarse y procesar rápidamente las solicitudes, sin tomar en cuenta cuanto más tardó en transmitirlas.

Ganador: Empate entre MPM-Event+PHP5-FPM y MPM-Event+PHP5-CGI+FCGID

tiempo-total

El tiempo total de la prueba, es lo que tardó Apache desde que se inició el apache-benchmark hasta que se completaron las 100 solicitudes, como vemos (y muy interesante el resultado) event-fcgid fue el peor en el resultado, tardando incluso más que mpm_prefork en conectar-procesar y transmitir resultados, de manera paradójica, la misma configuración pero usando mpm_worker fue la mejor de todas.

Ganador: MPM-Worker+PHP5-CGI+mod_fcgidsolicitud

En general, los resultados fueron parejos, sin embargo, worker-fcgid aparece nuevamente victorioso acá, además, en promedio terminó más solicitudes por segundo (unas 3.11 solicitudes/seg versus 2.9 de worker-fpm).

Ganador: MPM-Worker+PHP5-CGI+mod_fcgid
transfer-rate

 

La velocidad de respuesta, o rata de transferencia de los datos desde el servidor hacia el cliente, es también muy importante, como vemos, Worker-fcgid aparece con una velocidad más alta que el resto.

Ganador: MPM-Worker+PHP5-CGI+mod_fcgid

… ¿Y por qué no Nginx?

Con un conjunto de VPS, uso de .htaccess, facilidad de implementación de instalaciones adaptadas a apache2, en uso de apache2 es *casi* que una obligación en el proyecto que estoy realizando, sin embargo, es más que notable la diferencia de Nginx+PHP5-FPM versus el resto de configuraciones.

Pero para este caso en particular, necesitaba apache2.

Las conclusiones

Es precipitado adelantarse a dar ganadores sin explicar para qué se podría utilizar cada combinación, por ejemplo, mpm_prefork se muy sencillo de configurar y para sitios web con muy pocas visitas y si el recurso no es problema, con APC (o xcache) más mod_deflate+mod_expires puede superar a cualquiera de las configuraciones actuales.

Para sitios web con muchísimo tráfico y tiempos de respuesta cortos, es obvio que MPM-Worker+PHP5-CGI+mod_fcgid podría rendir mejor que cualquier otra combinación (MPM-Event+PHP5-FPM+FastCGI podría ser una segunda opción); sin embargo, hay que recordar que mod_fcgid no permite llamar procesos externos (como PHP5-FPM).

PHP5-FPM aparece como una buena opción (en conjunto con MPM-Worker, aunque mejores números, MPM-Event suele consumir más recursos como RAM y CPU que Worker) para pequeños servidores con bajos recursos, PHP5-FPM es bastante óptimo (durante las pruebas Apache+PHP-FPM+todo el sistema operativo no consumían más de 150MB de RAM), además la posibilidad de “compartir” el proceso PHP5-FPM con otras instancias (de apache o de nginx) tanto en el servidor como en otros servidores, nos brindan un ahorro notable de recursos.

La gran sorpresa de la noche fue mpm_event, tal vez me faltó algún detalle de configuración, sin embargo, ver que MPM_EVENT consume más recursos que mpm_worker y además, no rinde mejor que este … me hace dudar de implementarlo con PHP.

[Linux] De las comparativas (benchmarks) y otras justificaciones

Introducción

En un comentario anterior, el compañero Piccoro, hace una remembranza de unas pruebas de rendimiento que hiciera hace ya mucho Sun Microsystems  (antes que la comprara Oracle Corp.) sobre sus conocidos equipos SunFire, estas pruebas de rendimiento (conocidas como las “SPECjAppServer2004”) realizadas en 2007, ahora no están al alcance del público (aunque pueden aún ser encontradas en mi dropbox) pero demuestran el rendimiento de una misma aplicación, optimizada en estos equipos para Oracle, postgreSQL y MySQL.

¿Qué descubrimos con esta prueba?, veamos!.

La prueba Java (antes que fuera de Oracle)

MySQL 5 fué instalado en un equipo con las siguientes características:

  • Sun Fire X4100 (2×285,4x2GB,2X73GB) (2)
  • Sun StorEdge 3320, 12x73GB, 1 RAID CONT
  • Single-Port PCI Ultra320 SCSI HBA

Costo de la Licencia: 0$
Costo de implantación : 59.260 US$
MySQL: 720 JOPS

PostgreSQL 8.2 fué instalado con estas características:

  • Server HP Integrity rx2660 1.6Ghz 18GB 4-core (2)
  • 12GB DDR2 memory pair
  • SAN Array 1000

Costo de la Licencia: PostgreSQL 8.2 (0 US$)
Costo: 70.701 US$
Puntaje: 778 JOPS

Y Oracle 10g fué instalado con las siguientes características (semejantes a PostgreSQL)

  • Server HP Integrity rx2660 1.6Ghz 18GB 4-core (2)
  • 12GB DDR2 memory pair
  • SAN Array 1000

Costo de implementación: 70.701 US$
Licencias: Oracle 10g Enterprise + Oracle App Server + Oracle Partition Option
Costo en Licencias: 120.000 US$
Puntaje: 874 JOPS

Las pruebas, aunque en el mismo hardware físico gana Oracle (por al menos unos 70 puntos), demuestran que necesitas gastar 200US$ por unidad adicional para poder implementar Oracle, es decir, que con el costo *únicamente* de las licencias Oracle podrías incorporar 2 nodos más al cluster postgreSQL; qué, manteniendo la proporción de crecimiento, implementar un único servidor Oracle a 874 JOPS cuesta lo mismo que implementar un cluster de 3 nodos postgreSQL (ejecutandose a un rendimiento de 2334 JOPS).-

¿Cierto o falso?, queda a criterio del lector, la EULA de Oracle prohibe terminantemente la realización de pruebas y publicación de resultados sin su autorización, so-pena de recibir acciones legales, pero como yo no hice el benchmark! ;)

pero revisemos otro benchmark.

Cuándo VMWare decidió no publicar “malos benchmarks”

En una aclaratoria en su blog, la gente de VMWare explica que la clausula de la EULA (End-User License Aggrement) donde se prohíbe terminantemente la publicación de benchmarks de su producto versus otros productos de virtualización, no es porque “ellos estén en contra de las pruebas”, sino que le “sugieren amablemente” a las empresas encargadas de hacerlas, a que optimicen su producto y sólo utilicen el hardware que a “ellos” les es más conveniente, ¿interesante, no?.

Hace ya algún tiempo, la gente de specs.org publicaron una comparativa entre VMware ESX, la solución de virtualización para datacenters, y Linux KVM sobre Red Hat 6.1, resumiendo la conclusión:

KVM: SPECvirt_sc2010 1820 @ 114 VMs

VMWare: SPECvirt_sc2010 2721 @ 168 VMs

114 máquinas virtuales versus 168 es bastante, ¿no?, 900 puntos de diferencia en cuánto a rendimiento, también, ¿verdad?, pero, veamos a los detalles:

Primero, el equipo “sugerido” por VMWare para la prueba:

CPU: Intel(R) Xeon(R) X7560
Velocidad: (MHz) 2266
Núcleos: 32 cores, 4 chips, 8 cores/chip, 2 threads/core

Y el equipo con Red Hat:

CPU: Intel Xeon E7-2870
Velocidad: (MHz) 2400
Núcleos: Cores 20 cores, 2 chips, 10 cores/chip, 2 threads/core

El último es un simple HP Proliant Generación 7 (a un costo de 16800US$), el primero es un equipo ensamblado “especificamente” para VMWare, por su partner Bull Novascale, el “Novascale Bullion” fué catalogado como “el equipo para datacenter x86 más rápido del mundo” en 2011 y tiene un costo de 25 mil dólares la unidad.

Si a eso le sumamos la licencia de VMWare ESXi (9200 dólares por cada 2 núcleos), la cosa quedaría *más o menos* así:

KVM: Red Hat Licencias (Server=6500$ + Virtualización=6700) = 13200$
Servidor: 16800$
Total: 30000 US$
Costo: 263 dólares por VM (máquina virtual)

VMWare: Licencia=9200$ x 16 cores = 147200US$
Servidor: 25000 US$
Total: 172200 US$
Costo:  1025 US$ por VM (máquina virtual)

Entonces, ¿dónde está el rendimiento y el abaratamiento de precios?, además, hagamos algo bastante “jocoso”, reemplacemos Red Hat por Debian Linux (que el valor de siu licencia es “0$” – se lee cero!-) y te darás cuenta que por el mismo precio de la implementación de VMWare en tu empresa podrías pagar 11 servidores Proliant con GNU/Linux, ¡En vez de un equipo, tendrías un datacenter!  donde podrías en promedio (y según las cifras de Debian) virtualizar 990 máquinas virtuales.

A mí, me enseñaron que 990 VMs > (se lee, “es mayor qué”) 168 VMs, ¿no creen?.

Saquen ustedes sus propias conclusiones.

[postgreSQL] Una instalación de postgreSQL básica (¡pero mejor!)

PostgreSQL: Introducción

PostgreSQL es una de las grandes maravillas del software libre, robusto, potente, altamente funcional, distribuido en miles de formas posibles (greenplum=clusterizador masivo, postgres Plus=”imitador” de Oracle,deepgreen=granjas de datawarehousing con postgreSQL, etc) puede ser optimizado (como todo lo que es software libre) de maneras inimaginables para cada necesidad específica. Entonces, ¿por qué hay gente que denigra de él? …

El primer error que comete la gente, es pretender que un sistema tan necesario como la base de datos, sea utilizado “directamente” luego de su instalación; un detalle de distribuciones Linux como Debian, es no optimizar para ningún aspecto (ya que son meta-distribuciones genéricas sin una orientación específica).

Mientras Oracle saca libros de 900 páginas de cómo optimizar al máximo hardware, sistema de archivos, sistema operativo y la base de datos como tal, mucha gente piensa “migrar” a postgreSQL ejecutando un “aptitude install postgresql” y dejándolo así … nada más perdido y lejos de la realidad.

Acá, ejecutaremos una instalación que debería ser “básica”, la más básica, para un entorno pequeño de datos, para que sus sistemas “rindan”.

Preámbulo

Uno de los aspectos más importantes es que postgreSQL “no debería” compartir acceso a disco con el sistema operativo, esto es, si es posible que postgreSQL esté en una partición distinta a “root” (incluso un disco separado, de ser recomendable); por lo que la opción “instalar y usar” no debería ser para instalaciones en producción de postgreSQL 9.1.

Hay que tomar en cuenta que postgreSQL (como cualquier otra base de datos) debería ser optimizada posteriormente a su instalación de manera correcta, una de las optimizaciones más necesarias (pero que casi nadie sigue) es gestionar los espacios de datos y separarlos del tablespace pg_default (que gestiona la DB “postgres”, la DB de “information_schema” y demás información, por lo general en “/var/lib/postgresql/9.1/main”); además, ambos deberían estar separados de la partición raíz donde está el sistema operativo.

Las optimizaciones acá realizadas son de las más sencillas a nombrar para postgreSQL, se tomó una máquina virtual en Xen 4.1 en una portátil y se optimizó de lo más básico, para demostrar, que hasta en los cambios más sencillos, pueden afectar el “performance” de aplicaciones diseñadas con postgreSQL.

Preparación primaria

Si estamos instalando un servidor de datos, lo primero que debemos pensar es en separar el montaje de /var del resto del sistema, de hecho, si podemos incluso separar /var/log sería muy apropiado; también es bueno separar /tmp (más 1Gb es innecesario) ya que si no separamos /tmp, Debian GNU/Linux utilizará un tmpfs montado en RAM para gestionar /tmp (restándonos un poco de RAM para trabajar, además que postgreSQL no utiliza la partición /tmp).

Un esquema básico podría ser:

  • / (raiz) (Debian GNU/Linux no ocupa más de 5Gb en este modo)
  • /tmp (1Gb como máximo)
  • swap (Lo necesario, aunque no mayor a 2GB en sistemas con más de 4Gb de RAM)
  • /var (2~4GB ya que será un servidor en producción)

Y de resto, un volumen lógico (LVM) que podemos modificar de tamaño de acuerdo a nuestra necesidad.

Luego de instalado el sistema, procedemos a instalar PostgreSQL.

Instalación

La instalación de postgreSQL 9.1 en Debian GNU/Linux es bastante sencilla:

  • Instalamos postgreSQL 9.1 (pero así no se debería quedar):
    apt-get install postgresql-9.1

PostgreSQL por defecto, creará una carpeta de configuración en: /etc/postgresql/9.1/main/

Y creará un espacio de datos en: /var/lib/postgresql/9.1/main/

Que no utilizaremos para nuestra base de datos, ya que crearemos un espacio propio.

Configuración inicial

Siempre es recomendable dejar el usuario “postgres” (el super-usuario de PostgreSQL) como un usuario “para accesos de emergencia”, ya que este usuario tiene garantizado el acceso a todas partes(si eres root en el sistema), es recomendable que NINGUNA base de datos tenga como “owner” el usuario postgres (y evitar en lo posible utilizarlo como usuario de acceso desde sistemas, aunque esto, obviamente lo he visto más de una vez ocurrir hasta en sistemas web).

  • Creamos un super-usuario para nuestras necesidades, primero cambiamos al usuario postgres:
    su postgres
  • Creamos un usuario, que será nuestro “super-usuario” para “nuestros” accesos, evitando así el usuario postgres:
    createuser -sPl jesuslara
    
    -- ingresamos nuestra contraseña
    Enter password for new role: 
    Enter it again:
  • Ejecutamos la consola SQL de postgreSQL:
    psql
  • Garantizamos al usuario que creaste acceso irrestricto sobre el la DB postgres:
    psql (9.1.3)
    Type "help" for help.
    
    postgres=# grant all on database postgres to jesuslara;
    GRANT

Y salimos de la consola:

postgres=#\quit

Configuración de postgreSQL

  • Accedemos al directorio /etc/postgresql/9.1/main
    cd /etc/postgresql/9.1/main
  • Si vamos a acceder de manera remota a nuestro postgreSQL, agregamos la siguiente línea al archivo pg_hba.conf:
    # la forma es:
    # host -> database (all: todas las db) -> usuario (all: todos los usuarios) -> subnet (de nuestra red) -> modo de clave
    host    all     jesuslara       192.168.100.0/24        md5
  • Habilitamos el acceso remoto en nuestro postgreSQL:

archivo /etc/postgresql/9.1/main/postgresql.conf

listen_addresses = '*'

Optimización del archivo postgresql.conf

  • Y cambiamos algunas opciones básicas del archivo postgresql.conf:
    shared_buffers = 256MB

‘shared_buffers’: Es la memoria de trabajo compartida para todo el servidor postgreSQL, fíjese que por defecto en Debian GNU/Linux la opción es 24MB (y el valor por defecto si comentamos es 32MB), sin embargo, como esta es la memoria utilizada para trabajo de postgreSQL, es recomendable “al menos” el 25% de la RAM disponible (y jamás > 40%).

temp_buffers = 16MB

‘temp_buffers’: La memoria temporal utilizada por cada sesión para las tablas temporarias y para apertura de tablas en cada sesión de cada base de datos, tome en cuenta que este valor dependerá obviamente de la cantidad de datos que carga cada sesión y dependerá muchísimo del sistema que se utiliza.

work_mem = 16MB

‘work_mem’: uno de los valores más importantes y más despreciados, “work_mem” se refiere a la memoria temporal utilizada por cada sesión, para las operaciones de ordenamiento (ORDER BY) para las sesiones de diferenciación (GROUP … HAVING y DISTINCT) y para la gestión de hash (uniones HASH, indices HASH, hash_aggregations), si en nuestro sistema realizamos muchísimas consultas ordenadas, agrupadas, diferenciadas por cadenas, etc se crearán mucho de estos buffers de manera paralela, mientras más memoria asignemos, menos probabilidades hay que los ordenamientos y otras operaciones se hagan con archivos temporales en disco (más lentos que la memoria RAM).

max_stack_depth = 8MB

‘max_stack_depth’: define el tamaño del espacio utilizado para cómputo de operaciones complejas, su valor está asociado al límite máximo que un usuario (en este caso, “postgres”) tiene derecho a reservar un stack, el valor soportado por nuestra distribución se determina con “ulimit -s”.

shared_preload_libraries = '$libdir/plpython2.so'

‘shared_preload_libraries’: Permite cargar una librería específica cuando arranca el sistema, si utilizamos muchos procedimientos almacenados en un lenguaje específico (ej: python, perl, tcl, java, etc), es bueno pre-cargarla para que esté disponible cuando se utilice por primera vez. Nota: esta opción ralentiza un poco el reinicio del sistema.

bgwriter_delay = 500ms

‘bgwriter_delay’: El background-writer es un proceso del servidor que se encarga de escribir a disco todos los “shared_buffers” modificados, este proceso conlleva una carga de I/O sobre el disco, su modificación permite o reducir el valor para evitar en lo más posible pérdidas de datos en equipos que pueden fallar, o su incremento permite reducir el I/O al disco duro en sistemas perfectamente protegidos.

Modificados estos parámetros básicos, vamos a modificar nuestro sistema operativo.

Optimización de Linux para postgreSQL

Una de las cosas que olvidamos “optimizar” (tunning) es nuestro sistema operativo GNU/Linux, con grupo de valores en el sysctl ya podemos ayudar “mucho” a nuestro postgreSQL.

  • Agregamos al archivo sysctl.conf

archivo: /etc/sysctl.conf

kernel.sem = 100 32000 100 128
kernel.shmall = 3279547
kernel.shmmax = 289128448
kernel.shmmni = 8192
fs.file-max = 287573
vm.dirty_bytes = 67108864
vm.dirty_background_bytes = 134217728

Nota: observe el valor de shmmax, la cantidad de “memoria máxima reservada para un shared_buffer” que puede crear una aplicación debe ser igual o mayor al valor del shared_buffer de postgreSQL, este valor está en bytes y es ~ 275MB.

La cantidad máxima de archivos que pueden abrirse en un sistema, dependerá obviamente del nivel de trabajo de la DB, durante una operación regular, la gente puede ejecutar “lsof | wc” para obtener la cantidad de archivos abiertos.

  • Y luego, las aplicamos:
    sysctl -p
    
    --
    kernel.sem = 100 32000 100 128
    kernel.shmall = 3279547
    kernel.shmmax = 289128448
    kernel.shmmni = 8192
    fs.file-max = 287573
    vm.dirty_bytes = 67108864
    vm.dirty_background_bytes = 134217728

Ya, con estos sencillos cambios, podemos reiniciar el postresql:

/etc/init.d/postgresql restart
Restarting PostgreSQL 9.1 database server: main.

Y estamos listos para crear una partición y tablespace para nuestra DB.

Creación del espacio de tablas

Creamos una partición del tamaño necesario para contener “al menos” nuestra base de datos (esta es una guía básica, no hablaremos de particiones adicionales para metadatos, para índices y demás).

Nota: en nuestro caso, la partición es /dev/xvdb1 y mide 10GB.

El “journal”, para quien no lo conoce, es la razón por la cual no existe software de “desfragmentación” en Linux, todos los sistemas operativos que lo soportan (ext3, ext4, jfs, reiserfs, xfs, zfs, etc) tienen servicios que se encargan de ordenar, desfragmentar y gestionar tanto la data como los metadatos (información acerca de los archivos y carpetas en sí), pero además, los journal cumplen otras funciones, entre ellas, recuperar desde sus logs la data que pudiera “haberse perdido” luego de un fallo de energía y/o de sistema.

En sistemas de base de datos, la data es contenida en uno o más (y diversos) tablespaces, espacios de tablas donde la data, metadata e índices es contenida, como es la base de datos la encargada de gestionar la posición de los datos en ellos, el Sistema Operativo no requiere la presencia de un journal, o al menos, de un journal más relajado y menos estricto.

Formateando la partición

  • Se formatea la partición (disco):
    mkfs.ext4 -E stride=32 -m 0 -O extents,uninit_bg,dir_index,filetype,has_journal,sparse_super /dev/xvdb1

Utilizamos ext4, porque en modo “writeback” tiene un mayor performance que XFS para almacenar los tablespaces y tiene menor propensión a fallos.

  • Habilita el journal en modo writeback:
    tune2fs -o journal_data_writeback /dev/xvdb1
  • Si simplemente desea eliminar el journal, ejecute:
    tune2fs -O ^has_journal /dev/xvdb1
  • Nota: utilice esta opción a su propio riesgo, recuerde que no tener un journal afecta de 2 modos:
  • La data no es colocada en orden en el disco, fragmentando el mismo
  • Ante un fallo de energía, el FS no podrá recuperar desde el journal las últimas actividades para recuperar esos datos.
  • Se ejecuta un chequeo de archivo básico:
    e2fsck -f /dev/xvdb1
  • Creamos la carpeta de postgresql:
    mkdir /srv/postgresql
  • Y luego se monta con las opciones que describiremos más abajo:
    mount -t ext4 /dev/xvdb1 /srv/postgresql -o  noatime,nouser_xattr,noacl,discard,nodelalloc,data=writeback,barrier=0,commit=300,nobh,i_version,inode_readahead_blks=64,errors=remount-ro

Las opciones son:

Opciones de FS Linux:

noatime

No guardar la información del timestamp del último acceso a los archivos, esta información no es necesaria ya que postgreSQL gestiona apropiadamente el acceso a los tablespaces.

nouser_xattr

Deshabilita el uso de atributos extendidos de usuario, esto es seguro en postgreSQL ya que la carpeta donde se guardan los tablespaces no requiere ninguno de esos atributos.

noacl

No utilizar atributos extendidos ni ACLs POSIX, no son necesarias ya que solamente postgreSQL tendrá acceso a los archivos en esta partición.

Opciones específicas de ext4:

nobh

ext4 asocia buffers de datos con las páginas de datos, esos bloques de cache proveen garantía de ordenamiento de los datos; “nobh” evita el uso de estos buffers de ordenamiento de datos (sólo activable con “data=writeback”).

data=writeback

No se preserva el ordenamiento de los datos, la data será escrita en el sistema de archivos solo después que la metadata ha sido guardada en el journal. Aunque hay personas que recomiendan desactivar el “journaling” del disco, esto no es recomendable pues, aunque postgreSQL gestiona correctamente los datos, los metadatos (información de los archivos y carpetas en el FS) es responsabilidad de mantenerla consistente el FS.

commit=seconds

Los datos y metadatos son escritos a disco cada “n” cantidad de segundos, el valor por defecto son 5 segundos (commit=0 es igual a dejar el valor por defecto), un valor más bajo puede mejorar la seguridad de los datos, un valor muy alto mejora el performance pero ante un fallo podría perderse datos.

barrier=0

Deshabilita el uso de barreras de escritura, las barreras de escritura fuerzan el uso de ordenamiento on-disk de los commits al journal, haciendo las caché de disco seguras de usar, pero un daño en el performance del disco.

inode_readahead_blks=n

Cantidad de inodes que el sistema de pre-lectura de ext4 lee al buffer caché, el valor por defecto de n es 32, pero un valor de 64 es normal para optimizar las lecturas.

discard

Permite decidir que realiza con los bloques que son liberados, por lo general ext4 ejecuta una operación de trim (limpieza), con esta opción, ellos simplemente son marcados como descartados, evitando la escritura innecesaria de bloques.

i_version

Permite indicar que los inodes serán de 64-bits, solo disponible si se está en un sistema a 64 bits.

  • Luego de montada de esta manera, lo fijamos en el /etc/fstab
# particion para postgresql
/dev/xvdb1 /srv/postgresql ext4 rw,noatime,errors=remount-ro,nouser_xattr,noacl,commit=300,barrier=0,i_version,nodelalloc,data=writeback,inode_readahead_blks=64,discard 0 0
  • Comprobamos:
    mount -a

Y ya estamos listos para crear el espacio de datos para nuestra DB!.

El espacio de tablas (tablespace)

Crearemos un simple espacio de tablas en nuestro optimizado sistema de archivos ext4 para contener nuestra base de datos:

  • cambiamos el propietario a la carpeta /srv/postgresql
    chown postgres.postgres /srv/postgresql
  • cambiamos al usuario “postgres” y abrimos la consola ‘psql’:
    su postgres
    psql
  • En la consola, ejecutamos el comando para crear un espacio de tablas:
    postgres=# CREATE TABLESPACE db_sistema OWNER jesuslara LOCATION '/srv/postgresql';

Y listo!, ya tenemos un espacio de tablas disponible para crear bases de datos y optimizado!

Usando el espacio de datos optimizado

Para crear una DB que no esté asociada al espacio “por defecto” (pg_default) ejecutamos:

  • Crear una DB:
CREATE DATABASE sistema WITH ENCODING='UTF8' OWNER=jesuslara TEMPLATE=template0 TABLESPACE=db_sistema;

Y como verán, le pasamos el tablespace “db_sistema” que hemos creado anteriormente.

¿Alguna prueba de la eficiencia?

La configuración siguiente no se hizo en un sistema dedicado para tal, se realizó en una portátil, corriendo Xen 4.1 y en una VM con 1GB de RAM se instaló el postgreSQL con las opciones nombradas, sin embargo, es posible notar una mejora en el performance general de las consultas (y eso que son solamente optimizaciones básicas).

Para ello, creamos una DB adicional, de un sistema administrativo (migrado desde Oracle hasta postgreSQL) que un amigo amablemente me facilitó para esta prueba.

Para ello, se movieron algunas funciones de código “Visual Basic” a código PL/Python y PL/pgSQL y se creó una consulta semi-compleja, de unas 26 líneas de extensión, que unifica unas 6 tablas del sistema para calcular una simple pre-nómina (ivss, paro forzoso, caja de ahorros, faov, isrl, etc); hay que notar que en la versión “cliente-servidor” de la aplicación, la nómina de 13 mil empleados dura varias minutos hasta horas con múltiples conceptos; para nuestra versión “simplificada” (5 asignaciones y 3 deducciones y cálculo de salario integral); la consulta se ejecutó en: 33068ms Para 13674 registros.

Pero, lo mejor ocurre si lo ejecutas por segunda vez!, ya que los buffers de trabajo mantienen en cache las operaciones de hash_aggregate (necesarias para algunos de los cómputos de agregado realizados), la segunda ejecución fué: 3107 milisegundos (3 segundos)

¿13 mil cómputos de empleados en 3 segundos?, ¡Nada mal para ser una portátil!

Conclusiones

Estas optimizaciones no son ni la décima parte de las que podemos optimizar de postgreSQL, pero es un comienzo, esta guía surge de la necesidad de orientar a las personas, que creen que pueden poner un sistema en producción de un postgreSQL recién instalado, estas optimizaciones mínimas, que cualquiera puede seguir, son un ejemplo y un comienzo.

No se dejen engañar con esas personas que dicen que “postgreSQL no rinde como Oracle” y un largo etcétera de excusas baratas, si alguien en su sano juicio instala Oracle cambiando parámetros en el sysctl, modificando los valores de tunning del sistema operativo o del sistema de archivos, clusterizar al máximo e incluso hace cosas más “malandras” como generar índices “al vuelo” por aquellos DBA vagos que jamás piensan bien sus bases de datos; ¿por qué la gente no hace lo mismo con postgreSQL?, tal vez porque ser un DBA “certificado postgreSQL” es más difícil y hacer entender a la gente, cuando crean un sistema conectado a datos, que su principal preocupación no debería ser “si usar PHP o Python” sino ver de qué formas optimizarás el S.O, el sistema de archivos, las consultas, el planificador, el acceso a disco y la gestión de índices para lograr que te sea “inocuo” si la gente utiliza perl o Visual Basic como Front-End.

Al final, postgreSQL debe tener el mando de los datos de la aplicación, y aprender a “verdaderamente” instalarlo, es el primer paso!.

¡Happy Hacking!

[Trac] Instalando SCM Trac en Debian Wheezy y derivados (Ubuntu, Mint, Canaima)

Preámbulo

Un amigo me solicitó la bitácora de instalación de Trac en Debian Wheezy, había tenido algunos detalles utilizando Trac y postgreSQL 9, por lo que decidí publicarla para que más personas pudieran aprovecharla, sin embargo, como el Wiki de GNU de Venezuela no está operativo (donde estaba la versión Squeeze) entonces publicaré toda la guía por acá.

Instalación de Trac

Trac funciona en el modo “instancia”, cada instancia requiere de su propia base de datos y de su propia carpeta (instancia), pero comparten un único punto en el servidor web, aunque Trac utiliza por defecto sqlite para la base de datos, utilizaremos postgreSQL.

La instalación se realiza en una distribución Debian-based pero puede ser realizada en cualquier distribución GNU/Linux que posea python-setuptools y el comando easy_install (o pip).

Instalación de dependencias

  • Instalar las dependencias en Debian Wheezy (o distribución compatible con aptitude | apt-get):
aptitude install apache2 python2.7-setuptools python-genshi python-pybabel python-psycopg2 python2.7-psycopg2 libapache2-mod-wsgi python-babel babel-1.4.0 postgresql-8.4 subversion git mercurial bzr

Nota: si utiliza postgresql-9.1 con Trac < 0.12.2 tendrá que realizar una correción en el código fuente de Trac para poder crear instancias en schemas de postgreSQL 9.

Nota: Si se instala babel posterior a la instalación de Trac, deberá reinstalar trac y actualizar sus instancias.

  • Opcionalmente, podemos actualizar setuptools (requiere conexión a Internet)
easy_install -U setuptools

Instalación de Trac

  • Vía apt-get:
    apt-get install trac trac-bzr trac-git trac-graphviz trac-mercurial trac-odtexport trac-wikiprint
  • ó via easy_install:
easy_install Babel==0.9.5 Genshi==0.6
easy_install Trac
  • También podemos descargar el fuente e instalarlo manualmente:
    wget -c http://ftp.edgewall.com/pub/trac/Trac-0.12.2.tar.gz
    tar xvf Trac-0.12.2.tar.gz
    cd Trac-0.12.2
    python ./setup.py install

Nota: si deseamos instalar (o descargar) la versión de pruebas ejecutamos:

  • Usando easy_install:
easy_install Trac==dev
  • Descargando:
    svn co http://svn.edgewall.org/repos/trac/trunk trac
    cd trac
    python ./setup.py install

Por ultimo, luego de instalado, verificamos que tenemos la última versión:

trac-admin --version

Luego de instalado Trac, procedemos a configurar una instancia.

Configuración de una instancia

Preparación de la DB de postgreSQL

Agregar las siguientes líneas al archivo pg_hba.conf:

archivo: /etc/postgresql/{version}/main/pg_hba.conf

local tracdb tracuser password
host tracdb tracuser 127.0.0.1/32 md5
host tracdb tracuser [subnet]/24 md5
#para poder iniciar sesion en red:
host all all [subnet]/24 md5

Donde [subnet] se reemplaza por la subnet de la red local; ejemplo:

local tracdb tracuser password
host tracdb tracuser 127.0.0.1/32 md5
host tracdb tracuser 192.168.1.0/24 md5
#para poder iniciar sesion en red:
host all all 192.168.1.0/24 md5

Y en postgresql.conf modificamos:

listen_addresses = '*'

Nota: solo necesario si el postgreSQL y el Trac estarán en diferentes equipos.

  • Iniciar una consola y ejecutar:
su postgres
  • E iniciar una consola de postgreSQL:
    >psql
  • En la consola de postgreSQL, crear la DB:
  • Para crear una DB en > 8.4 ejecutar:
    CREATE DATABASE tracdb
      WITH ENCODING='UTF8'
           TEMPLATE=template0
           LC_COLLATE='C'
           LC_CTYPE='C'
           CONNECTION LIMIT=-1;
  • para 8.3 o inferior:
    CREATE DATABASE tracdb 
    WITH ENCODING='UTF8' 
    TEMPLATE=template0 
    LC_COLLATE 'C' 
    LC_CTYPE 'C';
  • Crear el usuario necesario para gestionar la DB:
create user tracuser password 'clavesecreta';
  • Y garantizar los permisos necesarios sobre la DB de trac:
    grant all on database tracdb to tracuser;
  • Salimos del postgresql:
postgres=# \q

Y reiniciamos el postgreSQL:

/etc/init.d/postgresql restart

Ya estamos listos para crear una instancia de Trac.

(Opcional) Preparación de Trac con postgreSQL 9.1

Nota: cambios iniciales para Trac 0.12 y postgreSQL 9.1

Si se intenta crear una instancia de Trac en postgreSQL 9.1 utilizando un schema personalizado (no “public”), Trac devolverá un error por un detalle en el uso de psycopg (la librería python para conectarse a Trac), dicho error se ve así:

Traceback (most recent call last):
  File "/usr/lib/python2.7/dist-packages/trac/admin/console.py", line 422, in do_initenv
    options=options)
  File "/usr/lib/python2.7/dist-packages/trac/env.py", line 213, in __init__
    self.create(options)
  File "/usr/lib/python2.7/dist-packages/trac/env.py", line 401, in create
    DatabaseManager(self).init_db()
  File "/usr/lib/python2.7/dist-packages/trac/db/api.py", line 146, in init_db
    connector.init_db(**args)
  File "/usr/lib/python2.7/dist-packages/trac/db/postgres_backend.py", line 98, in init_db
    params)
  File "/usr/lib/python2.7/dist-packages/trac/db/postgres_backend.py", line 87, in get_connection
    params)
  File "/usr/lib/python2.7/dist-packages/trac/db/postgres_backend.py", line 212, in __init__
    cnx.cursor().execute('SET search_path TO %s', (self.schema,))
DataError: invalid value for parameter "search_path": "weyu"
DETAIL:  schema "weyu" does not exist

Es un error en el archivo /usr/lib/python2.7/dist-packages/trac/db/postgres_backend.py, dicho error ya está corregido en versiones posteriores de Trac y existe un patch para dicho archivo:

  • Parche que está en la incidencia #10406 de Trac:

 http://trac.edgewall.org/attachment/ticket/10406/10406-search-path-r10830.patch

Si desean hacer los cambios ustedes mismos, las líneas a cambiar son:

Línea 34:

34	 	    from psycopg2 import ProgrammingError as PGSchemaError <- eliminar esta
 	34	    from psycopg2 import DataError, ProgrammingError <- agregar esta

Línea 214:

214	 	        except PGSchemaError: <- eliminar esta
 	214	        except (DataError, ProgrammingError): <- agregar esta

Con esta correción podrán crear instancias en postgreSQL 9.1.

Creando un ambiente base (environment Trac)

  • Creamos el árbol de proyectos:
mkdir /srv/{repositorios,trac,proyectos} -p
  • Nos dirigimos a la carpeta de proyectos:
cd /srv/proyectos
  • Inicializamos la primera instancia de trac (se llamará documentacion)
trac-admin /srv/proyectos/documentacion initenv
  • Se inicia un script que realliza una serie de preguntas:
Project Name [My Project]> Documentacion GNU/Linux
  • Conexión a la DB:
Database connection string [sqlite:db/trac.db]>
  • forma del database connection string
    ''{database}://{usuario}:{contraseña}@{host}:{port}/{database}?schema={schema}''

Ejemplo:

postgres://tracuser:clavesecreta@localhost:5432/tracdb?schema=documentacion

Nota: de usar el schema “public”, simplemente no pasar la opcion schema: ejemplo:

postgres://tracuser:clavesecreta@localhost/tracdb
  • Si deseamos usar unix-sockets:

postgres://user:pass@/dbname?host=/path/to/unix/socket/dir&schema=schemaname

Ejemplo:

postgres://tracuser:clavesecreta@/tracdb?host=/var/run/postgresql/.s.PGSQL.5432/dir&schema=documentacion

— Al terminar la configuración de trac, podemos iniciar las pruebas:

  • ejecutamos:

tracd –port 8000 /srv/proyectos/documentacion

Y apuntamos nuestro navegador a:

 http://host:8000/documentacion

Luego de chequeado, procedemos a configurar nuestra instancia de Trac.

Configuración de Apache y Trac

Debemos crear un ambiente web (www) con WSGI del Trac para apache, para ello desplegamos en la carpeta web (/srv/trac/www’) el sitio web:

trac-admin /srv/proyectos/weyu deploy /srv/trac/www/

Creamos el virtualHost para multiples proyectos de trac, creamos un archivo en:

/etc/apache2/sites-availables/trac.site

<VirtualHost *:80>
# administrador del servidor
ServerAdmin jesuslara@DOMINIO
# nombre del vhost
ServerName proyectos.DOMINIO
# alias del servidor
ServerAlias trac.DOMINIO
DocumentRoot /srv/trac/www/htdocs/

        <Directory />
                Options FollowSymLinks
                AllowOverride None
        </Directory>

WSGIScriptAlias / /srv/trac/www/cgi-bin/trac.wsgi

    <Directory /srv/trac/www>
        WSGIApplicationGroup %{GLOBAL}
        SetEnv trac.env_parent_dir /srv/proyectos
        Order deny,allow
        Allow from all
    </Directory>

    ErrorLog /srv/trac/www/log/apache-error.log
    CustomLog /srv/trac/www/log/access.log combined

</VirtualHost>
  • Creamos el directorio para los logs de apache:
mkdir /srv/trac/www/log && chown www-data.www-data /srv/trac/www/ -R
  • Modificamos el archivo trac.wsgi /srv/trac/www/cgi-bin/trac.wsgi:

Este queda:

#!/usr/bin/python
# -*- coding: utf-8 -*-

import sys
sys.stdout = sys.stderr

import os
import trac.db.postgres_backend
trac.db.postgres_backend.PostgreSQLConnection.poolable = False

os.environ['TRAC_ENV_PARENT_DIR'] = '/srv/proyectos/'

def application(environ, start_request):
    if not 'trac.env_parent_dir' in environ:
        environ.setdefault('trac.env_path', '/srv/proyectos/documentacion')
    if 'PYTHON_EGG_CACHE' in environ:
        os.environ['PYTHON_EGG_CACHE'] = environ['PYTHON_EGG_CACHE']
    elif 'trac.env_path' in environ:
        os.environ['PYTHON_EGG_CACHE'] = \
            os.path.join(environ['trac.env_path'], '.egg-cache')
    elif 'trac.env_parent_dir' in environ:
        os.environ['PYTHON_EGG_CACHE'] = \
            os.path.join(environ['trac.env_parent_dir'], '.egg-cache')
    from trac.web.main import dispatch_request
    return dispatch_request(environ, start_request)

Apache debe acceder al directorio de proyectos:

chown www-data.www-data /srv/proyectos -R
  • Y al directorio trac/htdocs:
chown www-data.www-data /srv/trac -R
  • Reiniciamos apache:
/etc/init.d/apache2 restart
  • Y ya podemos acceder a nuestra instancia vía la ruta del  virtualhost:

 http://host/documentacion

Quedando el directorio así:

.
|-- proyectos
|   `-- documentacion
|       |-- attachments
|       |-- conf
|       |-- htdocs
|       |-- log
|       |-- plugins
|       `-- templates
|-- repositorio
|   `-- documentacion
`-- trac
    `-- www
        |-- cgi-bin
        |-- htdocs
        |   |-- common
        |   |   |-- css
        |   |   |-- guide
        |   |   `-- js
        |   `-- site
        `-- log

(opcional) Configuración de múltiples ambientes (instancias)

Aunque se puede crear una base de datos para cada instancia, utilizaremos una única base de datos postgreSQL y schemas por cada instancia de Trac.

  • Inicializamos una nueva instancia:
trac-admin /srv/proyectos/lyx-book/ initenv
  • Configuramos la instancia:
Project Name [My Project]> Lyx Book

Database connection string [sqlite:db/trac.db]> postgres://tracuser:clavesecreta@localhost:5432/tracdb?schema=lyx
  • Propietario www-data a la carpeta del proyecto:
chown www-data.www-data /srv/proyectos -R
  • reiniciamos apache:
/etc/init.d/apache2 restart
  • Y ya podemos ver la nueva instancia en la lista de instancias:
  • al acceder al vhost, veremos la lista de instancias:

 http://host/

— Lista de instancias:

—————————————-

Available Projects

—————————————-

Autenticación inicial del Trac

La autenticación inicial se realizará vía htpasswd (en próximo artículo, agregaré la autenticación openldap).

  • Agregamos un usuario de sistema, para administrar el trac
useradd administrador
  • Creamos el archivo inicial para autenticar los usuarios con Trac
htpasswd -c /srv/trac/www/.htpasswd administrador
  • nota: inicialmente autenticamos con el usuario administrador, con la contraseña que le asignemos.
  • Y agregamos la entrada de autenticación al vhost del trac:
        <Location />
                AuthType Basic
                AuthName "Trac"
                AuthUserFile /srv/trac/www/.htpasswd
                Require valid-user
        </Location>
  • Luego, agregamos la info de autenticación via HTPASSWD al archivo de configuración de la instancia:
  • nota: el archivo de configuración de la instancia está en /srv/proyectos/{instancia}/conf/trac.ini, ejemplo:

archivo: /srv/proyectos/documentacion/conf/trac.ini

  • Agregamos la autenticación vía htpasswd:
[account-manager]
account_changes_notify_addresses =
password_file = /srv/trac/www/.htpasswd
password_format = htpasswd
password_store = HtPasswdStore
  • Le damos privilegios de TRAC_ADMIN al usuario administrador:
trac-admin /srv/proyectos/documentacion
  • Aparece la consola de la instancia de Trac:
-
Welcome to trac-admin 0.12.2
Interactive Trac administration console.
Copyright (C) 2003-2011 Edgewall Software

Type:  '?' or 'help' for help on commands.

Trac [/srv/proyectos/documentacion]>
  • Y en la consola ejecutamos el siguiente comando:
permission add administrador TRAC_ADMIN
  • Salimos de la consola:
>exit
  • Ejecutamos el upgrade de la instancia:
trac-admin /srv/proyectos/weyu upgrade
  • Y reiniciamos apache:
/etc/init.d/apache2 restart

Y ya podemos entrar al trac como el usuario administrador:

 http://host/documentacion/admin/

Ahora podemos personalizar ciertas opciones como incorporar plugins o agregar temas.

Incorporar un Tema a Trac

Para incorporar un tema a Trac, se debe primeramente incorporar el  http://trac-hacks.org/wiki/ThemeEnginePlugin Theme Engine Plugin

Instalación del Theme Engine Plugin

  • Descargamos el gestor de temas:
svn co http://trac-hacks.org/svn/themeengineplugin/0.11/ theme-engine
  • compilamos e instalamos:
cd theme-engine
python setup.py install
  • Habilitamos el theme engine plugin en el archivo conf/trac.ini
[components]
themeengine.* = enabled
  • Y reiniciamos el apache:
    /etc/init.d/apache2 restart

Ya podemos instalar un nuevo tema.

Instalar un Tema

  • Descargamos el tema que necesitamos:
svn co http://trac-hacks.org/svn/pydotorgtheme/0.11/ pydotorgtheme
  • Habilitamos el tema como plugin en el archivo conf/trac.ini
  • Se agregan a la sección ![components] del archivo trac.ini:
    pydotorgtheme.* = enabled
  • Habilitamos el tema en la sección ![theme] del archivo conf/trac.ini
[theme]
theme = PyDotOrg
  • Reiniciamos apache:
/etc/init.d/apache2 restart

Y ya contamos con un nuevo tema instalado.

Instalando un plugin de Trac

Para instalar un plugin de trac por la vía de la descarga, primero, ubicamos y descargamos la fuente;

  • Descargamos, el plugin de Mercurial
svn co http://svn.edgewall.com/repos/trac/plugins/0.12/mercurial-plugin
  • Nos movemos a la carpeta:
    cd mercurial-plugin
  • Ejecutamos la instalación del plugin:
python setup.py install
  • Y luego incorporamos dicho plugin al ‘conf/trac.ini’
[components]
tracext.hg.backend.*
  • Nota: podremos saber el nombre del componente a agregar en el archivo “setup.py > packages”.

Algunos plugins solicitarán actualizar (upgrade) de la instancia, para ello:

  • Ejecutamos en una cónsola:
trac-admin /srv/proyectos/documentacion upgrade
  • Y reiniciamos apache:
    /etc/init.d/apache2 restart

Configuración de repositorios

La configuración de repositorios (directorios donde se almacena código fuente versionado gracias a un VCS) depende de cada software de VCS utilizado, por defecto Trac gestiona Subversion, pero puede habilitarse para otros VCS.

Subversion

  • Instalamos subversion
aptitude install subversion libapache2-svn
  • Creamos la carpeta para el proyecto que deseamos versionar:
mkdir /srv/repositorio/proyecto-svn
  • Creamos el ambiente del proyecto SVN:
svnadmin create /srv/repositorio/proyecto-svn
  • Y le damos privilegio a apache para leerlo:
chown www-data.www-data /srv/repositorio -R
  • Entramos en el environment del trac:
trac-admin /srv/proyectos/documentacion
  • Agregamos el repositorio:
repository add proyecto-svn /srv/repositorio/proyecto-svn svn
  • nota: la sintaxis es: repository add {nombre} {ruta} {tipo}
  • Y ejecutamos la sincronización:
Trac> repository resync proyecto-svn 

Resyncing repository history for proyecto-svn ... 
0 revisions cached. 
Done.
  • Podemos ejecutar la resincronización de todos los repositorios existentes ejecutando:
repository resync '*'

Mercurial (Hg)

  • Instalamos el soporte a mercurial en nuestra distribución:
aptitude install mercurial
  • Descargamos el plugin
svn co http://svn.edgewall.com/repos/trac/plugins/0.12/mercurial-plugin
  • E instalamos el plugin de mercurial:
    cd mercurial-plugin
    python setup.py install
  • Configuramos el plugin de mercurial (hg) en el trac.ini
[components]
tracext.hg.backend.*
  • agregamos la configuración del plugin mercurial
    [hg]
    # -- Show revision number in addition to the changeset hash (defaults to yes)
    show_rev = yes
    # -- Changeset hash format
    node_format = short
  • Reiniciamos el environment de trac y apache:
trac-admin /srv/proyectos/documentacion upgrade && /etc/init.d/apache2 restart

Y ya tenemos configurado el soporte para Mercurial en Trac, ahora procedemos a agregar un repositorio:

  • Para agregar un repositorio Hg (Mercurial) creamos:
mkdir /srv/repositorio/hg/gnu
  • Nos movemos al directorio:
cd /srv/repositorio/hg/gnu/
  • Iniciamos Mercurial en la carpeta
    hg init
  • Y actualizamos:
    hg update
    0 files updated, 0 files merged, 0 files removed, 0 files unresolved
  • Entramos en el environment del trac:
trac-admin /srv/proyectos/documentacion
  • Agregamos el repositorio:
>repository add gnu-hg /srv/repositorio/hg/gnu hg
  • Y ejecutamos la re-sincronización:
    Trac [/srv/proyectos/documentacion]> repository resync gnu-hg
    Resyncing repository history for gnu... 
    0 revisions cached.
    Done.

GIT

Configurando Git

  • Instalamos lo necesario para git:
    aptitude install git git-core git-daemon-run
  • instalamos el plugin de GIT
    easy_install http://github.com/hvr/trac-git-plugin/tarball/master
  • Reiniciamos apache:
    /etc/init.d/apache2 restart
  • Agregamos la sección GIT al trac.ini
    [git]
    cached_repository = false
    persistent_cache = false
    shortrev_len = 7
    wiki_shortrev_len = 7
    git_bin = /usr/bin/git
    trac_user_rlookup = true
    use_committer_id = false
    use_committer_time = false
  • Y habilitamos el plugin (trac.ini)
    [components]
    tracext.git.* = enabled
  • Tambien agregamos la posibilidad de tener GIT post-commit hooks:
    [components]
    tracopt.ticket.commit_updater.committicketreferencemacro = enabled
    tracopt.ticket.commit_updater.committicketupdater = enabled
  • Y cambiamos esto (en el trac.ini):
    repository_sync_per_request = (default)

    — por esto:

    repository_sync_per_request =

Ya configurado GIT, creamos un repositorio.

Creación de un repositorio GIT

  • Creamos la carpeta:
mkdir /srv/repositorios/lyx-book
  • La convertimos en un repositorio git vacio:
    git --bare init
  • Nota: el directorio debe ser de tipo “bare”, ya que Trac debe tener acceso a los archivos de control (HEAD y config) de GIT y no solo el directorio .git/
  • Incorporamos los archivos necesarios, ejecutamos su adhesión al GIT:
    git add .
  • Ejecutamos el primer commit del repositorio:
    git commit -a -m 'first commit'
  • Verificamos su estado:
    git status
    # On branch master
    nothing to commit (working directory clean)
  • Cargamos la consola de la instancia:
    trac-admin /srv/proyectos/documentacion
    
    Welcome to trac-admin 0.12.2
    Interactive Trac administration console.
    Copyright (C) 2003-2011 Edgewall Software
    
    Type:  '?' or 'help' for help on commands.
    
    Trac [/srv/proyectos/documentacion]>
  • Incorporamos el repositorio:
repository add lyx-book /srv/repositorio/lyx-book git
  • Ejecutamos la sincronización:
    repository resync lyx-book

Conclusiones

Trac es una excelente herramienta  de SCM (Source Code Management) ya que combina Wiki, Gestión de incidencias (ticket, bug-tracking), gestión de código VCS y se le pueden incorporar plugins de terceros que incluyen desde un foro hasta un blog.

Xen 4 y Debian: corrigiendo algunos detalles

Instalar Xen 4.x en Debian GNU/Linux es bastante sencillo (el metapaquete xen-linux-system), ahora bien, configurar para hacer funcionar otras cosas es otra tarea distinta; por ejemplo, encontrarán que 6 cosas no  funcionan “a la primera” en Debian y deberá corregirlas para disfrutar al máximo de Xen 4.x:

1.- Habilitando XenAPI y accediendo con virt-manager

Virt-manager es la herramienta gráfica para libvirt (librería para acceso a servicios de virtualización, integra KVM, Qemu, Xen, LXC, openVZ y hasta VMWare) diseñada por la gente de Red Hat y que raya en lo infantil por su facilidad de uso para gestionar sistemas virtualizados, sin embargo, notaremos que luego de instalarlo, no podremos acceder a nuestro sistema Xen.

Para acceder con virt-manager (luego de instalado virt-manager y libvirt-bin) es activar el acceso por la API de Xen:

Editamos:

archivo: /etc/xen/xend-config.sxp

Y habilitamos http-server (en el puerto 8000, es el que usa libvirt), descomentamos (y ponemos en “yes”):

(xend-http-server yes)

Nota: si desean acceder desde cualquier equipo con libvirt (y no solo desde localhost), agregan esta línea:

(xend-address ”)

Posteriormente, debemos agregar al usuario con el que vamos a acceder al dominio Xen al grupo libvirt (ojo: esto como medida de seguridad para no acceder con el usuario root):

adduser jesuslara libvirt

E instalamos los paquetes necesarios para virt-manager y para que este nos interrogue por nuestra contraseña:

aptitude install virt-goodies ssh-askpass ssh-askpass-gnome

Listo!, ya podremos conectarnos a nuestro Xen vía un tunel remoto SSH (accedemos a “Archivo > Nueva Conexión  y seleccionamos Xen y modo “Tunel SSh Remoto”), usando nuestro usuario y nuestra contraseña.

2.- Creando VMs, configurando virt-manager

Una cosa que debemos configurar antes de empezar a crear máquinas con virt-manager, es indicarle en qué forma creamos los discos de las máquinas virtuales, esto se hace en el menú “Detalles” de la conexión al servidor Xen:

En esta ventana hay una pestaña que dice “almacenamiento”, donde podrán indicar si se crean volúmenes LVM, archivos de imagen en disco, etc

He creado 3 tipos de almacenamiento, un grupo de volúmenes LVM (para las máquinas virtuales), un espacio en disco (en /srv/xen) para aquellas máquinas que crearé usando archivos .img (imágenes qcow exportables) y una carpeta especial, donde he copiado los ISO de todos los sistemas operativos que utilizaré, así los podré usar rápidamente cada vez que quiera crear una nueva VM.

Ya con esto (Y la red), podrán crear máquinas virtuales.

3.- Creando VMs con HVM (virtualización completa) en virt-manager

Cuando intentan crear una VM HVM (que requiera virtualización completa, ejemplo, un Windows) con virt-manager, este emitirá un error de que no encuentra qemu-dm, esto es debido a que Xen utiliza una forma modificada de KVM y el ejecutable (aunque instalado, se llama “xen-qemu-dm-4.0”) no se encuentra en el lugar que espera virt-manager, esto se resuelve fácilmente con un enlace simbólico:

ln -s /usr/lib64/xen-4.0 /usr/lib64/xen

Y listo!, ya pueden crear máquinas usando HVM, fijense en este equipo freeBSD:

4.- virt-manager y “xm new” no funciona

“xm create” es la forma “usual” como creamos VMs en Xen, sin embargo, esto tiene un inconveniente, la VM es “creada” cada vez que se inicia y “destruida” (léase mejor, retirada de la lista de dominios administrados) del gestor de dominios Xen cada vez que se apaga, debido a esto, la VM no puede ser gestionada vía la XenAPI o vía gestores externos basados en libvirt (como virt-manager).

Este es un error heredado de Xen 3.x, cuando ejecutamos “xm new” aparece el siguiente error:

xm new -f test.cfg

Unexpected error: <type ‘exceptions.ImportError’>
Please report to xen-devel@lists.xensource.com
Traceback (most recent call last):
File “/usr/lib/xen-4.0/bin/xm”, line 8, in <module>
main.main(sys.argv)
File “/usr/lib/xen-4.0/lib/python/xen/xm/main.py”, line 3620, in main
_, rc = _run_cmd(cmd, cmd_name, args)
File “/usr/lib/xen-4.0/lib/python/xen/xm/main.py”, line 3644, in _run_cmd
return True, cmd(args)
File “<string>”, line 1, in <lambda>
File “/usr/lib/xen-4.0/lib/python/xen/xm/main.py”, line 1449, in xm_importcommand
cmd = __import__(command, globals(), locals(), ‘xen.xm’)
File “/usr/lib/xen-4.0/lib/python/xen/xm/new.py”, line 26, in <module>
from xen.xm.xenapi_create import *
File “/usr/lib/xen-4.0/lib/python/xen/xm/xenapi_create.py”, line 22, in <module>
from xml.parsers.xmlproc import xmlproc, xmlval, xmldtd
ImportError: No module named xmlproc

Esto es debido a la ausencia del módulo xmlproc de python, sin embargo, cuando intentamos instalarlo ocurre esto:

apt-get install python-xml
Leyendo lista de paquetes… Hecho
Creando árbol de dependencias
Leyendo la información de estado… Hecho
El paquete python-xml no está disponible, pero algún otro paquete hace referencia
a él. Esto puede significar que el paquete falta, está obsoleto o sólo se
encuentra disponible desde alguna otra fuente
E: El paquete «python-xml» no tiene un candidato para la instalación

El paquete ya no existe (porque fué reemplazado por python-lxml) y porque xmlproc ya no está en esa librería, sin embargo, como XMLproc es utilizado simplemente para validar el DTD de los archivos XML generados por xenAPI (y eso no es un “error fatal” que afecte la creación de la VM administrada) entonces;  para hacerlo funcionar, simplemente abrimos el archivo:

archivo : /usr/lib/xen-4.0/lib/python/xen/xm/xenapi_create.py

Y editamos la línea 22, comentándola:

#from xml.parsers.xmlproc import xmlproc, xmlval, xmldtd

Cuando ejecutamos:

xm new -f test.cfg 
Using config file "./test.cfg".

Ahora veremos que la VM test está incorporada al administrador Xen permanentemente (permitiendo ser gestionada por la API vía xenapi o vía libvirt):

xm list
Name        ID  Mem    VCPUs    State Time(s)
Domain-0    0   2752   2        r----- 90.2
freebsd         512    1               0.0
test            256    1               0.0
winxp           1250   2               1358.4

Nótese que las VMs gestionadas por XenAPI no tienen ID si están apagadas, para encenderlas indicamos:

xm start test

Y veremos que la VM “test” se inicia, incluso podemos gestionarla vía libvirt (ej: virt-manager):

Nota: ¿y cómo editamos un domU administrado?, si contamos con el archivo cfg, entonces simplemente eliminamos el dominio:

xm delete test

Y lo volvemos a incorporar con xm new.

Si no contamos con el archivo cfg (porque tal vez lo creó otra herramienta) entonces debemos editar el dominio en “/var/lib/xend/domains/”, recuerde, sin embargo, que este archivo tiene la forma “SXP” (un parser a XML hecho en perl para sablotron, que permite persistencia de objetos en un pseudo-lenguaje de marcado), como esta:

(domain
(domid 3)
(vcpus_params ((cap 0) (weight 256)))
(PV_args ‘root=/dev/xvda2 ro ip=:127.0.255.255::::eth0:dhcp ‘)
(PV_bootloader )
(cpus (()))
(memory_sharing 0)
(superpages 0)
(VCPUs_live 1)
(actions_after_crash restart)
(uuid 6257207b-6831-ddcd-a21d-010a5fb77070)
(PV_ramdisk /boot/initrd.img-3.2.0-0.bpo.2-amd64)

5.- Mi VM Windows es lenta, ¿cómo hago?

Una de las razones por las cuáles la gente usa VMWare, es qué, como toda herramienta privativa, accede a información confidencial a la cual no acceden empresas dedicadas al software libre, esto es, VMWare “inyecta” drivers Windows WHQL para que el acceso a red, disco y video de la máquina virtual sea más rápido, sin embargo, desde 2011 eso es posible en Xen también!, ya que un joven hizo “ingeniería inversa” de los drivers Microsoft Windows para Hyper-V y existe una versión “libre” de los drivers para Windows, se llaman los Xen PV Drivers y al instalarlos en la VM con Windows, modificarán el acceso al “disco virtual” y a la “red virtual” de manera notable.

Para instalarlo, descargue la versión necesaria para la versión de Windows que instaló acá:

http://www.meadowcourt.org/downloads/

Antes de instalar, la tarjeta de red se ejecuta a 100Mbps, el acceso a disco en modo “IDE” y la tarjeta de video era cirrus;

Instale a la VM Windows, verá al instalar:

 

5.- Quiero cambiar de CDROM en virt-manager

Una de las cosas más frustrantes que te puedes encontrar, es que si intentas cambiar el CDROM (expulsar->desconectar en virt-manager) este te pedirá que reinicies la VM, esto debido a que el CDROM es tratado como “un disco más”, sin embargo, es posible cambiar de CDROM en una VM encendida; para ello:

1.- Expulsamos el CDROM en el sistema operativo

2.- Cambiamos a la cónsola de virt-manager (CTRL+ALT+2 en la ventana de la máquina virtual)

3.- Expulsamos (desconectamos) el CDROM en Virt-manager:

(qemu) eject hdc

4.- Montamos el nuevo disco, si es una imagen ISO, escribimos:

(qemu) change hdc /path/to/file.iso

Si es un CD en una unidad de CD-ROM, la ruta física a la unidad

(qemu) change hdc /dev/sr0

5.- Volvemos al sistema operativo y montamos la unidad de CDROM

Conclusiones

Espero que estos trucos les sirvan, a mí me han salvado un mundo en trabajo con virtualización Xen y como siempre, los publico acá por si alguien más los necesita.

Happy Hacking!

[Samba] Incorporando estaciones Windows 7 a un dominio Samba

Esta pregunta me la hizo el gran amigo @echevemaster y con gusto la publicaré para todos aquéllos que tengan la misma intriga ¿cómo hago para meter estaciones de trabajo con Windows 7 en un dominio con Samba 3.x? …

Acá la simple respuesta, no sin antes, la explicación.

Windows 7: Modo de compatibilidad: 0

Windows 7 viene por defecto con un modo de compatibilidad que le impide incorporarse a dominios (tanto Windows como Samba) previos a 2003, de tal manera que es IMPOSIBLE incorporarlo a un dominio construido sobre Samba 3.x

¿Cómo se corrige?

Para corregirlo, simplemente debemos agregar unas líneas del registro que modifican el comportamiento de la estación de trabajo ante un dominio Samba:

archivo: win7.reg

Windows Registry Editor Version 5.00
 
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\LanmanWorkstation\Parameters]
“DomainCompatibilityMode”=dword:00000001
“DNSNameResolutionRequired”=dword:00000000
 
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa]
“LmCompatibilityLevel”=dword:00000001
 
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\Netlogon\Parameters]
“Update”=”no”
“DisablePasswordChange”=dword:00000000
“MaximumPasswordAge”=dword:0000001e
“RequireSignOrSeal”=dword:00000001
“RequireStrongKey”=dword:00000001
“SealSecureChannel”=dword:00000001
“SignSecureChannel”=dword:00000001

Este archivo deberá ejecutarse con privilegios de administrador (local o de dominio) en cada estación de trabajo Windows 7 y listo!, al reiniciar (no fuera windows) podrán incorporar la estación de trabajo al dominio Samba.

¿Y si estoy migrando desde Active Directory, cómo lo puedo hacer más rápido?

Si te da pereza pasear por las estaciones, o estas son muchas, y cuentas con la posibilidad de ejecutar un script de inicio de sesión en la estación Windows 7, agrega la siguiente línea al script para que la línea se ejecute cuando inicies como un administrador del dominio:

set __COMPAT_LAYER=RunAsInvoker
start regedit.exe \\directorio\netlogon\win7.reg /s

De esta manera, se ejecuta el script de netlogon en todas las estaciones y así podrás incorporarlas al nuevo dominio Samba después.

¿Y puedo migrar aún más rápido?

Si, si cuentas con OCS Inventory en la red local, podrías crear un paquete que ingrese las líneas en el registro de Windows 7 y posteriormente ejecute algún script para cambiarla automáticamente de dominio, a todas las estaciones de una sola vez; pero eso, ya es tarea para otro artículo! …

Happy Hacking!

[mini-howto] Cómo compartir Internet en GNU/Linux o por fin tengo Internet en Guanare!

Preámbulo

Vivir en una ciudad pequeña de los llanos occidentales como Guanare tiene muchas ventajas, es calmada, al ser pequeña se pueden hacer muchas cosas el mismo día, etc.
Uno de los inconvenientes del conjunto residencial hecho a las afueras de la ciudad, es que aunque tiene más de 5 años de construído, no hay “ni esperanzas” de que haya líneas telefónicas y la cobertura de la telefonía celular es realmente patética, para navegar en Internet tenía que ir “al pueblo” a buscar un cybercafé.

Hace algún tiempo había ideado la posibilidad de adquirir un modem con antena GSM para amplificar la señal y tener una conectividad “más decente” en mi apartamento, de estas experiencias, nace este post.

La conectividad

Luego de probadas las velocidades de las 3 principales operadoras (Movilnet, Movistar y Digitel), y comparado con el hecho que Movilnet suele tener demasiadas desconexiones aún con una señal decente y Digitel solamente conecta en EDGE, nos quedamos con Movistar, que por suerte mía, tengo una línea con plan ilimitado (de las primeras que ofertaron!).

Mi conectividad 3G con movistar en Guanare!

Antena

He adquirido una antena con conector TS9, de 2.5dbi de ganancia (próximamente compraré una de más ganancia) que me permite tener una señal medianamente aceptable en un lugar donde antes no había señal.

Antena 6 bandas 2.5Dbi

Modem 4G

He comprado un modem 4G Sierra USB Connect (AT&T, pero lo liberé, aunque puede adquirirse liberado) y luego de unas pruebas de velocidad, la más decente era una Movistar, que en algunos puntos podía tener 3 rayas UMTS.

Nota: para quien tenga más “dólares” puede adquirir el Momentum 4G de sierra Wireless que es mucho más potente.

Modem USB openConnect Sierra

El Servidor

El equipo que estoy usando como Servidor es un Lemote Fuloong Mini, con su CPU ICT Loongson-2 (arquitectura MIPSEL) y sus 80Gb en disco, es más que suficiente para ejecutar una combinación de actividades:

* Firewall y compartir Internet
* Squid3 como caché de contenido y Filtro
* DNSmasq como caché de DNS y reglas de ads blocking (bloqueo de anuncios)

He instalado Debian Wheezy (según guía adjunta: https://phenobarbital.wordpress.com/2011/07/13/instalar-gnulinux-debian-wheezy-en-una-lemote-fuloong/) en el equipo, una instalación estándar, para luego proceder a instalar el resto de paquetes.

Nota: hay un beneficio adicional de usar este equipo y es su extremadamente bajo consumo de energía, además de que es muy silencioso (está en mi cuarto y ni lo escucho encendido) por lo que es ideal para este tipo de servicios.

Conectando a Internet

Para conectar a Internet he instalado pppconfig:

aptitude install pppconfig

Luego, configuro una conexión para Movistar con los siguientes valores:
– número de llamada: *99#
– Modo de autenticación: CHAP
– Puerto: /dev/ttyUSB2

Para el chatscript, hay que modificarlo de la siguiente manera:

archivo: /etc/chatscripts/movistar

# This chatfile was generated by pppconfig 2.3.18.
# Please do not delete any of the comments. Pppconfig needs them.
#
# ispauth CHAP
# abortstring
ABORT BUSY ABORT 'NO CARRIER' ABORT VOICE ABORT 'NO DIALTONE' ABORT 'NO DIAL TONE' ABORT 'NO ANSWER' ABORT DELAYED
# modeminit
'' ATZ
# pasar el pin de la conexion (si tiene)
#'' ATZ+CPIN="0000"
OK "ATQ0 V1 E1 S0=0 &C1 &D2 +FCLASS=0"
OK 'AT+CGDCONT=1,"IP","internet.movistar.ve"'
# ispnumber
OK-AT-OK "ATDT*99#"
# ispconnect
CONNECT \d\c
# prelogin
# ispname
# isppassword
# postlogin
# end of pppconfig stuff

Esta línea es importante:

OK ‘AT+CGDCONT=1,”IP”,”internet.movistar.ve“‘

Esta representa el APN de tu carrier (en mi caso Movistar).

Para conectarnos, simplemente ejecuto:

$pon movistar

Y la conexión se realiza.

(Nota: ejecutar “$poff movistar” para cerrar la conexión).

Un script para conectar a Internet

Como la electricidad acá fluctua demasiado (al igual que el agua y otros servicios xD), hice un simple script que conecta a Internet y ejecuta las reglas de firewall para dejar el sistema completamente listo.

archivo: /usr/local/bin/conectar_internet.sh

#!/bin/bash
/usr/bin/pon movistar
sleep 5
/usr/local/bin/firewall.sh apply

Y este script lo llamo en la opción UP de la interfaz eth0 (la que está conectada a mi Access Point inalámbrico y a mi red local):

archivo: /etc/network/interfaces

allow-hotplug eth0
iface eth0 inet static
 address 192.168.1.1
 network 192.168.1.0
 netmask 255.255.255.0
 broadcast 192.168.1.255
 up /usr/local/bin/conectar_internet.sh

Esto me permite saber que las reglas de firewall, la redirección al proxy Squid y la conexión UMTS estarán activas cuando se encienda la interfaz eth0.

Nota: podría dedicarme más tiempo a por ejemplo, hacer “tunning” de parámetros del kernel en sysctl para mejorar el performance de la conectividad IPv4, etc, pero eso sería un próximo artículo.

Ya estamos conectados!, ahora viene el Squid y el DNSmasq.

Un sencillo ping-alive

La conexión por falta de actividad a veces se cae, entonces, hice un sencillo ping-alive que ejecuta un ping regularmente y cada 30 minutos a una lista de hosts pre-definidos.

* Creamos el script:

archivo: /usr/local/bin/ping_alive

#!/bin/bash
HOSTS="google.co.ve ftp.us.debian.org"
COUNT=4
for myHost in $HOSTS
do
 count=$(ping -w $COUNT -c $COUNT $myHost | grep 'received' | awk -F',' '{ print $2 }' | awk '{ print $1 }')
 if [ $count -eq 0 ]; then
 # 100% failed
 echo "Host : $myHost is down (ping failed) at $(date)"
 fi
done

* Lo convertimos en ejecutable:

chmod +x /usr/local/bin/ping_alive

* En orden para ejecutar cada 30 minutos, lo agregamos a crontab:

crontab -e

* Y agregamos:

# Monitorizar cada 30 minutos
30 * * * * /usr/local/bin/ping_alive

Y listo!, esto hará ping y chequeará si hay conexión cada 30 minutos.

Squid3

Squid es un software de proxy de contenido, content-filtering y caché para servicios web, ¿por qué montaría un squid en una red local?, la conexión por lo general es lenta, sobre todo en el día (con los miles de blackberrys de mis vecinos enviando pines para Canadá), y como mi esposa por lo general usa el Internet para visitar sus sitios web favoritos (pinterest, facebook, twitter, flickr, tumblr) entonces tener un servidor Squid es una gran ventaja.

Para instalar:

aptitude install squid3

Y he utilizado este archivo de configuración:

Anexo: Archivo squid.conf

Es común, no tuneado, salvo por los siguientes cambios:

  • Proxy transparente
  • he denegado vía URL_REGEX muchas direcciones a sitios web de estadísticas o banners
  • He incorporado varias reglas de refresh_pattern para conservar ancho de banda de diversos tipos de archivos comunes en Internet

Reiniciamos el squid y ya simplemente debemos aplicar el firewall

Capitulo extra: Firewall

Aplico un firewall sencillo, ya le tengo cariño a este script (lleva conmigo mucho tiempo, son suscesivas modificaciones a un script original hecho por mi amiga Nerissa Aguilera) y pues cumple su función (bloquear algunas cosas, compartir el Internet y re-dirigir todo al Proxy).

Anexo: archivo firewall.sh

El firewall tiene 3 opciones: apply (aplicar), clean (limpiar) y test (probar si será posible aplicar este script), ejemplo:

/usr/local/bin/firewall.sh apply

Aplica las reglas iptables.

DNS masq (DNS Caché)

Para mejorar la resolución DNS, colocaremos un servidor DNS que permite proveer DNS cache a la red local.

* instalar:

aptitude install dnsmasq

* editamos /etc/default/dnsmasq para definir ENABLED=1

# Whether or not to run the dnsmasq daemon; set to 0 to disable.
ENABLED=1

* Agregamos un archivo de configuración para nuestra red en /etc/dnsmasq.d y editamos este archivo:

archivo: /etc/dnsmasq.d/intranet.conf

# listen address:
listen-address=192.168.1.1
# Never forward plain names (without a dot or domain part)
domain-needed
# Never forward addresses in the non-routed address spaces.
bogus-priv

Nota: agreguen “log-queries” durante las pruebas para verificar la correcta resolución de direcciones.

* Editamos el /etc/resolv.conf para agregar DNS con una resolución más rápida que el de nuestros ISP:

# google
nameserver 8.8.8.8
# opendns
nameserver 208.67.222.222
# ISP
nameserver 200.35.65.5
nameserver 200.35.65.4

Nota: el Firewall ya aplica los DNS personalizados.

* Y reiniciamos el dnsmasq:

/etc/init.d/dnsmasq restart

Recordemos además modificar DNSmasq para utilizarlo como DHCP que nos permita entregar como puerta de enlace (gateway) este equipo.

Con el DHCP, DNS, Squid3 y todo configurado, ya ponemos a funcionar todo y feliz conexión!.

Extra: Bloquear anuncios (advertisements) con DNS masq

¿Saben qué es fastidioso?, saber que teniendo un ancho de banda extremadamente limitado,  que haya páginas full de publicidad y anuncios (cual vallas de carretera) que se coman mi preciado ancho de banda descargando banners Flash y textos que son inútiles para mí.

Para ello utilizaremos un proyecto de la gente de yoyo.org, que llevan una lista de sitios conocidos de publicidad y marketing, al indicarle a dnsmasq que responda con una URL nula estas solicitudes, nuestras páginas web se verán limpias de contenido.

* Necesitamos crear un archivo, que nos permitirá crear la lista de bloqueo:

archivo: /usr/local/bin/get-ad-block-list.sh

#!/bin/sh
# Down the DNSmasq formatted ad block list
curl "http://pgl.yoyo.org/adservers/serverlist.php?hostformat=dnsmasq&showintro=0&mimetype=plaintext" | sed "s/127\.0\.0\.1/192.168.1.1/" > /etc/dnsmasq.d/adblock.conf

* Y lo volvemos ejecutable:

chmod 755 /usr/local/bin/get-ad-block-list.sh

* Agregamos un cron-job que lo ejecute semanalmente:

ln -s /usr/local/bin/get-ad-block-list.sh /etc/cron.weekly/get-ad-block-list

* Y Lo ejecutamos por primera vez (para descargar la lista):

root@fuloong:~# /usr/local/bin/get-ad-block-list.sh
 % Total % Received % Xferd Average Speed Time Time Time Current
 Dload Upload Total Spent Left Speed
100 98305 0 98305 0 0 1364 0 --:--:-- 0:01:12 --:--:-- 10236

El archivo queda más o menos así:

address=/101com.com/192.168.1.1
address=/101order.com/192.168.1.1
address=/103bees.com/192.168.1.1
address=/1100i.com/192.168.1.1
address=/123banners.com/192.168.1.1
address=/123found.com/192.168.1.1
address=/123pagerank.com/192.168.1.1
… 

Esto indica, que para cualquier solicitud de un dominio en ESA lista  (/etc/dnsmasq.d/adblock.conf) entonces DNSMASQ responderá con un servidor local (en 192.168.1.1). ¿y qué servidor web responderá esa solicitud?, ahí entra el pixelserver.

* Creación de un pixelserver:

Un pixelserver es un super-minimo web-server, su única finalidad es servir un gif de 1×1 transparente (sólo mide 43 bytes), este servidor responderá toda solicitud HTTP con un pixel.

* descargamos:

wget http://proxytunnel.sourceforge.net/files/pixelserv.pl.txt -O /usr/local/bin/pixelserv.pl

* hacemos ejecutable:

chmod 755 /usr/local/bin/pixelserv.pl

* Incorporamos un script de init.d para pixelserv (compatible con Debian)

archivo: /etc/init.d/pixelserv

#!/bin/sh
## BEGIN INIT INFO
# Provides: pixelserv
# Required-Start: $network
# Required-Stop: $network
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: minimal Web Server
### END INIT INFO
set -e
. /lib/lsb/init-functions
case "$1" in
 start)
 echo "Starting pixelserv "
 /usr/local/bin/pixelserv.pl &
 ;;
 stop)
 echo "Stopping script pixelserv"
 killall pixelserv.pl
 ;;
 *)
 echo "Usage: /etc/init.d/pixelserv {start|stop}"
 exit 1
 ;;
esac
exit 0

* Y le indicamos a Debian que lo ejecute en cada inicio:

update-rc.d pixelserv defaults

* Como la lista de ad-block está incorporada al dnsmasq en:

archivo: /etc/dnsmasq.d/adblock.conf

* Entonces reiniciamos el dnsmasq:

/etc/init.d/dnsmasq restart

Verificamos que cualquier solicitud de un Dominio en esa lista, responde adblock:

dig @192.168.1.1 doubleclick.com
;; QUESTION SECTION:
;doubleclick.com. IN A
;; ANSWER SECTION:
doubleclick.com. 0 IN A 192.168.1.1

* Ya se puede navegar por cualquier página web y desaparecerán los anuncios (ejemplo: youtube.com)

Conclusiones

Este caso mio es un frikismo puro, ganas de tener un Internet decente en mi casa, un lugar cualquiera de Venezuela olvidado por el centralismo, pero es muy útil para aquellos centros, educativos, culturales, indígenas y de cualquier índole, que deseen una comunicación decente con el mundo a través de Internet; como conclusión puedo indicar que mis costos fueron supremamente bajos (los equipos para conectividad comprados por ebay usando dólares electrónicos no superaron los 150US$) y para cualquier persona que desee conectividad en una finca, granja y/o poblado rural, una solución así, compacta, segura, barata y en software libre puede ser de gran beneficio.

¿Trucos para personas más diestras?, podrían plantearse un trunking de conexiones, conectando dos o más conexiones GSM (o de diversos tipos) para balancear el Internet y hacer que vaya mucho más rápido, podría comprar una antena de 12Db y 5Dbi de ganancia externa y conectar toda la solución en exteriores en una caja Nema con muy pequeños equipos (beagleboards o raspberry-pi corriendo una mini-distribución sobre un disco SSD), la capacidad de crear “pequeñas cajas con Internet” para comunidades remotas crea ilimitadas posibilidades.

¿Qué otras cosas se les ocurrirán a mis lectores?

¡Happy Hacking!

Seguir

Recibe cada nueva publicación en tu buzón de correo electrónico.

Únete a otros 3.600 seguidores

A %d blogueros les gusta esto: