Sunday, August 28, 2011

Mirroring an existing and encrypted disk with mdadm

I have all my data (personal, music etc.) stored on one 1.5TB disk and to avoid manual backups to external devices I want (need) to create a mirror. The disk itself is encrypted and formatted with ext3. The big picture is like this:

Now I want to do the following:
1. keep my data healthy (most important)
2. setup an software mirror containing the disks /dev/sdc and /dev/sdd
3. the mirror should also be encrypted (luks again)
4. update the filesystem from ext3 to ext4
5. migrate the data from the old disk to the mirror

Before I continue I should let you know that I have created a backup from my data. If you follow these instructions, create also a backup. Don't blame me for loosing your data!

The existing disk has the device /dev/sdc and contains one partition /dev/sdc1. It is opened by luks to /dev/mapper/export and mounted to /export. For the start create a mirror with the new disk and one missing disk. The missing disk will be /dev/sdc later.

# mdadm --create /dev/md0 --level 1 --raid-devices 2 missing /dev/sdd
mdadm: array /dev/md0 started.

/dev/md0 will be our mirrored device, 'level 1' tells mdadm that we want to create a Raid Level 1 with two devices. One disk is missing and will be added later, so we can easily migrate our date from /dev/sdc to the new mirror.

Now I need a new partition where I can store my data encrypted:

# fdisk /dev/md0

Command (m for help): n
Command action
e extended
p primary partition (1-4)
Partition number (1-4): 1
First cylinder (1-366284624, default 1):
Using default value 1
Last cylinder, +cylinders or +size{K,M,G} (1-366284624, default 366284624):
Using default value 366284624

Command (m for help): w
The partition table has been altered!

Calling ioctl() to re-read partition table.
Syncing disks.

The fdisk command above just created a new partition on the mirror device /dev/md0. The partition itself is /dev/md0p1 then:

Next you need to encrypt the new partition /dev/md0p1:

# cryptsetup -c aes-cbc-essiv:sha256 -y luksFormat /dev/md0p1

This will overwrite data on /dev/md0p1 irrevocably.

Are you sure? (Type uppercase yes): YES
Enter LUKS passphrase:
Verify passphrase:

This will encrypt all data on /dev/md0p1 with AES for future use. Now open the device using the mapper crypt:

# cryptsetup luksOpen /dev/md0p1 crypt
Enter passphrase for /dev/md0p1:
Key slot 0 unlocked.

Now the device is /dev/mapper/crypt:

Finally, create a file system on the mapper device:

# mkfs.ext4 /dev/mapper/crypt
mke2fs 1.41.11 (14-Mar-2010)
Filesystem label=
OS type: Linux
Block size=4096 (log=2)
Fragment size=4096 (log=2)
Stride=0 blocks, Stripe width=0 blocks
91578368 inodes, 366283727 blocks
18314186 blocks (5.00%) reserved for the super user
First data block=0
Maximum filesystem blocks=4294967296
11179 block groups
32768 blocks per group, 32768 fragments per group
8192 inodes per group
Superblock backups stored on blocks:
32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208,
4096000, 7962624, 11239424, 20480000, 23887872, 71663616, 78675968,
102400000, 214990848

Writing inode tables: done
Creating journal (32768 blocks): done
Writing superblocks and filesystem accounting information: done

This filesystem will be automatically checked every 34 mounts or
180 days, whichever comes first. Use tune2fs -c or -i to override.

With the new created filesystem the big picture is now like this:


Turn of filesystem check if applicable:

# tune2fs -c 0 /dev/mapper/crypt
tune2fs 1.41.11 (14-Mar-2010)
Setting maximal mount count to -1

And now the final moment - mount the encrypted disk:

# mkdir /mnt/crypt
# mount /dev/mapper/crypt /mnt/crypt

Before you begin to migrate your data, make sure the encrypted mirror can be stopped and started again. Here is an example for stopping the encrypted mirror:

# umount /mnt/crypt/
# cryptsetup luksClose crypt
# mdadm --stop /dev/md0
mdadm: stopped /dev/md0

And an example for starting the mirror:

# mdadm --assemble -v /dev/md0 /dev/sdd
mdadm: looking for devices for /dev/md0
mdadm: /dev/sdd is identified as a member of /dev/md0, slot 1.
mdadm: no uptodate device for slot 0 of /dev/md0
mdadm: added /dev/sdd to /dev/md0 as 1
mdadm: /dev/md0 has been started with 1 drive (out of 2).
# cryptsetup luksOpen /dev/md0p1 crypt
Enter passphrase for /dev/md0p1:
Key slot 0 unlocked.
# mount /dev/mapper/crypt /mnt/crypt

It is also a good idea to reboot your server to see what is happening before you begin to migrate your data.
Now when everything is working, the encrypted mirror can be started and stopped, then you can migrate your data, e.g.:

# rsync -a /export/home /mnt/crypt/
# rsync -a /export/data/music /mnt/crypt/
# rsync -a /export/data/movie /mnt/crypt/

When all data is copied then add the remaining disk /dev/sdc to the mirror /dev/md0:

# mdadm --add /dev/md0 /dev/sdc
mdadm: added /dev/sdc

All data from /dev/sdd will now be copied to /dev/sdc. You can see the progress in /proc/mdstat:

# cat /proc/mdstat
Personalities : [linear] [raid0] [raid1] [raid10] [raid6] [raid5] [raid4] [multipath]
md0 : active raid1 sdc[2] sdd[1]
1465138496 blocks [2/1] [_U]
[>....................] recovery = 0.5% (7931200/1465138496) finish=450.4min speed=53914K/sec
unused devices: <none>

The big picture is complete now: