#!/bin/bash ############################################################################### # Layer 1B: Nodito (Proxmox) Setup # # This script configures the Nodito Proxmox server. # Runs independently - can be executed without VPS setup. ############################################################################### set -e # Exit on error # Colors for output RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' # No Color # Project root directory SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" ANSIBLE_DIR="$PROJECT_ROOT/ansible" ############################################################################### # Helper Functions ############################################################################### print_header() { echo -e "\n${BLUE}========================================${NC}" echo -e "${BLUE}$1${NC}" echo -e "${BLUE}========================================${NC}\n" } print_success() { echo -e "${GREEN}✓${NC} $1" } print_error() { echo -e "${RED}✗${NC} $1" } print_warning() { echo -e "${YELLOW}⚠${NC} $1" } print_info() { echo -e "${BLUE}ℹ${NC} $1" } confirm_action() { local prompt="$1" local response read -p "$(echo -e ${YELLOW}${prompt}${NC} [y/N]: )" response [[ "$response" =~ ^[Yy]$ ]] } ############################################################################### # Verification Functions ############################################################################### check_layer_0_complete() { print_header "Verifying Layer 0 Prerequisites" local errors=0 # Check if venv exists if [ ! -d "$PROJECT_ROOT/venv" ]; then print_error "Python venv not found. Run Layer 0 first." ((errors++)) else print_success "Python venv exists" fi # Check if we're in a venv if [ -z "$VIRTUAL_ENV" ]; then print_error "Virtual environment not activated" echo "Run: source venv/bin/activate" ((errors++)) else print_success "Virtual environment activated" fi # Check if Ansible is installed if ! command -v ansible &> /dev/null; then print_error "Ansible not found" ((errors++)) else print_success "Ansible found: $(ansible --version | head -n1)" fi # Check if inventory.ini exists if [ ! -f "$ANSIBLE_DIR/inventory.ini" ]; then print_error "inventory.ini not found" ((errors++)) else print_success "inventory.ini exists" fi if [ $errors -gt 0 ]; then print_error "Layer 0 is not complete. Please run ./scripts/setup_layer_0.sh first" exit 1 fi print_success "Layer 0 prerequisites verified" } get_hosts_from_inventory() { local group="$1" cd "$ANSIBLE_DIR" ansible-inventory -i inventory.ini --list | \ python3 -c "import sys, json; data=json.load(sys.stdin); print(' '.join(data.get('$group', {}).get('hosts', [])))" 2>/dev/null || echo "" } check_nodito_configured() { print_header "Checking Nodito Configuration" local nodito_hosts=$(get_hosts_from_inventory "nodito") if [ -z "$nodito_hosts" ]; then print_error "No nodito host configured in inventory.ini" print_info "Add nodito to [nodito] group in inventory.ini to proceed" exit 1 fi print_success "Nodito configured: $nodito_hosts" echo "" } ############################################################################### # Nodito Setup Functions ############################################################################### setup_nodito_bootstrap() { print_header "Bootstrapping Nodito (Proxmox Server)" cd "$ANSIBLE_DIR" print_info "This will:" echo " • Set up SSH key access for root" echo " • Create the counterweight user with SSH keys" echo " • Update and secure the system" echo " • Disable root login and password authentication" echo "" print_info "Running: ansible-playbook -i inventory.ini infra/nodito/30_proxmox_bootstrap_playbook.yml" print_warning "You will be prompted for the root password" echo "" if ! confirm_action "Proceed with nodito bootstrap?"; then print_warning "Skipped nodito bootstrap" return 1 fi # Run with root user and ask for password if ansible-playbook -i inventory.ini infra/nodito/30_proxmox_bootstrap_playbook.yml -e 'ansible_user=root' --ask-pass; then print_success "Nodito bootstrap complete" return 0 else print_error "Nodito bootstrap failed" return 1 fi } setup_nodito_community_repos() { print_header "Switching Nodito to Community Repositories" cd "$ANSIBLE_DIR" print_info "This will:" echo " • Remove enterprise repository files" echo " • Add community repository files" echo " • Disable subscription nag messages" echo " • Update Proxmox packages" echo "" print_info "Running: ansible-playbook -i inventory.ini infra/nodito/31_proxmox_community_repos_playbook.yml" echo "" if ! confirm_action "Proceed with community repos setup?"; then print_warning "Skipped community repos setup" return 1 fi if ansible-playbook -i inventory.ini infra/nodito/31_proxmox_community_repos_playbook.yml; then print_success "Community repositories configured" print_warning "Clear browser cache before using Proxmox web UI (Ctrl+Shift+R)" return 0 else print_error "Community repos setup failed" return 1 fi } setup_nodito_zfs() { print_header "Setting Up ZFS Storage Pool on Nodito (Optional)" cd "$ANSIBLE_DIR" print_warning "⚠️ ZFS setup will DESTROY ALL DATA on the specified disks!" echo "" print_info "Before proceeding, you must:" echo " 1. SSH into nodito: ssh root@" echo " 2. List disks: ls -la /dev/disk/by-id/ | grep -E '(ata-|scsi-|nvme-)'" echo " 3. Identify the two disk IDs you want to use for RAID 1" echo " 4. Edit ansible/infra/nodito/nodito_vars.yml" echo " 5. Set zfs_disk_1 and zfs_disk_2 to your disk IDs" echo "" print_info "Example nodito_vars.yml content:" echo ' zfs_disk_1: "/dev/disk/by-id/ata-WDC_WD40EFRX-68N32N0_WD-WCC7K1234567"' echo ' zfs_disk_2: "/dev/disk/by-id/ata-WDC_WD40EFRX-68N32N0_WD-WCC7K7654321"' echo "" if [ ! -f "$ANSIBLE_DIR/infra/nodito/nodito_vars.yml" ]; then print_warning "nodito_vars.yml not found" if confirm_action "Create nodito_vars.yml template?"; then cat > "$ANSIBLE_DIR/infra/nodito/nodito_vars.yml" << 'EOF' # Nodito Variables # Configure these before running ZFS setup # ZFS Storage Pool Configuration # Uncomment and configure these lines after identifying your disk IDs: # zfs_disk_1: "/dev/disk/by-id/ata-YOUR-DISK-1-ID-HERE" # zfs_disk_2: "/dev/disk/by-id/ata-YOUR-DISK-2-ID-HERE" # zfs_pool_name: "proxmox-storage" # CPU Temperature Monitoring monitoring_script_dir: /opt/cpu-temp-monitor monitoring_script_path: "{{ monitoring_script_dir }}/cpu_temp_monitor.sh" log_file: "{{ monitoring_script_dir }}/cpu_temp_monitor.log" temp_threshold_celsius: 80 EOF print_success "Created nodito_vars.yml template" print_info "Edit this file and configure ZFS disks, then re-run this script" fi return 1 fi # Check if ZFS disks are configured if ! grep -q "^zfs_disk_1:" "$ANSIBLE_DIR/infra/nodito/nodito_vars.yml" 2>/dev/null; then print_info "ZFS disks not configured in nodito_vars.yml" print_info "Edit ansible/infra/nodito/nodito_vars.yml to configure disk IDs" if ! confirm_action "Skip ZFS setup for now?"; then print_info "Please configure ZFS disks first" return 1 fi print_warning "Skipped ZFS setup" return 1 fi print_info "Running: ansible-playbook -i inventory.ini infra/nodito/32_zfs_pool_setup_playbook.yml" echo "" if ! confirm_action "⚠️ Proceed with ZFS setup? (THIS WILL DESTROY DATA ON CONFIGURED DISKS)"; then print_warning "Skipped ZFS setup" return 1 fi if ansible-playbook -i inventory.ini infra/nodito/32_zfs_pool_setup_playbook.yml; then print_success "ZFS storage pool configured" return 0 else print_error "ZFS setup failed" return 1 fi } setup_nodito_cloud_template() { print_header "Creating Debian Cloud Template on Nodito (Optional)" cd "$ANSIBLE_DIR" print_info "This will:" echo " • Download Debian cloud image" echo " • Create a VM template (ID 9000)" echo " • Configure cloud-init for easy VM creation" echo "" print_info "Running: ansible-playbook -i inventory.ini infra/nodito/33_proxmox_debian_cloud_template.yml" echo "" if ! confirm_action "Proceed with cloud template creation?"; then print_warning "Skipped cloud template creation" return 1 fi if ansible-playbook -i inventory.ini infra/nodito/33_proxmox_debian_cloud_template.yml; then print_success "Debian cloud template created (VM ID 9000)" return 0 else print_error "Cloud template creation failed" return 1 fi } ############################################################################### # Verification Functions ############################################################################### verify_layer_1b() { print_header "Verifying Layer 1B Completion" cd "$ANSIBLE_DIR" local ssh_key=$(grep "ansible_ssh_private_key_file" "$ANSIBLE_DIR/inventory.ini" | head -n1 | sed 's/.*ansible_ssh_private_key_file=\([^ ]*\).*/\1/') ssh_key="${ssh_key/#\~/$HOME}" local nodito_hosts=$(get_hosts_from_inventory "nodito") print_info "Testing SSH as counterweight user..." echo "" for host in $nodito_hosts; do if timeout 10 ssh -i "$ssh_key" -o StrictHostKeyChecking=no -o BatchMode=yes counterweight@$host "echo 'SSH OK'" &>/dev/null; then print_success "SSH to $host as counterweight: OK" else print_error "Cannot SSH to $host as counterweight" print_info "Test manually: ssh -i $ssh_key counterweight@$host" fi done echo "" } ############################################################################### # Summary Functions ############################################################################### print_summary() { print_header "Layer 1B: Nodito Setup Complete! 🎉" echo "Summary of what was configured:" echo "" print_success "Nodito bootstrapped with SSH keys" print_success "counterweight user created" print_success "Community repositories configured" print_success "Root login and password auth disabled" if grep -q "^zfs_disk_1:" "$ANSIBLE_DIR/infra/nodito/nodito_vars.yml" 2>/dev/null; then print_success "ZFS storage pool configured (if you ran it)" fi echo "" print_warning "Important Security Changes:" echo " • Root SSH login is now disabled" echo " • Always use 'counterweight' user for SSH access" echo " • Password authentication is disabled" echo "" print_info "Proxmox Web UI:" local nodito_hosts=$(get_hosts_from_inventory "nodito") echo " • Access at: https://$nodito_hosts:8006" echo " • Clear browser cache (Ctrl+Shift+R) to avoid UI issues" echo "" print_info "Next steps:" echo " 1. Test SSH: ssh -i ~/.ssh/counterganzua counterweight@" echo " 2. Access Proxmox web UI and verify community repos" echo " 3. Create VMs on Proxmox (if needed)" echo " 4. Proceed to Layer 2: ./scripts/setup_layer_2.sh" echo "" } ############################################################################### # Main Execution ############################################################################### main() { clear print_header "🖥️ Layer 1B: Nodito (Proxmox) Setup" echo "This script will configure your Nodito Proxmox server." echo "" print_info "Target: nodito (Proxmox server)" echo "" if ! confirm_action "Continue with Layer 1B setup?"; then echo "Setup cancelled." exit 0 fi check_layer_0_complete check_nodito_configured # Nodito Setup local setup_failed=false setup_nodito_bootstrap || setup_failed=true setup_nodito_community_repos || setup_failed=true setup_nodito_zfs || setup_failed=true setup_nodito_cloud_template || setup_failed=true verify_layer_1b if [ "$setup_failed" = true ]; then print_warning "Some optional steps were skipped - this is normal" fi print_summary } # Run main function main "$@"