The Problem
Provisioning a macOS VM on Proxmox 9 requires manual OpenCore plist edits, GenSMBIOS runs, and a series of qm commands. Even a seasoned admin can spend 3–6 hours correcting a single flag, and the process must be repeated for every new VM or hardware change.
What This Does
osx-proxmox-next replaces the manual workflow with a six‑step TUI wizard that runs on the Proxmox host. The wizard auto‑detects CPU type, RAM, and storage, downloads the appropriate OpenCore and recovery images, generates a unique SMBIOS, and builds a dry‑run plan that can be inspected before execution.
Key implementation pieces:
- CLI entry point –
src/osx_proxmox_next/cli.py(_dispatch_simple_commands,_validate_and_fetch_assets). - Application core –
src/osx_proxmox_next/app.py(run,_go_next,_preflight_worker). - Domain model –
src/osx_proxmox_next/domain.pydefinesVmConfig,PlanStep, and validation helpers used by 19 other modules. - Planner & executor –
src/osx_proxmox_next/planner.pybuilds the step list;src/osx_proxmox_next/executor.pyapplies it via the Proxmox CLI wrappers insrc/osx_proxmox_next/infrastructure.py.
The repository also ships a static documentation site (docs/ built with React/TypeScript) and a handful of helper shell scripts in scripts/ for profile toggling and demo recording.
How It Is Wired
Execution begins in src/osx_proxmox_next/app.py:run (line 401). run creates a NextApp instance and hands control to the Textual UI loop. The UI drives _go_next, which sequentially invokes the planner (build_plan → PlanStep objects) and then the executor (apply_plan).
- Core call hub –
src/osx_proxmox_next/domain.pyis imported by 19 modules; changes here have the widest blast radius. - Circular dependencies –
src/osx_proxmox_next/services/__init__.py,defaults.py, androllback.pyform a 14‑node import cycle, increasing maintenance risk. - Filesystem impact – 68 functions read/write files, e.g.,
downloader.download_recoverywrites the recovered DMG,infrastructure.run_commandinvokessubprocess.runto executeqm,pvesm, andpvesh. - Network impact –
downloader._fetch_github_releasesperforms outbound HTTP calls to fetch OpenCore assets. - External commands –
infrastructure.run_commandruns the Proxmox CLI;executor.apply_planultimately calls these wrappers for eachqmoperation.
The internal call graph shows _run (called from 137 places) as the most fan‑out function, followed by _cfg (75) and run_cli (70). These functions are the primary mutation points; any refactor should start there to limit ripple effects.
How To Use It
# Clone the repo
git clone https://github.com/moses-y/osx-proxmox-next
cd osx-proxmox-next
# Install Python dependencies (pyproject.toml)
pip install . # or: pip install -e . for editable dev install
# Optional: build the docs site (requires npm)
cd docs
npm ci # respects the committed package-lock.json
npm run build # generates static site under docs/build
# Run the wizard (requires root on the Proxmox host)
python -m osx_proxmox_next.app # launches the TUI
# Or invoke the CLI directly
python -m osx_proxmox_next.cli --help
Configuration is supplied via CLI flags (e.g., --iso-dir for shared storage) and environment variables are not required. The wizard persists no secret material; the only external I/O is the downloaded OpenCore assets and the generated VM definition files.
Real‑World Use
A CI pipeline that provisions a temporary macOS VM for automated UI tests could call:
python -m osx_proxmox_next.cli create \
--os sonoma \
--cpu auto \
--ram 8G \
--storage local-lvm \
--dry-run json > plan.json
python -m osx_proxmox_next.cli apply --plan plan.json
The dry‑run JSON can be version‑controlled, enabling reproducible VM builds across test environments.
Code Health & Issues
- HIGH – No LICENSE – repository root lacks a license file; redistribution rights are undefined.
- HIGH – Missing Python lockfile –
pyproject.tomlhas no accompanying lockfile; transitive dependencies are not pinned. - HIGH – CI steps discard exit codes (
.github/workflows/release.ymlline 30). Failures are hidden, risking stale artifacts. - HIGH – Direct push to
mainin CI – release workflow pushes straight to the default branch, bypassing PR review. - MEDIUM – GitHub token permissions –
.github/workflows/test.ymldeclares nopermissions:block, granting broader access than needed. - MEDIUM – No Dependabot/Renovate – repository lacks automated dependency updates.
- MEDIUM – npm install instead of npm ci – CI reinstalls without lockfile enforcement, allowing version drift.
- MEDIUM – No dependency‑vulnerability scan – CI does not run a vulnerability review action.
- MEDIUM – Checkout persists credentials –
.github/workflows/docs.ymldoes not setpersist-credentials: false. - LOW – No job timeouts – CI jobs lack
timeout-minutes, risking runaway runs.
Additional static findings: 14 import cycles, 2 unguarded file opens, duplicated shell script blocks, deep nesting (max depth 7), and several oversized files (>1 800 lines). These increase cognitive load and maintenance cost.
The Bottom Line
osx-proxmox-next delivers a functional, well‑documented wizard that reduces macOS VM provisioning from hours to minutes and integrates cleanly with Proxmox CLI tooling. The codebase is functional but suffers from architectural smells (import cycles, large hub modules) and several high‑severity process issues (missing license, unlocked dependencies, CI practices). It is suitable for teams that need rapid VM setup and are prepared to address the identified health concerns before using it in production‑critical pipelines.