Páginas

martes, 15 de abril de 2025

Script sh Replicar Instantáneas de Conjunto de Datos ZFS desde Servidor FreeBSD Local a otra Máquina FreeBSD Externa

Fuente:

https://www.iceflatline.com/2015/07/using-zfs-replication-features-in-freebsd-to-improve-my-offsite-backups/

El autor de este sencillo e ingenioso guión es iceflatline. Contiene algunas modificaciones para adaptarlo a este laboratorio

https://gnulinuxcodigo.blogspot.com/2025/03/crear-particiones-en-disco-duro-usb-con.html

Crear el pool de respaldo zbackup

 zpool create -o ashift=12 \
-O compression=lz4 \
-O atime=off \
-O mountpoint=none \
backup /dev/gpt/zbackup

Conjuntos de datos zbackup

 sudo zfs create -o mountpoint=none zbackup/solaris
 sudo zfs create -o mountpoint=none zbackup/solaris/home
 sudo zfs create -o mountpoint=none zbackup/solaris/home/carlos
 sudo zfs create -o mountpoint=none zbackup/tormenta-confiles
 sudo zfs create -o mountpoint=none zbackup/usr/
 sudo zfs create -o mountpoint=none zbackup/usr/backup
 sudo zfs create -o mountpoint=none zbackup/usr/backup/docs
 sudo zfs create -o mountpoint=none zbackup/usr/home

Flujo de trabajo recomendado para un disco de respaldo mountpoint=none

Seguridad contra modificaciones accidentales

Evita conflictos de rutas

Comportamiento en el arranque — Con mountpoint=none ZFS no intenta montar nada del pool zbackup al arrancar, lo que acelera el boot y evita errores si el disco USB no está conectado en ese momento.

Acceso bajo demanda — Cuando se necesita recuperar algo, se monta puntualmente el dataset de interés, se hace lo que se necesita, y luego se desmonta.

Los scripts no se ven afectados — zfs receive escribe directamente al dataset sin necesidad de que esté montado. mountpoint=none no interfiere en absoluto con zfs send/receive.

carlos@tormenta:~ % zfs list -r zbackup
zbackup                            48.9G  1.71T  4.86M  none
zbackup/solaris                    40.8G  1.71T    96K  none
zbackup/solaris/home               40.8G  1.71T    96K  none
zbackup/solaris/home/carlos        40.8G  1.71T  39.9G  none
zbackup/tormenta-confiles           800K  1.71T   800K  none
zbackup/usr                        8.16G  1.71T   104K  none
zbackup/usr/backup                 7.80G  1.71T   104K  none
zbackup/usr/backup/docs            7.80G  1.71T  7.80G  none
zbackup/usr/home                    368M  1.71T   132M  none
#!/bin/sh
### BEGIN INFO
# PROVIDE:
# REQUIRE:
# KEYWORD:

### INICIO DEL GUION
# Estas variables se nombran primero porque están anidadas en otras variables.
snap_prefix=snap
retention=15

# Se necesitan rutas completas a estas utilidades al ejecutar el script desde \
cron.
date=/bin/date
grep=/usr/bin/grep
sed=/usr/bin/sed
sort=/usr/bin/sort
xargs=/usr/bin/xargs
zfs=/sbin/zfs

src_0="zroot/home/carlos"
dst_0="zbackup/solaris/home/carlos"
host="root@192.168.88.160"

# Usar $date en lugar de date para consistencia con rutas absolutas.
today="$snap_prefix-`$date +%Y%m%d`"
yesterday="$snap_prefix-`$date -v -1d +%Y%m%d`"
snap_today="$src_0@$today"
snap_yesterday="$src_0@$yesterday"

# Patrón grep con sufijo numérico para evitar falsos positivos.
snap_old=`$zfs list -t snapshot -o name \
  | $grep "${src_0}@${snap_prefix}-[0-9]" \
  | $sort -r \
  | $sed 1,${retention}d \
  | $sort \
  | $xargs -n 1`

log=/home/carlos/cronlog

# Todo el pipeline de listado remoto corre en tormenta vía SSH.
snap_old_dst_0=`ssh $host "$zfs list -t snapshot -o name \
  | grep '${dst_0}@${snap_prefix}-[0-9]' \
  | sort -r \
  | sed 1,${retention}d \
  | sort"`

