netsapiensis

rocky-storage

0
0
# Install this skill:
npx skills add netsapiensis/claude-code-skills --skill "rocky-storage"

Install specific skill from multi-skill repository

# Description

Rocky Linux 8/9 storage management including LVM lifecycle (PV/VG/LV), XFS and ext4 filesystem operations, fstab configuration, disk partitioning, and mount management. Use when managing disks, partitions, logical volumes, filesystems, or mount points.

# SKILL.md


name: rocky-storage
description: Rocky Linux 8/9 storage management including LVM lifecycle (PV/VG/LV), XFS and ext4 filesystem operations, fstab configuration, disk partitioning, and mount management. Use when managing disks, partitions, logical volumes, filesystems, or mount points.


Rocky Linux Storage Management

LVM, filesystems, partitioning, fstab, and mount management for Rocky Linux 8/9.

Prerequisite: See rocky-foundation for OS detection and safety tier definitions.

Disk and Partition Inspection

# List block devices  # [READ-ONLY]
lsblk
lsblk -f                             # Show filesystem info
lsblk -o NAME,SIZE,TYPE,FSTYPE,MOUNTPOINT,UUID

# Disk usage  # [READ-ONLY]
df -h
df -hT                                # Include filesystem type
df -i                                 # Inode usage

# Partition tables  # [READ-ONLY]
fdisk -l /dev/sda
gdisk -l /dev/sda                     # GPT disks
parted /dev/sda print

# Disk health (SMART)  # [READ-ONLY]
smartctl -a /dev/sda
smartctl -H /dev/sda                  # Quick health check

Partitioning

# Create GPT partition table and partition  # [DESTRUCTIVE]
parted /dev/sdb mklabel gpt
parted /dev/sdb mkpart primary xfs 0% 100%

# Or interactive:
parted /dev/sdb                       # [DESTRUCTIVE]
# (parted) mklabel gpt
# (parted) mkpart primary xfs 0% 100%
# (parted) quit

MBR Partitioning (Legacy)

# Create MBR partition  # [DESTRUCTIVE]
fdisk /dev/sdb
# n (new) -> p (primary) -> 1 -> defaults -> w (write)

WRONG -- partitioning a mounted/in-use disk:

# WRONG: Modifying partitions on a disk with mounted filesystems
fdisk /dev/sda          # sda has mounted partitions!

# CORRECT: Only partition unused disks or unmounted partitions
lsblk /dev/sdb          # Verify nothing is mounted  # [READ-ONLY]
fdisk /dev/sdb           # Safe if no mounts  # [DESTRUCTIVE]

LVM (Logical Volume Management)

LVM Concepts

Physical Volumes (PV)  ->  Volume Groups (VG)  ->  Logical Volumes (LV)  ->  Filesystem
/dev/sdb1                  vg_data                  lv_app                    /opt/app
/dev/sdc1                                           lv_logs                   /var/log/app

Inspection

# Physical volumes  # [READ-ONLY]
pvs
pvdisplay
pvdisplay /dev/sdb1

# Volume groups  # [READ-ONLY]
vgs
vgdisplay
vgdisplay vg_data

# Logical volumes  # [READ-ONLY]
lvs
lvdisplay
lvdisplay /dev/vg_data/lv_app

Create LVM Stack

# 1. Create physical volume  # [CONFIRM]
pvcreate /dev/sdb1

# 2. Create volume group  # [CONFIRM]
vgcreate vg_data /dev/sdb1

# 3. Create logical volume  # [CONFIRM]
lvcreate -L 50G -n lv_app vg_data
# Or use percentage of free space:
lvcreate -l 80%FREE -n lv_app vg_data

# 4. Create filesystem  # [DESTRUCTIVE]
mkfs.xfs /dev/vg_data/lv_app

# 5. Mount  # [CONFIRM]
mkdir -p /opt/app
mount /dev/vg_data/lv_app /opt/app

Extend LVM (Online)

The most common LVM operation -- growing a volume:

# Check available space in VG  # [READ-ONLY]
vgs

# Extend logical volume + filesystem in one command  # [CONFIRM]
lvextend -r -L +10G /dev/vg_data/lv_app    # -r resizes filesystem too

# Or extend to a specific size  # [CONFIRM]
lvextend -r -L 100G /dev/vg_data/lv_app

# Or use all remaining space  # [CONFIRM]
lvextend -r -l +100%FREE /dev/vg_data/lv_app

WRONG -- extending LV without -r and forgetting filesystem resize:

# WRONG: LV is bigger but filesystem still sees old size
lvextend -L +10G /dev/vg_data/lv_app
# df still shows old size!

# CORRECT: Use -r to auto-resize filesystem
lvextend -r -L +10G /dev/vg_data/lv_app
# Or manually resize after:
# XFS: xfs_growfs /opt/app
# ext4: resize2fs /dev/vg_data/lv_app

Add Disk to Existing VG

# 1. Create PV on new disk  # [CONFIRM]
pvcreate /dev/sdc1

