Prepara tu casa para la cyberguerra

cyberwar

Hoy vamos a actualizar la red de casa o pequeña oficina estrenando placa y de paso tirando algo de cable de red de por medio.

Para ello usaremos Opnsense, fork del famoso Pfsense, distro basada en FreeBSD con fines de cortafuegos y enrutador.

La placa SBC (Single Board Computer) o alternativa a Raspberry con “muchos esteroides”, es una Odroid modelo H2+, basada en la arquitectura X86 (nos viene genial para montar servicios en docker próximamente). Tiene múltiples puntos fuertes esta placa, pero en concreto lo que más nos puede resultar útil, para este proyecto en cuestión, es que cuenta con dos interfaces de red 2.5 Gigabit. (Lo que la hacen perfecta para hacer de router).

Imagen de Odroid H2+

Primero procederemos a montar la placa, es muy delicada en cuanto a hardware compatible, al no incluir ni memoria RAM ni disco integrado tendremos que ir buscando que tipos de tarjetas RAM o que discos son compatibles y cuales no.

En mi caso únicamente monto una memoria Ram de 4GB ( donada por Ale, GRACIAS de nuevo) y el sistema correrá en un pendrive USB3*. (Al no detectar los viejos discos SATA que tengo… seguiré investigando).

*Lo ideal sería correr el sistema en una memoria eMMC ya que la velocidad aumentaría considerablemente.

Procedemos a descargar la imagen de Opnsense y comprobar su checksum.

Luego montamos la imagen en el pendrive con dd

sudo dd if=opnsense-version.img of=/dev/rutadetupendrive

Luego aprovechamos y formateamos otro pendrive USB que tengamos libre en formato FAT32, para cargarle los drivers de las interfaces de red Realtek RTL8125B, ya que no vienen incluidos en la version 12 de FreeBSD.

El binario de los drivers los he encontrado en la siguiente web, de un proyecto similar y procedemos a instalarlos una vez la instalación haya concluido.

Nos logueamos como root y la pass Opnsense y pulsamos 8 + Enter para acceder a la consola FreeBSD.

Montamos el segundo pendrive USB que contiene los drivers Realtek de los puertos Ethernet.

mkdir /mnt/usbstick
mount -t msdosfs /dev/da0s1 /mnt/usbstick

Copiamos el driver y cambiamos los permisos del archivo.

cd /boot/kernel
cp /mnt/usbstick/if_re.ko ./
chown root:wheel if_re.ko
chmod 0555 if_re.ko

Para cargar el módulo al arranque debemos añadir la siguiente línea al archivo /boot/loader.conf

vi /boot/loader.conf
add line --> if_re_load=“YES”

Si no estas familiarizad@ con vi:

i→ Modo de inserción de texto

Esc→ Salir del modo de inserción de texto

:wq→ Guardar fichero y salir

:q!→ Salir sin guardar.

El driver debería de estar cargado al reiniciar.

Lo comprobamos con el comando kldstat, o ifconfig,

Deberían aparecer las dos redes re0 y re1. Opnsense asigna la interfaz re0 a la red LAN y la interfaz re1 a la red WAN.

Por defecto el puerto WAN tendra cliente dhcp y espera a ser asignada una ip.

Por defecto el puerto LAN tiene un servidor dhcp y una dirección estática de 192.168.1.1 donde podremos visualizar la interfaz de Opnsense por web https.

La Lan tendría la ip estática de 192.168.1.1 y gateway de 192.168.2.2. A su vez actuaría como servidor DHCP y DNS.En el modem del proveedor procedemos a cambiar la ip a 192.168.2.1 y añadir como estática la 192.168.2.2 con la MAC del puerto WAN de la placa Odroid H2+, deshabilitamos servidor DHCP al igual que las interfaces Wifi y añadimos la dirección ip 192.168.2.2 como DMZ (zona desmilitarizada).

Una vez comprobado que todo funciona con normalidad en nuestro caso procedemos a conectar la interfaz LAN a un switch gigabit de 8 puertos que distribuya la red. Posteriormente procedemos a conectar los routers a este switch, asignamos ip estática del opnsense con cada router con su ip y dirección Mac, desactivando el servidor DHCP en la interfaz LAN de cada router Openwrt.

