Add NixOS support with configuration module

- Add nixos/kawa.nix module for NixOS integration
- Add flake.nix for Nix flakes support
- Update setup script to detect and handle NixOS
- Include NATS, Syncthing, and Tailscale configuration
- Add parameters for Headscale connection
This commit is contained in:
Debian
2026-03-14 22:20:34 +00:00
parent 18a602aa60
commit aaa11df19f
4 changed files with 426 additions and 87 deletions

30
flake.nix Normal file
View File

@@ -0,0 +1,30 @@
{
description = "KAWA OS - NixOS Configuration";
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
};
outputs = { self, nixpkgs, ... }@inputs: {
nixosModules = {
default = import ./nixos;
kawa = import ./nixos/kawa.nix;
};
nixosConfigurations = {
# Exemple de configuration
kawa-node = nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
modules = [
./nixos
{
services.kawa = {
enable = true;
hostname = "kawa-node-01";
};
}
];
};
};
};
}

18
nixos/default.nix Normal file
View File

@@ -0,0 +1,18 @@
# KAWA OS - Configuration par défaut
# Usage: import dans configuration.nix
{ config, lib, pkgs, ... }:
{
imports = [
./kawa.nix
];
services.kawa = {
enable = true;
autoConnect = true;
enableNats = true;
enableSyncthing = true;
enableOllama = false; # Activer si GPU disponible
};
}

148
nixos/kawa.nix Normal file
View File

