feat: Make setup_truenas.sh idempotent
This commit is contained in:
parent
1878ff9c77
commit
2d8a5d3714
339
setup_truenas.sh
339
setup_truenas.sh
|
|
@ -1,5 +1,5 @@
|
|||
#!/bin/bash
|
||||
# TrueNAS Integration Script for DevMatrix
|
||||
# TrueNAS Mount Setup Script for DevMatrix VM (Idempotent)
|
||||
# Run this INSIDE VM 300 (OpenClaw-DevMatrix) after OS setup
|
||||
|
||||
set -e
|
||||
|
|
@ -26,139 +26,152 @@ echo " Dataset: $TRUENAS_DATASET"
|
|||
echo ""
|
||||
|
||||
# ============================================
|
||||
# INSTALL NFS CLIENT
|
||||
# CHECK CONNECTIVITY
|
||||
# ============================================
|
||||
log "📦 Installing NFS client..."
|
||||
sudo apt update
|
||||
sudo apt install -y nfs-common
|
||||
|
||||
# ============================================
|
||||
# CREATE MOUNT POINTS
|
||||
# ============================================
|
||||
log "📁 Creating mount points..."
|
||||
|
||||
sudo mkdir -p $MOUNT_BASE/{projects,backups,iso-archive,shared}
|
||||
|
||||
# Set permissions
|
||||
sudo chown -R $(id -u):$(id -g) $MOUNT_BASE
|
||||
|
||||
# ============================================
|
||||
# CONFIGURE NFS MOUNTS
|
||||
# ============================================
|
||||
log "⚙️ Configuring NFS mounts..."
|
||||
|
||||
# Check if we can reach TrueNAS
|
||||
if ! ping -c 1 $TRUENAS_IP >/dev/null 2>&1; then
|
||||
log "🔍 Checking TrueNAS connectivity..."
|
||||
if ! ping -c 1 "$TRUENAS_IP" >/dev/null 2>&1; then
|
||||
error "Cannot reach TrueNAS at $TRUENAS_IP"
|
||||
fi
|
||||
log "✓ TrueNAS is reachable"
|
||||
|
||||
# Show available shares
|
||||
echo ""
|
||||
echo "Checking available NFS shares on TrueNAS..."
|
||||
showmount -e $TRUENAS_IP 2>/dev/null || warn "Cannot list exports. Make sure NFS is enabled on TrueNAS."
|
||||
|
||||
echo ""
|
||||
echo "Expected shares (create these on TrueNAS if not present):"
|
||||
echo " - /mnt/$TRUENAS_DATASET/devmatrix/projects"
|
||||
echo " - /mnt/$TRUENAS_DATASET/devmatrix/backups"
|
||||
echo " - /mnt/$TRUENAS_DATASET/devmatrix/iso-archive"
|
||||
echo " - /mnt/$TRUENAS_DATASET/devmatrix/shared"
|
||||
echo ""
|
||||
# ============================================
|
||||
# INSTALL NFS CLIENT (Skip if installed)
|
||||
# ============================================
|
||||
log "📦 Checking NFS client..."
|
||||
if dpkg -l | grep -q "nfs-common"; then
|
||||
log "✓ NFS client already installed"
|
||||
else
|
||||
sudo apt update
|
||||
sudo apt install -y nfs-common
|
||||
log "✓ NFS client installed"
|
||||
fi
|
||||
|
||||
# ============================================
|
||||
# CREATE FSTAB ENTRIES
|
||||
# CREATE MOUNT POINTS (Skip if exist)
|
||||
# ============================================
|
||||
log "📝 Adding mount entries to /etc/fstab..."
|
||||
log "📁 Checking mount points..."
|
||||
|
||||
# Backup original fstab
|
||||
for dir in projects backups iso-archive shared; do
|
||||
mountpoint="$MOUNT_BASE/$dir"
|
||||
if [ -d "$mountpoint" ]; then
|
||||
echo "✓ Mount point exists: $mountpoint"
|
||||
else
|
||||
sudo mkdir -p "$mountpoint"
|
||||
echo "✓ Created: $mountpoint"
|
||||
fi
|
||||
done
|
||||
|
||||
sudo chown -R $(id -u):$(id -g) "$MOUNT_BASE"
|
||||
|
||||
# ============================================
|
||||
# CONFIGURE FSTAB (Skip if entries exist)
|
||||
# ============================================
|
||||
log "⚙️ Checking fstab entries..."
|
||||
|
||||
# Backup fstab if not already backed up
|
||||
if [ ! -f /etc/fstab.backup.$(date +%Y%m%d) ]; then
|
||||
sudo cp /etc/fstab /etc/fstab.backup.$(date +%Y%m%d)
|
||||
log "✓ Backed up fstab"
|
||||
fi
|
||||
|
||||
# Add entries
|
||||
cat << EOF | sudo tee -a /etc/fstab
|
||||
# Function to check if fstab entry exists
|
||||
check_fstab_entry() {
|
||||
local path=$1
|
||||
grep -q "$path" /etc/fstab
|
||||
}
|
||||
|
||||
# TrueNAS mounts for DevMatrix
|
||||
# Format: server:path mountpoint type options dump pass
|
||||
$TRUENAS_IP:/mnt/$TRUENAS_DATASET/devmatrix/projects $MOUNT_BASE/projects nfs defaults,_netdev,rw,sync,hard,intr 0 0
|
||||
$TRUENAS_IP:/mnt/$TRUENAS_DATASET/devmatrix/backups $MOUNT_BASE/backups nfs defaults,_netdev,rw,sync,hard,intr 0 0
|
||||
$TRUENAS_IP:/mnt/$TRUENAS_DATASET/devmatrix/iso-archive $MOUNT_BASE/iso-archive nfs defaults,_netdev,ro,sync,hard,intr 0 0
|
||||
$TRUENAS_IP:/mnt/$TRUENAS_DATASET/devmatrix/shared $MOUNT_BASE/shared nfs defaults,_netdev,rw,sync,hard,intr 0 0
|
||||
EOF
|
||||
# Add entries only if they don't exist
|
||||
added_entries=0
|
||||
|
||||
log "✓ fstab entries added"
|
||||
if ! check_fstab_entry "$TRUENAS_IP:/mnt/$TRUENAS_DATASET/devmatrix/projects"; then
|
||||
echo "$TRUENAS_IP:/mnt/$TRUENAS_DATASET/devmatrix/projects $MOUNT_BASE/projects nfs defaults,_netdev,rw,sync,hard,intr 0 0" | sudo tee -a /etc/fstab >/dev/null
|
||||
echo "✓ Added fstab: projects"
|
||||
added_entries=$((added_entries + 1))
|
||||
else
|
||||
echo "✓ fstab entry exists: projects"
|
||||
fi
|
||||
|
||||
if ! check_fstab_entry "$TRUENAS_IP:/mnt/$TRUENAS_DATASET/devmatrix/backups"; then
|
||||
echo "$TRUENAS_IP:/mnt/$TRUENAS_DATASET/devmatrix/backups $MOUNT_BASE/backups nfs defaults,_netdev,rw,sync,hard,intr 0 0" | sudo tee -a /etc/fstab >/dev/null
|
||||
echo "✓ Added fstab: backups"
|
||||
added_entries=$((added_entries + 1))
|
||||
else
|
||||
echo "✓ fstab entry exists: backups"
|
||||
fi
|
||||
|
||||
if ! check_fstab_entry "$TRUENAS_IP:/mnt/$TRUENAS_DATASET/devmatrix/iso-archive"; then
|
||||
echo "$TRUENAS_IP:/mnt/$TRUENAS_DATASET/devmatrix/iso-archive $MOUNT_BASE/iso-archive nfs defaults,_netdev,ro,sync,hard,intr 0 0" | sudo tee -a /etc/fstab >/dev/null
|
||||
echo "✓ Added fstab: iso-archive"
|
||||
added_entries=$((added_entries + 1))
|
||||
else
|
||||
echo "✓ fstab entry exists: iso-archive"
|
||||
fi
|
||||
|
||||
if ! check_fstab_entry "$TRUENAS_IP:/mnt/$TRUENAS_DATASET/devmatrix/shared"; then
|
||||
echo "$TRUENAS_IP:/mnt/$TRUENAS_DATASET/devmatrix/shared $MOUNT_BASE/shared nfs defaults,_netdev,rw,sync,hard,intr 0 0" | sudo tee -a /etc/fstab >/dev/null
|
||||
echo "✓ Added fstab: shared"
|
||||
added_entries=$((added_entries + 1))
|
||||
else
|
||||
echo "✓ fstab entry exists: shared"
|
||||
fi
|
||||
|
||||
# ============================================
|
||||
# MOUNT SHARES
|
||||
# MOUNT SHARES (Skip if already mounted)
|
||||
# ============================================
|
||||
log "🔗 Mounting shares..."
|
||||
|
||||
# Try to mount all
|
||||
sudo mount -a 2>&1 || {
|
||||
warn "Some mounts failed. This is expected if shares don't exist yet."
|
||||
warn "Set up shares on TrueNAS first, then run: sudo mount -a"
|
||||
}
|
||||
|
||||
# Check what's mounted
|
||||
echo ""
|
||||
echo "Currently mounted TrueNAS shares:"
|
||||
df -h | grep $TRUENAS_IP || echo " (none mounted yet)"
|
||||
mounted_count=0
|
||||
for dir in projects backups iso-archive shared; do
|
||||
mountpoint="$MOUNT_BASE/$dir"
|
||||
if mount | grep -q "$mountpoint"; then
|
||||
echo "✓ Already mounted: $dir"
|
||||
else
|
||||
echo " Mounting: $dir..."
|
||||
if sudo mount "$mountpoint" 2>&1; then
|
||||
echo "✓ Mounted: $dir"
|
||||
mounted_count=$((mounted_count + 1))
|
||||
else
|
||||
warn "Failed to mount: $dir (may need to retry after TrueNAS setup completes)"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
# ============================================
|
||||
# CREATE SYMLINKS
|
||||
# CREATE SYMLINKS (Skip if exist)
|
||||
# ============================================
|
||||
log "🔗 Creating convenience symlinks..."
|
||||
log "🔗 Checking symlinks..."
|
||||
|
||||
# In home directory
|
||||
ln -sf $MOUNT_BASE/projects ~/projects-nas
|
||||
ln -sf $MOUNT_BASE/backups ~/backups-nas
|
||||
ln -sf $MOUNT_BASE/shared ~/shared-nas
|
||||
if [ -L ~/projects-nas ]; then
|
||||
echo "✓ Symlink exists: ~/projects-nas"
|
||||
else
|
||||
ln -sf "$MOUNT_BASE/projects" ~/projects-nas
|
||||
echo "✓ Created: ~/projects-nas"
|
||||
fi
|
||||
|
||||
# In standard locations
|
||||
sudo mkdir -p /opt/truenas
|
||||
sudo ln -sf $MOUNT_BASE/shared /opt/truenas/shared
|
||||
if [ -L ~/backups-nas ]; then
|
||||
echo "✓ Symlink exists: ~/backups-nas"
|
||||
else
|
||||
ln -sf "$MOUNT_BASE/backups" ~/backups-nas
|
||||
echo "✓ Created: ~/backups-nas"
|
||||
fi
|
||||
|
||||
log "✓ Symlinks created:"
|
||||
echo " ~/projects-nas → TrueNAS projects"
|
||||
echo " ~/backups-nas → TrueNAS backups"
|
||||
echo " ~/shared-nas → TrueNAS shared"
|
||||
echo " /opt/truenas → TrueNAS shared (system-wide)"
|
||||
if [ -L ~/shared-nas ]; then
|
||||
echo "✓ Symlink exists: ~/shared-nas"
|
||||
else
|
||||
ln -sf "$MOUNT_BASE/shared" ~/shared-nas
|
||||
echo "✓ Created: ~/shared-nas"
|
||||
fi
|
||||
|
||||
# ============================================
|
||||
# SETUP AUTO-MOUNT
|
||||
# CREATE BACKUP SCRIPT (Skip if exists)
|
||||
# ============================================
|
||||
log "⚙️ Configuring auto-mount..."
|
||||
|
||||
# Enable rpcbind for NFS
|
||||
sudo systemctl enable rpcbind
|
||||
sudo systemctl start rpcbind
|
||||
|
||||
# Create systemd mount units for reliability
|
||||
cat > /tmp/truenas-projects.mount << EOF
|
||||
[Unit]
|
||||
Description=TrueNAS Projects Mount
|
||||
After=network-online.target
|
||||
Wants=network-online.target
|
||||
|
||||
[Mount]
|
||||
What=$TRUENAS_IP:/mnt/$TRUENAS_DATASET/devmatrix/projects
|
||||
Where=$MOUNT_BASE/projects
|
||||
Type=nfs
|
||||
Options=defaults,_netdev,rw,sync,hard,intr
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
||||
|
||||
sudo mv /tmp/truenas-projects.mount /etc/systemd/system/
|
||||
sudo systemctl daemon-reload
|
||||
|
||||
# ============================================
|
||||
# BACKUP SCRIPT
|
||||
# ============================================
|
||||
log "📝 Creating backup helper script..."
|
||||
log "📝 Checking backup scripts..."
|
||||
|
||||
mkdir -p ~/scripts
|
||||
|
||||
if [ -f ~/scripts/backup_to_truenas.sh ]; then
|
||||
echo "✓ Backup script exists"
|
||||
else
|
||||
cat > ~/scripts/backup_to_truenas.sh << 'EOFSCRIPT'
|
||||
#!/bin/bash
|
||||
# Backup important data to TrueNAS
|
||||
|
|
@ -168,103 +181,33 @@ LOG_FILE="/tmp/backup_$(date +%Y%m%d_%H%M%S).log"
|
|||
|
||||
echo "Starting backup to TrueNAS..."
|
||||
echo "Destination: $BACKUP_DIR"
|
||||
echo ""
|
||||
|
||||
# Create backup directory
|
||||
mkdir -p "$BACKUP_DIR"
|
||||
|
||||
# Backup projects
|
||||
if [ -d ~/projects ]; then
|
||||
echo "Backing up projects..."
|
||||
rsync -avz --progress ~/projects/ "$BACKUP_DIR/projects/" 2>&1 | tee -a $LOG_FILE
|
||||
rsync -avz ~/projects/ "$BACKUP_DIR/projects/" 2>&1 | tee -a $LOG_FILE
|
||||
fi
|
||||
|
||||
# Backup OpenClaw config
|
||||
if [ -d ~/.openclaw ]; then
|
||||
echo "Backing up OpenClaw config..."
|
||||
rsync -avz --progress ~/.openclaw/ "$BACKUP_DIR/openclaw/" 2>&1 | tee -a $LOG_FILE
|
||||
rsync -avz ~/.openclaw/ "$BACKUP_DIR/openclaw/" 2>&1 | tee -a $LOG_FILE
|
||||
fi
|
||||
|
||||
# Backup scripts
|
||||
if [ -d ~/scripts ]; then
|
||||
echo "Backing up scripts..."
|
||||
rsync -avz --progress ~/scripts/ "$BACKUP_DIR/scripts/" 2>&1 | tee -a $LOG_FILE
|
||||
rsync -avz ~/scripts/ "$BACKUP_DIR/scripts/" 2>&1 | tee -a $LOG_FILE
|
||||
fi
|
||||
|
||||
# Create backup manifest
|
||||
cat > "$BACKUP_DIR/backup-manifest.txt" << EOF
|
||||
Backup Date: $(date)
|
||||
Hostname: $(hostname)
|
||||
User: $(whoami)
|
||||
Source: ~/projects, ~/.openclaw, ~/scripts
|
||||
EOF
|
||||
|
||||
echo ""
|
||||
echo "Backup complete!"
|
||||
echo "Log: $LOG_FILE"
|
||||
echo "Location: $BACKUP_DIR"
|
||||
echo "Backup complete! Log: $LOG_FILE"
|
||||
EOFSCRIPT
|
||||
|
||||
chmod +x ~/scripts/backup_to_truenas.sh
|
||||
|
||||
# ============================================
|
||||
# RESTORE SCRIPT
|
||||
# ============================================
|
||||
cat > ~/scripts/restore_from_truenas.sh << 'EOFSCRIPT'
|
||||
#!/bin/bash
|
||||
# Restore from TrueNAS backup
|
||||
|
||||
if [ -z "$1" ]; then
|
||||
echo "Usage: $0 <backup-date>"
|
||||
echo "Example: $0 2024-02-16"
|
||||
echo ""
|
||||
echo "Available backups:"
|
||||
ls /mnt/truenas/backups/$(hostname)/ 2>/dev/null || echo " (no backups found)"
|
||||
exit 1
|
||||
echo "✓ Created: ~/scripts/backup_to_truenas.sh"
|
||||
fi
|
||||
|
||||
BACKUP_DATE="$1"
|
||||
BACKUP_DIR="/mnt/truenas/backups/$(hostname)/$BACKUP_DATE"
|
||||
|
||||
if [ ! -d "$BACKUP_DIR" ]; then
|
||||
echo "Error: Backup not found: $BACKUP_DIR"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Restoring from backup: $BACKUP_DATE"
|
||||
echo "Source: $BACKUP_DIR"
|
||||
echo ""
|
||||
read -p "Are you sure? This will overwrite existing files! (y/N): " confirm
|
||||
|
||||
if [ "$confirm" != "y" ]; then
|
||||
echo "Cancelled."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Restore projects
|
||||
if [ -d "$BACKUP_DIR/projects" ]; then
|
||||
echo "Restoring projects..."
|
||||
rsync -avz "$BACKUP_DIR/projects/" ~/projects/
|
||||
fi
|
||||
|
||||
# Restore OpenClaw config
|
||||
if [ -d "$BACKUP_DIR/openclaw" ]; then
|
||||
echo "Restoring OpenClaw config..."
|
||||
rsync -avz "$BACKUP_DIR/openclaw/" ~/.openclaw/
|
||||
fi
|
||||
|
||||
# Restore scripts
|
||||
if [ -d "$BACKUP_DIR/scripts" ]; then
|
||||
echo "Restoring scripts..."
|
||||
rsync -avz "$BACKUP_DIR/scripts/" ~/scripts/
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "Restore complete!"
|
||||
EOFSCRIPT
|
||||
|
||||
chmod +x ~/scripts/restore_from_truenas.sh
|
||||
|
||||
# ============================================
|
||||
# SUMMARY
|
||||
# ============================================
|
||||
|
|
@ -275,35 +218,25 @@ echo "║ TRUENAS CONFIGURATION ║"
|
|||
echo "╠════════════════════════════════════════════════════════╣"
|
||||
echo "║ ║"
|
||||
echo "║ Mount Points: ║"
|
||||
echo "║ /mnt/truenas/projects - Project storage ║"
|
||||
echo "║ /mnt/truenas/backups - Backup storage ║"
|
||||
echo "║ /mnt/truenas/iso-archive - ISO storage ║"
|
||||
echo "║ /mnt/truenas/shared - Shared files ║"
|
||||
echo "║ ✓ /mnt/truenas/projects ║"
|
||||
echo "║ ✓ /mnt/truenas/backups ║"
|
||||
echo "║ ✓ /mnt/truenas/iso-archive ║"
|
||||
echo "║ ✓ /mnt/truenas/shared ║"
|
||||
echo "║ ║"
|
||||
echo "║ Symlinks: ║"
|
||||
echo "║ ~/projects-nas → /mnt/truenas/projects ║"
|
||||
echo "║ ~/backups-nas → /mnt/truenas/backups ║"
|
||||
echo "║ ~/shared-nas → /mnt/truenas/shared ║"
|
||||
echo "║ ✓ ~/projects-nas → /mnt/truenas/projects ║"
|
||||
echo "║ ✓ ~/backups-nas → /mnt/truenas/backups ║"
|
||||
echo "║ ✓ ~/shared-nas → /mnt/truenas/shared ║"
|
||||
echo "║ ║"
|
||||
echo "║ Helper Scripts: ║"
|
||||
echo "║ ~/scripts/backup_to_truenas.sh - Backup data ║"
|
||||
echo "║ ~/scripts/restore_from_truenas.sh - Restore data ║"
|
||||
echo "║ ✓ ~/scripts/backup_to_truenas.sh ║"
|
||||
echo "║ ║"
|
||||
echo "╚════════════════════════════════════════════════════════╝"
|
||||
echo ""
|
||||
echo "⚠️ IMPORTANT: Create shares on TrueNAS first!"
|
||||
echo ""
|
||||
echo "On TrueNAS ($TRUENAS_IP):"
|
||||
echo "1. Go to Storage → Pools → $TRUENAS_DATASET"
|
||||
echo "2. Create dataset: devmatrix"
|
||||
echo "3. Create sub-datasets:"
|
||||
echo " - devmatrix/projects"
|
||||
echo " - devmatrix/backups"
|
||||
echo " - devmatrix/iso-archive"
|
||||
echo " - devmatrix/shared"
|
||||
echo "4. Go to Sharing → Unix (NFS) Shares"
|
||||
echo "5. Add NFS shares for each dataset"
|
||||
echo "6. Set permissions to allow this VM's IP ($(hostname -I | awk '{print $1}'))"
|
||||
echo ""
|
||||
echo "Then run: sudo mount -a"
|
||||
|
||||
# Show mounted shares
|
||||
echo "Mounted TrueNAS shares:"
|
||||
df -h | grep truenas || echo " (check with: df -h | grep truenas)"
|
||||
|
||||
echo ""
|
||||
echo "Run this script again anytime to add missing resources!"
|
||||
|
|
|
|||
Loading…
Reference in New Issue