--- title: "How to Set Up Software RAID with mdadm on Ubuntu 24.04" description: "Create a software RAID 1 array with mdadm on Ubuntu 24.04, mount it at boot, monitor its health and replace a failed disk, with notes for RAID 5, 6 and 10." category: "Storage Management" language: en source: https://cubepath.com/docs/storage-management/software-raid-configuration-with-mdadm updated: 2026-09-25 --- # How to Set Up Software RAID with mdadm on Ubuntu 24.04 `mdadm` is the standard Linux tool for software RAID: it combines several disks into one block device (`/dev/md0`) that survives the failure of a disk or runs faster than a single one, without a hardware RAID controller. In this tutorial you will build a RAID 1 (mirror) array from two data disks on Ubuntu 24.04, format and mount it, make it assemble at boot, set up monitoring and practice replacing a failed disk. The last section shows the commands for RAID 5, 6 and 10. ## Prerequisites To follow this guide you need: - A server running Ubuntu 24.04 LTS with a non-root user that has `sudo` privileges. Software RAID is most useful on dedicated servers, such as a CubePath bare metal server, with several physical disks. - Two empty disks of the same size for the array. This guide uses `/dev/sdb` and `/dev/sdc`; the operating system is on `/dev/sda`. - A backup of anything on those two disks. Creating the array erases them. > Warning: RAID protects against a disk failing, not against deleting files, ransomware or a corrupted filesystem. Keep separate backups. ## Choosing a RAID level | Level | Minimum disks | Usable capacity | Disks that can fail | Typical use | |-------|---------------|-----------------|---------------------|-------------| | RAID 0 | 2 | All disks | None | Scratch space where speed matters and data is disposable | | RAID 1 | 2 | One disk | All but one | Boot and data disks on small servers | | RAID 5 | 3 | All but one | 1 | Read-heavy storage with 3 or 4 disks | | RAID 6 | 4 | All but two | 2 | Large arrays of big disks, where rebuilds take many hours | | RAID 10 | 4 | Half | 1 per mirror pair | Databases and virtual machines: speed and redundancy | With two disks, RAID 1 is the only level that gives redundancy, so it is what this guide builds. ## Step 1 - Installing mdadm and identifying the disks `mdadm` is usually preinstalled on Ubuntu Server. Make sure it is present: ```bash sudo apt update sudo apt install mdadm ``` List the disks with their size, type and mount point: ```bash lsblk -o NAME,SIZE,TYPE,FSTYPE,MOUNTPOINTS ``` ```output NAME SIZE TYPE FSTYPE MOUNTPOINTS sda 480G disk ├─sda1 1G part vfat /boot/efi └─sda2 479G part ext4 / sdb 1.8T disk sdc 1.8T disk ``` `sdb` and `sdc` have no partitions and no filesystem. If `lsblk -f` shows an old `linux_raid_member` or filesystem signature on them, wipe it first with `sudo wipefs -a /dev/sdb /dev/sdc`, after making sure these are the right disks. ## Step 2 - Partitioning the disks You can build an array from whole disks, but a partition of type "Linux RAID" makes the disk's purpose obvious to other tools and to anyone who looks at it later. Create a GPT table with one partition that fills each disk, using `sgdisk` from the `gdisk` package: ```bash sudo apt install gdisk sudo sgdisk -o -n 1:0:0 -t 1:FD00 /dev/sdb sudo sgdisk -o -n 1:0:0 -t 1:FD00 /dev/sdc ``` `-o` creates a new GPT table, `-n 1:0:0` creates partition 1 from the first to the last usable sector, and `FD00` is the Linux RAID type code. Check the result: ```bash lsblk /dev/sdb /dev/sdc ``` ```output NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS sdb 8:16 0 1.8T 0 disk └─sdb1 8:17 0 1.8T 0 part sdc 8:32 0 1.8T 0 disk └─sdc1 8:33 0 1.8T 0 part ``` ## Step 3 - Creating the RAID 1 array Create `/dev/md0` as a RAID 1 array with two members: ```bash sudo mdadm --create /dev/md0 --level=1 --raid-devices=2 /dev/sdb1 /dev/sdc1 ``` `mdadm` warns that this metadata format is not ideal for a boot device. That does not matter for a data array. Answer `y`: ```output mdadm: Note: this array has metadata at the start and may not be suitable as a boot device. If you plan to store '/boot' on this device please ensure that your boot-loader understands md/v1.x metadata, or use --metadata=0.90 Continue creating array? y mdadm: Defaulting to version 1.2 metadata mdadm: array /dev/md0 started. ``` The array is usable right away, while the kernel copies one disk onto the other in the background. Follow the initial sync in `/proc/mdstat`: ```bash cat /proc/mdstat ``` ```output Personalities : [raid1] [linear] [multipath] [raid0] [raid6] [raid5] [raid4] [raid10] md0 : active raid1 sdc1[1] sdb1[0] 1953381376 blocks super 1.2 [2/2] [UU] [>....................] resync = 2.4% (46880768/1953381376) finish=158.2min speed=200862K/sec bitmap: 15/15 pages [60KB], 65536KB chunk unused devices: ``` `[2/2] [UU]` means both members are up. An underscore, as in `[U_]`, marks a missing or failed disk. The `bitmap` line shows the write-intent bitmap that `mdadm` adds automatically on large arrays: after an unclean shutdown only the regions that changed are resynced, not the whole disk. Use `watch -n 5 cat /proc/mdstat` to follow the progress. You can continue with the next steps while it runs. ## Step 4 - Creating a filesystem and mounting it Format the array with ext4 and create a mount point: ```bash sudo mkfs.ext4 -L raid1 /dev/md0 sudo mkdir -p /mnt/raid1 ``` Get the filesystem UUID, which is what you will use in `/etc/fstab`: ```bash sudo blkid /dev/md0 ``` ```output /dev/md0: LABEL="raid1" UUID="5c0e9a7d-2f41-4d6b-9e1a-8b3c7f2d4a60" BLOCK_SIZE="4096" TYPE="ext4" ``` Open the file: ```bash sudo nano /etc/fstab ``` Add this line at the end, with your UUID: ```text UUID=5c0e9a7d-2f41-4d6b-9e1a-8b3c7f2d4a60 /mnt/raid1 ext4 defaults,nofail 0 2 ``` `nofail` lets the server boot even if the array cannot be assembled, instead of stopping in emergency mode. Validate the file and mount it: ```bash sudo findmnt --verify sudo systemctl daemon-reload sudo mount -a df -h /mnt/raid1 ``` ```output Filesystem Size Used Avail Use% Mounted on /dev/md0 1.8T 28K 1.7T 1% /mnt/raid1 ``` ## Step 5 - Making the array assemble at boot Record the array in `/etc/mdadm/mdadm.conf` so it is assembled with the same name at every boot. Without this, it often comes back as `/dev/md127`: ```bash sudo mdadm --detail --scan | sudo tee -a /etc/mdadm/mdadm.conf ``` ```output ARRAY /dev/md0 metadata=1.2 UUID=3f8e2a1b:7c4d9e05:a2b6f1c3:8d0e4f72 ``` Ubuntu assembles arrays early in the boot process from the initramfs, so rebuild it to include the new configuration: ```bash sudo update-initramfs -u ``` Reboot, then confirm the array is `md0`, active and mounted: ```bash cat /proc/mdstat findmnt /mnt/raid1 ``` ## Step 6 - Monitoring the array Check the full state of an array at any time: ```bash sudo mdadm --detail /dev/md0 ``` ```output /dev/md0: Version : 1.2 Raid Level : raid1 Array Size : 1953381376 (1862.89 GiB 2000.26 GB) Raid Devices : 2 Total Devices : 2 State : clean Active Devices : 2 Working Devices : 2 Failed Devices : 0 Spare Devices : 0 Number Major Minor RaidDevice State 0 8 17 0 active sync /dev/sdb1 1 8 33 1 active sync /dev/sdc1 ``` `State : clean` and `Failed Devices : 0` are what you want to see. `mdadm` also runs as a monitoring daemon and sends an email when a disk fails. It uses the `MAILADDR` line in `/etc/mdadm/mdadm.conf`, which is `root` by default. Open the file: ```bash sudo nano /etc/mdadm/mdadm.conf ``` Set the address that should receive alerts: ```text MAILADDR admin@your_domain ``` Mail delivery requires a working mail transfer agent on the server (for example Postfix configured to relay through your mail provider). Send a test alert for every array to check the whole chain: ```bash sudo mdadm --monitor --scan --oneshot --test ``` The Ubuntu `mdadm` package also schedules a periodic consistency check of all arrays. To run one by hand, which reads both disks and compares them: ```bash echo check | sudo tee /sys/block/md0/md/sync_action ``` When it finishes (`cat /proc/mdstat` no longer shows `check`), the number of mismatched blocks should be 0: ```bash cat /sys/block/md0/md/mismatch_cnt ``` ```output 0 ``` Combine this with SMART monitoring (`sudo apt install smartmontools`, then `sudo smartctl -H /dev/sdb`) to catch disks that are about to fail. ## Step 7 - Replacing a failed disk Practice the replacement procedure now, while the data is not critical, so you know it works. First, mark `sdc1` as failed to simulate a broken disk: ```bash sudo mdadm --manage /dev/md0 --fail /dev/sdc1 cat /proc/mdstat ``` ```output md0 : active raid1 sdc1[1](F) sdb1[0] 1953381376 blocks super 1.2 [2/1] [U_] ``` The array keeps working on one disk (`[U_]`), and the mount point stays available. Remove the failed member from the array: ```bash sudo mdadm --manage /dev/md0 --remove /dev/sdc1 ``` ```output mdadm: hot removed /dev/sdc1 from /dev/md0 ``` With a real failure, you would now replace the physical disk. Before pulling a disk, note its serial number with `sudo smartctl -i /dev/sdc` so you remove the right one. When the new disk is installed, copy the partition table from the healthy disk to it, then give it new unique GUIDs. The first command copies **from** `sdb` **to** `sdc`, so double check the order: ```bash sudo sgdisk /dev/sdb -R /dev/sdc sudo sgdisk -G /dev/sdc ``` Add the new partition to the array: ```bash sudo mdadm --manage /dev/md0 --add /dev/sdc1 ``` The array starts rebuilding onto the new disk: ```bash cat /proc/mdstat ``` ```output md0 : active raid1 sdc1[2] sdb1[0] 1953381376 blocks super 1.2 [2/1] [U_] [=>...................] recovery = 6.3% (123057152/1953381376) finish=151.9min speed=200774K/sec ``` When the recovery reaches 100%, the status returns to `[2/2] [UU]`. In this simulation, the rebuild of the same disk finishes much faster thanks to the write-intent bitmap. Rebuild speed is limited so it does not starve normal I/O. If the server is idle and you want it to finish sooner, raise the minimum speed (in KB/s) temporarily: ```bash sudo sysctl -w dev.raid.speed_limit_min=100000 ``` ## Other RAID levels The rest of the workflow (filesystem, `fstab`, `mdadm.conf`, `update-initramfs`) is identical for every level. Only the create command changes. Partition each disk as in Step 2 first. RAID 5 with three disks: ```bash sudo mdadm --create /dev/md0 --level=5 --raid-devices=3 /dev/sdb1 /dev/sdc1 /dev/sdd1 ``` RAID 6 with four disks: ```bash sudo mdadm --create /dev/md0 --level=6 --raid-devices=4 /dev/sdb1 /dev/sdc1 /dev/sdd1 /dev/sde1 ``` RAID 10 with four disks: ```bash sudo mdadm --create /dev/md0 --level=10 --raid-devices=4 /dev/sdb1 /dev/sdc1 /dev/sdd1 /dev/sde1 ``` To add a hot spare that takes over automatically when a member fails, add an extra partition to an array that is already complete: ```bash sudo mdadm --manage /dev/md0 --add /dev/sdf1 ``` It appears with an `(S)` next to it in `/proc/mdstat`. ## Removing an array If you need to dismantle the array, unmount it and remove its `/etc/fstab` line first, then stop it and erase the RAID metadata from its members: ```bash sudo umount /mnt/raid1 sudo mdadm --stop /dev/md0 sudo mdadm --zero-superblock /dev/sdb1 /dev/sdc1 ``` Delete the `ARRAY /dev/md0` line from `/etc/mdadm/mdadm.conf` and run `sudo update-initramfs -u` again. ## Troubleshooting **The array appears as `/dev/md127` after a reboot.** It is not listed in `/etc/mdadm/mdadm.conf` or the initramfs was not updated. Repeat Step 5. Because `fstab` uses the filesystem UUID, the mount keeps working even with the wrong name. **The array is `inactive` in `/proc/mdstat`.** It was only partly assembled at boot. Stop it and assemble it again from the configuration: ```bash sudo mdadm --stop /dev/md127 sudo mdadm --assemble --scan ``` **`mdadm: Cannot open /dev/sdX1: Device or resource busy` when creating the array.** The partition is mounted or already part of an array that the kernel auto-assembled from old metadata. Check `cat /proc/mdstat`, stop that array, and wipe the old signatures with `sudo wipefs -a` on the partition. **A disk is marked faulty but SMART shows no errors.** A cable or controller glitch can cause this. Remove it and add it back with `--remove` and `--add` as in Step 7, then watch `sudo smartctl -a` and the kernel log (`sudo journalctl -k`) closely. If it fails again, replace it. ## Conclusion You built a RAID 1 array with `mdadm`, mounted it by UUID, made it assemble at boot, set up alerts and consistency checks, and rehearsed replacing a failed disk. As next steps, put LVM on top of `/dev/md0` for flexible volumes, schedule SMART self-tests with `smartd`, and set up off-server backups, since RAID keeps the server running but does not protect your data from deletion or corruption.