- 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 access
sudo addgroup --system --gid 9898 pypiserver
sudo adduser --uid 9898 --ingroup pypiserver --system --no-create-home pypiserver
sudo mkdir data/packages
sudo chown -R pypiserver:pypiserver data/packages
sudo 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.node-energy https://pypi.node.energy/ # no simple!
poetry config http-basic.node-energy <username> # this will then ask for the password
Now you can publish the package
poetry publish -r node-energy
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 = "node-energy"
url = "https://pypi.node.energy/simple"
priority = "explicit"
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:pass@pypi.node.energy/
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: