Páginas

Mostrando entradas con la etiqueta canmount. Mostrar todas las entradas
Mostrando entradas con la etiqueta canmount. Mostrar todas las entradas

sábado, 3 de octubre de 2026

Backup Manual y Recuperación

FreeBSD 14.5

ZFS FreeBSD Copia de seguridad del servidor tormenta
ZFS FreeBSD Copia de seguridad del cliente solaris

Sistema: solaris y tormenta (FreeBSD 14.5)
Método: Backup manual a disco USB (Modelo B — USB guardado fuera)
Fecha: 2026-10-03

1. Introducción y filosofía

Este documento describe el sistema de backup manual a disco USB implementado en solaris y tormenta. Está diseñado para:

  • Ejecutarse manualmente cuando se conecta el disco USB.
  • Mantener los USB guardados fuera de las máquinas para protección ante ransomware y desastres locales.
  • Ser recuperable tanto para archivos individuales como para el sistema completo.
Filosofía del Modelo B: los USB no están conectados permanentemente. Se conectan solo cuando se va a hacer el backup, y después se guardan en otro lugar. Esto protege contra:
  • Ransomware que cifraría también el USB conectado.
  • Robo o incendio que afectaría a máquina y backup a la vez.
  • Errores humanos que borrarían el backup por accidente.

Estado del sistema

Elementosolaristormenta
Pool origenzrootzroot
Pool destino (USB)zbackupzbk
Dataset destinozbackup/recovery/solariszbk/tormenta
Etiqueta USBZFSBACKUPbackup1tb
Tamaño del pool origen~220 GB~312 GB
Script/root/bin/zfs-backup.sh/root/bin/zfs-backup.sh
Log/var/log/zfs-backup.log/var/log/zfs-backup.log
Retención origen7 snapshots7 snapshots
Retención destino30 snapshots30 snapshots

2. El script zfs-backup.sh

Script único que funciona en ambas máquinas, detectando automáticamente el hostname. Versión 2.4.

Ubicación

/root/bin/zfs-backup.sh

Contenido completo

#!/bin/sh
# zfs-backup.sh - Backup incremental de zroot a pool USB
# Versión: 2.4 (snapshot por dataset + export en error)
# Uso: sh /root/bin/zfs-backup.sh

set -e

# ========== CONFIGURACIÓN SEGÚN MÁQUINA ==========
HOSTNAME=$(hostname -s)
case "$HOSTNAME" in
    solaris)
        SRC_POOL="zroot"
        DST_POOL="zbackup"
        DST_DATASET="zbackup/recovery/solaris"
        USB_DEV="/dev/gpt/ZFSBACKUP"
        RETENTION_SRC=7
        RETENTION_DST=30
        ;;
    tormenta)
        SRC_POOL="zroot"
        DST_POOL="zbk"
        DST_DATASET="zbk/tormenta"
        USB_DEV="/dev/gpt/backup1tb"
        RETENTION_SRC=7
        RETENTION_DST=30
        ;;
    *)
        echo "Hostname no reconocido: $HOSTNAME" >&2
        exit 1
        ;;
esac

SNAP_PREFIX="snap"
SNAP_TODAY="${SNAP_PREFIX}-$(date +%Y%m%d)"
LOG="/var/log/zfs-backup.log"
LOCKFILE="/var/run/zfs-backup.lock"

# ========== VARIABLES DE ESTADO ==========
IMPORTED_BY_US=0

# ========== FUNCIONES ==========
log() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" >> "$LOG"
}

die() {
    log "ERROR: $*"
    if [ "${IMPORTED_BY_US:-0}" -eq 1 ]; then
        log "Exportando pool $DST_POOL antes de salir..."
        zpool export "$DST_POOL" >> "$LOG" 2>&1 || log "Aviso: no se pudo exportar"
    fi
    rm -f "$LOCKFILE"
    exit 1
}

# ========== BLOQUEO ==========
if [ -f "$LOCKFILE" ]; then
    PID=$(cat "$LOCKFILE" 2>/dev/null)
    if kill -0 "$PID" 2>/dev/null; then
        echo "Ya hay una ejecución en curso (PID $PID)"
        exit 0
    fi
    rm -f "$LOCKFILE"
fi
echo $$ > "$LOCKFILE"

log "=========================================="
log "Iniciando backup en $HOSTNAME"
log "=========================================="

# ========== VERIFICAR POOL USB ==========
if ! zpool list "$DST_POOL" >/dev/null 2>&1; then
    log "Pool $DST_POOL no está importado. Intentando importar..."
    if [ ! -e "$USB_DEV" ]; then
        die "Disco USB $USB_DEV no encontrado. ¿Está conectado?"
    fi
    if ! zpool import "$DST_POOL" 2>>"$LOG"; then
        die "No se pudo importar el pool $DST_POOL"
    fi
    log "Pool $DST_POOL importado correctamente"
    IMPORTED_BY_US=1