Todo muy casero .

Luego podemos cacharrear a nuestro gusto , como jugando con las prioridades del tráfico o la prevención de instrusos con la integración de snort y sus reglas.

Aquí priorizamos parte del tráfico.
IDS Reglas por defecto.

Y bueno a partir de ahi ir añadiendo routers secundarios como Puntos de Acceso Wifi, por ejemplo, con sistemas OpenWRT para tener control total sobre la red.

Diagrama de red hecho con draw.io

El Swarm (enjambre) de Docker

dockerswarm

En esta entrada vamos a introducir la funcionalidad Swarm que soporta el motor (engine) de Docker, esto nos permitirá desplegar contenedores en varias máquinas añadiendo una infraestructura clúster entre ellas, y así poder utilizar y compartir los recursos de varias máquinas con Docker como si fuera una única instancia.

La gestión de red y algunos recursos es transparente para el usuario, el Swarm se encarga de orquestar la comunicación entre contenedores, también se publican los puertos compartidos de los contenedores por defecto en todos los nodos, por lo que no tendremos de que preocuparnos, da la posibilidad de escalar servicios fácilmente y distribuirlos entre los nodos, etc.

Iniciar el Swarm

En el Swarm de Docker existen dos tipos de nodos, los manager y los worker, siendo el manager el que delega las tareas a los workers y no al revés, el manager también forma parte del Swarm. En un entorno en producción se recomienda tener mínimo unos tres managers para soportar la tolerancia a fallos.

Se inicia el swarm en el manager con el siguiente comando

$ docker swarm init

Para añadir un manager al Swarm se ejecuta el siguiente comando, hay que seguir las instrucciones en el nodo correspondiente

$ docker swarm join-token manager

Para añadir un worker se ejecuta y seguir las instrucciones

$ docker swarm join-token worker

Una vez añadidos los nodos podremos visualizarlos desde el manager ejecutando

$ docker node ls

Desplegar servicios

Para desplegar (deploy) servicios en el Swarm usaremos docker-compose y la configuración correspondiente que está disponible a partir de la versión 3, configuramos un servicio:

version: '3'

services:
  servicio:
    image: imagen_del_servicio
    deploy:
      mode: replicated
      replicas: 1
      restart_policy:
        condition: on-failure
      placement:
        constraints: [node.hostname==nodehostname]
    volumes:
      - ssh-entrypoint:/entrypoint:ro
    networks:
      netservice:

networks:
  netservice:

volumes:
  ssh-entrypoint:
    driver: vieux/sshfs
    driver_opts:
      sshcmd: user@host:/remote_shared_folder
      password: secret
      port: 2222
      sftp_server: "/usr/bin/sudo /usr/lib/openssh/sftp-server"
      allow_other: ""

Ejecutamos el stack que vamos a desplegar en el Swarm

$ docker stack up --with-registry-auth -c docker-compose.yml nombre_del_servicio

La opción –with-registry-auth se utiliza por si usamos imágenes de un registro de Docker propio, el Swarm buscará la imagen a desplegar en los registros que estemos conectados en los nodos y la bajará en cada uno de ellos. Pueden mezclarse arquitecturas para tener un conjunto de imágenes multiarch jugando con el manifest del repositorio, pero esa opción es todavía experimental.

Hemos creado el volumen compartido por sshfs con el driver vieux/sshfs para varias arquitecturas, por lo que cada nodo se conectará a la carpeta /remote_shared_folder del host que indiquemos con la correspondiente configuración por sshfs.

En el apartado node.hostname se indica una máquina concreta para desplegar el servicio, si se omite esta opción se replicará en la que elija el Swarm

Gestión del Swarm

Una vez desplegado el servicio puede verse ejecutando

$ docker service ls

Y si queremos ver uno en concreto

$ docker service ps nombre_del_servicio

Para ver logs de un servicio se ejecuta

$ docker service logs -f nombre_del_servicio

Eliminar un servicio ejecutando

$ docker stack rm nombre_del_servicio

Y eliminar un nodo del Swarm

