Untitled
unknown
plain_text
10 months ago
5.7 kB
12
Indexable
#!/usr/bin/env bash
# Create separate LVs for /var, /var/log, /var/log/audit, /var/tmp
# AlmaLinux 9.6 — CIS-ish mount options (nosuid,noexec + nodev)
set -euo pipefail
# ---------- Tunables ----------
# Sizes (change as needed)
VAR_SIZE="${VAR_SIZE:-20G}"
VAR_LOG_SIZE="${VAR_LOG_SIZE:-4G}"
VAR_AUDIT_SIZE="${VAR_AUDIT_SIZE:-2G}"
VAR_TMP_SIZE="${VAR_TMP_SIZE:-4G}"
# Mount options
# Per your ask: nosuid+noexec everywhere. nodev added as a safe default.
# If you *don't* want noexec on /var, set VAR_NOEXEC=0 before running.
VAR_NOEXEC="${VAR_NOEXEC:-1}"
# Filesystem type
FS_TYPE="${FS_TYPE:-xfs}"
# ---------- Helpers ----------
die(){ echo "[!] $*" >&2; exit 1; }
ok(){ echo "[+] $*"; }
run(){ echo "[*] $*"; eval "$@"; }
[[ $EUID -eq 0 ]] || die "Run as root."
# Find a VG with free space (first match)
VG_NAME="${VG_NAME:-$(vgs --noheadings -o vg_name,vg_free --units m --nosuffix \
| awk '$2+0>0 {print $1; exit}')}"
[[ -n "${VG_NAME}" ]] || die "No LVM volume group with free space found. Set VG_NAME=your_vg and ensure free extents."
ok "Using VG: ${VG_NAME}"
# Device paths
LV_VAR="/dev/${VG_NAME}/var"
LV_LOG="/dev/${VG_NAME}/var_log"
LV_AUD="/dev/${VG_NAME}/var_log_audit"
LV_TMP="/dev/${VG_NAME}/var_tmp"
# Create LVs if missing
maybe_lvcreate () {
local lv="$1" size="$2" name="$(basename "$lv")"
if lvdisplay "$lv" &>/dev/null; then
ok "LV $lv already exists"
else
run "lvcreate -L ${size} -n ${name} ${VG_NAME}"
fi
}
maybe_lvcreate "$LV_VAR" "$VAR_SIZE"
maybe_lvcreate "$LV_LOG" "$VAR_LOG_SIZE"
maybe_lvcreate "$LV_AUD" "$VAR_AUDIT_SIZE"
maybe_lvcreate "$LV_TMP" "$VAR_TMP_SIZE"
# Make filesystems if needed
maybe_mkfs () {
local dev="$1"
if blkid "$dev" &>/dev/null; then
ok "Filesystem already present on $dev"
else
run "mkfs.${FS_TYPE} -f $dev"
fi
}
maybe_mkfs "$LV_VAR"
maybe_mkfs "$LV_LOG"
maybe_mkfs "$LV_AUD"
maybe_mkfs "$LV_TMP"
# Temp mount points
mkdir -p /mnt/newvar /mnt/newvarlog /mnt/newaudit /mnt/newvartmp
# Mount new filesystems to staging
mountpoint -q /mnt/newvar || run "mount $LV_VAR /mnt/newvar"
mountpoint -q /mnt/newvarlog || run "mount $LV_LOG /mnt/newvarlog"
mountpoint -q /mnt/newaudit || run "mount $LV_AUD /mnt/newaudit"
mountpoint -q /mnt/newvartmp || run "mount $LV_TMP /mnt/newvartmp"
# First pass copy (preserve ACLs, xattrs, selinux)
ok "Copying data (first pass)…"
run "rsync -aAXH --numeric-ids /var/ /mnt/newvar/"
run "rsync -aAXH --numeric-ids /var/log/ /mnt/newvarlog/"
mkdir -p /var/log/audit
run "rsync -aAXH --numeric-ids /var/log/audit/ /mnt/newaudit/"
run "rsync -aAXH --numeric-ids /var/tmp/ /mnt/newvartmp/"
# Quiesce logging briefly for a clean second pass
run "systemctl stop rsyslog || true"
run "systemctl stop auditd || true"
sleep 1
# Second pass (catch deltas)
ok "Copying data (second pass)…"
run "rsync -aAXH --delete --numeric-ids /var/ /mnt/newvar/"
run "rsync -aAXH --delete --numeric-ids /var/log/ /mnt/newvarlog/"
run "rsync -aAXH --delete --numeric-ids /var/log/audit/ /mnt/newaudit/"
run "rsync -aAXH --delete --numeric-ids /var/tmp/ /mnt/newvartmp/"
# Ensure required directories exist on the new /var
mkdir -p /mnt/newvar/log /mnt/newvar/log/audit /mnt/newvar/tmp
# Start services back
run "systemctl start auditd || true"
run "systemctl start rsyslog || true"
# Get UUIDs
UUID_VAR="$(blkid -s UUID -o value "$LV_VAR")"
UUID_LOG="$(blkid -s UUID -o value "$LV_LOG")"
UUID_AUD="$(blkid -s UUID -o value "$LV_AUD")"
UUID_TMP="$(blkid -s UUID -o value "$LV_TMP")"
[[ -n "$UUID_VAR" && -n "$UUID_LOG" && -n "$UUID_AUD" && -n "$UUID_TMP" ]] || die "Could not read UUIDs."
# Compose mount options
VAR_OPTS="defaults,nodev"
if [[ "${VAR_NOEXEC}" -eq 1 ]]; then
VAR_OPTS="${VAR_OPTS},nosuid,noexec"
fi
LOG_OPTS="defaults,nodev,nosuid,noexec"
AUD_OPTS="defaults,nodev,nosuid,noexec"
TMP_OPTS="defaults,nodev,nosuid,noexec"
# Backup fstab
cp -a /etc/fstab "/etc/fstab.bak.$(date +%Y%m%d-%H%M%S)"
# Remove any previous lines for these mountpoints (idempotent)
sed -i -r '/[[:space:]]\/var[[:space:]]/d' /etc/fstab
sed -i -r '/[[:space:]]\/var\/log[[:space:]]/d' /etc/fstab
sed -i -r '/[[:space:]]\/var\/log\/audit[[:space:]]/d' /etc/fstab
sed -i -r '/[[:space:]]\/var\/tmp[[:space:]]/d' /etc/fstab
# Append new entries
cat >>/etc/fstab <<EOF
UUID=${UUID_VAR} /var ${FS_TYPE} ${VAR_OPTS} 0 2
UUID=${UUID_LOG} /var/log ${FS_TYPE} ${LOG_OPTS} 0 2
UUID=${UUID_AUD} /var/log/audit ${FS_TYPE} ${AUD_OPTS} 0 2
UUID=${UUID_TMP} /var/tmp ${FS_TYPE} ${TMP_OPTS} 0 2
EOF
ok "Updated /etc/fstab with secure options."
# Create mountpoints (in case they don't exist) and mount the subtrees now
mkdir -p /var/log /var/log/audit /var/tmp
# Mount sub-mounts immediately (safe without reboot)
run "mount /var/log"
run "mount /var/log/audit"
run "mount /var/tmp"
# Restore SELinux context on mounted paths
run "restorecon -RFv /var/log /var/log/audit /var/tmp || true"
ok "Sub-mounts active. /var itself will switch at next reboot."
echo
echo "========================================================="
echo " Migration complete."
echo " - /var/log, /var/log/audit, /var/tmp are mounted now."
echo " - /var will switch to its new LV on the next reboot."
echo " - Verify: lsblk -f; findmnt /var/log /var/log/audit /var/tmp"
echo " *If you want to activate /var now anyway*, you can:"
echo " 1) ensure services are quiet, then"
echo " 2) run: mount /var (NOT RECOMMENDED on a busy system)"
echo "========================================================="
Editor is loading...
Leave a Comment