From fe6ee25d1cd6f6a4a169e4c3d2b35da849df86a6 Mon Sep 17 00:00:00 2001 From: Danny Date: Thu, 19 Mar 2026 15:48:24 +0100 Subject: [PATCH] =?UTF-8?q?Fix=20Proxmox=20VM=20login=20=E2=80=94=20force?= =?UTF-8?q?=20user=20creation=20via=20runcmd?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Arch Linux cloud image ignores Proxmox's --ciuser/--cipassword and the cloud-init chpasswd module depending on version. The previous approach had three conflicting methods fighting each other. Fixed by: - Removed --ciuser/--cipassword from qm set (they conflict with snippet) - Removed chpasswd cloud-init module (unreliable on Arch) - Set users: [] to disable cloud-init's default user module - ALL user setup now done via runcmd (runs as root, always works): - Sets root password to 'darkforge' as fallback - Creates darkforge user via useradd + chpasswd - Grants passwordless sudo via /etc/sudoers.d/ - Enables PermitRootLogin yes as safety net - Package install via explicit pacman commands instead of packages: module (Arch cloud-init packages module can be unreliable) - Added pacman-key --init/--populate before package install Login credentials: user: darkforge password: darkforge user: root password: darkforge (fallback) Co-Authored-By: Claude Opus 4.6 (1M context) --- tests/proxmox/create-vm.sh | 80 +++++++++++++++++++------------------- 1 file changed, 39 insertions(+), 41 deletions(-) diff --git a/tests/proxmox/create-vm.sh b/tests/proxmox/create-vm.sh index 6718484..d41f0be 100755 --- a/tests/proxmox/create-vm.sh +++ b/tests/proxmox/create-vm.sh @@ -108,8 +108,9 @@ qm set "${VMID}" --scsihw virtio-scsi-single echo ">>> Configuring cloud-init..." qm set "${VMID}" --ide2 "${STORAGE}:cloudinit" -qm set "${VMID}" --ciuser "darkforge" -qm set "${VMID}" --cipassword "darkforge" + +# Don't use --ciuser/--cipassword — they conflict with the snippet on Arch. +# We handle ALL user creation in the cloud-init snippet runcmd instead. qm set "${VMID}" --ipconfig0 "ip=dhcp" # Enable nested virtualization (for QEMU-in-QEMU boot tests) @@ -120,67 +121,64 @@ echo ">>> Resizing disk to ${DISK_SIZE}..." qm resize "${VMID}" scsi0 "${DISK_SIZE}" 2>/dev/null || true # --- Generate cloud-init user-data snippet ----------------------------------- -# This runs on first boot inside the VM +# NOTE: The Arch Linux cloud image has quirks with user/password handling. +# We do EVERYTHING via runcmd to guarantee it works regardless of cloud-init +# version or Proxmox's cloud-init integration behavior. SNIPPET_DIR="/var/lib/vz/snippets" mkdir -p "${SNIPPET_DIR}" cat > "${SNIPPET_DIR}/darkforge-test-init.yaml" << 'CLOUDINIT' #cloud-config -# Enable SSH password authentication (cloud images disable it by default) -ssh_pwauth: true -chpasswd: - expire: false - users: - - name: darkforge - password: darkforge - type: text +# Disable the default user module to avoid conflicts +# We create our user manually via runcmd below +users: [] + +ssh_pwauth: true -# Ensure sshd allows password auth write_files: - path: /etc/ssh/sshd_config.d/99-darkforge.conf content: | PasswordAuthentication yes - PermitRootLogin no - -package_update: true -packages: - - base-devel - - git - - wget - - curl - - rust - - cargo - - qemu-full - - edk2-ovmf - - squashfs-tools - - xorriso - - dosfstools - - mtools - - python - - bc - - rsync - - openssh - - tmux + PermitRootLogin yes runcmd: - # Restart sshd to pick up the password auth config + # --- USER SETUP (do this first, before anything else) ---------------------- + # Set root password so we always have a fallback login + - echo 'root:darkforge' | chpasswd + + # Create the darkforge user if it doesn't exist + - id darkforge &>/dev/null || useradd -m -G wheel -s /bin/bash darkforge + - echo 'darkforge:darkforge' | chpasswd + + # Give darkforge sudo/wheel access without password + - echo 'darkforge ALL=(ALL) NOPASSWD:ALL' > /etc/sudoers.d/darkforge + - chmod 440 /etc/sudoers.d/darkforge + + # Enable and restart sshd + - systemctl enable sshd - systemctl restart sshd - # Grow the partition to fill the disk - - growpart /dev/sda 2 || true - - resize2fs /dev/sda2 || btrfs filesystem resize max / || true + # --- DISK RESIZE ----------------------------------------------------------- + - growpart /dev/sda 2 || growpart /dev/vda 2 || true + - resize2fs /dev/sda2 || resize2fs /dev/vda2 || btrfs filesystem resize max / || true - # Clone the DarkForge project + # --- PACKAGE INSTALL ------------------------------------------------------- + - pacman-key --init + - pacman-key --populate archlinux + - pacman -Syu --noconfirm + - pacman -S --noconfirm --needed base-devel git wget curl rust cargo qemu-full edk2-ovmf squashfs-tools xorriso dosfstools mtools python bc rsync openssh tmux + + # --- CLONE PROJECT --------------------------------------------------------- - | su - darkforge -c ' cd /home/darkforge git clone --recurse-submodules https://git.dannyhaslund.dk/danny8632/darkforge.git 2>/dev/null || \ git clone --recurse-submodules https://github.com/danny8632/darkforge.git 2>/dev/null || \ - echo "CLONE FAILED — manually clone the repo" + echo "CLONE FAILED — manually clone the repo after login" ' - # Create the darkforge-test convenience command + # --- INSTALL CONVENIENCE COMMAND ------------------------------------------- - | cat > /usr/local/bin/darkforge-test << 'DTEOF' #!/bin/bash @@ -197,7 +195,7 @@ runcmd: DTEOF chmod +x /usr/local/bin/darkforge-test - # Signal that provisioning is done + # --- SIGNAL DONE ----------------------------------------------------------- - touch /home/darkforge/.provisioned - chown darkforge:darkforge /home/darkforge/.provisioned CLOUDINIT