Files
Nixos_Fleet/installer/install.sh
T
DamienandClaude Sonnet 5 77b089bc45 Persiste la config sur /etc/nixos à l'install, firmware wifi, wallpaper par défaut
- install.sh: copie le repo (clone substitué) vers /mnt/etc/nixos après
  nixos-install, sinon la machine installée n'a aucun fichier à éditer
- base.nix: hardware.enableRedistributableFirmware pour les cartes wifi
  nécessitant un firmware non-libre
- desktop.nix: fond d'écran NixOS par défaut via dconf (n'existait pas)

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-09 16:53:08 +02:00

227 lines
9.5 KiB
Bash

# Pas de shebang ici : ce fichier est injecté comme corps de script par
# pkgs.writeShellScriptBin dans installer-base.nix (qui ajoute juste
# `#!...`, PAS de mode strict — d'où le `set` explicite ci-dessous : sans
# lui, une erreur (ex: DNS indisponible) n'arrête pas le script, qui
# continuait jusqu'au reboot final en masquant l'échec.
set -euo pipefail
# Installeur unique pour les deux repos :
# - branche "flotte" -> nixos_fleet (public, jamais chiffré)
# - branche "utilisateur nommé" -> nixos_users (privé, chiffrement au choix)
# Ce script ne contient aucun secret : le token du repo privé est saisi en
# direct, jamais stocké dans ce fichier ni dans un repo git.
FLEET_REPO="git+https://gitea.miniclic.net/Damien/Nixos_Fleet.git"
USERS_REPO_HOST="gitea.miniclic.net"
USERS_REPO_PATH="Damien/Nixos_Users.git"
# Le script se lance dès le login (autologin), potentiellement avant que
# NetworkManager ait fini de négocier le DHCP. On attend une route par
# défaut avant de continuer (jusqu'à 30s), plutôt que d'échouer trop tôt.
echo "Attente du réseau..."
for _ in $(seq 1 30); do
ip route | grep -q '^default' && break
sleep 1
done
# Installe en 4 étapes séparées (clone -> partition -> swap sur le disque
# cible -> vrai build) au lieu d'un seul `disko-install`. Raison : disko-
# install fait tout d'un coup dans le tmpfs RAM de l'environnement live,
# qui sature sur les PC à peu de RAM (4 Go) avant même de toucher le
# disque cible. Un swapfile posé sur /mnt (une fois partitionné) donne
# accès aux ~200 Go du disque comme mémoire virtuelle pendant la vraie
# construction — méthode documentée officiellement pour RAM limitée
# (wiki.nixos.org/wiki/Swap, manuel NixOS section installation).
#
# Le clone local est nécessaire car la commande `disko` seule (contrairement
# à `disko-install`) n'a AUCUN mécanisme de substitution de disque nommé
# (`--disk`/diskMappings n'existe que dans install-cli.nix, utilisé
# uniquement par disko-install — vérifié dans le code source de
# nix-community/disko : fichiers disko, disko-install, cli.nix). On substitue
# donc le vrai disque directement dans une copie locale du fichier disko
# avec sed, puis on pointe `disko` ET `nixos-install` sur ce même clone
# (chemin local, pas l'URL distante) pour que le partitionnement et le
# système construit restent cohérents entre eux.
do_install() {
local remote_url="$1" # URL flake (git+https://...), pour cloner
local attr="$2"
local disko_rel_path="$3" # diskos/plain.nix ou diskos/luks.nix
local repo_dir="/tmp/install-repo"
local clone_url="${remote_url#git+}" # git clone ne comprend pas le préfixe git+
echo "Récupération de la config ($attr)..."
rm -rf "$repo_dir"
git clone --depth 1 "$clone_url" "$repo_dir"
echo "Substitution du disque cible dans la config disko..."
sed -i "s#/dev/placeholder#$DEVICE#" "$repo_dir/$disko_rel_path"
echo "Partitionnement de $DEVICE..."
# --yes-wipe-all-disks : évite la confirmation interactive "type yes to
# continue" (vu dans le code source de la commande disko) — un install
# de flotte ne doit pas dépendre de quelqu'un présent au clavier pour
# confirmer, l'effacement est le but assumé de ce script.
nix run --no-write-lock-file --refresh 'github:nix-community/disko' -- \
--mode destroy,format,mount \
--yes-wipe-all-disks \
"$repo_dir/$disko_rel_path"
echo "Swap temporaire sur le disque cible (RAM limitée sur certains PC du parc)..."
# Sur btrfs (notre système de fichiers), le CoW doit être désactivé
# (chattr +C) AVANT toute écriture de données dans le fichier, sinon
# swapon échoue avec "Invalid argument" (source : btrfs.readthedocs.io/
# en/latest/Swapfile.html — chattr +C sur un fichier déjà écrit ne
# s'applique pas rétroactivement).
truncate -s 0 /mnt/.install-swapfile
chattr +C /mnt/.install-swapfile
fallocate -l 4G /mnt/.install-swapfile
chmod 600 /mnt/.install-swapfile
mkswap /mnt/.install-swapfile
swapon /mnt/.install-swapfile
echo "Construction et installation du système (peut prendre plusieurs minutes)..."
# --no-channel-copy, --no-root-passwd : confirmés dans le man nixos-install
# (mankier.com/8/nixos-install, miroir du manuel officiel). Le mot de
# passe root est de toute façon déjà déclaré (initialPassword) dans la
# config cible, --no-root-passwd évite juste tout risque de prompt
# interactif qui bloquerait un install non surveillé. --flake pointe sur
# le clone local (avec le disque déjà substitué), pas l'URL distante,
# pour rester cohérent avec ce qui a été partitionné.
nixos-install --root /mnt --flake "${repo_dir}#${attr}" --no-channel-copy --no-root-passwd
swapoff /mnt/.install-swapfile
rm -f /mnt/.install-swapfile
# Sans cette étape, la machine installée n'a AUCUNE config sur son
# disque : le clone ci-dessus vit dans /tmp de l'environnement live, en
# RAM, effacé au reboot. La convergence auto (system.autoUpgrade, voir
# hosts/common/base.nix) continue de fonctionner sans ça (elle pointe
# sur l'URL distante), mais un technicien qui arrive sur la machine
# après coup n'a alors ni /etc/nixos, ni moyen d'ajouter/enlever un
# paquet à la main. On installe donc le même clone (déjà substitué avec
# le vrai disque) à l'emplacement standard NixOS, en conservant .git
# pour que `git pull`/`git log` marchent dessus normalement ensuite.
echo "Installation de la configuration dans /mnt/etc/nixos..."
rm -rf /mnt/etc/nixos
mkdir -p /mnt/etc
cp -a "$repo_dir" /mnt/etc/nixos
# Le disque cible a été substitué localement (sed plus haut) : ce fichier
# diffère donc de ce qui est sur git (placeholder). On le committe en
# local (jamais poussé) pour que `git status` reste propre sur la
# machine installée -- sinon chaque `git pull` ultérieur affiche un
# fichier modifié, source de confusion pour un technicien.
git -C /mnt/etc/nixos \
-c user.name="Installeur Nixos_Fleet" \
-c user.email="installeur@nixos-fleet.local" \
commit -aqm "Substitution locale du disque cible ($DEVICE)"
INSTALLED_ATTR="$attr"
}
echo "=== Installeur Nixos_Fleet ==="
echo "1) PC de la flotte (générique)"
echo "2) Poste utilisateur nommé"
read -rp "Choix [1/2] : " CHOICE
# --- Détection automatique du disque cible -------------------------------
# On exclut les disques amovibles (la clé USB de boot elle-même) et les
# loop/rom. S'il en reste plusieurs (rare), on prend le plus gros et on le
# signale clairement dans les logs plutôt que de bloquer sur un menu.
echo
echo "Détection du disque cible..."
mapfile -t CANDIDATES < <(
lsblk -dn -b -o NAME,TYPE,RM,SIZE |
awk '$2 == "disk" && $3 == 0 { print $4, $1 }' |
sort -rn
)
if [ "${#CANDIDATES[@]}" -eq 0 ]; then
echo "Aucun disque fixe détecté. Abandon." >&2
exec bash
fi
DEVICE="/dev/$(echo "${CANDIDATES[0]}" | awk '{print $2}')"
if [ "${#CANDIDATES[@]}" -gt 1 ]; then
echo "ATTENTION : plusieurs disques fixes détectés, le plus gros a été retenu : $DEVICE"
printf ' %s\n' "${CANDIDATES[@]}"
else
echo "Disque retenu : $DEVICE"
fi
case "$CHOICE" in
1)
# --- Branche flotte : rien d'autre à saisir -----------------------
echo
echo "Installation du profil générique 'usagers' sur $DEVICE..."
do_install "$FLEET_REPO" "usagers" "diskos/plain.nix"
;;
2)
# --- Branche utilisateur nommé -------------------------------------
read -rp "Utilisateur (thomas/clara/jade/oreo) : " USER_PROFILE
USER_PROFILE=$(echo "$USER_PROFILE" | tr '[:upper:]' '[:lower:]' | xargs)
case "$USER_PROFILE" in
thomas|clara|jade|oreo) ;;
*)
echo "Utilisateur inconnu : $USER_PROFILE" >&2
exec bash
;;
esac
read -rp "Chiffrer le disque ? [o/N] : " ENCRYPT
ATTR="$USER_PROFILE"
if [[ "$ENCRYPT" =~ ^[oOyY] ]]; then
ATTR="${USER_PROFILE}-luks"
fi
read -rsp "Token Gitea (repo privé Nixos_Users) : " TOKEN
echo
# Le token n'est utilisé qu'en mémoire/ligne de commande pour ce fetch
# ponctuel : il n'est jamais écrit dans un fichier suivi par git.
AUTHED_URL="git+https://${TOKEN}@${USERS_REPO_HOST}/${USERS_REPO_PATH}"
echo
echo "Installation du profil '$ATTR' sur $DEVICE..."
DISKO_REL_PATH="diskos/plain.nix"
if [[ "$ATTR" == *-luks ]]; then
echo "Disque chiffré : disko va demander une passphrase LUKS pendant le partitionnement."
DISKO_REL_PATH="diskos/luks.nix"
fi
do_install "$AUTHED_URL" "$ATTR" "$DISKO_REL_PATH"
# Le système installé doit pouvoir continuer à tirer ses mises à jour
# du repo privé tout seul : on lui laisse un netrc, jamais commité,
# jamais dans le Nix store (nix.settings.netrc-file dans le repo
# nixos_users pointe vers ce même chemin).
#
# ATTENTION : le format exact attendu par Gitea (login=token vs
# login+password séparés) dépend de la version/config du serveur —
# à vérifier sur l'instance réelle avant le déploiement pilote.
mkdir -p /mnt/etc/nix
{
echo "machine ${USERS_REPO_HOST}"
echo "login ${TOKEN}"
echo "password x-oauth-basic"
} > /mnt/etc/nix/netrc
chmod 600 /mnt/etc/nix/netrc
;;
*)
echo "Choix invalide." >&2
exec bash
;;
esac
echo
echo "Installation terminée."
echo "Config installée dans /etc/nixos (attribut : ${INSTALLED_ATTR})."
echo "Pour ajouter/enlever un paquet après le premier démarrage :"
echo " 1. éditer les fichiers dans /etc/nixos"
echo " 2. nixos-rebuild switch --flake /etc/nixos#${INSTALLED_ATTR}"
echo "Redémarrage dans 10s (Ctrl-C pour annuler et inspecter /mnt)..."
sleep 10
reboot