--- title: "Cómo instalar y configurar ZFS en Ubuntu 24.04" description: "Instala OpenZFS en Ubuntu 24.04, crea un pool en espejo con datasets comprimidos y automatiza snapshots, réplicas con zfs send y el scrub de los discos." category: "Almacenamiento y Copia de Seguridad Avanzada" language: es source: https://cubepath.com/es/docs/almacenamiento-y-copia-de-seguridad-avanzada/instalacion-y-configuracion-de-zfs-en-linux updated: 2026-09-25 --- # Cómo instalar y configurar ZFS en Ubuntu 24.04 ZFS es a la vez un sistema de archivos y un gestor de volúmenes: agrupa discos en un *pool*, verifica cada bloque con sumas de comprobación, repara datos corruptos a partir de la redundancia y crea snapshots instantáneos. En Linux se usa a través de OpenZFS. En este tutorial instalarás ZFS en Ubuntu 24.04, crearás un pool en espejo con dos discos, configurarás datasets con compresión y cuotas, y automatizarás snapshots, réplicas y la verificación periódica de los datos. ## Requisitos previos - Un servidor con Ubuntu 24.04 LTS, por ejemplo un servidor dedicado o un VPS de CubePath con volúmenes adicionales. - Un usuario no root con privilegios `sudo`. - Dos discos vacíos del mismo tamaño para el pool, distintos del disco del sistema. En los ejemplos aparecen como `/dev/vdb` y `/dev/vdc`. - Al menos 2 GB de RAM. ZFS usa la memoria libre como caché (ARC) y la libera cuando otros procesos la necesitan. - Para el paso 7, un segundo servidor con ZFS al que tengas acceso por SSH con clave. ## Paso 1: Instalar ZFS Ubuntu incluye el módulo del kernel de ZFS en sus kernels oficiales, así que solo necesitas las herramientas de usuario: ```bash sudo apt update sudo apt install zfsutils-linux ``` Comprueba que el módulo está cargado y la versión instalada: ```bash zfs version ``` ```output zfs-2.2.2-0ubuntu9.1 zfs-kmod-2.2.2-0ubuntu9 ``` En Debian 12 el módulo no viene incluido: instala `zfs-dkms` y `zfsutils-linux` desde el repositorio `contrib`, que compila el módulo para tu kernel. En Rocky Linux 9 se usa el repositorio de OpenZFS (`zfs-release`). ## Paso 2: Identificar los discos Localiza los discos vacíos: ```bash lsblk -o NAME,SIZE,TYPE,MOUNTPOINTS ``` ```output NAME SIZE TYPE MOUNTPOINTS vda 40G disk ├─vda1 39G part / ... vdb 100G disk vdc 100G disk ``` Los nombres `/dev/sdX` o `/dev/vdX` pueden cambiar entre arranques. Para crear el pool es preferible usar los nombres estables de `/dev/disk/by-id/`: ```bash ls -l /dev/disk/by-id/ | grep -E 'vdb|vdc' ``` ```output lrwxrwxrwx 1 root root 9 Sep 25 10:00 virtio-disk-data1 -> ../../vdb lrwxrwxrwx 1 root root 9 Sep 25 10:00 virtio-disk-data2 -> ../../vdc ``` En discos físicos verás nombres como `ata-WDC_WD40EFRX-..._WD-XXXX` o `nvme-Samsung_SSD_...`. Si tu VPS no muestra entradas en `by-id`, usa `/dev/vdb` y `/dev/vdc`; ZFS identifica los discos por sus etiquetas internas al importar el pool. ## Paso 3: Crear un pool en espejo Un espejo (*mirror*) guarda una copia completa de los datos en cada disco y tolera la pérdida de uno de ellos. Crea el pool `tank`: ```bash sudo zpool create -o ashift=12 -O compression=lz4 -O atime=off -O xattr=sa \ -O mountpoint=/tank tank mirror \ /dev/disk/by-id/virtio-disk-data1 /dev/disk/by-id/virtio-disk-data2 ``` - `-o ashift=12` alinea las escrituras a sectores de 4 KiB, correcto para casi cualquier disco moderno. No se puede cambiar después. - `-O compression=lz4` activa una compresión muy rápida que suele ahorrar espacio y E/S. - `-O atime=off` evita escribir la hora de acceso en cada lectura. - `-O xattr=sa` guarda los atributos extendidos de forma más eficiente. Las propiedades con `-O` se heredan en todos los datasets que crees dentro del pool. Comprueba el estado: ```bash zpool status tank ``` ```output pool: tank state: ONLINE config: NAME STATE READ WRITE CKSUM tank ONLINE 0 0 0 mirror-0 ONLINE 0 0 0 virtio-disk-data1 ONLINE 0 0 0 virtio-disk-data2 ONLINE 0 0 0 errors: No known data errors ``` Con cuatro o más discos puedes usar `raidz1` (tolera un fallo), `raidz2` (dos fallos) o varios espejos (`mirror a b mirror c d`). Para bases de datos y máquinas virtuales, los espejos ofrecen mejor rendimiento aleatorio. ## Paso 4: Crear datasets Los datasets son sistemas de archivos independientes dentro del pool, cada uno con sus propias propiedades, cuotas y snapshots. Crea uno para las copias de seguridad y otro para una base de datos: ```bash sudo zfs create tank/backups sudo zfs create -o recordsize=16K tank/mysql ``` `recordsize=16K` coincide con el tamaño de página de InnoDB y mejora el rendimiento de MySQL. El valor por defecto, 128K, es adecuado para archivos grandes. Limita el espacio que puede ocupar `tank/backups` y cambia su compresión a zstd, más lenta pero con mayor ratio: ```bash sudo zfs set quota=50G tank/backups sudo zfs set compression=zstd tank/backups ``` Comprueba los datasets y sus propiedades: ```bash zfs list -o name,used,avail,quota,compression,mountpoint ``` ```output NAME USED AVAIL QUOTA COMPRESS MOUNTPOINT tank 756K 96.4G none lz4 /tank tank/backups 96K 50.0G 50G zstd /tank/backups tank/mysql 96K 96.4G none lz4 /tank/mysql ``` Los datasets se montan automáticamente en el arranque. Copia algunos datos para comprobar la compresión: ```bash sudo cp -r /usr/share/doc /tank/backups/ zfs get compressratio tank/backups ``` ```output NAME PROPERTY VALUE SOURCE tank/backups compressratio 3.12x - ``` > Nota: evita activar `dedup`. La deduplicación necesita mucha RAM para sus tablas y rara vez compensa frente a la compresión. ## Paso 5: Trabajar con snapshots Un snapshot es una copia de solo lectura de un dataset en un momento dado. Se crea al instante y solo ocupa espacio a medida que los datos cambian. Crea uno: ```bash sudo zfs snapshot tank/backups@antes-de-limpiar ``` Simula un error borrando datos: ```bash sudo rm -rf /tank/backups/doc ``` Los snapshots son accesibles en el directorio oculto `.zfs/snapshot`, desde donde puedes recuperar archivos sueltos: ```bash ls /tank/backups/.zfs/snapshot/antes-de-limpiar/ ``` ```output doc ``` Para devolver el dataset completo al estado del snapshot, usa `rollback`. Se pierden todos los cambios posteriores al snapshot: ```bash sudo zfs rollback tank/backups@antes-de-limpiar ls /tank/backups ``` ```output doc ``` Lista los snapshots existentes: ```bash zfs list -t snapshot ``` ```output NAME USED AVAIL REFER MOUNTPOINT tank/backups@antes-de-limpiar 0B - 45.2M - ``` ## Paso 6: Automatizar snapshots con Sanoid Sanoid crea y elimina snapshots según una política de retención. Instálalo desde los repositorios de Ubuntu: ```bash sudo apt install sanoid ``` Crea su archivo de configuración: ```bash sudo mkdir -p /etc/sanoid sudo nano /etc/sanoid/sanoid.conf ``` Esta configuración mantiene 36 snapshots horarios, 30 diarios y 3 mensuales de `tank` y de todos sus datasets hijos: ```ini [tank] use_template = production recursive = yes [template_production] frequently = 0 hourly = 36 daily = 30 monthly = 3 yearly = 0 autosnap = yes autoprune = yes ``` El paquete incluye un temporizador de systemd que ejecuta Sanoid cada 15 minutos. Asegúrate de que está activo: ```bash sudo systemctl enable --now sanoid.timer systemctl list-timers sanoid.timer ``` Fuerza una ejecución y comprueba que aparecen los snapshots: ```bash sudo sanoid --cron --verbose zfs list -t snapshot -o name | grep autosnap | head ``` ```output tank@autosnap_2026-09-25_10:15:02_monthly tank@autosnap_2026-09-25_10:15:02_daily tank@autosnap_2026-09-25_10:15:02_hourly tank/backups@autosnap_2026-09-25_10:15:02_monthly ... ``` ## Paso 7: Replicar un dataset a otro servidor `zfs send` convierte un snapshot en un flujo de datos y `zfs receive` lo reconstruye en otro pool, conservando propiedades y snapshots. Es la forma nativa de hacer copias de seguridad fuera del servidor. En el servidor de destino (`backup.your_domain`), que debe tener un pool llamado `backup`, crea el dataset contenedor: ```bash sudo zfs create backup/replicas ``` En el servidor de origen, crea un snapshot y envíalo completo. La opción `-u` evita que el dataset recibido se monte en el destino: ```bash sudo zfs snapshot tank/mysql@repl-1 sudo zfs send tank/mysql@repl-1 | ssh root@backup.your_domain zfs receive -u backup/replicas/mysql ``` Los envíos siguientes solo transfieren los bloques que han cambiado entre dos snapshots (`-i`): ```bash sudo zfs snapshot tank/mysql@repl-2 sudo zfs send -i tank/mysql@repl-1 tank/mysql@repl-2 | ssh root@backup.your_domain zfs receive -u backup/replicas/mysql ``` Comprueba en el destino que los dos snapshots han llegado: ```bash ssh root@backup.your_domain zfs list -t snapshot -r backup/replicas/mysql ``` ```output NAME USED AVAIL REFER MOUNTPOINT backup/replicas/mysql@repl-1 56K - 104K - backup/replicas/mysql@repl-2 0B - 104K - ``` Para automatizarlo, el paquete `sanoid` incluye `syncoid`, que calcula los snapshots incrementales por ti. Esta orden hace la misma réplica y se puede programar con cron o un temporizador de systemd: ```bash sudo syncoid tank/mysql root@backup.your_domain:backup/replicas/mysql ``` ## Paso 8: Verificar los discos con scrub Un *scrub* lee todos los bloques del pool, verifica sus sumas de comprobación y repara los datos dañados usando la otra copia del espejo. Lánzalo manualmente: ```bash sudo zpool scrub tank zpool status tank | grep scan ``` ```output scan: scrub repaired 0B in 00:00:12 with 0 errors on Fri Sep 25 10:30:14 2026 ``` Ubuntu ya programa un scrub mensual de todos los pools. Comprueba la tarea que instala el paquete: ```bash cat /etc/cron.d/zfsutils-linux ``` Si un disco falla, `zpool status` mostrará el pool como `DEGRADED`. Tras instalar el disco nuevo, sustitúyelo en el pool y ZFS reconstruirá la copia (*resilver*): ```bash sudo zpool replace tank /dev/disk/by-id/virtio-disk-data2 /dev/disk/by-id/virtio-disk-data3 ``` ## Paso 9: Limitar la memoria de la caché ARC (opcional) Por defecto, ARC puede usar hasta la mitad de la RAM en Ubuntu 24.04. En un servidor que también ejecuta aplicaciones con mucha memoria, como una base de datos, conviene limitarla. Para fijar un máximo de 4 GiB (4 × 1024³ = 4294967296 bytes), aplícalo en caliente: ```bash echo 4294967296 | sudo tee /sys/module/zfs/parameters/zfs_arc_max ``` Hazlo persistente creando `/etc/modprobe.d/zfs.conf`: ```bash sudo nano /etc/modprobe.d/zfs.conf ``` ```text options zfs zfs_arc_max=4294967296 ``` Comprueba el tamaño máximo actual de ARC: ```bash arc_summary -s arc | grep -i "max size" ``` ```output Max size (high water): 16:1 4.0 GiB ``` ## Solución de problemas - **`zpool create` falla con `/dev/vdb is in use` o `contains a filesystem`**: el disco tiene una tabla de particiones o datos anteriores. Si estás seguro de que puede borrarse, ejecuta `sudo wipefs -a /dev/vdb` y repite. - **El pool no aparece tras reiniciar**: impórtalo con `sudo zpool import tank`. Si el problema se repite, comprueba que `zfs-import-cache.service` y `zfs-mount.service` están habilitados. - **`zfs receive` falla con `destination has been modified`**: el dataset de destino ha cambiado desde el último snapshot recibido, normalmente porque estaba montado. Recibe siempre con `-u` o añade `-F` al receive para descartar esos cambios en el destino. ## Conclusión Tienes un pool ZFS en espejo con datasets comprimidos, snapshots automáticos con Sanoid, réplicas incrementales a otro servidor y scrubs periódicos. Como siguientes pasos puedes programar `syncoid` con un temporizador de systemd para tener copias externas diarias, crear volúmenes de bloques (`zfs create -V`) para máquinas virtuales o activar el cifrado nativo en datasets nuevos con `-o encryption=on`.