# Crea una línea en blanco entre la entrada de registro anterior y esta.
echo >> $log

# Imprimir el nombre del script.
echo "zfsrep.sh" >> $log
# Imprime la fecha de hoy.
$date >> $log
# Crea una línea en blanco.
echo >> $log

# Buscar instantánea de hoy y, si no la encuentra, créala.
if $zfs list -H -o name -t snapshot \
  | $sort \
  | $grep "${snap_today}$" > /dev/null
then
	echo "La instantánea de hoy '$snap_today' ya existe." >> $log
else
	echo "Tomando la instantánea de hoy: $snap_today" >> $log
	$zfs snapshot -r $snap_today >> $log 2>&1
fi

echo >> $log

# Replicar el snapshot diario (ayer) o mostrar error si falta.
if $zfs list -H -o name -t snapshot \
  | $sort \
  | $grep "${snap_yesterday}$" > /dev/null
then
	echo "La instantánea de ayer '$snap_yesterday' existe. Continuando \
    con la replicacion..." >> $log
	$zfs send -R -i $snap_yesterday $snap_today \
	  | ssh $host $zfs receive -vuF -x mountpoint $dst_0 >> $log 2>&1
	echo >> $log
	echo "Replicacion completada." >> $log
else
	echo "Error: Replicacion no completada. Falta la instantánea de \
    ayer." >> $log
fi

echo >> $log

# Eliminar instantáneas locales más antiguas que el valor asignado a retention.
echo "Intentando destruir instantáneas antiguas $src_0..." >> $log

if [ -n "$snap_old" ]
then
	echo "Destruyendo las siguientes instantáneas antiguas:" >> $log
	echo "$snap_old" >> $log
	$zfs list -t snapshot -o name \
	  | $grep "${src_0}@${snap_prefix}-[0-9]" \
	  | $sort -r \
	  | $sed 1,${retention}d \
	  | $sort \
	  | $xargs -n 1 $zfs destroy -r >> $log 2>&1
else
	echo "No se pudo encontrar ninguna instantánea local para \
    destruir." >> $log
fi

echo >> $log

# Purgar snaps remotos > retention
# Todo el pipeline, incluido zfs destroy, corre en tormenta vía SSH.
echo "Intentando destruir instantáneas antiguas $dst_0..." >> $log

if [ -n "$snap_old_dst_0" ]
then
	echo "Destruyendo las siguientes instantáneas antiguas en $host:" >> $log
	echo "$snap_old_dst_0" >> $log
	ssh $host "$zfs list -t snapshot -o name \
	  | grep '${dst_0}@${snap_prefix}-[0-9]' \
	  | sort -r \
	  | sed 1,${retention}d \
	  | sort \
	  | xargs -n 1 $zfs destroy -r" >> $log 2>&1
else
	echo "No se pudo encontrar ninguna instantánea remota para \
    destruir." >> $log
fi

# Marcar el fin del script con un delimitador.
echo "**********" >> $log

### FIN DEL SCRIPT

Luego, agregue una tarea a la tabla cron bajo la cuenta del usuario. El script se ejecuta todos los días a las 22:00 (hora local):

# Ejecuta script backup cada día a las 22:00
0 22 * * * /home/carlos/bin/zfsrep.sh

Las entradas del archivo /home/carlos/cronlog se verán así:

**********

zfsrep.sh
Tue Apr 15 09:45:19 CEST 2025

Tomando la instantánea de hoy: zroot/home@snap-20250415

La instantánea de ayer 'zroot/home@snap-20250414' existe. \
Continuando con la replicacion...
receiving incremental stream of zroot/home@snap-20250415 into \
zbackup/solaris/home/carlos@snap-20250415
received 312B stream in 0.91 seconds (341B/sec)
receiving incremental stream of zroot/home/carlos@snap-20250415 \
into zbackup/solaris/home/carlos@snap-20250415
received 16.3M stream in 7.07 seconds (2.30M/sec)

Replicacion completada.

Intentando destruir instantáneas antiguas zroot/home...
Destruyendo las siguientes instantáneas antiguas:
zroot/home@snap-20250327

Intentando destruir instantáneas antiguas zbackup/solaris...
No se pudo encontrar ninguna instantánea para destruir.
FreeBSD es genial!.

viernes, 11 de abril de 2025

Configuración de Zerotier Acceso a Servidor LAN vía SSH FreeBSD 14.2

