Setting Up a Private NuGet Repository

These days most developers use NuGet to reference third-party dependencies like EntityFramework, Enterprise Library and NInject.  A full discussion of NuGet is beyond this post.  There are lots of articles on what it is, how to use it and how to package and publish to it so I’ll ignore all these things.  But what about internal dependencies like shared libraries used by company applications?  It turns out you can host your own private NuGet repository as well.  Visual Studio is already set up to support this.  The hard part is getting the repository set up.  At my company we’ve been running a local NuGet repository for a year and it works great, for the most part.  We have a company policy that all dependencies must be stored in NuGet.  This pretty much eliminates versioning issues, sharing code across projects and storing binaries in source control.  In this post I’m going to go over the steps to set up a private NuGet repository.  Others have posted on this topic and there is some documentation available but unfortunately it is out of date.


Note: These instructions are based upon the NuGet Gallery source as of 6 Jan 2013.


Prerequisites


Before you can get NuGet up and running you’ll need some prerequisite software.


For compiling NuGet:



For hosting NuGet (using the preferred approach):


  • IIS to host the web site
  • SQL Server to store the site metadata
  • File system to store packages
  • URL Rewrite 2.0

Compiling the NuGet Gallery


Here’s the steps for compiling the NuGet source code.


  1. Download the source from here
  2. Extract the files to your local drive.
  3. At this point you can build the source via PowerShell and the .ps1 file but I’ve never had any luck with it.  So I follow the next set of steps instead.
  4. Open the solution in Visual Studio.
  5. Build the project.

At this point you have the NuGet website (the Website project) compiled and ready to go.  Note that NuGet is configured to use HTTPS for authentication.  For your internal repository you might not want this.  Unfortunately to disable it you have to modify the code.  Find all references to the attribute ‘RequireRemoteHttps’ and comment them out.


Deploy NuGet to IIS


  1. Copy the website to the target directory on IIS (for our purposes we assume \wwwroot\NuGet).  For the current source this includes the following files and directories:
    1. \Api
    2. \App_Code
    3. \App_Data
    4. \Bin
    5. \Content
    6. \DataServices\*.svc
    7. \DynamicData
    8. \Errors
    9. \Infrastructure\*.sql
    10. \Scripts
    11. \Views
    12. All files in root other than: *.cs, *.ruleset, packages.config, *.resx, *.tt, *.csproj
  2. If not already done create a new IIS website backing the target directory.
    1. It is strongly recommended that you create a new app pool for NuGet and use a custom account.  Note that the account will need access to the SQL database so a network account is best.  Where I work we use the same account as our TFS services.
    2. The app pool will use .NET 4.0 with an Integrated pipeline
  3. Ensure that the app pool has read/write access to the App_Data/Lucene folder

Configure NuGet


NuGet is now deployed but it is not configured yet.  Open the web.config for the site and change the following settings.


  1. <appSettings>
    1. Gallery:SiteRoot – Specify the full URL to the NuGet gallery site.  This will be used by the site when creating links.
  2. <connectionStrings>
    1. NuGetGallery – Specify the connection string to connect to the SQL database that will house the NuGet metadata.  If the NuGet app pool is configured to use a custom account then integrated security can be used otherwise specify the account to use when connecting to SQL.

Configure SQL Server


NuGet will automatically initialize the database when it first connects.  However the database must exist so if you do not yet have a database for NuGet then create one now. 


  1. Open SQL Server Management Studio.
  2. Connect to the SQL server that will host the database.  Where I work we use the existing TFS server’s database because we are not using the instance of SQL provided by TFS.  If you are using the SQL instance that ships as part of TFS then refer to the licensing restrictions of TFS before doing this.
  3. Create a new database for NuGet.  The default is NuGetGallery.
  4. Ensure that the account that NuGet will run under has full permissions to the database.

Start NuGet


If all is well you should now be able to browse to the NuGet site.  Note that the first time it starts it will be slow as it updates the database.  If any errors occur or the site refuses to start then disable custom errors in the web.config and resolve the errors.  When I initially tried to get the site running under Windows 8 it complained the web.config was invalid.  I narrowed down the error to the <rewrite> section.  Removing that section allowed the site to load.  A quick check revealed that the URL Rewrite 2.0 module for IIS (which NuGet needs) is not part of IIS that ships with Windows 8.  Using the Web Platform Installer I installed it and everything worked correctly.


Set Up E-mail


NuGet uses Forms authentication for authenticating users.  When creating a new user account NuGet will, by default, send an e-mail to the user to confirm their e-mail address.  You will want to set up NuGet to use your company e-mail server so that you can get this e-mail, and any other e-mails that are sent over time.  Otherwise creating a new user requires that you manually get and forward the generated e-mail. 


NuGet does not expose any UI to update the e-mail information and it is stored in the database.  Open the GallerySettings table in SSMS and set the following columns.


  • SmtpPort – The SMTP port of your e-mail server.  Normally this is 25.
  • SmtpHost – The SMTP host address.
  • SmtpUsername – The user name for authentication, if any.
  • SmtpPassword – The password for authentication, if any.
  • UseSmtp – Set to 1 to enable e-mail
  • ConfirmEmailAddresses – Set this to 0 to disable confirmation e-mail addresses.