$ docker node rm nodo_a_eliminar

Por último comentar que podemos usar otras herramientas para gestionar el Swarm como es Portainer, aunque existen otras muchas nos facilita información gráficamente del clúster.

Portainer

Esto es todo por el momento, volveremos pronto con Kubernetes (k8s), saludos

Instalar brave (navegador) en Arch.

brave

Hola!, Buenos días! Teniendo siempre en cuenta mi compromiso de compartir todo aquello que pueda ahorra tiempo a quienes inician en el multiverso GNU/Linux, compartiré unos cortos pasos para instalar el negador web Brave; obviamente en Arch linux.

Antes de nada… ¿Qué es brave?

Brave es un navegador web de código abierto basado en Chromium, creado por la compañía Brave Software en el año 2016, fundada por el cofundador del Proyecto Mozilla y creador de JavaScript, Brendan Eich. by Wikipedia

Creo inmensamente que por algo se debe empezar y al momento de usar internet el navegador es una de esas herramientas que si o si debes usar , por eso he decidido darle una oportunidad. Antes he estado usando firefox sin problemas y como todo entusiasta siempre estoy probando nuevas herramientas, creando posibilidades de uso, indagando sobre lo que funciona mejor, eso no hace dueños de lo que usamos.

Instalando…

Lo que me gusta hacer a mi, es ir a la pagina https://aur.archlinux.org/ aquí siempre encuentro todo lo que necesito, aunque… podría usar pacman pero me gusta ir a la fija y el proceso no es complicado.

La anterior url nos dirige hacia el repositorio comunitario de arch.

Como lo señalo en la imagen anterior, solo debemos escribir el nombre del paquete que necesitamos en el campo Package search.

Los resultados para brave son varios. Basta con usar como referente para escoger el paquete los item Votes y Popularity, el mejor calificado por la comunidad sera el ganador, en esta caso lo señale con la linea roja. Damos click en el nombre y nos enviará a su pagina de detalles, ahí encontraremos mucha mas información y la url del código fuente para clonar y “compilar”.

Copiamos (click derecho, copiar URL) el Git Clone URL para usarlo en nuestra terminal.

Usaremos la sentencia git clone mas la dirección del repo que copiamos anteriormente para clonar de manera local, algo así:

$ git clone https://aur.archlinux.org/brave-bin.git

Una vez se tiene descargado el código fuente pasaremos a compilar ubicándonos dentro de la carpeta del repositorio git que acabamos de clonar, generalmente tiene el nombre del proyecto.

Yo siempre tengo una carpeta en mi home a la que llamo Aur dentro de esta carpeta mantengo todos los repositorios que he clonado para así ir actualizando con un git pull.

Como muestra la imagen con el comando pwd veo la ruta completa en la que estoy, recuerden que estando en la terminal pueden usar cd mas el nombre del directorio para entrar a el por decirlo de alguna manera y con ls ver las subcarpetas. Solo nos faltaría ejecutar makepkg -sir, ingresar la contraseña en el caso de que la solicite y listo tendremos instalado brave.

Me gusta hacerlo así pues me siento como un juaker jajajajajajajaja, un saludo y abrazo a todos!

El placer de hacer y compartir.

DNSCrypt y anonimiza tus datos

dnscrypt

Hola, hoy os vamos a comentar en esta entrada como montar vuestro propio cliente DNSCrypt, que nos servirá para anonimizar los datos de resolución de dominio que van por nuestra conexión, esto pondrá un poco más difícil la parametrización que hacen los gobiernos y grandes corporaciones con nuestra información.

¿Qué es DNSCrypt?

DNSCrypt crea un túnel cifrado entre el servidor y el cliente, y resuelve las peticiones DNS que realiza. Evita la suplantación de identidad y utiliza firmas criptográficas para verificar que las respuestas se originan en el sistema y que no hayan sido manipuladas.

Es una especificación abierta, con implementación libre, y que no está afiliada a ninguna empresa u organización.

Usar DNSCrypt

Necesitamos tener instalado el programa dnscrypt-proxy para conectar a un servidor.

$ apt install dnscrypt-proxy