else
    log "Pool $DST_POOL ya estaba importado"
    IMPORTED_BY_US=0
fi

# ========== CREAR SNAPSHOT DE HOY (dataset por dataset) ==========
log "Creando snapshot $SNAP_TODAY en todos los datasets (los que falten)..."

CREATED=0
SKIPPED=0
FAILED=0
for ds in $(zfs list -H -o name -r "$SRC_POOL" 2>/dev/null); do
    if zfs list -t snapshot "$ds@$SNAP_TODAY" >/dev/null 2>&1; then
        SKIPPED=$((SKIPPED + 1))
    else
        if zfs snapshot "$ds@$SNAP_TODAY" >> "$LOG" 2>&1; then
            CREATED=$((CREATED + 1))
        else
            log "  → error al crear $ds@$SNAP_TODAY"
            FAILED=$((FAILED + 1))
        fi
    fi
done
log "Snapshots: creados=$CREATED, ya existían=$SKIPPED, fallos=$FAILED"

if [ "$FAILED" -gt 0 ]; then
    log "AVISO: hubo $FAILED fallos al crear snapshots (se continúa)"
fi

# ========== DETECTAR ÚLTIMA SNAPSHOT EN DESTINO ==========
LAST_DST_SNAP=$(zfs list -t snapshot -H -o name -r "$DST_DATASET" 2>/dev/null \
    | grep '@snap-[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]$' \
    | sort -r \
    | head -1 \
    | sed 's/.*@//')

if [ -z "$LAST_DST_SNAP" ]; then
    log "No hay snapshots previas en destino. Envío COMPLETO."
    zfs send -Rwcv "$SRC_POOL@$SNAP_TODAY" \
        | zfs receive -Fsuv -x mountpoint "$DST_DATASET" >> "$LOG" 2>&1 \
        || die "Error en el envío completo"

elif [ "$LAST_DST_SNAP" = "$SNAP_TODAY" ]; then
    log "Última snapshot en destino: $LAST_DST_SNAP"
    log "La snapshot $SNAP_TODAY ya está replicada. Nada que enviar."

elif ! zfs list -t snapshot "$SRC_POOL@$LAST_DST_SNAP" >/dev/null 2>&1; then
    log "AVISO: $LAST_DST_SNAP no existe en origen. Envío COMPLETO."
    zfs send -Rwcv "$SRC_POOL@$SNAP_TODAY" \
        | zfs receive -Fsuv -x mountpoint "$DST_DATASET" >> "$LOG" 2>&1 \
        || die "Error en el envío completo"

else
    log "Enviando incremental desde $LAST_DST_SNAP hasta $SNAP_TODAY"
    zfs send -Rwcv -i "$SRC_POOL@$LAST_DST_SNAP" "$SRC_POOL@$SNAP_TODAY" \
        | zfs receive -Fsuv -x mountpoint "$DST_DATASET" >> "$LOG" 2>&1 \
        || die "Error en el envío incremental"
fi

log "Envío completado correctamente"

# ========== FUNCIÓN DE RETENCIÓN ==========
apply_retention() {
    local root="$1"
    local label="$2"
    local ret="$3"

    log "Aplicando retención de $ret snapshots en $label..."

    zfs list -t snapshot -H -o name -r "$root" 2>/dev/null \
        | grep '@snap-[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]$' \
        | sort -t@ -k1,1 -k2,2r \
        | awk -F@ -v r="$ret" '
            {
                ds = $1
                if (ds != prev_ds) { count = 0; prev_ds = ds }
                count++
                if (count > r) print $0
            }' \
        | while read snap; do
            log "Borrando $snap"
            zfs destroy "$snap" >> "$LOG" 2>&1 || log "  → error al borrar"
        done

    log "Retención en $label aplicada"
}

# ========== RETENCIÓN EN DESTINO (30 snapshots) ==========
apply_retention "$DST_DATASET" "destino" "$RETENTION_DST"

# ========== RETENCIÓN EN ORIGEN (7 snapshots) ==========
apply_retention "$SRC_POOL" "origen" "$RETENTION_SRC"

# ========== EXPORTAR POOL ==========
if [ "$IMPORTED_BY_US" -eq 1 ]; then
    log "Exportando pool $DST_POOL"
    zpool export "$DST_POOL" >> "$LOG" 2>&1 || log "Aviso: no se pudo exportar"
    log "Ya puedes desconectar el USB de forma segura"
fi

log "Backup completado con éxito"
log "=========================================="
rm -f "$LOCKFILE"

Características clave

