惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

C
CERT Recently Published Vulnerability Notes
K
Kaspersky official blog
S
Schneier on Security
Latest news
Latest news
Cisco Talos Blog
Cisco Talos Blog
T
Threatpost
T
Tor Project blog
T
Tenable Blog
The Register - Security
The Register - Security
T
Threat Research - Cisco Blogs
阮一峰的网络日志
阮一峰的网络日志
F
Fortinet All Blogs
D
Darknet – Hacking Tools, Hacker News & Cyber Security
V
Visual Studio Blog
Google DeepMind News
Google DeepMind News
H
Help Net Security
博客园_首页
I
Intezer
aimingoo的专栏
aimingoo的专栏
Last Week in AI
Last Week in AI
Project Zero
Project Zero
Recorded Future
Recorded Future
C
Cybersecurity and Infrastructure Security Agency CISA
Vercel News
Vercel News
A
Arctic Wolf
P
Palo Alto Networks Blog
The Hacker News
The Hacker News
博客园 - 三生石上(FineUI控件)
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
P
Proofpoint News Feed
S
SegmentFault 最新的问题
Know Your Adversary
Know Your Adversary
P
Privacy & Cybersecurity Law Blog
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
P
Proofpoint News Feed
P
Privacy International News Feed
G
GRAHAM CLULEY
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
罗磊的独立博客
Simon Willison's Weblog
Simon Willison's Weblog
C
CXSECURITY Database RSS Feed - CXSecurity.com
Scott Helme
Scott Helme
T
The Exploit Database - CXSecurity.com
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Security Latest
Security Latest
Cyberwarzone
Cyberwarzone
L
Lohrmann on Cybersecurity
C
Cisco Blogs
C
Cyber Attacks, Cyber Crime and Cyber Security
AWS News Blog
AWS News Blog

DigitalOcean Community Tutorials

Mastering grep with Regular Expressions for Efficient Text Search It's Time to Break Up with Your Cloud: Why AI Teams are Switching We Built a Private-Document AI App to Test Platform Security. Here Is What We Could Actually Verify. PostgreSQL Explained: A Complete Beginner-to-Advanced Guide How To Install and Configure Postfix on Ubuntu How To Build a Web Application Using Flask in Python 3 Build AI Reading List with DigitalOcean Functions and Mistral How To Concatenate Strings in Python How to Allow MySQL Remote Access Securely How To Install and Use Docker on Rocky Linux How To Build a Multi-Agent AI System with Docker Agent DSPy Use Cases: Build Optimized LLM Pipelines How To Submit AJAX Forms with jQuery Build an AI-Powered GPU Fleet Optimizer with the DigitalOcean AI Platform ADK Monitor GPU Utilization in Real Time: A Complete Guide Reduce File Size of Images in Linux - CLI and GUI methods Reduce PDF File Size in Linux: Tools and Methods How To Set Up a Private Docker Registry on Ubuntu How To Troubleshoot Terraform: Errors and Fixes How to Use Go Modules Python Multiprocessing Example: Process, Pool & Queue Convert Class Components to Functional Components with React Hooks How To Install and Configure Ansible on Ubuntu LLM Tokenizers Simplified: BPE, SentencePiece, and More How To Monitor System Authentication Logs on Ubuntu How to Use Traceroute and MTR to Diagnose Network Issues How to Deploy Postgres to Kubernetes Cluster Importing Packages in Go: A Complete Guide How To Make an HTTP Server in Go How To Set Up Time Synchronization on Ubuntu How To Use Struct Tags in Go apt-key Deprecation: Add Repositories with GPG on Ubuntu Linux ps Command: 20 Real-World Examples Python struct.pack and struct.unpack for Binary Data Deadlock in Java: Examples, Detection, and Prevention How To Use Find and Locate to Search for Files on Linux Structured Resume Skill Extraction Using Mistral-7B Inference How to Use the Python Main Function How to Set Up NemoClaw on a DigitalOcean Droplet with 1-Click Build an End-to-End RAG Pipeline for LLM Applications From Single to Multi-Agent Systems: Key Infrastructure Needs Back Up Data to Object Storage Using Restic How to Generate Videos with LTX-2.3 on DigitalOcean GPU Droplets How To Install LAMP Stack (Apache, MySQL, PHP) on Ubuntu How to Download Files with cURL How To Use Variadic Functions in Go Generate UUIDs with uuidgen on Linux How To Use EJS to Template Your Node Application How to Install Node.js on Ubuntu (Step-by-Step Guide) MongoDB Indexes: Improve Query Performance with Node.js LLM Tool Calling with DigitalOcean AI Platform and Databases What are Text Diffusion Models? - An Overview Crafting a Game from Scratch with GPT-5.4 Building Long-Term Memory in AI Agents with LangGraph and Mem0 How To Install PHP 7.4 and Set Up a Local Development Environment on Ubuntu 20.04 Build a GraphQL API in Go to Upload Files to Spaces How To Lint and Format Code with ESLint in Visual Studio Code Train YOLO26 for Retail Object Detection on DigitalOcean GPUs How To Work with JSON in MySQL How to Use the JavaScript .map() Method Building a Scalable App with MongoDB Using DigitalOcean's MCP Server How to Create an SSH Key in Linux: Easy Step-by-Step Guide Measure MySQL Query Performance with mysqlslap How To Use *args and **kwargs in Python 3 Nemotron 3 helped me find the perfect dish rack? A2A vs MCP - How These AI Agent Protocols Actually Differ How To Install and Manage Supervisor Docker Container Images with Watchtower on Ubuntu Getting Started with Qwen3.5 Vision-Language Models How To Create a New Sudo-Enabled User on Ubuntu How to Use Ansible to Install and Set Up Docker on Ubuntu How To Enable Remote Desktop Protocol Using xrdp on Ubuntu 22.04 How To Convert a String to a List in Python How To Check If a String Contains Another String in Python How to Read a Properties File in Python Python Command Line Arguments: sys.argv, argparse, getopt Mastering Grep command in Linux/Unix: A Beginner's Tutorial Understanding Python Data Types How to Implement a Stack in C With Code Examples Python os.system() vs subprocess: Run System Commands How To Install and Use Docker Compose on Ubuntu How to Add and Delete Users on Ubuntu How To Order Query Results in Laravel Eloquent How To Define and Use Handlers in Ansible Playbooks How To Install and Use SQLite on Ubuntu How To Install and Use Homebrew on macOS How To Manage DateTime with Carbon in Laravel and PHP How To Install Git on Ubuntu How To Install and Secure Redis on Ubuntu How To Build and Install Go Programs on Linux Using ldflags to Set Version Information for Go Applications How To Build a Node.js Application with Docker How To Add JavaScript to HTML How To Reset Your MySQL or MariaDB Root Password How To Add Images in Markdown How To Set Up a Production Elasticsearch Cluster with Ansible How To Set Up a Firewall Using firewalld on CentOS Understanding Systemd Units and Unit Files How To Set Up Replication in MySQL How To Use the .htaccess File
Create RAID Arrays with mdadm on Ubuntu
2026-03-25 · via DigitalOcean Community Tutorials

Introduction

mdadm is the standard Linux utility for creating and managing software RAID arrays. It lets you combine multiple raw block devices into a single logical device with configurable performance, redundancy, or both, without requiring dedicated hardware.

This guide walks through creating RAID 0, 1, 5, 6, and 10 arrays on Ubuntu using mdadm. For each level you will identify component disks, create the array, format and mount it, and persist the configuration across reboots. A dedicated section covers array monitoring, disk failure handling, failed disk replacement, and a comparison of mdadm software RAID against ZFS and LVM.

Key Takeaways

  • RAID 0 maximises capacity and throughput but provides no redundancy.
  • RAID 1 mirrors data across two disks; one disk can fail without data loss.
  • RAID 5 distributes parity across three or more disks; one disk can fail.
  • RAID 6 adds a second parity block; two disks can fail simultaneously.
  • RAID 10 combines striping and mirroring for performance and redundancy.
  • Persisting an array requires three steps: update /etc/mdadm/mdadm.conf, run update-initramfs -u, and add the device to /etc/fstab.

Prerequisites

To follow the steps in this guide, you will need:

  • A non-root user with sudo privileges on an Ubuntu server. To learn how to set up an account with these privileges, follow our Ubuntu initial server setup guide.
  • A basic understanding of RAID terminology and concepts. To learn more about RAID and what RAID level is right for you, read Introduction to RAID.
  • Multiple raw storage devices available on your server. The examples in this tutorial demonstrate how to configure various types of arrays on the server. As such, you will need some drives to configure.
  • Depending on the array type, you will need two to four storage devices. These drives do not need to be formatted prior to following this guide.

Info: Due to the inefficiency of RAID setups on virtual private servers, we don’t recommend deploying a RAID setup on DigitalOcean droplets. The efficiency of data center disk replication makes the benefits of a RAID negligible relative to a setup on bare-metal hardware. This tutorial aims to be a reference for a conventional RAID setup.

Resetting Existing RAID Devices (Optional)

You can skip this section for now if you have not yet set up any arrays. This guide will introduce a number of different RAID levels. If you wish to follow along and complete each RAID level for your devices, you will likely want to reuse your storage devices after each section. This specific section Resetting Existing RAID Devices can be referenced to reset your component storage devices prior to testing a new RAID level.

Warning: This process will completely destroy the array and any data written to it. Make sure that you are operating on the correct array and that you have copied any data you need to retain prior to destroying the array.

Begin by finding the active arrays in the /proc/mdstat file:

  1. cat /proc/mdstat

Output

Personalities : [raid0] [linear] [multipath] [raid1] [raid6] [raid5] [raid4] [raid10] md0 : active raid0 sdc[1] sdd[0] 209584128 blocks super 1.2 512k chunks unused devices: <none>

Then unmount the array from the filesystem:

  1. sudo umount /dev/md0

Now stop and remove the array:

  1. sudo mdadm --stop /dev/md0

Find the devices that were used to build the array with the following command:

Warning: Keep in mind that the /dev/sd* names can change any time you reboot. Check them every time to make sure you are operating on the correct devices.

  1. lsblk -o NAME,SIZE,FSTYPE,TYPE,MOUNTPOINT

Output

NAME SIZE FSTYPE TYPE MOUNTPOINT sda 100G linux_raid_member disk sdb 100G linux_raid_member disk sdc 100G disk sdd 100G disk vda 25G disk ├─vda1 24.9G ext4 part / ├─vda14 4M part └─vda15 106M vfat part /boot/efi vdb 466K iso9660 disk

The linux_raid_member value in the FSTYPE column identifies disks that are currently part of a RAID array. After identifying them, zero their superblock, which holds the RAID metadata. Zeroing the superblock removes that metadata and returns the disk to a plain, unformatted state:

  1. sudo mdadm --zero-superblock /dev/sda
  2. sudo mdadm --zero-superblock /dev/sdb

It’s recommended to also remove any persistent references to the array. Edit the /etc/fstab file and comment out or remove the reference to your array. You can comment it out by inserting a hashtag symbol # at the beginning of the line, using nano or your preferred text editor:

  1. sudo nano /etc/fstab

/etc/fstab

. . .
# /dev/md0 /mnt/md0 ext4 defaults,nofail,discard 0 0

Also, comment out or remove the array definition from the /etc/mdadm/mdadm.conf file:

  1. sudo nano /etc/mdadm/mdadm.conf

/etc/mdadm/mdadm.conf

. . .
# ARRAY /dev/md0 metadata=1.2 name=mdadmwrite:0 UUID=7261fb9c:976d0d97:30bc63ce:85e76e91

Finally, update the initramfs again so that the early boot process does not try to bring an unavailable array online:

  1. sudo update-initramfs -u

From here, you should be ready to reuse the storage devices individually, or as components of a different array.

Creating a RAID 0 Array

The RAID 0 array works by breaking up data into chunks and striping it across the available disks. This means that each disk contains a portion of the data and that multiple disks will be referenced when retrieving information.

  • Requirements: Minimum of 2 storage devices.
  • Primary benefit: Full aggregate capacity and maximum sequential throughput. Two 100G disks give you a single 200G device with roughly double the read/write bandwidth of a single disk.
  • When to use it: Scratch disks, video editing working storage, caching layers, or any workload where speed matters and data is either disposable or backed up elsewhere.
  • Critical limitation: A single disk failure destroys the entire array with no recovery path. Do not use RAID 0 for any data you cannot afford to lose. Always maintain an independent backup.