@@ -0,0 +1,148 @@
# KAWA OS - Module NixOS
# Configuration automatique pour rejoindre le mesh KAWA
{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.services.kawa;
in
{
options.services.kawa = {
enable = mkEnableOption "KAWA mesh network";
hostname = mkOption {
type = types.str;
default = "";
description = "Hostname personnalisé pour le nœud KAWA";
};
headscaleUrl = mkOption {
type = types.str;
default = "https://headscale.du-senegal.com";
description = "URL du serveur Headscale";
};
headscaleFallback = mkOption {
type = types.str;
default = "http://141.94.23.212";
description = "URL de fallback du serveur Headscale";
};
authKey = mkOption {
type = types.str;
default = "f43f36ef159b3df799eb316b81bdac1b415c7cc2add174d0";
description = "Clé d'authentification Headscale";
};
autoConnect = mkOption {
type = types.bool;
default = true;
description = "Connexion automatique au mesh au démarrage";
};
# Services KAWA
enableNats = mkOption {
type = types.bool;
default = true;
description = "Activer le client NATS";
};
enableSyncthing = mkOption {
type = types.bool;
default = true;
description = "Activer Syncthing pour la synchronisation";
};
enableOllama = mkOption {
type = types.bool;
default = false;
description = "Activer Ollama pour l'inférence locale";
};
};
config = mkIf cfg.enable {
# Tailscale configuration
services.tailscale = {
enable = true;
extraUpFlags = [
"--login-server=${cfg.headscaleUrl}"
"--authkey=${cfg.authKey}"
"--hostname=${if cfg.hostname != "" then cfg.hostname else "kawa-${config.networking.hostName}"}"
];
};
# NATS client
services.nats = mkIf cfg.enableNats {
enable = true;
server = "100.64.0.1:4222";
};
# Syncthing
services.syncthing = mkIf cfg.enableSyncthing {
enable = true;
user = "kawa";
group = "kawa";
config = {
folders = {
"kawa-memory" = {
path = "/home/kawa/.local/share/kawa/memory";
devices = [ "vps-7ed4abb0" ];
};
"kawa-workspace" = {
path = "/home/kawa/.local/share/kawa/workspace";
devices = [ "vps-7ed4abb0" ];
};
"kawa-forge" = {
path = "/home/kawa/.local/share/kawa/forge";
devices = [ "vps-7ed4abb0" ];
};
};
};
};
# Ollama (optionnel)
services.ollama = mkIf cfg.enableOllama {
enable = true;
acceleration = false; # À activer si GPU disponible
};
# Utilisateur KAWA
users.users.kawa = {
isNormalUser = true;
description = "KAWA Node User";
extraGroups = [ "wheel" "networkmanager" "tailscale" ];
};
# Firewall
networking.firewall = {
allowedTCPPorts = [ 22 4222 22000 ];
allowedUDPPorts = [ 41641 22000 ];
trustedInterfaces = [ "tailscale0" ];
};
# Environment packages
environment.systemPackages = with pkgs; [
tailscale
natscli
syncthing
git
curl
wget
];
# Systemd service pour la connexion automatique
systemd.services.kawa-connect = mkIf cfg.autoConnect {
description = "KAWA Mesh Auto-Connect";
after = [ "network-online.target" "tailscale.service" ];
wants = [ "network-online.target" ];
wantedBy = [ "multi-user.target" ];
serviceConfig = {
Type = "oneshot";
ExecStart = "${pkgs.tailscale}/bin/tailscale up --login-server=${cfg.headscaleUrl} --authkey=${cfg.authKey} --force-reauth";
RemainAfterExit = true;
};
};
};
}

317
setup
View File

@@ -8,50 +8,231 @@ HEADSCALE_URL="https://headscale.du-senegal.com"
HEADSCALE_FALLBACK="http://141.94.23.212"
HEADSCALE_AUTHKEY="f43f36ef159b3df799eb316b81bdac1b415c7cc2add174d0"
# Paramètres NATS
NATS_SERVER="100.64.0.1:4222"
NATS_CLUSTER="KAWA"
NATS_USER="kawa"
NATS_PASS="kawa123"
# Paramètres Syncthing
SYNCTHING_DEVICE_ID="" # Sera généré
SYNCTHING_FOLDERS="kawa-memory,kawa-workspace,kawa-forge"
SYNCTHING_VPS_ID="AHF53QZ-ZYCQ2K7-556QBZ2-2UAYZL4-QNEQOGZ-PHZQIAG-4ZRXI3P-QLLJNA6"
echo "🜄 KAWA OS - Installation"
echo ""
# Détection du type de système
detect_system() {
# NixOS
if [ -f /etc/NIXOS ]; then
echo "nixos"
return
fi
# Debian/Ubuntu
if [ -f /etc/debian_version ]; then
echo "debian"
return
fi
# Fedora/RHEL
if [ -f /etc/redhat-release ]; then
echo "redhat"
return
fi
# Arch Linux
if [ -f /etc/arch-release ]; then
echo "arch"
return
fi
# Docker/Container
if [ -f /.dockerenv ]; then
echo "docker"
elif grep -q "docker\|lxc\|container" /proc/1/cgroup 2>/dev/null; then
echo "container"
elif [ -f /sys/class/dmi/id/product_name ]; then
echo "physical"
else
echo "unknown"
return
fi
# Container générique
if grep -q "docker\|lxc\|container" /proc/1/cgroup 2>/dev/null; then
echo "container"
return
fi
# Machine physique
if [ -f /sys/class/dmi/id/product_name ]; then
echo "physical"
return
fi
echo "unknown"
}
# Génération du hostname
generate_hostname() {
local SYSTEM_TYPE=$(detect_system)
local MODEL
local SUFFIX
# Installation spécifique NixOS
install_nixos() {
echo "📦 Installation NixOS détectée"
echo ""
case "$SYSTEM_TYPE" in
docker|container)
# Pour les conteneurs, utiliser le hostname du host ou générer
if [ -f /etc/hostname ]; then
MODEL=$(cat /etc/hostname | tr '[:upper:]' '[:lower:]' | tr -d ' ' | cut -c1-15)
else
MODEL="container"
fi
SUFFIX=$(head -c 4 /dev/urandom | xxd -p 2>/dev/null || echo "$(date +%s | tail -c 4)")
echo "kawa-${MODEL}-${SUFFIX}"
;;
physical)
# Pour les machines physiques
MODEL=$(cat /sys/class/dmi/id/product_name 2>/dev/null | tr '[:upper:]' '[:lower:]' | tr -d ' ' | cut -c1-15 || echo "node")
SUFFIX=$(head -c 4 /dev/urandom | xxd -p 2>/dev/null || echo "$(date +%s | tail -c 4)")
echo "kawa-${MODEL}-${SUFFIX}"
;;
*)
SUFFIX=$(head -c 4 /dev/urandom | xxd -p 2>/dev/null || echo "$(date +%s | tail -c 4)")
echo "kawa-node-${SUFFIX}"
;;
esac
# Demander le hostname
read -p "Hostname pour ce nœud (ex: kawa-node-01): " HOSTNAME_INPUT
HOSTNAME="${HOSTNAME_INPUT:-kawa-node-$(head -c 4 /dev/urandom | xxd -p 2>/dev/null || echo "$(date +%s | tail -c 4)")}"
# Créer la configuration NixOS
echo "Création de la configuration NixOS..."
NIXOS_CONFIG="/etc/nixos/kawa-configuration.nix"
cat > "$NIXOS_CONFIG" << NIXOS_EOF
# KAWA Node - Configuration NixOS
# Généré automatiquement par kawa-setup
{ config, lib, pkgs, ... }:
{
imports = [
./hardware-configuration.nix
./kawa.nix
];
# Configuration réseau
networking.hostName = "$HOSTNAME";
networking.firewall = {
allowedTCPPorts = [ 22 4222 22000 ];
allowedUDPPorts = [ 41641 22000 ];
trustedInterfaces = [ "tailscale0" ];
};
# Tailscale/Headscale
services.tailscale = {
enable = true;
extraUpFlags = [
"--login-server=$HEADSCALE_URL"
"--authkey=$HEADSCALE_AUTHKEY"
"--hostname=$HOSTNAME"
"--force-reauth"
];
};
# NATS Client
services.nats = {
enable = true;
server = "$NATS_SERVER";
};
# Syncthing
services.syncthing = {
enable = true;
user = "kawa";
group = "kawa";
config = {
devices = {
"vps-7ed4abb0" = { id = "$SYNCTHING_VPS_ID"; };
};
folders = {
"kawa-memory" = {
path = "/home/kawa/.local/share/kawa/memory";
devices = [ "vps-7ed4abb0" ];
};
"kawa-workspace" = {
path = "/home/kawa/.local/share/kawa/workspace";
devices = [ "vps-7ed4abb0" ];
};
"kawa-forge" = {
path = "/home/kawa/.local/share/kawa/forge";
devices = [ "vps-7ed4abb0" ];
};
};
};
};
# Utilisateur KAWA
users.users.kawa = {
isNormalUser = true;
extraGroups = [ "wheel" "networkmanager" "tailscale" "syncthing" ];
};
# Packages système
environment.systemPackages = with pkgs; [
tailscale
natscli
syncthing
git
curl
wget
htop
];
}
NIXOS_EOF
# Copier le module kawa.nix
cp ./nixos/kawa.nix /etc/nixos/ 2>/dev/null || true
echo ""
echo "✓ Configuration NixOS créée: $NIXOS_CONFIG"
echo ""
echo "Pour appliquer:"
echo " sudo nixos-rebuild switch"
echo ""
echo "Ou ajouter à votre configuration existante:"
echo " imports = [ ./kawa.nix ];"
echo " services.kawa.enable = true;"
return 0
}
# Installation standard (Debian/Ubuntu/Fedora/etc.)
install_standard() {
echo "📦 Installation standard ($1)"
HOSTNAME="${2:-kawa-$SYSTEM_TYPE-$(head -c 4 /dev/urandom | xxd -p 2>/dev/null || echo "$(date +%s | tail -c 4)")}"
echo "Hostname: $HOSTNAME"
echo ""
# Vérifier connexion existante
check_existing
# Installer Tailscale si nécessaire
if ! command -v tailscale &> /dev/null; then
echo "Installation de Tailscale..."
curl -fsSL https://tailscale.com/install.sh | sh
fi
# Démarrer tailscaled
echo "Démarrage de tailscaled..."
tailscaled 2>/dev/null &
sleep 3
# Connexion au mesh
echo "Connexion au mesh KAWA..."
tailscale down 2>/dev/null || true
sleep 1
if tailscale up --login-server="$HEADSCALE_URL" --authkey="$HEADSCALE_AUTHKEY" --hostname="$HOSTNAME" --force-reauth 2>/dev/null; then
echo "✓ Connecté via $HEADSCALE_URL"
elif tailscale up --login-server="$HEADSCALE_FALLBACK" --authkey="$HEADSCALE_AUTHKEY" --hostname="$HOSTNAME" --force-reauth 2>/dev/null; then
echo "✓ Connecté via $HEADSCALE_FALLBACK"
else
echo "✗ Échec de connexion"
exit 1
fi
sleep 2
# Afficher les infos
echo ""
echo "🜄 Nœud KAWA configuré!"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo "Hostname: $HOSTNAME"
echo "IP Mesh: $(tailscale ip 2>/dev/null || echo 'en attente...')"
echo "NATS: $NATS_SERVER"
echo ""
echo "Commandes utiles:"
echo " tailscale status # Voir le mesh"
echo " tailscale ip # Voir l'IP"
echo " tailscale ping NODE # Ping un nœud"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
}
# Vérifier si déjà connecté
@@ -76,59 +257,21 @@ check_existing() {
echo "Détection du système..."
SYSTEM_TYPE=$(detect_system)
echo "Type détecté: $SYSTEM_TYPE"
HOSTNAME=$(generate_hostname)
echo "Hostname: $HOSTNAME"
echo ""
# Vérifier connexion existante
check_existing
# Installer Tailscale si nécessaire
if ! command -v tailscale &> /dev/null; then
echo "Installation de Tailscale..."
curl -fsSL https://tailscale.com/install.sh | sh
fi
# Démarrer tailscaled
echo "Démarrage de tailscaled..."
tailscaled 2>/dev/null &
sleep 3
# Connexion au mesh
echo "Connexion au mesh KAWA..."
# Déconnexion préalable si existante
tailscale down 2>/dev/null || true
sleep 1
# Tentative de connexion
if tailscale up --login-server="$HEADSCALE_URL" --authkey="$HEADSCALE_AUTHKEY" --hostname="$HOSTNAME" --force-reauth 2>/dev/null; then
echo "✓ Connecté via $HEADSCALE_URL"
elif tailscale up --login-server="$HEADSCALE_FALLBACK" --authkey="$HEADSCALE_AUTHKEY" --hostname="$HOSTNAME" --force-reauth 2>/dev/null; then
echo "✓ Connecté via $HEADSCALE_FALLBACK"
else
echo "✗ Échec de connexion"
echo ""
echo "Vérifiez:"
echo " - La connexion réseau"
echo " - Le serveur Headscale est accessible"
echo " - L'authkey est valide"
exit 1
fi
sleep 2
# Afficher les infos
echo ""
echo "🜄 Nœud KAWA configuré!"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo "Hostname: $HOSTNAME"
echo "IP Mesh: $(tailscale ip 2>/dev/null || echo 'en attente...')"
echo "IPv6: $(tailscale ip -6 2>/dev/null || echo 'en attente...')"
echo ""
echo "Commandes utiles:"
echo " tailscale status # Voir le mesh"
echo " tailscale ip # Voir l'IP"
echo " tailscale ping NODE # Ping un nœud"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
case "$SYSTEM_TYPE" in
nixos)
install_nixos
;;
debian|redhat|arch|physical)
install_standard "$SYSTEM_TYPE"
;;
docker|container)
install_standard "container"
;;
*)
echo "Type de système non reconnu: $SYSTEM_TYPE"
echo "Tentative d'installation standard..."
install_standard "unknown"
;;
esac