Servidor VPN en Raspberry Pi

Un uso muy clásico de usar una raspberry es configurarla como VPN, prácticamente cualquier modelo da un rendimiento aceptable, siempre y cuando sea para uso personal y no requiera una gran transferencia de datos, en este caso se va a dar un ejemplo con una Raspberry Pi Model B, una de las primeras que salió al mercado que tiene solo 256MB (sí, con M) de RAM y una tarjeta SD (sí, no es micro) de 8GB.

Primero como siempre actualizar el sistema, en este caso como la fundación Raspberry son muy retrocompatibles (algo que no se agradece lo suficiente) vamos a usar la última distribución disponible Bookworm.

Se recomienda esta optimización.

NoIP

Primero vamos a crear un DNS dinámico de esta forma aunque nuestra dirección IP pública cambie siempre podremos alcanzar al servidor VPN si nos estamos conectando desde el exterior, hay varios proveedores y en este caso vamos a usar NoIP.

Lo primero será crear una cuenta, gratuitamente se dan hasta 3 dominios, cada mes hay que confirmar que estamos usando el servicio, poca molestia por el servicio gratuito.

Después de crear una cuenta tendremos que usar el cliente NoIP este cliente sirve para actualizar dinámicamente la dirección IP con el servidor NoIP, esto es necesario porque si el ISP cambia la IP del router NoIP no lo sabrá a menos que se lo notifiquemos.

NoIP tiene una guia detallada de como instalar el cliente aquí.

En este caso vamos a usar la compilación manual por el simple hecho que en ciertas Raspberry podemos obtener el error Segmentation fault un equivalente al BSOD de Windows.

Las instrucciones para compilar desde fuente también se comentan en el propio documento, esta es una guía de ejemplo:

Vamos a crear una carpeta para almacenar el código y los binarios:

mkdir noip
cd noip

Ahora descargar los fuentes (revisar esta dirección si no descarga puede haber una versión nueva):

wget https://dmej8g5cpdyqd.cloudfront.net/downloads/noip-duc_3.1.0.tar.gz

Extraer los fuentes y posicionarnos en la carpeta:

tar xf noip-duc_3.1.0.tar.gz
cd noip-duc_3.1.0

Necesitamos Rust para poder compilar así que lo instalamos, la instalación dura un poco pero la compilación es muy muy larga, así que usamos screen para que no se pare:

Instalamos Rust primero:

curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

Se recomienda aumentar la memoria swap, al menos a 512MB, esto está explicado aquí, sino se corre el riesgo (altamente probable) de que la Raspberry se quede colgada en el último paso, también se recomienda configurar zswap.

Y ahora lanzamos la compilación, primero recargamos el shell como nos indica Rust y luego el comando propio de Rust para la compilación.

. "$HOME/.cargo/env"
cargo build --release

Ahora solo queda configurar el binario que tendremos en /target/release para que se inicie al arrancar, así que lo configuramos como un servicio usando systemd.

Primero copiamos el binario que tenemos en /target/release a la carpeta /usr/bin

sudo cp target/release/noip-duc /usr/bin/

Ahora creamos un fichero en /etc/default/

sudo nano /etc/default/noip-duc

Vamos a añadir en este fichero la configuración, -la configuración completa está en la ayuda-, estamos usando el usuario y grupo de pi para arrancar el servicio por comodidad (que no seguridad).

NOIP_USERNAME=Raspberry
NOIP_PASSWORD=drN01p
NOIP_DAEMON_USER=pi
NOIP_DAEMON_GROUP=pi
NOIP_DAEMON_PID_FILE=/var/run/noip.pid
NOIP_HOSTNAMES=uno.ddns.net,dos.ddns.net

El parámetro NOIP_HOSTNAMES puede ser tanto una lista de hosts como un grupo que se puede crear para actualizar todos los hosts en bloque, la creación de un grupo se hace desde el portal de noip.

Ahora creamos un fichero noip.service in /etc/systemd/system:

sudo nano /etc/systemd/system/noip.service

y vamos a poner lo siguiente (el contenido también está en la carpeta debian):

[Unit]
Description=No-IP Dynamic Update Client
After=network.target auditd.service

[Service]
EnvironmentFile=/etc/default/noip-duc
ExecStart=/usr/bin/noip-duc
Restart=on-failure
Type=simple

[Install]
WantedBy=multi-user.target

Ahora recargamos los servicios:

sudo systemctl daemon-reload

Ahora vamos a hacer que el servicio se inicie al arrancar:

sudo systemctl enable noip.service

Finalmente vamos a arrancarlo manualmente a ver si funciona todo bien.

sudo systemctl start noip.service

Y si queremos saber el estado en el que está usamos:

sudo systemctl status noip.service

PiVPN

Vamos a usar PiVPN como herramienta software para la instalación, bastante sencilla de usar, primero la instalación:

curl -L https://install.pivpn.io | bash

Aparecerá un instalador que hará algunas preguntas:

PiVPN Automated Installer es un mensaje informativo, OK para continuar.

Static IP Needed otro mensaje informativo, OK para continuar.

IPv6 leak elegimos OK, es para que el cliente use el tunel y evitar que su dirección IPv6 se filtre a los servidores, esto no implica que hay que realizar ninguna configuración adicional relacionada con IPv6.