Configuramos el programa para que escuche en el puerto 53 de localhost (127.0.0.1) y se conecte al servidor DNSCrypt de HatThieves.

listen_addresses = ['127.0.0.1:53']
server_names = ['hatthieves', 'hatthieves6']

[static.'hatthieves']
  stamp = 'sdns://AQUAAAAAAAAAETgyLjIyMy4zLjEzNTo1NDQzICIJ3we16VXeoGdYSnOd3QYm2h5ZQCUmjS_GNx-JOELOHTIuZG5zY3J5cHQtY2VydC5oYXR0aGlldmVzLmVz'
[static.'hatthieves6']
  stamp = 'sdns://AQUAAAAAAAAAHFsyMDAxOmJhMDoxODAwOjgwZTA6OjFdOjU0NDMgIgnfB7XpVd6gZ1hKc53dBibaHllAJSaNL8Y3H4k4Qs4dMi5kbnNjcnlwdC1jZXJ0LmhhdHRoaWV2ZXMuZXM'

Una vez conectado podremos configurar nuestro sistema para que utilice el puerto local.

$ echo 'nameserver 127.0.0.1' > /etc/resolv.conf

Y todas las peticiones del sistema pasarán a través de nuestro servidor que resuelve directamente a los servidores raíz de internet, usamos DNSSEC y no guardamos registros como puede verse en nuestra instancia. También se pueden usar los servidores públicos oficiales.

Un saludo, estad seguros y nos vemos en la próxima entrada.

Libera tu voz con Grumble

grumble

Hola, como ya sabéis, con todo lo que está sucediendo referente a la pandemia está cambiando el estilo de vida. Se tiende a utilizar servicios telemáticos tanto para trabajar, si es posible hacerlo, como en todos los ámbitos: compras, formación, reuniones familiares, etc.

Esta tendencia obliga al usuario a utilizar plataformas “gratuitas” de empresas que se quedan con nuestra voz y datos (ya sabes que cuando algo es gratis el producto eres tú). Por eso queremos hacer hincapié en que los usuarios utilicen servicios gestionados por ellos mismos y alejarse lo máximo posible de dar beneficios a estas empresas que han ganado popularidad con la pandemia y se quedan con los datos (el petróleo del siglo XXI).

Grumble

Si conocéis el famoso programa de chat de voz Mumble, su hermano se llama Grumble. Éste es la implementación en lenguaje Go de Mumble y está en desarrollo. Vamos a instalarlo en una Raspberry Pi ya que no necesita consumir muchos recursos y podremos tenerlo en un servidor casero sin mucho esfuerzo. Utilizaremos Docker para desplegarlo porque es más cómodo, limpio y sus programadores nos han facilitado un Dockerfile en su repositorio.

Creamos una carpeta y clonamos el repositorio:

$ git clone https://github.com/mumble-voip/grumble

En la misma carpeta creamos un archivo docker-compose.yml con el siguiente contenido:

version: '2'

services:
  grumble:
    build: ./grumble
    container_name: grumble
    hostname: grumble
    restart: always
#    volumes:
#      - ./data:/data
    ports:
      - 64738:64738
      - 64738:64738/udp
    networks:
      grumblenet:

networks:
  grumblenet:

Con el volumen comentado, construimos la imagen y levantamos el contenedor. Seguidamente copiamos la carpeta /data en la carpeta local para compartir el volumen:

$ docker-compose up -d
Building grumble
Step 1/14 : FROM golang:1.14-alpine as builder
1.14-alpine: Pulling from library/golang
...
$ docker cp grumble:/data .

Y finalmente lo descomentamos todo, lo paramos y volvemos a crear el contenedor:

$ docker-compose down && docker-compose up -d

Ya podemos conectarnos con nuestro cliente favorito a nuestro Grumble como lo haríamos con Mumble, esperamos que os sea de ayuda y os animéis a montarlo para ser dueños de vuestra propia voz cifrada. Nos leemos en la próxima entrada.

TensorFlow 2.0 y redes neuronales

tf_logo

