0

Managing PowerShellGet Repository Configurations

PowerShellGet is a PowerShell module that you probably didn’t even know you need or use because it ships with Windows. PowerShellGet is the brains behind all of the Get-Module, Find-Module, Install-Module commands which lets you manage the modules installed on your system. The provided modules are simply NuGet packages, which is a package manager for .NET. If you’re into module authoring, you probably also recognize the Publish-Module and Publish-Script commands, which let you share modules and scripts through a centralized NuGet feed.

By default there is one repository configured on your computer: The PowerShell Gallery. It’s the go to place for publicly available modules. That leads us into our next question though. What if I’m in an enterprise and I want to establish a repository of my own to share our proprietary modules? Well, you’re going to have to stand up a repository that supports NuGet feeds and then you’re going to have to configure all of your clients to use it. I’m not going to cover standing up a feed here but Kevin Marquette (@KevinMarquette) has a great post PowerShell: Using a NuGet server for a PSRepository on running Simple NuGet Server in Docker if you want to try it out. Inedo and JFrog both have commercial versions of package repositories that support NuGet if open source software won’t meet your needs. Managing system configurations is where this post comes in.

Repository configuration is a user based setting stored in an XML file in the user’s local application data folder. If I login to a computer and add a repository that’s only good for my account on that computer. So how do we add a repository to all of our systems for every user?

Method 1: Provide Scripts to Users

Yeah, no thanks. What a support nightmare that would be. I hope if you considered this method it quickly left your head. Manual configurations are time consuming and prone to error (if you even remember to do it).

Method 2: Use a Logon Script

You could write a PowerShell script and use group policy to run it at logon. The script would check if the repository was there and if it wasn’t it would add it. Not too bad. A script to do that would look something like this.

Import-Module -Name 'PowerShellGet'

if (-not (Get-PSRepository -Name 'Contoso')) {
    $repositoryParams = @{
        Name               = 'Contoso'
        SourceLocation     = 'https://psrepo.contoso.local'
        PublishLocation    = 'https://psrepo.contoso.local'
        InstallationPolicy = 'Trusted'
    }
    Register-PSRepository @repositoryParams
}

One of the things to note about this approach is that it’s only as smart as your script. The code snippet above will only check if the repository exists and if it doesn’t exist it will add it. If a user changes settings about the repository it will not change them back to your desired state. You would have to write all of that logic into the script.

Method 3: Manage the Repositories XML File

This is the method we went with as it provided most stringent enforcement of repository settings while writing the least amount of code (none). Through group policy you can manage local files on computers from a source file share. That means we can make sure everyone’s repository settings file matches a “master” file exactly. The first step to this is to setup your account with exactly what you want your repositories to look like. Once you have your repositories configured like you’d like you can use the PSRepositories.xml file located in %USERPROFILE%\AppData\Local\Microsoft\Windows\PowerShell\PowerShellGet in your group policy. I found a post by Kunal Udapi (@kunalUdapi) Copy files on all computers using group policy that gives pretty good directions on how to setup a group policy to then distribute this file to systems. Kunal’s example uses Putty, but you would follow the same steps with the PSRepositories.xml file.

Method 4: PowerShell Desired State Configuration (DSC)

If you’re already using PowerShell Desired State Configuration (DSC) to manage your servers I would encourage you to look at PowerShellGet’s PSRepository resource. A resource definition like below is equivalent to the one provided in Method 2.

Import-DscResource -ModuleName 'PowerShellGet'

PSRepository ContosoRepository
{
    Name                  = 'Contoso'
    SourceLocation        = 'https://psrepo.contoso.local/api/v2'
    PublishLocation       = 'https://psrepo.contoso.local/api/v2/package/'
    ScriptSourceLocation  = 'https://psrepo.contoso.local/api/v2/items/psscript/'
    ScriptPublishLocation = 'https://psrepo.contoso.local/api/v2/package/'
    InstallationPolicy = 'Trusted'
    Ensure             = 'Present'
}

Conclusion

Using non-PowerShell tools like Group Policy to apply logon scripts or copying the PSRepositories.xml file you can pretty seamlessly centrally manage your enterprise’s repository configurations. If your organization has already invested time and resources into DSC then you can use the PackageManagementSource resource.

If you have any comments, questions, corrections, or feedback feel free to reach out to me at @awickham on Twitter or in the comments!

Update

I originally published this article mentioning the PackageManagementRepository DSC resource. Johan Ljunggren (@ johanljunggren) reminded me that PowerShellGet has its own PSRepository DSC resource so I updated Method 4 to use it instead. Thanks Johan!

Andrew Wickham

?‍?‍?‍? Dad ?‍? PowerSheller ? SQL Server DBA ?‍♂️ Marathoner ?‍♂️ Not Drew

Leave a Reply

Your email address will not be published. Required fields are marked *