diff --git a/[core]:-cloud‐init.func.md b/[core]:-cloud‐init.func.md new file mode 100644 index 0000000..2bb1ae4 --- /dev/null +++ b/[core]:-cloud‐init.func.md @@ -0,0 +1,571 @@ +# Cloud-Init.func Wiki + +VM cloud-init configuration and first-boot setup module for Proxmox VEs, providing automatic system initialization, network configuration, user account setup, and SSH key management for virtual machines. + +--- + +## 📋 Table of Contents + +- [Overview](#overview) +- [Cloud-Init Fundamentals](#cloud-init-fundamentals) +- [Main Configuration Functions](#main-configuration-functions) +- [Interactive Configuration](#interactive-configuration) +- [Configuration Parameters](#configuration-parameters) +- [Data Formats](#data-formats) +- [Best Practices](#best-practices) +- [Troubleshooting](#troubleshooting) +- [Contributing](#contributing) + +--- + +## Overview + +Cloud-init.func provides **VM first-boot automation** infrastructure: + +- ✅ Cloud-init drive creation (IDE2 or SCSI fallback) +- ✅ User account and password configuration +- ✅ SSH public key injection +- ✅ Network configuration (DHCP or static IP) +- ✅ DNS and search domain setup +- ✅ Interactive whiptail-based configuration +- ✅ Credential file generation and display +- ✅ Support for Debian nocloud and Ubuntu cloud-init +- ✅ System package upgrade on first boot + +### Integration Pattern + +```bash +# In Proxmox VM creation scripts +source <(curl -fsSL .../cloud-init.func) + +# Basic setup: +setup_cloud_init "$VMID" "$STORAGE" "$HOSTNAME" "yes" + +# Interactive setup: +configure_cloud_init_interactive "root" +setup_cloud_init "$VMID" "$STORAGE" "$HOSTNAME" "$CLOUDINIT_ENABLE" +``` + +### First-Boot Sequence + +``` +VM Power On + ↓ +Cloud-init boot phase + ↓ +Read cloud-init config + ↓ +Create/modify user account + ↓ +Install SSH keys + ↓ +Configure network + ↓ +Set DNS/search domain + ↓ +Upgrade packages (if configured) + ↓ +Boot completion +``` + +--- + +## Cloud-Init Fundamentals + +### What is Cloud-Init? + +Cloud-init is a system that runs on the first boot of a VM/Instance to: +- Create user accounts +- Set passwords +- Configure networking +- Install SSH keys +- Run custom scripts +- Manage system configuration + +### Proxmox Cloud-Init Integration + +Proxmox VE supports cloud-init natively via: +- **Cloud-init drive**: IDE2 or SCSI disk with cloud-init data +- **QEMU parameters**: User, password, SSH keys, IP configuration +- **First-boot services**: systemd services that execute on first boot + +### Nocloud Data Source + +Proxmox uses the **nocloud** data source (no internet required): +- Configuration stored on local cloud-init drive +- No external network call needed +- Works in isolated networks +- Suitable for private infrastructure + +--- + +## Main Configuration Functions + +### `setup_cloud_init()` + +**Purpose**: Configures Cloud-init for automatic VM first-boot setup. + +**Signature**: +```bash +setup_cloud_init() +``` + +**Parameters**: +- `$1` - VMID (required, e.g., 100) +- `$2` - Storage name (required, e.g., local, local-lvm) +- `$3` - Hostname (optional, default: vm-${VMID}) +- `$4` - Enable Cloud-Init (yes/no, default: no) +- `$5` - User (optional, default: root) +- `$6` - Network mode (dhcp/static, default: dhcp) +- `$7` - Static IP (optional, CIDR format: 192.168.1.100/24) +- `$8` - Gateway (optional) +- `$9` - Nameservers (optional, space-separated, default: 1.1.1.1 8.8.8.8) + +**Returns**: 0 on success, 1 on failure; exits if not enabled + +**Behavior**: +```bash +# If enable="no": +# Returns immediately (skips all configuration) + +# If enable="yes": +# 1. Create cloud-init drive (IDE2, fallback to SCSI1) +# 2. Set user account +# 3. Generate random password +# 4. Configure network +# 5. Set DNS servers +# 6. Add SSH keys (if available) +# 7. Save credentials to file +# 8. Export variables for calling script +``` + +**Operations**: + +| Operation | Command | Purpose | +|-----------|---------|---------| +| Create drive | `qm set $vmid --ide2 $storage:cloudinit` | Cloud-init data disk | +| Set user | `qm set $vmid --ciuser $ciuser` | Initial user | +| Set password | `qm set $vmid --cipassword $cipassword` | Auto-generated | +| SSH keys | `qm set $vmid --sshkeys $SSH_KEYS_FILE` | Pre-injected | +| DHCP network | `qm set $vmid --ipconfig0 ip=dhcp` | Dynamic IP | +| Static network | `qm set $vmid --ipconfig0 ip=192.168.1.100/24,gw=192.168.1.1` | Fixed IP | +| DNS | `qm set $vmid --nameserver $servers` | 1.1.1.1 8.8.8.8 | +| Search domain | `qm set $vmid --searchdomain local` | Local domain | + +**Environment Variables Set**: +- `CLOUDINIT_USER` - Username configured +- `CLOUDINIT_PASSWORD` - Generated password (in memory only) +- `CLOUDINIT_CRED_FILE` - Path to credentials file + +**Usage Examples**: + +```bash +# Example 1: Basic DHCP setup +VMID=100 +STORAGE="local-lvm" +setup_cloud_init "$VMID" "$STORAGE" "myvm" "yes" +# Result: VM configured with DHCP, random password, root user + +# Example 2: Static IP configuration +setup_cloud_init "$VMID" "$STORAGE" "myvm" "yes" "root" \ + "static" "192.168.1.100/24" "192.168.1.1" "1.1.1.1 8.8.8.8" +# Result: VM configured with static IP, specific DNS + +# Example 3: Disabled (no cloud-init) +setup_cloud_init "$VMID" "$STORAGE" "myvm" "no" +# Result: Function returns immediately, no configuration +``` + +--- + +### `configure_cloud_init_interactive()` + +**Purpose**: Interactive whiptail-based configuration prompts for user preferences. + +**Signature**: +```bash +configure_cloud_init_interactive() +``` + +**Parameters**: +- `$1` - Default user (optional, default: root) + +**Returns**: 0 on success, 1 if whiptail unavailable; exports configuration variables + +**Environment Variables Exported**: +- `CLOUDINIT_ENABLE` - Enable (yes/no) +- `CLOUDINIT_USER` - Username +- `CLOUDINIT_NETWORK_MODE` - dhcp or static +- `CLOUDINIT_IP` - Static IP (if static mode) +- `CLOUDINIT_GW` - Gateway (if static mode) +- `CLOUDINIT_DNS` - DNS servers (space-separated) + +**User Prompts** (5 questions): +1. **Enable Cloud-Init?** (yes/no) +2. **Username?** (default: root) +3. **Network Mode?** (DHCP or static) +4. **Static IP?** (if static, CIDR format) +5. **Gateway IP?** (if static) +6. **DNS Servers?** (default: 1.1.1.1 8.8.8.8) + +**Fallback Behavior**: +- If whiptail unavailable: Shows warning and returns 1 +- Auto-defaults to DHCP if error occurs +- Non-interactive: Can be skipped in scripts + +**Implementation Pattern**: +```bash +configure_cloud_init_interactive() { + local default_user="${1:-root}" + + # Check whiptail availability + if ! command -v whiptail >/dev/null 2>&1; then + echo "Warning: whiptail not available" + export CLOUDINIT_ENABLE="no" + return 1 + fi + + # Ask enable + if ! (whiptail --backtitle "Proxmox VE Helper Scripts" --title "CLOUD-INIT" \ + --yesno "Enable Cloud-Init for VM configuration?" 16 68); then + export CLOUDINIT_ENABLE="no" + return 0 + fi + + export CLOUDINIT_ENABLE="yes" + + # Username + CLOUDINIT_USER=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox \ + "Cloud-Init Username" 8 58 "$default_user" --title "USERNAME" 3>&1 1>&2 2>&3) + export CLOUDINIT_USER="${CLOUDINIT_USER:-$default_user}" + + # Network mode + if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "NETWORK MODE" \ + --yesno "Use DHCP for network configuration?" 10 58); then + export CLOUDINIT_NETWORK_MODE="dhcp" + else + export CLOUDINIT_NETWORK_MODE="static" + # ... prompt for static IP and gateway ... + fi + + # DNS servers + CLOUDINIT_DNS=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox \ + "DNS Servers (space-separated)" 8 58 "1.1.1.1 8.8.8.8" --title "DNS" 3>&1 1>&2 2>&3) + export CLOUDINIT_DNS +} +``` + +**Usage Examples**: + +```bash +# Example 1: Interactive configuration +configure_cloud_init_interactive "root" +# Prompts user for all settings interactively +# Exports variables for use in setup_cloud_init() + +# Example 2: With custom default user +configure_cloud_init_interactive "debian" +# Suggests "debian" as default username + +# Example 3: In script workflow +configure_cloud_init_interactive "$DEFAULT_USER" +setup_cloud_init "$VMID" "$STORAGE" "$HOSTNAME" "$CLOUDINIT_ENABLE" "$CLOUDINIT_USER" +# User configures interactively, then script sets up VM +``` + +--- + +## Configuration Parameters + +### VMID (Virtual Machine ID) + +- **Type**: Integer (100-2147483647) +- **Required**: Yes +- **Example**: `100` +- **Validation**: Must be unique, >= 100 on Proxmox + +### Storage + +- **Type**: String (storage backend name) +- **Required**: Yes +- **Examples**: `local`, `local-lvm`, `ceph-rbd` +- **Validation**: Must exist in Proxmox +- **Cloud-init Drive**: Placed on this storage + +### Hostname + +- **Type**: String (valid hostname) +- **Required**: No (defaults to vm-${VMID}) +- **Example**: `myvm`, `web-server-01` +- **Format**: Lowercase, alphanumeric, hyphens allowed + +### User + +- **Type**: String (username) +- **Required**: No (defaults: root) +- **Example**: `root`, `ubuntu`, `debian` +- **Cloud-init**: User account created on first boot + +### Network Mode + +- **Type**: Enum (dhcp, static) +- **Default**: dhcp +- **Options**: + - `dhcp` - Dynamic IP from DHCP server + - `static` - Manual IP configuration + +### Static IP + +- **Format**: CIDR notation (192.168.1.100/24) +- **Example**: `192.168.1.50/24`, `10.0.0.5/8` +- **Validation**: Valid IP and netmask +- **Required**: If network mode = static + +### Gateway + +- **Format**: IP address (192.168.1.1) +- **Example**: `192.168.1.1`, `10.0.0.1` +- **Validation**: Valid IP +- **Required**: If network mode = static + +### Nameservers + +- **Format**: Space-separated IPs +- **Default**: `1.1.1.1 8.8.8.8` +- **Example**: `1.1.1.1 8.8.8.8 9.9.9.9` + +### DNS Search Domain + +- **Type**: String +- **Default**: `local` +- **Example**: `example.com`, `internal.corp` + +--- + +## Data Formats + +### Cloud-Init Credentials File + +Generated at: `/tmp/${hostname}-${vmid}-cloud-init-credentials.txt` + +**Format**: +``` +======================================== +Cloud-Init Credentials +======================================== +VM ID: 100 +Hostname: myvm +Created: Tue Dec 01 10:30:00 UTC 2024 + +Username: root +Password: s7k9mL2pQ8wX + +Network: dhcp +DNS: 1.1.1.1 8.8.8.8 + +======================================== +SSH Access (if keys configured): +ssh root@ + +Proxmox UI Configuration: +VM 100 > Cloud-Init > Edit +- User, Password, SSH Keys +- Network (IP Config) +- DNS, Search Domain +======================================== +``` + +### Proxmox Cloud-Init Config + +Stored in: `/etc/pve/nodes//qemu-server/.conf` + +**Relevant Settings**: +``` +ide2: local-lvm:vm-100-cloudinit,media=cdrom +ciuser: root +cipassword: (encrypted) +ipconfig0: ip=dhcp +nameserver: 1.1.1.1 8.8.8.8 +searchdomain: local +``` + +### Network Configuration Examples + +**DHCP**: +```bash +qm set 100 --ipconfig0 "ip=dhcp" +``` + +**Static IPv4**: +```bash +qm set 100 --ipconfig0 "ip=192.168.1.100/24,gw=192.168.1.1" +``` + +**Static IPv6**: +```bash +qm set 100 --ipconfig0 "ip6=2001:db8::100/64,gw6=2001:db8::1" +``` + +**Dual Stack (IPv4 + IPv6)**: +```bash +qm set 100 --ipconfig0 "ip=192.168.1.100/24,gw=192.168.1.1,ip6=2001:db8::100/64,gw6=2001:db8::1" +``` + +--- + +## Best Practices + +### 1. **Always Configure SSH Keys** + +```bash +# Ensure SSH keys available before cloud-init setup +CLOUDINIT_SSH_KEYS="/root/.ssh/authorized_keys" + +if [ ! -f "$CLOUDINIT_SSH_KEYS" ]; then + mkdir -p /root/.ssh + # Generate or import SSH keys +fi + +setup_cloud_init "$VMID" "$STORAGE" "$HOSTNAME" "yes" +``` + +### 2. **Save Credentials Securely** + +```bash +# After setup_cloud_init(): +# Credentials file generated at $CLOUDINIT_CRED_FILE + +# Copy to secure location: +cp "$CLOUDINIT_CRED_FILE" "/root/vm-credentials/" +chmod 600 "/root/vm-credentials/$(basename $CLOUDINIT_CRED_FILE)" + +# Or display to user: +cat "$CLOUDINIT_CRED_FILE" +``` + +### 3. **Use Static IPs for Production** + +```bash +# DHCP - suitable for dev/test +setup_cloud_init "$VMID" "$STORAGE" "$HOSTNAME" "yes" "root" "dhcp" + +# Static - suitable for production +setup_cloud_init "$VMID" "$STORAGE" "$HOSTNAME" "yes" "root" \ + "static" "192.168.1.100/24" "192.168.1.1" +``` + +### 4. **Validate Network Configuration** + +```bash +# Before setting up cloud-init, ensure: +# - Gateway IP is reachable +# - IP address not in use +# - DNS servers are accessible + +ping -c 1 "$GATEWAY" || msg_error "Gateway unreachable" +``` + +### 5. **Test First Boot** + +```bash +# After cloud-init setup: +qm start "$VMID" + +# Wait for boot +sleep 10 + +# Check cloud-init status +qm exec "$VMID" cloud-init status + +# Verify network configuration +qm exec "$VMID" hostname -I +``` + +--- + +## Troubleshooting + +### Cloud-Init Not Applying + +```bash +# Inside VM: +cloud-init status # Show cloud-init status +cloud-init analyze # Analyze cloud-init boot +cloud-init query # Query cloud-init datasource + +# Check logs: +tail -100 /var/log/cloud-init-output.log +tail -100 /var/log/cloud-init.log +``` + +### Network Not Configured + +```bash +# Verify cloud-init config in Proxmox: +cat /etc/pve/nodes/$(hostname)/qemu-server/100.conf + +# Check cloud-init drive: +qm config 100 | grep ide2 + +# In VM, verify cloud-init wrote config: +cat /etc/netplan/99-cloudinit.yaml +``` + +### SSH Keys Not Installed + +```bash +# Verify SSH keys set in Proxmox: +qm config 100 | grep sshkeys + +# In VM, check SSH directory: +ls -la /root/.ssh/ +cat /root/.ssh/authorized_keys +``` + +### Password Not Set + +```bash +# Regenerate cloud-init drive: +qm set 100 --delete ide2 # Remove cloud-init drive +qm set 100 --ide2 local-lvm:vm-100-cloudinit,media=cdrom # Re-create + +# Set password again: +qm set 100 --cipassword "newpassword" +``` + +--- + +## Contributing + +### Adding New Configuration Options + +1. Add parameter to `setup_cloud_init()` function signature +2. Add validation for parameter +3. Add `qm set` command to apply configuration +4. Update documentation with examples +5. Test on actual Proxmox VE + +### Enhancing Interactive Configuration + +1. Add new whiptail dialog to `configure_cloud_init_interactive()` +2. Export variable for use in setup +3. Add validation logic +4. Test with various input scenarios + +### Supporting New Data Sources + +Beyond nocloud, could support: +- ConfigDrive (cloud-init standard) +- ESXi (if supporting vSphere) +- Hyper-V (if supporting Windows) + +--- + +## Notes + +- Cloud-init requires **QEMU guest agent** for optimal functionality +- Network configuration applied **on first boot only** +- Credentials file contains **sensitive information** - keep secure +- SSH keys are **persisted** and not displayed in credentials file +- Cloud-init is **optional** - VMs work without it +