Buenas, hoy vamos a explicar un poco en esta entrada como funciona el framework que nos ofrece herramientas para programar tareas de aprendizaje automático, crear redes neuronales, deeplearning, deep reinforcement learning, etc. En definitiva lo que suelen denominarse hoy inteligencias artificiales, se llama TensorFlow y va por la versión 2.3

TensorFlow es el sistema de aprendizaje automático de segunda generación de Google Brain, liberado como software libre en noviembre de 2015. El nombre TensorFlow deriva de las operaciones que tales redes neuronales realizan sobre arrays multidimensionales de datos. Estos arrays multidimensionales son llamados tensores

Unidad de procesamiento del tensor (TPU)

En mayo de 2016 Google anunció su unidad de procesamiento del tensor (TPU), una construcción ASIC personalizada específicamente para aprendizaje automático y adaptada para TensorFlow. TPU es un acelerador de IA programable diseñado para proporcionar alta eficiencia aritmética de precisión baja, y orientado a utilizar modelos más que para entrenarlos

TensorFlow

La API de TensorFlow está disponible en varios lenguajes, nosotros usaremos la de NodeJS para el ejemplo de red neuronal artificial que construiremos con el conjunto de datos MNIST

// Cargamos los módulos necesarios
const tfnode = require('@tensorflow/tfjs-node-gpu'),
    fs = require('fs'),
    zlib = require('zlib');

(async () => {
// Leemos el conjunto de datos (dataset) y preparamos los datos para la entrada
    const features = (new Uint8Array(zlib.gunzipSync(fs.readFileSync(__dirname + '/mnist/train-images-idx3-ubyte.gz')))).slice(16),
        labels = (new Uint8Array(zlib.gunzipSync(fs.readFileSync(__dirname + '/mnist/train-labels-idx1-ubyte.gz')))).slice(8),
        featuresTest = (new Uint8Array(zlib.gunzipSync(fs.readFileSync(__dirname + '/mnist/t10k-images-idx3-ubyte.gz')))).slice(16),
        labelsTest = (new Uint8Array(zlib.gunzipSync(fs.readFileSync(__dirname + '/mnist/t10k-labels-idx1-ubyte.gz')))).slice(8),
        feats = tfnode.data.array((new Float32Array(features)).map(f => f / 255.0)).batch(784),
        lbls = tfnode.data.array(labels).batch(1),
        featTests = tfnode.data.array((new Float32Array(featuresTest)).map(f => f / 255.0)).batch(784),
        lblTests = tfnode.data.array(labelsTest).batch(1)
// Instanciación del modelo
    const model = tfnode.sequential()
// Se añaden las capas de la red neuronal
    model.add(tfnode.layers.dense({ units: 128, activation: 'relu', inputShape: [784] }))
    model.add(tfnode.layers.dropout(0.2))
    model.add(tfnode.layers.dense({ units: 10, activation: 'softmax' }))
// Compilación del modelo
    model.compile({ optimizer: 'adam', loss: 'sparseCategoricalCrossentropy', metrics: ['acc'] })
    model.summary()
    console.log(`Training dataset with ${feats.size} features and ${lbls.size} labels...`)
// Fase de entrenamiento del modelo
    const dataTrain = tfnode.data.zip({ xs: feats, ys: lbls }).batch(1),
        testTrain = tfnode.data.zip({ xs: featTests, ys: lblTests }).batch(1),
        history = await model.fitDataset(dataTrain, {
            epochs: 5,
            validationData: testTrain,
            callbacks: {
                onTrainBegin: logs => console.log('Start Training...'),
                onTrainEnd: logs => console.log('Stop Training'),
                onEpochBegin: (epoch, logs) => console.log('Begin epoch: ' + epoch),
                onEpochEnd: (epoch, logs) => console.log('End epoch: ' + epoch + '\n- Loss: ' + logs.loss + '\n- Accuracy: ' + logs.acc)
            }
        }).catch(err => console.error(err))
// Se muestran los valores de salida
    Object.keys(history.history).map(key => console.log(`${key}=${history.history[key]}`))
})()

Necesitamos instalar las dependencias del módulo @tensorflow/tfjs-node-gpu para que funcione, o el módulo @tensorflow/tfjs-node en caso de no usar GPU