ElementoDescripción
Detección automáticaUsa el hostname para elegir el pool y dataset correctos
Snapshot dataset por datasetEvita el fallo atómico de zfs snapshot -r
Detección de sincronizaciónSi ya está todo replicado, no envía nada
Incremental automáticoDetecta la última snapshot en destino y envía solo diferencias
Fallback a full sendSi no hay base común, hace envío completo automáticamente
Retención independiente7 snapshots en origen, 30 en destino
Export automáticoSi el script importó el USB, lo exporta al terminar
Logging completoTodo se registra en /var/log/zfs-backup.log
LockfileEvita ejecuciones simultáneas

3. Ejecución manual paso a paso

Cuándo ejecutar: semanalmente (recomendado domingo por la tarde), o siempre que haya cambios importantes que se quieran respaldar.

Paso 1 — Conectar el USB

Conectar el disco USB (ZFSBACKUP en solaris, backup1tb en tormenta) a la máquina correspondiente. Esperar unos segundos a que el sistema lo detecte.

ls -la /dev/gpt/ZFSBACKUP    # En solaris
ls -la /dev/gpt/backup1tb    # En tormenta

Debe aparecer el device node. Si no aparece, probar con otro puerto USB o revisar dmesg:

dmesg | tail -20

Paso 2 — Ejecutar el script

sh /root/bin/zfs-backup.sh
Importante: NO ejecutar el script si no se está seguro de que el USB está conectado. Si no lo está, el script fallará limpiamente sin tocar nada.

Paso 3 — Verificar el resultado

tail -30 /var/log/zfs-backup.log

Debe verse al final:

[XX:XX:XX] Backup completado con éxito
[XX:XX:XX] ==========================================

Paso 4 — Desconectar el USB

Si el script importó el pool, lo habrá exportado automáticamente. Se verá en el log:

[XX:XX:XX] Ya se puede desconectar el USB de forma segura

Verificar que el pool está exportado:

zpool list

El pool de backup (zbackup o zbk) no debe aparecer en la lista. Si aparece, exportarlo manualmente antes de desconectar:

zpool export zbackup    # En solaris
zpool export zbk        # En tormenta

sync

Paso 5 — Guardar el USB en lugar seguro

Una vez exportado y sincronizado, se puede retirar el cable USB y guardarlo donde corresponda (fuera de casa, caja fuerte, casa de un familiar, etc.).

¡Backup completado! El proceso completo tarda típicamente entre 1 y 15 minutos dependiendo de cuántos datos hayan cambiado desde el último backup.

4. Interpretación del log

Ejemplo de ejecución exitosa (con cambios)

[2026-10-03 18:30:00] ==========================================
[2026-10-03 18:30:00] Iniciando backup en solaris
[2026-10-03 18:30:00] ==========================================
[2026-10-03 18:30:00] Pool zbackup no está importado. Intentando importar...
[2026-10-03 18:30:02] Pool zbackup importado correctamente
[2026-10-03 18:30:02] Creando snapshot snap-20261003 en todos los datasets (los que falten)...
[2026-10-03 18:30:02] Snapshots: creados=18, ya existían=0, fallos=0
[2026-10-03 18:30:03] Última snapshot en destino: snap-20261002
[2026-10-03 18:30:03] Enviando incremental desde snap-20261002 hasta snap-20261003
[2026-10-03 18:32:15] Envío completado correctamente
[2026-10-03 18:32:15] Aplicando retención de 30 snapshots en destino...
[2026-10-03 18:32:15] Retención en destino aplicada
[2026-10-03 18:32:15] Aplicando retención de 7 snapshots en origen...
[2026-10-03 18:32:15] Retención en origen aplicada
[2026-10-03 18:32:15] Exportando pool zbackup
[2026-10-03 18:32:16] Ya puedes desconectar el USB de forma segura
[2026-10-03 18:32:16] Backup completado con éxito
[2026-10-03 18:32:16] ==========================================

Ejemplo de ejecución sin cambios

[2026-10-03 18:30:00] ==========================================
[2026-10-03 18:30:00] Iniciando backup en solaris
[2026-10-03 18:30:00] ==========================================
[2026-10-03 18:30:00] Pool zbackup ya estaba importado
[2026-10-03 18:30:00] Creando snapshot snap-20261003 en todos los datasets (los que falten)...
[2026-10-03 18:30:00] Snapshots: creados=18, ya existían=0, fallos=0
[2026-10-03 18:30:00] Última snapshot en destino: snap-20261003
[2026-10-03 18:30:00] La snapshot snap-20261003 ya está replicada. Nada que enviar.
[2026-10-03 18:30:00] Envío completado correctamente
[2026-10-03 18:30:00] Aplicando retención de 30 snapshots en destino...
[2026-10-03 18:30:00] Retención en destino aplicada
[2026-10-03 18:30:00] Aplicando retención de 7 snapshots en origen...
[2026-10-03 18:30:00] Retención en origen aplicada
[2026-10-03 18:30:00] Backup completado con éxito
[2026-10-03 18:30:00] ==========================================

Ejemplo de error (USB no conectado)

