125 lines
3.6 KiB
Bash
Executable File
125 lines
3.6 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
# shellcheck source=./lib.sh
|
|
source "$SCRIPT_DIR/lib.sh"
|
|
|
|
DEVICE=""
|
|
MOUNT_POINT="/srv/ops"
|
|
FS_TYPE="ext4"
|
|
AUTO_YES=false
|
|
FORCE_FORMAT=false
|
|
|
|
usage() {
|
|
cat <<USAGE
|
|
Usage: $(basename "$0") [options]
|
|
|
|
Prepare and mount an SSD for persistent monitoring data.
|
|
|
|
Options:
|
|
--device=/dev/sda1 Block device or partition to mount
|
|
--mount-point=PATH Mount path (default: /srv/ops)
|
|
--fs=ext4 Filesystem to create if blank (default: ext4)
|
|
--force-format Reformat even if filesystem exists (destructive)
|
|
--yes, -y Skip confirmation prompts
|
|
--help, -h Show help
|
|
|
|
Examples:
|
|
$(basename "$0") --device=/dev/sda1
|
|
$(basename "$0") --device=/dev/sda --force-format --yes
|
|
USAGE
|
|
}
|
|
|
|
for arg in "$@"; do
|
|
case "$arg" in
|
|
--device=*) DEVICE="${arg#*=}" ;;
|
|
--mount-point=*) MOUNT_POINT="${arg#*=}" ;;
|
|
--fs=*) FS_TYPE="${arg#*=}" ;;
|
|
--force-format) FORCE_FORMAT=true ;;
|
|
--yes|-y) AUTO_YES=true ;;
|
|
--help|-h) usage; exit 0 ;;
|
|
*) log_error "Unknown argument: $arg"; usage; exit 1 ;;
|
|
esac
|
|
done
|
|
|
|
require_cmd sudo lsblk blkid findmnt mount mountpoint grep awk sed
|
|
|
|
if [[ -z "$DEVICE" ]]; then
|
|
root_parent="/dev/$(lsblk -no PKNAME "$(findmnt -n -o SOURCE /)")"
|
|
DEVICE="$(lsblk -dpno NAME,TYPE | awk '$2 == "disk" {print $1}' | grep -v "^${root_parent}$" | head -n1 || true)"
|
|
if [[ -z "$DEVICE" ]]; then
|
|
log_error "Could not auto-detect a non-root disk. Specify --device=/dev/sdX1"
|
|
exit 1
|
|
fi
|
|
log_info "Auto-detected device: $DEVICE"
|
|
fi
|
|
|
|
if [[ ! -b "$DEVICE" ]]; then
|
|
log_error "Device does not exist or is not a block device: $DEVICE"
|
|
exit 1
|
|
fi
|
|
|
|
TARGET_DEVICE="$DEVICE"
|
|
if [[ "$(lsblk -no TYPE "$DEVICE")" == "disk" ]]; then
|
|
first_part="$(lsblk -ln -o NAME "$DEVICE" | sed -n '2p' || true)"
|
|
if [[ -n "$first_part" ]]; then
|
|
TARGET_DEVICE="/dev/${first_part}"
|
|
log_info "Using first partition on disk: $TARGET_DEVICE"
|
|
fi
|
|
fi
|
|
|
|
existing_fs="$(sudo blkid -s TYPE -o value "$TARGET_DEVICE" 2>/dev/null || true)"
|
|
if [[ -n "$existing_fs" && "$FORCE_FORMAT" != "true" ]]; then
|
|
log_info "Existing filesystem detected on $TARGET_DEVICE: $existing_fs"
|
|
log_info "Skipping format. Use --force-format to recreate filesystem."
|
|
else
|
|
if [[ -n "$existing_fs" && "$FORCE_FORMAT" == "true" ]]; then
|
|
prompt="Reformat $TARGET_DEVICE (current: $existing_fs)? This destroys existing data. Continue?"
|
|
else
|
|
prompt="Create new $FS_TYPE filesystem on $TARGET_DEVICE?"
|
|
fi
|
|
|
|
if ! confirm_action "$prompt" "$AUTO_YES"; then
|
|
log_info "Cancelled"
|
|
exit 0
|
|
fi
|
|
|
|
log_info "Formatting $TARGET_DEVICE as $FS_TYPE..."
|
|
sudo mkfs -t "$FS_TYPE" "$TARGET_DEVICE"
|
|
fi
|
|
|
|
uuid="$(sudo blkid -s UUID -o value "$TARGET_DEVICE" 2>/dev/null || true)"
|
|
if [[ -z "$uuid" ]]; then
|
|
log_error "Could not read UUID from $TARGET_DEVICE"
|
|
exit 1
|
|
fi
|
|
|
|
sudo mkdir -p "$MOUNT_POINT"
|
|
|
|
fstab_line="UUID=${uuid} ${MOUNT_POINT} ${FS_TYPE} defaults,noatime,nofail 0 2"
|
|
if grep -q "UUID=${uuid}" /etc/fstab; then
|
|
log_info "Existing fstab entry found for UUID=${uuid}; leaving as-is"
|
|
else
|
|
log_info "Adding mount to /etc/fstab"
|
|
printf '%s\n' "$fstab_line" | sudo tee -a /etc/fstab >/dev/null
|
|
fi
|
|
|
|
log_info "Mounting $MOUNT_POINT..."
|
|
if mountpoint -q "$MOUNT_POINT"; then
|
|
log_info "$MOUNT_POINT is already mounted"
|
|
else
|
|
sudo mount "$MOUNT_POINT"
|
|
fi
|
|
|
|
log_info "Creating monitoring data directories..."
|
|
sudo mkdir -p \
|
|
"$MOUNT_POINT/portainer/data" \
|
|
"$MOUNT_POINT/grafana/data" \
|
|
"$MOUNT_POINT/prometheus/data" \
|
|
"$MOUNT_POINT/prometheus/targets" \
|
|
"$MOUNT_POINT/uptime-kuma/data" \
|
|
"$MOUNT_POINT/backups"
|
|
|
|
log_success "SSD mount ready at $MOUNT_POINT"
|