Header banner showing post overview

Using private packages with Pip

Pierce Freeman

4 weeks ago

As Python projects become more sophisticated, development teams often need to manage proprietary code across multiple projects and teams. While PyPI is excellent for open-source packages, organizations frequently require private package repositories for their internal libraries and tools. This guide explores how to effectively manage private Python packages using pip, the standard package installer for Python.

Why host packages privately?

The need for private package repositories often emerges from common development challenges. You might find yourself duplicating utility functions across projects, or your team might struggle to maintain consistent versions of internal libraries across different applications. These situations indicate that basic code sharing methods no longer suffice, and a more robust solution is needed.

Private package repositories provide a centralized, secure location for proprietary code. Large corporations might use them to host internal machine learning models or business-critical algorithms that provide competitive advantages. Startups often use private repositories to protect intellectual property while providing simple installation methods for clients. Individual developers frequently find private repositories valuable for managing code across multiple projects or client engagements.

Consider a healthcare company developing proprietary patient data processing algorithms. They can't publish these algorithms as open-source software, but they need to share them across multiple internal systems. A private package repository enables their development team to manage these algorithms as easily as open-source dependencies while maintaining strict access controls.

Understanding pip: The Python Package Installer

Pip has been the standard package installer for Python since its inception. While newer tools have emerged in the Python ecosystem, pip remains the foundational tool for package management, supported by every Python installation and used by millions of developers worldwide.

Pip excels at its core functionality: installing Python packages. It handles dependency resolution, package downloads, and installation with remarkable reliability. When combined with requirements.txt files, pip provides a straightforward way to specify and install project dependencies, making it an essential tool in any Python developer's toolkit.

Understanding private package repositories

Before diving into the practical aspects of using pip with private packages, it's important to understand the underlying mechanics. A private Python package repository is essentially a specialized web server implementing Python's package repository API.

When you run a command like pip install your-private-package, pip needs to know where to find the package and how to authenticate with the repository. This interaction follows a standardized protocol defined in PEP 503, known as the "Simple Repository API." The repository must provide an index page listing available packages and separate pages for each package showing its available versions.

Downloading private packages

Setting up pip to work with private packages involves configuring both the repository URL and authentication credentials. Pip's configuration system allows you to specify these settings at the user level, making them available across all your projects.

First, create or edit your pip configuration file (~/.pip/pip.conf on Unix-like systems, or pip.ini on Windows):

[global]
extra-index-url = https://your-repository.com/simple/

For authentication, you can use environment variables or configure credentials in your .netrc file:

export PIP_INDEX_URL=https://username:password@your-repository.com/simple/

Publishing your own private packages

Publishing private packages with pip requires a few more tools in your toolkit, primarily setuptools for building packages and twine for secure uploads. The process starts with configuring your upload destination in your .pypirc file:

[distutils]
index-servers =
    private

[private]
repository = https://your-repository.com/legacy/
username = username
password = password

The process of building and publishing your package involves two steps:

python setup.py sdist bdist_wheel
twine upload -r private dist/*

These commands handle several complex tasks: building both wheel and source distributions of your package, generating metadata, and securely uploading everything to your private repository.

Using Private Packages with pip

Choosing where to host your private packages

One of the most crucial decisions when implementing private packages is selecting where to host them. The Python ecosystem offers several options, from self-managed solutions to enterprise-grade hosting services. Let's explore these options to help you make an informed decision for your organization.

Self-Hosted PyPI Server

For teams with basic requirements or those just starting with private packages, you can set up your own PyPI-compatible server using tools like PyPI-Server or Devpi. At its core, this implements PEP 503's Simple Repository API through a lightweight web server.

Here's what a basic compliant repository structure looks like:

/simple/
    index.html
    your-package/
        index.html
        your-package-1.0.0.tar.gz
        your-package-1.0.0-py3-none-any.whl

While this approach is educational and might work for small teams, it requires significant maintenance effort. You'll need to handle security, access control, and package uploads yourself. Scaling this solution across a growing organization can become challenging.

Enterprise Solutions: JFrog Artifactory

For larger organizations, especially those already invested in enterprise tooling, JFrog Artifactory provides a comprehensive solution for package management. Artifactory offers features beyond simple package hosting:

  • Multi-repository management (not just Python packages)
  • Fine-grained access control
  • Repository replication and backup
  • Integration with CI/CD pipelines
  • Advanced security features and vulnerability scanning

However, Artifactory's enterprise focus comes with corresponding complexity and cost. Setting up and maintaining an Artifactory installation requires dedicated DevOps resources, and the licensing costs can be significant for smaller teams.

Modern Cloud Solutions: Envelope.dev

Envelope.dev represents a middle ground between self-hosted solutions and enterprise platforms. It's designed specifically for Python package management, offering a streamlined and cost-effective approach.

Envelope.dev stands out for several reasons:

First, it provides unlimited package support without tiered pricing based on repository count – a departure from traditional enterprise pricing models. This makes it particularly attractive for organizations with many small packages or those looking to modularize their codebase.

The platform also excels in access management. Rather than forcing a specific authentication scheme, Envelope.dev allows extensive customization of access credentials. This flexibility enables you to implement package access patterns that match your organization's security requirements.

Setting up a new private package repository on Envelope.dev with pip is straightforward:

# In your .pypirc file
[distutils]
index-servers =
    pypi
    envelope

[envelope]
repository: https://app.envelope.dev/legacy/
username: pypi
password: your_api_key

Downloading packages is equally simple - just add to your pip configuration:

# In your pip.conf or pip.ini
[global]
extra-index-url = https://app.envelope.dev/simple/

Making the Right Choice

When selecting a hosting solution for your private packages, consider these factors:

Scale of operations: A self-hosted solution might work for a small team with a few packages, but larger organizations will benefit from managed solutions like Envelope.dev or Artifactory.

Resource availability: Consider both financial and human resources. Enterprise solutions provide comprehensive features but require significant investment in both areas. Cloud-based solutions like Envelope.dev offer a middle ground with managed infrastructure and predictable pricing.

Integration requirements: If you need to integrate with existing systems or manage multiple package types beyond Python, an enterprise solution might be necessary. However, if your focus is purely on Python packages, a specialized solution could provide a better experience.

Security requirements: While all solutions can be secured appropriately, they differ in the complexity of setting up and maintaining security configurations. Managed solutions typically provide better security out of the box, with regular updates and vulnerability scanning.

Private package best practices

Managing private packages with pip requires careful attention to several organizational aspects. Version management becomes particularly important when dealing with private packages, as version changes in an internal library can affect multiple projects across your organization.

Version Management

Implement clear guidelines for version numbering. Semantic versioning (major.minor.patch) provides an excellent framework, but ensure all team members understand when to increment each number:

  • Major version (1.0.0 → 2.0.0): Breaking changes
  • Minor version (1.1.0 → 1.2.0): New features, backward-compatible
  • Patch version (1.1.1 → 1.1.2): Bug fixes, backward-compatible

Security Considerations

Private packages often contain sensitive code, making security crucial:

  1. Use environment variables for sensitive credentials
  2. Regularly rotate authentication tokens
  3. Implement IP whitelisting where possible
  4. Audit access logs regularly
  5. Use HTTPS for all repository communications

Documentation Strategy

Documentation presents unique challenges with private packages:

  1. Set up an internal documentation site
  2. Use tools like Sphinx to generate documentation from docstrings
  3. Include example usage in README files
  4. Maintain a changelog for each package
  5. Document deployment and installation procedures

Dependency Management

For reliable package management:

  1. Pin exact versions in requirements.txt files
  2. Use pip freeze to generate complete dependency lists
  3. Regularly update and test dependencies
  4. Maintain a dedicated requirements-dev.txt for development dependencies

Conclusion

Private Python packages, when properly managed with pip, provide a robust solution for code sharing within organizations. While the setup process requires careful planning, the long-term benefits in terms of code organization, version management, and deployment consistency make it worthwhile.

As you implement private packages in your organization, remember that the goal is to enhance development efficiency and maintainability. Start with a single widely-used internal library, then gradually expand your private package ecosystem as you become more comfortable with the workflow.

Pip's reliable handling of private packages demonstrates the maturity of Python's package management ecosystem. By embracing these established tools and practices, we can build more maintainable and secure Python applications while keeping proprietary code properly protected.

Easy, private Python packages.

Stop worrying about authorizing git clones, manual indexes, or expensive solutions. Envelope makes hosting private packages as easy as publishing to pypi.

App screenshot