{"id":12,"date":"2026-07-31T13:48:41","date_gmt":"2026-07-31T20:48:41","guid":{"rendered":"https:\/\/pointyhair.com\/?p=12"},"modified":"2026-08-05T16:48:31","modified_gmt":"2026-08-05T23:48:31","slug":"using-lvm2-for-a-resilient-drive-array","status":"publish","type":"post","link":"https:\/\/pointyhair.com\/index.php\/2026\/07\/31\/using-lvm2-for-a-resilient-drive-array\/","title":{"rendered":"Using LVM2 for a resilient scalable drive array, with script to re-initialize array"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">63 terabytes of storage built from 8 USB drives in &#8220;RAID 1&#8221; configuration &#8212; I.e. you don&#8217;t lose data even if one drive goes dead.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">A bit of background:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">I started a (multi-domain) web service ten years ago. I wanted some extra storage as backups.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Fairly quickly I was running out of space, as well as backups of backups &#8212; so I had to add storage to my USB drive. Now I wanted to serve the pages out of an NVME (originally M2.SATA) drive, and have the backups on a slower (cheaper medium). I started to grow the number of USB drives.<\/li>\n\n\n\n<li>The number of USB drives became unwieldy because if the server (Linux) reboots, the drives come in an undetermined order. Sorting out the drives between sdb, sdc&#8230;sdi is not fun.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">To start with&#8230; this is a completely safe, benign operation &#8212; it just makes LVM2 available to your machine:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo apt install lvm2<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Enter LVM2, which I had used in the past.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo pvs&nbsp;\nPV &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;VG &nbsp;&nbsp;Fmt &nbsp;Attr PSize &nbsp;PFree &nbsp;&nbsp;&nbsp;\n&nbsp;\/dev\/sdb &nbsp;&nbsp;big2 lvm2 a-- &nbsp;&lt;4.55t &nbsp;&nbsp;&lt;1.55t\n&nbsp;\/dev\/sdc &nbsp;&nbsp;big &nbsp;lvm2 a-- &nbsp;&lt;7.28t &lt;284.04g\n&nbsp;\/dev\/sdd &nbsp;&nbsp;big &nbsp;lvm2 a-- &nbsp;&lt;7.28t &nbsp;&nbsp;75.07g\n&nbsp;\/dev\/sde &nbsp;&nbsp;big &nbsp;lvm2 a-- &nbsp;&lt;7.28t &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0 &nbsp;\n&nbsp;\/dev\/sdf &nbsp;&nbsp;big2 lvm2 a-- &nbsp;&lt;3.64t &nbsp;&nbsp;&lt;3.64t\n&nbsp;\/dev\/sdg &nbsp;&nbsp;big &nbsp;lvm2 a-- &nbsp;&lt;7.28t &lt;284.04g\n&nbsp;\/dev\/sdh &nbsp;&nbsp;big &nbsp;lvm2 a-- &nbsp;12.73t &nbsp;&nbsp;10.73t\n&nbsp;\/dev\/sdi &nbsp;&nbsp;big2 lvm2 a-- &nbsp;14.55t &nbsp;818.96g<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">I took all the USB drives, ran PVcreate (Physical Volume create) on each drive, adding them to a Volume Groug (VG). I realized that the drives could be categorized as Slow and Fast, depending on their seek times (and whether they &#8220;fell asleep&#8221; between access). So I added the PVs into <strong>big<\/strong> and <strong>big2<\/strong> groups [using VGcreate](not the best naming, should have used Fast and Slow).<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo vgs&nbsp;\nVG &nbsp;&nbsp;#PV #LV #SN Attr &nbsp;&nbsp;VSize &nbsp;&nbsp;VFree &nbsp;\n&nbsp;big &nbsp;&nbsp;&nbsp;5 &nbsp;28 &nbsp;&nbsp;0 wz--n- &nbsp;41.84t 11.36t\n&nbsp;big2 &nbsp;&nbsp;3 &nbsp;&nbsp;9 &nbsp;&nbsp;0 wz--n- &lt;22.74t &lt;5.99t\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Finally I started creating Logical Volumes (LVcreate) for each purpose always creating LVcreate on VG1 and VG2 same size, and creating an rsync between the LVs (backup of a backup &#8212; effectively bring the whole array into a RAID1 configuration). Now, I could have used LVM2s native tools to do this as well, but I wanted more control (and I had been burned by LVM1 in the pre-historic 10year+ past).<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Nowadays, I have 38 Logical volumes (spread across 9 PVs), that I occasionally expand or shink depending on size needed, usually about a terabyte at a time.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">My LVS map is too long (and private to show).<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Here&#8217;s the killer!<br>When the California heatwave occured, I lost the machine (srv3) completely. and I built a new server (srv4), I just took all the USB hubs from srv3, plugged into srv4, and ran PVSCAN. LVM2 rebuilt the whole raid array, with configurations (PVS, and VGs). All I needed to do was copy the \/etc\/fstab from a backup of srv3&#8230; and we&#8217;re back in business!<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The USBs, the drive IDs, the HUBs don&#8217;t matter, everything fell back in place correctly.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The only thing I wish is that I hoped I hade done better job in taking mysqldumps of the databases instead of doing rsyncs, thus not needing to rebuild the sites. But the sites that were HTML came back immediately.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">I had a bad USB hub, causing some PVs (Physical Volumes) to go off-line, and since I have many of the Logical Volumes  shared\/mounted via NFS that became a problem. Here is a script that 1) takes NFS off-line, 2) checks all the mount points, 3) re-mounts them, 4) restarts NFS. Easy to run, All shares restored, all volumes re-mounted.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>cat \/root\/reseatusb.sh &nbsp;\n#\/bin\/bash\n\nsudo \/etc\/init.d\/nfs-kernel-server stop\nDF1=$(df -h|grep \/dev\/mapper|awk '{print $1}')\nDF6=$(df -h|grep \/dev\/mapper|awk '{print $6}')\necho $DF6|xargs umount\necho $DF1|xargs lvchange -an &nbsp;\necho $DF1|xargs lvchange -ay &nbsp;\nmount -a\nsudo \/etc\/init.d\/nfs-kernel-server start\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Of course, once I realized it was because the bad hub, I replaced with another USB3 hub, and I&#8217;ve never needed the script anymore.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Emails on user accounts were a bit trickier, Folder by folder reconstruction became a possibility, though some tricks were involved (sendmail, dovecot &#8212; I will probably write another article). I will likely add more details to this if interested.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>63 terabytes of storage built from 8 USB drives in &#8220;RAID 1&#8221; configuration &#8212; I.e. you don&#8217;t lose data even if one drive goes dead. A bit of background: I&hellip;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"slim_seo":{"title":"Using LVM2 for a resilient scalable drive array, with script to re-initialize array - Pointyhair","description":"63 terabytes of storage built from 8 USB drives in \"RAID 1\" configuration -- I.e. you don't lose data even if one drive goes dead. A bit of background: I starte"},"footnotes":""},"categories":[4],"tags":[],"class_list":["post-12","post","type-post","status-publish","format-standard","hentry","category-linux-system-configuration"],"_links":{"self":[{"href":"https:\/\/pointyhair.com\/index.php\/wp-json\/wp\/v2\/posts\/12","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/pointyhair.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/pointyhair.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/pointyhair.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/pointyhair.com\/index.php\/wp-json\/wp\/v2\/comments?post=12"}],"version-history":[{"count":10,"href":"https:\/\/pointyhair.com\/index.php\/wp-json\/wp\/v2\/posts\/12\/revisions"}],"predecessor-version":[{"id":64,"href":"https:\/\/pointyhair.com\/index.php\/wp-json\/wp\/v2\/posts\/12\/revisions\/64"}],"wp:attachment":[{"href":"https:\/\/pointyhair.com\/index.php\/wp-json\/wp\/v2\/media?parent=12"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/pointyhair.com\/index.php\/wp-json\/wp\/v2\/categories?post=12"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/pointyhair.com\/index.php\/wp-json\/wp\/v2\/tags?post=12"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}