How To Setup a Private Powershell Repository

In this blog post, I will walk through the process of setting up a private Powershell repository using Azure DevOps Nuget Feed. After this tutorial, you will be able to upload and download your Powershell modules and scripts from the repository over the internet securely.

Everybody who is just a bit familiar with Powershell knows the PowerShell Gallery. This is the main repository hosted by Microsoft, from which you can download thousands of different packages such as Powershell modules and scripts. You can also publish your code to the Powershell Gallery for anyone to download and use. The only problem with this is if your code is proprietary for your environment, or if for some reason you don’t want anyone outside of your company to have access to your code, then it might not be the best idea to upload it to the Powershell Gallery.

Now you could just create a shared folder to store your scripts and modules in, and although this is a viable solution, you can do it a bit more professionally, and by creating a Nuget Feed in Azure DevOps, you won’t have to bother with NTF permissions.

Setting up a Nuget Feed in Azure Devops

The first thing you will need to do is create an account on Azure DevOps if don’t already have one. You can do this by heading over to the site [dev.azure.com](https://dev.azure.com) and click on “Start free” Then login with a Microsoft Account.

Once you have created an account you will need to create a project and inside this project, you will need to create a new Repository. If you are having trouble doing this I would highly suggest you go through the [Microsoft Docs](https://docs.microsoft.com/en-us/learn/modules/get-started-with-devops/) It is a quick tutorial of Azure DevOps and will quickly learn you have to navigate around.

Now once you have created your repository you can go ahead and create your Nuget Feed.

On the left side of the screen you should see the menu Artifacts, go ahead and click on it.

Inside the Artifacts menu, you should see that a name as your Azure DevOps Organization has already been created. It is perfectly fine to use this Nuget Feed as your Powershell repository, but for the sake of the tutorial, I will go ahead and create a new feed.

1. Start by clicking on “+ Create Feed”

2. Give the feed a new name

3. Select you can have access to the feed. In this case, i have chosen people who are members of my Azure DevOps Organization

4. Make sure that “Include packages from common public sources have been selected”

5. At the end chose the scope of this feed. Unless you develop Powershell modules in another project which should be published to this feed, then just select the “Project” and not the Organization.

You should now see the feed you just created

Adding Azure DevOps Nuget Feed as Powershell Repository

Now that you have created a Nuget Feed in Azure DevOps you will be able to connect the feed as a Powershell repository.

Creating a Personal Access Token

First, you will need a PAT(Personal Access Token). To get this, click on the small user icon with a gear, just to the right of your user profile icon, in the upper right corner. Then click on “Personal Access Token”

Now click on “New Token”

To create the Token you will be prompted for which Scopes the token should have access to. This acts as the permissions for what you will be able to do with the access token. Now I strongly recommend for a production environment you should go through all the scopes to be sure that the access token only has access to the needed permissions. The best way to figuring out which scopes the token should have access to is just to try and see what works.

For this tutorial and testing purposes, I will select “Full Access”

Once the token is created you will receive the option for copying the Token. You need to do this and save it somewhere safe, preferably in a Password Mager or a Vault of some sort. If you somehow don’t manage to save the token, you can always delete the newly created token and regenerate a new token

Registering The Powershell Repository

Before you can register the Powershell repository on your local machine you will need the name of the NuGet Feed and you will need the source location. The source location is the URL defining your Nuget Feed.

To find the URL of your feed, go to Artifacts and be sure to select the right Nuget Feed. Then click on “Connect to feed”

Click on “NuGet.exe”

Then you should be provided with a URL under the “Project setup”. You should look for the value of the key named your Nuget Feed.

You now need to modify the URL a bit before Powershell will accept it.

The URL might look a bit different depending on if you created a new feed or you used the already created organization feed.

The URL should be built like this:

https:// pkgs.dev.azure.com/ <organization name> / <project name> /_packaging/ <nuget feed name> /nuget/v3/index.json

You will need to remove the following from the URL “v3/index.json” and then add “v2” instead.

The complete should look similar to this:

https://pkgs.dev.azure.com/scriptingchris/PowerShell-Modules/_packaging/awesome-private-modules/nuget/v2

Now to register the Nuget Feed as a PowerShell Repository in your Powershell terminal, you can create the following variables containing your Personal Access Token, The Nuget Feed URL, and the name of your Nuget Feed

$AzureDevopsPAT = <personal access token>

$SourceURL = "<nuget feed url>"

$RepoName = "<nuget feed name>"

Then to register the PSRepository you can use the Powershell cmdlet Register-PSRepository like shown below

$password = ConvertTo-SecureString -String $($AzureDevopsPAT) -AsPlainText -Force
$credential = New-Object System.Management.Automation.PSCredential ('PSRepo', $password)

$params = @{
	Name                      = $RepoName
	SourceLocation            = $SourceURL
	PublishLocation           = $SourceURL
	InstallationPolicy        = 'Trusted'
	Credential                = $Credential
}

Register-PSRepository @params

Once you have run the command, you can check if registering the repository worked by running the command Get-PSRepository and see if your new repository is shown.

Uploading to your private Powershell Repository

Uploading to your new Private module is fairly easy although you do need to have some prerequisites done before you can upload your module.

First of all, you will need to have a module manifest for your module and you will need to have the following parameters set in your module manifest:

– RootModule

– ModuleVersion –> should be set as 0.0.0 instead of 0.0

– Author

– Description

You can see my module manifest below

# Script module or binary module file associated with this manifest.
RootModule = 'SCPSMeraki.psm1'

# Version number of this module.
ModuleVersion = '0.30.16'

# ID used to uniquely identify this module
GUID = '1be9db23-a239-4ed6-8b53-a7efe394cbb2'

# Author of this module
Author = 'Christian Hojesager'

# Company or vendor of this module
CompanyName = 'ScriptingChris'

# Copyright statement for this module
Copyright = '(c) ScriptingChris. All rights reserved.'

# Description of the functionality provided by this module
Description = 'Module for administrating Cisco Meraki Network equipment'

# Minimum version of the PowerShell engine required by this module
PowerShellVersion = '5.1'

I also always make sure to export the desired functions from my .psm1 file, inside the module manifest

# Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export.
FunctionsToExport = 'Get-SCMrkAppliancePort', 'Get-SCMrkAppliancePorts', 
               'Get-SCMrkClient', 'Get-SCMrkDevice', 'Get-SCMrkDeviceClients', 
               'Get-SCMrkDeviceMgtInterface', 'Get-SCMrkFirewalledService', 
               'Get-SCMrkFirewalledServices', 'Get-SCMrkL3FirewallRules', 
               'Get-SCMrkNetworkDevices', 'Get-SCMrkNetworks', 
               'Get-SCMrkNetworkSNMP', 'Get-SCMrkNetworkVlans', 
               'Get-SCMrkSiteToSiteVPN', 'Get-SCMrkSwitchPort', 
               'Get-SCMrkSwitchPorts', 'Get-SCMrkVlan', 'Get-SCMrkVlans', 
               'New-SCMrkVlan', 'Set-SCMrkAppliancePort', 'Set-SCMrkAuth', 
               'Set-SCMrkDeviceMgtInterface', 'Set-SCMrkFirewalledService', 
               'Set-SCMrkL3FirewallRule', 'Set-SCMrkNetworkSNMP', 
               'Set-SCMrkSiteToSiteVPN', 'Set-SCMrkSwitchPort'

The second important thing is that you will need to have your module and manifest inside of a correct folder structure.

– Your root folder should have the exact name of your module.

– Then inside the root folder I store the module manifest (.psd1) file, and the module (.psm1) file.

C:.
└───SCPSMeraki
	SCPSMeraki.psd1
	SCPSMeraki.psm1

If you have these prerequisites in place you can use the cmdlet Publish-Module to upload your module to your new private repository

Publish-Module -Path ".\SCPSMeraki\" -Repository $RepoName -NuGetApiKey $AzureDevopsPAT -Credential $credential

The first time you run the command you will be prompted to install NuGet.exe. You will need to select (y) to install the application

Possible errors when publishing Powershell modules to a repository

  • The first time you run the command Publish-Module you might get the following error
Publish-PSArtifactUtility : Failed to publish module '<modulename>': 'Cannot prompt for input in non-interactive mode.'

To resolve the error you will need to update the module PowerShellGet. You can do this by running the following command

Install-Module PowerShellGet -AllowClobber -Force
  • Another error you might experience when running the command Publish-Module is:
Publish-PSArtifactUtility : Failed to publish module '<modulename>': 'nuget.exe failed to push Response status code does not indicate success: 401 (Unauthorized).'

This error usually occurs when the Nuget client installed by PowerShellGet does not have the right credentials, and therefore will not have access to publish modules to your Azure DevOps Nuget feed.

To mitigate this error you will need to do the following:

1. Start by adding nuget.exe to your path

You do this by opening your advanced systems settings and clicking on “Environment Variables”

Then under “User Variables” select Path and click on “Edit”

Then click on new and enter the following path for NuGet.

“C:\Users\<username>\AppData\Local\Microsoft\Windows\PowerShell\PowerShellGet\”

This is the default place where Powershell will store Nuget when downloaded.

2. After you have added Nuget to your path, you will need to re-register the repository in your Powershell terminal

Before you unregister the repository you will need to reopen your Powershell terminal for the PATH update to take place. Once you have reopened Powershell you can run the following command to unregister the repository

Unregister-PSRepository -Name <nuget feed name>

3. Add the Nuget feed as a source to NuGet.

To add your Azure DevOps Nuget Feed as a Nuget Source you can run the following command in Powershell

nuget sources add -name <nuget feed name> -source <source url> -username "PSRepo" -password <personal access token>

4. Register the Powershell repository

Once you have added the Nuget Feed as a Nuget Source you can register the Feed as a Powershell repository like show in a previous step or like show below

$password = ConvertTo-SecureString -String $($AzureDevopsPAT) -AsPlainText -Force
$credential = New-Object System.Management.Automation.PSCredential ('PSRepo', $password)

$params = @{
	Name                      = $RepoName
	SourceLocation            = $SourceURL
	PublishLocation           = $SourceURL
	InstallationPolicy        = 'Trusted'
	Credential                = $Credential

Register-PSRepository @params

Now once you have registered the repository you should be able to publish your module with the following command

Publish-Module -Path ".\SCPSMeraki\" -Repository $RepoName -NuGetApiKey $AzureDevopsPAT -Credential $credential

Conclusion

In this blog post, I walked through the process of setting up a Nuget Feed in Azure DevOps and use it as a private Powershell repository. This way you can create your private and free Powershell repository which you can connect to securely from anywhere in the world.

I also walked through how you can add the repository to your local PC’s Powershell terminal and how you can publish modules to the repository. Once you have the repository set up on your local pc you will also be able to install all of your modules with ease securely.

To Install a Powershell module from your private repository would be as easy as running the command.

Install-Module <module name> -Repository <repository name>

At last, I walked through some of the errors you might run into when setting the repository up and how you can mitigate the errors. 

From my experience, I only experienced errors when I was trying to publish modules from a local pc. When I registered the module on another PC’s I was able to install modules without any mitigation. The only issue was when trying to publish my modules.

If you have followed the blog post you should be able to publish and install Powershell modules from your own private Powershell repository without any issues.

All URLs and access tokens from this blog post are only for tutorial/testing purposes and have been erased after the creation of this blog post

2 Comments

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

This website uses cookies. By continuing to use this site, you accept our use of cookies.