Reference

VMware Tools ProductLocker: shared repository and why it resets

/productLocker is a symbolic link on every ESXi host that determines the active VMware Tools repository – where the host looks for the VMware Tools ISOs it offers to guest VMs for install/upgrade. Its target is controlled by the UserVars.ProductLockerLocation advanced setting, defaulting to the local path /locker/packages/vmtoolsRepo/ on each host. Applies to any ESXi host regardless of track (VCF, VVF, or standalone vSphere) – this is a plain ESXi/vCenter setting, independent of any licensing layer.

Why point it at shared storage instead of the local default: at any real scale (tens of hosts and up), leaving every host on its own local copy means VMware Tools versions can silently drift host-to-host, and each host carries its own redundant copy of the Tools ISOs. Pointing every host’s /productLocker at the same shared datastore path centralizes the repository – one place to update, one version truth across the cluster.


Setting it – two methods

Method 1: Advanced Settings (needs a host reboot to take effect)

# Query current value across every host
Get-VMHost | Get-AdvancedSetting -Name "UserVars.ProductLockerLocation" |
  Select-Object Entity, Value

# Set it
Get-VMHost | Get-AdvancedSetting -Name "UserVars.ProductLockerLocation" |
  Set-AdvancedSetting -Confirm:$false -Value "/vmfs/volumes/<datastore>/<repo-folder>/"

Or directly on the host via esxcli (ESXi shell/SSH):

esxcli system settings advanced set -o /UserVars/ProductLockerLocation -s /vmfs/volumes/<datastore-name-or-volume-id>/<repo-folder>

Per Broadcom, this method does not check that the target directory exists or contains valid Tools files – a typo in the path silently breaks Tools install/upgrade for every VM on that host until caught. And updating the /productLocker symlink itself needs the host rebooted – setting the advanced parameter alone doesn’t relocate the live symlink until the next reboot. (Not independently lab-verified for this method specifically – Method 2 below was tested directly, and its existence-check behavior turned out to differ from what’s claimed about it, so treat the “no existence check” claim here as unconfirmed rather than assumed to also apply.)

Method 2: MOB API via PowerCLI’s ExtensionData – no reboot needed

The reboot requirement above is avoidable – calling the same host API the advanced-setting UI eventually triggers, directly, relocates the symlink immediately:

# Query, per cluster
$allhosts = Get-Cluster "<clustername>" | Get-VMHost
foreach ($esxihost in $allhosts) {
  Get-VMHost -Name $esxihost | %{ $_.ExtensionData.QueryProductLockerLocation() }
  Write-Host $esxihost -ForegroundColor Green
}

# Set, per cluster
$allhosts = Get-Cluster "<clustername>" | Get-VMHost
foreach ($esxihost in $allhosts) {
  Get-VMHost -Name $esxihost | %{ $_.ExtensionData.UpdateProductLockerLocation_Task("/vmfs/volumes/<datastore>/<repo-folder>") }
}

Lab-verified 2026-09-21 (holodeck lab, PowerCLI 13.5.1, vCenter/ESXi 9.1.1) – confirmed no reboot is needed: QueryProductLockerLocation() reflects the change immediately after the task completes. Two corrections to what secondary sources claim about this method:

  • The target folder must already exist first. Calling UpdateProductLockerLocation_Task against a path that doesn’t exist yet fails outright – the task errors with "File /vmfs/volumes/<datastore>/<folder> was not found" and the value is left unchanged. This directly contradicts the claim (repeated in a Broadcom VCF blog, cited below) that this method “does not check the existence of the directory.” Create the folder first, e.g. via PowerCLI’s datastore drive:
    $ds = Get-Datastore "<datastore>"
    New-PSDrive -Location $ds -Name repo -PSProvider VimDatastore -Root '\' | Out-Null
    New-Item -ItemType Directory -Path 'repo:\<repo-folder>' | Out-Null
    Remove-PSDrive -Name repo
  • On a vSAN datastore, the path you get back is not the path you set. Pointing it at /vmfs/volumes/<vsan-datastore-name>/<folder> and then re-querying returned an internal canonicalized path instead (observed: /vmfs/volumes/vsan:<container-uuid>/<object-uuid>) – expected behavior for vSAN’s object store, not a sign the set failed, but it means a later “does this match what I set” comparison needs to check functionally (can Tools actually be reached) rather than a literal string match against the friendly datastore-name path.