En el ejemplo anterior estamos leyendo el dataset y creando una red neuronal artificial con 128 neuronas, la capa de dropout permite desactivar un porcentaje de las neuronas durante el entrenamiento en nuestro caso el 20%, esto es necesario para no tener resultados por sobreentrenamiento. Finalmente tenemos 10 unidades en la capa de salida por lo que el resultado será un tensor de 10 elementos que indica la probabilidad de que la imagen sea correcta. Hacemos 5 pasadas de entrenamiento y validamos los resultados

La salida por lo tanto muestra el resumen del modelo y el entrenamiento, dando los valores de pérdida y acierto en cada entrenamiento y al final el total

_________________________________________________________________
Layer (type)                 Output shape              Param #   
=================================================================
dense_Dense1 (Dense)         [null,128]                100480    
_________________________________________________________________
dropout_Dropout1 (Dropout)   [null,128]                0         
_________________________________________________________________
dense_Dense2 (Dense)         [null,10]                 1290      
=================================================================
Total params: 101770
Trainable params: 101770
Non-trainable params: 0
_________________________________________________________________
Training dataset with 60000 features and 60000 labels...
Start Training...
Epoch 1 / 5
Begin epoch: 0
eta=863.4 ==>-------------------------------- acc=1.00 loss=0.102 

Una vez entrenado el modelo podremos pasarle imágenes para detectar la coincidencia en la probabilidad de los resultados

// Adaptamos las imágenes a la entrada del modelo y se crea el tensor de entrada
    fs.createReadStream('/images.json.gz').pipe(zlib.createGunzip()).on('data', async data => {
        const imagen = Float32Array.from(await sharp(Buffer.from(data.image, 'base64')).resize(28, 28).greyscale().raw().toBuffer().catch(err => next(err))),
            buffer = tfnode.buffer([1, 784], 'float32', imagen.map(f => f / 255.0))
        model.predict(buffer.toTensor()).print()
    })
        .on('end', () => {
            console.log('All images predicted.')
        })

Tensor
     [[0, 0, 0, 0, 0, 0.0427372, 0, 0.9571278, 0, 0.0001349],]
Tensor
     [[0.0002897, 0, 0.209211, 0.0000031, 0, 0.0015369, 0.7871032, 0.001465, 0.0003912, 0],]
Tensor
     [[0.0000626, 0, 0.4744948, 0.0397445, 0, 0.0002614, 0, 0.4854368, 0, 0],]
Tensor
     [[0.0000023, 0, 0.0093701, 0.1584364, 0, 0.3968244, 0.0428764, 0.3924459, 0.0000444, 2e-7],]
Tensor
     [[0.0000071, 0, 0.0316687, 0.0000178, 0, 0.0000988, 0.9680935, 0.0001098, 0.0000045, 0],]
...

Esperamos que os haya gustado, nos leemos en la próxima haciendo redes neuronales de convolución 🤖

Me quedo en Arch linux…

Primero que nada pedir disculpa por no escribir con frecuencia, la verdad la falta de tiempo por el incremento de las actividades relacionadas con mi trabajo no dejan tiempo para escribir con tranquilidad… aquí estoy, así que continuemos…

Con el titulo de hoy quiero expresar lo cómodo que me siento en Arch linux pero también las razones que en su momento me hicieron dejarlo. Hace ya varios años que lo había probado y lo que mas llamó mi atención fue la posibilidad de compilar desde el código fuente solo utilizando el pkgbuild que muchas veces se encuentra disponible en los repos de la comunidad AUR, pero por otro lado lo que a mi parecer es una decisión que discrimina al usuario amateur es lo tedioso del proceso de instalación y configuración para poner el sistema a punto, Ahora, si bien el lema es “mantelo simple estúpido” la pregunta es: ¿simple para quien? Para ellos? o para los usuarios? esto lo resalto pues es la mosca en la sopa.

El proceso de instalación es complejo para quienes vienen de la paradoja de la ventana y a eso le sumamos la necesidad de tener claro ciertos conceptos que para muchos usuarios son cosas de hackers, al parecer no soy el único que piensa así, al punto que hay entusiastas de nivel PRO que están del lado de los mas nuevos y enfocaron sus esfuerzos en ofrecer alternativas que mantienen la motivación que se requiere para montar al ÑU; una de ellas es ArcoLinux.