[2026-10-03 18:30:00] ==========================================
[2026-10-03 18:30:00] Iniciando backup en solaris
[2026-10-03 18:30:00] ==========================================
[2026-10-03 18:30:00] Pool zbackup no está importado. Intentando importar...
[2026-10-03 18:30:00] ERROR: Disco USB /dev/gpt/ZFSBACKUP no encontrado. ¿Está conectado?
Este error es normal si se ejecuta el script sin el USB conectado. No corrompe nada. Simplemente conectar el USB y volver a ejecutar.

5. Política de retención

El script aplica automáticamente dos políticas distintas:

UbicaciónSnapshots conservadosRazón
Origen (zroot)7Liberar espacio en el NVMe. Solo se necesitan los últimos días para incrementales.
Destino (USB)30Histórico más largo. El USB tiene más espacio y es el "archivo".

Ajustar la retención

Si se quieren cambiar los valores, editar el script:

ee /root/bin/zfs-backup.sh

Buscar las líneas:

RETENTION_SRC=7
RETENTION_DST=30

Y modifícalas a los valores se preferencia. Por ejemplo, para guardar más histórico en el USB:

RETENTION_SRC=7
RETENTION_DST=60
Espacio: cada snapshot diaria ocupa entre 50 MB y varios GB según lo que cambie. Con 30 snapshots en destino, asegurarse de que el USB tiene espacio suficiente (consultar con zpool list).

6. Recuperación de archivos individuales

Escenario: se ha borrado un archivo por error o se quiere recuperar una versión anterior de algo.

Paso 1 — Conectar el USB y localizar el snapshot

# Conectar el USB de backup
zpool import zbackup        # En solaris
zpool import zbk            # En tormenta

# Ver snapshots disponibles
zfs list -t snapshot -r zbackup/recovery/solaris | grep 'snap-2026'

Paso 2 — Montar el snapshot en un punto temporal

mkdir -p /mnt/snap
mount -t zfs zbackup/recovery/solaris/home/carlos@snap-20261002 /mnt/snap

Ahora /mnt/snap contiene el contenido de /home/carlos tal como estaba en esa fecha.

Paso 3 — Buscar y copiar el archivo

# Ver qué hay
ls -la /mnt/snap/

# Copiar el archivo deseado
cp /mnt/snap/documento.txt /home/carlos/documento_recuperado.txt

Paso 4 — Desmontar y exportar

umount /mnt/snap
rmdir /mnt/snap

zpool export zbackup        # En solaris
zpool export zbk            # En tormenta

sync
Ventaja sobre el método .gz: con el backup ZFS solo montas el snapshot y accedes a los archivos directamente. No hay que descomprimir 300 GB para sacar un documento.

7. Recuperación completa del sistema

Escenario: el NVMe del sistema ha fallado o necesitas reinstalar FreeBSD desde cero.

ATENCIÓN: Este procedimiento borra todo el contenido del disco actual. Asegurarse de tener el backup antes de empezar.

Paso 1 — Arrancar desde USB de FreeBSD

Insertar el USB de instalación, arrancar la máquina desde él, y elegir "Shell" en lugar de instalar.

Paso 2 — Identificar discos

geom disk list
camcontrol devlist

Paso 3 — Preparar el disco destino

gpart destroy -F nda0
gpart create -s gpt nda0
gpart add -t efi -a 1m -s 260m -l EFI nda0
gpart add -t freebsd-boot -a 1m -s 512k -l BOOT nda0
gpart add -t freebsd-swap -a 1m -s 16g -l SWAP nda0
gpart add -t freebsd-zfs -a 1m -l ZFS nda0
newfs_msdos -F 32 -c 1 /dev/nda0p1

Paso 4 — Crear el pool zroot

zpool create -o ashift=12 \
             -O compression=lz4 \
             -O atime=off \
             -O mountpoint=none \
             -R /mnt \
             zroot /dev/gpt/ZFS

Paso 5 — Importar el USB de backup

zpool import zbackup        # En solaris
zpool import zbk            # En tormenta

Paso 6 — Restaurar el sistema

zfs send -Rwcv zbackup/recovery/solaris@snap-20261003 \
    | zfs receive -Fduv zroot

Paso 7 — Configurar el bootfs

zpool set bootfs=zroot/ROOT/default zroot
zpool get bootfs zroot

Paso 8 — Copiar el cargador UEFI

mkdir -p /mnt2
mount_msdosfs /dev/nda0p1 /mnt2
mkdir -p /mnt2/efi/boot
cp /mnt/zroot/ROOT/default/boot/loader.efi /mnt2/efi/boot/bootx64.efi
umount /mnt2
rmdir /mnt2

Paso 9 — Ajustar propiedades de montaje

zfs set mountpoint=/ zroot/ROOT/default
zfs set mountpoint=/home zroot/home
zfs set mountpoint=/usr zroot/usr
zfs set mountpoint=/var zroot/var
zfs set mountpoint=/tmp zroot/tmp

