#!/usr/bin/env bash # # KAWA OS Installation Script # Ce script est exécuté après le boot de l'ISO KAWA CELL en RAM # Il configure automatiquement la connexion au mesh KAWA et installe le système # # Usage: curl -fsSL https://git.du-senegal.com/kawa_bot/kawa-context/raw/main/install-kawa.sh | bash # set -e # Couleurs pour les messages RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' CYAN='\033[0;36m' NC='\033[0m' # No Color # Bannière KAWA echo -e "${CYAN}" cat << "EOF" ╔═══════════════════════════════════════════════════════════╗ ║ ║ ║ ██╗ ██╗ █████╗ ██╗ ██╗ ██████╗ █████╗ ██████╗ ║ ║ ██║ ██╔╝██╔══██╗██║ ██║ ██╔══██╗██╔══██╗██╔══██╗║ ║ █████╔╝ ███████║██║ ██║ ██████╔╝███████║██████╔╝║ ║ ██╔═██╗ ██╔══██║██║ ██║ ██╔══██╗██╔══██║██╔══██╗║ ║ ██║ ██╗██║ ██║███████╗███████╗██████╔╝██║ ██║██║ ██║║ ║ ╚═╝ ╚═╝╚═╝ ╚═╝╚══════╝╚══════╝╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═╝║ ║ ║ ║ KAWA OS - Installation Automatique ║ ║ Version: 1.0.0 ║ ╚═══════════════════════════════════════════════════════════╝ EOF echo -e "${NC}" # Configuration HEADSCALE_URL="https://headscale.du-senegal.com" HEADSCALE_FALLBACK="http://141.94.23.212" HEADSCALE_AUTHKEY="" GIT_REPO="https://git.du-senegal.com/kawa_bot/kawa-context.git" NAMESPACE="kawa" # Fonctions utilitaires log_info() { echo -e "${GREEN}[INFO]${NC} $1"; } log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; } log_error() { echo -e "${RED}[ERROR]${NC} $1"; } log_step() { echo -e "${BLUE}[STEP]${NC} $1"; } # Détection du hostname detect_hostname() { log_step "Détection du nom d'hôte..." # Générer un hostname basé sur le modèle de machine if [ -f /sys/class/dmi/id/product_name ]; then MODEL=$(cat /sys/class/dmi/id/product_name 2>/dev/null | tr '[:upper:]' '[:lower:]' | tr -d ' ' | cut -c1-20) else MODEL="unknown" fi # Générer un suffixe aléatoire SUFFIX=$(head -c 4 /dev/urandom | xxd -p) # Hostname final HOSTNAME="kawa-${MODEL}-${SUFFIX}" log_info "Hostname détecté: $HOSTNAME" echo "$HOSTNAME" } # Vérification des prérequis check_prereqs() { log_step "Vérification des prérequis..." # Vérifier si on est root if [ "$EUID" -ne 0 ]; then log_error "Ce script doit être exécuté en root" exit 1 fi # Vérifier si on est sur NixOS if [ ! -f /etc/NIXOS ]; then log_warn "Ce script est conçu pour NixOS" fi # Vérifier la connexion réseau if ! ping -c 1 8.8.8.8 >/dev/null 2>&1; then log_error "Pas de connexion réseau" exit 1 fi log_info "Prérequis OK" } # Installation de Tailscale install_tailscale() { log_step "Installation de Tailscale..." # Sur NixOS, utiliser nix-env ou la config if command -v nix-env &> /dev/null; then nix-env -iA nixpkgs.tailscale || log_warn "Tailscale peut déjà être installé" elif command -v apt-get &> /dev/null; then curl -fsSL https://tailscale.com/install.sh | sh else log_error "Impossible d'installer Tailscale" exit 1 fi log_info "Tailscale installé" } # Connexion au mesh KAWA connect_mesh() { log_step "Connexion au mesh KAWA..." local HOSTNAME="$1" # Démarrer tailscaled log_info "Démarrage de tailscaled..." tailscaled 2>/dev/null & sleep 3 # Essayer le serveur principal log_info "Connexion à $HEADSCALE_URL..." if tailscale up --login-server="$HEADSCALE_URL" --authkey="$HEADSCALE_AUTHKEY" --hostname="$HOSTNAME" 2>/dev/null; then log_info "Connecté au mesh KAWA via $HEADSCALE_URL" else # Fallback log_warn "Échec de connexion, essai du fallback $HEADSCALE_FALLBACK..." if tailscale up --login-server="$HEADSCALE_FALLBACK" --authkey="$HEADSCALE_AUTHKEY" --hostname="$HOSTNAME" 2>/dev/null; then log_info "Connecté au mesh KAWA via $HEADSCALE_FALLBACK" else log_error "Impossible de se connecter au mesh KAWA" log_info "Vérifiez votre connexion réseau et réessayez" exit 1 fi fi # Attendre la connexion sleep 5 # Vérifier la connexion tailscale status log_info "Mesh KAWA connecté!" } # Téléchargement de la configuration fetch_config() { log_step "Téléchargement de la configuration KAWA..." local TEMP_DIR=$(mktemp -d) # Cloner le repo log_info "Clonage de $GIT_REPO..." git clone --depth 1 "$GIT_REPO" "$TEMP_DIR/kawa-config" || { log_error "Impossible de cloner le repo" exit 1 } log_info "Configuration téléchargée dans $TEMP_DIR/kawa-config" echo "$TEMP_DIR/kawa-config" } # Génération de la configuration NixOS generate_nixos_config() { log_step "Génération de la configuration NixOS..." local HOSTNAME="$1" local CONFIG_DIR="$2" local DISK="${3:-/dev/sda}" mkdir -p /etc/nixos # Configuration de base KAWA cat > /etc/nixos/configuration.nix << EOF # KAWA OS Configuration # Généré automatiquement par install-kawa.sh # Hostname: $HOSTNAME { config, pkgs, ... }: { imports = [ ./hardware-configuration.nix ./kawa-base.nix ]; # Configuration réseau networking.hostName = "$HOSTNAME"; networking.networkmanager.enable = true; # Timezone time.timeZone = "Europe/Paris"; # Internationalisation i18n.defaultLocale = "fr_FR.UTF-8"; # Utilisateurs users.users.kawa = { isNormalUser = true; extraGroups = [ "wheel" "networkmanager" "docker" "audio" "video" ]; initialPassword = "kawa"; }; # Packages de base environment.systemPackages = with pkgs; [ vim git curl wget tailscale htop neofetch tmux ]; # Services services.openssh.enable = true; services.tailscale.enable = true; # Firewall networking.firewall.enable = true; networking.firewall.allowedTCPPorts = [ 22 ]; # Version NixOS system.stateVersion = "26.05"; } EOF # Configuration KAWA base cat > /etc/nixos/kawa-base.nix << EOF # KAWA Base Configuration # Services communs à tous les nœuds KAWA { config, pkgs, ... }: { # Tailscale avec Headscale services.tailscale = { enable = true; extraUpFlags = [ "--login-server=https://headscale.du-senegal.com" "--authkey=" ]; }; # NATS pour la communication inter-nœuds services.nats = { enable = true; servername = "$HOSTNAME"; port = 4222; httpPort = 8222; }; # Docker virtualisation.docker.enable = true; # Ollama pour l'inférence locale services.ollama = { enable = true; acceleration = "cuda"; }; # Git programs.git.enable = true; # Scripts KAWA environment.etc."kawa/scripts" = { source = /var/lib/kawa/scripts; }; } EOF # Générer la configuration hardware nixos-generate-config --root /mnt 2>/dev/null || { log_warn "Configuration hardware générée manuellement" cp /etc/nixos/hardware-configuration.nix /mnt/etc/nixos/ 2>/dev/null || true } log_info "Configuration NixOS générée" } # Installation sur le disque install_to_disk() { log_step "Installation sur le disque..." local DISK="$1" # Lister les disques disponibles log_info "Disques disponibles:" lsblk -o NAME,SIZE,TYPE,MOUNTPOINT | grep disk # Demander confirmation read -p "Installer KAWA OS sur $DISK ? (y/N): " confirm if [[ ! "$confirm" =~ ^[Yy]$ ]]; then log_warn "Installation annulée" exit 0 fi # Partitionnement log_info "Partitionnement de $DISK..." # Créer les partitions parted "$DISK" --script mklabel gpt parted "$DISK" --script mkpart ESP fat32 1MiB 512MiB parted "$DISK" --script set 1 esp on parted "$DISK" --script mkpart primary 512MiB 100% # Formater mkfs.vfat -n BOOT "${DISK}1" mkfs.ext4 -L NIXOS "${DISK}2" # Monter mount "${DISK}2" /mnt mkdir -p /mnt/boot mount "${DISK}1" /mnt/boot log_info "Disque préparé" } # Installation complète install_system() { log_step "Installation du système..." # Installer NixOS nixos-install --no-root-passwd || { log_error "Erreur lors de l'installation" exit 1 } log_info "Système installé!" } # Post-installation post_install() { log_step "Post-installation..." # Copier les configs KAWA mkdir -p /mnt/var/lib/kawa/scripts mkdir -p /mnt/var/lib/kawa/config # Configurer le mesh log_info "Configuration du mesh KAWA..." # Message final echo -e "${CYAN}" cat << "EOF" ╔═══════════════════════════════════════════════════════════╗ ║ ║ ║ ✅ KAWA OS Installation terminée! ║ ║ ║ ║ Prochaines étapes: ║ ║ 1. Redémarrez la machine ║ ║ 2. Connectez-vous avec: user: kawa, password: kawa ║ ║ 3. Le nœud sera automatiquement connecté au mesh ║ ║ ║ ║ Commandes utiles: ║ ║ - tailscale status : Voir le statut du mesh ║ ║ - tailscale ip : Voir l'IP du nœud ║ ║ - nats-server : Bus de messages KAWA ║ ║ ║ ╚═══════════════════════════════════════════════════════════╝ EOF echo -e "${NC}" } # Mode live USB (sans installation) live_mode() { log_step "Mode Live USB (sans installation sur disque)..." local HOSTNAME="$1" local CONFIG_DIR="$2" # Configurer le mesh connect_mesh "$HOSTNAME" # Copier les scripts KAWA mkdir -p /var/lib/kawa/scripts cp -r "$CONFIG_DIR/scripts"/* /var/lib/kawa/scripts/ 2>/dev/null || true # Configurer le hostname hostnamectl set-hostname "$HOSTNAME" 2>/dev/null || echo "$HOSTNAME" > /etc/hostname log_info "Mode Live configuré!" log_info "Ce nœud est connecté au mesh KAWA en tant que $HOSTNAME" # Afficher l'IP log_info "IP Mesh: $(tailscale ip 2>/dev/null || echo 'en attente...')" } # Main main() { log_info "Démarrage de l'installation KAWA OS..." # Vérifier les prérequis check_prereqs # Détecter le hostname HOSTNAME=$(detect_hostname) # Demander le mode echo "" echo -e "${YELLOW}Mode d'installation:${NC}" echo " 1) Mode Live USB (en RAM, sans installation sur disque)" echo " 2) Installation sur disque" echo "" read -p "Choisir le mode (1/2): " mode # Télécharger la config CONFIG_DIR=$(fetch_config) case "$mode" in 1) live_mode "$HOSTNAME" "$CONFIG_DIR" ;; 2) # Lister les disques log_info "Disques disponibles:" lsblk -o NAME,SIZE,TYPE,MOUNTPOINT | grep disk read -p "Disque cible (ex: /dev/sda): " DISK install_tailscale install_to_disk "$DISK" generate_nixos_config "$HOSTNAME" "$CONFIG_DIR" "$DISK" connect_mesh "$HOSTNAME" install_system post_install ;; *) log_error "Mode invalide" exit 1 ;; esac } # Exécution main "$@"