Para encontrar todos los usuarios disponibles en un sistema MacOS desde la línea de comandos, se puede utilizar un script en Bash. El sistema operativo MacOS, al igual que otros sistemas de tipo Unix, almacena la información de los usuarios en varios archivos del sistema, principalmente en /etc/passwd
. Sin embargo, MacOS utiliza Open Directory para la gestión de usuarios, por lo que se pueden usar comandos como dscl
para consultar esta información. Además veremos cómo hacer logout de otro usuario del Mac desde la línea de comando.
El siguiente script en Bash muestra todos los usuarios disponibles en tu sistema MacOS, junto con sus respectivos números de ID de usuario (UID):
#!/bin/bash
# Muestra todos los usuarios del sistema con su UID
echo "Usuarios y sus UIDs en este sistema macOS:"
# Recorre la lista de usuarios obtenidos con dscl
for user in $(dscl . list /Users | grep -v '^_'); do
# Obtiene el UID del usuario actual
uid=$(dscl . -read /Users/$user UniqueID | awk '{ print $2 }')
# Muestra el nombre de usuario y su UID
echo "Usuario: $user, UID: $uid"
done
Para ejecutar este script:
mac_lista_usuarios.sh
.chmod +x mac_lista_usuarios.sh
./mac_lista_usuarios.sh
$ ./mac_lista_usuarios.sh
Usuarios y sus UIDs en este sistema macOS:
Usuario: daemon, UID: 1
Usuario: luis, UID: 501 <== Mi usuario
Usuario: pruebas, UID: 502 <== USUARIO para pruebas
Usuario: nobody, UID: -2
Usuario: root, UID: 0
Este script lista todos los usuarios registrados en el sistema, excluyendo aquellos cuyos nombres de usuario comienzan con un guion bajo (_), que suelen ser cuentas de sistema o de servicios. Utiliza el comando dscl
que interactúa con Open Directory. El script podría modificarse para mostrar más información de cada usuario si fuera necesario.
En alguna ocasión puedo necesitarlo, por ejemplo cuando estar realizando tareas administrativas de tu Mac en remoto, te conectas vía ssh
, sin acceso al GUI y con la necesidad de echar al resto de usuarios.
Asumiendo que mi usuario tiene derechos de administración, para hacer logout del otro usuario bastaría con averiguar cuál es el UID del otro usuario usando el comando anterior ./macusers.sh
y después ejecutar el siguiente script:
#!/bin/bash
# Verificar si se ha proporcionado un UID
if [ "$#" -ne 1 ]; then
echo "Uso: $0 <UID>"
exit 1
fi
UID=$1
# Hacer logout del usuario con el UID proporcionado
sudo launchctl bootout user /$UID
Para ejecutar este script:
mac_logout_usuario.sh
.chmod +x mac_logout_usuario.sh
./mac_logout_usuario.sh 502
Este comando utiliza launchctl
, una herramienta para interactuar con el MacOS y terminar la sesión del usuario especificado. Ten en cuenta que forzar el cierre de sesión de otro usuario puede resultar en la pérdida de datos no guardados en sus aplicaciones abiertas, así que úsalo con precaución.
Un ejemplo completo sería:
$ ./mac_lista_usuarios.sh
Usuarios y sus UIDs en este sistema macOS:
Usuario: daemon, UID: 1
Usuario: luis, UID: 501
Usuario: pruebas, UID: 502 <== USUARIO DESTINO LOGOUT
Usuario: nobody, UID: -2
Usuario: root, UID: 0
$ ./mac_logout_usuario.sh 502
En este apunte explico cómo gestiono mis datos en un Mac. Mi objetivo es poder trabajar a máxima velocidad y desde cualquier sitio con los datos más utilizados, contar con un almacén extra para los menos accedidos y por supuesto contar con múltiples copias de seguridad.
Los datos fuentes están en el disco SSD interno del Mac y un par de discos externos. Las réplicas y los backups están en iCloud, un linux remoto y Google Drive. Varios sitios, diferentes tecnologías, velocidades, necesidades. La herramienta rclone
es perfecta para ayudarme a la hora de contar con múltiples copias de seguridad sincronizadas
Rclone es una poderosa herramienta de línea de comandos que permite gestionar y sincronizar archivos y directorios. Es muy versátil, te ayudará a administrar tus datos de manera efectiva, hacer copias de seguridad en servicios en la nube, en discos externos locales, remotos y mantenerlos sincronizados entre todos ellos.
Mis datos están en dos sitios: priv
y Baul
. La carpeta priv
está alojada en iCloud
y sincronizada (100% descargada) en el disco duro local del Mac. Es donde tengo los datos principales (accesibles desde el entorno Apple, iPhone, iPad, etc). El sitio Baul
es un disco duro externo SSD (Thunderbolt 4) muy rápido, donde tengo el almacén al que solo necesito acceder de vez en cuando y desde un único equipo (el Mac); me recuerda al típico disco D:\
de otra época.
Del Mac: Quiero asegurar todo, uso TimeMachine
para el backup completo del disco principal del Mac a un disco USB externo (USB 3.0, mecánico). Lo configuro y el sistema operativo se encarga de todo.
De priv
y Baul
: Son mis dos fuentes originales, así que las copio en varios sitios usando rclone
: disco externo Trastero, un linux remoto y Google Drive. Al tenerlo en Google Drive consigo un par de beneficios: una copia de “último recurso” si todo falla y acceso desde cualquier sistema operativo a cualquier dato desde cualquier lugar.
Para configurar Time Machine en un Mac, primero conecta un disco duro externo y ábrelo en “Preferencias del Sistema”, luego selecciona “Time Machine” y activa la función, elige la unidad externa como destino, configura las opciones de respaldo si es necesario y, finalmente, inicia Time Machine para que realice copias de seguridad automáticas de tu sistema en la unidad externa, asegurándote de mantenerla conectada para mantener las copias de seguridad actualizadas
En mi caso he configurado un disco externo USB 3.0 (Seagate Portable Drive) de 5TB bastante asequible y con un buen balance entre fiabilidad (mecánico de 2,5 pulgadas) y velocidad (120 MB/s).
rclone
Abre el Terminal en tu Mac.
Instala Homebrew si aún no lo tienes instalado.
Ejecuta el siguiente comando para instalar rclone:
brew install rclone
:
=> Caveats
Homebrew's installation does not include the `mount` subcommand on MacOS.
zsh completions have been installed to:
/opt/homebrew/share/zsh/site-functions
Verifica que rclone se haya instalado correctamente:
rclone version
La instalación de rclone en Linux es igualmente sencilla. A continuación, se describen los pasos generales:
Abre un Terminal en tu distribución Linux.
Puedes utilizar el administrador de paquetes de tu distribución para instalar rclone. Por ejemplo, en Ubuntu, puedes ejecutar:
sudo apt-get install rclone
En otras distribuciones, como Fedora, CentOS o Debian, puedes utilizar el administrador de paquetes correspondiente.
Verifica la instalación ejecutando:
rclone version
Como decía, el disco duro principal interno del Mac “Macintosh HD” (HD
a partir de ahora) tiene el Sistema Operativo, las aplicaciones y el HOME de mi usuario (/Users/luis
) con la carpeta priv
. El disco externo SSD Thunderbolt 4 (1000MB/s) Baul
tiene el espacio extra para datos que comentaba al principio.
Dato | Origen | Dónde se hace el backup |
---|---|---|
HD | Disco interno | TimeMachine disco externo USB |
priv |
iCloud (Datos principales) | 1) por la sincronización iCloud <> Local y 2) Backups en Trastero (rclone ), en linux (rclone ) y futuro Dropbox/Google (rclone ) |
Baul |
Disco externo (1000MB/s) | Backups en Trastero (rclone ) y en linux remoto (rclone ) |
Trastero |
Disco externo | Este disco externo SSD (500MB/s) los uso exclusivamente como destino para los backups. ¿Porqué tan rápido? pues porque también guardo alguna cosa extra y si se rompe Baul podrá dar un buen servicio mientras busco un reemplazo |
Google Drive |
Disco en la Nube | Lo uso para tener una copia extra por si todo falla, pero también para poder acceder a mis datos desde cualquier sitio y cualquier sistema operativo (por ejemplo un Linux) |
Veamos cómo configurar los destinos (incluye carpetas o discos locales y además los sitios remotos):
Nota: Toda la configuración reside en ~/.config/rclone/rclone.conf |
Ejecuta el siguiente comando para iniciar la configuración de rclone:
rclone config
Puedes seguir las instrucciones del asistente de configuración para añadir un nuevo almacenamiento remoto. Puedes elegir entre una amplia gama de servicios en la nube y sistemas de archivos locales.
Proporciona la información requerida, como las credenciales de acceso, y asigna un nombre al almacenamiento remoto para referencia futura.
Una vez configurado el almacenamiento remoto, puedes utilizar rclone para sincronizar tus directorios con él.
Así es como quedó mi fichero rclone.conf
tras mi configuración inicial, donde dí de alta las carpetas y discos locales (Luis, Baul, Trastero
) y el directorio priv
que está bajo iCloud
.
[Luis]
type = alias
remote = /Users/luis
[Baul]
type = alias
remote = /Volumes/Baul
[Trastero]
type = alias
remote = /Volumes/Trastero
[iCloud]
type = alias
remote = /Users/luis/Library/Mobile Documents/com~apple~CloudDocs
IMPORTANTE: Mi carpeta priv realmente reside en iCloud, para que TODO el contenido de dicha carpeta esté siempre completamente sincronizado en el disco duro interno local, y poder copiarlos a otro sitio con rclone , es importante indicarle a macOS que se los baje a local. ¿Cómo?, pues desde Finder > iCloud > busco y botón derecho sobre priv > “Descargar ahora”. Se bajará una copia completa que sincroniza permanentemente a partir de ese momento con iCloud. |
Antes de añadir el destino de Google Drive a la configuración de rclone
vamos a preparar nuestra cuenta con Google.
client_id
en Google (fuente)Entrar en la Google API Console
Creo un proyecto nuevo: Rclone LuisPa
, en Organización dejé Sin Organización
y “Seleccionar Proyecto”.
Bajo “APIs y servicios” > Habilitar APIs y Servicios > busco Drive
, click en “Google Drive API” y “HABILITAR”, en la pantalla que muestra
Click en “Credenciales” en el panel izquierdo (no en “Crear Credenciales” que habríría un asistente) Si ya habías configurado la “Oauth Consent Screen”, salta al siguiente paso
Click en el botón “CONFIGURAR PANTALLA DE CONSENTIMIENTO” > “Externos” > CREAR
Application name: rclone
User Support Email: pon.aquí.tu.email@gmail.com
Developer Contact Email: pon.aquí.tu.email@gmail.com
GUARDAR Y CONTINUAR
Click en AGREGAR o QUITAR PERMISOS.
Doy permisos a .../auth/docs, .../auth/drive, .../auth/drive.metadata.readonly
ACTUALIZAR
GUARDAR y CONTINUAR
Añádete a tí mismo en “Usuarios de prueba”,
Añado a mi usuario con el correo
GUARDAR Y CONTINUAR
Click de nuevo en “Credenciales” en el panel izquierdo.
Elijo un tipo de apliación “App de escritorio” y en nombre pongo “Cliente Escritorio”, CREAR
Muesta el client ID y un client secret. GUARDARLOS en un lugar seguro :-)
Click en “Pantalla de consentimiento de OAuth” en el panel izquierdo, click en “publicar App” y confirmar. Ignoro la necesidad de “Verificación”.
Nota: Teóricamente se espera que “envíes tu aplicación para su verificación” y luego esperes semanas para su respuesta; en la práctica, puedes seguir adelante y utilizar el ID de cliente y el secreto de cliente con rclone, el único problema será una pantalla de confirmación muy aterradora que se muestra cuando te conectas a través de tu navegador para que rclone pueda obtener su token-id (pero como esto sólo ocurre durante la configuración remota, no es demasiado problema). |
$ rclone config
:
n) New remote
e/n/d/r/c/s/q> n
name> Drive
Storage> drive
client_id> 1111111111111-el_client_id_que_cree_en_el_paso_anterior.apps.googleusercontent.com
client_secret> ELSECRETO-CreadoEnElPaso-Anterior
scope> 1 (Full access all files..)
service_account_file> (Pulso Intro, lo dejo vacío)
Edit advanced config?
y/n> n
Use web browser to automatically authenticate rclone with remote?
y/n> Y
:
Abre el navegador y autorizo !!
2023/12/13 11:48:22 NOTICE: Log in and authorize rclone for access
2023/12/13 11:48:22 NOTICE: Waiting for code...
2023/12/13 11:48:33 NOTICE: Got code
Configure this as a Shared Drive (Team Drive)?
y/n> n
Configuration complete.
Options:
- type: drive
- client_id: 1111111111111-el_client_id_que_cree_en_el_paso_anterior.apps.googleusercontent.com
- client_secret: ELSECRETO-CreadoEnElPaso-Anterior
- scope: drive
- token: {"access_token":"ya29.token-largísimo","token_type":"Bearer","refresh_token":"1//token-mas-largo-todavía","expiry":"2023-12-13T12:48:32.418859+01:00"}
- team_drive:
Keep this "Drive" remote?
y/e/d> y
q) Quit config
e/n/d/r/c/s/q> q
Ya tengo disponible un nuevo destino en la nube de Google para poder utilizar con rclone
Veamos el típico ejemplo de sincronización de directorios entre dos discos locales. Imaginemos que queremos hacer copia de seguridad en Trastero
de varios directorios. Recuerda preparar las carpetas destino de los Backups
mkdir -p /Volumes/Trastero/Baul
mkdir -p /Volumes/Trastero/iCloud
mkdir -p /Volumes/Trastero/priv
mkdir -p /Volumes/Trastero/Other
Estos serían algunos ejemplos:
rclone sync --progress --copy-links --skip-links --exclude="*.socket" --exclude=".DS_Store*" Baul:fotos Trastero:Baul/fotos
rclone sync --progress --copy-links --skip-links --exclude="*.socket" --exclude=".DS_Store*" Baul:gestión Trastero:Baul/gestión
rclone sync --progress --copy-links --skip-links --exclude="*.socket" --exclude=".DS_Store*" iCloud:priv Trastero:iCloud/priv
rclone sync --progress --copy-links --skip-links --exclude="*.socket" --exclude=".DS_Store*" Luis:Pictures/Lightroom Trastero:Other/Lightroom
Ah!, recomiendo usar --dry-run
o check
para probar primero. Otra opción es crearse un fichero de filtraje donde especifico qué quiero excluír e incluir. Por ejemplo, para los directorios de Baul, creo el fichero filter-from-Baul.txt
- .DS_Store
- _gsdata_
- .DocumentRevisions-V100
- .Spotlight-V100
- .TemporaryItems
- .Trashes
- .fseventsd
+ /fotos**
+ /gestión**
- *
check
y luego el sync
:rclone check --progress --copy-links --filter-from ~/.config/rclone/filter-from-Baul.txt Baul: Trastero:
rclone sync --progress --copy-links --filter-from ~/.config/rclone/filter-from-Baul.txt Baul: Trastero:
Para sincronizar un directorio con Google Drive, utilizaría el siguiente comando de ejemplo:
rclone sync --progress --copy-links --skip-links --exclude="*.socket" --exclude=".DS_Store*" iCloud:0_priv Drive:0_priv
Para sincronizar tus directorios con un ordenador remoto que ejecute rclone servidor, puedes utilizar el siguiente comando de ejemplo:
rclone sync /ruta/al/priv OrdenadorRemoto:/ruta/en/el/servidor/priv
rclone sync /ruta/al/work OrdenadorRemoto:/ruta/en/el/servidor/work
rclone sync /ruta/al/Negativos OrdenadorRemoto:/ruta/en/el/servidor/Negativos
rclone sync /ruta/al/Baul OrdenadorRemoto:/ruta/en/el/servidor/Baul
Reemplaza /ruta/al/priv
, /ruta/al/work
, /ruta/al/Negativos
, /ruta/al/Baul
, OrdenadorRemoto
, y /ruta/en/el/servidor
con las rutas y nombres de servidor correctos.
Con estos comandos, puedes mantener tus directorios sincronizados tanto en la nube como en un servidor remoto. Rclone te proporciona una forma eficaz de gestionar tus datos en macOS y Linux, permitiéndote respaldarlos y mantenerlos actualizados en múltiples ubicaciones.
En resumen, rclone es una herramienta esencial para cualquier usuario que necesite sincronizar y respaldar datos en macOS y Linux. Su versatilidad y facilidad de uso hacen que sea una elección sólida para la gestión de archivos en la nube y la sincronización entre dispositivos.
Tenemos un par de opciones. Yo no las uso, porque una vez que te pones a jugar y probar con la versión del CLI la verdad es que resulta muy cómodo poner todos los comandos en un script y vas mucho más rápido.
rclone
Existe un GUI experimental que puedes instalar para trabajar en modo gráfico. Basta con ejecutar el siguiente comando, que se bajará todo lo necesario y arrancará un servidor web local. Arranca un navegador y se conecta (puedes evitarlo con --rc-web-gui-no-open-browser
).
En este ejemplo pido que use un usuario/password concretos y que sea “verbose”, cambia el usuario y la contraseña a lo que quieras. También puede funcionar sin autenticación con --rc-no-auth
rclone rcd --rc-web-gui --rc-user luis --rc-pass mipase -vv
:
2023/11/18 12:38:47 DEBUG : rclone: Version "v1.64.2" starting with parameters ["rclone" "rcd" "--rc-web-gui" "--rc-user" "luis" "--rc-pass" "mipase" "-vv"]
2023/11/18 12:38:47 DEBUG : Current tag: v2.0.5, Release tag: v2.0.5
2023/11/18 12:38:47 NOTICE: Web GUI exists. Update skipped.
2023/11/18 12:38:47 NOTICE: Serving Web GUI
2023/11/18 12:38:47 INFO : Using --user luis --pass XXXX as authenticated user
2023/11/18 12:38:47 NOTICE: Serving remote control on http://127.0.0.1:5572/
2023/11/18 12:38:47 DEBUG : login_token "bHVp12343535hc2U="
2023/11/18 12:38:47 INFO : /: 127.0.0.1:59654: Unauthorized request from
:
Otra opción, si quieres una versión estable, es RcloneBrowser, un GUI multi plataforma que soporta macOS, GNU/Linux, la familia BSD y Windows.
Para instalarlo en macOS, sigue estos pasos:
Descarga la última versión desde https://github.com/kapitainsky/RcloneBrowser/releases. En el momento de la publicación utilicé rclone-browser-1.8.0-a0b66c6-macos.dmg
Al ejecutarlo configuro el path al ejecutable y la ubicación del fichero de configuración
Para tenerlo actualizado a la última versión, puedes utilizar el siguiente comando:
brew update
brew upgrade
apt update && apt upgrade -y
rclone rcd --rc-web-gui --rc-web-gui-update
# Si el GUI está roto se puede forzar el update con `--rc-web-gui-force-update`
En este apunte describo cómo aprovechar un macbook air antiguo (2015) para instalarle Linux y extender su tiempo de vida. Con el tiempo estos mac’s se convierten en equipos casi inútiles, con una velocidad pasmosa y memoria insuficiente.
¿Porqué no aprovecharlos con Linux?. Un Macbook Air del 2015, con 8GB y 128GB de disco puede convertirse en un equipo muy útil.
He elegido Ubuntu Desktop para realizar la instalación. Estos son los pasos que he seguido:
Si no quieres GUI, a partir de aquí ya sólo te haría falta deshabilitarlo
$ sudo systemctl set-default multi-user
$ reboot
Para iniciar un rearranque completo se puede utilizar el comando systemctl reboot
, pero ¿cómo puedo programarlo a una hora determinada?. En este apunte explico cómo hacerlo utilizando systemd, el gestor de arranque y administración para distribuciones Linux.
Entre los servicios de timer de systemd hay una funcionalidad poco conocida que permite programar un reboot automático cuando queramos.
Creo un fichero reboot-diario.timer
donde pido la ejecución de una de las Unidades Especiales de Systemd, en concreto la Unit “reboot.target”, que permite hacer un shutdown y reboot de mi equipo Linux.
/etc/systemd/system/reboot-diario.timer
[Unit]
Description=Reboot Diario.
[Timer]
OnCalendar=*-*-* 04:30:00
Unit=reboot.target
[Install]
WantedBy=timers.target
systemctl daemon-reload
systemctl enable reboot-diario.timer
systemctl start reboot-diario.timer
A partir de ahora mi equipo hará un reboot todos los días a las 04:30 am
.
Algunas unidades son tratadas especialmente por systemd. Muchas de ellas tienen semántica interna especial y no pueden renombrarse, mientras que otras simplemente tienen un significado estándar y deberían estar presentes en todos los sistemas.
Existen bajo systemd.special y puedes consumirlas cuando lo necesites. Dejo aquí la explicación sobre la que uso en este ejemplo:
Es un target especial para apagar y reiniciar el sistema. Las aplicaciones que deseen reiniciar el sistema no deben usarla, sino que deben ejecutar systemctl reboot
(posiblemente con la opción –no-block) o llamar a systemd-logind(8)’s org.freedesktop.login1.Manager.Reboot() D-Bus directamente.
Recomiendo investigar también el servicio systemd-reboot.service(8) para más detalles de la operación que este target realiza.
Esta unidad tiene un alias llamado runlevel6.target
por compatibilidad con SysV.
Vagrant permite crear y configurar entornos de desarrollo virtuales, ligeros y reproducibles. Lo hace creando máquinas virtuales y necesita un Virtualizador. Le da igual qué virtualizador usar, soporta Virtualbox, KVM, Docker, VMWare y otros 30 más. Es una herramienta fantástica para poder montar Servidores para nuestros desarrollos de software.
Este apunte solo vale, de momento, para trabajar con chip INTEL. De momento no he sido capaz de hacerlo funcionar en un Mac con ARM (Apple Silicon) como anfitrión.
VirtualBox es un software de virtualización que permite instalar sistemas operativos adicionales, conocidos como «sistemas invitados, guest, máquinas virtuales», dentro de tu sistema operativo «anfitrión», cada uno con su propio ambiente virtual. Puedes crear máquinas virtuales basadas en FreeBSD, GNU/Linux, OpenBSD, OS/2 Warp, Windows, Solaris, MS-DOS, Genode y muchos otros.
Para instalarlo descargo el binario de VirtualBox desde Download VirtualBox, el proceso de instalación es muy sencillo. Una vez instalado no necesitas crear ninguna máquina virtual, lo haremos directamente desde Vagrant.
Hace tiempo escribí un apunte sobre cómo trabajar con Vagrant en Linux usando otro virtualizador: Vagrant con Libvirt KVM.
Nota: He visto que VirtualBox tiene una versión que corre de forma nativa sobre ARM y funciona correctamente, pero todavía no he conseguido que Vagrant levante una VM Linux ARM nativa o una VM Windows ARM nativa. |
A modo de curiosidad, si haberlo probado todavía, parece que otro virtualizador, Parallels Desktop
, permite instalar Windows 11 sobre ARM descargando la imagen desde los servidores de MS. Se puede activar con cualquier licencia válida de W7/8/10/11, dado que las licencias no tienen dependencia de la arquitectura. Así que en teoría se puede comprar W11 sobre ARM y hacerlo funcionar en un Parallels Desktop sobre M1/M2.
Recomiendo instalar Vagrant usando Homebrew
. Si tienes un Mac lee el apunte MAC para desarrollo donde describo cómo instalar Homebrew y un montón de herramientas muy últiles para poder desarrollar en un Mac.
brew update && brew upgrade
brew install vagrant
source ~/.zshrc
Una vez instalado compruebo la verisón y que funciona correctamente
Creo una máquina virtual para pruebas, la levanto y la destruyo para comprobar todo el proceso.
Creo un directorio temporal y una VM de pruebas usando la imagen (Vagran los llama boxes) trusty64
. Puedes encontrar mucho más en Discover Vagrant Boxes.
mkdir prueba
cd prueba
vagrant init ubuntu/trusty64
vagrant up
El disco virtual se crea en el HOME de tu usuario, en el subdiretorio ` ~/VirtualBox\ VMs`
ls -al ~/VirtualBox\ VMs/prueba_default_1682326653672_96128
total 3119136
drwx------ 6 luis staff 192 23 abr 10:59 .
drwx------ 3 luis staff 96 23 abr 10:57 ..
drwx------ 5 luis staff 160 23 abr 10:59 Logs
-rw------- 1 luis staff 1584726016 23 abr 10:59 box-disk1.vmdk
-rw------- 1 luis staff 4495 23 abr 10:59 prueba_default_1682326653672_96128.vbox
-rw------- 1 luis staff 4904 23 abr 10:59 prueba_default_1682326653672_96128.vbox-prev
Conecto con la VM usando SSH
ssh -p 2222 vagrant@127.0.0.1 <== La constraseña es 'vagrant'
Podemos destruir esta máquina virtual rápidamente con
➜ prueba vagrant destroy
default: Are you sure you want to destroy the 'default' VM? [y/N] y
==> default: Destroying VM and associated drives...
En este repositorio en GitHub tienes un maquina virtual para desarrollo de software preparada con Vagrant.
Se trata de un repositorio con todo lo necesario para crear una máquina virtual orientada al Desarrollo de Software con Python y JupyterLabs.
Podrás utilizar esta VM para conectar con servicios adicionales de Bases de Datos, cuadernos Jupyter de ejercicios. Tienes toda la información en el README del repositorio.
Otra referencias interesantes:
]]>En este apunte describo mi bitácora de configuración de un Mac (INTEL o ARM) como equipo de desarrollo. Instalo varias aplicaciones gráficas y de línea de comando que para mi son fundamentales para trabajar con el equipo.
Está documentado partiendo de una instalación nueva de Ventura, desde cero. El orden de instalación puede variarse, pero te recomiendo (si tu MacOS está recién instalado) que sigas el mismo orden para ver los mismos resultados.
Empezamos con la instalación, si estás buscando cómo actualizar o reparar, ve al final del apunte.
Es obligatorio instalar las Apple command line tools (también conocidas como Xcode command line tools) porque algunas herramientas te lo van a pedir más adelante.
La instalación de Xcode es opcional, solo si vas a desarrollar para macOS, iOS, watchOS y tvOS. Dependiendo de qué decidas, el orden sería este:
xcode-select --install
sudo xcodebuild -license accept
xcode-select --install
iTerm2 es un sustituto al Terminal.app del MacOS. Admite muchas más cosas que el Terminal como la transparencia de ventanas, modo de pantalla completa, paneles divididos, pestañas Exposé, notificaciones Growl y atajos de teclado, perfiles personalizables y reproducción instantánea de entradas/salidas de terminales anteriores.
Instalación:
Un par de tips:
sudo xcodebuild -license accept
iTerm
cuando el cursor está en una carpeta de Finder.
Ajustes Sistema → Teclado → Funciones rápidas de teclado → Servicios
→ Archivos y carpetas → New iTerm2 Tab Here → Ctrl Shift T
oh-my-zsh es un entorno de trabajo en línea de comando mucho más bonito para trabajar con Zsh. Viene con miles de funciones útiles, ayudantes, plugins, temas. Trae varios plugins que hacen la vida más fácil. Lo mejor de Oh My Zsh son sus temas.
Instalación:
sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"
~/.zshrc
Una vez instalado iTerm + Oh My Zsh te recomiendo que te copies el contenido de mi fichero ~/.zshrc
. Tras instalar iTerm2 y Oh-My-Zsh se habrá creado ya uno e irás viendo que te pido hacer modificaciones en este fichero más adelante.
Te dejo el mío, es una copia final completa, compatible con lo que acabamos de instalar y lo que instalaremos. Ahora bien, es muy importante que una vez copiado lo revises y adaptes a tu caso. El mío está preparado para un Mac sobre chip ARM. Si tu Mac usa chip Intel revisa el fichero, verás notas en las líneas para saber qué comentar/descomentar.
cd ~
cp .zshrc .zshrc.ORIGINAL
curl -s -O https://gist.githubusercontent.com/LuisPalacios/f66942b329af7920bebd4b95fa36cdb5/raw/52fe5b891b524bde6d315aab92a6b82d0dafa19e/.zshrc
Visual Studio Code es un editor de código fuente desarrollado por Microsoft para Windows, Linux, macOS y Web. Incluye soporte de tantas cosas que es imposible explicarlo aquí. Con la inmensa diversidad de características, plugins y lenguajes soportados puedes usarlo como IDE para cualquier proyecto.
Instalación:
Un par de tips:
~/.zshrc
para lanzar el programa de forma rápida desde el CLI. Si te bajaste mi copia no hace falta que lo hagas.# Alias para llamar a VSCode desde CLI con "e"
alias e="/usr/local/bin/code"
e .
Siendo desarrollador con un Mac, quieres Homebrew (o brew
por resumir) Aunque Mac OS trae de todo (al estar basado en FreeBSD) por desgracia no está a la última y le faltan cosas.
Con brew
vas a poder instalar (en paralelo a tu Mac OS sin tocarlo ni estropearlo) un montón de programas de software libre super interesantes, software de bajo nivel, herramientas para la línea de commandos, aplicaciones, compiladores, lenguajes, etc. podrás instalar hasta MongoDB (ver más adelante).
Instalación:
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
source ~/.zshrc
Líneas relevantes en mi ~/.zshrc
# LuisPa: --------------------------------------------------------------
export PATH=$HOME/0_priv/bin:/usr/local/bin:/usr/local/sbin:$PATH
launchctl setenv PATH "/usr/local/bin:/usr/local/sbin:$PATH"
# Homebrew
(echo; echo 'eval "$(/opt/homebrew/bin/brew shellenv)"') >> /Users/luis/.zprofile # Homebrew en Mac ARM
eval "$(/opt/homebrew/bin/brew shellenv)" # Homebrew en Mac ARM
#(echo; echo 'eval "$(/usr/local/bin/brew shellenv)"') >> /Users/luis/.zprofile # Homebrew en Mac Intel
#eval "$(/usr/local/bin/brew shellenv)" # Homebrew en Mac Intel
# Ruby y Gems
export PATH="/opt/homebrew/opt/ruby/bin:~/.gems/bin:$PATH" # Versión para Mac ARM
#export PATH="/usr/local/opt/ruby/bin:~/.gems/bin:$PATH" # Versión para Mac Intel
# LuisPa: --------------------------------------------------------------
Git es un sistema de control de versiones distribuido, gratuito y de código abierto, diseñado para gestionar desde proyectos pequeños a muy grandes con rapidez y eficacia. Existen varias opciones de Instalación del cliente para la línea de comandos (fuente original), en mi caso utilizo la de Homebrew.
Instalación:
brew update && brew upgrade
brew install git
source ~/.zshrc
Creo el fichero ~/.gitconfig y ~/.gitignore_global, que te puedes bajar así:
curl -s -O https://gist.githubusercontent.com/LuisPalacios/0ee871ee236485d4a064179b16ada400/raw/348a8a448095a460756f85ef0362521b886b0a2e/.gitconfig
curl -s -O https://gist.githubusercontent.com/LuisPalacios/6923f8cc708ce10f3bd4a6772625fb0c/raw/65d0ed6acba83ece4db78228821589212b9f9f4b/.gitignore_global
# Edítalo para adaptarlo
e .gitconfig
Como cliente GUI uso GitKraken. Tienes más información sobre git en esta chuleta sobre GIT y GIT en detalle.
Ahora es buen momento para configurar tu pareja de claves pública/privada para conectar con Hosts remotos y/o usarlo con servidor(es) Git. La clave pública-privada SSH es un sistema de autenticación y encriptación utilizado para la conexión entre un cliente y un servidor. Se utilizan un par de claves: una clave pública y una clave privada. Los dos casos de uso más típicos son:
git
con un servidor Git remoto (por ejemplo github.com
)Creo mi clave pública-privada, crea dos archivos de texto bajo ~/.ssh
.
➜ ~ ssh-keygen -t ed25519 -a 200 -C "luis@mihost" -f ~/.ssh/id_ed25519
:
Enter passphrase (empty for no passphrase): <=== Pon una contraseña que usarás durante las futuras conexiones
Your identification has been saved in /Users/luis/.ssh/id_ed25519 <== Clave PRIVADA. NUNCA LO COMPARTAS
Your public key has been saved in /Users/luis/.ssh/id_ed25519.pub <== Clave PÚBLICA. Este contenido es el que compartes !!
:
El contenido del fichero con la clave pública lo compartes con el servidor remoto (github
o un linux para terminal remoto), mientras que la clave privada se mantiene en local. Simplificándolo muchísimo, mi clave pública que le paso a Github la va a usar para encriptar información que solo yo, que poseo la privada equivalente, puedo descifrar y así comunicarnos.
En el caso de Github se puede usar este método (SSH pública-privada) para acceso directo a tu cuenta y modificar repositorios de forma segura, sin necesidad de hacer login (https con usuario y contraseña). Es importante destacar que debes mantener tu clave privada segura, ya que si alguien más la tiene, puede acceder a tu cuenta y repositorios.
El contenido de tu pública se comparte:
~/.ssh/authorized_keys
Tienes un par de apuntes adicionales en SSH y X11 y SSH en Linux
Podemos instalar JRE (Java Runtime Environment) para ejecutar aplicaciones Java o el JDK (Java Development Kit), para desarrollar y ejecutar aplicaciones Java.
En mi caso obviamente me instalo JDK, trae herramientas como el compilador (javac), el desensamblador de binarios (javap), el debugger, etc. y toda instalación de JDK incluye JRE. Te recomiendo echar un ojo a esta imagen sobre la estructura de componentes de Java.
Instalación:
Una vez instalado, hacemos nuestra prueba de concepto desde iTerm
$ mkdir -p ~/Desktop/hola
$ cd ~/Desktop/hola
$ cat > HolaMundo.java << EOF
public class HolaMundo {
public static void main(String[] args) {
System.out.println("Hola Mundo!");
}
}
EOF
$ javac HolaMundo.java
$ ls -l
total 16
-rw-r--r--@ 1 luis staff 423 22 abr 15:22 HolaMundo.class
-rw-r--r--@ 1 luis staff 111 22 abr 15:21 HolaMundo.java
$ java HolaMundo
Hola Mundo!
Te dejo aquí algunas referencias interesantes:
Podrías usar Visual Studio Code como IDE pero lo más normal es que te instales Eclipse, es La plataforma para trabajar con Java, y mucho más, en realidad con herramientas de programación de código abierto multiplataforma para desarrollar Aplicaciones.
Típicamente se ha usado para desarrollar IDE’s (entornos de desarrollo integrados), como el del propio Java (Java Development Toolkit - JDT).
Instalación:
Un tip:
Python es un lenguaje de programación interpretado cuya filosofía hace hincapié en la legibilidad de su código. Soporta parcialmente la orientación a objetos, programación imperativa y algo de programación funcional. MacOS trae versiones antiguas de Python 2 y 3 que NUNCA deben borrarse o sobreescribir. Uso Homebrew para hacer una instalación paralela.
Pip es un indispensable, es el sistema de gestión de paquetes utilizado para instalar y administrar programas y paquetes hechos en Python desde el Python Package Index (PyPI), el repositorio de software oficial para aplicaciones de terceros en Python.
PipEnv es otro indispensable. Las aplicaciones en Python hacen uso de paquetes y módulos que no forman parte de la librería estándar. Gestionar todas las librerías que deben acompañar a mi programa es un infierno. Con PipEnv
puedo “contener” todo dentro de un directorio, creando un entorno virtual, sin conflictos. Nota: hay dos paquetes equivalentes a PipEnv
: Virtualenv y Conda que no suelo utilizar.
Instalación:
brew install python <--- (También nos instala pip)
brew install pipenv
source ~/.zshrc
Cuando instalamos Homebrew (en un paso anterior) ya habíamos modificado el PATH en ~/.zshrc
. Homebrew deja los ejecutables en /usr/local/
en Mac’s Intel y en /opt/homebrew
en Mac’s ARM. Creo un par de alias, de modo que al ejecutar python
o pip
en realidad se ejecuten las últimsa versiones de Homebrew.
# Añado al final de ~/.zshrc
# Mac ARM
alias python="/opt/homebrew/bin/python3"
alias pip="/opt/homebrew/bin/pip3"
# Mac Intel
#alias python="/usr/local/bin/python3"
#alias pip="/usr/local/bin/pip3"
Compruebo las versiones
python --version
Python 3.11.3
pip --version
pip 23.0.1 from /opt/homebrew/lib/python3.11/site-packages/pip (python 3.11)
pipenv --version
pipenv, version 2023.3.20
Voy a crear un mini proyecto en Python, con un único fuente llamado main.py
bajo un entorno virtual preparado con pipenv
. Recuerda que debes instalar las librerías necesarias con pipenv
siempre desde el directorio de tu proyecto. En este ejemplo uso la librería requests
.
cd Desktop
mkdir proyecto
cd proyecto
pipenv install requests
pipenv lock
Copia el código siguiente, ejecuta cat > main.py
, pégalo y sal: ⌘V, ⮐, ⌃D
import requests
response = requests.get('https://httpbin.org/ip')
print('Tu dirección IP es: {0}'.format(response.json()['origin']))
Ejecuta la prueba de concepto
$ pipenv run python main.py
Ya tienes python
instalado y funcionando. Podemos borrar el directorio de pruebas.
cd ~/Desktop
rm -fr proyecto
Dejo aquí algunas recomendaciones para integrar Visual Studio Code y Python
Recomendado: Advanced Visual Studio Code for Python Developers |
MacOS ya trae Ruby, pero voy a instalar la última versión con Hombrew en paralelo. Necesito Bundler
y Jekyll
(ver más adelante) para trabajar en mi blog en local (más info aquí). Ruby es un lenguaje de programación interpretado, reflexivo y orientado a objetos, creado por el programador japonés Yukihiro “Matz” Matsumoto, quien comenzó a trabajar en Ruby en 1993, y lo presentó públicamente en 1995.
Instalación:
brew install ruby
Ruby no se asocia directamente al directorio de instalación de Homebrew al terminar de instalarlo y el motivo es que podría entrar en conflicto con la instalación de Ruby que trae el MacOS. En mi caso sí que quiero que se ejecute este nuevo Ruby así que añado su PATH en el fichero .zshrc
y también el sitio donde voy a instalar las futuras “gemas” (~/.gems/bin
).
# LuisPa: Añado el path de Ruby y de las futuras Gemas a mi fichero .zshrc
# Versión para Mac ARM
export PATH="/opt/homebrew/opt/ruby/bin:~/.gems/bin:$PATH"
# Versión para Mac Intel
#export PATH="/usr/local/opt/ruby/bin:~/.gems/bin:$PATH"
Para poder instalar gem’s sin necesidad de ser root
(es decir sin sudo
) y que se instale todo en un directorio de mi usuario, creo el directorio ~/.gems
y modifico ~/.zshrc
:
mkdir ~/.gems
~/.zshrc
export GEM_HOME=~/.gems
export PATH=~/.gems/bin:$PATH
Recuerda salir de iTerm y volver a entrar o ejecutar source ~/.zshrc para que encuentre los nuevos ejecutables |
Los necesito para trabajar con mi blog en local. Jekyll es un generador simple para sitios web estáticos con capacidades de blog (creas ficheros markdown y él te genera el HTML). Está escrito en Ruby por Tom Preston-Werner (cofundador de GitHub) y es rapidísimo. Bundler es un gestor de paquetes de software que va a facilitar el trabajo con Jekyll y sus dependencias.
Instalación:
gem install jekyll bundler
Nota1: Se instalan en /Users/luis/.gems/bin/jekyll , así que es muy importante que hayas actualizado tu PATH en el paso anterior. |
Nota2: Al terminar la instalación me da un mensaje: A new release of RubyGems is available: 3.4.10 → 3.4.12 y propone que ejecute gem update --system 3.4.12 . Lo ignoro, voy a seguir los procesos de actualización que haga brew cuando toque |
Una vez que tengo todo lo anterior instalado hago una prueba de concepto:
jekyll new test
New jekyll site installed in /Users/luis/test.
cd test
bundle add webrick
bundle exec jekyll serve
Desde un browser conecto con http://127.0.0.1:4000/ y veo que funciona!!
Node.js es un entorno en tiempo de ejecución multiplataforma, de código abierto, para servidor, basado en JavaScript, asíncrono, con E/S de datos en una arquitectura orientada a eventos y basado en el motor V8 de Google. Fue creado con el enfoque de ser útil en la creación de programas de red altamente escalables, como por ejemplo, servidores web.
Podría instalar Node.js desde su sitio oficial, pero implica utilizar sudo
. Si lo instalo con Homebrew lo tengo en el usuario, no tengo que tocar el PATH y además es más fácil instalar paquetes con NPM.
Instalación:
brew install node
node -v
v19.9.0
npm -v
9.6.3
Vamos a hacer un ejemplo super sencillo:
MongoDB es un sistema de base de datos NoSQL, orientado a documentos y de código abierto. En lugar de guardar los datos en tablas, tal y como se hace en las bases de datos relacionales, MongoDB guarda estructuras de datos BSON (una especificación similar a JSON) con un esquema dinámico, haciendo que la integración de los datos en ciertas aplicaciones sea más fácil y rápida
Instalo MongoDB 6.0 Community Edition en macOS utilizando Homebrew (fuente). Uso un tap
, solo se hace una vez. Consiste en añadir un repositorio (externo) a la lista de sitios desde donde instala Homebrew.
Preparar la instalación:
brew tap mongodb/brew
brew update
Instalación (incluye el servidor mongod
, el mongos sharded cluster query router
y la shell mongosh
):
brew install mongodb-community@7.0
Intel | ARM | |
---|---|---|
Configuración | /usr/local/etc/mongod.conf | /opt/homebrew/etc/mongod.conf |
Log | /usr/local/var/log/mongodb | /opt/homebrew/var/log/mongodb |
Datos | /usr/local/var/mongodb | /opt/homebrew/var/mongodb |
Ejecutar MongoDB
brew
brew services start mongodb-community@7.0
brew services stop mongodb-community@7.0
Si Mac OS no deja abrir mongodb o mongosh por un tema de seguridad: Preferencias -> Security and Privacy pane > Gemeral > mongod Open Anyway or Allow Anyway
Comprobar que arrancó y escucha en localhost
en el puerto por defecto 127.0.0.1:27017
netstat -na|grep -i 27017
tcp6 0 0 ::1.27017 *.* LISTEN
tcp4 0 0 127.0.0.1.27017 *.* LISTEN
a3f97c9f1c2bb4f1 stream 0 0 a3f97cad866b9521 0 0 0 /tmp/mongodb-27017.sock
Y pdemos monitorizar el Log
tail -f /opt/homebrew/var/log/mongodb/mongo.log
Programa de ejemplo
Te dejo una referencia a un pequeño proyecto en GitHub para que puedas probar npm
y mongod
.
Jupyter Lab es una aplicación web que permite codificar, ejecutar y “documentar”. Esta última es una de las partes más interesante del proyecto, puedes tener documentación y código a la vez y que se ejecute.
He documentado el proceso en otro apunte, más antiguo. La parte de Python puedes ignorarla porque la de aquí es más moderna, pero el resto te puede valer: Python y JupyterLab en MacOS.
Nota: Este punto solo me ha funcionado en un Mac on chip Intel, así que estás avisado, de momento no he encontrado cómo emular un Linux o Windows ARM con VirtualBox y Vagrant instalados en un Mac con Apple Silicon (ARM) |
VirtualBox es un software de virtualización que permite isntalar sistemas operativos adicionales, conocidos como «sistemas invitados, guest o máquinas virtuales», dentro de tu sistema «anfitrión» (en mi caso el MacOS), cada uno con su propio ambiente virtual. Puedes crear máquinas virtuales basadas en FreeBSD, GNU/Linux, OpenBSD, OS/2 Warp, Windows, Solaris, MS-DOS, Genode y muchos otros.
Vagrant permite crear y configurar entornos de desarrollo virtuales, ligeros y reproducibles, creando máquinas virtuales. Usa VirtualBox como virtualizador de forma nativa.
Podemos instalar ambos para montarnos Servidores virtuales para acompañar a nuestros desarrollos de software.
No dejes de leer el apunte Vagrant para desarrollo.
Dejo aquí una lista de programas que suelo instalar en mi portatil. Puedes instalar varios a la vez, poniendo más de uno en la lína de comandos (separados por espacio).
Instalación:
brew install <programa(s)>
Programa | Descripción |
---|---|
ffmpeg | Una solución completa y multiplataforma para grabar, convertir y transmitir audio y vídeo. |
iperf3 | Para hacer pruebas en redes. El caso de uso es crear flujos de datos TCP y UDP y medir el rendimiento de la red. |
jq | Filtrar, buscar y mostrar de forma “bonita” el resultado de un JSON en lugar de en una sola línea. |
knock | Cliente para hacer “Port Knocking” (llamar a la puerta), una técnica para aplicar seguridad a nuestro servidor. |
Normalmente nos olvidamos de mantener lo que instalamos, así que saber cómo hacer actualizaciones y reparaciones es interesante. Suelo actualizar periódicamente, mínimo una vez al mes, aunque no instale nada nuevo. Compruebo que está todo al día. Los programas que no menciono en esta sección se actualizan automáticamente desde AppStore o sus propias opciones GUI.
brew update && brew upgrade # Actualización estándar de homebrew
brew update && brew update
brew doctor # Herramienta de autodiagnóstico de Homebrew.
brew --version # Comprobar la versión
brew list # Ver que está instalado
brew cask list # Ver que cask’s están instalados
brew leaves # Top level instalados (es lo más interesante)
gem cleanup && gem pristine --all # Reparar problema con el comando gem
Systemd es un sistema utilizado en linux para administrar el arranque y los procesos del sistema. Sus “unidades” (units
) son archivos de configuración que describen los procesos y servicios que systemd
administra.
Una de estas unidades es la systemd.socket
, que arranca el daemon correspondiente cuando se establece una conexión a través de un socket con el equipo. Un socket es una forma de comunicación entre procesos en red o en el sistema. Al crear una unidad de este tipo le estamos pidiendo que escuche en un socket determinado y si recibe una conexión que inicie un servicio específico.
Por ejemplo, si creamos apache.socket
, le pedimos a systemd que inicie el servidor Apache en cuanto se reciba la primera petición de conexión puerto 80
(estándar para solicitudes web). Apache solo se ejecutará cuando sea necesario, lo que puede ahorrar recursos del sistema. Podríamos hacer lo mismo creando ssh.socket
, le pedimos a systemd
que inicie el servicio de OpenSSH solo cuando reciba una petición de conexión a través del puerto 22.
Debian como Ubuntu han cambiado la forma de configurar OpenSSH y ahora utilizan systemd socket activation
. Si queremos cambiar el puerto estándar ya no se hace en el fichero /etc/ssh/sshd_config
. De hecho, tampoco recomiendo modificando la unidad /etc/systemd/system/sockets.target.wants/ssh.socket
(no sobreviviría a un apt update
). Lo correcto es crear el fichero siguiente:
/etc/systemd/system/ssh.socket.d/ssh-override.conf
mkdir -p /etc/systemd/system/ssh.socket.d/
cat > /etc/systemd/system/ssh.socket.d/ssh-override.conf << EOF
[Socket]
ListenStream=
ListenStream=12345
EOF
systemctl daemon-reload
systemctl restart ssh.socket
La línea ListenStream=
hace que deje de escuchar en el puerto 22
y la segunda ListenStream=12345
es el puerto por el que va a escuchar a partir de ahora.
Si rearrancas el equipo (sin ninguna conexión SSH) y pudieses conectar a su consola (en directo o vía Serial, por ejemplo con virsh
) podrás comprobarlo mejor:
root@debian:~# systemctl status ssh.socket
* ssh.socket - OpenBSD Secure Shell server socket
Loaded: loaded (/lib/systemd/system/ssh.socket; enabled; vendor preset: enabled)
Drop-In: /etc/systemd/system/ssh.socket.d
`-ssh-override.conf
Active: active (listening) since Wed 2023-04-19 19:17:21 CEST; 16s ago
Listen: [::]:12345 (Stream)
Accepted: 0; Connected: 0;
CGroup: /system.slice/ssh.socket
Apr 19 19:17:21 npm systemd[1]: Listening on OpenBSD Secure Shell server socket.
root@debian:~# netstat -tpuln| grep '22\|12345'
tcp6 0 0 :::12345 :::* LISTEN 1/init
root@debian:~# ps -ef | grep -i "[s]shd"
root@debian:~#
Comparto mi networking doméstico con la opción de llamar a la puerta para accesos puntuales desde Internet. Las redes caseras de hoy en día acaban soportando múltiples servicios y con la irrupción de la domótica se complica la cosa, así que he decidido documentarlo para no perderme en el futuro.
El número de dispositivos crece y mantener la red de un hogar inteligente y automatizado se convierte en una prioridad. Dedico el apunte a esos Geeks o Techys que, como yo, llevamos tiempo metidos en la complicación del networking en una red casera domotizada.
El objetivo es que el diseño soporte muchos cacharros variopintos, vía LAN/WiFi, que se puedan usar certificados con https
, poder entrar llamando a la puerta desde intenet y ya por pedir, que la domótica siga funcionando si cae internet o la WiFi (que haya unos mínimos).
¿Cuanto puede crecer tu red? pues sin darte cuenta, sumando switches, AP’s, servidores físicos, virtuales, sensores, relés, actuadores, clientes, etc. el otro día veía 122 IP’s únicas 😱 en mi router Linux.
Empiezo la casa por el tejado describiendo:
El 99% de los hogares usa el router del Proveedor de Servicios (Operadora) y cuelga todo debajo, traen varios puertos y un punto de acceso embebido, suena bien.
Cuando tienes conocimientos de routing y switching mi recomendación es poner detrás un router propio + switch(es) + AP(s) y desactivar el WiFi del Proveedor 😆. El beneficio principal es que pasas a tener un control total, incluso permite añadir extras: por ejemplo lo de llamar a la puerta abriendo puertos bajo demanda, levantar túneles ipsec, silenciar los pings (solo si conectas directamente al ONT), identificar intentos de ataques, control del tráfico VoIP e IPTV y otros.
Partiendo de esta premisa, tengo tres opciones.
192.168.1.0/24
).
¿Cuál recomiendo?
Si tienes el ONT, es la mejor opción. Llevo usándolo años, cuando Movistar lo instalaba junto con el router. Por desgracia hoy en día no se puede pedir en un alta nueva.
Modo bridge - si puedes y tu router lo soporta sería mi segunda opción. Ojo!, hay routers (p.ej GPT-2841GX4X5) que no soportan esta modalidad.
Modo estándar - sería la última si no me quedase más remedio. Ojo!, vale para todo lo que explico en este apunte pero me incomoda el uso de doble port forwarding, el posible doble NAT o tener que poner las estáticas a mi intranet, tener que abrir demasiados puertos y la pérdida del control total de VoIP e IPTV.
En mi caso tengo ONT y uso Linux sobre máquina virtual, con su routing nativo e iptables
. Deniego todo el tráfico de entrada y hago Masquerade en salida. Tienes otras opciones más fáciles, como usar OpenWrt, IPFire o pfSense (solo intel). También puede irte a hardware dedicado estilo Mikrotik o router neutro. Por cierto, si te gusta OpenWrt o IPFire hay una opción barata con Raspberry Pi 4B con 1GB.
Volviendo a mi instalación (la de la derecha en la figura). El hardware que uso para mi máquina virtual es un Host NUC de Intel. Siempre te hará falta un Switch (mínimo uno de 8xGbe con soporte de VLAN’s e IGMP) y AP’s con soporte de Roaming para la WiFi.
En el gráfico dejo cómo sería la conexión física en la modalidad “Estándar” (no es mi caso). Si lo conectas así yo pondría el Router del Operador a un puerto de Acceso de mi switch y el Host con mi Router a un puerto TRUNK. Cearía una VLAN exclusiva para que puedan verse el router del Operador con el mío (por ejemplo VLAN 192
) y subnet 192.168.1/24
y dejaría la VLAN 100
para mi casa y mi propia subnet 192.168.100/24
. No es obligatorio hacer Masquerade en la modalidad Estándar, pero yo lo prefiero (aunque haya doble NAT en salida) porque no quiero dar de alta todas las rutas estáticas en el router del operador.
En mi caso (que conecto directo al ONT), a nivel físico tanto mi Host como el ONT a puertos TRUNK del Switch (puerto del ONT vlan’s 2,3,6 y puerto del Host vlan’s 2,3,6,100). Hablaré PPPoE
por la vlan6
y la VLAN 100
para mi casa y mi propia subnet 192.168.100/24
.
Como distribución Linux me he decantado por Ubuntu 22.04 LTS, robusto y fácil de mantener. Lo instalé usando la Plantilla de VM en Proxmox (luego explico qué es Proxmox). Concedo acceso a las vlan’s 2,3,6,100. Una vez que tengo activo mi Linux termino su instalación con algunas herramientas, eliminando cloud-init
y preparando el fichero netplan
.
root@muro:~# apt install qemu-guest-agent
root@muro:~# apt install nano net-tools iputils-ping tcpdump ppp
:
root@muro:~# rm -fr /etc/cloud
root@muro:~# apt purge -y cloud-init
root@muro:~# rm /etc/netplan/50-cloud-init.yaml
Netplan para la configuración de red.
root@muro:~# cat /etc/netplan/50-muro.yaml
#
# Ejemplo de fichero netplan para Ubuntu Linux como VM
# en un Host que está conectado a un puerto TRUNK en el Switch.
#
# Recibo mi interfaz eth0 en modo TRUNK y habilito las
# vlans que necesito para hacer de Router con Movistar
#
# En este ejemplo NO configuro las vlans 2 y 3 (VoIP/IPTV)
#
network:
ethernets:
eth0:
dhcp4: no
vlans:
vlan6: <== VLAN con el ONT (aquí irá el PPPoE)
id: 6
link: eth0
macaddress: "52:54:12:34:56:78"
dhcp4: no
vlan100: <== VLAN principal
id: 100
link: eth0
macaddress: "52:54:12:12:12:12" <== Debe coincidir con la config de VM de Proxmox
addresses:
- 192.168.100.1/22 <== Mi IP en la intranet
nameservers:
addresses:
- 192.168.100.224 <== El DNS/DHCP server
search:
- tudominio.com
vlan33: <== Un ejemplo de VLAN extra
id: 33
link: eth0
macaddress: "52:54:AB:CD:EF:33"
addresses:
- 192.168.33.1/24
version: 2
Importante en el Software de Virtualización del Host (en mi caso Proxmox: muro -> hardware -> network device
) configuro la tarjeta de red de la VM con la misma MAC que puse en netplan
(52:54:12:12:12:12
).
Verifico que el router Linux reciba el Trunk. En el caso de Proxmox basta con dejar vacío el campo VLAN Tag
. Ah! también recomiendo quitar la opción Firewall
en las opciones. No se porqué, pero me dió problemas con IGMP
mullticast a pesar de tenerlo desactivado a nivel global.
Ficheros que configuro alrededor de PPP
, NAT
e iptables
. Recuerda que son solo una referencia y que debes revisarlos para adaptarlos a tu instalación.
Recuerda habilitarlos. También dejé unidades para el arranque de PPPoE
, una que espera a que se establezca la sesión y otra que no. En mi caso uso la que espera (ppp_wait@movistar.service
).
# chmod 755 /root/firewall/*.sh
# systemctl enable internet_wait.service
# systemctl enable firewall_1_pre_network.service
# systemctl enable firewall_2_post_network.service
# systemctl enable ppp_wait@movistar.service
Tu proveedor de servicios puede cambiar la IP que te asigna vía PPPoE en cada arranque o reconexión. Si quiero tener un nombre fijo (p.ej. miservidor.tudominio.com
) para saber a dónde llamar desde Internet necesito tener un dominio propio y que mi proveedor DNS soporte alguna forma de hacer “Dominio Dinámico”.
Es un servicio que permite actualizar mi nueva IP en mi dominio en Internet. Hay proveedores de DNS dinámico como DynDNS, No-IP, DuckDNS. Probablemente tu proveedor DNS también lo soporte, como es mi caso.
Yo tengo mi dominio alojado en cdmon.es
y soportan esta función (documentación para actualizar la IP). A modo de ejemplo estos son los servicio en systemd
y un pequeño script
que uso en mi router Linux.
# chmod 755 /usr/bin/cdmon_update.sh
# systemctl enable cdmon_update.timer
Cada 5 minutos mira a ver si ha cambiado la IP y si es así la actualiza. Tengo dados de alta varios registros de tipo 'A'
resolviendo a la misma IP Pública de mi casa:
ha.tudominio.com
,ssh.tudominio.com
,Resolución de nombres desde internet:
Luego veremos cómo lo hago en mi Intranet. Te anticipo que cuento con un servidor DNS interno que sirve el mismo dominio (tudominio.com
) en local, entregando IP’s privadas de casa. Este donde esté (internet o intranet) las App’s siempre saben cómo llegar a los servicios caseros.
Durante años he usado varias técnicas para protegerme de ataques y desde hace tiempo he optado por no abrir ningún puerto. Mi router descarta/tira todos los paquetes que llegan desde internet, siempre. Bueno, casi siempre. Hay un par de servicios a los que sí que me gustaría poder acceder desde Internet: levantar un túnel ssh
o ipsec
para hacer una administración puntual y acceso a mi servidor Home Assistant para la domótica.
Descubrí la técnica del Port Knocking (llamar a la puerta) y me gustó mucho. Se trata de un App que envia 3 o 4 paquetes especiales al Router/Firewall para que reconozca que estás “llamando a la puerta” y si llamas como a él le gusta te abre temporalmente (solo a la IP desde la que llamo) el puerto del servicio que quieras consumir.
Uso PortKnock (App para smartphone): lanza la petición (1) Ábreme el puerto para llegar a Home Assistant (envía una serie de paquetes con una cadencia determinada), el router/firewall se da por enterado y abre durante un rato el puerto p.ej. 28123
. (2) Home asistant pueda entrar.
Podemos configurar cuántos toques se dan a la puerta y a qué puertos. Deben coincidir en el servidor y cliente. Por ejemplo, dar tres toques cada segundo sería: Envía un SYN
al puerto #1, espera un segundo, un SYN
al puerto #2, espera otro segundo y envía un último SYN
al puerto #3. En ese instante nuestro daemon knockd
ejecuta lo que queramos, que será típicamente iptables
para abrir el puerto (28123
en este ejemplo).
Veremos que HomeAssistant siempre conecta con ha.tudominio.com:28123
, en casa o en internet. Si estoy en casa mi DNS Server resuelve con la IP privada correcta. Así no tengo que cambiar su configuración.
Instalación y activación
root@muro:~# apt install knockd
:
root@muro:~# systemctl enable knockd
Aquí tienes un ejemplo del fichero de configuración, revísalo para adaptarlo a tu instalación.
Para montar un Servidor de Acceso IPSec uso OpenVPN que sigue siendo la mejor solución, es fiable, rápido y seguro. Como cliente utilizo Passepartout.
## ACCESO EXTERNO a mis Servicios
## IPSec como Servidor: XXXXXX (Cambiar por el puerto donde escuchas en ipsec)
# Dejé de usar esta opción para pasar a usar knockd.
#iptables -N CH_OPENPORTS
#iptables -A INPUT -p udp -m udp -m multiport --dports XXXXXX -m conntrack --ctstate NEW -j CH_OPENPORTS # OpenVPN en UDP
#if [ "${LOGSERVICIOS}" = "yes" ] || [ "${LOGALL}" = "yes" ]; then
# iptables -A CH_OPENPORTS -j $LOGGING "CH_OPENPORTS -- OK "
#fi
#iptables -A CH_OPENPORTS -j ACCEPT
Este sería un ejemplo de configuración a modo de referencia, recomiendo revisarlo.
Te dejo un par de apuntes (algo antiguos pero válidos) como referencia para la instalación de OpenVPN.
Vamos bajando por la casa y llegamos a la Intranet, cosas que he montado y algunos consejos humildes después de muchas experiencias negativas:
La red física: Dos switches principales, de 24 y 10 puertos de 1Gbe y luego switches pequeños en los cuartos. Tardé años aprovechando obras para ir tirando cables 🤗. Recomiendo encarecidamente cablear todo lo posible. No os fiéis del alcance y potencia de los AP’s WiFi, un muro de carga o ciertos materiales pueden destrozarte la cobertura en un santiamén.
También desaconsejo (mucho) WiFi MESH, ese día que “pixela” el video, que falla la domótica (WiFi), que tus móviles se desasocian, que Homekit, Alexa o Google se va, en fin, te acordarás del cable!. Ya se que hay muchos casos donde no podemos pasar cable (o no nos dejan), pero lo recuerdo porque lo he sufrido.
Si tienes la fortuna de casa nueva o una obra, no lo dudes, cable a “todos” los espacios de la casa con CAT6 minimo. También a techos o paredes donde irán los AP’s (mejor alimentarlos con PoE).
Cuidado también con equipos WiFi demasiado inteligentes que montan redes privadas en la WiFi y te obligan a hacer NAT. Son equipos para consumo que desaconsejo; suelo huir de tecnologías que no te permite configurar transparentemente como tu quieras.
Servicios de Red: Tengo un Servidor DNS/DHCP sobre PiHole, un controlador para los AP’s, un Proxy Inverso y he probado algunas herramientas (opcionales) de monitorización como Gatus, Uptime Kuma, LibreNMS, Netdisco. Todo como VM/LXC’s en mi(s) Host(s).
Servicios de domótica: El networking de la casa da conectividad a Home Assistant, Node-RED, Zigbee2MQTT, Mosquito, Grafana e InfluxDB, como VM/LXC’s en mi(s) Host(s). Permiten controlar y automatizar diferentes dispositivos en el hogar, como la iluminación, los sistemas de climatización, sensores, luces, enchufes, relés, las cerraduras y los electrodomésticos. La gran mayoría utilizan WiFi y algunos Zigbee (esta red no la cubro en este apunte).
Ya lo he anticipado antes, utilizo una mezcla de máquinas virtuales y/o contenedores (Docker o LXC). Durante años usé un Host Linux con KVM/QEMU y hace poco cambié a Proxmox VE.
Poner todo los huevos en el mismo cesto no es aconsejable y los Tecky’s lo sabemos bien. De hecho, cuando se me caía el “host” con mis VM’s me quedaba sin casa 😂 y me caía la bronca. Hace poco he evolucionado a un Cluster Proxmox VE con 2xNUC’s + 1xPi3B para hospedar las máquinas virtuales, contenedores LXC o Docker con servicios. La Pi es lo más barato que tenía para que el Cluster “negocie bien” la tolerancia a fallos, no tiene servicios.
Utilizo Pi-hole como servidor DNS y DHCP. Para DHCP uso un rango dinámico y muchas IP’s fijas (por MAC). Mi dominio interno es exactamente el mismo que el externo: tudominio.com
.
Cuando se pide desde Internet un nombre bajo tudominio.com
se entrega mi IP pública (que actualizo dinámicamente). Cuando se lanza una consulta DNS desde la Intranet siempre se hace a PiHole, si es un nombre bajo tudominio.com
entregará una IP privada directamente, si es cualquier otro nombre irá a averiguarlo a su siguiente nivel (DNS Servers de Movistar por ejemplo).
Te recomiendo consultar este apunte sobre Pi-hole casero para entender mejor cómo funciona. En casa uso una CMDB muy simple en un fichero excel para llevar el control de MAC->IP privada y actualizo un par de ficheros de PiHole cuando hay cambios.
Un proxy inverso es un servidor que actúa como intermediario entre los usuarios y los servidores web que hay tras él. Cuando se solicita un sitio web, en lugar de enviarle la solicitud, se envía al proxy inverso y este a su vez al servidor web. Permite que el navegador use https
con el proxy inverso y este use http
con el Web original.
Podré usar https
con certificados válidos generados con Let’s Encrypt, con un certificado para cada nombre del servidor Web al que quiero llegar. Todas mis sesiones https
quedan centralizadas a través de él.
Configuración DNS
Veamos con ejemplos la configuración. Tengo los servicios git, grafana y home assistant. Quiero poder llegar vía https
a los tres y además ssh
al servidor git.
A
para cada uno y todos resuelven a mi misma IP pública (w.x.y.z), que actualizo dinámicamente. git.tudominio.com w.x.y.z
grafana.tudominio.com w.x.y.z
ha.tudominio.com w.x.y.z
git.tudominio.com 192.168.100.243 <- VM de mi Proxy Inverso (NPM)
grafana.tudominio.com 192.168.100.243 <- VM de mi Proxy Inverso (NPM)
ha.tudominio.com 192.168.100.243 <- VM de mi Proxy Inverso (NPM)
:
vm-git.tudominio.com 192.168.100.XXX <- VM del servidor Gitea
vm-grafana.tudominio.com 192.168.100.YYY <- VM del servidor con grafana e influxdb
vm-ha.tudominio.com 192.168.100.ZZZ <- VM de HASS (Home Assistant)
La foto final quedaría así:
Configuración Proxy Inverso
Utilizo Nginx Proxy Manager (NPM) como Proxy Inverso, porque es rápido, ligero y soporta lo que necesito, https
con gestión de Certificados SSL vía Let’s Encrypt y Port Forwarding (lo llama Streams).
Lo instalo como Contenedor LXC en Proxmox VE, mediante un Helper Script. Ocupa muy poca memoria y su arranque es ultra rápido.
La instalación se hace desde la consola de uno de mis Host:
root@pve-sol:~# LANG=C bash -c "$(wget -qLO - https://github.com/tteck/Proxmox/raw/main/ct/nginxproxymanager.sh)"
Configuración de Proxy Hosts
Proxy Hosts creados a través de su interfaz Web.
Ejemplo de Proxy Host de Home Assistant.
Domain Name | Nombre con el que se accede al servicio vía https , por ejemplo ha.tudominio.com . Por omisión el puerto por el que escucha es el estándar: 443 (excepto Grafana, ver Parámetros avanzados). Estamos hablando de la conexión entre el Navegador y NPM |
Scheme | La forma en la que se llega al servidor web que hay detrás, típicamente será http . Esta es la conexión entre NPM y el Web Server |
Forward Hostname/IP | Nombre del servidor web que hay detrás o su IP, por ejemplo vm-ha.tudominio.com o su IP 192.168.100.ZZZ (yo uso la IP) |
Forward Port | Número de puerto por el que escucha el servidor web que ha detrás, por ejemplo 8123 |
Websockets Support | Siempre lo activo. No suelo activar Cache Assets ni Block Common Exploits |
Custom Locations | No añado nada |
SSL | Aquí añadiré el Certificado de ha.tudominio.com más adelante, cuando lo pida a Let’s Encrypt en el siguiente paso. Siempre activaré la opción Force SSL |
Advanced | No añado nada, excepto para Home Asssistant y Grafana, ver Parámetros avanzados más adelante |
Esta es la configuración de Certificados con Let’s Encrypt. Para poder crear y renovar los certificados necesitas que Let’s Encrypt valide que eres quien dices ser. Primero tu proveedor DNS debe resolver correctamente el subdominio sobre el cual estás solicitando el certificado (en este ejemplo de Home Assistant sería ha.tudominio.com
). Segundo y más importante, confirmarlo con uno de los dos métodos siguientes.
Método DNS Challenge: Es el mejor, no necesitas abrir ningún puerto en tu router. Tu proveedor DNS tiene que estar en la lista de los soportados por Let’s Encrypt. Si no está ni tampoco puedes crear registros TXT dinámicamente, tendrás que usar el método manual.
Método Manual: Me fuerza a abrir temporalmente el puerto 80. Desde Let’s Encrypt necesita hablar por ese puerto (y no otro) con un web server temporal que levanta NPM.
Yo uso el método manual y un par de scripts, open-npm-letsencrypt.sh para abrir el puerto 80
antes de solicitar o renovar el certificado y cuando acaba vuelvo a cerrarlo con close-npm-letsencrypt.sh.
Parámetros avanzados
En la VM de NPM: Proxy Hosts > Home Assistant > Advanced > Custom Nginx Configuration.
# Para que Visual Studio Server funcione correctamente.
location / {
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $http_connection;
proxy_http_version 1.1;
proxy_set_header X-Forwarded-Host $http_host;
include /etc/nginx/conf.d/include/proxy.conf;
}
En Home Assistan: Settings > System > Network: http://192.168.100.ZZZ:8123
Y en su fichero configuration.yaml
para que acepte peticiones de un proxy inverso:
## Sección en el configuration.yaml de Home Assistant
## para que funcione bien a través de un Proxy Inverso
http:
use_x_forwarded_for: true
trusted_proxies:
- 192.168.100.243 ### IP del Nginx Proxy Manager LXC ###
En la VM de NPM: Proxy Hosts > Grafana > Advanced > Custom Nginx Configuration.
# Para que NPM también escuche por el puerto `48123` además del `443` para grafana
listen 48123 ssl http2;
En la VM de Grafana: Fichero /etc/grafana/grafana.ini
[server]
protocol = http
http_port = 3000
Configuración de Stream (Port Forwarding)
Para aclarar la nomenclatura, he visto que NPM llama Stream al hecho de hacer Port Forwarding. Permite reenviar todo lo que recibe por un puerto hacia otro equipo por el mismo u otro puerto. Hago Port Forwarding del puerto 22
hacia mi servidor GIT en la Intranet.
¡¡¡ MUY IMPORTANTE !!! Antes de hacer Port Forwarding del puerto ssh (22) en el Nginx Proxy Manager es importantísimo cambiar el puerto por el que escucha su propio daemon sshd por uno alternativo o perdería el aceso vía ssh al NPM. He documentado en el apunte Socketed SSH cómo se hace (en un Contenedor LXC con Ubuntu, donde he montado mi NPM). |
¿Porqué quiero hacer Port Forwarding hacia mi servidor Git?. Pues porque quiero usar ssh
como método de comunicación para conectar con git@git.tudominio.com:...
(commits, push, pull, etc…) y además usar el mismo nombre DNS que uso para administrar mi servidor Git vía https
: https://git.tudominio.com
.
Como Git usa el puerto (fijo) 22
cuando uso la nomenclatura git@git.tudominio.com
no me queda más remedio que hacer algún truco para redirigir dicho puerto en mi NPM.
Como ya había dado de alta un Proxy Host para la parte https
solo me falta añadir el Stream para reenviar el tráfico del puerto 22
hacia mi servidor Git en la intranet.
Ahora tengo disponible https://git.tudominio.com (puerto 443)
para administrar y git@git.tudominio.com:repositorio.git (puerto 22)
para trabajar con mi Git server privado. Lo mejor es que también es compatible con el acceso, previo knock, knock, desde internet.
Proxmox VE es una plataforma de virtualización de código abierto potente y fácil de usar que permite el despliegue y la gestión de máquinas virtuales (VM’s con KVM/QEMU) y contenedores (CT’s basados en LXC). Proxmox nos ofrece Plantillas para minimizar el tiempo de creación de nuevas instancias de estas máquinas virtuales o contendores.
En este apunte me concentro en cómo crear mi propia Plantillas de máquina virtual junto con una imagen basada en la nube y cloud-init.
¿Qué es una Plantilla de VM en Proxmox?, se trata de una VM normal y corriente que convertimos en “Plantilla” y a partir de ella podemos clonar nuevas VM’s idénticas rápidamente. Si las combinamos con imágenes basadas en la nube y cloud-init conseguimos un activo muy potente para crear VM’s ágiles y ligeras.
Las imágenes basadas en la nube (VM cloud based images) son muy útiles porque tienen un tamaño mínimo y permite hacer despliegues ágiles de máquinas virtuales. Podemos bajarnos estas imágenes y configurarlas como el “disco” de nuestra VM (se trata del sistema operativo completamente instalado). ¿Cuál es la diferencia?, pues que evitamosinstalar el Sistema Operativo, estas imágenes son el “disco” ya instalado.
cloud-init
es un estandar para la personalización de instancias en la cloud (o de instancias de nuestras VMs en nuestro Proxmox). Vamos a poder parametrizar el usuario, contraseña, claves SSH y otras lindezas para ahorrarnos trabajo.
Empezamos con la creación de la VM (desde una imagen basada en la nube), luego seguiremos con su parametrización, conversión a plantilla y a clonar…
$ curl -O https://cloud-images.ubuntu.com/minimal/releases/jammy/release/ubuntu-22.04-minimal-cloudimg-amd64.img
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 285M 100 285M 0 0 70.1M 0 0:00:04 0:00:04 --:--:-- 70.2M
$ mv ubuntu-22.04-minimal-cloudimg-amd64.img ubuntu-22.04.img
Hardware -> Add -> CloudInit Drive (ide0)
.Importante: No te olvides de darle a Regenerate Image. La ventaja de cloud-init es que me ahorro configurar varias cosas en las futuras VMs. |
➜ ~ ssh root@pve-tierra.tudominio.com
Last login: Sat Apr 8 10:20:18 2023 from 192.168.100.3
root@pve-tierra:~#
# qm set 900 --serial0 socket --vga serial0
root@pve-tierra:~# pvesm list panoramix
Volid Format Type Size VMID
panoramix:iso/ubuntu-22.04-minimal-cloudimg-amd64.img iso iso 299827200
root@pve-tierra:~# pvesm path panoramix:iso/ubuntu-22.04-minimal-cloudimg-amd64.img
/mnt/pve/panoramix/template/iso/ubuntu-22.04-minimal-cloudimg-amd64.img
root@pve-tierra:~# qm importdisk 900 /mnt/pve/panoramix/template/iso/ubuntu-22.04-minimal-cloudimg-amd64.img local-zfs
importing disk '/mnt/pve/panoramix/template/iso/ubuntu-22.04-minimal-cloudimg-amd64.img' to VM 900 ...
:
transferred 2.2 GiB of 2.2 GiB (100.00%)
Successfully imported disk as 'unused0:local-zfs:vm-900-disk-0'
qemu-img
antes de importarla, pero vamos a usar qm resize
después de hacer la importación:
# qm disk resize 900 scsi0 32G
.raw
, en concreto el fichero debian-11-genericcloud-amd64.raw. La versión que elijo es la genericcloud
(la diferencia con la generic
es que la primera excluye los drivers de hardware físico, que no necesito para nada)..img
para poder subirla a mi NFS Server conectado a Proxmox
$ curl -O https://laotzu.ftp.acc.umu.se/images/cloud/bullseye/latest/debian-11-genericcloud-amd64.raw
$ mv debian-11-genericcloud-amd64.raw debian-11-genericcloud-amd64.img
Ya podemos crear todas las máquinas virtuales que queramos partiendo de la(s) Plantilla(s). Se realiza con la Función Clonar. Veamos un ejemplo con la de Ubuntu (para la de Debian es igual).
cloud-init
termina entro con mi usuario (luis
), averiguo qué IP he recibido (para futuras conexiones vía SSH), instalo qemu-guest-agent
(para controlar mejor la VM desde Proxmox) y rearranco la VM.
ip a
sudo apt install qemu-guest-agent
sudo reboot -f
genericcloud
puede correr en cualquier entorno virtual y la diferencia con la generic
es que excluye los drivers de hardware físico.Este apunte describo el proceso de instalación de una Raspberry Pi4B Rev1.5
(también probado con la Pi3B+
) con el sistema operativo Raspberry Pi OS (64bits) (basado en Debian). Normalmente uso estas Pi’s como mini servidores de propósito específico o para pruebas y laboratorios.
Lo primero es lo primero, preparar una tarjeta Micro SD con el sistema operativo, he elegido Raspbian OS Lite 64bits. No necesito la parte gráfica, voy a utilizarlo como un servidor corriendo diferentes servcios. Podemos usar cualquier método para clonar la imagen en una tarjeta SD, en mi caso he usado programa Raspberry Pi imager.
Cuando termina retiro la tarjeta y la introduzco en la Pi. Conecto la Pi a un monitor, teclado y conecto con cable ethernet al switch, para iniciar la primera fase de la instalación, donde es importante tener acceso a Internet. La Pi recibirá una dirección IP vía DHCP inicialmente.
Un rato después de arrancar la Pi empezaremos a ver una serie de menús donde hacemos la configuración básica. A continuación describo lo que configuré en mi caso:
Other -> Spanish
, Spanish
luis
Hago login con el usuario y contraseña que acabo de configurar y lo primero que voy a hacer es activar sshd
para poder conectar con la Pi a través de la red local y continuar desde ahí.
raspberrypi Login: luis
Password: <la del paso anterior>
luis@raspberrypi:~ $ sudo raspi-config
Selecciono Interface options -> SSH -> Ok, arrancará el servicio SSHD. Me salgo de raspi-config
y averiguo qué dirección IP ha recibido de la red.
$ sudo ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 192.168.1.82 netmask 255.255.255.0 broadcast 192.168.1.255
============
:
Me conecto desde mi puesto de trabajo
$ ssh luis@192.168.1.82
:
Last login: Tue Feb 21 04:29:57 2023
-bash: warning: setlocale: LC_ALL: cannot change locale (es_ES.UTF-8)
Wi-Fi is currently blocked by rfkill.
Use raspi-config to set the country before use.
luis@raspberrypi:~ $
Vuelvo a ejecutar raspi-config
para terminar de configurar múltiples aspectos importantes:
luis@raspberrypi:~ $ sudo raspi-config
System Options > hostname > "idefix"
Localisation Options > Locale >
[ ] en_GB.UTF-8 UTF-8 <---- Lo quito
[*] es_ES.UTF-8 UTF-8 <---- Lo pongo
Default Locale: es_ES.UTF-8 UTF-8
Localisation Options > Timezone > Europa, Madrid
Localisation Options > WLAN Country > ES
Advance Options > Network interface names > No
No
: Si quieres usar eth0, eth1, etc..Yes
: Si quieres usar nombres predeciblesFinish y Reboot
Por último hacemos una actualización del sistema operativo !
$ ssh luis@192.168.1.82
:
luis@idefix:~ $ sudo su -
root@idefix:~# apt update && apt upgrade -y && apt full-upgrade -y
Ya hemos terminado, tengo una Raspberry Pi perfectamente operativa, actualizada a la última versión de Raspberry OS de 64 bits.
Esta parte del proceso es opcional, a mi me gusta tener algunos ficheros y scripts de apoyo en todos los sistemas linux con los que trabajo y algunas modificaciones al sistema. Los dejo aquí como referencia.
De nuevo opcional, solo si lo necesitas, así es como se elimina IPv6, la tarjeta Wifi de la Pi y el Bluetooth. En mi caso cuando hago laboratorios de IPv4 y no lo necesito prefiero desactivarlo todo.
/boot/cmdline.txt
, añado al final de la línea ipv6.disable=1
console=serial0,115200 console=tty1 root=PARTUUID=2c310193-02 rootfstype=ext4 fsck.repair=yes rootwait ipv6.disable=1
/boot/config.txt
, añado al final del fichero dos líneas adicionales:dtoverlay=disable-wifi
dtoverlay=disable-bt
reboot
de la Pi.Normalmente dejo que la Pi trabaje con el cliente dhcp por defecto, pero a veces necesito asignarle una IP fija. No es evidente cómo hacerlo, porque depende de la versión del SO. En mi caso he configurado raspi-config
-> Avanzado -> Netowrk -> Nombres de interfaces predecibles -> No. Después modifico estos dos ficheros:
/etc/dhcpcd.conf
, añado al final lo siguiente:interface eth0
static ip_address=192.168.103.3/22
static routers=192.168.100.1
static domain_name_servers=192.168.100.224
/etc/network/interfaces
, añado al final lo siguiente:auto eth0
allow-hotplug eth0
iface eth0 inet maual
Si los quieres instalar bájate los gists y dales permiso de ejecución. Para instalarlos, a continuación un ejemplo: haz clic en el enlace (p.ej. el de /usr/bin/e
), selecciánalo todo y copia con Ctrl-C. Depués usa cat
, Intro, Ctrl-D y al volver a la línea de comandos cambia los permisos:
luis@idefix:~ $ sudo su -
root@idefix:~# cat > /usr/bin/e
:
:
root@idefix:~# chmod 755 /usr/bin/e
root
como para mi usuario.
luis@idefix:~ $ sudo mkdir /root/.nano
luis@idefix:~ $ mkdir ~/.nano
luis@idefix:~ $ sudo chmod 755 /usr/bin/e /usr/bin/confcat /usr/bin/s
El fichero /etc/sudoers.d/010_pi-nopasswd
ya viene preparado para que al usuario luis
no le pida contraseña de root y pueda ejecutar sudo
directamente.
A partir de ahora al ejecutar el comando e fichero
se arrancará el editor nano
. El editor funcionará con el esquema de teclado descrito en /etc/nanorc
. Al ejecutar s
me convertiré en root
y por último el comando confcat
muestra el contenido de archivos de texto ignorando las líneas de comentarios.