DHCP Reservation para usar la dirección IP del servidor DHCP que tengamos en la red, es verdad que esto es poco habitual, generalmente los servidores suelen tener una IP estática, así que indicamos No.

Static IP Address: si ya tenemos una IP asignada por un servidor DHCP podemos usar la que indica sino pulsamos No y en la siguiente pantalla IPv4 address indicamos la IP y máscara de red, después en la pantalla IPv4 gateway (router) indicamos la IP del router.

Local Users es un mensaje informativo, OK para continuar.

Choose A User sirve para indicar que usuario ejecutará el servicio, el usuario por defecto pi es una buena opción, lo normal es que en un servidor VPN no existan cuentas de usuario.

Installation Mode (1) seleccionamos OpenVPN, la siguiente opción marcamos No para poder usar el protocolo UDP, más rápido en este caso.

Installation Mode (2) usamos UDP por defecto, que en este caso da mejor rendimiento. La opción custom search domain es para indicar si en las peticiones DNS del cliente hay que adjuntar este nombre de dominio, lo normal es que no sea el caso. Seleccionamos No en esta pantalla.

Default openvpn Port el puerto que usará OpenVPN, por defecto es el 1194 (¡UDP!) importante recordarlo para configurarlo en un firewall o router.

Confirm Custom Port Number la simple confirmación de que estamos de acuerdo con el número de puerto.

DNS Provider aquí podemos elegir uno externo como Google o CloudFare, o podemos usar el propio servidor PiVPN-is-local-DNS si también es servidor DNS (algo poco habitual y recomendable), con la opción Custom podemos elegir otro, esto lo veremos más adelante pero para una configuración estándar las dos primeras opciones son correctas.

Public IP or DNS aquí a no ser que tengamos una IP pública que no cambie (no suele ser así) elegiremos DNS Entry e indicaremos un nombre de dominio como el que hemos configurado anteriormente.

Confirm DNS Name simple confirmación que el nombre elegido es correcto.

Server information seleccionamos OK para poder generar la clave HMAC, necesaria para la autenticación TLS de OpenVPN.

Unattended Upgrades seleccionamos OK de esta forma OpenVPN se actualizará automáticamente con parches, seleccionamos Yes.

Installation Complete! si todo ha ido bien llegaremos aquí, presionamos OK para poder reiniciar y confirmamos el reinicio.

Después de este paso podemos actualizar la Raspberry y después reiniciar.

sudo apt-get -y update && sudo apt-get -y upgrade

Optimizaciones

A continuación algunas mejoras de rendimiento para una Raspberry Pi 1.

Deshabilitamos algunos servicios del arranque:

# Deshabilitamos el servicio de modem
sudo systemctl disable ModemManager.service
# Deshabilitamos el servicio Avahi
sudo systemctl disable avahi-daemon.service
# Deshabilitamos triggerhappy
sudo systemctl disable triggerhappy.service

Ajustamos el tamaño de los buffers de red en /etc/sysctl.conf añadimos estas líneas

net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
net.ipv4.tcp_rmem = 4096 87380 16777216
net.ipv4.tcp_wmem = 4096 87380 16777216
net.core.netdev_max_backlog = 2000

Y recargamos los parámetros con:

sudo sysctl -p

Ahora vamos a cambiar algunos valores de OpenVPN, para esto editamos el fichero /etc/openvpn/server.conf

#Bajamos el cifrado a 128 para reducir carga en CPU
cipher AES-128-CBC
#Optimizar TUN/TAP/UDP y escrituras I/O 
fast-io
#Cambiamos tamaño de buffer en cliente y servidor
sndbuf 524288
rcvbuf 524288
#Tamaño de la longitud de la cola, mismo valor que net.core.netdev_max_backlog
txqueuelen 2000

Crear clientes

Ahora solo queda crear los clientes, OpenVPN tiene aplicación cliente para prácticamente todos los sistemas, IOS, Android, Windows, Linux…. así que la opción preferida es crear una por dispositivo que vayamos a usar.

Para crear un cliente solamente tenemos que usar este comando:

pivpn add

Simplemente rellenamos las preguntas con nombre del certificado, contraseña y duración que tiene que estar entre 1 y 3650 días.

Por defecto el certificado lo creará en la carpeta /home/pi/ovpns lo recomendable es sacarlo de aquí y llevarlo al dispositivo destino usando el comando scp, por ejemplo:

scp pi@192.168.1.2:/home/pi/ovpns/client.ovpn .

Donde 192.168.128.1 es la ip del servidor y /home/pi/ovpns/client.ovpn es la ruta al certificado.

Si quisiéramos revocar un certificado, ya sea para que ese cliente no se pueda conectar o para cambiar la contraseña tendríamos que hacer.

pivpn -r client

Done client es el nombre del cliente que queremos revocar, es decir el mismo nombre que usamos al crearlo. Después de hacer esto solo tenemos que volver a crearlo usando pivpn add. Y si queremos saber que clientes están instalados podemos usar pivpn -l

Referencias

https://www.industrialshields.com/es_ES/blog/raspberry-pi-para-la-industria-26/configurar-un-servidor-vpn-en-una-raspberry-pi-566
https://linuxblog.io/improving-openvpn-performance-and-throughput

Servidor VPN en Raspberry Pi

Docker en Raspberry Pi

Actualizado el 27 de Junio de 2024

