Historischer Beitrag vom 6. Januar 2023, für den Neubau übersetzt und überarbeitet. Das Beispiel verwendete pypiserver 1.5.1; die aktuelle Einrichtung kann abweichen. Prüfe vor dem Einsatz die Dokumentation von pypiserver.

Manchmal möchte man ein eigenes Python-Paketrepository im lokalen Netz betreiben – zum Beispiel, um Pakete zwischen Entwicklungs- und Zielrechner zu verteilen, ohne sie öffentlich hochzuladen. Statt Dateien von Hand zu kopieren, kann pip die Installation übernehmen.

Dieses Beispiel baut auf der Dokumentation von pypiserver auf und lief bei mir auf einem Raspberry Pi 3. Voraussetzungen sind Python 3, venv und pip; ein bisschen Wissen über Python-Paketierung hilft ebenfalls.

Vorbereiten

Zuerst aktualisieren wir die Pakete:

sudo apt update
sudo apt upgrade

Dann legen wir ohne sudo eine virtuelle Umgebung an und installieren pypiserver und passlib:

mkdir -p app
cd app
python3 -m venv ./pypiserver
cd pypiserver
source ./bin/activate
python -m pip install pypiserver passlib
mkdir packages
pypi-server --version

Im ursprünglichen Beispiel meldete der Server Version 1.5.1. Als Nächstes legen wir ein Login an. Achtung: -c erstellt die Datei neu und überschreibt eine bestehende Passwortdatei.

htpasswd -sc htpasswd.txt pypiuser

Das Passwort wird interaktiv abgefragt. Fehlt htpasswd, kann auf Debian-basierten Systemen das Paket apache2-utils installiert werden. Keine echten Passwörter in einen fremden Online-Generator eingeben.

Server starten

pypi-server run -p 8080 -P htpasswd.txt ./packages

Auf dem Raspberry Pi lässt sich der Server unter http://localhost:8080 prüfen. Das ist nur ein Test. HTTP verschlüsselt weder Zugangsdaten noch Pakete; für Zugriffe über das Netzwerk brauchen wir eine passende HTTPS-Konfiguration und Zugriffsbeschränkungen. Nicht ungeprüft ins Internet stellen.

Startseite des lokalen Paketservers
Die Startseite des Servers im ursprünglichen Beispiel.

Pakete hochladen

Auf dem Entwicklungsrechner können wir ein vorbereitetes Paket bauen, prüfen und mit Twine hochladen. build und twine müssen dort installiert sein; die Paketkonfiguration liegt im Projekt. Die Adresse ist ein Platzhalter für den eigenen, per HTTPS erreichbaren Server. Twine fragt das Passwort ab, statt es als Kommandozeilenargument zu speichern:

python -m build -o ./build
python -m twine check build/*
python -m twine upload --repository-url https://DEIN-SERVER:8080 build/* -u pypiuser
Ausgabe nach einem Paket-Upload
Ein erfolgreicher Upload im ursprünglichen Beispiel.

Installation testen

Und jetzt ein Probelauf mit pip. Wieder die eigene Serveradresse und den Paketnamen einsetzen:

python -m pip install --index-url https://DEIN-SERVER:8080/simple/ PACKAGENAME --dry-run

Das war's: Pakete lokal verteilen und dabei pip verwenden. Authentifizierung, TLS und die aktuelle Serverkonfiguration bitte passend zur eigenen Umgebung einrichten.