Configuración para conectar clientes a un servidor FreeBSD via Zerotier y SSH

Instalación y configuración de Zerotier en el servidor FreeBSD

Instalación y puesta en marcha de Zerotier

 pkg install net/zerotier
 sysrc zerotier_enable=YES
 service zerotier start

Unirse a la Red Zerotier (192.168.192.0-24):

 zerotier-cli join <Network ID>

Reemplaza <Network ID> con el ID de tu red Zerotier (puedes verlo en Zerotier central).

Autorizar el servidor en Zerotier, aparecerá en la lista de miembros con su ID

Asigna una IP fija al servidor en la red Zerotier (por ej: 192.168.192.133).

Configuración del cortafuegos PF en el servidor FreeBSD

Habilitar IP Forwarding (Reenvío de paquetes):

echo "net.inet.ip.forwarding=1" >> /etc/sysctl.conf

Aplicar los cambios:

sysctl net.inet.ip.forwarding=1
net.inet.ip.forwarding: 1

Reglas PF (/etc/pf.conf)

# Macros
wan_if = "re0"               # Interfaz conectada al MikroTik (LAN)
lan_net = "192.168.88.0/24"  # Red local
zt_if = "zt1ocu1pr8e2sac"    # Interfaz ZeroTier
zt_net = "192.168.192.0/24"  # Red ZeroTier

# Opciones generales
set block-policy drop
set skip on { lo0, $zt_if }  # ZeroTier no necesita filtrado estricto
scrub in all fragment reassemble

# Reglas predeterminadas
block all
pass out quick keep state

# Permitir tráfico entre redes LAN y ZeroTier
pass quick from $lan_net to $zt_net
pass quick from $zt_net to $lan_net

# Permitir servicios desde la LAN (Samba, NFSv4, SSH)
pass in on $wan_if proto { tcp, udp } from $lan_net to any port { 139, \
445, 111, 2049, 22 }

# Permitir SSH desde ZeroTier (clientes externos)
pass in on $zt_if proto tcp from $zt_net to ($wan_if) port 22

# Reglas para ZeroTier (puerto UDP 9993 y comunicación entre peers)
pass in on $zt_if proto udp from any to any port 9993

# Permitir ICMP (pings y mensajes de error)
pass in inet proto icmp all icmp-type { echoreq, unreach }

Configuración de clientes Zerotier:

Instalar Zerotier en los dispositivos cliente

Unirlos a la red Zerotier

zerotier-cli join <Network ID> o mediante la app

Autoriza los clientes en Zerotier y asígnales IPs fijas si es necesario

Acceso SSH al servidor

Conectarse desde un cliente usando la IP de Zerotier del servidor

 ssh usuario@192.168.192.133

Ruta estática entre la red local (192.168.88.0/24) y Zerotier (192.168.192.0/24)

¿Por qué es necesaria?

Los clientes en Zerotier (192.168.192.0/24) no saben como llegar a la red local del servidor (192.168.88.0/24) por defecto.

La ruta estática indica a Zerotier que el servidor actúa como puerta de enlace para la red local.

Configuración en Zerotier Central:

Ir a su red en Zerotier
En Advanced > Managed Routes,
añadir:

 - Destination: 192.168.88.0/24
 - Via: 192.168.192.133 (IP Zerotier del servidor)

Explicación Técnica

Zerotier como VPN Layer 2:

Crea una red virtual donde todos los dispositivos aparecen como si estuvieran en la misma LAN, evitando la necesidad de port forwarding

Ruta estática:

Dirige el tráfico desde Zerotier hacia la red local a través del servidor, que actúa como router.

Regla de Cortafuegos en Mikrotik

Agregar una regla que permita el tráfico SSH desde la red ZeroTier hacia el servidor FreeBSD

# En Mikrotik (RouterOS CLI)

/ip firewall filter add chaind=filter action=accept protocol=tcp \
dst-port=22 src-address=192.168.192.0/24 comment="Permitir SSH desde ZeroTier"

El servidor usa la IP de ZeroTier para SSH, asegúrese de que SSH está configurado para escuchar en esa IP

# En /etc/ssh/sshd_config
ListenAddress 192.168.192.133

Reiniciar SSH después

service sshd restart

Verificaión:

Desde un cliente Zerotier, por ej: desactivo la conexión wifi de mi teléfono móvil y activo los datos para conectarme desde una red externa:

 ssh carlos@192.168.192.133


Captura de tráfico

 tcpdump -i zt1ocu1pr8e2sac

Optimizar ZeroTier:

- En /usr/local/etc/zerotier-one/zerotier-one.conf, configura allowManaged y allowGlobal para controlar el acceso a rutas:

   {
     "settings": {
       "allowManaged": true,
       "allowGlobal": false
     }
   }

Diagrama de Flujo

Esta configuración garantiza que solo los servicios necesarios estén expuestos, y la comunicación entre redes se realice de manera segura y controlada.

FreeBSD es genial!.

martes, 25 de marzo de 2025

Crear Particiones en Disco Duro USB Sistema de Archivos ZFS con gpart en FreeBSD 14

# Identificar el disco USB

Primero, verifica el nombre del disco USB conectado:

 gpart show

O también:

 camcontrol devlist

El disco USB generalmente aparecerá como daX (por ejemplo: da0).


# Eliminar particiones existentes (si es necesario)

Si el disco ya tiene particiones, puedes limpiarlo con:

 gpart destroy -F /dev/daX

(Reemplaza daX con tu dispositivo, como da0).


# Crear tabla de particiones (GPT)

Crea una tabla de particiones GPT en el disco:

 gpart create -s GPT /dev/daX

# Crear partición para ZFS

Crea una partición que ocupe todo el disco (o el espacio deseado):

 gpart add -t freebsd-zfs -a 1M -l ZFSBACKUP /dev/daX

