supabase-postgres.git / summary / log / commit / refs
commit d0fbf41a7977a6551cc0b191ee6d37abcd9569bf
Author: andres suarez <valigula@gmail.com>
Commit: GitHub <noreply@github.com>
Date: Wed Jul 30 17:11:38 2025 +0000
feat: add script to mount/unmount disks (#1727)
* feat: add script to mount/unmount disks
* feat: add script to unmount disk
* fix: rmove files to correct path
* feat: validating the disk in a state
---------
Co-authored-by: andres.suarez <andres.suarez@supabase.io>
ansible/files/admin_api_scripts/mount-volume.sh | 62 +++++++++++++++++++++++
ansible/files/admin_api_scripts/unmount-volume.sh | 43 ++++++++++++++++
ansible/files/adminapi.sudoers.conf | 2 +
ansible/tasks/internal/admin-api.yml | 2 +
4 files changed, 109 insertions(+)
diff --git a/ansible/files/admin_api_scripts/mount-volume.sh b/ansible/files/admin_api_scripts/mount-volume.sh
new file mode 100644
index 00000000..5f4277f2
--- /dev/null
+++ b/ansible/files/admin_api_scripts/mount-volume.sh
@@ -0,0 +1,62 @@
+#!/usr/bin/env bash
+
+set -euo pipefail
+
+DEVICE=${1:-}
+MOUNT_POINT=${2:-}
+
+if [[ -z "$DEVICE" || -z "$MOUNT_POINT" ]]; then
+ echo "Usage: $0 <device> <mount_point>"
+ echo "Example: sudo ./mount-volume.sh /dev/nvme1n1 /data/150008"
+ exit 1
+fi
+
+# Mount a block device to a specified mount point
+# If the device is not formatted, format it as ext4
+# Set ownership to postgres:postgres and permissions to 750
+# Add the mount entry to /etc/fstab for persistence across reboots
+
+OWNER="postgres:postgres"
+PERMISSIONS="750"
+FSTYPE="ext4"
+MOUNT_OPTS="defaults"
+FSTAB_FILE="/etc/fstab"
+
+if [ ! -b "$DEVICE" ]; then
+ echo "Error: Block device '$DEVICE' does not exist."
+ exit 2
+fi
+
+if ! blkid "$DEVICE" >/dev/null 2>&1; then
+ echo "Device $DEVICE appears unformatted. Formatting as $FSTYPE..."
+ mkfs."$FSTYPE" -F "$DEVICE"
+else
+ echo "$DEVICE already has a filesystem — skipping format."
+fi
+
+mkdir -p "$MOUNT_POINT"
+
+e2fsck -pf "$DEVICE"
+
+if ! mountpoint -q "$MOUNT_POINT"; then
+ echo "Mounting $DEVICE to $MOUNT_POINT"
+ mount -t "$FSTYPE" -o "$MOUNT_OPTS" "$DEVICE" "$MOUNT_POINT"
+else
+ echo "$MOUNT_POINT is already mounted"
+fi
+
+echo "Setting ownership and permissions on $MOUNT_POINT"
+chown "$OWNER" "$MOUNT_POINT"
+chmod "$PERMISSIONS" "$MOUNT_POINT"
+
+UUID=$(blkid -s UUID -o value "$DEVICE")
+FSTAB_LINE="UUID=$UUID $MOUNT_POINT $FSTYPE $MOUNT_OPTS 0 2"
+
+if ! grep -q "$UUID" "$FSTAB_FILE"; then
+ echo "Adding $FSTAB_LINE to $FSTAB_FILE"
+ echo "$FSTAB_LINE" >> "$FSTAB_FILE"
+else
+ echo "UUID $UUID already in $FSTAB_FILE — skipping"
+fi
+
+echo "Mounted $DEVICE at $MOUNT_POINT with postgres:postgres and mode $PERMISSIONS"
diff --git a/ansible/files/admin_api_scripts/unmount-volume.sh b/ansible/files/admin_api_scripts/unmount-volume.sh
new file mode 100644
index 00000000..6250b8c4
--- /dev/null
+++ b/ansible/files/admin_api_scripts/unmount-volume.sh
@@ -0,0 +1,43 @@
+#!/usr/bin/env bash
+
+set -euo pipefail
+
+MOUNT_POINT=${1:-}
+DELETE_FLAG=${2:-}
+
+if [[ -z "$MOUNT_POINT" ]]; then
+ echo "Usage: $0 <mount_point> [--delete-dir]"
+ echo "Unmount only: sudo ./unmount-volume.sh /data/150008"
+ echo "Unmount delete dir: sudo ./unmount-volume.sh /data/150008 --delete-dir"
+ exit 1
+fi
+
+# Unmount a block device from a specified mount point
+# Remove the corresponding entry from /etc/fstab for persistence across reboots
+
+FSTAB_FILE="/etc/fstab"
+BACKUP_FILE="/etc/fstab.bak"
+
+if mountpoint -q "$MOUNT_POINT"; then
+ echo "Unmounting $MOUNT_POINT"
+ umount "$MOUNT_POINT"
+else
+ echo "$MOUNT_POINT is not currently mounted — skipping umount"
+fi
+
+UUID=$(findmnt -no UUID "$MOUNT_POINT" 2>/dev/null || true)
+
+if [[ -n "$UUID" ]]; then
+ echo "Removing UUID=$UUID from $FSTAB_FILE"
+ cp "$FSTAB_FILE" "$BACKUP_FILE"
+ sed -i "/UUID=${UUID//\//\\/}/d" "$FSTAB_FILE"
+else
+ echo "Could not find UUID for $MOUNT_POINT — skipping fstab cleanup"
+fi
+
+if [[ "$DELETE_FLAG" == "--delete-dir" ]]; then
+ echo "Deleting mount point directory: $MOUNT_POINT"
+ rm -rf "$MOUNT_POINT"
+fi
+
+echo "Unmount and cleanup complete for $MOUNT_POINT"
diff --git a/ansible/files/adminapi.sudoers.conf b/ansible/files/adminapi.sudoers.conf
index 531d47ca..904377c2 100644
--- a/ansible/files/adminapi.sudoers.conf
+++ b/ansible/files/adminapi.sudoers.conf
@@ -5,6 +5,8 @@ Cmnd_Alias GOTRUE = /bin/systemctl start gotrue.service, /bin/systemctl stop got
Cmnd_Alias PGBOUNCER = /bin/systemctl start pgbouncer.service, /bin/systemctl stop pgbouncer.service, /bin/systemctl restart pgbouncer.service, /bin/systemctl disable pgbouncer.service, /bin/systemctl enable pgbouncer.service, /bin/systemctl reload pgbouncer.service, /bin/systemctl try-restart pgbouncer.service
%adminapi ALL= NOPASSWD: /root/grow_fs.sh
+%adminapi ALL= NOPASSWD: /root/mount-volume.sh
+%adminapi ALL= NOPASSWD: /root/unmount-volume.sh
%adminapi ALL= NOPASSWD: /root/manage_readonly_mode.sh
%adminapi ALL= NOPASSWD: /etc/adminapi/pg_upgrade_scripts/prepare.sh
%adminapi ALL= NOPASSWD: /etc/adminapi/pg_upgrade_scripts/initiate.sh
diff --git a/ansible/tasks/internal/admin-api.yml b/ansible/tasks/internal/admin-api.yml
index 5eb6fd27..5844b3f5 100644
--- a/ansible/tasks/internal/admin-api.yml
+++ b/ansible/tasks/internal/admin-api.yml
@@ -14,6 +14,8 @@
- { file: "grow_fs.sh" }
- { file: "manage_readonly_mode.sh" }
- { file: "pg_egress_collect.pl" }
+ - { file: "mount-volume.sh" }
+ - { file: "unmount-volume.sh" }
- name: give adminapi user permissions
copy:
[parent: ae29c6f6d07e]