Chocolatey as an Enterprise Package Manager

Chocolatey is a Windows package manager built on NuGet infrastructure that automates software installation, upgrades, and removal across Windows environments. In an enterprise context, Chocolatey eliminates manual installer downloads, enables scripted builds, and provides an internal package feed that mirrors or replaces the public Chocolatey community repository. Windows Server 2022 is a common deployment target for Chocolatey because it is used as a build server, CI/CD agent, developer workstation base image, and general-purpose infrastructure node. This guide covers everything from initial installation through managing an internal feed with automated upgrades.

Installing Chocolatey

The official installation method uses a PowerShell one-liner that downloads and runs the install script from Chocolatey’s CDN. Run this in an elevated PowerShell session:

Set-ExecutionPolicy Bypass -Scope Process -Force
[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072
Invoke-Expression ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1'))

After installation, verify and check the version:

choco --version
# 2.3.0

For air-gapped or enterprise environments, download the Chocolatey NuGet package (chocolatey.x.y.z.nupkg) from the website on a connected machine, transfer it to the target server, and install offline:

# Set CHOCOLATEY_VERSION and path accordingly
$env:ChocolateyInstall = 'C:ProgramDatachocolatey'
$nupkg = 'C:Tempchocolatey.2.3.0.nupkg'
$zip = [System.IO.Path]::ChangeExtension($nupkg, '.zip')
Copy-Item $nupkg $zip
Expand-Archive $zip -DestinationPath "$env:ChocolateyInstall" -Force
& "$env:ChocolateyInstalltoolschocolateyInstall.ps1"

Core Chocolatey Configuration

The choco config command manages Chocolatey’s configuration file (C:ProgramDatachocolateyconfigchocolatey.config). Key settings for automated deployments:

# Do not ask for confirmation on installs/upgrades
choco config set --name="allowGlobalConfirmation" --value="true"

# Cache downloaded packages locally for offline installs
choco config set --name="cacheLocation" --value="C:ChocolateyCache"

# Timeout for downloads in seconds (default is 2700)
choco config set --name="commandExecutionTimeoutSeconds" --value="3600"

# Proxy settings for environments requiring an HTTP proxy
choco config set --name="proxy" --value="http://proxy.example.com:8080"
choco config set --name="proxyUser" --value="DOMAINProxyUser"
choco config set --name="proxyPassword" --value="ProxyPassword"

# Show current config
choco config list

Installing Packages Unattended

The -y flag confirms all prompts, making installation fully non-interactive. The --no-progress flag suppresses the progress bar output, which is useful in CI logs:

# Install a single package
choco install git -y --no-progress

# Install multiple packages at once
choco install git googlechrome vscode 7zip notepadplusplus -y --no-progress

# Install a specific version
choco install dotnet-8.0-sdk --version=8.0.301 -y

# Install from a params string (package-specific switches)
choco install visualstudio2022buildtools -y `
    --package-parameters "--add Microsoft.VisualStudio.Workload.MSBuildTools --passive --norestart"

Upgrade all installed packages in one command — ideal for a scheduled maintenance task:

choco upgrade all -y --no-progress

Creating Internal Chocolatey Packages

The choco new command scaffolds a package from a template. Navigate to your packages working directory and generate a package skeleton:

mkdir C:ChocoPkgs
cd C:ChocoPkgs
choco new mycompany-agent --version=1.0.0 --maintainername="Ops Team" --maintainerrepo="https://gitea.example.com"

This creates a directory mycompany-agent with a mycompany-agent.nuspec and a tools folder. Edit the NuSpec file to describe your package:



  
    mycompany-agent
    1.0.0
    MyCompany Agent
    Ops Team
    Installs the MyCompany monitoring agent.
    mycompany agent monitoring
    Initial package release.
  

Place the installer binary in the tools folder and write the installation script in toolschocolateyInstall.ps1:

$ErrorActionPreference = 'Stop'
$packageDir = Split-Path -Parent $MyInvocation.MyCommand.Definition

$packageArgs = @{
    packageName    = 'mycompany-agent'
    fileType       = 'exe'
    file           = Join-Path $packageDir 'MyCompanyAgentSetup.exe'
    silentArgs     = '/S /NORESTART'
    validExitCodes = @(0, 3010)
}

Install-ChocolateyInstallPackage @packageArgs

Add an uninstall script at toolschocolateyUninstall.ps1:

$ErrorActionPreference = 'Stop'

$uninstallPath = (Get-ItemProperty `
    "HKLM:SoftwareMicrosoftWindowsCurrentVersionUninstallMyCompanyAgent" `
    -ErrorAction SilentlyContinue).UninstallString

if ($uninstallPath) {
    Start-Process -FilePath $uninstallPath -ArgumentList "/S" -Wait
    Write-Host "MyCompany Agent uninstalled."
} else {
    Write-Warning "Uninstall path not found in registry."
}

Building and Publishing Packages

Run choco pack in the package directory to create a .nupkg file:

cd C:ChocoPkgsmycompany-agent
choco pack
# Created: mycompany-agent.1.0.0.nupkg (1.23 MB)

Push the package to an internal feed (see Hosting an Internal Feed below):

choco push mycompany-agent.1.0.0.nupkg --source="http://nexus.example.com/repository/choco-internal/" `
    --api-key="YOUR_NEXUS_API_KEY"

Hosting an Internal Chocolatey Feed with Nexus

Sonatype Nexus Repository Manager OSS is one of the most common choices for hosting an internal NuGet/Chocolatey feed. Once Nexus is installed and running, create a NuGet hosted repository from the Nexus UI, then add it as a Chocolatey source on your Windows servers:

# Remove the default public Chocolatey source for production machines
choco source remove --name="chocolatey"

# Add the internal Nexus feed
choco source add --name="internal" `
    --source="http://nexus.example.com/repository/choco-internal/index.json" `
    --user="choco-reader" --password="ReaderPassword" --priority=1

# Verify sources
choco source list

Alternatively, Chocolatey.Server is a simpler ASP.NET-based NuGet server that ships as a Chocolatey package itself:

choco install chocolatey.server -y
# Follow post-install instructions to configure IIS and the API key

Automated Upgrades via Scheduled Tasks

Schedule nightly upgrades across all managed servers using a PowerShell script triggered by Windows Task Scheduler:

# upgrade-all.ps1
$logFile = "C:Logschoco-upgrade-$(Get-Date -Format 'yyyyMMdd').log"
Start-Transcript -Path $logFile -Append

try {
    Write-Host "Starting Chocolatey upgrade at $(Get-Date)"
    choco upgrade all -y --no-progress --source="internal" 2>&1
    Write-Host "Upgrade complete at $(Get-Date)"
}
catch {
    Write-Error "Chocolatey upgrade failed: $_"
    exit 1
}
finally {
    Stop-Transcript
}

# Register the scheduled task
$action = New-ScheduledTaskAction `
    -Execute "powershell.exe" `
    -Argument "-NonInteractive -ExecutionPolicy Bypass -File C:Scriptsupgrade-all.ps1"
$trigger = New-ScheduledTaskTrigger -Daily -At "03:00AM"
$principal = New-ScheduledTaskPrincipal -UserId "SYSTEM" -RunLevel Highest
$settings = New-ScheduledTaskSettingsSet -StartWhenAvailable -ExecutionTimeLimit (New-TimeSpan -Hours 2)
Register-ScheduledTask -TaskName "Chocolatey Upgrade All" `
    -Action $action -Trigger $trigger -Principal $principal -Settings $settings -Force

Chocolatey in Group Policy and Enterprise Deployment

For large fleets, Chocolatey can be deployed via Group Policy using a startup script that installs Chocolatey and then installs a baseline set of packages on first boot. Create a GPO startup script at the computer level:

# bootstrap.ps1 — runs at machine startup via GPO
# Only run if Chocolatey is not already installed
if (-not (Get-Command choco -ErrorAction SilentlyContinue)) {
    Set-ExecutionPolicy Bypass -Scope Process -Force
    [Net.ServicePointManager]::SecurityProtocol = [Net.ServicePointManager]::SecurityProtocol -bor 3072
    Invoke-Expression ((New-Object Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1'))

    # Configure internal source
    choco source remove --name="chocolatey"
    choco source add --name="internal" `
        --source="http://nexus.example.com/repository/choco-internal/index.json" --priority=1

    # Install baseline software
    choco install git googlechrome 7zip notepadplusplus vscode -y --no-progress --source="internal"
    Write-Host "Chocolatey bootstrap complete."
}

Deploy this script via: Computer Configuration > Windows Settings > Scripts > Startup in Group Policy Management Console.

Chocolatey Central Management

Chocolatey Central Management (CCM) is a licensed feature that provides a web-based dashboard for monitoring package versions, compliance status, and scheduling upgrades across all managed machines. After purchasing a Chocolatey for Business license, install CCM on a dedicated server:

# On the CCM server
choco install chocolatey-management-database -y --params="/ConnectionString='Server=localhost;Database=ChocolateyCentral;Integrated Security=SSPI;'"
choco install chocolatey-management-service -y
choco install chocolatey-management-web -y

# On each managed machine, install the CCM agent
choco install chocolatey-agent -y
choco config set --name="centralManagementServiceUrl" --value="https://ccm.example.com:24020/ChocolateyManagementService"
choco feature enable --name="useChocolateyCentralManagement"
choco feature enable --name="useChocolateyCentralManagementDeployments"

Once agents are reporting, the CCM web UI allows you to create deployment plans targeting specific machines or groups, approve package updates before they roll out, and view an organization-wide compliance report showing which machines are running outdated package versions.