Package: pypiserver
pypiserver - minimal PyPI server for use with pip/easy_installnamedescriptionVersion2.0.1Date:2023-10-01Sourcehttps://github.com/pypiserver/pypiserverPyPIhttps://pypi.org/project/pypiserver/Testshttps://github.com/pypiserver/pypiserver/actionsMaintainersKostis Anagnostopoulosankostis@gmail.com, Matthew Planchardmplanchard@gmail.com,  Dmitrii Orlovdmtree.dev@yahoo.com,Someone new?We are looking for new maintainers!#397Licensezlib/libpng + MITCommunityhttps://pypiserver.zulipchat.comChat with us onZulip!pypiserveris a minimalPyPIcompatible server forpiporeasy_install.
It is based onbottleand serves packages from regular directories.
Wheels, bdists, eggs and accompanying PGP-signatures can be uploaded
either withpip,setuptools,twine,pypi-uploader, or simply copied
withscp.Note
The official software poweringPyPIisWarehouse. However,Warehouseis fairly specialized to bepypi.org's own software, and should not
be used in other contexts. In particular, it does not officially support
being used as a custom package index by users wishing to serve their own
packages.pypiserverimplements the same interfaces asPyPI, allowing
standard Python packaging tooling such aspipandtwineto
interact with it as a package index just as they would withPyPI, while
making it much easier to get a running index server.pypiserverTable of Contentspypiserver - minimal PyPI server for use with pip/easy_installQuickstart Installation and UsageMore details about pypi-server runMore details about pypi-server updateClient-Side ConfigurationsConfiguring pipConfiguring easy_installUploading Packages RemotelyApache like Authentication ( htpasswd )Upload with setuptoolsUpload with twineUsing the Docker ImageAlternative Installation methodsInstalling the Very Latest VersionRecipesManaging the Package DirectoryServing Thousands of PackagesManaging Automated StartupRunning as a systemd serviceLaunching through supervisorRunning as a service with NSSM (Windows)Using a Different WSGI ServerApacheGunicornPasteBehind a Reverse ProxyNginxSupporting HTTPSTraefikUtilizing the APIUsing Ad-Hoc Authentication ProvidersUse with MicroPythonCustom Health Check EndpointConfigure a custom health check by CLI argumentsConfigure a custom health endpoint by scriptSourcesKnown LimitationsSimilar ProjectsUnmaintained or archivedRelated ProjectsLicenseQuickstart Installation and Usagepypiserverworks with Python 3.6+ and PyPy3.Older Python versions may still work, but they are not tested.For legacy Python versions, usepypiserver-1.xseries. Note that these are
not officially supported, and will not receive bugfixes or new features.TipThe commands below work on a unix-like operating system with a posix shell.
The'~'character expands to user's home directory.If you're using Windows, you'll have to use their "Windows counterparts".
The same is true for the rest of this documentation.Installpypiserverwith this commandpipinstallpypiserver# Or: pypiserver[passlib,cache]mkdir~/packages# Copy packages into this directory.See alsoAlternative Installation methodsCopy some packages into your~/packagesfolder and then
get yourpypiserverup and runningpypi-serverrun-p8080~/packages&# Will listen to all IPs.From the client computer, type this# Download and install hosted packages.pipinstall--extra-index-urlhttp://localhost:8080/simple/...# orpipinstall--extra-index-urlhttp://localhost:8080...# Search hosted packages.pipsearch--indexhttp://localhost:8080...# Note that pip search does not currently work with the /simple/ endpoint.See alsoClient-side configurationsfor avoiding tedious typing.Enterpypi-server -hin the cmd-line to print a detailed usage messageusage: pypi-server [-h] [-v] [--log-file FILE] [--log-stream STREAM]
                   [--log-frmt FORMAT] [--hash-algo HASH_ALGO]
                   [--backend {auto,simple-dir,cached-dir}] [--version]
                   {run,update} ...

start PyPI compatible package server serving packages from PACKAGES_DIRECTORY. If PACKAGES_DIRECTORY is not given on the command line, it uses the default ~/packages. pypiserver scans this directory recursively for packages. It skips packages and directories starting with a dot. Multiple package directories may be specified.

positional arguments:
  {run,update}
    run                 Run pypiserver, serving packages from
                        PACKAGES_DIRECTORY
    update              Handle updates of packages managed by pypiserver. By
                        default, a pip command to update the packages is
                        printed to stdout for introspection or pipelining. See
                        the `-x` option for updating packages directly.

optional arguments:
  -h, --help            show this help message and exit
  -v, --verbose         Enable verbose logging; repeat for more verbosity.
  --log-file FILE       Write logging info into this FILE, as well as to
                        stdout or stderr, if configured.
  --log-stream STREAM   Log messages to the specified STREAM. Valid values are
                        stdout, stderr, and none
  --log-frmt FORMAT     The logging format-string.  (see `logging.LogRecord`
                        class from standard python library)
  --hash-algo HASH_ALGO
                        Any `hashlib` available algorithm to use for
                        generating fragments on package links. Can be disabled
                        with one of (0, no, off, false).
  --backend {auto,simple-dir,cached-dir}
                        A backend implementation. Keep the default 'auto' to
                        automatically determine whether to activate caching or
                        not
  --version             show program's version number and exit

Visit https://github.com/pypiserver/pypiserver for more informationMore details about pypi server runEnterpypi-server run -hin the cmd-line to print a detailed usageusage: pypi-server run [-h] [-v] [--log-file FILE] [--log-stream STREAM]
                       [--log-frmt FORMAT] [--hash-algo HASH_ALGO]
                       [--backend {auto,simple-dir,cached-dir}] [--version]
                       [-p PORT] [-i HOST] [-a AUTHENTICATE]
                       [-P PASSWORD_FILE] [--disable-fallback]
                       [--fallback-url FALLBACK_URL]
                       [--health-endpoint HEALTH_ENDPOINT] [--server METHOD]
                       [-o] [--welcome HTML_FILE] [--cache-control AGE]
                       [--log-req-frmt FORMAT] [--log-res-frmt FORMAT]
                       [--log-err-frmt FORMAT]
                       [package_directory [package_directory ...]]

positional arguments:
  package_directory     The directory from which to serve packages.

optional arguments:
  -h, --help            show this help message and exit
  -v, --verbose         Enable verbose logging; repeat for more verbosity.
  --log-file FILE       Write logging info into this FILE, as well as to
                        stdout or stderr, if configured.
  --log-stream STREAM   Log messages to the specified STREAM. Valid values are
                        stdout, stderr, and none
  --log-frmt FORMAT     The logging format-string.  (see `logging.LogRecord`
                        class from standard python library)
  --hash-algo HASH_ALGO
                        Any `hashlib` available algorithm to use for
                        generating fragments on package links. Can be disabled
                        with one of (0, no, off, false).
  --backend {auto,simple-dir,cached-dir}
                        A backend implementation. Keep the default 'auto' to
                        automatically determine whether to activate caching or
                        not
  --version             show program's version number and exit
  -p PORT, --port PORT  Listen on port PORT (default: 8080)
  -i HOST, -H HOST, --interface HOST, --host HOST
                        Listen on interface INTERFACE (default: 0.0.0.0)
  -a AUTHENTICATE, --authenticate AUTHENTICATE
                        Comma-separated list of (case-insensitive) actions to
                        authenticate (options: download, list, update;
                        default: update).
                         
                         Any actions not specified are not authenticated, so
                         to authenticate downloads and updates, but allow
                         unauthenticated viewing of the package list, you would
                         use:
                         
                          pypi-server -a 'download, update' -P
                          ./my_passwords.htaccess
                         
                        To disable authentication, use:
                         
                          pypi-server -a . -P .
                         
                        See the `-P` option for configuring users and
                        passwords.
                         
                        Note that when uploads are not protected, the
                        `register` command is not necessary, but `~/.pypirc`
                        still needs username and password fields, even if
                        bogus.
  -P PASSWORD_FILE, --passwords PASSWORD_FILE
                        Use an apache htpasswd file PASSWORD_FILE to set
                        usernames and passwords for authentication.
                         
                        To allow unauthorized access, use:
                         
                          pypi-server -a . -P .
                         
  --disable-fallback    Disable the default redirect to PyPI for packages not
                        found in the local index.
  --fallback-url FALLBACK_URL
                        Redirect to FALLBACK_URL for packages not found in the
                        local index.
  --health-endpoint HEALTH_ENDPOINT
                        Configure a custom liveness endpoint. It always
                        returns 200 Ok if the service is up. Otherwise, it
                        means that the service is not responsive.
  --server METHOD       Use METHOD to run the server. Valid values include
                        paste, cherrypy, twisted, gunicorn, gevent, wsgiref,
                        and auto. The default is to use "auto", which chooses
                        one of paste, cherrypy, twisted, or wsgiref.
  -o, --overwrite       Allow overwriting existing package files during
                        upload.
  --welcome HTML_FILE   Use the contents of HTML_FILE as a custom welcome
                        message on the home page.
  --cache-control AGE   Add "Cache-Control: max-age=AGE" header to package
                        downloads. Pip 6+ requires this for caching.AGE is
                        specified in seconds.
  --log-req-frmt FORMAT
                        A format-string selecting Http-Request properties to
                        log; set to '%s' to see them all.
  --log-res-frmt FORMAT
                        A format-string selecting Http-Response properties to
                        log; set to '%s' to see them all.
  --log-err-frmt FORMAT
                        A format-string selecting Http-Error properties to
                        log; set to '%s' to see them all.More details about pypi-server updateMore details aboutpypi-server updateusage: pypi-server update [-h] [-v] [--log-file FILE] [--log-stream STREAM]
                          [--log-frmt FORMAT] [--hash-algo HASH_ALGO]
                          [--backend {auto,simple-dir,cached-dir}] [--version]
                          [-x] [-d DOWNLOAD_DIRECTORY] [-u]
                          [--blacklist-file IGNORELIST_FILE]
                          [package_directory [package_directory ...]]

positional arguments:
  package_directory     The directory from which to serve packages.

optional arguments:
  -h, --help            show this help message and exit
  -v, --verbose         Enable verbose logging; repeat for more verbosity.
  --log-file FILE       Write logging info into this FILE, as well as to
                        stdout or stderr, if configured.
  --log-stream STREAM   Log messages to the specified STREAM. Valid values are
                        stdout, stderr, and none
  --log-frmt FORMAT     The logging format-string. (see `logging.LogRecord`
                        class from standard python library)
  --hash-algo HASH_ALGO
                        Any `hashlib` available algorithm to use for
                        generating fragments on package links. Can be disabled
                        with one of (0, no, off, false).
  --backend {auto,simple-dir,cached-dir}
                        A backend implementation. Keep the default 'auto' to
                        automatically determine whether to activate caching or
                        not
  --version             show program's version number and exit
  -x, --execute         Execute the pip commands rather than printing to
                        stdout
  -d DOWNLOAD_DIRECTORY, --download-directory DOWNLOAD_DIRECTORY
                        Specify a directory where packages updates will be
                        downloaded. The default behavior is to use the
                        directory which contains the package being updated.
  -u, --allow-unstable  Allow updating to unstable versions (alpha, beta, rc,
                        dev, etc.)
  --blacklist-file IGNORELIST_FILE, --ignorelist-file IGNORELIST_FILE
                        Don't update packages listed in this file (one package
                        name per line, without versions, '#' comments
                        honored). This can be useful if you upload private
                        packages into pypiserver, but also keep a mirror of
                        public packages that you regularly update. Attempting
                        to pull an update of a private package from `pypi.org`
                        might pose a security risk - e.g. a malicious user
                        might publish a higher version of the private package,
                        containing arbitrary code.Client-Side ConfigurationsAlways specifying the pypi url on the command line is a bit
cumbersome. Sincepypiserverredirectspip/easy_installto thepypi.orgindex if it doesn't have a requested package, it is a
good idea to configure them to always use your local pypi index.Configuring pipForpipcommand this can be done by setting the environment variablePIP_EXTRA_INDEX_URLin your.bashr/.profile/.zshrcexportPIP_EXTRA_INDEX_URL=http://localhost:8080/simple/or by adding the following lines to~/.pip/pip.conf[global]extra-index-url=http://localhost:8080/simple/NoteIf you have installedpypiserveron a remote url withouthttpsyou will receive an "untrusted" warning frompip, urging you to append
the--trusted-hostoption.  You can also include this option permanently
in your configuration-files or environment variables.Configuring easy_installForeasy_installcommand you may set the following configuration in~/.pydistutils.cfg[easy_install]index_url=http://localhost:8080/simple/Uploading Packages RemotelyInstead of copying packages directly to the server's folder (i.e. withscp),
you may use python tools for the task, e.g.python setup.py upload.
In that case,pypiserveris responsible for authenticating the upload-requests.NoteWe strongly advise to password-protected your uploads!It is possible to disable authentication for uploads (e.g. in intranets).
To avoid lazy security decisions, read help for-Pand-aoptions.Apache Like Authentication (htpasswd)First make sure you have thepasslibmodule installed (note thatpasslib>=1.6is required), which is needed for parsing the Apachehtpasswdfile specified by the-P,--passwordsoption
(see next steps)pipinstallpasslibCreate the Apachehtpasswdfile with at least one user/password pair
with this command (you'll be prompted for a password)htpasswd-schtpasswd.txt<some_username>TipRead thisSOquestion for runninghtpasswdcmd underWindowsor if you have bogus passwords that you don't care because they are for
an internal service (which is still "bad", from a security perspective...)
you may use thispublic serviceTipWhen accessing pypiserver via the api, alternate authentication
methods are available via theautherconfig flag. Any callable
returning a boolean can be passed through to the pypiserver config in
order to provide custom authentication. For example, to configure
pypiserver to authenticate using thepython-pamimportpampypiserver.default_config(auther=pam.authenticate)Please seeUsing Ad-hoc authentication providers_ for more information.You  need to restart the server with the-Poption only once
(but user/password pairs can later be added or updated on the fly)./pypi-serverrun-p8080-Phtpasswd.txt~/packages&Upload with setuptoolsOn client-side, edit or create a~/.pypircfile with a similar content:[distutils]index-servers=pypilocal[pypi]username:<your_pypi_username>password:<your_pypi_passwd>[local]repository:http://localhost:8080username:<some_username>password:<some_passwd>Then from within the directory of the python-project you wish to upload,
issue this command:pythonsetup.pysdistupload-rlocalUpload with twineTo avoid storing you passwords on disk, in clear text, you may either:use theregistersetuptools's command with the-roption,
like thatpythonsetup.pysdistregister-rlocalupload-rlocalusetwinelibrary, which
breaks the procedure in two steps.  In addition, it supports signing
your files with PGP-Signatures and uploading the generated.ascfiles
topypiserver::twineupload-rlocal--sign-identityuser_name./foo-1.zipUsing the Docker ImageStarting with version 1.2.5, official Docker images will be built for each
push to master, each dev, alpha, or beta release, and each final release.
The most recent full release will always be available under the taglatest,
and the current master branch will always be available under the tagunstable.You can always check to see what tags are currently available at ourDocker Repo.To run the most recent release ofpypiserverwith Docker, simplydockerrunpypiserver/pypiserver:latestrunThis startspypiserverserving packages from the/data/packagesdirectory inside the container, listening on the container port 8080.The container takes all the same arguments as the normalpypi-serverexecutable, with the exception of the internal container port (-p),
which will always be 8080.Of course, just running a container isn't that interesting. To map
port 80 on the host to port 8080 on the container::dockerrun-p80:8080pypiserver/pypiserver:latestrunYou can now access yourpypiserveratlocalhost:80in a web browser.To serve packages from a directory on the host, e.g.~/packagesdockerrun-p80:8080-v~/packages:/data/packagespypiserver/pypiserver:latestrunTo authenticate against a local.htpasswdfile::dockerrun-p80:8080-v~/.htpasswd:/data/.htpasswdpypiserver/pypiserver:latestrun-P.htpasswdpackagesYou can also specifypypiserverto run as a Docker service using a
composefile. An example composefile isprovidedAlternative Installation MethodsWhen trying the methods below, first use the following command to check whether
previous versions ofpypiserveralready exist, and (optionally) uninstall them::# VERSION-CHECK: Fails if not installed.pypi-server--version# UNINSTALL: Invoke again until it fails.pipuninstallpypiserverInstalling the Very Latest VersionIn case the latest version inpypiis a pre-release, you have to usepip's--preoption.  And to update an existing installation combine it
with--ignore-installedpipinstallpypiserver--pre-IYou can even install the latestpypiserverdirectly fromgithubwith the
following command, assuming you havegitinstalled on yourPATHpipinstallgit+git://github.com/pypiserver/pypiserver.gitRecipesManaging the Package DirectoryThepypi-servercommand has theupdatecommand that searches for updates of
available packages. It scans the package directory for available
packages and searches on pypi.org for updates. Without further
optionspypi-server updatewill just print a list of commands which must
be run in order to get the latest version of each package. Output
looks like$./pypi-serverupdatechecking106packagesfornewerversion.........u.e...........e..u..................e..............................e.............................noreleasesfoundonpypiforPyXML,Pymacs,mercurial,setuptools# update raven from 1.4.3 to 1.4.4pip-qinstall--no-deps--extra-index-urlhttps://pypi.org/simple/-d/home/ralf/packages/mirrorraven==1.4.4# update greenlet from 0.3.3 to 0.3.4pip-qinstall--no-deps--extra-index-urlhttps://pypi.org/simple/-d/home/ralf/packages/mirrorgreenlet==0.3.4It first prints for each package a single character after checking the
available versions on pypi. A dot(.) means the package is up-to-date,'u'means the package can be updated and'e'means the list of releases on
pypi is empty. After that it shows apipcommand line which can be used
to update a one package. Either copy and paste that or runpypi-server update -xin order to really execute those commands. You need
to havepipinstalled for that to work however.Specifying an additional-uoption will also allow alpha, beta and
release candidates to be downloaded. Without this option these
releases won't be considered.Serving Thousands of PackagesBy default,pypiserverscans the entire packages directory each time an
incoming HTTP request occurs. This isn't a problem for a small number of
packages, but causes noticeable slow-downs when serving thousands of packages.If you run into this problem, significant speedups can be gained by enabling
pypiserver's directory caching functionality. The only requirement is to
install thewatchdogpackage, or it can be installed duringpypiserverinstallation, by specifying thecacheextras option::pipinstallpypiserver[cache]Additional speedups can be obtained by using your webserver's builtin
caching functionality. For example, if you are usingnginxas a
reverse-proxy as described below inBehind a reverse proxy, you can
easily enable caching. For example, to allow nginx to cache up to
10 gigabytes of data for up to 1 hour::proxy_cache_path/data/nginx/cachelevels=1:2keys_zone=pypiserver_cache:10mmax_size=10ginactive=60muse_temp_path=off;server{# ...location/{proxy_cachepypiserver_cache;proxy_passhttp://localhost:8080;}}Using webserver caching is especially helpful if you have high request
volume. Using nginx caching, a real-world pypiserver installation was
able to easily support over 1000 package downloads/min at peak load.Managing Automated StartupThere are a variety of options for handling the automated starting of
pypiserver upon system startup. Two of the most common aresystemdandsupervisorfor linux systems. For windows creating services with scripts isn't
an easy task without a third party tool such asNSSM.Running As a systemd Servicesystemdis installed by default on most modern Linux systems and as such,
it is an excellent option for managing the pypiserver process. An example
config file forsystemdcan be seen below[Unit]Description=AminimalPyPIserverforusewithpip/easy_install.After=network.target[Service]Type=simple# systemd requires absolute path here too.PIDFile=/var/run/pypiserver.pidUser=www-dataGroup=www-dataExecStart=/usr/local/bin/pypi-serverrun-p8080-aupdate,download--log-file/var/log/pypiserver.log-P/etc/nginx/.htpasswd/var/www/pypiExecStop=/bin/kill-TERM$MAINPIDExecReload=/bin/kill-HUP$MAINPIDRestart=alwaysWorkingDirectory=/var/www/pypiTimeoutStartSec=3RestartSec=5[Install]WantedBy=multi-user.targetAdjusting the paths and adding this file aspypiserver.serviceinto yoursystemd/systemdirectory will allow management of the pypiserver process withsystemctl, e.g.systemctl start pypiserver.More useful information aboutsystemdcan be found athttps://www.digitalocean.com/community/tutorials/how-to-use-systemctl-to-manage-systemd-services-and-unitsLaunching through supervisorsupervisorhas the benefit of being a pure python
package and as such, it provides excellent cross-platform support for process
management. An example configuration file forsupervisoris given below[program:pypi]command=/home/pypi/pypi-venv/bin/pypi-serverrun-p7001-P/home/pypi/.htpasswd/home/pypi/packagesdirectory=/home/pypiuser=pypiautostart=trueautorestart=truestderr_logfile=/var/log/pypiserver.err.logstdout_logfile=/var/log/pypiserver.out.logFrom there, the process can be managed viasupervisordusingsupervisorctl.Running As a service with NSSMFor Windows download NSSM fromhttps://nssm.ccunzip to a desired location such as Program Files. Decide whether you are going
to use win32 or win64, and add that exe to environment PATH.Create a start_pypiserver.batpypi-serverrun-p8080C:\Path\To\Packages&Test the batch file by running it first before creating the service. Make sure you can access
the server remotely, and install packages. If you can, proceed, if not troubleshoot until you can.
This will ensure you know the server works, before adding NSSM into the mix.From the command promptnssminstallpypiserverThis command will launch a NSSM gui applicationPath:C:\Path\To\start_pypiserver.batStartupdirectory:AutogenerateswhenselectingpathServicename:pypiserverThere are more tabs, but that is the basic setup. If the service needs to be running with a certain
login credentials, make sure you enter those credentials in the logon tab.Start the servicenssmstartpypiserverOther useful commandsnssm--helpnssmstop<servicename>nssmrestart<servicename>nssmstatus<servicename>For detailed information please visithttps://nssm.ccUsing a Different WSGI ServerThebottleweb-server which supports many WSGI-servers, among others,paste,cherrypy,twistedandwsgiref(part of Python); you select
them using the--serverflag.You may view all supported WSGI servers using the following interactive code>>>frompypiserverimportbottle>>>list(bottle.server_names.keys())['cgi','gunicorn','cherrypy','eventlet','tornado','geventSocketIO','rocket','diesel','twisted','wsgiref','fapws3','bjoern','gevent','meinheld','auto','aiohttp','flup','gae','paste','waitress']If none of the above servers matches your needs, invoke just thepypiserver:app()method which returns the internal WSGI-app WITHOUT
starting-up a server - you may then send it to any WSGI server you like.
Read also theUtilizing the APIsection.Some examples are given below - you may find more details inbottle
site.ApacheTo use yourApache2withpypiserver, prefer to utilizemod_wsgias
explained inbottle's documentation.Note
If you choose instead to go withmod_proxy, mind that you may bump into problems
with the prefix-path (see#155).Adapt and place the followingApacheconfiguration either into top-level scope,
or inside some(contributed by Thomas Waldmann):WSGIScriptAlias//yoursite/wsgi/pypiserver-wsgi.pyWSGIDaemonProcesspypisrvuser=pypisrvgroup=pypisrvumask=0007\processes=1threads=5maximum-requests=500\display-name=wsgi-pypisrvinactivity-timeout=300WSGIProcessGrouppypisrvWSGIPassAuthorizationOn# Required for authentication (https://github.com/pypiserver/pypiserver/issues/288)<Directory/yoursite/wsgi>Requireallgranted</Directory>or if using olderApache < 2.4, substitute the last part with this::<Directory/yoursite/wsgi>Orderdeny,allowAllowfromall</Directory>Then create the/yoursite/cfg/pypiserver.wsgifile and make sure that
theuserandgroupof theWSGIDaemonProcessdirective
(pypisrv:pypisrvin the example) have the read permission on itimportpypiserverconf=pypiserver.default_config(root="/yoursite/packages",password_file="/yoursite/htpasswd",)application=pypiserver.app(**conf)Tip
If you have installedpypiserverin a virtualenv, followmod_wsgi'sinstructionsand prepend the python code above with the followingimportsitesite.addsitedir('/yoursite/venv/lib/pythonX.X/site-packages')Note
For security reasons, notice that theDirectorydirective grants access
to a directory holding thewsgistart-up script, alone; nothing else.Note
To enable HTTPS support on Apache, configure the directive that contains the
WSGI configuration to use SSL.gunicornThe following command usesgunicornto startpypiservergunicorn-w4'pypiserver:app(root="/home/ralf/packages")'or when using multiple rootsgunicorn-w4'pypiserver:app(root=["/home/ralf/packages", "/home/ralf/experimental"])'pastepasteallows to run multiple WSGI applications
under different URL paths. Therefore, it is possible to serve different set
of packages on different paths.The following examplepaste.inicould be used to serve stable and
unstable packages on different paths[composite:main]use=egg:Paste#urlmap/unstable/=unstable/=stable[app:stable]use=egg:pypiserver#mainroot=~/stable-packages[app:unstable]use=egg:pypiserver#mainroot=~/stable-packages~/unstable-packages[server:main]use=egg:gunicorn#mainhost=0.0.0.0port=9000workers=5accesslog=-Note
You need to install some more dependencies for this to work, like::pipinstallpastepastedeploygunicornpypiserverThe server can then start withgunicorn_pasterpaste.iniBehind a Reverse ProxyYou can runpypiserverbehind a reverse proxy as well.NginxExtend your nginx configurationupstreampypi{serverpypiserver.example.com:12345fail_timeout=0;}server{server_namemyproxy.example.com;location/{proxy_set_headerHost$host:$server_port;proxy_set_headerX-Forwarded-Proto$scheme;proxy_set_headerX-Real-IP$remote_addr;proxy_passhttp://pypi;}}As of pypiserver 1.3, you may also use theX-Forwarded-Hostheader in your
reverse proxy config to enable changing the base URL. For example if you
want to host pypiserver under a particular path on your serverupstreampypi{serverlocalhost:8000;}server{location/pypi/{proxy_set_headerX-Forwarded-Host$host:$server_port/pypi;proxy_set_headerX-Forwarded-Proto$scheme;proxy_set_headerX-Forwarded-For$proxy_add_x_forwarded_for;proxy_set_headerX-Real-IP$remote_addr;proxy_passhttp://pypi;}}Supporting HTTPSUsing a reverse proxy is the preferred way of getting pypiserver behind
HTTPS. For example, to put pypiserver behind HTTPS on port 443, with
automatic HTTP redirection, usingnginxupstreampypi{serverlocalhost:8000;}server{listen80default_server;server_name_;return301https://$host$request_uri;}server{listen443ssl;server_namepypiserver.example.com;ssl_certificate/etc/star.example.com.crt;ssl_certificate_key/etc/star.example.com.key;ssl_protocolsTLSv1TLSv1.1TLSv1.2;ssl_ciphersHIGH:!aNULL:!MD5;location/{proxy_set_headerHost$host:$server_port;proxy_set_headerX-Forwarded-Proto$scheme;proxy_set_headerX-Real-IP$remote_addr;proxy_passhttp://pypi;}}Please seenginx's HTTPS docs for more details.Getting and keeping your certificates up-to-date can be simplified using,
for example, usingcertbot and letsencrypt.TraefikIt is also possible to useTraefikto put pypiserver behind HTTPS on port 443, with
automatic HTTP redirection using Docker Compose. Please see the provideddocker-compose.ymlexample for more information.Utilizing the APIIn order to enable ad-hoc authentication-providers or to use WSGI-servers
not supported bybottleout-of-the-box, you needed to launchpypiservervia its API.The main entry-point for configuringpypiserveris thepypiserver:app()function.  This function returns the internal WSGI-app that you my then
send to any WSGI-server you like.To get allpypiserver:app()keywords and their explanations, read the
functionpypiserver:default_config()Finally, to fire-up a WSGI-server with the configured app, invoke
thebottle:run(app, host, port, server)function.
Note thatpypiserverships with its own copy ofbottle; to use it,
import it like that:from pypiserver import bottleUsing Ad-Hoc Authentication ProvidersTheautherkeyword ofpypiserver:app()function maybe set only using
the API. This can be any callable that returns a boolean when passed
theusernameand thepasswordfor a given request.For example, to authenticate users based on the/etc/passwdfile under Unix,
you may delegate such decisions to thepython-pamlibrary by following
these steps:Ensurepython-pammodule is installedpip install python-pamCreate a python-script along these lines$cat>pypiserver-start.pyimportpypiserverfrompypiserverimportbottleimportpamapp=pypiserver.app(root='./packages',auther=pam.authenticate)bottle.run(app=app,host='0.0.0.0',port=80,server='auto')[Ctrl+D]Invoke the python-script to start-uppypiserver$pythonpypiserver-start.pyNote
Thepython-pammodule, requiresreadaccess to/etc/shadowfile;
you may add the user under whichpypiserverruns into theshadowgroup, with a command like this:sudo usermod -a -G shadow pypy-user.Use with MicroPythonThe MicroPython interpreter for embedded devices can install packages with the
moduleupip.py. The module uses a specialized json-endpoint to retrieve
package information. This endpoint is supported bypypiserver.It can be tested with the UNIX port ofmicropythoncdmicropythonports/unix/micropython-mtools.upipinstall-ihttp://my-server:8080-p/tmp/mymodulesmicropython-foobarInstalling packages from the REPL of an embedded device works in this way:importnetworkimportupipsta_if=network.WLAN(network.STA_IF)sta_if.active(True)sta_if.connect('<your ESSID>','<your password>')upip.index_urls=["http://my-server:8080"]upip.install("micropython-foobar")Further information on micropython-packaging can be found here:https://docs.micropython.org/en/latest/reference/packages.htmlCustom Health Check Endpointpypiserverprovides a default health endpoint at/health. It always returns200 Okif the service is up. Otherwise, it means that the service is not responsive.In addition,pypiserverallows users to customize the health endpoint.
Alphanumeric characters, hyphens, forward slashes and underscores are allowed
and the endpoint should not overlap with any existing routes.
Valid examples:/healthz,/health/live-1,/api_health,/action/healthConfigure a custom health endpoint by CLI argumentsRun pypiserver with--health-endpointargument:pypi-serverrun--health-endpoint/action/healthConfigure a custom health endpoint by scriptimportpypiserverfrompypiserverimportbottleapp=pypiserver.app(root="./packages",health_endpoint="/action/health")bottle.run(app=app,host="```pythonimportpypiserverfrompypiserverimportbottleapp=pypiserver.app(root="./packages",health_endpoint="/action/health")bottle.run(app=app,host="0.0.0.0",port=8080,server="auto")Trycurlhttp://localhost:8080/action/healthSourcesTo create a copy of the repository, usegitclonehttps://github.com/pypiserver/pypiserver.gitcdpypiserverTo receive any later changes, in the above folder use:gitpullKnown Limitationspypiserverdoes not implement the full API as seen onPyPI. It
implements just enough to makeeasy_install,pip install, andsearchwork.The following limitations are known:Commandpypi -Uthat compares uploaded packages withpypito see if
they are outdated, does not respect a http-proxy environment variable
(see#19.It accepts documentation uploads but does not save them to
disk (see#47for a
discussion)It does not handle misspelled packages aspypi-repodoes,
therefore it is suggested to use it with--extra-index-urlinstead
of--index-url(see#38).Please use Github'sbugtrackerfor other bugs you find.Similar ProjectsThere are lots of other projects, which allow you to run your own
PyPI server. Ifpypiserverdoesn't work for you, the following are
among the most popular alternatives:devpi-server:
a reliable fast pypi.org caching server, part of
the comprehensivegithub-style pypi index server and packaging meta tool.
(version: 2.1.4, access date: 8/3/2015)Check this SO question:How to roll my own pypiUnmaintained or archivedThese projects were once alternatives to pypiserver but are now either unmaintained or archived.pip2pia simple cmd-line tool that builds a PyPI-compatible local folder from pip requirementsflask-pypi-proxyA proxy for PyPI that also enables uploading custom packages.Related SoftwareThough not direct alternatives forpypiserver's use as an index
server, the following is a list of related software projects that you
may want to familiarize with:pypi-uploader:
A command-line utility to upload packages to yourpypiserverfrom pypi without
having to store them locally first.twine:
A command-line utility for interacting with PyPI orpypiserver.warehouse:
the software that powersPyPIitself. It is not generally intended to
be run by end-users.Licensingpypiservercontains a copy ofbottlewhich is available under the
MIT license, and the remaining part is distributed under the zlib/libpng license.
See theLICENSE.txtfile.