Identifying the Component Devices (RAID 0)

To start, find the identifiers for the raw disks that you will be using:

  1. lsblk -o NAME,SIZE,FSTYPE,TYPE,MOUNTPOINT

Output

NAME SIZE FSTYPE TYPE MOUNTPOINT sda 100G disk sdb 100G disk vda 25G disk ├─vda1 24.9G ext4 part / ├─vda14 4M part └─vda15 106M vfat part /boot/efi vdb 466K iso9660 disk

In this example, you have two disks without a filesystem, each 100G in size. These devices have been given the /dev/sda and /dev/sdb identifiers for this session and will be the raw components used to build the array. The vda device is the system disk. The vdb entry with iso9660 filesystem is a read-only cloud-init or metadata disk attached by the hypervisor — you can ignore it. You are only working with the raw, unformatted disks, which are the ones showing no FSTYPE value.

Creating the RAID 0 Array

To create a RAID 0 array with these components, pass them into the mdadm --create command. You will have to specify the device name you wish to create, the RAID level, and the number of devices. In this command example, you will be naming the device /dev/md0, and include the two disks that will build the array:

  1. sudo mdadm --create --verbose /dev/md0 --level=0 --raid-devices=2 /dev/sda /dev/sdb

Output

mdadm: layout defaults to -p original mdadm: chunk size defaults to 512K mdadm: size set to 104792064K mdadm: Defaulting to version 1.2 metadata mdadm: array /dev/md0 started.

Confirm that the RAID was successfully created by checking the /proc/mdstat file:

  1. cat /proc/mdstat

Output

Personalities : [linear] [multipath] [raid0] [raid1] [raid6] [raid5] [raid4] [raid10] md0 : active raid0 sdb[1] sda[0] 209584128 blocks super 1.2 512k chunks unused devices: <none>

This output reveals that the /dev/md0 device was created in the RAID 0 configuration using the /dev/sda and /dev/sdb devices.

Creating and Mounting the Filesystem (RAID 0)

Next, create an ext4 filesystem on the array. The -F flag forces mkfs.ext4 to proceed even though /dev/md0 is not a partition — it is a whole block device, and mkfs requires this flag to confirm you intend to format the entire device:

  1. sudo mkfs.ext4 -F /dev/md0

Then, create a mount point to attach the new filesystem:

  1. sudo mkdir -p /mnt/md0

You can mount the filesystem with the following command:

  1. sudo mount /dev/md0 /mnt/md0

After mounting, check whether the new space is available:

  1. df -h -x devtmpfs -x tmpfs

Output

Filesystem Size Used Avail Use% Mounted on /dev/vda1 25G 1.4G 23G 6% / /dev/vda15 105M 3.4M 102M 4% /boot/efi /dev/md0 196G 61M 186G 1% /mnt/md0

The new filesystem is mounted and accessible. The available space shows 196G rather than the full 200G (2x 100G) because ext4 reserves approximately 5% of the filesystem for root and internal metadata by default.

Saving the RAID 0 Array Layout

Persisting the array across reboots requires three separate steps, each solving a different failure mode:

  1. mdadm --detail --scan writes the array definition including its UUID to /etc/mdadm/mdadm.conf, which is what mdadm reads at boot to know which arrays to assemble and under which device names.
  2. update-initramfs -u rebuilds the early boot image to include the updated mdadm.conf. Without this step, the initramfs used during boot still reflects the old configuration and the array may not assemble at all, or may assemble under an unexpected name like /dev/md127.
  3. The /etc/fstab entry with nofail tells the OS where to mount the array after it assembles. The nofail flag is critical: if the array fails to assemble at boot for any reason, nofail allows the system to continue booting instead of dropping to emergency mode.

Skipping any one of these three steps is the most common cause of an array that works on first boot but fails to come back after a reboot.

  1. sudo mdadm --detail --scan | sudo tee -a /etc/mdadm/mdadm.conf
  1. sudo update-initramfs -u

Add the new filesystem mount options to the /etc/fstab file for automatic mounting at boot:

  1. echo '/dev/md0 /mnt/md0 ext4 defaults,nofail,discard 0 0' | sudo tee -a /etc/fstab

Your RAID 0 array will now automatically assemble and mount each boot.

You’re now finished with your RAID set up. If you want to try a different RAID, follow the resetting instructions at the beginning of this tutorial to proceed with creating a new RAID array type.

Creating a RAID 1 Array

The RAID 1 array type is implemented by mirroring data across all available disks. Each disk in a RAID 1 array gets a full copy of the data, providing redundancy in the event of a device failure.

  • Requirements: Minimum of 2 storage devices.
  • Primary benefit: Full mirror redundancy. Either disk can fail completely and the array keeps running without data loss. Read performance can improve because mdadm can service read requests from both disks simultaneously.
  • When to use it: OS disks, boot volumes, and any two-disk setup where uptime matters more than capacity. RAID 1 is the standard choice for the system disk on a production server.
  • Capacity tradeoff: Usable space equals the size of the smallest disk. Two 100G disks give you 100G of usable storage.

Identifying the Component Devices (RAID 1)

To start, find the identifiers for the raw disks that you will be using:

  1. lsblk -o NAME,SIZE,FSTYPE,TYPE,MOUNTPOINT

Output

NAME SIZE FSTYPE TYPE MOUNTPOINT sda 100G disk sdb 100G disk vda 25G disk ├─vda1 24.9G ext4 part / ├─vda14 4M part └─vda15 106M vfat part /boot/efi vdb 466K iso9660 disk

In this example, you have two disks without a filesystem, each 100G in size. These devices have been given the /dev/sda and /dev/sdb identifiers for this session and will be the raw components you use to build the array.

Creating the RAID 1 Array

To create a RAID 1 array with these components, pass them into the mdadm --create command. You will have to specify the device name you wish to create, the RAID level, and the number of devices. In this command example, you will be naming the device /dev/md0, and include the disks that will build the array:

  1. sudo mdadm --create --verbose /dev/md0 --level=1 --raid-devices=2 /dev/sda /dev/sdb

If the component devices you are using are not partitions with the boot flag enabled, you will likely receive the following warning. It is safe to respond with y and continue:

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 mdadm: size set to 104792064K Continue creating array? y

The mdadm tool will start to mirror the drives. This can take some time to complete, but the array can be used during this time. You can monitor the progress of the mirroring by checking the /proc/mdstat file:

  1. cat /proc/mdstat

Output

Personalities : [linear] [multipath] [raid0] [raid1] [raid6] [raid5] [raid4] [raid10] md0 : active raid1 sdb[1] sda[0] 104792064 blocks super 1.2 [2/2] [UU] [====>................] resync = 20.2% (21233216/104792064) finish=6.9min speed=199507K/sec unused devices: <none>

In the first highlighted line, the /dev/md0 device was created in the RAID 1 configuration using the /dev/sda and /dev/sdb devices. The second highlighted line reveals the progress on the mirroring. You can continue to the next step while this process completes.

Creating and Mounting the Filesystem (RAID 1)

Next, create an ext4 filesystem on the array. The -F flag forces mkfs.ext4 to proceed even though /dev/md0 is not a partition — it is a whole block device, and mkfs requires this flag to confirm you intend to format the entire device:

  1. sudo mkfs.ext4 -F /dev/md0

Then, create a mount point to attach the new filesystem:

  1. sudo mkdir -p /mnt/md0

You can mount the filesystem by running the following:

  1. sudo mount /dev/md0 /mnt/md0

Check whether the new space is available:

  1. df -h -x devtmpfs -x tmpfs

Output

Filesystem Size Used Avail Use% Mounted on /dev/vda1 25G 1.4G 23G 6% / /dev/vda15 105M 3.4M 102M 4% /boot/efi /dev/md0 99G 60M 94G 1% /mnt/md0

The new filesystem is mounted and accessible. The available space shows 94G rather than the full 100G because ext4 reserves approximately 5% of the filesystem for root and internal metadata by default.

Saving the RAID 1 Array Layout

As with RAID 0, persisting this array across reboots requires the same three steps, each solving a different failure mode:

  1. mdadm --detail --scan writes the array definition including its UUID to /etc/mdadm/mdadm.conf, which is what mdadm reads at boot to know which arrays to assemble and under which device names.
  2. update-initramfs -u rebuilds the early boot image to include the updated mdadm.conf. Without this step, the initramfs used during boot still reflects the old configuration and the array may not assemble at all, or may assemble under an unexpected name like /dev/md127.
  3. The /etc/fstab entry with nofail tells the OS where to mount the array after it assembles. The nofail flag is critical: if the array fails to assemble at boot for any reason, nofail allows the system to continue booting instead of dropping to emergency mode.

Skipping any one of these three steps is the most common cause of an array that works on first boot but fails to come back after a reboot.

  1. sudo mdadm --detail --scan | sudo tee -a /etc/mdadm/mdadm.conf
  1. sudo update-initramfs -u

Add the new filesystem mount options to the /etc/fstab file for automatic mounting at boot:

  1. echo '/dev/md0 /mnt/md0 ext4 defaults,nofail,discard 0 0' | sudo tee -a /etc/fstab

Your RAID 1 array will now automatically assemble and mount each boot.

You’re now finished with your RAID set up. If you want to try a different RAID, follow the resetting instructions at the beginning of this tutorial to proceed with creating a new RAID array type.

Creating a RAID 5 Array

The RAID 5 array type is implemented by striping data across the available devices. One component of each stripe is a calculated parity block. If a device fails, the parity block and the remaining blocks can be used to calculate the missing data. The device that receives the parity block is rotated so that each device has a balanced amount of parity information.

  • Requirements: Minimum of 3 storage devices.
  • Primary benefit: Distributed parity across all member disks. One disk can fail and the array remains fully readable using parity reconstruction.
  • When to use it: General-purpose file storage where you need more capacity than RAID 1 but still need one disk’s worth of fault tolerance. With N disks you get N-1 disks of usable space.
  • Production caveat: RAID 5 rebuild times on large disks can run several hours. During a rebuild, a second disk failure destroys the array. On disks larger than 2TB, seriously consider RAID 6 instead. RAID 5 also has significantly degraded write performance while in degraded state.

Identifying the Component Devices (RAID 5)

To start, find the identifiers for the raw disks that you will be using:

  1. lsblk -o NAME,SIZE,FSTYPE,TYPE,MOUNTPOINT

Output

NAME SIZE FSTYPE TYPE MOUNTPOINT sda 100G disk sdb 100G disk sdc 100G disk vda 25G disk ├─vda1 24.9G ext4 part / ├─vda14 4M part └─vda15 106M vfat part /boot/efi vdb 466K iso9660 disk

You have three disks without a filesystem, each 100G in size. These devices have been given the /dev/sda, /dev/sdb, and /dev/sdc identifiers for this session and will be the raw components you use to build the array.

Creating the RAID 5 Array

To create a RAID 5 array with these components, pass them into the mdadm --create command. You will have to specify the device name you wish to create, the RAID level, and the number of devices. In this command example, you will be naming the device /dev/md0, and include the disks that will build the array:

  1. sudo mdadm --create --verbose /dev/md0 --level=5 --raid-devices=3 /dev/sda /dev/sdb /dev/sdc

Output

mdadm: layout defaults to left-symmetric mdadm: chunk size defaults to 512K mdadm: size set to 104791040K mdadm: Defaulting to version 1.2 metadata mdadm: array /dev/md0 started.

The mdadm tool will start to configure the array. It uses the recovery process to build the array because writing parity incrementally as data is placed is faster than zeroing all blocks first — this means the array is technically in a recovery state during the initial build. This can take some time to complete, but the array can be used during this time. You can monitor the progress of the mirroring by checking the /proc/mdstat file:

  1. cat /proc/mdstat

Output

Personalities : [linear] [multipath] [raid0] [raid1] [raid6] [raid5] [raid4] [raid10] md0 : active raid5 sdc[3] sdb[1] sda[0] 209582080 blocks super 1.2 level 5, 512k chunk, algorithm 2 [3/2] [UU_] [>....................] recovery = 0.9% (957244/104791040) finish=18.0min speed=95724K/sec unused devices: <none>

In the first highlighted line, the /dev/md0 device was created in the RAID 5 configuration using the /dev/sda, /dev/sdb and /dev/sdc devices. The second highlighted line shows the progress of the build.