Source: Paul’s own write-up, Set ProductLocker location with PowerCLI – the base technique this method is drawn from (holds up; the folder-must-exist and vSAN-canonicalization behavior above are additions from lab testing, not corrections to that post itself).


Populating and updating the shared repository

Pointing /productLocker at a shared path (above) does nothing on its own if that path is empty – the repository’s actual contents need to be placed there first, and refreshed whenever a newer VMware Tools version ships. Per the Broadcom VCF blog and KB 313876 (both cited below):

First-time setup:

  1. Create the target folder on the shared datastore and lock it down:
    cd /vmfs/volumes/<datastore-name-or-volume-id>
    mkdir <repo-folder>
    chmod 700 <repo-folder>
  2. Download the VMware Tools package from Broadcom Support and extract it. The package contains (at minimum) a vmtools/ subfolder – isoimages_manifest.txt (+ .sig), windows.iso (+ .sha / .sig), windows_avr_manifest.txt (+ .sig), and Linux equivalents – plus a floppies/ subfolder (driver floppies, e.g. pvscsi-Windows8.flp).
  3. Copy both subfolders into the repository:
    cp -r /path-to-extracted-package/vmtools /vmfs/volumes/<datastore-name-or-volume-id>/<repo-folder>/
    cp -r /path-to-extracted-package/floppies /vmfs/volumes/<datastore-name-or-volume-id>/<repo-folder>/
  4. Re-lock permissions on everything just copied in:
    chmod -R 700 /vmfs/volumes/<datastore-name-or-volume-id>/<repo-folder>/*
  5. Point every host’s /productLocker at this folder – see Setting it – two methods above.

Updating to a newer VMware Tools version later: empty the existing folder, then repeat steps 2–4 against the same path:

rm -rf /vmfs/volumes/<datastore-name-or-volume-id>/<repo-folder>/*

No re-pointing needed on the hosts – they’re already reading from this path, so refreshing its contents updates what every host offers to guest VMs without touching /productLocker again.

Not yet lab-verified – sourced from documentation, not run end-to-end against the holodeck lab in this pass (unlike the pointer-setting methods above, which were). If run against a real environment, confirm the exact package contents/structure still match what’s described here before relying on it, and flag any discrepancy.


Why it resets – and why this needs to be a repeatable step, not a one-off

A confirmed, now-fixed bug: on ESXi 7.x, applying a patch via VUM and rebooting could truncate the configured path, corrupting it into something like /VMware-Tools/productLocker/ with each consecutive patch, showing as an invalid/inaccessible location afterward. Fixed in ESXi 7.0 Update 3f (PR 2964856) – if still seeing this exact symptom, confirm the target build is at or past that patch level.

The general, still-current reason this needs periodic re-verification: UserVars.ProductLockerLocation is a per-host advanced setting. Nothing about a normal ESXi major-version upgrade guarantees it survives – Broadcom’s own documentation doesn’t state that it’s preserved automatically across an upgrade, only how to set it. Anything that re-provisions or reimages a host from scratch (a fresh ESXi install, a stateless Auto Deploy boot, or any restore-to-default-config path) has no reason to carry a custom local advanced setting forward unless something explicitly re-applies it.

Practical takeaway for an upgrade project:

  • Re-verify the ProductLocker location as part of post-upgrade validation, the same way builds, VMware Tools versions, vSAN on-disk format, and vDS versions already get checked – see Full VCF upgrade sequence: Post-upgrade validation. Use the query snippet above per cluster/host after every ESXi upgrade, not just once at initial setup.
  • Set it via Host Profile if the environment already uses them – Host Profile remediation re-applies advanced settings on drift, which turns “did the reboot reset it” into a non-issue instead of a manual recheck.
  • If in the middle of a VUM baseline → vLCM image transition (see VUM to vLCM images migration), re-check ProductLocker after the transition completes – Broadcom’s own documentation doesn’t specifically confirm how a vLCM image switch interacts with a custom ProductLocker location, so treat it as unverified rather than assumed-safe until checked directly against the target environment.

Sources

ITQ – What's Next. VCF upgrade-planning material. © 2026 ITQ. hollebollevsan.nl