Introducción

Es posible usar Docker con Raspberry Pi, puede parecer que en un dispositivo de prestaciones limitadas no tenga mucho sentido pero cada vez es más común verlo para dispositivos IoT y los dispositivos Raspberry han mejorado mucho con el tiempo sobre todo a partir de Raspberry Pi 4.

Aquí coloco algunas notas de como configurar Docker y algunas posibles mejoras de rendimiento.

Preparando el sistema

Lo primero es actualizar el sistema y reiniciar.

sudo apt-get update
sudo apt-get upgrade

Instalando Docker

Instalamos Docker usando el script proporcionado por ellos.

curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh

Después agregamos al usuario pi al grupo docker haciendo:

 sudo usermod -aG docker pi

Una vez agregado si estamos con el usuario tendremos que volver a iniciar sesión o reiniciar para que los cambios de pertenencia al nuevo grupo se hagan efectivos.

Reiniciamos con sudo reboot now y verificamos la versión Docker con docker version.
Probamos también a verificar el sistema usando este comando que descargará una imagen Docker y la ejecutará, se verá un mensaje como Hello from Docker!

docker run --rm hello-world

Instalando Docker-Compose

Ahora instalamos Docker Compose que nos hará falta para gestionar varios contenedores a la vez y la comunicación entre ellos, primero instalamos pip, el gestor de paquetes de Python, cualquier distribución de Raspberry ya viene con Python instalado así que no hará falta instalarlo.

sudo curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py && sudo python3 get-pip.py

Si tenemos algún error podemos probar a ejecutar este comando y después volvemos a ejecutar el comando anterior para actualizar pip.

sudo apt-get install python3-pip

Es importante que en el fichero /etc/pip.conf tengamos agregado el repositorio de piwheels

[global]
extra-index-url=https://www.piwheels.org/simple

Es posible también que tengamos que instalar distutils

sudo apt-get install python3-distutils

Ahora instalamos Docker Compose

python3 -m pip install docker-compose

Si nos da este error: command ‘arm-linux-gnueabihf-gcc’ failed with exit status 1 podemos probar lo siguiente y repetir el comando anterior:

sudo apt-get install libzbar-dev libzbar0

Si nos da un error relacionado con python.h instalamos este paquete:

sudo apt-get install python3-dev

Si tenemos un error relacionado con ffi.h instalamos este paquete:

apt install libffi-dev

Finalmente para verificar que docker-compose se ha instalado bien se puede usar:

docker-compose --version

Rendimiento

Usando ZRAM

A veces puede suceder que zswap no nos de el resultado esperado, podemos probar en ese caso con zram, para eso seguimos estos pasos:

sudo wget -O /usr/bin/zram.sh https://raw.githubusercontent.com/Bash-Projects/rpi_zram/master/zram.sh

Damos permisos para ejecutar el script que nos acabamos de descargar:

sudo chmod +x /usr/bin/zram.sh

Ahora lo vamos a programar para que se ejecute 50 segundos después del arranque, así que lanzamos crontab.

sudo crontab -e

y programamos la ejecución del script:

@reboot ( sleep 50 ; sudo /usr/bin/zram.sh &)

El comando lo podemos lanzar directamente para ver el resultado o podemos reiniciar y esperar 50 segundos para ver el resultado, podemos verificar el aumento de memoria usando:

free -h

para ver como ha aumentado la RAM y para poder ver el aumento en la swap usamos:

swapon -s

Recomendaciones

Una serie de recomendaciones y problemas frecuentes.

Usar gosu en lugar de sudo

Las imágenes Docker normalmente se ejecutan como root pero a veces hace falta ejecutar algunos comandos como un usuario concreto dentro del entry point en este caso la mejor opción es usar gosu en lugar de sudo.

Problemas

Job for docker.service failed because the control process exited with error code.
See «systemctl status docker.service» and «journalctl -xe» for details.

Si el servicio da errores al arrancar podemos usar journalctl -xe y si vemos un error como The process’ exit code is ‘exited’ and its exit status is 2, podemos intentar lo siguiente:

rm -rf /var/lib/docker
sudo curl -sSL https://get.docker.com | sh
service docker restart

Es decir, borramos la carpeta, volvemos a instalar y reiniciamos el servicio, es posible que este error indique la tarjeta SD está fallando.

Errores al subir imágenes

Si al hacer push da un error como file integrity checksum failed for «usr/lib/arm-linux-gnueabihf/libicui18n.so.66.1» ejecutamos este comando:

docker system prune -a

Si aún así continuamos con el error no nos quedará otra que borrar la imagen y volverla a crear con docker build.

At least one invalid signature was encountered

Si durante la creación de imágenes obtenemos un error «At least one invalid signature was encountered» al instalar paquetes via apt-get es necesario instalar la versión actualizada de libseccomp2 la opción recomendada es descargar l paquete (en este caso via wget) e instalarlo desde aquí aquí.
Es posible que la versión del paquete haya cambiado y no se encuentre en el servidor, en ese caso se puede acceder a más mirrors aquí.

wget  http://ftp.us.debian.org/debian/pool/main/libs/libseccomp/libseccomp2_2.4.4-1+b1_armhf.deb
sudo apt-get install ./libseccomp2_2.4.4-1+b1_armhf.deb

E: Release file for xxx is not valid yet (invalid for another 2h 45min 28s). Updates for this repository will not be applied.

Esto es por un problema con la hora del sistema, posiblemente el sistema no tiene la hora correcta, recordar que Raspberry no incluye un reloj de hardware, se puede solucionar configurando la zona regional a través de raspi-config pero si eso no funciona una forma cómoda es instalando el cliente de ntp:

sudo apt-get install ntpdate

Después solo nos queda ejecutarlo indicando el servidor de tiempo que queramos usar:

sudo ntpdate time.windows.com
Docker en Raspberry Pi

Compilando Tensorflow 2 para Raspberry Pi

Actualizado el 31 de Octubre de 2020

Introducción

Raspberry instala por defecto TensorFlow 1.x, existen varias opciones para instalar TensorFlow 2, una de ellas es acceder a la página de TensorFlow y descargarse la versión 2 para Python 3.5, en la parte inferior veremos el enlace actualmente con esta dirección:

https://storage.googleapis.com/tensorflow/raspberrypi/tensorflow-2.3.0-cp35-none-linux_armv6l.whl
https://storage.googleapis.com/tensorflow/raspberrypi/tensorflow-2.3.0-cp35-none-linux_armv7l.whl

Ambos paquetes instalarán tensorflow 2.3 para una versión de Python 3.5 el primero para una Raspberry 0 o 1 (arquitectura ARMv6) y el segundo para una Raspberry 2 o 3 (ARMv7).

Puede ser que junto con TensorFlow 2 queramos usar una versión de Python superior (actualmente está disponible la 3.7) en ese caso la mejor opción será crear la versión desde el propio código fuente. Este proceso se puede realizar desde la propia Raspberry pero el proceso es bastante largo debido a las limitaciones de la Raspberry así que vamos a apoyarnos en otra máquina (escritorio, portátil,…) para agilizar el proceso y también tenerlo preparado para futuras versiones.

El proceso se puede realizar de varias formas, en este caso nos apoyaremos en Windows Linux Subsytem.

Windows Linux Subsystem

Lo primero será instalar Windows Linux Subsystem, siguiendo los pasos que se dan en la página se puede preparar Windows 10 para ejecutar Linux sin problemas. Vamos a elegir como distribución a instalar Ubuntu 20.04 LTS.

Una vez arrancado y creado un usuario Linux seguimos los siguientes pasos:

Descargar el código fuente

El código fuente de TensorFlow lo podemos descargar de su repositorio oficial, vamos a trabajar con las ramas release en concreto para este caso la 2.4 que es la última disponible:

git clone https://github.com/tensorflow/tensorflow.git
git checkout r2.4

Compilación del código

TensorFlow 2 se compila a través de Docker, si estamos usando Windows 10 podemos habilitar la integración con WSL, la información completa esta aquí, pero con los siguientes pasos podemos verificar rápidamente si todo está correcto.

  1. Dentro de Settings -> General
    Habilitar Use the WSL 2 based engine (habilitado por defecto). Apply & restart.
  2. Verificar que WSL se está ejecutando en modo 2, ejecutamos este comando en una línea de comandos (cmd): wsl -l -v
    Tenemos que ver que la versión es la 2.
  3. En Settings -> Resources -> WSL Integration habilitamos Enable integration with my default WSL distro y marcamos todas las imágenes en las que queramos habilitar WSL 2. Después Apply & restart.
    Sino vemos la opción de WSL Integration es que estamos ejecutando Docker con contenedores Windows, tenemos que usar contenedores Linux esta opción la tenemos en el menú contextual de Docker Switch to Linux containers.

Ahora nos movemos a la carpeta donde lanzaremos la compilación, que típicamente estará en tensorflow/tensorflow/tools/ci_build (hay dos carpetas tensorflow, la de descarga del código y otra propia del repositorio).

En este caso tenemos que cambiar un par de detalles en el archivo Dockerfile.pi-python37 tenemos que quitar las librerías de Python 2.7, esto hará que no sea compatible con Python 2.7 pero no es un problema ya que Python 2 está en desuso y además la compilación será más rápida, también asociaremos la versión de Python de la imagen Docker con la 3.7, normalmente se hace con update-alternatives pero en este caso lo vamos a simplificar modificando el enlace simbólico.

El siguiente código lo vamos a colocar justo después de la instalación de Python.

...
# The following line installs the Python 3.7 cross-compilation toolchain.
RUN /install/install_pi_python3x_toolchain.sh "3.7"

# Code to remove Python 2.7 and update symbolic link
RUN ln -sf /usr/bin/python3.7 /usr/bin/python
RUN apt-get remove -y libpython2.7-dev

RUN /install/install_bazel.sh
...

Ahora lanzamos este comando y comenzará la compilación, este comando (ci_build.sh) acepta dos parámetros.

  • El primero sirve para indicar en que maquina Docker se ejecutará (PI-PYTHON37), hay otros valores para compilar para otras máquinas Raspberry, si se quiere compilar para todas se puede usar el parámetro PI_ONE.
  • El segundo parámetro (build_raspberry_pi.sh) indica el comando que se ejecutará dentro de la máquina virtual.
./ci_build.sh PI-PYTHON37 \
    tensorflow/tools/ci_build/pi/build_raspberry_pi.sh

