6.9 KiB
App Deployer VM
Deploy LXC applications inside a full Virtual Machine instead of an LXC container.
Overview
The App Deployer VM bridges the gap between CT install scripts (install/*.sh) and VM infrastructure. It leverages the existing install scripts — originally designed for LXC containers — and runs them inside a full VM via a first-boot systemd service.
Supported Operating Systems
| OS | Version | Codename | Cloud-Init |
|---|---|---|---|
| Debian | 13 | Trixie | Optional |
| Debian | 12 | Bookworm | Optional |
| Ubuntu | 24.04 LTS | Noble | Required |
| Ubuntu | 22.04 LTS | Jammy | Required |
Usage
Create a new App VM (interactive)
bash -c "$(curl -fsSL https://git.community-scripts.org/community-scripts/ProxmoxVED/raw/branch/main/vm/app-deployer-vm.sh)"
Pre-select application
APP_SELECT=yamtrack bash -c "$(curl -fsSL https://git.community-scripts.org/community-scripts/ProxmoxVED/raw/branch/main/vm/app-deployer-vm.sh)"
Update the application later (inside the VM)
bash /opt/community-scripts/update-app.sh
How It Works
Installation Flow
┌─────────────────────────────────────┐
│ Proxmox Host │
│ │
│ 1. Select app (e.g. Yamtrack) │
│ 2. Select OS (e.g. Debian 13) │
│ 3. Configure VM resources │
│ 4. Download cloud image │
│ 5. virt-customize: │
│ - Install base packages │
│ - Inject install.func │
│ - Inject tools.func │
│ - Inject install script │
│ - Create first-boot service │
│ - Inject update mechanism │
│ 6. Create VM (qm create) │
│ 7. Import customized disk │
│ 8. Start VM │
└────────────┬────────────────────────┘
│ First Boot
┌────────────▼────────────────────────┐
│ VM (Debian/Ubuntu) │
│ │
│ app-install.service (oneshot): │
│ 1. Wait for network │
│ 2. Set environment variables │
│ (FUNCTIONS_FILE_PATH, etc.) │
│ 3. Run install/<app>-install.sh │
│ 4. Mark as installed │
│ │
│ → Application running in VM! │
└─────────────────────────────────────┘
Update Flow
┌─────────────────────────────────────┐
│ Inside the VM (SSH or console) │
│ │
│ bash /opt/community-scripts/ │
│ update-app.sh │
│ │
│ → Downloads ct/<app>.sh │
│ → start() detects no pveversion │
│ → Shows update/settings menu │
│ → Runs update_script() │
└─────────────────────────────────────┘
The update mechanism reuses the existing CT script logic. Since pveversion is not available inside the VM, the start() function automatically enters the update/settings mode — the same path it takes inside LXC containers.
Architecture
Files
| File | Purpose |
|---|---|
vm/app-deployer-vm.sh |
Main user-facing script |
misc/vm-app.func |
Core library for VM app deployment |
misc/vm-core.func |
Shared VM functions (colors, spinner, etc.) |
misc/cloud-init.func |
Cloud-Init configuration (optional) |
Key Design Decisions
-
Install scripts run unmodified — The same
install/*.shscripts that work in LXC containers work inside VMs. The environment (FUNCTIONS_FILE_PATH, exports) is replicated identically. -
Image customization via
virt-customize— All files are injected into the qcow2 image before the VM boots. No SSH or guest agent required during setup. -
First-boot systemd service — The install script runs automatically on first boot. Progress can be monitored via
/var/log/app-install.log. -
Update via CT script — The existing CT script's
start()→update_script()flow works in VMs without modification.
Environment Variables (set during first-boot)
| Variable | Description |
|---|---|
FUNCTIONS_FILE_PATH |
Full contents of install.func |
APPLICATION |
App display name (e.g. "Yamtrack") |
app |
App identifier (e.g. "yamtrack") |
VERBOSE |
"no" (silent mode) |
SSH_ROOT |
"yes" |
PCT_OSTYPE |
OS type (debian/ubuntu) |
PCT_OSVERSION |
OS version (12/13/22.04/24.04) |
COMMUNITY_SCRIPTS_URL |
Repository base URL |
DEPLOY_TARGET |
"vm" (distinguishes from LXC) |
VM Directory Structure
/opt/community-scripts/
├── install.func # Function library
├── tools.func # Helper functions
├── install/
│ └── <app>-install.sh # Application install script
├── ct/
│ └── (downloaded on update) # CT script for updates
└── update-app.sh # Update wrapper script
Limitations
- Alpine-based apps: Currently only Debian/Ubuntu VMs are supported. Alpine install scripts are not compatible.
- LXC-specific features: Some CT features (FUSE, TUN, GPU passthrough) are configured differently in VMs.
- First-boot timing: The app installation happens after the VM boots, so the application is not immediately available (monitor
/var/log/app-install.log). cleanup_lxc: This function works fine in VMs (it only cleans package caches), but the name is LXC-centric.
Troubleshooting
Check installation progress
# From inside the VM
tail -f /var/log/app-install.log
# From the Proxmox host (via guest agent)
qm guest exec <VMID> -- cat /var/log/app-install.log
Re-run installation
# Remove the installed marker and reboot
rm /root/.app-installed
systemctl start app-install.service
Check if installation completed
test -f /root/.app-installed && echo "Installed" || echo "Not yet installed"