zpool set altroot= zroot
zpool set cachefile=/boot/zfs/zpool.cache zroot

Paso 10 — Exportar y reiniciar

zpool export zbackup
zpool export zbk

reboot

Paso 11 — Verificar

freebsd-version
zpool status zroot
zfs list -r zroot | head -20

8. Recuperación del dataset cifrado

El dataset zroot/nfsv4/secifrado en tormenta está cifrado con ZFS native encryption.

Guardar la clave en al menos 3 sitios distintos:
  • Gestor de contraseñas (Bitwarden, KeePass, etc.).
  • Papel en caja fuerte.
  • USB de emergencia separado del USB de backup.

Ver el contenido de la clave

base64 /etc/zfs/secifrado.key

Restaurar la clave

echo 'TU_CLAVE_EN_BASE64' | base64 -d > /etc/zfs/secifrado.key
chmod 400 /etc/zfs/secifrado.key
chown root:wheel /etc/zfs/secifrado.key
ls -la /etc/zfs/secifrado.key

Montar el dataset cifrado

zfs mount zroot/nfsv4/secifrado
ls -la /nfsv4/secifrado/
Recomendación: una vez al año, haz una prueba real de recuperación del dataset cifrado en una máquina de prueba.

9. Checklist y rutinas

Rutina semanal (domingo)

  • [ ] Conectar USB ZFSBACKUP a solaris
  • [ ] Ejecutar sh /root/bin/zfs-backup.sh
  • [ ] Verificar log: tail -20 /var/log/zfs-backup.log
  • [ ] Confirmar "Backup completado con éxito"
  • [ ] Desconectar USB y guardarlo en lugar seguro
  • [ ] Repetir con USB backup1tb en tormenta

Rutina mensual

  • [ ] Verificar snapshots recientes en los USB
  • [ ] Comprobar espacio disponible: zpool list
  • [ ] Revisar el log en busca de errores: grep "ERROR" /var/log/zfs-backup.log

Rutina semestral

  • [ ] Prueba de restauración de un archivo aleatorio.
  • [ ] Verificar integridad del pool USB: zpool scrub zbackup
  • [ ] Comprobar que las claves de cifrado siguen accesibles.

Apéndice A — Comandos útiles

Ver estado de los pools

zpool list
zpool status
zpool status -v

Ver snapshots

# Todos los snapshots del pool
zfs list -t snapshot -r zroot

# Solo los snapshots diarios (formato snap-YYYYMMDD)
zfs list -t snapshot -r zroot | grep 'snap-2026'

# Contar snapshots por dataset
zfs list -t snapshot -r zroot | awk -F@ '{print $1}' | sort | uniq -c

Comprobar integridad

zpool scrub zroot
zpool scrub zbackup
zpool status

Ver procesos de backup en curso

ps aux | grep -E "zfs (send|receive)" | grep -v grep
tmux ls

Reconectar a una sesión tmux

tmux attach -t backup_usb

Apéndice B — Solución de problemas

Error: "Pool zbackup no está importado"

ls -la /dev/gpt/ZFSBACKUP
zpool import zbackup
sh /root/bin/zfs-backup.sh

Error: "cannot create snapshot ... dataset already exists"

Causa: alguno de los datasets ya tiene la snapshot de hoy. La versión 2.4 del script ya maneja esto dataset por dataset.

Error: "cannot send ... encrypted dataset"

Causa: falta el flag -w en zfs send.

Solución: usar -Rwcv en lugar de -Rcv.

El USB no se puede exportar (pool is busy)

lsof | grep zbackup
fuser -m /zbackup

zfs unmount -a
zpool export -f zbackup

Backup incompleto o corrupto

zpool scrub zbackup
zpool status zbackup

Apéndice C — Glosario

TérminoSignificado
PoolConjunto de discos gestionados por ZFS como una unidad
DatasetSistema de archivos dentro de un pool
SnapshotImagen inmutable de un dataset en un momento concreto
Full sendEnvío completo de un dataset a otro pool
Incremental sendEnvío solo de los cambios desde una snapshot base
RetenciónNúmero de snapshots que se conservan antes de borrar las más antiguas
ashiftTamaño de sector usado por ZFS (12 = 4096 bytes)
-w (raw)Envío de bloques cifrados sin descifrar
BEBoot Environment — entorno de arranque de FreeBSD
tmux

Multiplexor de terminal (permite sesiones persistentes)

 

FreeBSD es genial!.

Realizar copia de seguridad del cliente solaris en disco USB

ZFS FreeBSD Copia de seguridad del servidor tormenta
Backup Manual y Recuperación

FreeBSD14.5

1. Identificar discos

geom disk list
camcontrol devlist
gpart show

En solaris, el disco USB suele aparecer como da0 o da1. Verificar con geom disk list cuál es el correcto (etiqueta ZFSBACKUP).

2. Comprobaciones previas (antes de destruir nada)

¿Tiene particiones?

gpart show da0

¿Tiene restos de ZFS?

zpool import | grep -B2 -A5 da0

¿Está montado en algún sitio?

mount | grep da0

3. Plan resumido

ComandoQué hace
gpart destroy -F da0Borra particiones
zpool labelclear -f /dev/da0Borra restos ZFS
gpart create -s gpt da0Tabla GPT nueva
gpart add -t freebsd-zfs -l ZFSBACKUP da0Partición ZFS
zpool create -o ashift=12 ... zbackup /dev/gpt/ZFSBACKUPPool zbackup
zfs create -o mountpoint=none zbackup/recovery/solarisDataset 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 zbackupCerrar limpiamente

4. Preparar el disco

gpart destroy -F da0
# → da0 destroyed

Borrar cualquier resto de ZFS (aunque no haya, por asegurar)

zpool labelclear -f /dev/da0 2>/dev/null

Crear tabla GPT nueva

gpart create -s gpt da0
# → da0 created

Crear partición ZFS ocupando todo el disco

gpart add -t freebsd-zfs -l ZFSBACKUP da0
# → da0p1 added

Verificar

gpart show da0
# →       40  3907029088  da0  GPT  (2T)
# →       40  3907029088    1  freebsd-zfs  (2T)

5. Crear el pool zbackup

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 da0 | 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 \
             zbackup /dev/gpt/ZFSBACKUP

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 zbackup
zpool list zbackup
zfs list

Crear dataset destino

zfs create -o mountpoint=none zbackup/recovery
zfs create -o mountpoint=none zbackup/recovery/solaris
zfs list -r zbackup

Salida esperada:

zbackup                     XXXG   XXXG    96K  none
zbackup/recovery            XXXG   XXXG    96K  none
zbackup/recovery/solaris    XXXG   XXXG    96K  none

Pool zbackup creado correctamente:

DatoValor
Poolzbackup
Tamaño~2 TB
Dataset destinozbackup/recovery/solaris (listo)
zroot a respaldar~220 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 solaris actual: ~30.

Nota para el futuro: si un script creó el snapshot en un solo dataset sin usar -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 zbackup/recovery/solaris

Banderas explicadas

FlagSignificado
-RRecursivo: envía zroot y todos sus hijos
-wRaw: envía los bloques cifrados tal cual (necesario si hay datasets cifrados)
-cCompresión nativa ZFS (lz4)
-vVerbose: muestra progreso por dataset
-FFuerza rollback en destino si hay divergencias
-sGuarda token de resume en /var/tmp/ (permite reanudar si se corta)
-uNo monta los datasets recibidos
-x mountpointNo replica los mountpoints del origen
Importante sobre -w: aunque solaris no tiene datasets cifrados actualmente, el -w es inofensivo si no hay cifrado. Mantener el mismo script/comando que en tormenta para consistencia y por si en el futuro se añade cifrado.

8. Salir de tmux sin matar el proceso

Ctrl+b  d

9. Monitorizar (en otra terminal)

Ver datasets llegando en tiempo real

watch -n 10 'zfs list -r zbackup/recovery/solaris | head -30'

Ver velocidad de escritura al USB

zpool iostat zbackup 5

Ver espacio consumido

watch -n 30 'zfs list zbackup'

10. 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 zbackup/recovery/solaris | wc -l

Deben coincidir.

Verificar datasets replicados

zfs list -r zbackup/recovery/solaris | head -30

Espacio usado

zfs list zbackup
zpool list zbackup

11. 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 zbackup
zfs list -r zbackup/recovery/solaris | head -20

Se verá si quedó un dataset a medias (zbackup/recovery/solaris con datos parciales).

¿Hay un token de resume guardado?

ls -la /var/tmp/ | grep -i zfs
ls -la / | grep -i zfs
El token de resume solo existe si se usó -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 zbackup/recovery/solaris
zfs create -o mountpoint=none zbackup/recovery/solaris
zfs list -r zbackup/recovery

Relanzar con -s para permitir resume

tmux new -s backup_usb

Dentro de tmux:

zfs send -Rwcv zroot@snap-20261002 \
  | zfs receive -Fsuv -x mountpoint zbackup/recovery/solaris
El flag -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.

12. Exportar el pool y desconectar el USB

Verificar que no hay nada escribiendo

zpool status zbackup
lsof | grep zbackup 2>/dev/null

Exportar limpiamente

zpool export zbackup

Y por último

sync

Ya se puede retirar el cable USB.

13. Tiempo estimado

Velocidad USB~220 GB
80 MB/s~45 min
120 MB/s~30 min
200 MB/s~18 min
400 MB/s~9 min