Durante la compilación nos irá sacando información del proceso, el tiempo que tarda depende de la máquina en particular, en este caso concreto en una máquina i7-6700K@4Ghz con 16GB RAM y en un disco SSD tarda alrededor de 30′-45′.

El resultado de la compilación lo tendréis en la carpeta tensorflow/output-artifacts y el paquete a instalar tendrá este nombre:
tensorflow-2.4.0rc0-cp37-none-linux_armv7l.whl

Vemos que hemos compilado una release candidate #0 de la versión 2.4 (2.4.0rc0) para una versión de Python 3.7 (cp37) y una arquitectura ARMv7 (armv7l) el none simplemente indica que no está compilado pensando en optimizaciones para GPU (Raspberry no soporta CUDA) o versiones especiales de Python (las versiones m).

Si tarda más de 60′ es posible que el proceso no termine, en ese caso la mejor opción es detener el proceso (Ctrl+Z) buscar el trabajo parado y coger el id (jobs -l) y matar el proceso (kill -9 #id).

Después de esto probamos a volver a lanzar el comando pero antes es muy recomendable reiniciar Docker, volver a abrir la máquina Ubuntu y hacer una limpieza de ficheros con git clean -fxd desde el raíz del repositorio.

Instalación

Ahora solo tenemos que copiar el fichero a la Raspberry, la forma más cómoda posiblemente sea usando el comando scp, por ejemplo:

scp tensorflow-2.4.0rc0-cp37-none-linux_armv7l.whl pi@192.168.1.5:/home/pi

En este ejemplo estamos copiando el fichero a una máquina remota 192.168.1.5 en la carpeta /home/pi y para acceder a esa máquina usamos el usuario pi, al conectar nos pedirá contraseña.

Una vez en la máquina Raspberry nos movemos a la carpeta donde hayamos copiado el fichero (/home/pi) primero vamos a actualizar pip, después actualizaremos setuptools y finalmente instalaremos el paquete TensorFlow 2:

sudo python3 -m pip install --upgrade pip
sudo pip3 install --upgrade setuptools
sudo pip3 install tensorflow-2.4.0rc0-cp37-none-linux_armv7l.whl

También hace falta tener instalado la librería ATLAS

sudo apt-get install libatlas-base-dev

La instalación tarda un poco pero nos irá información del proceso, al terminar para verificar que está bien instalado podemos usar:

sudo python3 -c 'import tensorflow as tf; print(tf.__version__)'

Y deberíamos ver…


2.4.0-rc0

Bonus

Es posible también coger paquetes precompilados desde varios orígenes de terceros y evitar tener que hacer este proceso, pero al no ser repositorios oficiales no se puede asegurar el funcionamiento del mismo.

Otra opción sería usar TensorFlow lite una versión más apropiada para dispositivos de menores prestaciones.

Problemas

Durante el desarrollo de este artículo me he encontrado varios problemas, los enumero aquí para la posteridad (muchos de ellos relacionados con la rama master).

Cannot add PPA: ‘ppa:~openjdk-r/ubuntu/ppa’.
ERROR: ‘~openjdk-r’ user or team does not exist.
Es un problema de certificados, ejecutamos:

sudo apt-get install --reinstall ca-certificates

wget: unable to resolve host address ‘xxx’
Es un problema con los DNS, se puede editar el fichero resolv.conf (sudo nano /etc/resolv.conf) y añadir la siguiente línea para configurar el DNS de Google.

nameserver 8.8.8.8

sudo: pip3: command not found
Hay que instalar el gestor de paquetes de Python pip, en este caso estamos obligados a modificar la imagen de TensorFlow, en el fichero DockerFile que corresponda (en este caso Dockerfile.pi-python37) añadimos esta línea encima de la línea que haya fallado, por ejemplo en este caso ha fallado la instalación del paquete auditwheel

...
RUN /install/install_buildifier.sh
RUN apt install -y python3-pip
RUN pip install --upgrade pip
RUN /install/install_auditwheel.sh
...

ERROR: An error occurred during the fetch of repository ‘local_config_python’:
…
Problem getting numpy include path.
…
ModuleNotFoundError: No module named ‘numpy’

Hay que hacer dos cosas, por un lado es un problema con la versión de Python, por defecto la versión de Python es la 3.5 cuando tendría que ser la 3.7 y además también hay que instalar numpy

Referencias

https://github.com/tensorflow/tensorflow/issues/26947
http://www.itworkman.com/97618.html
https://devblogs.microsoft.com/commandline/a-guide-to-invoking-wsl/
https://github.com/tensorflow/tensorflow/issues/39340

Compilando Tensorflow 2 para Raspberry Pi

USB externo en Raspberry Pi

Actualizado el 22 de Noviembre de 2020

Una forma rápida y sencilla de añadir un disco duro externo por USB y asociarlo a una carpeta, primero como siempre actualizar:

sudo apt-get update
sudo apt-get upgrade
sudo apt-get dist-upgrade

Antes de empezar tenemos que tener en cuenta que hay unidades USB con alimentación externa y otros sin ella, con alimentación externa no habrá problemas pero debido a las limitaciones de la RaspberryPi en términos de alimentación es posible que no pueda arrancar un disco que requiera alimentación por USB, así que lo primero será encontrar las unidades que tenemos conectadas.

sudo blkid

Si no vemos nuestra unidad y no tiene alimentación externa podemos probar a hacer los siguientes pasos:

Archivos sin fuente de alimentación externa

Editamos el fichero config.txt

sudo nano /boot/config.txt

Agregamos esta línea al final del fichero

max_usb_current=1

Reiniciamos

sudo reboot

Ahora volveríamos a probar el comando blkid y ver si aparece nuestra unidad, de no ser así podemos probar lo siguiente.

Instalamos wringPi desde aquí y comprobamos si tenemos el pin GPIO 38 activo que es el que nos permitirá doblar la potencia de la RaspberryPi y alimentar dispositivos externos:

gpio -g read 38

Si devuelve 1 lo tenemos habilitado, si vemos un 0 lo habilitamos con:

gpio -g write 38 1

En caso de no funcionar hay que usar una fuente de alimentación de más calidad, para verificar si el problema es la fuente de alimentación al arrancar la RaspberryPi tenemos que fijarnos en la cantidad de iconos de frambuesa que veamos, cuantos más mejor y sobre todo fijarnos de no ver ningún símbolo de un rayo lo que querría decir que no hay potencia suficiente.

Configurando unidad externa

Cuando veamos nuestra unidad usamos el siguiente comando:

sudo lsblk -o UUID,NAME,FSTYPE,SIZE,MOUNTPOINT,LABEL,MODEL

Veremos un listado de unidades conectadas, una buena pista suele ser mirar la columna LABEL y MODEL también por el tamaño podemos averiguar cual es nuestra unidad.

La columna FSTYPE muestra el tipo del sistema de archivos, hay que tener instalado el driver adecuado para que se pueda leer, por ejemplo para exFAT:

sudo apt install exfat-fuse

O para NTFS (poder leer y escribir):

sudo apt install ntfs-3g

Tenemos que crear la carpeta en la que queramos mapear la unidad de red, por ejemplo:

mkdir /media/usb/acme

Ahora localizamos el valor UUID (la primera columna) lo guardamos y editamos el fichero /etc/fstab, incluyendo esta línea:

UUID=12345678ABCDEFGH /media/usb/acme ntfs-3g default,uid=pi,gid=pi,nofail 0 0

Donde UUID es el valor que teníamos guardado, luego tenemos la ruta a la carpeta que hemos creado /media/usb/acme, ntfs-3g es el driver necesario para leer la unidad, en este caso ntfs-3g porque es una unidad con sistema de archivos ntfs, uid es el nombre de usuario que se usará para acceder a la unidad (en este ejemplo el usuario pi) y gid es el nombre del grupo con permiso para acceder (en este caso el grupo pi), nofail sirve para indicar que si la unidad no se puede montar en el arranque no se produzca un error.

En este caso hemos usado el usuario pi que viene por defecto en la instalación, si quisiéramos usar otro haríamos:

sudo adduser acme

Igual puede interesar crear un usuario solo para validarse por red pero no para poder iniciar sesión como un usuario normal, algo parecido a una cuenta de servicio.

sudo adduser -shell /bin/false --no-create-home acme

Ahora solo nos queda montar la unidad USB con:

sudo mount -a

Si accedemos a la carpeta que hemos creado veremos el contenido del disco, también podemos compartirla por unidad de red siguiendo los detalles de este post.

Referencias

https://www.htpcguides.com/power-2-5-hard-drive-with-raspberry-pi-b/
https://www.raspberrypi.org/documentation/configuration/external-storage.md
https://www.raspberrypi.org/forums/viewtopic.php?t=238095

USB externo en Raspberry Pi

Torrent en Raspberry Pi (Deluge & Transmission) con Apache

Actualizado a 3 de Septiembre de 2020

Instrucciones para instalar torrent manualmente en un servidor ya existente para proporcionarle más funcionalidad, en este caso estas son las instrucciones para los dos más populares, Deluge y Transmission.

Primero actualizar la Raspberry pi

sudo rpi-update
sudo apt-get update
sudo apt-get upgrade
sudo apt-get dist-upgrade

Vamos a utilizar el cliente Deluge así que instalamos los paquetes:

sudo apt-get install deluged
sudo apt-get deluge-console

Ahora hay que arrancar el demonio en Linux y después lo paramos, esto es para que cree la configuración por defecto.

sudo deluged 
sudo pkill deluged

Primero un backup de la configuración original y editamos el archivo, al haber instalado con sudo los ficheros estarán en la carpeta /root.

sudo cp /root/.config/deluge/auth /root/.config/deluge/auth.old.nano
sudo nano /root/config/deluge/auth

Ahora hay que cambiar la línea que aparece en fichero con este formato user:password:level, esta cuenta sirve para administrar raspberry, en este caso usamos los valores por defecto de raspberry como ejemplo, donde 10 indica máximo nivel de permisos, pi:raspberry:10 y ahora arrancamos el demonio y arrancamos la consola.

sudo deluged 
sudo deluge-console

En esta consola arrancamos los siguientes comandos: config -s allow_remote True, esto habilita las conexiones remotas, para verificar el valor se puede usar el comando config allow_remote, para salir basta con usar exit.

Ahora reiniciar para hacer efectivos los cambios.

sudo pkill deluged
sudo deluged

En web de Deluge existen clientes de escritorio para instalar, pero en este caso vamos a usarlo vía web.

sudo apt-get install python-mako
sudo apt-get install deluge-web
sudo deluge-web &

El puerto por defecto es 8112, si se quiere cambiar se puede hacer con el siguiente comando, en el fichero cambiar la línea port por el puerto (superior a 1000), en este mismo fichero completamos la línea: «default_daemon»:»localhost:58846″

sudo pkill deluge-web
sudo nano /root/.config/deluge/web.conf

Ahora se puede acceder a la dirección web http://raspberry:8112 la cual abrirá una web con una contraseña que por defecto es deluge.

Después de esto es necesario reiniciar y arrancar de nuevo.

sudo pkill deluged
sudo deluged

Ahora solo queda configurar Deluge para que arranque en el inicio, para esto editamos el archivo /etc/rc.local y agregamos las siguientes líneas al final del archivo (antes de la línea exit 0)

sudo -u pi /usr/bin/python /usr/bin/deluged
sudo -u pi /usr/bin/python /usr/bin/deluge-web

Ahora vamos a instalar transmission:

Primero instalar los paquetes:

sudo apt-get update
sudo apt-get install transmission transmission-daemon

Ahora paramos el servicio para poder editar los ficheros de configuración

sudo service transmission-daemon stop

Ahora editamos el fichero:

sudo nano /etc/transmission-daemon/settings.json

Y modificamos los siguientes parámetros, en este caso los parámetros «download-dir» y «incomplete-dir» apuntan a la carpeta donde se guardará el torrent y la carpeta temporal donde se ubican mientras se van descargando. La carpeta «watch-dir» es la carpeta donde se dejan los torrent que se descargarán automaticamente.

"blocklist-enabled": true,
"blocklist-url": "http://john.bitsurge.net/public/biglist.p2p.gz",
"download-dir": "/mnt/samba/hdd/download", 
"incomplete-dir": "/mnt/samba/hdd/temp", 
"incomplete-dir-enabled": true, 
"rpc-password": "TuPassWord", 
"rpc-username": "transmission", 
"rpc-whitelist-enabled": false,
"watch-dir":"/mnt,
"rpc-host-whitelist-enabled": false,

Ahora tenemos que cambiar el usuario con el que se ejecuta para poder hacerlo con el usuario pi, esto es especialmente útil sobre todo si hemos usado el usuario pi para mapear una unidad de red o una unidad USB.

Primero detenemos el demonio.

service transmission-daemon stop

Cambiamos el usuario

sudo nano /etc/init.d/transmission-daemon

y cambiamos:

USER=debian-transmission por USER=pi

También tenemos que editar el siguiente fichero:

nano /etc/systemd/system/multi-user.target.wants/transmission-daemon.service

Y ponemos esto:

[Unit]
Description=Transmission BitTorrent Daemon
After=network.target
[Service]
User=pi
Type=forking
PIDFile=/var/lib/transmission-daemon/.config/transmission-daemon/trans.PID 
ExecStart=/usr/bin/transmission-daemon --pid-file /var/lib/transmission-daemon/.config/transmission-daemon/trans.PID --config-dir /var/lib/transmission-daemon/.config/transmission-daemon/ 
[Install] 
WantedBy=multi-user.target

Ahora creamos el archivo pid y configuramos los permisos:

touch /var/lib/transmission-daemon/.config/transmission-daemon/trans.PID 
chown pi.pi /var/lib/transmission-daemon/.config/transmission-daemon/trans.PID

Ahora cambiamos el propietario de los ficheros:

chown -R pi.pi /var/lib/transmission-daemon 
chown -R pi.pi /etc/transmission-daemon/settings.json 
chown -h pi.pi /var/lib/transmission-daemon/info/settings.json

La dirección por defecto para acceder es:

http://127.0.0.1:9091/transmission

Hay que tener en cuenta que el fichero settings.json se tiene que editar cuando el servicio esté parado de lo contrario al pararse sobreescribe con los cambios actuales.

Ahora vamos a ver como configurar estas rutas por algo más fácil de recordar, para ello en Apache creamos un virtual host que nos haga de proxy con el servidor de torrent, creamos un fichero en la carpeta /etc/apache2/sites-available/004-torrent.conf con el siguiente contenido, obviamente deberemos tener un sistema DNS que nos resuelva correctamente el nombre torrent, vamos a suponer que el servidor está en la dirección 192.168.1.4

 <VirtualHost torrent:80>
   ServerName torrent.domain
   ServerAlias torrent
   ProxyPreserveHost Off
   ProxyRequests On
   ProxyPass / http://192.168.1.4:9091/
   ProxyPassReverse / http://192.168.1.4:9091/
   CustomLog /var/log/apache2/torrent.log combined
   ErrorLog /var/log/apache2/torrent.error.log
 </VirtualHost>

Ahora habilitamos el sitio usando el archivo de configuración que hemos creado

sudo a2ensite 004-torrent.conf

Después de reiniciar el servidor podremos acceder al servidor torrent usando la dirección http://torrent

Finalmente es posible que haya problemas con las carpetas watch de torrent si están en un disco externo ya que es posible que no detecte los cambios, así que vamos a configurar una carpeta por samba para poder dejar los ficheros ahí, así que editamos el fichero /etc/samba/smb.conf e incluimos el siguiente contenido:

[torrent]
comment = Carpeta para dejar torrents que se descargarán automaticamente
path = /media/torrent
read only = No
force user = pi
force group = pi
create mask = 0660

En este caso estamos suponiendo que la carpeta donde se colocarán los torrent está en /media/torrent

En caso de reinstalar la aplicación si no aparecen todos los ficheros que hemos descargado previamente es porque tenemos que rellenar la carpeta torrents con todos los torrents que nos hayamos descargado, podemos copiar el contenido de la antigua carpeta torrents en la nueva.

Enlaces:

https://www.alvaroreig.com/como-configurar-un-proxy-inverso-con-apache/

https://www.vichaunter.org/como-se-hace/cambiar-nombre-usuario-transmission-linux

https://www.vichaunter.org/como-se-hace/instalar-configurar-transmission-raspbian-raspberry-pi

Torrent en Raspberry Pi (Deluge & Transmission) con Apache

Configuración servidor de impresión y escaner con Raspberry Pi

Con una impresora antigua y una Raspberry es posible crear un servidor de impresión, estos son los pasos:

Primero como siempre actualizar Raspberry.

sudo apt-get update
sudo apt-get upgrade

Ahora instalamos CUPS, el servidor de impresión por excelencia de UNIX.

sudo apt-get install cups

Esto nos creará un grupo de administración de impresoras llamado lpadmin, agregamos el usuario pi a este grupo, se puede elegir cualquier usuario y cuando se acceda a través de web será este el usuario que se tendrá que validar.

sudo usermod -a -G lpadmin pi

Tenemos que habilitar el acceso remoto más allá de localhost, para que se puedan administrar las impresoras desde otra máquina en la red de área local.

sudo cupsctl --remote-any
sudo /etc/init.d/cups restart

Ahora podemos probar la web, usando la dirección de la Raspberry y el puerto 631 que es el de defecto, si quisiéramos cambiar el puerto se puede editar desde /etc/cups/cupsd.conf en la línea marcada como Port.

Si no tenemos instalado samba, estos serían los pasos rápidos:

sudo apt-get install samba

Ahora hay que editar el archivo de configuración de samba para agregar la entrada de la impresora, realmente esta entrada ya está creada solo hay que verificar que sea igual que esta:

# CUPS printing.  
[printers]
comment = All Printers
browseable = no
path = /var/spool/samba
printable = yes
guest ok = yes
read only = yes
create mask = 0700

# Windows clients look for this share name as a source of downloadable
# printer drivers
[print$]
comment = Printer Drivers
path = /var/lib/samba/printers
browseable = yes
read only = no
guest ok = no

También tenemos que establecer correctamente el valor del parámetro workgroup y de wins support:

workgroup = my_workgroup
wins support = yes

Ahora reiniciamos samba para hacer efectivos estos cambios.

sudo /etc/init.d/samba restart

Ahora a través de la web accedemos a la sección de administración, desde allí agregamos una impresora con el botón «Add printer» posiblemente haya que acceder con la cuenta que hemos agregado anteriormente al grupo lpadmin, si CUPS es capaz de detectar la impresora la veremos aquí como una impresora local, la seleccionamos y continuamos, cambiamos nombre y descripción o aceptamos las que vienen por defecto y marcamos compartir impresora «Share this printer» con esto ya tendremos una impresora configurada en red.

Esta es una configuración por defecto que funcionará tanto para pcs como para dispositivos móviles.

Mas info:

https://pimylifeup.com/raspberry-pi-print-server/

 

Configuración servidor de impresión y escaner con Raspberry Pi

Global Robot Expo 2017

Patrocinado por la FNAC tuve ocasión de echar un vistazo a la Expo Robot que se celebró este año en Madrid, un espacio amplio donde había varias áreas temáticas.

La primera sección dedicada a robótica industrial, robots que se mueven por ejemplo siguiendo una línea o que se dedican a automatizar ciertas tareas.

Img 1

Img 2

Después un paseo por las cada vez más pujantes impresoras 3D, se pueden apreciar creaciones de cierta complejidad.

Img 3

Los robots educativos que se puedan programar siguen apareciendo aunque es verdad que todavía sigue siendo un poco cara la gama alta.

Img 4

Img 5

Una sección dedicada a la domótica casera, por ejemplo el clásico ejemplo de la aspiradora:

Img 6

O un autónomo limpiador de cristales al más puro estilo spiderman:

Img 7

O algo un poco más complejo como un pequeño asistente casero:

Img 8

Ahora un espacio dedicado a los fans de los clásicos:

Img 9

Una de las secciones más grandes estuvo dedicada a los drones habiendo incluso competiciones entre ellos, siendo algunos de ellos de gama profesional necesitando sistemas de manejo en remoto.

Img 10

Img 11

Img 12

Una de las secciones más interesantes aunque no tuviera grandes máquinas a la vista, la UPV con su hyperloop de Elon Musk:

Img 13

Una sección dedicada a armazones asistidos, principalmente orientado a discapacidad, aunque más de uno estaría pensando en ser el próximo IronMan:

Img 14

Img 15

También se pudieron ver ejemplos de asistentes, cada vez un poco mejores:

Img 16

Img 17

Img 18

Interesantes de ver en acción:

Vid 1

O más interactivos:

Vid 2

O un ejemplo muy interesante de una araña artificial, muy logrado:

Vid 3

En general muy entretenido e interesante, habrá que volver el próximo año.

Global Robot Expo 2017