Imagen de la pagína oficial de ArcoLinux https://arcolinux.info/

ArcoLinux notoriamente es un arch con un asistente y scripts para dejar todo bien bonito reduciendo así la curva de aprendizaje inicial y alimentando el deseo de saber mas, que a mi parecer es lo que se debe hacer. Y si, es cierto, necesitamos saber que sucede detrás de cámaras, esa es de las ventajas mas prominentes del ecosistemas del software libre; la oportunidad de poder rebuscar en el código y la increíble posibilidad de tropezar tantos conceptos hacen de los usuarios de GNU/Linux expertos que controlan cada aspecto del software que usan, pero ¡por DIOS! Transferir toda esa información de la memoria de corto plazo a la de largo plazo toma tiempo, osea que la primera impresión no tiene segunda oportunidad, es mi opinión. Entonces pensando en lo anterior el arch+vitamina ofrece también varias rutas de instalación que propulsan y desmenuza los concepto para no tragar entero ¡ufff ! ¿era difícil hacer eso? Quizás si, quizás no, ¿quien soy yo para juzgar? Simplemente doy mi punto de vista.

Resumiendo…

Las ventajas que yo veo: (esto es aparte de lo que ofrece ser usuario de GNU/Linux)

1. Compilar desde el código con los scripts alojados en el repositorio AUR.

2. Instalar solo lo necesario (hay distribuciones que bien con software que creo nunca usé)

3. Los paquetes al ser compilados en tu hardware (algunos no todos) quedan optimizados.

4. La compatibilidad y la enorme disponibilidad de paquetes que hay en los repositorios.

5. Solidez y seriedad

6. Documentación actualizada.

7. Comunidad muy activa

8. compatibilidad

9. Paquetes siempre actualizados.

Lo que no me gusta:

1. La rudimentaria forma de instalar el sistema operativo.

En lo antes mencionados creo que muchas ventajas hacen parte de las opciones GNU/Linux disponibles, pero es que… en Arch he disfrutado a plenitud de ellas.

Ahora…

Que pasaría si lo quiero hacer por mi mismo? (personalizaciones y demás) y ademas deseo con todas mis fuerzas evadir el rudimentario proceso de instalación. Pues que entonces esos entusiastas de los que hable y estoy seguro que pensaron igual que yo, resolvieron el problema. ¿como lo resolvieron? Crearon anarchy installer.

Anarchy installer es la joya que faltaba a la corona Arch, simple como pregonan y amable con quienes empiezan a tropezar con asistentes de instalación apartados del típico “Siguiente”. La verdad no tengo mucho que decir aparte de lo que esta disponible en innumerables tutoriales e incluso en su propia pagina web, solo agregaré que puedes escoger desde entornos ya personalizados hasta apps muy conocidas como VLC. A continuación dejo la web para que hagan la tarea ¡no todo es papilla, hay que darle!

https://anarchyinstaller.org/

Bueno… queria compartir un poco solamente. Un saludo y abrazo a todos.

El placer de hacer y compartir!

Integración Continua: Gitea + Drone + SonarQube

¿Qué es y para que se usa la integración continua?

Es una práctica de ingeniería de software que consiste en hacer integraciones automáticas de un proyecto lo más a menudo posible para así poder detectar fallos cuanto antes. Entendemos por integración la compilación y ejecución de pruebas de todo un proyecto.

Gitea + Drone + SonarQube

Se utiliza el software libre de Gitea para almacenar los repositorios de código y que conectaremos a Drone para realizar la IC

Drone permite ejecutar las pipelines que tiene configuradas el repositorio, cuenta con mucha variedad de plugins dando posibilidad de despliegues o comunicaciones

SonarQube provee de métricas y analiza la calidad y seguridad del código

Con este stack podremos montar un ciclo de IC que cubre las necesidades básicas, también destaca los pocos recursos que necesita esta configuración pudiendo desplegarse en máquinas pequeñas como una Raspberry

Docker

Usamos Docker para desplegar las aplicaciones en distintos contenedores

