1. Identificar discos
geom disk list camcontrol devlist gpart show
2. Comprobaciones previas (antes de destruir nada)
¿Tiene particiones?
gpart show da1
¿Tiene restos de ZFS?
zpool import | grep -B2 -A5 da1
¿Está montado en algún sitio?
mount | grep da1
3. Plan resumido
| Comando | Qué hace |
|---|---|
gpart destroy -F da1 | Borra particiones |
zpool labelclear -f /dev/da1 | Borra restos ZFS |
gpart create -s gpt da1 | Tabla GPT nueva |
gpart add -t freebsd-zfs -l backup1tb da1 | Partición ZFS |
zpool create -o ashift=12 ... zbk /dev/gpt/backup1tb | Pool zbk |
zfs create -o mountpoint=none zbk/tormenta | Dataset destino |
zfs snapshot -r zroot@snap-$(date +%Y%m%d) | Snapshot del sistema |
zfs send -Rwcv ... | zfs receive -Fsuv ... | Envío local (en tmux) |
zpool export zbk | Cerrar limpiamente |
4. Preparar el disco
gpart destroy -F da1 # → da1 destroyed
Borrar cualquier resto de ZFS (aunque no haya, por asegurar)
zpool labelclear -f /dev/da1 2>/dev/null
Crear tabla GPT nueva
gpart create -s gpt da1 # → da1 created
Crear partición ZFS ocupando todo el disco
gpart add -t freebsd-zfs -l backup1tb da1 # → da1p1 added
Verificar
gpart show da1 # → 40 1953525088 da1 GPT (932G) # → 40 1953525088 1 freebsd-zfs (932G)
5. Crear el pool zbk
Los discos modernos suelen tener sectores de 4K, pero muchos discos USB reportan 512B. Es crítico crear el pool con ashift=12 (4096 bytes) para evitar problemas de rendimiento.
Ver ashift que ZFS detectaría por defecto
diskinfo -v da1 | grep -i "sector size"
Si dice 512, hay que forzar ashift=12 al crear el pool.
zpool create -o ashift=12 \
-O compression=lz4 \
-O atime=off \
-O xattr=sa \
-O relatime=on \
-O mountpoint=none \
zbk /dev/gpt/backup1tb
Banderas
- ashift=12 → sectores 4K (crítico para rendimiento en discos modernos).
- compression=lz4 → compresión ligera y rápida.
- atime=off → no actualizar tiempo de acceso (más rápido).
- xattr=sa → atributos extendidos en el inodo.
- relatime=on → atime solo cuando sea útil.
- mountpoint=none → no montar automáticamente.
Verificar
zpool status zbk zpool list zbk zfs list
Crear dataset destino
zfs create -o mountpoint=none zbk/tormenta zfs list -r zbk
Salida esperada:
zbk XXXG XXXG 96K none zbk/tormenta 96K XXXG 96K none
Pool zbk creado correctamente:
| Dato | Valor |
|---|---|
| Pool | zbk |
| Tamaño | 928 G |
| Disponible | 899 G |
| Dataset destino | zbk/tormenta (listo) |
| zroot a respaldar | 312 G |
6. Crear snapshot del sistema
zfs snapshot -r zroot@snap-$(date +%Y%m%d)
Verificar
zfs list -t snapshot -r zroot | grep snap-$(date +%Y%m%d) | wc -l
El resultado depende del número de datasets del sistema. En tormenta actual: ~48.
-r,
o si otro proceso lo creó antes para otro propósito, puede haber conflictos. Cuando se monte el cron
para backups automáticos, usar date +%Y%m%d-%H%M%S para evitar colisiones si se ejecuta
dos veces el mismo día.
zfs snapshot -r zroot@snap-$(date +%Y%m%d-%H%M%S)
7. Lanzar el envío en tmux
Entrar en tmux
tmux new -s backup_usb
Comando de envío (dentro de tmux)
zfs send -Rwcv zroot@snap-$(date +%Y%m%d) \ | zfs receive -Fsuv -x mountpoint zbk/tormenta
Banderas explicadas
| Flag | Significado |
|---|---|
-R | Recursivo: envía zroot y todos sus hijos |
-w | Raw: envía los bloques cifrados tal cual (necesario si hay datasets cifrados como zroot/nfsv4/secifrado) |
-c | Compresión nativa ZFS (lz4) |
-v | Verbose: muestra progreso por dataset |
-F | Fuerza rollback en destino si hay divergencias |
-s | Guarda token de resume en /var/tmp/ (permite reanudar si se corta) |
-u | No monta los datasets recibidos |
-x mountpoint | No replica los mountpoints del origen |
zroot/nfsv4/secifrado está cifrado con ZFS native encryption.
Con zfs send -Rcv (sin -w) el envío falla. Siempre usar -Rwcv.
8. Cifrado: consideraciones
El flag -w envía el dataset cifrado tal cual (raw).
Ventaja: funciona, conserva el cifrado, es rápido.
Inconveniente: en destino el dataset también estará cifrado y necesitarás la clave para montarlo.
¿Qué se necesita para recuperarlo?
La passphrase o keyfile utilizada para cifrar zroot/nfsv4/secifrado.
Sin ella, el backup es inútil.
Si se pierde la clave, se pierden los datos y el backup. Guardarla en:
- Un gestor de contraseñas (Bitwarden, KeePass, etc.)
- Un archivo en un USB que no sea el mismo del backup
- Papel impreso en un lugar seguro
Comprobar qué método de cifrado se utilizó
zfs get encryption,keyformat,keylocation zroot/nfsv4/secifrado # NAME PROPERTY VALUE SOURCE # zroot/nfsv4/secifrado encryption aes-256-gcm - # zroot/nfsv4/secifrado keyformat raw - # zroot/nfsv4/secifrado keylocation file:///etc/zfs/secifrado.key
Si dice keyformat=passphrase, se necesita esa passphrase.
Si dice keyformat=raw con keylocation=file:///..., es necesario ese archivo.
Ver el contenido (para copiarlo en un gestor de contraseñas)
Convertir a base64 para poder copiarlo como texto:
base64 /etc/zfs/secifrado.key
9. Salir de tmux sin matar el proceso
Ctrl+b d
10. Monitorizar (en otra terminal)
Ver datasets llegando en tiempo real
watch -n 10 'zfs list -r zbk/tormenta | head -30'
Ver velocidad de escritura al USB
zpool iostat zbk 5
Ver espacio consumido
watch -n 30 'zfs list zbk'
11. Verificar tras el envío
Volver a la sesión tmux
tmux attach -t backup_usb
Si ya terminó, se verá el real Xm Ys del comando. Entonces:
Contar snapshots origen vs destino
zfs list -t snapshot -r zroot | wc -l zfs list -t snapshot -r zbk/tormenta | wc -l
Deben coincidir (probablemente ~300+).
Verificar datasets replicados
zfs list -r zbk/tormenta | head -30
Espacio usado
zfs list zbk zpool list zbk
12. Si algo falla durante el envío
¿Sigue algún proceso zfs vivo?
ps aux | grep -E "zfs (send|receive)" | grep -v grep
Si aparece algo, sigue corriendo. Esperar y dejarlo terminar.
¿En qué estado está el destino?
zfs list zbk zfs list -r zbk/tormenta | head -20
Se verá si quedó un dataset a medias (zbk/tormenta con datos parciales).
¿Hay un token de resume guardado?
ls -la /var/tmp/ | grep -i zfs ls -la / | grep -i zfs
-s en el zfs receive.
Si no se usó, no hay reanudación posible: hay que empezar de cero.
¿El proceso murió? Limpiar el destino parcial
zfs destroy -r zbk/tormenta zfs create -o mountpoint=none zbk/tormenta zfs list -r zbk
Relanzar con -s para permitir resume
tmux new -s backup_usb
Dentro de tmux:
zfs send -Rwcv zroot@snap-20260930 \ | zfs receive -Fsuv -x mountpoint zbk/tormenta
-s en zfs receive guarda un token de reanudación en /var/tmp/.
Si se vuelve a cortar, se podrá reanudar con:
zfs send -t $(ls /var/tmp/zfs_*.resume 2>/dev/null | head -1)
Salir de tmux con Ctrl+b d antes de cerrar SSH.
No cerrar la sesión SSH hasta que tmux esté desconectado.
13. Exportar el pool y desconectar el USB
Verificar que no hay nada escribiendo
zpool status zbk lsof | grep zbk 2>/dev/null
Exportar limpiamente
zpool export zbk
Y por último
sync
Ya se puede retirar el cable USB.
14. Tiempo estimado
| Velocidad USB | 312 GB |
|---|---|
| 80 MB/s | ~1.1 h |
| 120 MB/s | ~43 min |
| 200 MB/s | ~26 min |
| 400 MB/s | ~13 min |
Con el chip ASMT USB 3.0 + disco SATA: ~20–45 min si es SSD, ~50–80 min si es HDD.
tmux new -s backup_usb, lanzar el envío, y salir con
Ctrl+b d.
- Backup Tormenta
- snap-20260930
- zbk pool
15. Restaurar archivos de configuración
No requiere reiniciar. Solo copia los archivos desde el snapshot.
Paso 1: Montar el snapshot
mkdir -p /mnt/snap mount -t zfs zroot/ROOT/default@snap-14.4-RELEASE-p8-casa.lan-2026-28-sept-2026 /mnt/snap
Paso 2: Comparar qué cambió
diff /etc/pf.conf /mnt/snap/etc/pf.conf diff /etc/rc.conf /mnt/snap/etc/rc.conf diff /etc/sysctl.conf /mnt/snap/etc/sysctl.conf diff /boot/loader.conf /mnt/snap/boot/loader.conf
Paso 3: Backup de los actuales
cp /etc/pf.conf /etc/pf.conf.broken-$(date +%Y%m%d) cp /etc/rc.conf /etc/rc.conf.broken-$(date +%Y%m%d) cp /etc/sysctl.conf /etc/sysctl.conf.broken-$(date +%Y%m%d) cp /boot/loader.conf /boot/loader.conf.broken-$(date +%Y%m%d)
Paso 4: Restaurar desde el snapshot
cp /mnt/snap/etc/pf.conf /etc/pf.conf cp /mnt/snap/etc/rc.conf /etc/rc.conf cp /mnt/snap/etc/sysctl.conf /etc/sysctl.conf cp /mnt/snap/boot/loader.conf /boot/loader.conf
Paso 5: Desmontar y probar
umount /mnt/snap rmdir /mnt/snap # Recargar pf (sin reiniciar) pfctl -f /etc/pf.conf # Ver rutas netstat -rn # Probar red ping -c 3 192.168.88.1 ping -c 3 8.8.8.8 ping -c 3 google.com
Paso 6: Si funciona, reiniciar para aplicar loader.conf y sysctl.conf
shutdown -r now
16. Rollback completo
Requiere arrancar en modo monousuario. No se puede hacer con el dataset montado.
Paso 1: Crear snapshot de seguridad del estado actual
Antes de tocar nada, para poder volver si algo falla:
zfs snapshot -r zroot@before-rollback-$(date +%Y%m%d-%H%M)
Paso 2: Reiniciar en modo monousuario
shutdown -r now
En el menú de arranque de FreeBSD, pulsar 2 (Boot Single User).
Paso 3: Preparar el sistema
zfs set readonly=off zroot zfs mount -a
Paso 4: Rollback
zfs rollback -R zroot/ROOT/default@snap-14.4-RELEASE-p8-casa.lan-2026-28-sept-2026
Paso 5: Salir del modo monousuario y reiniciar
exit
O directamente:
reboot
Qué se pierde con el rollback
| Elemento | Estado |
|---|---|
| pf.conf | ext_if="wlan0" (vuelve atrás) |
| loader.conf | Sin hw.em.eee_setting=1 |
| sysctl.conf | Sin dev.em.0.eee_control=0 |
| /etc/rc.conf | Estado del snapshot |
| Archivos en /home/carlos | NO se pierden (dataset separado) |
| Archivos en /var | NO se pierden (dataset separado, si no se hace rollback ahí) |
zroot/ROOT/default (el sistema base).
Los datos personales en zroot/home/carlos no se tocan.
17. Errores comunes a evitar
- Usar
zfs send -Rcvsin-w→ falla si hay datasets cifrados. - Olvidar
-senzfs receive→ no hay reanudación posible si se corta. - Cerrar la sesión SSH sin tmux → el envío muere al desconectar.
- No guardar la clave de cifrado fuera del backup → backup inútil si se pierde.
- Usar
zfs destroysin-nprimero → riesgo de borrar snapshots con dependencias. - Ejecutar el script de retención sin verificar → puede borrar snapshots indiscriminadamente.
18. Checklist final
- [ ] Disco USB identificado y preparado
- [ ] Pool
zbkcreado conashift=12 - [ ] Dataset
zbk/tormentacreado - [ ] Snapshot del sistema creado (
zfs snapshot -r) - [ ] Envío lanzado dentro de tmux
- [ ] Proceso monitorizado hasta el final
- [ ] Verificado: snapshots origen vs destino coinciden
- [ ] Pool exportado limpiamente (
zpool export zbk) - [ ] USB desconectado y guardado en lugar seguro
- [ ] Clave de cifrado guardada en al menos 2 sitios distintos







