- Deploy a droplet on Digital Ocean having Docker preinstalled (one click apps). The cheapest one will do the job for us.
- Set your DNS records up, so you have a URL for that IP (required for Let's encrypt)
- ssh into it
- Clone this repository and cd into it
- Install
htpasswd
to setup http authentication:apt install apache2-utils
- Create folder to store packages, create
pypiserver
user and group and give them accessaddgroup --gid 9898 —system pypiserver
adduser --uid 9898 --ingroup pypiserver --system —no-create-home pypiserver
mkdir data/packages
chown -R pypiserver:pypiserver data/packages
chmod g+s data/packages
Next, you need to create a .htpasswd
file to restrict access to the server:
htpasswd -c config/nginx/auth/.htpasswd username
If you want to add more users, call
htpasswd config/nginx/auth/.htpasswd second_username
Now it's time to get a SSL certificate. There is a chicken and egg problem involved here.
You need to have a certificate for nginx to start but you need nginx to be running to serve the challenge required by Let's Encrypt.
Luckily wmnnd wrote a script that solves this issue.
It's part of this repository, so you can simply run ./init-letsencrypt.sh
.
Finally you can start the server. It's as simple as docker-compose up -d
.
You don't want to ssh into the server every time the server did a reboot. The easiest way to ensure it auto starts on system boot is setting up a systemd service. This repository contains a configuration for that service. You can enable it by:
cp docker-compose-privatepypi.service /etc/systemd/system/
systemctl enable docker-compose-privatepypi
To upgrade the dependencies, run docker-compose pull && docker-compose down && docker-compose up -d
Update version number in pyproject.toml
, then
poetry build
Make sure poetry is configured to have access to that PyPI.
poetry config repositories.nodeenergy https://pypi.node.energy/ # no simple!
poetry config http-basic.nodeenergy username password
Now you can publish the package
poetry publish -r nodeenergy
python setup.py sdist bdist_wheel
Somehow reading from environment variables didn't work for me, at least not locally.
twine upload dist/* --repository-url $TWINE_REPOSITORY_URL -u $TWINE_USERNAME -p $TWINE_PASSWORD
By default the private PyPI server will fallback to the https//pypi.org/ if the desired package is not found. Therefore you'll want to name your packages in a way they don't clash with existing packages on PyPI. Otherwise this can become a source of hard to track bugs because a possibly failing install won't fail loudly.
Add this to the pyproject.toml
[[tool.poetry.source]]
name = "nodeenergy"
url = "https://pypi.node.energy/simple/"
and make sure you configured poetry to have access to the credentials (see section for uploading above).
Configure Pipfile similar to this:
[[source]]
name = "node-energy"
verify_ssl = true
url = "https://${PRIVATE_PYPI_USERNAME}:${PRIVATE_PYPI_PASSWORD}@pypi.node.energy"
and set the user and password environment variables on your system. Now you can install packages from the private PyPI via:
pipenv install package-name --index node-energy
Alternatively, you can install it without configuring the index in Pipfile
:
pipenv install package-name --index https://user:[email protected]/
This will store your credentials in clear text in your Pipfile
and Pipfile.lock
, so you should rather not do this.
pip install -f https://pypi.node.energy/packages package-name
This will ask you for your username and password.
Thanks for inspiration: