Dev Sandbox VM — Proxmox Ubuntu 24.04 with xrdp
Set up a Proxmox VM running Ubuntu 24.04 LTS cloud image with xrdp remote desktop, Android development tools, and nested virtualization. Fully automated via cloud-init with manual post-boot configuration for lightdm and Android SDK.
- Step 1
Overview
This guide documents the complete setup of a development sandbox VM on Proxmox VE using Ubuntu 24.04 LTS cloud image. The VM provides a full desktop environment via xrdp, Android development tools, and nested virtualization for running VMs inside the VM.
Key Features:
- Remote desktop access via xrdp (port 3389)
- SSH access (port 22, key + password auth)
- XFCE4 desktop environment
- Android SDK and development tools
- Nested KVM virtualization
- Automated setup via cloud-init
VM Configuration:
- VM ID: 102
- Hostname: dev-sandbox
- IP: 192.168.1.xxx (assigned by DHCP; find yours via Proxmox Summary or router)
- OS: Ubuntu 24.04 LTS (cloud image)
- User: youruser
- Memory: 8192 MB
- Cores: 4
- Step 2
Download Ubuntu Cloud Image
Download the Ubuntu 24.04 LTS cloud image to Proxmox local storage. This image is pre-configured for cloud-init and optimized for virtualization.
wget -O /var/lib/vz/template/iso/ubuntu-24.04-server-cloudimg-amd64.img \ https://cloud-images.ubuntu.com/noble/current/noble-server-cloudimg-amd64.img - Step 3
Create Cloud-Init User Data File
Create the cloud-init user data YAML file that will configure the VM on first boot. This file contains all user setup, package installation, and initial configuration.
Store the file at
/var/lib/vz/snippets/dev-sandbox-userdata.yamlon the Proxmox host.#cloud-config hostname: dev-sandbox manage_etc_hosts: true users: - name: sawyer groups: sudo, kvm, libvirt sudo: ALL=(ALL) NOPASSWD:ALL shell: /bin/bash lock_passwd: false passwd: "$5$YOURSALT$YOURHASH" # Generate with: openssl passwd -5 'yourpassword' ssh_authorized_keys: - ssh-ed25519 AAAA... your-key-comment # Replace with your public key from ~/.ssh/id_ed25519.pub chpasswd: expire: false ssh_pwauth: true package_update: true package_upgrade: true packages: - xfce4 - xfce4-goodies - xrdp - xorg - dbus-x11 - openjdk-17-jdk - git - curl - wget - unzip - zip - adb - build-essential - qemu-kvm - libvirt-daemon-system - bridge-utils - cpu-checker - htop - neofetch - firefox - qemu-guest-agent runcmd: - systemctl enable qemu-guest-agent - systemctl start qemu-guest-agent - echo xfce4-session > /home/sawyer/.xsession - chown sawyer:sawyer /home/sawyer/.xsession - systemctl enable xrdp - systemctl start xrdp - echo 'options kvm-intel nested=1' > /etc/modprobe.d/kvm-nested.conf - echo 'options kvm-amd nested=1' >> /etc/modprobe.d/kvm-nested.conf final_message: "dev-sandbox is ready. Connect via xrdp on port 3389."⚠ Heads up: When using `--cicustom user=` in Proxmox, it completely replaces the auto-generated cloud-init user config. Do NOT use `--ciuser`, `--cipassword`, or `--sshkeys` alongside it — they are silently ignored. All user setup (name, password, sudo, SSH keys, shell) must live inside the custom YAML. - Step 4
Create and Configure the VM
Run these commands on the Proxmox host as root to create the VM, import the cloud image disk, attach it, and configure cloud-init.
# Create VM qm create 102 \ --name dev-sandbox \ --memory 8192 \ --cores 4 \ --net0 virtio,bridge=vmbr0,tag=2 \ --ostype l26 \ --machine q35 \ --cpu host \ --agent enabled=1 # Import cloud image as disk qm importdisk 102 \ /var/lib/vz/template/iso/ubuntu-24.04-server-cloudimg-amd64.img \ local-lvm # Attach disk and set boot order qm set 102 \ --scsihw virtio-scsi-pci \ --scsi0 local-lvm:vm-102-disk-0 \ --ide2 local-lvm:cloudinit \ --boot order=scsi0 \ --serial0 socket \ --vga serial0 # Resize disk (30GB is sufficient; expand if needed) qm resize 102 scsi0 +28G # Attach the custom cloud-init user config # NOTE: local:snippets maps to /var/lib/vz/snippets/ qm set 102 --cicustom "user=local:snippets/dev-sandbox-userdata.yaml" # Start the VM qm start 102 - Step 5
Post-Boot: Fix lightdm Configuration
The cloud image ships with lightdm but no correct session/greeter defaults. Without this fix, xrdp logins fail with "Failed to start session".
SSH into the VM and create
/etc/lightdm/lightdm.confwith the correct session and greeter settings.# SSH into the VM ssh sawyer@192.168.1.xxx # Create lightdm configuration sudo tee /etc/lightdm/lightdm.conf > /dev/null << 'EOF' [Seat:*] user-session=xfce greeter-session=unity-greeter EOF # Restart lightdm sudo systemctl restart lightdm⚠ Heads up: The installed greeter is `unity-greeter`, not `lightdm-gtk-greeter`. Using the wrong greeter name causes the same "Failed to start session" error. - Step 6
Remote Desktop Access
Connect to the VM using any RDP client (Microsoft Remote Desktop, Remmina, etc.).
Connection Details:
- Host:
192.168.1.xxx - Port:
3389 - Username:
sawyer - Password: (configured via the passwd hash in cloud-init)
You should see the XFCE4 desktop environment after logging in.
- Host:
- Step 7
SSH Access
SSH access is available from the Proxmox host or any machine with the SSH key configured in cloud-init.
ssh sawyer@192.168.1.xxx⚠ Heads up: Password authentication is enabled (`ssh_pwauth: true`) as a fallback, but key-based authentication is recommended for security. - Step 8
Android Development Setup
After the VM is running, set up the Android SDK manually. The SDK is not included in cloud-init because it requires interactive license acceptance and the download size would slow first boot.
Download and install command-line tools:
# Download command-line tools mkdir -p ~/android-sdk/cmdline-tools cd /tmp wget https://dl.google.com/android/repository/commandlinetools-linux-11076708_latest.zip unzip commandlinetools-linux-11076708_latest.zip -d ~/android-sdk/cmdline-tools/ mv ~/android-sdk/cmdline-tools/cmdline-tools ~/android-sdk/cmdline-tools/latest # Accept licenses and install build tools export ANDROID_HOME=~/android-sdk export PATH=$PATH:$ANDROID_HOME/cmdline-tools/latest/bin:$ANDROID_HOME/platform-tools yes | sdkmanager --licenses sdkmanager "platforms;android-34" "build-tools;34.0.0" "platform-tools" - Step 9
Configure Android SDK Environment Variables
Add the Android SDK paths to your shell profile so they persist across sessions.
# Add to ~/.bashrc cat >> ~/.bashrc << 'EOF' export ANDROID_HOME=~/android-sdk export PATH=$PATH:$ANDROID_HOME/cmdline-tools/latest/bin:$ANDROID_HOME/platform-tools EOF # Reload the configuration source ~/.bashrc - Step 10
Configure Git Authentication
Set up Git with your user information and configure credential storage. This example uses a GitHub Personal Access Token (PAT) for authentication.
git config --global user.name "Your Name" git config --global user.email "your@email.com" git config --global credential.helper store # On next git push/pull, enter PAT as password — it will be cached - Step 11
Verify Nested Virtualization
Nested virtualization was enabled via cloud-init in the kernel module configuration. Verify it's working:
# Check if nested virtualization is enabled cat /sys/module/kvm_intel/parameters/nested # Expected output: Y (for Intel) or N if not enabled # Alternative check using kvm-ok kvm-ok # Expected output: KVM acceleration can be used - Step 12
Common Pitfalls and Solutions
Using
--ciuser/--cipassword/--sshkeyswith--cicustom user=- Problem: User never created, SSH auth fails
- Solution: Put everything in the YAML; drop those flags
Wrong greeter in lightdm.conf
- Problem: "Failed to start session" on RDP
- Solution: Use
unity-greeternotlightdm-gtk-greeter
Not including
chpasswd: {expire: false}- Problem: Password expired on first login
- Solution: Already included in the YAML above
Forgetting
--cicustomuseslocal:snippets/not a filesystem path- Problem:
qm seterror - Solution: Use
local:snippets/filename.yamlformat
Feature requests
Sign in to suggest features or vote on existing ones.
No feature requests yet.
Discussion
Sign in to join the discussion.
No comments yet.