Guix sur Android

par Julien Lepiller — dim. 29 avril 2018

Il y a quelques jours, j'ai publié un article sur le blog de Guix. Aujourd'hui, je vous propose d'en lire un traduction.

L'année dernière, je me suis dit que puisque mon téléphone n'était qu'un ordinateur qui faisait tourner un système d'exploitation, Android (ou Replicant !), et qu'Android est basé sur un noyau Linux, ce n'était rien d'autre qu'une distribution externe sur laquelle sur laquelle je pouvais installer GNU Guix, pas vrai ? Il se trouve que j'avais bien raison. Aujourd'hui, une discussion sur IRC m'a rappelé ma tentative d'installation de GNU Guix sur mon téléphone. D'où cet article. Je vais essayer de vous donner les connaissances et les commandes requises pour l'installer sur votre propre system android.

Les commandes que je donne ici peuvent ne pas fonctionner sur votre téléphone. La moindre fausse manip' peut bloquer votre téléphone, soyez très prudent.

Prérequis

Tout d'abord, vous aurez besoin d'un appareil où Android ou Replicant est installé. Comme toutes les installation de GNU Guix, vous aurez besoin des privilèges root sur l'appareil. Malheureusement, ce n'est pas souvent le cas dans le monde d'Android. Ensuite vous devrez utiliser un cable pour connecter votre ordinateur à votre téléphone. Une fois que vous avez le matériel, vous aurez besoin d'adb (Android Debugging Bridge) :

guix package -i adb

Explorer l'appareil

Tous les appareils Android ont leur propre disposition de partitions, mais en gros il y a :

  1. Une partition de démarrage pour démarrer l'appareil
  2. Une partition de récupération pour démarrer l'appareil en mode de secours
  3. Une partition de données pour les données de l'utilisateur, dont les applications, les fichiers utilisateurs etc
  4. Une partition système qui contient le système de base et les applications. C'est par exemple là que les compagnies téléphoniques placent leurs propres applications pour que vous ne puissiez pas les enlever
  5. Une partition vendeur pour les pilotes
  6. D'autres partitions

Pendant le processus de démarrage, le chargeur d'amorçage recherche la partition de démarrage. Elle ne contient pas un système de fichier, mais seulement une archive cpio compressée (l'image de démarrage) et le noyau. Le chargeur d'amorçage les charge en mémoire et le noyau démarre sur l'image de démarrage. Ensuite, le système d'initialisation de l'image de démarrage charge les partitions dans le répertoire correspondant : la partition système dans /system, la partition vendeur dans /vendor et la partition de données dans/data. D'autres partitions peuvent être chargées.

Et c'est tout. Le système de fichier racine d'Android est en fait l'image de démarrage, donc toute modification de son contenu sera perdue après un redémarrage. Heureusement (?), les appareils Android ne sont généralement pas redémarrés souvent.

Un autre problème est posé par la bibliothèque C d'Android, nommée Bionic : elle a moins de fonctionnalités et fonctionne très différemment de la bibliothèque C de GNU. Comme Guix est construit avec la Glibc, nous allons devoir travailler pour la faire fonctionner sur notre appareil.

Installer les fichiers nécessaires

Nous allons suivre le guide d'installation binaire. Mon appareil a un processeur aarch64, donc j'ai téléchargé la version binaire correspondante.

Maintenant il est temps de commencer à utiliser adb. Connectez votre appareil et obtenez les privilèges root pour adb. Vous pourriez avoir besoin d'autoriser votre ordinateur sur votre téléphone :

adb root

Maintenant, nous allons transférer certains fichiers nécessaires :

adb push guix-binary-* /data

# Glibc a besoin de ces deux fichiers pour le réseau.
adb push /etc/protocols /system/etc/
adb push /etc/services /system/etc/

# … et de celui-ci pour effectuer des requêtes DNS.  Vous devrez sans doute
# changer les serveurs de noms si vous utilisez votre connexion mobile.
adb push /etc/resolv.conf /system/etc/

Remarquez que certains appareils n'ont pas /system/etc. Dans ce cas, /etc peut être disponible. Si aucun n'est présent, créez le répertoire avec adb shell pour récupérer un shell sur votre appareil, puis poussez les fichiers vers ce nouveau répertoire.

Installer Guix lui-même

Maintenant tous les fichiers nécessaires sont présents sur l'appareil, donc nous pouvons nous y connecter :

adb shell

Depuis ce shell, nous allons installer Guix. Le système de fichier racine est monté en lecture-seule car ça ne fait aucun sens d'essayer de le modifier. Rappelez-vous : c'est une image en RAM. Remontez-la en lecture-écriture et créez les répertoires nécessaires :