# 2. Extend volume group  # [CONFIRM]
vgextend vg_data /dev/sdc1

# 3. Now extend LVs as needed  # [CONFIRM]
lvextend -r -L +50G /dev/vg_data/lv_app

Shrink LVM (ext4 Only)

XFS cannot be shrunk. ext4 can:

# ext4 shrink -- MUST unmount first  # [DESTRUCTIVE]
umount /opt/app
e2fsck -f /dev/vg_data/lv_app                    # Required before shrink
resize2fs /dev/vg_data/lv_app 30G                 # Shrink filesystem first
lvreduce -L 30G /dev/vg_data/lv_app               # Then shrink LV
mount /dev/vg_data/lv_app /opt/app

WRONG -- shrinking LV before filesystem:

# WRONG: Shrinking LV first destroys data
lvreduce -L 30G /dev/vg_data/lv_app    # DATA LOSS -- filesystem extends beyond LV!

# CORRECT: Always shrink filesystem first, then LV
resize2fs /dev/vg_data/lv_app 30G
lvreduce -L 30G /dev/vg_data/lv_app

Remove LVM Components

# Remove logical volume  # [DESTRUCTIVE]
umount /opt/app                           # Unmount first
lvremove /dev/vg_data/lv_app              # Confirm when prompted

# Remove volume group (all LVs must be removed first)  # [DESTRUCTIVE]
vgremove vg_data

# Remove physical volume  # [DESTRUCTIVE]
pvremove /dev/sdb1

LVM Snapshots

# Create snapshot  # [CONFIRM]
lvcreate -L 5G -s -n lv_app_snap /dev/vg_data/lv_app

# Mount snapshot (read-only)  # [CONFIRM]
mkdir -p /mnt/snap
mount -o ro /dev/vg_data/lv_app_snap /mnt/snap

# Remove snapshot  # [CONFIRM]
umount /mnt/snap
lvremove /dev/vg_data/lv_app_snap

LVM Thin Provisioning

# Create thin pool  # [CONFIRM]
lvcreate -L 100G --thinpool thin_pool vg_data

# Create thin volume  # [CONFIRM]
lvcreate -V 50G --thin -n thin_vol vg_data/thin_pool

# Check thin pool usage  # [READ-ONLY]
lvs -a -o +lv_layout,pool_lv,data_percent vg_data

Filesystems

XFS (Default on Rocky Linux)

# Create XFS filesystem  # [DESTRUCTIVE]
mkfs.xfs /dev/vg_data/lv_app

# Create with label  # [DESTRUCTIVE]
mkfs.xfs -L appdata /dev/vg_data/lv_app

# Grow XFS (online, mount point required)  # [CONFIRM]
xfs_growfs /opt/app                   # Grows to fill the LV

# XFS info  # [READ-ONLY]
xfs_info /opt/app

# XFS repair (unmount first)  # [CONFIRM]
umount /opt/app
xfs_repair /dev/vg_data/lv_app
mount /opt/app

# XFS freeze/thaw (for consistent snapshots)  # [CONFIRM]
xfs_freeze -f /opt/app               # Freeze
# Take snapshot here
xfs_freeze -u /opt/app               # Thaw

Key XFS limitation: XFS can only grow, never shrink. Plan accordingly.

Cloud image note: Rocky 9 GenericCloud images use a single XFS root partition. Since XFS cannot shrink, you cannot repartition the root disk for LVM after deployment. Instead, add a second virtio disk for LVM volumes (see rocky-virtualization -- LVM on Cloud Image VMs).

ext4

# Create ext4 filesystem  # [DESTRUCTIVE]
mkfs.ext4 /dev/vg_data/lv_app

# Create with label  # [DESTRUCTIVE]
mkfs.ext4 -L appdata /dev/vg_data/lv_app

# Grow ext4 (online)  # [CONFIRM]
resize2fs /dev/vg_data/lv_app         # Grows to fill the LV
resize2fs /dev/vg_data/lv_app 50G     # Or to specific size

# Shrink ext4 (offline only)  # [DESTRUCTIVE]
umount /opt/app
e2fsck -f /dev/vg_data/lv_app
resize2fs /dev/vg_data/lv_app 30G
mount /opt/app

# ext4 info  # [READ-ONLY]
tune2fs -l /dev/vg_data/lv_app
dumpe2fs /dev/vg_data/lv_app | head -50

# Filesystem check (unmount first)  # [CONFIRM]
umount /opt/app
e2fsck -f /dev/vg_data/lv_app
mount /opt/app

XFS vs ext4 Comparison

Feature XFS ext4
Default on Rocky Yes No
Online grow Yes Yes
Online shrink No No
Offline shrink No (never) Yes
Max file size 8 EiB 16 TiB
Max volume size 8 EiB 1 EiB
Fragmentation Better for large files Better for small files
Journal Metadata only Metadata + optional data
Best for Large files, databases General purpose

fstab Configuration

Rules for fstab

  1. Always use UUID, never device paths (/dev/sdX can change between boots)
  2. Always run findmnt --verify after editing
  3. Keep a backup of fstab before editing

Find UUIDs

# Find UUID of a filesystem  # [READ-ONLY]
blkid
blkid /dev/vg_data/lv_app
lsblk -f

fstab Entry Format

# <device>                                <mountpoint>  <type>  <options>        <dump> <pass>
UUID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx /opt/app      xfs     defaults         0      2
UUID=yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy /var/log/app  ext4    defaults         0      2
/dev/vg_data/lv_app                       /opt/app      xfs     defaults         0      2

For LVM volumes, using the /dev/mapper/ or /dev/vg/lv path is acceptable since LVM names are stable:

/dev/mapper/vg_data-lv_app  /opt/app  xfs  defaults  0  2

Adding fstab Entry

# 1. Back up fstab  # [CONFIRM]
cp /etc/fstab /etc/fstab.bak.$(date +%Y%m%d%H%M%S)

# 2. Get UUID  # [READ-ONLY]
blkid /dev/vg_data/lv_app

# 3. Add entry to /etc/fstab  # [CONFIRM]
echo 'UUID=<uuid-here>  /opt/app  xfs  defaults  0  2' >> /etc/fstab

# 4. Verify fstab syntax  # [READ-ONLY]
findmnt --verify

# 5. Test mount  # [CONFIRM]
mount -a

# 6. Verify mount  # [READ-ONLY]
findmnt /opt/app
df -h /opt/app

WRONG -- skipping verification:

# WRONG: Edit fstab and reboot without testing
echo '/dev/sdb1 /data xfs defaults 0 2' >> /etc/fstab
reboot    # May fail to boot if fstab entry is wrong!

# CORRECT: Always verify before reboot
findmnt --verify     # Check for errors
mount -a             # Test all entries
# Only reboot if both commands succeed

Common Mount Options

Option Purpose
defaults rw, suid, dev, exec, auto, nouser, async
noexec Prevent execution of binaries
nosuid Ignore SUID/SGID bits
nodev Ignore device files
noatime Don't update access times (performance)
nofail Don't fail boot if device missing
ro Read-only

Security-hardened mount for /tmp:

UUID=xxx  /tmp  xfs  defaults,noexec,nosuid,nodev  0  2

Swap Management

# Check current swap  # [READ-ONLY]
swapon --show
free -h

# Create swap file  # [CONFIRM]
dd if=/dev/zero of=/swapfile bs=1M count=2048
chmod 600 /swapfile
mkswap /swapfile
swapon /swapfile

# Add to fstab  # [CONFIRM]
echo '/swapfile  none  swap  sw  0  0' >> /etc/fstab

# Create swap on LVM  # [CONFIRM]
lvcreate -L 4G -n lv_swap vg_data
mkswap /dev/vg_data/lv_swap
swapon /dev/vg_data/lv_swap
# Add to fstab:
# /dev/mapper/vg_data-lv_swap  none  swap  sw  0  0

Monitoring Disk Usage

# Filesystem usage  # [READ-ONLY]
df -h
df -hT

# Directory sizes  # [READ-ONLY]
du -sh /var/log/*
du -sh /home/* | sort -rh | head -10

# Find large files  # [READ-ONLY]
find / -xdev -type f -size +100M -exec ls -lh {} \; 2>/dev/null

# Inode usage (out of inodes = can't create files even with space)  # [READ-ONLY]
df -i

# Monitor IO  # [READ-ONLY]
iostat -x 1 5
iotop -b -n 3

Checklist: Adding New Storage

  • [ ] Identify the disk (lsblk, fdisk -l)
  • [ ] Partition if needed (parted or fdisk)
  • [ ] Create PV (pvcreate)
  • [ ] Create or extend VG (vgcreate or vgextend)
  • [ ] Create LV (lvcreate)
  • [ ] Create filesystem (mkfs.xfs or mkfs.ext4)
  • [ ] Create mount point (mkdir -p)
  • [ ] Add to fstab with UUID
  • [ ] Run findmnt --verify
  • [ ] Test with mount -a
  • [ ] Set SELinux context if needed (semanage fcontext + restorecon)
  • [ ] Verify with df -h and ls -Z

When to Use This Skill

  • Adding new disks or partitions
  • Extending logical volumes (the most common LVM task)
  • Creating or resizing filesystems
  • Editing /etc/fstab
  • Troubleshooting disk space issues
  • Setting up swap
  • LVM snapshot management
  • rocky-foundation -- OS detection, safety tiers
  • rocky-selinux -- Setting file contexts on new mount points
  • rocky-core-system -- systemd mount units (alternative to fstab)
  • rocky-borg-backup -- Backup before destructive storage operations

# Supported AI Coding Agents

This skill is compatible with the SKILL.md standard and works with all major AI coding agents:

Learn more about the SKILL.md standard and how to use these skills with your preferred AI coding agent.