Con el chip ASMT USB 3.0 + disco SATA: ~15-30 min si es SSD, ~40-60 min si es HDD.

Recordatorio: para poder cerrar la sesión SSH sin que se corte el envío, primero entrar en tmux con tmux new -s backup_usb, lanzar el envío, y salir con Ctrl+b d.
Recomendación adicional: poner una etiqueta al disco físico con rotulador o adhesivo:
  • Backup Solaris
  • snap-20261002
  • zbackup pool

14. 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

15. 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

Esto destruye los snapshots posteriores a este (incluido el de before-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

ElementoEstado
pf.confVuelve al estado del snapshot
loader.confVuelve al estado del snapshot
sysctl.confVuelve al estado del snapshot
/etc/rc.confEstado del snapshot
Archivos en /home/carlosNO se pierden (dataset separado)
Archivos en /varNO se pierden (dataset separado, si no se hace rollback ahí)
Solo afecta a zroot/ROOT/default (el sistema base). Los datos personales en zroot/home/carlos no se tocan.

16. Uso del script automatizado

Solaris tiene instalado el script /root/bin/zfs-backup.sh que automatiza todo el proceso.

Ejecución manual (modelo B: USB guardado fuera)

# 1. Conectar el USB ZFSBACKUP a solaris
# 2. Ejecutar:
sh /root/bin/zfs-backup.sh

# 3. Ver el resultado
tail -20 /var/log/zfs-backup.log

# 4. Cuando termine, el script exporta el pool automáticamente
# 5. Desconectar el USB y guardarlo en lugar seguro

Qué hace el script automáticamente

  • Detecta que está en solaris y usa zbackup/zbackup/recovery/solaris/ZFSBACKUP.
  • Importa el pool zbackup si no está importado.
  • Crea el snapshot zroot@snap-YYYYMMDD (dataset por dataset, sin fallos atómicos).
  • Detecta la última snapshot en destino y envía solo el incremental.
  • Aplica retención: 7 snapshots en origen, 30 en destino.
  • Exporta el pool al terminar (para poder desconectar el USB).
  • Registra todo en /var/log/zfs-backup.log.

Frecuencia recomendada

Semanal (domingo por la tarde). Total: 5-15 minutos por backup.

17. Errores comunes a evitar

  • Usar zfs send -Rcv sin -w → falla si hay datasets cifrados.
  • Olvidar -s en zfs 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 destroy sin -n primero → riesgo de borrar snapshots con dependencias.
  • Ejecutar el script de retención sin verificar → puede borrar snapshots indiscriminadamente.
  • Importar el mismo pool en dos máquinas simultáneamente → corrompe metadatos.
  • Desconectar el USB sin zpool export → riesgo de corrupción.

18. Checklist final

  • [ ] Disco USB identificado y preparado
  • [ ] Pool zbackup creado con ashift=12
  • [ ] Dataset zbackup/recovery/solaris creado
  • [ ] 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 zbackup)
  • [ ] USB desconectado y guardado en lugar seguro
  • [ ] Clave de cifrado guardada en al menos 2 sitios distintos (si aplica)

19. Dónde guardar el USB

UbicaciónProtección
❌ Junto a la máquinaNinguna (robo/incendio afecta a ambos)
⚠️ Otra habitación de la casaProtección baja
✅ Otra planta / garaje / trasteroProtección media
✅✅ Casa de un familiar / amigoProtección alta
✅✅✅ Caja de seguridad del bancoProtección máxima

Recomendación: caja fuerte pequeña en casa + copia secundaria en casa de un familiar.

20. Verificaciones periódicas (cada 3-6 meses)

# 1. Conectar el USB ZFSBACKUP a solaris
# 2. Importar el pool
zpool import zbackup

# 3. Verificar el pool
zpool status zbackup

# 4. Contar snapshots en destino
zfs list -t snapshot -r zbackup/recovery/solaris | grep 'snap-2026' | wc -l

# 5. Ver las más recientes
zfs list -t snapshot -r zbackup/recovery/solaris | grep 'snap-2026' | sort | tail -5

# 6. Exportar
zpool export zbackup

Si todo está en orden, los datos son recuperables.

FreeBSD es genial!.

viernes, 2 de octubre de 2026

Realizar copia de seguridad del servidor tormenta en disco USB

ZFS FreeBSD Copia de seguridad del cliente solaris
Backup Manual y Recuperación

FreeBSD 14.5

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

ComandoQué hace
gpart destroy -F da1Borra particiones
zpool labelclear -f /dev/da1Borra restos ZFS
gpart create -s gpt da1Tabla GPT nueva
gpart add -t freebsd-zfs -l backup1tb da1Partición ZFS
zpool create -o ashift=12 ... zbk /dev/gpt/backup1tbPool zbk
zfs create -o mountpoint=none zbk/tormentaDataset 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 zbkCerrar 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:

DatoValor
Poolzbk
Tamaño928 G
Disponible899 G
Dataset destinozbk/tormenta (listo)
zroot a respaldar312 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.

Nota para el futuro: si un script creó el snapshot en un solo dataset sin usar -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

FlagSignificado
-RRecursivo: envía zroot y todos sus hijos
-wRaw: envía los bloques cifrados tal cual (necesario si hay datasets cifrados como zroot/nfsv4/secifrado)
-cCompresión nativa ZFS (lz4)
-vVerbose: muestra progreso por dataset
-FFuerza rollback en destino si hay divergencias
-sGuarda token de resume en /var/tmp/ (permite reanudar si se corta)
-uNo monta los datasets recibidos
-x mountpointNo replica los mountpoints del origen
Importante sobre -w: el dataset 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.

GUARDAR LA PASSPHRASE/KEYFILE
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
El token de resume solo existe si se usó -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
El flag -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 USB312 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.

Recordatorio: para poder cerrar la sesión SSH sin que se corte el envío, primero entrar en tmux con tmux new -s backup_usb, lanzar el envío, y salir con Ctrl+b d.
Recomendación adicional: poner una etiqueta al disco físico con rotulador o adhesivo:
  • 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

Esto destruye los snapshots posteriores a este (incluido el de before-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

ElementoEstado
pf.confext_if="wlan0" (vuelve atrás)
loader.confSin hw.em.eee_setting=1
sysctl.confSin dev.em.0.eee_control=0
/etc/rc.confEstado del snapshot
Archivos en /home/carlosNO se pierden (dataset separado)
Archivos en /varNO se pierden (dataset separado, si no se hace rollback ahí)
Solo afecta a zroot/ROOT/default (el sistema base). Los datos personales en zroot/home/carlos no se tocan.

17. Errores comunes a evitar

  • Usar zfs send -Rcv sin -w → falla si hay datasets cifrados.
  • Olvidar -s en zfs 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 destroy sin -n primero → 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 zbk creado con ashift=12
  • [ ] Dataset zbk/tormenta creado
  • [ ] 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
FreeBSD es genial!.

jueves, 26 de febrero de 2026

mount FreeBSD Cifrado ZFS desde liveCD y encontrar partición root

Fuente:

https://klarasystems.com/articles/manipulating-a-pool-from-the-rescue-system/
 mkdir /tmp/mountado
 geli attach /dev/nda0p4
 zpool import -f -R /tmp/montado zroot
 zfs list zroot
 NAME                            USED  AVAIL  REFER  MOUNTPOINT
zroot                            223G   211G    96K  /zroot
zroot/ROOT                      82.9G   211G    96K  none
zroot/ROOT/14.3-RELEASE-p8         8K   211G  21.1G  /
zroot/ROOT/default              82.9G   211G  21.3G  /
zroot/cache                     3.04G   211G    96K  /zroot/cache
zroot/cache/ccache              3.04G   211G  3.04G  /var/cache/ccache
zroot/home                      75.3G   211G    96K  /home
zroot/home/carlos               75.3G   211G  67.4G  /home/carlos
zroot/reserved                  50.0G   261G    96K  /zroot/reserved
zroot/tmp                        320K   211G   180K  /tmp
zroot/usr                       9.89G   211G    96K  /usr
zroot/usr/ports                 6.99G   211G  2.91G  /usr/ports
zroot/usr/src                   2.90G   211G  2.63G  /usr/src
zroot/var                       1.61G   211G    96K  /var
zroot/var/audit                   96K   211G    96K  /var/audit
zroot/var/crash                 1.60G   211G  1.60G  /var/crash
zroot/var/log                   3.11M   211G  2.00M  /var/log
zroot/var/mail                   356K   211G   260K

Propiedad canmount de zroot/ROOT/default

zfs get mountpoint,canmount,mounted zroot/ROOT/default
NAME                PROPERTY    VALUE       SOURCE
zroot/ROOT/default  mountpoint  /           local
zroot/ROOT/default  canmount    noauto      local
zroot/ROOT/default  mounted     yes         -

¿Qué hace canmount=noauto?

La propiedad canmount en ZFS controla si un dataset puede ser montado. Tiene tres valores posibles:

on - El dataset se monta automáticamente cuando es necesario (por ejemplo, al importar el pool o al ejecutar zfs mount -a).

off - El dataset no puede ser montado en absoluto.

noauto - El dataset no se monta automáticamente por operaciones generales del sistema (como zfs mount -a o la importación del pool), pero puede ser montado manualmente con zfs mount. Es un estado intermedio que lo hace "disponible pero no automático".

Montar zroot/ROOT/default con el comando mount

 zfs mount zroot/ROOT/default

Despues de finalizar los cambios exportar el zpool

zpool export zroot

Reiniciar y arrancar desde el disco duro NVMe (nda0)

 shutdown -r now
FreeBSD es genial!.