mount -o remount,rw /
mkdir /gnu /var
mount -o remount,ro /

Maintent, nous ne pouvons pas simplement copier le contenu de l'archive binaire vers ces répertoires car l'image de démarrage a une taille limitée. Guix se plaint si /gnu ou /gnu/store est un lien symbolique. Une solution consiste à installer le contenu de l'archive binaire sur une partition existante (parce qu'on ne peut pas modifier facilement le partitionnement) qui a suffisament d'espace libre, typiquement la partition de données. Ensuite cette partition est montée sur /var et /gnu.

Avant cela, vous devrez trouver la partition de données sur votre system. Lancez simplement mount | grep /data pour la trouver.

Nous montons la partition, extrayons l'archive et déplaçons le contenu à son emplacement final :

mount /dev/block/bootdevice/by-name/userdata /gnu
mount /dev/block/bootdevice/by-name/userdata /var
cd /data
tar xf guix-binary-...
mv gnu/store .
mv var/guix .
rmdir gnu
rmdir var

Finalement, nous allons devoir créer des utilisateurs et des groupes pour que Guix fonctionne correctement. Comme Bionic n'utilise ni /etc/passwd ni /etc/group pour stocker les utilisateurs, nous allons devoir les créér de toute pièce. Remarquez l'ajout de l'utilisateur et du groupe root, ainsi que de l'utilisateur nobody.

# crée les utilisateur pour guix et root pour la glibc
cat > /etc/passwd << EOF
root:x:0:0:root:/data:/sbin/sh
nobody:x:99:99:nobody:/:/usr/bin/nologin
guixbuilder01:x:994:994:Guix build user 01:/var/empty:/usr/bin/nologin
guixbuilder02:x:993:994:Guix build user 02:/var/empty:/usr/bin/nologin
guixbuilder03:x:992:994:Guix build user 03:/var/empty:/usr/bin/nologin
guixbuilder04:x:991:994:Guix build user 04:/var/empty:/usr/bin/nologin
guixbuilder05:x:990:994:Guix build user 05:/var/empty:/usr/bin/nologin
guixbuilder06:x:989:994:Guix build user 06:/var/empty:/usr/bin/nologin
guixbuilder07:x:988:994:Guix build user 07:/var/empty:/usr/bin/nologin
guixbuilder08:x:987:994:Guix build user 08:/var/empty:/usr/bin/nologin
guixbuilder09:x:986:994:Guix build user 09:/var/empty:/usr/bin/nologin
guixbuilder10:x:985:994:Guix build user 10:/var/empty:/usr/bin/nologin
EOF

cat > /etc/group << EOF
root:x:0:root
guixbuild:x:994:guixbuilder01,guixbuilder02,guixbuilder03,guixbuilder04,guixbuilder05,guixbuilder06,guixbuilder07,guixbuilder08,guixbuilder09,guixbuilder10
EOF

Lancer Guix

Tout d'abord, nous installons le profil de root quelque part :

export HOME=/data
ln -sf /var/guix/profiles/per-user/root/guix-profile          $HOME/.guix-profile

Nous pouvons maintenant lancer le démon Guix. Il est impossible de « chrooter » sur mon téléphone donc j'ai du le désactiver :

export PATH="$HOME/.guix-profile/bin:$HOME/.guix-profile/sbin:$PATH"
guix-daemon --build-users-group=guixbuild --disable-chroot &

Pour finir, c'est une bonne idée d'autoriser les substituts depuis hydra :

mkdir /etc/guix
guix archive --authorize <   $HOME/.guix-profile/share/guix/hydra.gnu.org.pub

Profitez !

Travail restant

Et voilà, on peut maintenant profiter du gestionnaire de paquets Guix sur Android ! Un des inconvénients, c'est qu'après un redémarrage on devrait refaire la moitié des étapes : recréer /var et /gnu, monter les partitions dessus. À chaque fois que vous lancez un shell, vous devrez ré-exporter le PATH pour pouvoir utiliser guix. Vous devrez lancer le démon guix-daemon manuellement. Pour résoudre tous ces problèmes d'un coup, vous devriez modifier l'image de démarrage. C'est compliqué et j'ai déjà tenté le coup, mais le téléphone a fini sur une boucle de redémarrage après avoir flashé l'image modifiée. Les bénévoles de #replicant suggéraient de souder un cable pour accéder à une console série où les messages de débogages seraient présents. Voyons combien de doigts je brule avant d'arriver à démarrer une image de démarrage personnalisée !