#!/usr/bin/env bash # Set root password on all LXC containers # Usage: ./set-container-passwords.sh [password] # If no password provided, will prompt for one set -euo pipefail # Load IP configuration SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" source "${PROJECT_ROOT}/config/ip-addresses.conf" 2>/dev/null || true SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" PROXMOX_HOST="${PROXMOX_HOST:-192.168.11.10}" # Colors for output RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' NC='\033[0m' # No Color # Function to print colored output info() { echo -e "${GREEN}[INFO]${NC} $1"; } warn() { echo -e "${YELLOW}[WARN]${NC} $1"; } error() { echo -e "${RED}[ERROR]${NC} $1"; } # Get password if [[ $# -eq 1 ]]; then if [[ "$1" == "--generate" ]] || [[ "$1" == "-g" ]]; then # Generate secure password PASSWORD=$(openssl rand -base64 24 | tr -d "=+/" | cut -c1-20) info "Generated secure password: $PASSWORD" info "⚠️ SAVE THIS PASSWORD - it will not be shown again!" echo "" # Skip prompt if running non-interactively if [[ -t 0 ]]; then read -p "Press Enter to continue or Ctrl+C to cancel..." echo "" fi else PASSWORD="$1" fi else echo "Enter root password for all LXC containers (or press Enter to generate one):" read -s PASSWORD echo "" if [[ -z "$PASSWORD" ]]; then # Generate secure password PASSWORD=$(openssl rand -base64 24 | tr -d "=+/" | cut -c1-20) info "Generated secure password: $PASSWORD" info "⚠️ SAVE THIS PASSWORD - it will not be shown again!" echo "" read -p "Press Enter to continue or Ctrl+C to cancel..." echo "" else echo "Confirm password:" read -s PASSWORD_CONFIRM echo "" if [[ "$PASSWORD" != "$PASSWORD_CONFIRM" ]]; then error "Passwords do not match!" exit 1 fi fi if [[ ${#PASSWORD} -lt 8 ]]; then error "Password must be at least 8 characters long!" exit 1 fi fi info "Setting root password on LXC containers (VMID 1000+)..." info "Proxmox Host: $PROXMOX_HOST" echo "" # Get list of all LXC containers ALL_CONTAINERS=$(ssh -o ConnectTimeout=5 -o StrictHostKeyChecking=no root@${PROXMOX_HOST} \ "pct list | tail -n +2 | awk '{print \$1}'" 2>/dev/null) if [[ -z "$ALL_CONTAINERS" ]]; then error "Failed to get container list from Proxmox host" exit 1 fi # Filter to only containers >= 1000 CONTAINERS="" for vmid in $ALL_CONTAINERS; do if [[ $vmid -ge 1000 ]]; then CONTAINERS="$CONTAINERS $vmid" fi done CONTAINERS=$(echo $CONTAINERS | xargs) # Trim whitespace if [[ -z "$CONTAINERS" ]]; then error "No containers found with VMID >= 1000" exit 1 fi # Count containers CONTAINER_COUNT=$(echo "$CONTAINERS" | wc -w) info "Found $CONTAINER_COUNT containers (VMID 1000+) to update" echo "" # Track results SUCCESS=0 FAILED=0 SKIPPED=0 # Set password on each container for vmid in $CONTAINERS; do # Filter: only process containers with VMID >= 1000 if [[ $vmid -lt 1000 ]]; then continue fi # Check if container is running STATUS=$(ssh -o ConnectTimeout=5 -o StrictHostKeyChecking=no root@${PROXMOX_HOST} \ "pct status $vmid 2>/dev/null | awk '{print \$2}'" 2>/dev/null || echo "unknown") if [[ "$STATUS" != "running" ]]; then warn "VMID $vmid: Container not running (status: $STATUS), skipping..." SKIPPED=$((SKIPPED + 1)) continue fi # Get container hostname for display HOSTNAME=$(ssh -o ConnectTimeout=5 -o StrictHostKeyChecking=no root@${PROXMOX_HOST} \ "pct exec $vmid -- hostname 2>/dev/null" || echo "unknown") echo -n "VMID $vmid ($HOSTNAME): " # Set password using chpasswd RESULT=$(ssh -o ConnectTimeout=5 -o StrictHostKeyChecking=no root@${PROXMOX_HOST} \ "pct exec $vmid -- chpasswd <<< \"root:${PASSWORD}\" 2>&1" 2>&1) EXIT_CODE=$? if [[ $EXIT_CODE -eq 0 ]]; then echo -e "${GREEN}✓ Password set${NC}" SUCCESS=$((SUCCESS + 1)) else echo -e "${RED}✗ Failed${NC}" if [[ -n "$RESULT" ]]; then echo " Error: $RESULT" fi FAILED=$((FAILED + 1)) fi done echo "" echo "==========================================" info "Summary:" echo " Success: $SUCCESS" echo " Failed: $FAILED" echo " Skipped: $SKIPPED" echo " Total: $CONTAINER_COUNT" echo "==========================================" if [[ $FAILED -gt 0 ]]; then exit 1 fi