Featured image of post 0x05 - Miroir Python local : créer un miroir offline optimisé

0x05 - Miroir Python local : créer un miroir offline optimisé

Découvrez comment mettre en place un miroir Python local sécurisé et filtré pour votre infrastructure isolée ; simplifiez la gestion des packages et gagnez de la place.

Présentation de mon architecture

Petite présentation de l’infrastructure dans laquelle ce projet va se dérouler.

Je travaille dans une infra complètement coupée d’internet, donc il faut mettre à disposition des utilisateurs un miroir Python en interne. Je vais installer ce miroir sur une LXC qui sera la seule à pouvoir accéder à internet. Évidemment, je configure dessus un firewall qui bloque tous les ports inutiles. De plus, après la synchronisation, je coupe totalement l’accès vers l’extérieur en désactivant virtuellement l’interface ethernet.

Création du miroir

J’ai décidé dès le départ que tout mon miroir Python serait stocké dans /DATA/MIRROR-PYTHON. Comme ce répertoire n’existe pas encore, je vais donc le créer.

1
mkdir -p /DATA/MIRROR-PYTHON

Installation du package

Pour ce projet, je vais utiliser le package bandersnatch. C’est ce package qui va télécharger les packages Python et créer la bonne arborescence du miroir en local. Pour l’installer, j’utilise la commande suivante :

1
pip3 install bandersnatch

Modification de la configuration

Voici un exemple de configuration que j’ai utilisé dans mon cas. Nous allons la détailler un peu plus loin :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
cat /etc/bandersnatchconf
[mirror]
directory = /DATA/MIRROR-PYTHON
master = https://pypi.org
workers = 3
timeout = 1500000
global-timeout = 1800000
stop-on-error = false

[plugins]
enabled =
        exclude_platform
        allowlist_project
        allowlist_release

[blocklist]
platforms =
        windows
        macos
        freebsd
        #linux
        py2.4
        py2.5
        py2.6
        #py2.7
        py3.1
        py3.2
        py3.3
        #py3.4
        py3.5
        #py3.6
        py3.7
        #py3.8
        #py3.9
        py3.10
        py3.11
        py3.12

[allowlist]
packages =
        Django

Dans cet exemple, je bloque toutes les versions de Python sauf : linux, 2.7, 3.4, 3.6, 3.8 et 3.9. De plus, je ne miroir que le package Django. Attention, il faut bien prendre en compte les dépendances : si vos utilisateurs essaient d’installer ce package, cela ne fonctionnera pas si les dépendances ne sont pas aussi présentes dans le miroir.

Petite précision : vous n’êtes pas obligé de laisser tous les packages dans la liste. Plus vous ajoutez de packages, plus la vérification et le téléchargement seront longs, et cela peut vite prendre beaucoup de place sur le disque dur à cause des mises à jour fréquentes. Pour optimiser le temps, ce que je fais personnellement, c’est que lorsqu’un utilisateur me demande un package, je sauvegarde le fichier de configuration, je commente tous les autres packages et j’ajoute uniquement celui demandé (avec ses dépendances) en haut. Cela permet de télécharger uniquement ce package sans vérifier les autres, et il devient disponible plus rapidement pour l’utilisateur. Ensuite, une fois le téléchargement terminé, je décommente les autres packages si besoin.

Vérifier les dépendances

Afin de vérifier que vous avez bien ajouté toutes les dépendances nécessaires dans le fichier de configuration, vous pouvez utiliser un autre serveur ayant accès à Internet et lancer un conteneur Docker temporaire pour exécuter les commandes suivantes :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
docker run -ti --rm -v /tmp:/tmp python:3.6.8 bash

pip install pandas

pip freeze
numpy==1.19.5
pandas==1.1.5
Pillow==8.4.0
python-dateutil==2.9.0.post0
pytz==2025.2
six==1.17.0

Ces lignes ouvrent un conteneur Docker qui sera supprimé dès que vous le quitterez (grâce à --rm). Dans ce conteneur, vous pouvez vérifier quelles dépendances sont installées automatiquement.

Il ne vous reste plus qu’à adapter la version de Python selon vos besoins et à récupérer les noms des packages pour les ajouter dans le fichier de configuration.

Forcer la synchro

Une fois ma configuration terminée, je vais forcer la synchronisation.

1
bandersnatch mirror --force-check

À noter que dans mon cas, les demandes de packages Python sont rares, donc je me permets, comme expliqué plus haut, de faire la synchronisation manuellement. Mais peut-être que dans votre situation, le plus simple serait de mettre en place une synchronisation automatique à intervalle régulier via une crontab.

Création de la crontab

Nous allons maintenant mettre en place une crontab qui va automatiquement démarrer notre serveur web au redémarrage de la machine. Comme ça, en cas de crash, il n’y a rien à faire : tout redémarre tout seul.

1
@reboot         root    sleep 10 && python3 -m http.server -d /DATA/MIRROR-PYTHON/web 7777 &

Configuration du miroir côté client

Enfin, côté client, pour que vos utilisateurs puissent télécharger vos packages sans avoir à modifier leur configuration et que ce soit le plus transparent possible pour eux, vous pouvez ajouter le fichier /etc/pip.conf avec la configuration ci-dessous :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
cat > /etc/pip.conf
[global]
index-url = https://python.mirror.intern/simple
trusted-host = python.mirror.intern

[install]
user = true
# Ctrl + q pour quitter

chmod 744 /etc/pip.conf

Dans mon cas, j’ai mis en place un reverse proxy, c’est pour cela qu’il n’y a pas de port 7777 mais bien du HTTPS. Rien ne vous empêche cependant de remplacer python.mirror.intern par VOTRE_ADRESSE_IP:7777.

Conclusion

Voilà, c’est fini !

J’ai adoré réaliser ce petit projet au travail. L’ancien système était plus complexe : on dupliquait TOUS les packages, ce qui prenait une place démentielle sur nos disques durs alors qu’on utilise seulement certaines versions de Python et quelques packages spécifiques. Je me suis dit que ce serait une bonne idée de créer un miroir en optimisant au maximum l’espace utilisé. Comme on dit dans mon équipe, je suis “un rat de l’espace disque” !

Généré avec Hugo
Thème Stack conçu par Jimmy