-t freebsd-zfs: Tipo de partición para ZFS.
-a 1M: Alineación a 1 MiB (mejor rendimiento en discos modernos).
-l ZFSBACKUP`: Etiqueta de la partición (opcional pero útil para identificación).

# Verificar la partición creada

 gpart show /dev/daX

Deberías ver algo como:

=>   40  625142368  da0  GPT  (298G)
     40  625142368    1  freebsd-zfs  (298G)  [ZFSBACKUP]

# Crear el pool ZFS en la partición

Ahora crea un pool ZFS en la partición (no en el disco completo, `/dev/daX`, sino en la partición, /dev/daXp1 o /dev/gpt/ZFSBACKUP si usaste etiqueta):

 zpool create -f zbackup /dev/gpt/ZFSBACKUP

- zbackup: Nombre del pool (cámbialo si lo prefieres).
- f Fuerza la creación si hay restos de particiones anteriores.

# Configurar propiedades del pool (opcional)

Para mejorar la compatibilidad y rendimiento:

 zfs set mountpoint=none zbackup
 zpool set autoexpand=on zbackup
 zpool set listsnapshots=on zbackup

# Habilitar compresión (recomendado)

 zfs set compression=lz4 zbackup

# Verificar el pool ZFS

 zpool status

zfs list

# Enviar instantáneas (snapshots) al disco USB

Desde el sistema origen (donde está el ZFS con los datos), usa zfs send y zfs receive:


# En el sistema origen:

zfs snapshot pool/dataset@backup1
zfs send pool/dataset@backup1 | zfs receive zbackup/dataset

Si el disco está conectado a otro sistema, usa ssh:

 zfs send pool/dataset@backup1 | ssh user@host "zfs receive zbackup/dataset"

# Notas importantes:

USB y ZFS: ZFS en discos USB puede ser lento y no es ideal para uso intensivo. Se recomienda usar discos con conexión SATA o NVMe si es posible.
- Montaje automático: Si deseas que el pool se monte al conectar el disco, agrega zfs_enable="YES" en /etc/rc.conf.
- Exportar el pool: Antes de desconectar el disco, ejecuta:

 zpool export zbackup

Esto asegura que el pool se cierre correctamente y se liberen todos los recursos asociados. Luego, el disco puede ser desconectado de forma segura.

¡Listo! Ahora tienes un disco USB con ZFS listo para recibir snapshots de FreeBSD.

 

FreeBSD es genial!.

lunes, 6 de enero de 2025

Gestionar el brillo de la pantalla con backlight y Gammy FreeBSD 14.1

Portatil Dell 7390
UHD Graphics 620 





 

Controlar el brillo de la pantalla (la luz de fondo conectada al chipset de video Intel).

 pkg install backlight

Controlar a través de las teclas de función (Fn+Arriba, Fn+Abajo) que Dell expone a través de ACPI

 echo 'acpi_video_load="YES"' >> /boot/loader.conf

 kldload acpi_video

 kldstat | grep "acpi_video"
  9  1 0xffffffff825c2000  9528 acpi_video.ko

 cp /usr/local/share/examples/intel-backlight/acpi-video-intel-backlight.conf \
 /usr/local/etc/devd/

Despues de cargar acpi_video deberian aparecer:

sysctl -a | grep -E '(backlight|brightness)'
hw.i915kms.enable_dpcd_backlight: -1
hw.i915kms.invert_brightness: 0
hw.acpi.video.lcd0.brightness: 80
compat.linuxkpi.i915_enable_dpcd_backlight: -1
compat.linuxkpi.i915_invert_brightness: 0

Brillo y temperatura de pantalla adaptables para Unix

 pkg install accessibility/gammy

Paquete movido intel-backlight -> xbacklight

Para una búsqueda más a fondo utilice make search key=cadena donde cadena es el término que busca. Podrá buscar nombres de ports, comentarios, descripciones y dependencias; también se puede usar para encontrar ports que tengan relación con algún tema en particular si no conoce el nombre del programa que busca.

sudo make fetchindex

 cd /usr/ports

 /usr/ports » pkg search name=intel-backlight

 /usr/ports » make search name=intel-backlight
 Port:	graphics/intel-backlight
 Moved:	
 Date:	2024-07-01
 Reason:  Has expired: Use xbacklight(8)

 pkg install x11/xbacklight

Eventos acpi

cat /etc/devd.conf|grep "acpi"
	action "/etc/rc.suspend acpi $notify";
	action "/etc/rc.resume acpi $notify";
	action	      "/etc/acpi_ac $notify";
FreeBSD es genial!.

martes, 24 de diciembre de 2024

FreeBSD DMA (Dragonfly Mail Agent)

dma

(Dragonfly Mail Agent) es un pequeño agente de transporte de correo (MTA). Es capaz de aceptar correos y entregarlo a destinos locales o remotos. Si desea enviar y recibir correos con su nombre de dominio, entonces necesitará un servidor de correo completo.

En FreeBSD 14 dma es el agente de correo por defecto

Archivos de configuración


cat /etc/dma/dma.conf

SMARTHOST smtp.gmail.com
PORT 587
AUTHPATH /etc/dma/auth.conf
SECURETRANSFER
STARTTLS
SECURE

Gmail contraseña de aplicación

Generar contraseña de aplicacón
https://support.google.com/mail/answer/185833?hl=es

cat /etc/dma/auth.conf

El password de la cuenta de Gmail se sustituye por la contraseña de aplicación generada

Formato: user|my.smarthost.example.com:password
nombreusuario@gmail.com|smtp.gmail.com:tryjajbxpoxknmir

Actualizar /etc/mail/mailer.conf para asegurar que DMA reemplace a sendmail

 sed -i '' 's/usr/sbin/sendmail|/usr/libexec/dma|g' /etc/mail/mailer.conf

Redirigir el correo del sistema a cuenta gmail

cat /etc/mail/aliases

...
# root's email from here.
root: nombreusuario@gmail.com
...

cat /etc/mail/mailer.conf

sendmail	/usr/libexec/dma
mailq		/usr/libexec/dma
newaliases	/usr/libexec/dma

Asegurar los permisos correctos

 chown root:mail /etc/dma/auth.conf
 chmod 640 /etc/dma/auth.conf

Regenerar la base

 newaliases

Probar el envío de correo

  cat >> mensaje.txt <<EOF
Esto es una prueba de envio de correo usando agente DMA
EOF

 mail -v -s Prueba nombreusuario@protonmail.com < mensaje.txt

Verificar el log de DMA

 tail -f /var/log/maillog
...
Sep 19 08:59:00 tormenta dma[dd67.2b6bad248050][86005]: trying remote delivery to smtp.gmail.com [74.125.133.109] pref 0
Sep 19 08:59:00 tormenta dma[dd67.2b6bad248050][86005]: using SMTP authentication for user tucorreo@gmail.com
Sep 19 08:59:01 tormenta dma[dd67.2b6bad248050][86005]: <tucorreo@gmail.com> delivery successful
FreeBSD es genial!.