By default the e-mail connection will use SSL. If you do not want SSL for your e-mail then you’ll have to modify the source code again.  Ultimately the setting should be stored in the database with the rest of the SMTP settings.  But to keep it simple just do the following.


  1. Edit the ContainerBindings file.
  2. Find the initialization code for IMailSender.
  3. Set EnableSsl to false.
  4. Rebuild the code.

Package Storage


NuGet uses the database to store package metadata but, by default, it stores the packages themselves on disk.  The appSetting Gallery:PackageStoreType specifies the provider to use.  For performance reasons you will likely want to continue using the file system to store packages but the default directory is not the best choice when you need to upgrade the site.  Instead you should consider storing the files in a more reasonable path.  Be sure that the site has read/write permissions to the new package directory.  To set the file path where packages are stored add/update the appSetting Gallery:FileStorageDirectory.  Specify the full path to where packages will be stored.


If you do not want to use the file system to store packages then you can use a different package store by setting the appSetting Gallery:PackageStoreType.  Currently only Windows Azure is the alternative.  You can technically add your own and update the corresponding enum and config setting to use a different store – such as a database.


Registering


At this point you should be able to access the site.  You will need to register an account so that you can add packages.  Technically all users will need an account.  You will also want to assign yourself as an administrator for the site.


  1. Open the Users table in SSMS.
  2. Get the Key for the user you want to make an administrator.
  3. Add a new row to the UserRoles table where the user matches the key you have and the role key is for administrators, 1 is currently the value.

When creating an account NuGet will generate an e-mail that you need to click on unless you’ve disabled confirmation e-mails.  Unless you’ve set up an e-mail server you’ll need to click on a link inside this e-mail from the account it was sent to.  If you’re using a corporate e-mail client like Outlook it shouldn’t be too hard to get the e-mail contents such that you can click on it.  For everybody else it is just easier to open the Users table in the database and copy the UnconfirmedEmailAddress value to EmailAddress. Then you can log in successfully.


Currently NuGet uses Forms authentication.  For a private gallery it might be more useful to use Windows authentication.  Unfortunately that requires adding code to the site.  NuGet relies on user accounts for managing packages so some updates will need to be made to handle Windows authentication.  That is left as an exercise for the user.


Connecting to Visual Studio


From this point on the private repository works just like the public repository.  You can upload and browse packages.  A word of warning – once a package is uploaded it is forever part of NuGet.  Nevertheless you should upload a package to make sure everything is in working order.  Once you’ve uploaded a package you can configure Visual Studio to use it.


  1. Open the Package Manager settings (Tools\Library Package Manager\Package Manager Settings or Tools\Options -> Package Manager).
  2. Go to the Package Sources section.
  3. Click the plus button to add a new source.
  4. Specify a name (ex. Company)
  5. Specify the source (http://<server>/<site>/api/v2).
  6. Click Update.
  7. Click OK to close the dialog.
  8. Open the Manage NuGet Packages dialog (I generally do so from a solution).
  9. Under Online select the new repository.
  10. The uploaded package should appear.
  11. Click Install to confirm the package can be downloaded and installed correctly.

Ownership


NuGet associates one or more owners with every package.  The owner of a package can upload new versions.  For a public repository this is fine but for a private repository it is likely that everyone should be able to update packages.  To add or remove owner(s) from a package do the following.


  1. Open the package on the NuGet site.
  2. Select Manage Owners.  This is only available for owners and adminstrators.
  3. Add or remove owners from the package.

Local Repository


One issue with NuGet is that once it is uploaded it will be forever available.  NuGet does not support deletion.  It is generally a good idea to verify that a NuGet package is working correctly before uploading it but this becomes a catch-22.  You cannot test the package unless you can download it from the repository.  You don’t want to upload the package until it works.  Fortunately there is an easy solution, a local repository.


A local repository is useful for testing packages.  Ultimately it is nothing more than a directory where NuGet can retrieve packages from.  Depending upon your need you might have a local repository on each developer’s machine or you might set up a file share where all devs can point to.  Either way you point the Package Manager to the directory and it’ll work just like a regular repository.  To get packages into the repository you just drop the .nupkg file into the folder.  You can then install/upgrade the packages through Package Manager in Visual Studio.  Note that packages always have a full version in the filename so it is easy to tell whether there are new versions available.  Once the testing is complete you can delete the packages.


To configure Visual Studio to use a local repository do the following.


  1. Open the Package Manager settings (Tools\Library Package Manager\Package Manager Settings or Tools\Options -> Package Manager).
  2. Go to the Package Sources section.
  3. Click the plus button to add a new source.
  4. Specify a name (ex. Local)
  5. Specify the source path (ex C:\MyTestNuGetGallery).
  6. Click Update.
  7. Click OK to close the dialog.
  8. Open the Manage NuGet Packages dialog (I generally do so from a solution).
  9. Under Online select the new repository.
  10. The uploaded package should appear.
  11. Click Install to confirm the package can be downloaded and installed correctly.