homelab infrastructure services
at fix-docker-install 332 lines 11 kB view raw
1#!/bin/bash 2 3# Service-specific NFS mount for tinsnip services 4# Implements DEPLOYMENT_STRATEGY.md conventions 5 6set -euo pipefail 7 8# Required parameters 9TIN_SERVICE_NAME="${1:-}" 10TIN_SERVICE_ENVIRONMENT="${2:-}" 11NAS_SERVER="${3:-}" 12 13# Get script directory and source lib 14SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" 15source "$SCRIPT_DIR/lib.sh" 16 17log() { 18 echo "[NFS Mount] $*" 19} 20 21error() { 22 log "ERROR: $*" >&2 23 exit 1 24} 25 26usage() { 27 echo "Usage: $0 <service_name> <service_env> <nas_server>" 28 echo " service_name: tinsnip, gazette, etc." 29 echo " service_env: prod, test" 30 echo " nas_server: NAS hostname or IP" 31 echo "" 32 echo "Example: $0 tinsnip test DS412plus" 33 exit 1 34} 35 36# calculate_service_uid is now provided by lib.sh 37 38 39install_nfs_dependencies() { 40 log "Installing NFS dependencies..." 41 42 if sudo apt-get update -qq >/dev/null 2>&1; then 43 log " Package lists updated" 44 else 45 error "Failed to update package lists" 46 fi 47 48 if sudo apt-get install -y nfs-common >/dev/null 2>&1; then 49 log " NFS utilities installed" 50 else 51 error "Failed to install NFS dependencies" 52 fi 53} 54 55create_service_user() { 56 local service_user="$1" 57 local service_uid="$2" 58 59 if ! id "$service_user" &>/dev/null; then 60 log "Creating service user: $service_user (UID: $service_uid)" 61 sudo useradd -u "$service_uid" -s /bin/bash -m "$service_user" 62 else 63 log "Service user $service_user already exists" 64 fi 65} 66 67show_nfs_setup_instructions() { 68 local service_name="$1" 69 local service_env="$2" 70 local nas_server="$3" 71 local namespace="$4" 72 local service_uid="$5" 73 74 local nfs_export="/volume1/${namespace}/${service_name}/${service_env}" 75 local client_host=$(hostname -f 2>/dev/null || hostname) 76 77 echo 78 echo "============================================================" 79 echo "NFS EXPORT SETUP REQUIRED" 80 echo "============================================================" 81 echo 82 echo "Before mounting, you need to configure NFS exports on your NAS." 83 echo "SSH into your NAS ($nas_server) and run these commands:" 84 echo 85 echo "# 1. Create directory and set ownership" 86 echo "sudo mkdir -p $nfs_export" 87 echo "sudo chown ${service_uid}:${service_uid} $nfs_export" 88 echo 89 echo "# 2. Add this line to /etc/exports (use TAB between path and options):" 90 echo "${nfs_export} ${client_host}(rw,async,no_subtree_check,all_squash,anonuid=${service_uid},anongid=${service_uid})" 91 echo 92 echo "# 3. Reload NFS exports" 93 echo "sudo exportfs -ra" 94 echo "sudo exportfs -v # Verify export is active" 95 echo 96 echo "============================================================" 97 echo 98 99 # Wait for user confirmation 100 while true; do 101 read -p "Have you completed the NFS export setup on $nas_server? (y/n): " confirm 102 case $confirm in 103 [Yy]* ) 104 log "Proceeding with NFS mount..." 105 break 106 ;; 107 [Nn]* ) 108 echo "Please complete the NFS export setup before continuing." 109 echo "You can also use: ./machine/scripts/generate_nfs_exports.sh $service_name $service_env $namespace $client_host" 110 ;; 111 * ) 112 echo "Please answer yes or no." 113 ;; 114 esac 115 done 116} 117 118mount_nfs_share() { 119 local service_name="$1" 120 local service_env="$2" 121 local nas_server="$3" 122 local mount_point="/mnt/${service_name}-${service_env}" 123 124 local namespace 125 namespace=$(get_namespace) 126 local nfs_export="/volume1/${namespace}/${service_name}/${service_env}" 127 128 # Calculate service UID for NFS setup instructions 129 local service_uid 130 service_uid=$(calculate_service_uid "$service_name" "$service_env") 131 132 log "Mounting NFS:" 133 log " Export: ${nas_server}:${nfs_export}" 134 log " Mount: ${mount_point}" 135 136 # Create mount point 137 sudo mkdir -p "$mount_point" 138 139 # Unmount if already mounted 140 if mountpoint -q "$mount_point" 2>/dev/null; then 141 log " Unmounting old $mount_point first" 142 sudo umount "$mount_point" 143 fi 144 145 # Mount NFS share 146 if ! sudo mount -t nfs "${nas_server}:${nfs_export}" "$mount_point"; then 147 echo 148 echo "❌ NFS mount failed!" 149 echo "Common issues:" 150 echo "1. NFS export not configured correctly on NAS" 151 echo "2. Wrong hostname/IP for NAS server" 152 echo "3. Directory doesn't exist or has wrong ownership on NAS" 153 echo "4. Firewall blocking NFS traffic (ports 111, 2049)" 154 echo "5. NFS service not running on NAS" 155 echo 156 echo "To troubleshoot:" 157 echo "1. Verify export exists: ssh $nas_server sudo exportfs -v" 158 echo "2. Test basic NFS: sudo mount -t nfs $nas_server:/volume1 /tmp/test" 159 echo "3. Check NAS logs for errors" 160 echo 161 error "Cannot mount NFS export ${nas_server}:${nfs_export}" 162 fi 163 164 # Verify mount 165 if ! mountpoint -q "$mount_point"; then 166 error "Mount point verification failed" 167 fi 168 169 log " NFS mount successful" 170} 171 172get_namespace() { 173 # Use namespace from environment, file, or default 174 if [[ -n "${TIN_NAMESPACE:-}" ]]; then 175 echo "$TIN_NAMESPACE" 176 elif [[ -f "/etc/tinsnip-namespace" ]]; then 177 cat "/etc/tinsnip-namespace" 178 else 179 echo "dynamicalsystem" 180 fi 181} 182 183# Check if NFS export exists and is accessible 184check_nfs_exists() { 185 local nas_server="$1" 186 local nfs_export="$2" 187 188 # First try using showmount if available 189 if command -v showmount >/dev/null 2>&1; then 190 if showmount -e "$nas_server" 2>/dev/null | grep -q "^${nfs_export}[[:space:]]"; then 191 log "NFS export found via showmount" 192 return 0 193 fi 194 fi 195 196 # Try temporary mount to check NFS export 197 local temp_mount="/tmp/nfs-check-$$" 198 mkdir -p "$temp_mount" 199 200 # Increased timeout and retries for better detection 201 if sudo mount -t nfs -o ro,soft,timeo=10,retry=3 "${nas_server}:${nfs_export}" "$temp_mount" 2>/dev/null; then 202 sudo umount "$temp_mount" 2>/dev/null || true 203 rmdir "$temp_mount" 2>/dev/null || true 204 return 0 # NFS export exists and is accessible 205 else 206 # Log why it failed for debugging 207 log " ❌ Mount test failed: ${nas_server}:${nfs_export}" 208 rmdir "$temp_mount" 2>/dev/null || true 209 return 1 # NFS export doesn't exist or can't mount 210 fi 211} 212 213# Guide user through NFS export creation using generate_nfs_exports.sh 214guide_nfs_export_creation() { 215 local service_name="$1" 216 local service_env="$2" 217 local nas_server="$3" 218 local namespace 219 namespace=$(get_namespace) 220 221 log " 📝 Generating $service_name-$service_env NFS export instructions..." 222 223 # Use generate_nfs_exports.sh to show exact commands needed 224 if ! NAS_HOST="$nas_server" "$SCRIPT_DIR/generate_nfs_exports.sh" "$service_name" "$service_env" "$namespace" "$(hostname)"; then 225 error "Failed to generate NFS export instructions" 226 fi 227 228 echo 229 log "Press Enter when you've completed the NFS export setup:" 230 read -p " $nas_server..." 231 232 # Build NFS export path for verification 233 local nfs_export="/volume1/${namespace}/${service_name}/${service_env}" 234 235 # Verify it's now accessible 236 if ! check_nfs_exists "$nas_server" "$nfs_export"; then 237 error "NFS export still not accessible: ${nas_server}:${nfs_export}. Please verify the setup." 238 fi 239 240 log "NFS export verified successfully" 241} 242 243# Set up service environment with NFS .env file and shell integration 244setup_service_environment() { 245 local service_name="$1" 246 local service_env="$2" 247 local service_uid="$3" 248 local service_user="${service_name}-${service_env}" 249 local mount_point="/mnt/${service_name}-${service_env}" 250 251 log "Setting up service environment for $service_user" 252 253 # Create the directories on the NFS mount 254 sudo -u "$service_user" mkdir -p "$mount_point"/{data,config,state,cache} 255 256 # Create service .env file on NFS mount (source of truth) 257 create_service_env_file "$service_name" "$service_env" "$service_uid" 258 259 # Update shell configs to load from NFS .env with cache fallback 260 local env_loader_code 261 env_loader_code=$(generate_service_env_loader) 262 263 sudo -u "$service_user" -i bash << 'SETUP_EOF' 264# Clear any existing environment loading code (more comprehensive cleanup) 265for config_file in ~/.bashrc ~/.profile; do 266 if [[ -f "$config_file" ]]; then 267 # Remove all tinsnip-related environment code 268 grep -v -E "(Tinsnip service environment|SERVICE_ENV_FILE|TIN_SERVICE_ENV_CACHE|XDG_.*_HOME.*=|export XDG_)" "$config_file" > "${config_file}.tmp" 2>/dev/null && mv "${config_file}.tmp" "$config_file" || touch "$config_file" 269 else 270 touch "$config_file" 271 fi 272done 273SETUP_EOF 274 275 # Add environment loading code to both files using printf 276 printf '%s\n' "$env_loader_code" | sudo -u "$service_user" tee -a /home/"$service_user"/.bashrc > /dev/null 277 printf '%s\n' "$env_loader_code" | sudo -u "$service_user" tee -a /home/"$service_user"/.profile > /dev/null 278 279 log "Service environment configured:" 280 log " Primary: $mount_point/.env" 281 log " Cache: \$XDG_CACHE_HOME/tinsnip/$service_user.env" 282 log " Shell integration: .bashrc and .profile updated" 283} 284 285main() { 286 # Validate parameters 287 if [[ -z "$TIN_SERVICE_NAME" || -z "$TIN_SERVICE_ENVIRONMENT" || -z "$NAS_SERVER" ]]; then 288 usage 289 fi 290 291 # Calculate service UID using convention 292 TIN_SERVICE_UID=$(calculate_service_uid "$TIN_SERVICE_NAME" "$TIN_SERVICE_ENVIRONMENT") 293 SERVICE_USER="${TIN_SERVICE_NAME}-${TIN_SERVICE_ENVIRONMENT}" 294 295 log "Setting up NFS mount:" 296 log " Service: $TIN_SERVICE_NAME" 297 log " Environment: $TIN_SERVICE_ENVIRONMENT" 298 log " Service user: $SERVICE_USER (UID: $TIN_SERVICE_UID)" 299 log " NAS server: $NAS_SERVER" 300 301 # Install dependencies 302 install_nfs_dependencies 303 304 # Create service user with calculated UID 305 create_service_user "$SERVICE_USER" "$TIN_SERVICE_UID" 306 307 # Check if NFS export exists, guide creation if needed 308 local namespace 309 namespace=$(get_namespace) 310 local nfs_export="/volume1/${namespace}/${TIN_SERVICE_NAME}/${TIN_SERVICE_ENVIRONMENT}" 311 312 log "Checking NFS export..." 313 if ! check_nfs_exists "$NAS_SERVER" "$nfs_export"; then 314 log "${NAS_SERVER}:${nfs_export}" 315 log "NFS export not found, guiding setup..." 316 guide_nfs_export_creation "$TIN_SERVICE_NAME" "$TIN_SERVICE_ENVIRONMENT" "$NAS_SERVER" 317 else 318 log " ${NAS_SERVER}:${nfs_export}" 319 fi 320 321 # Mount the NFS share 322 mount_nfs_share "$TIN_SERVICE_NAME" "$TIN_SERVICE_ENVIRONMENT" "$NAS_SERVER" 323 324 # Set up service environment (.env file and shell integration) 325 setup_service_environment "$TIN_SERVICE_NAME" "$TIN_SERVICE_ENVIRONMENT" "$TIN_SERVICE_UID" 326 327 log "NFS mount setup complete!" 328 log "Mount point: /mnt/${TIN_SERVICE_NAME}-${TIN_SERVICE_ENVIRONMENT}" 329 log "Service user: $SERVICE_USER" 330} 331 332main "$@"