Warning: Due to the way that mdadm builds RAID 5 arrays, while the array is still building, the number of spares in the array will be inaccurately reported. This means that you must wait for the array to finish assembling before updating the /etc/mdadm/mdadm.conf file. If you update the configuration file while the array is still building, the system will have incorrect information about the array state and will be unable to assemble it automatically at boot with the correct name.

You can continue the guide while this process completes.

Creating and Mounting the Filesystem (RAID 5)

Next, create an ext4 filesystem on the array. The -F flag forces mkfs.ext4 to proceed even though /dev/md0 is not a partition — it is a whole block device, and mkfs requires this flag to confirm you intend to format the entire device:

  1. sudo mkfs.ext4 -F /dev/md0

Create a mount point to attach the new filesystem:

  1. sudo mkdir -p /mnt/md0

You can mount the filesystem with the following:

  1. sudo mount /dev/md0 /mnt/md0

Check whether the new space is available:

  1. df -h -x devtmpfs -x tmpfs

Output

Filesystem Size Used Avail Use% Mounted on /dev/vda1 25G 1.4G 23G 6% / /dev/vda15 105M 3.4M 102M 4% /boot/efi /dev/md0 197G 60M 187G 1% /mnt/md0

The new filesystem is mounted and accessible.

Saving the RAID 5 Array Layout

As with RAID 0, persisting this array across reboots requires the same three steps, each solving a different failure mode:

  1. mdadm --detail --scan writes the array definition including its UUID to /etc/mdadm/mdadm.conf, which is what mdadm reads at boot to know which arrays to assemble and under which device names.
  2. update-initramfs -u rebuilds the early boot image to include the updated mdadm.conf. Without this step, the initramfs used during boot still reflects the old configuration and the array may not assemble at all, or may assemble under an unexpected name like /dev/md127.
  3. The /etc/fstab entry with nofail tells the OS where to mount the array after it assembles. The nofail flag is critical: if the array fails to assemble at boot for any reason, nofail allows the system to continue booting instead of dropping to emergency mode.

Skipping any one of these three steps is the most common cause of an array that works on first boot but fails to come back after a reboot.

Warning: Before running the steps below, confirm the array has finished assembling. If you run mdadm --detail --scan while the array is still building, the output will show an incorrect spare count and the UUID written to mdadm.conf may be wrong. A wrong entry means mdadm cannot match the stored definition to the array at boot and will assemble it under a fallback name like /dev/md127 instead of /dev/md0. If this happens after a reboot, run sudo mdadm --detail --scan again, clear the incorrect line from /etc/mdadm/mdadm.conf, append the correct entry, and run sudo update-initramfs -u again.

You can monitor the progress of the mirroring by checking the /proc/mdstat file:

  1. cat /proc/mdstat

Output

Personalities : [raid1] [linear] [multipath] [raid0] [raid6] [raid5] [raid4] [raid10] md0 : active raid5 sdc[3] sdb[1] sda[0] 209584128 blocks super 1.2 level 5, 512k chunk, algorithm 2 [3/3] [UUU] unused devices: <none>

This output reveals that the rebuild is complete. Now, you can automatically scan the active array and append the file:

  1. sudo mdadm --detail --scan | sudo tee -a /etc/mdadm/mdadm.conf
  1. sudo update-initramfs -u

Add the new filesystem mount options to the /etc/fstab file for automatic mounting at boot:

  1. echo '/dev/md0 /mnt/md0 ext4 defaults,nofail,discard 0 0' | sudo tee -a /etc/fstab

Your RAID 5 array will now automatically assemble and mount each boot.

You’re now finished with your RAID set up. If you want to try a different RAID, follow the resetting instructions at the beginning of this tutorial to proceed with creating a new RAID array type.

Creating a RAID 6 Array

The RAID 6 array type is implemented by striping data across the available devices. Two components of each stripe are calculated parity blocks. If one or two devices fail, the parity blocks and the remaining blocks can be used to calculate the missing data. The devices that receive the parity blocks are rotated so that each device has a balanced amount of parity information. This is similar to a RAID 5 array, but allows for the failure of two drives.

  • Requirements: Minimum of 4 storage devices.
  • Primary benefit: Double parity. Two disks can fail simultaneously and the array continues to operate. This makes RAID 6 the safer choice for large-disk arrays where a simultaneous second failure during a long rebuild is a realistic risk.
  • When to use it: High-capacity storage arrays with 4 or more large disks. The two-disk failure tolerance provides a meaningful safety margin that RAID 5 cannot offer.
  • Capacity tradeoff: Two disks worth of capacity is used for parity. Four 100G disks give you 200G of usable storage.

Identifying the Component Devices (RAID 6)

To start, find the identifiers for the raw disks that you will be using:

  1. lsblk -o NAME,SIZE,FSTYPE,TYPE,MOUNTPOINT

Output

NAME SIZE FSTYPE TYPE MOUNTPOINT sda 100G disk sdb 100G disk sdc 100G disk sdd 100G disk vda 25G disk ├─vda1 24.9G ext4 part / ├─vda14 4M part └─vda15 106M vfat part /boot/efi vdb 466K iso9660 disk

In this example, you have four disks without a filesystem, each 100G in size. These devices have been given the /dev/sda, /dev/sdb, /dev/sdc, and /dev/sdd identifiers for this session and will be the raw components used to build the array.

Creating the RAID 6 Array

To create a RAID 6 array with these components, pass them into the mdadm --create command. You have to specify the device name you wish to create, the RAID level, and the number of devices. In this following command example, you will be naming the device /dev/md0 and include the disks that will build the array:

  1. sudo mdadm --create --verbose /dev/md0 --level=6 --raid-devices=4 /dev/sda /dev/sdb /dev/sdc /dev/sdd

Output

mdadm: layout defaults to left-symmetric mdadm: chunk size defaults to 512K mdadm: size set to 104792064K mdadm: Defaulting to version 1.2 metadata mdadm: array /dev/md0 started.

The mdadm tool will start to configure the array. It uses the recovery process to build the array because writing parity incrementally as data is placed is faster than zeroing all blocks first — this means the array is technically in a recovery state during the initial build. This can take some time to complete, but the array can be used during this time. You can monitor the progress of the mirroring by checking the /proc/mdstat file:

  1. cat /proc/mdstat

Output

Personalities : [linear] [multipath] [raid0] [raid1] [raid6] [raid5] [raid4] [raid10] md0 : active raid6 sdd[3] sdc[2] sdb[1] sda[0] 209584128 blocks super 1.2 level 6, 512k chunk, algorithm 2 [4/4] [UUUU] [>....................] resync = 0.6% (668572/104792064) finish=10.3min speed=167143K/sec unused devices: <none>

In the first highlighted line, the /dev/md0 device has been created in the RAID 6 configuration using the /dev/sda, /dev/sdb, /dev/sdc and /dev/sdd devices. The second highlighted line shows the progress of the build. You can continue the guide while this process completes.

Creating and Mounting the Filesystem (RAID 6)

Next, create an ext4 filesystem on the array. The -F flag forces mkfs.ext4 to proceed even though /dev/md0 is not a partition — it is a whole block device, and mkfs requires this flag to confirm you intend to format the entire device:

  1. sudo mkfs.ext4 -F /dev/md0

Create a mount point to attach the new filesystem:

  1. sudo mkdir -p /mnt/md0

You can mount the filesystem with the following:

  1. sudo mount /dev/md0 /mnt/md0

Check whether the new space is available:

  1. df -h -x devtmpfs -x tmpfs

Output

Filesystem Size Used Avail Use% Mounted on /dev/vda1 25G 1.4G 23G 6% / /dev/vda15 105M 3.4M 102M 4% /boot/efi /dev/md0 197G 60M 187G 1% /mnt/md0

The new filesystem is mounted and accessible.

Saving the RAID 6 Array Layout

As with RAID 0, persisting this array across reboots requires the same three steps, each solving a different failure mode:

  1. mdadm --detail --scan writes the array definition including its UUID to /etc/mdadm/mdadm.conf, which is what mdadm reads at boot to know which arrays to assemble and under which device names.
  2. update-initramfs -u rebuilds the early boot image to include the updated mdadm.conf. Without this step, the initramfs used during boot still reflects the old configuration and the array may not assemble at all, or may assemble under an unexpected name like /dev/md127.
  3. The /etc/fstab entry with nofail tells the OS where to mount the array after it assembles. The nofail flag is critical: if the array fails to assemble at boot for any reason, nofail allows the system to continue booting instead of dropping to emergency mode.

Skipping any one of these three steps is the most common cause of an array that works on first boot but fails to come back after a reboot.

  1. sudo mdadm --detail --scan | sudo tee -a /etc/mdadm/mdadm.conf
  1. sudo update-initramfs -u

Add the new filesystem mount options to the /etc/fstab file for automatic mounting at boot:

  1. echo '/dev/md0 /mnt/md0 ext4 defaults,nofail,discard 0 0' | sudo tee -a /etc/fstab

Your RAID 6 array will now automatically assemble and mount each boot.

You’re now finished with your RAID set up. If you want to try a different RAID, follow the resetting instructions at the beginning of this tutorial to proceed with creating a new RAID array type.

Creating a Complex RAID 10 Array

The RAID 10 array type is traditionally implemented by creating a striped RAID 0 array composed of sets of RAID 1 arrays. This nested array type gives both redundancy and high performance, at the expense of large amounts of disk space. The mdadm utility has its own RAID 10 type that provides the same type of benefits with increased flexibility. It is not created by nesting arrays, but has many of the same characteristics and guarantees. You will be using the mdadm RAID 10 here.

  • Requirements: Minimum of 4 storage devices for a standard setup. mdadm’s native RAID 10 technically accepts 3 disks, but 4 is the practical minimum for balanced mirroring.
  • Primary benefit: Combines RAID 0 striping with RAID 1 mirroring. You get both the throughput of striping and the redundancy of mirroring. One disk per mirrored pair can fail without data loss.
  • When to use it: Database servers, high-throughput application storage, or any workload that needs both performance and redundancy. RAID 10 has the fastest rebuild time of any redundant RAID level because recovery only involves copying data from the surviving mirror, not computing parity.
  • Capacity tradeoff: Half of total disk capacity is used for mirroring. Four 100G disks give you 200G of usable storage.

By default, two copies of each data block will be stored in what is called the near layout. The possible layouts that dictate how each data block is stored are as follows:

  • near: The default arrangement. Copies of each chunk are written consecutively when striping, meaning that the copies of the data blocks will be written around the same part of multiple disks.
  • far: The first and subsequent copies are written to different parts of the storage devices in the array. For instance, the first chunk might be written near the beginning of a disk, while the second chunk would be written halfway down on a different disk. This can give some read performance gains for traditional spinning disks at the expense of write performance.
  • offset: Each stripe is copied, and offset by one drive. This means that the copies are offset from one another, but still close together on the disk. This helps minimize excessive seeking during some workloads.

You can find out more about these layouts by checking out the RAID10 section of this man page:

  1. man 4 md

Identifying the Component Devices (RAID 10)

To start, find the identifiers for the raw disks that you will be using:

  1. lsblk -o NAME,SIZE,FSTYPE,TYPE,MOUNTPOINT

Output

NAME SIZE FSTYPE TYPE MOUNTPOINT sda 100G disk sdb 100G disk sdc 100G disk sdd 100G disk vda 25G disk ├─vda1 24.9G ext4 part / ├─vda14 4M part └─vda15 106M vfat part /boot/efi vdb 466K iso9660 disk

In this example, you have four disks without a filesystem, each 100G in size. These devices have been given the /dev/sda, /dev/sdb, /dev/sdc, and /dev/sdd identifiers for this session and will be the raw components used to build the array.

Creating the RAID 10 Array

To create a RAID 10 array with these components, pass them into the mdadm --create command. You have to specify the device name you wish to create, the RAID level, and the number of devices. In this following command example, you will be naming the device /dev/md0 and include the disks that will build the array:

You can set up two copies using the near layout by not specifying a layout and copy number:

  1. sudo mdadm --create --verbose /dev/md0 --level=10 --raid-devices=4 /dev/sda /dev/sdb /dev/sdc /dev/sdd

Output

mdadm: layout defaults to n2 mdadm: chunk size defaults to 512K mdadm: size set to 104792064K mdadm: Defaulting to version 1.2 metadata mdadm: array /dev/md0 started.

If you want to use a different layout or change the number of copies, you will have to use the --layout= option, which takes a layout and copy identifier. The layouts are n for near, f for far, and o for offset. The number of copies to store is appended afterward.

For instance, to create an array that has three copies in the offset layout, the command would include the following:

  1. sudo mdadm --create --verbose /dev/md0 --level=10 --layout=o3 --raid-devices=4 /dev/sda /dev/sdb /dev/sdc /dev/sdd

The mdadm tool will start to configure the array. It uses the recovery process to build the array because writing parity incrementally as data is placed is faster than zeroing all blocks first — this means the array is technically in a recovery state during the initial build. This can take some time to complete, but the array can be used during this time. You can monitor the progress of the mirroring by checking the /proc/mdstat file:

  1. cat /proc/mdstat

Output

Personalities : [raid6] [raid5] [raid4] [linear] [multipath] [raid0] [raid1] [raid10] md0 : active raid10 sdd[3] sdc[2] sdb[1] sda[0] 209584128 blocks super 1.2 512K chunks 2 near-copies [4/4] [UUUU] [===>.................] resync = 18.1% (37959424/209584128) finish=13.8min speed=206120K/sec unused devices: <none>

In the first highlighted line, the /dev/md0 device has been created in the RAID 10 configuration using the /dev/sda, /dev/sdb, /dev/sdc and /dev/sdd devices. The second highlighted area shows the layout that was used for this example (two copies in the near configuration). The third highlighted area shows the progress on the build. You can continue the guide while this process completes.

Creating and Mounting the Filesystem (RAID 10)

Next, create an ext4 filesystem on the array. The -F flag forces mkfs.ext4 to proceed even though /dev/md0 is not a partition — it is a whole block device, and mkfs requires this flag to confirm you intend to format the entire device:

  1. sudo mkfs.ext4 -F /dev/md0

Create a mount point to attach the new filesystem:

  1. sudo mkdir -p /mnt/md0

You can mount the filesystem with the following:

  1. sudo mount /dev/md0 /mnt/md0

Check whether the new space is available:

  1. df -h -x devtmpfs -x tmpfs

Output

Filesystem Size Used Avail Use% Mounted on /dev/vda1 25G 1.4G 23G 6% / /dev/vda15 105M 3.4M 102M 4% /boot/efi /dev/md0 197G 60M 187G 1% /mnt/md0

The new filesystem is mounted and accessible.

Saving the RAID 10 Array Layout

As with RAID 0, persisting this array across reboots requires the same three steps, each solving a different failure mode:

  1. mdadm --detail --scan writes the array definition including its UUID to /etc/mdadm/mdadm.conf, which is what mdadm reads at boot to know which arrays to assemble and under which device names.
  2. update-initramfs -u rebuilds the early boot image to include the updated mdadm.conf. Without this step, the initramfs used during boot still reflects the old configuration and the array may not assemble at all, or may assemble under an unexpected name like /dev/md127.
  3. The /etc/fstab entry with nofail tells the OS where to mount the array after it assembles. The nofail flag is critical: if the array fails to assemble at boot for any reason, nofail allows the system to continue booting instead of dropping to emergency mode.

Skipping any one of these three steps is the most common cause of an array that works on first boot but fails to come back after a reboot.

  1. sudo mdadm --detail --scan | sudo tee -a /etc/mdadm/mdadm.conf
  1. sudo update-initramfs -u

Add the new filesystem mount options to the /etc/fstab file for automatic mounting at boot:

  1. echo '/dev/md0 /mnt/md0 ext4 defaults,nofail,discard 0 0' | sudo tee -a /etc/fstab

Your RAID 10 array will now automatically assemble and mount each boot.

Monitoring and Maintaining RAID Arrays

Once an array is running, mdadm provides several tools to inspect its health, respond to disk failures, and replace degraded members.

Reading /proc/mdstat

The /proc/mdstat file is the fastest way to check array state:

  1. cat /proc/mdstat

Output

Personalities : [raid1] [raid5] [raid10] md0 : active raid1 sdb[1] sda[0] 104792064 blocks super 1.2 [2/2] [UU] unused devices: <none>

Each U in the [UU] field represents a healthy member disk. A _ indicates a missing or degraded member. For a deeper summary of a specific array, use --detail:

  1. sudo mdadm --detail /dev/md0

Output

/dev/md0: Version : 1.2 Creation Time : Mon Jan 1 00:00:00 Raid Level : raid1 Array Size : 104792064 (99.94 GiB 107.31 GB) Used Dev Size : 104792064 (99.94 GiB 107.31 GB) Raid Devices : 2 Total Devices : 2 Persistence : Superblock is persistent Update Time : Mon Jan 1 00:05:00 State : clean Active Devices : 2 Working Devices : 2 Failed Devices : 0 Spare Devices : 0 Name : hostname:0 (local to host hostname) UUID : xxxxxxxx:xxxxxxxx:xxxxxxxx:xxxxxxxx Events : 17 Number Major Minor RaidDevice State 0 8 0 0 active sync /dev/sda 1 8 16 1 active sync /dev/sdb

Enabling Email Alerts with mdadm --monitor

Configure mdadm to send email notifications when array events occur. Add the following line to /etc/mdadm/mdadm.conf:

  1. sudo nano /etc/mdadm/mdadm.conf

/etc/mdadm/mdadm.conf

MAILADDR admin@example.com

Then enable and start the mdmonitor service:

  1. sudo systemctl enable mdmonitor
  2. sudo systemctl start mdmonitor

Verify the service is running:

  1. sudo systemctl status mdmonitor

Output

● mdmonitor.service - MD array monitor Loaded: loaded (/lib/systemd/system/mdmonitor.service; enabled) Active: active (running)

mdadm --monitor sends alerts for events including Fail, DegradedArray, SparesMissing, and RebuildFinished.

Note: If mdmonitor.service is not found, verify the correct service name on your system with systemctl list-units | grep -i md.

Adding a Hot Spare

A hot spare is a standby disk that mdadm automatically uses to begin rebuilding the array the moment a member disk fails. To add a spare to an existing array:

  1. sudo mdadm /dev/md0 --add /dev/sde

Output