version: '2'

services:
  gitea:
    image: gitea/gitea
    restart: always
    container_name: gitea
    hostname: gitea
    volumes:
      - ./data:/data
    expose:
      - 3000
    depends_on:
      - db
    networks:
      mynet:

  db:
    image: mariadb:10
    container_name: gitea-db
    hostname: gitea-db
    restart: always
    environment:
      - MYSQL_ROOT_PASSWORD=secretdb
      - MYSQL_DATABASE=gitea
      - MYSQL_USER=gitea
      - MYSQL_PASSWORD=secretpass
    volumes:
      - ./db/:/var/lib/mysql
    networks:
      mynet:

  drone:
    image: drone/drone
    restart: always
    container_name: drone
    hostname: drone
    environment:
      - DRONE_GITEA_SERVER=https://gitea.domain.com
      - DRONE_GITEA_CLIENT_ID=secretid
      - DRONE_GITEA_CLIENT_SECRET=secret
      - DRONE_RPC_SECRET=secret-rpc
      - DRONE_SERVER_HOST=drone.domain.com
      - DRONE_SERVER_PROTO=https
    volumes:
      - ./drone:/data
    expose:
      - 80
    networks:
      mynet:

  runner:
    image: drone/drone-runner-docker
    restart: always
    container_name: runner
    hostname: runner
    environment:
      - DRONE_RPC_PROTO=http
      - DRONE_RPC_HOST=drone
      - DRONE_RPC_SECRET=secret-rpc
      - DRONE_RUNNER_CAPACITY=2
      - DRONE_RUNNER_NAME=runner
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    expose:
      - 3000
    networks:
      mynet:

  sonarqube:
    image: sonarqube
    container_name: sonarqube
    hostname: sonarqube
    expose:
      - 9000
    volumes:
      - ./sonar/conf:/opt/sonarqube/conf
      - ./sonar/data:/opt/sonarqube/data
      - ./sonar/logs:/opt/sonarqube/logs
      - ./sonar/extensions:/opt/sonarqube/extensions
    networks:
      mynet:

networks:
  mynet:

Solo hay que crear la app en Gitea para conectarla a Drone y generar las claves de la configuración del runner de Drone. También habría que generar la token del plugin de sonar para cada proyecto de Drone que configuremos

Con esta receta de docker-compose se puede poner un proxy que ataque los distintos contenedores bajo el mismo dominio.com

Eso es todo, nos vemos en la próxima

Dockerizando una Raspberry Pi 4

En esta entrada vamos a instalar y preparar un ordenador Raspberry Pi 4 con la distribución Buster Debian GNU/Linux y arquitectura arm64 (aarch64) aprovechando al máximo el procesador que lleva de serie

Necesitamos la imagen de RaspiOS oficial con el software arm64 instalado, también necesitaremos una tarjeta microSD para grabarla, esto podemos hacerlo con un solo comando desde un terminal

$ curl -s https://downloads.raspberrypi.org/raspios_arm64/images/raspios_arm64-2020-05-28/2020-05-27-raspios-buster-arm64.zip | gzip -d - | sudo dd if=/dev/stdin of=/dev/sdX status=progress

Donde el dispositivo /dev/sdX será el de la memoria microSD

Una vez termina el comando tendremos la imagen grabada en la tarjeta, la conectamos a la Raspberry Pi 4 y arrancará el sistema por defecto

Abrimos un terminal desde la Raspberry y ejecutamos los siguientes comandos

$ echo 'deb https://download.docker.com/linux/debian buster stable' | sudo tee /etc/apt/sources.list.d/docker.list
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
$ sudo apt update
$ sudo apt install -y docker-ce

Cuando termine de instalar se necesita reiniciar el sistema para que todo funcione correctamente, y ya tenemos docker en nuestro ordenador arm64

$ docker -v
Docker version 19.03.12, build 48a6621

Kernel Version: 5.4.51-v8+
Operating System: Debian GNU/Linux 10 (buster)
OSType: linux
Architecture: aarch64
CPUs: 4
Total Memory: 7.633GiB
Name: raspberrypi

Hasta la próxima…