mdadm: added /dev/sde

Confirm the spare is registered:

  1. sudo mdadm --detail /dev/md0 | grep spare

Output

Spare Devices : 1 2 8 64 - spare /dev/sde

Handling a Failed Disk

When mdadm marks a disk as failed, the array enters a degraded state. The /proc/mdstat output will show a _ in the device status field:

Output

md0 : active raid1 sdb[1] sda[2](F) 104792064 blocks super 1.2 [2/1] [_U]

The (F) flag on /dev/sda confirms the failure. If no hot spare is configured, the array continues to operate in degraded mode, but has no further redundancy until the failed disk is replaced.

Replacing a Failed Disk

To replace the failed disk, first mark it as failed (if mdadm has not already done so automatically):

  1. sudo mdadm /dev/md0 --fail /dev/sda

Remove the failed disk from the array:

  1. sudo mdadm /dev/md0 --remove /dev/sda

Physically replace the disk, then add the new disk to the array:

  1. sudo mdadm /dev/md0 --add /dev/sda

mdadm immediately begins rebuilding the array onto the replacement disk. Monitor the rebuild progress:

  1. watch -n 1 cat /proc/mdstat

Output

md0 : active raid1 sda[2] sdb[1] 104792064 blocks super 1.2 [2/1] [_U] [=>...................] recovery = 6.4% (6710784/104792064) finish=13.8min speed=118080K/sec

The array returns to a fully healthy state when the rebuild finishes and the status field shows [UU].

Warning: On Ubuntu systems using udev, device names such as /dev/sda can change after a reboot or hardware change. Use persistent identifiers from ls -l /dev/disk/by-id/ when scripting replacement procedures, or when the server will be rebooted between the remove and add steps.

Software RAID vs Alternatives

mdadm software RAID is not the only option for redundant storage on Linux. The table below summarises when to use each approach.

Approach Best for Key tradeoff
mdadm software RAID General-purpose redundancy and performance on bare metal or dedicated servers CPU overhead; kernel must load correct RAID personality at boot
ZFS (via zfsutils-linux) Data integrity-critical workloads; built-in checksumming, snapshots, and RAID-Z Higher memory requirement (minimum 1 GB RAM per TB of storage recommended); licensing incompatibility with some kernels
LVM striping/mirroring Flexible volume management layered on top of RAID or single disks No checksumming; LVM mirroring is less battle-tested for failure scenarios than mdadm
Hardware RAID controller Environments requiring RAID offload from the host CPU Controller cost; portability risk if controller fails and replacement is unavailable

When to choose mdadm:

  • You are on bare-metal hardware without a hardware RAID controller.
  • You need a well-supported, kernel-native solution with a long track record on Ubuntu.
  • You want to combine redundancy levels (RAID 10) without additional licensing concerns.

When to consider ZFS instead:

  • Data integrity at scale is the primary concern (file servers, backup targets).
  • You require native snapshot and send/receive capabilities.
  • You can meet the memory requirements.

For volume management layered on top of an existing RAID array, see our guide on how to use LVM to manage storage devices on Ubuntu.

Frequently Asked Questions

What is the difference between RAID 5 and RAID 10 in mdadm?

RAID 5 distributes parity across three or more disks, using one disk-equivalent of capacity for parity. It tolerates one disk failure. RAID 10 mirrors pairs of disks and stripes across the mirrors, tolerating one failure per mirrored pair. RAID 10 generally delivers better write performance and faster rebuild times; RAID 5 gives more usable capacity per disk added.

How do I check the status of a RAID array created with mdadm?

Run cat /proc/mdstat for a quick overview of all active arrays. For detailed information about a specific array including member disk state, run sudo mdadm --detail /dev/md0.

How do I make a mdadm RAID array persist after a reboot on Ubuntu?

Three steps are required. First, append the array definition to /etc/mdadm/mdadm.conf by running sudo mdadm --detail --scan | sudo tee -a /etc/mdadm/mdadm.conf. Second, update the initramfs with sudo update-initramfs -u. Third, add the mount entry to /etc/fstab using the nofail option so the system boots even if the array is unavailable.

Can I add a hot spare to an existing mdadm RAID array?

Yes. Run sudo mdadm /dev/md0 --add /dev/sdX where /dev/sdX is the spare disk. mdadm registers it as a spare and will automatically begin a rebuild onto it if a member disk fails.

What happens when a disk in a mdadm RAID array fails?

mdadm marks the disk with a (F) flag in /proc/mdstat and the array enters degraded state. If a hot spare is configured, mdadm begins rebuilding automatically. If no spare is present, the array continues operating with reduced redundancy. RAID 0 has no redundancy: a single disk failure destroys all data.

How do I replace a failed disk in a mdadm RAID 1 or RAID 5 array?

Mark the disk as failed with sudo mdadm /dev/md0 --fail /dev/sdX, remove it with sudo mdadm /dev/md0 --remove /dev/sdX, replace the physical disk, then add the new disk with sudo mdadm /dev/md0 --add /dev/sdX. The array begins rebuilding immediately.

What is the /etc/mdadm/mdadm.conf file used for?

/etc/mdadm/mdadm.conf stores persistent array definitions including the array UUID, member devices, and monitoring configuration such as the alert email address. Without a correct entry here, mdadm cannot reliably reassemble the array at boot using the expected device name.

How does mdadm software RAID compare to ZFS on Ubuntu?

mdadm is kernel-native, lightweight, and well-tested across a wide range of hardware. ZFS adds built-in data checksumming, copy-on-write snapshots, and RAID-Z (similar to RAID 5/6), but requires more RAM and has licensing constraints that prevent it from being shipped in the Linux kernel directly. For most general-purpose redundancy use cases on Ubuntu servers, mdadm is the straightforward choice. For large-scale file servers where silent data corruption is a concern, ZFS is worth the additional overhead.

Conclusion

In this guide, you created RAID 0, 1, 5, 6, and 10 arrays using mdadm on Ubuntu. You formatted and mounted each array, persisted the configuration across reboots by updating /etc/mdadm/mdadm.conf and running update-initramfs -u, and set up monitoring and disk replacement procedures.

As next steps:

Creative CommonsThis work is licensed under a Creative Commons Attribution-NonCommercial- ShareAlike 4.0 International License.