commit d6a66c16b86a2c2b64804b0eb6ff4ab5b66b0fad Author: Amaury JOLY Date: Tue Mar 10 18:51:49 2026 +0100 init diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..26f5acd --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +01-trash/ +result \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..bc3f737 --- /dev/null +++ b/README.md @@ -0,0 +1,519 @@ +# NixOS Configuration + +Configuration NixOS modulaire basée sur Flakes pour laptop. + +## 📁 Structure + +``` +nixos-config/ +├── flake.nix # Point d'entrée principal avec inputs et configurations +├── configuration.nix # Configuration racine importée par le flake +├── hosts/ +│ └── laptop/ +│ └── configuration.nix # Configuration matérielle spécifique au laptop +└── modules/ + ├── laptop/ # Modules spécifiques au laptop + │ ├── default.nix # Secrets management (sops-nix) et config de base + │ ├── users.nix # Définition utilisateur et packages + │ ├── gaming.nix # Gaming (Steam, xpadneo) - avec options + │ ├── virtualization.nix # Docker & VirtualBox - avec options + │ ├── printing.nix # Imprimantes - avec options + │ ├── power.nix # Power management - avec options + │ ├── bluetooth.nix # Bluetooth - avec options + │ └── zwift.nix # Zwift cycling simulator - avec options + └── nixos/ # Modules système génériques + ├── base.nix # Configuration système de base (Nix, packages, fonts, locale) + ├── yubikey.nix # Authentification YubiKey globale (login/sudo) + ├── desktop-i3.nix # Window manager i3 + ├── net.nix # Réseau (DNS chiffré, WiFi settings) + ├── wireless-networks.nix # Configuration des réseaux WiFi (SSID, auth) + └── parsec.nix # Parsec Cloud client +``` + +## ⚙️ Configuration Centralisée + +Tous les paramètres personnalisables se trouvent dans [config.nix](config.nix) : + +```nix +{ + username = "alice"; # Votre username + userEmail = "amaury.joly"; # Email pour réseaux WPA-EAP + configFlakePath = /etc/nixos; # Chemin vers la config flake + timezone = "Europe/Paris"; # Timezone + locale = "fr_FR.UTF-8"; # Locale + hostname = "nixos"; # Hostname du système +} +``` + +**À adapter lors de la première installation :** +1. Ouvrir [config.nix](config.nix) +2. Remplacer les valeurs par vos préférences (username, email, timezone, etc.) +3. Ces valeurs sont ensuite utilisées automatiquement dans tous les modules + +## 🎛️ Système d'Options Modulaires + +La configuration utilise le système d'options NixOS pour activer/désactiver des fonctionnalités. Toutes les options sont définies dans [configuration.nix](configuration.nix) : + +### Gaming +```nix +custom.gaming.enable = true; # Active Steam et support gaming +custom.gaming.enableXpadneo = true; # Driver pour manettes Xbox +``` + +### Virtualisation +```nix +custom.virtualization.docker.enable = true; # Active Docker +custom.virtualization.docker.dnsServers = [ "172.17.0.1" ]; # DNS pour containers +custom.virtualization.virtualbox.enable = true; # Active VirtualBox +``` + +### Impression +```nix +custom.printing.enable = true; +custom.printing.printers = [ # Liste des imprimantes + { + name = "Mon_Imprimante"; + location = "Bureau"; + deviceUri = "http://192.168.1.100"; + model = "drv:///sample.drv/generic.ppd"; + } +]; +custom.printing.defaultPrinter = "Mon_Imprimante"; +``` + +### Power Management +```nix +custom.power.enable = true; +custom.power.cpuGovernor = "powersave"; # ou "performance", "ondemand" +``` + +### Bluetooth +```nix +custom.bluetooth.enable = true; +custom.bluetooth.powerOnBoot = true; # Activer Bluetooth au démarrage +``` + +### Zwift +```nix +custom.zwift.enable = true; # Zwift cycling simulator +``` + +**💡 Avantages :** +- ✅ **Activation conditionnelle** : Désactiver une fonctionnalité = `enable = false;` +- ✅ **Documentation intégrée** : `nixos-option custom.gaming.enable` affiche la doc +- ✅ **Pas de code mort** : Les modules désactivés ne sont pas évalués +- ✅ **Réutilisable** : Facile de créer une config pour une autre machine + +## 🚀 Déploiement + +### Build et test (sans activer) +```bash +cd ~/src/nixos-config +nixos-rebuild build --flake .#laptop +``` + +### Activer la configuration +```bash +sudo nixos-rebuild switch --flake .#laptop +``` + +### Mettre à jour les inputs +```bash +nix flake update +sudo nixos-rebuild switch --flake .#laptop +``` + +### Avec nh (helper recommandé) +```bash +nh os switch # NH_OS_FLAKE est configuré automatiquement +``` + +## 🔐 Gestion des Secrets (sops-nix) + +Cette configuration utilise [sops-nix](https://github.com/Mic92/sops-nix) pour gérer les secrets de manière sécurisée. + +### Configuration initiale + +1. **Générer une clé age** (si pas déjà fait) : +```bash +mkdir -p ~/.config/sops/age +age-keygen -o ~/.config/sops/age/keys.txt +``` + +2. **Configurer sops pour la clé publique** : +```bash +# Afficher votre clé publique +age-keygen -y ~/.config/sops/age/keys.txt + +# Créer .sops.yaml à la racine si nécessaire +cat > .sops.yaml << EOF +keys: + - &alice YOUR_PUBLIC_KEY_HERE +creation_rules: + - path_regex: secrets/.*\.yaml$ + key_groups: + - age: + - *alice +EOF +``` + +3. **Créer et éditer les fichiers secrets** : +```bash +mkdir -p ~/.config/secrets/ + +# Pour les credentials WiFi (legacy - optionnel) +sops ~/.config/secrets/wireless.yaml + +# Pour la configuration complète des réseaux WiFi (RECOMMANDÉ - tout chiffré) +sops ~/.config/secrets/wifi-networks.yaml + +# Pour Zwift +sops ~/.config/secrets/zwift.yaml +``` + +### 📡 Configuration WiFi Sécurisée (Tout Chiffré) + +**🔒 Nouveauté** : La configuration WiFi est maintenant **entièrement chiffrée** avec sops, incluant : +- ✅ Noms des réseaux (SSID) +- ✅ Identités/usernames +- ✅ Mots de passe +- ✅ Structure complète de configuration + +**Avantages** : +- Aucune information sensible visible dans le code source +- Pas d'exposition des lieux (noms de réseaux maison/travail) +- Configuration complète dans un seul fichier chiffré + +### Créer la configuration WiFi chiffrée + +1. **Copier l'exemple de configuration** : +```bash +cp wifi-networks.yaml.example ~/.config/secrets/wifi-networks.yaml +``` + +2. **Éditer avec sops** : +```bash +sops ~/.config/secrets/wifi-networks.yaml +``` + +3. **Format du fichier** (syntaxe wpa_supplicant.conf) : +```yaml +# Réseau personnel (WPA-PSK) +network={ + ssid="Mon_WiFi_Maison" + psk="mon_mot_de_passe_securise" + priority=100 +} + +# Réseau entreprise (WPA-EAP) +network={ + ssid="Work_Network" + key_mgmt=WPA-EAP + eap=TTLS + identity="username@company.com" + password="password_entreprise" + phase2="auth=PAP" + priority=10 +} + +# Eduroam (université) +network={ + ssid="eduroam" + key_mgmt=WPA-EAP + eap=PEAP + identity="etudiant@universite.fr" + password="mot_de_passe_univ" +} + +# Réseau caché +network={ + ssid="Hidden_Network" + psk="password" + scan_ssid=1 + priority=50 +} +``` + +### Ajouter un nouveau réseau WiFi + +**Tout se fait dans le fichier chiffré !** + +```bash +# Éditer le fichier chiffré +sops ~/.config/secrets/wifi-networks.yaml + +# Ajouter un nouveau bloc network={...} +# Sauvegarder et quitter + +# Appliquer la configuration +sudo nixos-rebuild switch --flake .#laptop +``` + +**Exemples de configuration selon le type de réseau** : + +**WiFi personnel (WPA2)** : +``` +network={ + ssid="MonReseau" + psk="MotDePasse123" + priority=100 +} +``` + +**WiFi entreprise (802.1X)** : +``` +network={ + ssid="CorpWiFi" + key_mgmt=WPA-EAP + eap=TTLS + identity="user@company.com" + password="my_password" + phase2="auth=PAP" +} +``` + +**Hotspot mobile** : +``` +network={ + ssid="iPhone_Alice" + psk="hotspot_pass" + scan_ssid=1 +} +``` + +### Migration depuis l'ancienne configuration + +Si vous aviez des réseaux définis en Nix (ancienne méthode), migrez-les vers le fichier chiffré : + +1. Copier les configs depuis [modules/nixos/wireless-networks.nix](modules/nixos/wireless-networks.nix) +2. Convertir au format wpa_supplicant.conf +3. Ajouter dans `~/.config/secrets/wifi-networks.yaml` +4. Chiffrer avec sops +5. Les anciennes définitions seront ignorées + +### Format du fichier zwift.yaml +```yaml +# Configuration Zwift ici +``` + +## 📦 Modules et Fonctionnalités + +### 🖥️ Système de Base + +**Base System** ([modules/nixos/base.nix](modules/nixos/base.nix)) +- Configuration Nix avec flakes et nix-command +- Packages système essentiels (wget, jq, element-desktop, etc.) +- Fonts Nerd Fonts (DejaVu, Droid Sans Mono) +- Locale française (Europe/Paris - configurable) +- Shell Fish par défaut + +**YubiKey Authentication** ([modules/nixos/yubikey.nix](modules/nixos/yubikey.nix)) +- Active l'authentification YubiKey (U2F) pour `login` et `sudo` +- S'applique à tous les systèmes qui importent ce module + +**Fingerprint (Laptop)** ([modules/laptop/fingerprint.nix](modules/laptop/fingerprint.nix)) +- Active `fprintd` sur le laptop +- Ajoute l'authentification empreinte pour `login` et `sudo` +- Sur laptop, l'authentification peut se faire avec **YubiKey ou empreinte** selon la méthode disponible + +**Networking** ([modules/nixos/net.nix](modules/nixos/net.nix)) +- **DNS chiffré** : dnscrypt-proxy (primaire + backup dns0-eu) +- **WiFi** : wpa_supplicant avec multi-réseaux +- **Hostname** : Configurable via [config.nix](config.nix) + +**Desktop** ([modules/nixos/desktop-i3.nix](modules/nixos/desktop-i3.nix)) +- Window manager **i3** +- Terminal : **alacritty** +- Launcher : **rofi** +- Panel : **tint2** +- Notifications : **dunst** + +### 🎮 Fonctionnalités Optionnelles (avec options) + +**Gaming** ([modules/laptop/gaming.nix](modules/laptop/gaming.nix)) +- Steam avec steam-hardware +- Driver xpadneo pour manettes Xbox (optionnel) +- Option : `custom.gaming.enable` + +**Virtualization** ([modules/laptop/virtualization.nix](modules/laptop/virtualization.nix)) +- Docker avec DNS personnalisé +- VirtualBox avec extension pack +- Options : `custom.virtualization.docker.enable`, `custom.virtualization.virtualbox.enable` + +**Printing** ([modules/laptop/printing.nix](modules/laptop/printing.nix)) +- CUPS avec configuration d'imprimantes +- Option : `custom.printing.enable` + +**Power Management** ([modules/laptop/power.nix](modules/laptop/power.nix)) +- CPU frequency governor configurable +- Option : `custom.power.enable` + +**Bluetooth** ([modules/laptop/bluetooth.nix](modules/laptop/bluetooth.nix)) +- Bluetooth avec blueman GUI +- Mode dual controller + experimental features +- Option : `custom.bluetooth.enable` + +**Zwift** ([modules/laptop/zwift.nix](modules/laptop/zwift.nix)) +- Zwift cycling simulator via Docker +- Ports réseau configurés automatiquement +- Option : `custom.zwift.enable` + +### 👤 Utilisateur & Applications + +**User Configuration** ([modules/laptop/users.nix](modules/laptop/users.nix)) + +Packages par catégorie : +- **Browsers** : Firefox +- **Office** : LibreOffice, OnlyOffice, Obsidian, TickTick, Nextcloud +- **Development** : VSCode, Git, Neovim, Zotero, tcpdump, Pandoc +- **Communication** : Slack, Thunderbird, Discord +- **Media** : VLC, Spotify, Mixxx, Pympress +- **Gaming** : Prismlauncher (Minecraft), Widelands, Moonlight +- **System** : Rclone, Fuse3, Pavucontrol + +## 🔧 Flake Inputs + +- **nixpkgs** : nixos-unstable channel +- **sops-nix** : Secrets management +- **parsec-cloud-nix** : Parsec Cloud client +- **claude-desktop** : Claude AI desktop app +- **zwift** : Zwift cycling simulator + +## � Personnalisation + +### Configuration de base + +1. **Timezone et Locale** : Éditer [config.nix](config.nix) + ```nix + timezone = "Europe/Paris"; + locale = "fr_FR.UTF-8"; + ``` + +2. **Username et email** : Éditer [config.nix](config.nix) + ```nix + username = "alice"; + userEmail = "votre.email"; + ``` + +3. **Hostname** : Éditer [config.nix](config.nix) + ```nix + hostname = "nixos"; + ``` + +### Activer/Désactiver des fonctionnalités + +Dans [configuration.nix](configuration.nix), modifier les options `custom.*` : + +```nix +# Désactiver le gaming +custom.gaming.enable = false; + +# Activer uniquement Docker (pas VirtualBox) +custom.virtualization.docker.enable = true; +custom.virtualization.virtualbox.enable = false; + +# Changer le CPU governor +custom.power.cpuGovernor = "performance"; # pour laptop branché +``` + +### Ajouter des packages utilisateur + +Éditer [modules/laptop/users.nix](modules/laptop/users.nix) et ajouter dans la liste appropriée : + +```nix +packages = with pkgs; [ + # Development + python3 + nodejs + # ... vos packages +]; +``` + +### Ajouter une nouvelle fonctionnalité avec options + +1. Créer `modules/laptop/ma-feature.nix` : +```nix +{ config, lib, pkgs, ... }: +{ + options.custom.maFeature.enable = lib.mkEnableOption "ma fonctionnalité"; + + config = lib.mkIf config.custom.maFeature.enable { + # votre configuration + }; +} +``` + +2. Importer dans [configuration.nix](configuration.nix) +3. Activer : `custom.maFeature.enable = true;` + +## 🐛 Dépannage + +### Lister les options disponibles +```bash +# Voir toutes les options custom.* +nixos-option custom + +# Voir une option spécifique avec sa documentation +nixos-option custom.gaming.enable +``` + +### Erreurs de build +```bash +# Vérifier la syntaxe Nix +nix flake check + +# Build avec logs détaillés +nixos-rebuild build --flake .#laptop --show-trace +``` + +### Secrets non déchiffrables +Vérifier que : +- La clé age existe : `~/.config/sops/age/keys.txt` +- Les fichiers secrets existent : `~/.config/secrets/*.yaml` +- Les permissions sont correctes (0400 recommandé) + +### Problèmes DNS +```bash +# Vérifier dnscrypt-proxy +systemctl status dnscrypt-proxy +systemctl status dnscrypt-proxy-backup + +# Tester la résolution +dig @127.0.0.1 example.com +``` + +## 📚 Ressources + +- [NixOS Manual](https://nixos.org/manual/nixos/stable/) +- [Nix Flakes Guide](https://nixos.wiki/wiki/Flakes) +- [sops-nix Documentation](https://github.com/Mic92/sops-nix) +- [Home Manager](https://github.com/nix-community/home-manager) (à considérer pour config utilisateur) + +## 📝 Notes + +- **stateVersion** : Actuellement `24.05` - **NE PAS MODIFIER** après installation +- **Auto-upgrade** : Désactivé pour éviter les mises à jour imprévues +- **Unfree packages** : Activé globalement pour Steam, Slack, etc. + +## 🔄 Maintenance + +### Nettoyage du store Nix +```bash +# Via nh (automatique toutes les 4 jours, garde 3 générations) +nh clean all --keep-since 4d --keep 3 + +# Ou manuellement +nix-collect-garbage -d +sudo nix-collect-garbage -d +``` + +### Lister les générations +```bash +nixos-rebuild list-generations +``` + +### Rollback +```bash +sudo nixos-rebuild switch --rollback +# Ou au boot via GRUB +``` diff --git a/config.nix b/config.nix new file mode 100644 index 0000000..72b397a --- /dev/null +++ b/config.nix @@ -0,0 +1,19 @@ +# Central Configuration +# Define user-specific and system-specific values here +# This file should be imported in flake.nix as specialArgs + +{ + # User configuration + username = "alice"; + userEmail = "amaury.joly"; + + # System paths + configFlakePath = /etc/nixos; + + # Timezone and locale + timezone = "Europe/Paris"; + locale = "fr_FR.UTF-8"; + + # Hostname + hostname = "nixos"; +} diff --git a/configuration.nix b/configuration.nix new file mode 100644 index 0000000..697bce5 --- /dev/null +++ b/configuration.nix @@ -0,0 +1,62 @@ +{ config, pkgs, ... }: + +{ + imports = [ + # Hardware configuration + ./hosts/laptop/configuration.nix + + # NixOS base modules + ./modules/nixos/base.nix + ./modules/nixos/yubikey.nix + ./modules/nixos/desktop-i3.nix + ./modules/nixos/net.nix + ./modules/nixos/wireless-networks.nix + ./modules/nixos/parsec.nix + + # Laptop-specific modules + ./modules/laptop/default.nix + ./modules/laptop/fingerprint.nix + ./modules/laptop/users.nix + ./modules/laptop/bluetooth.nix + ./modules/laptop/zwift.nix + + # Optional feature modules (with options) + ./modules/laptop/gaming.nix + ./modules/laptop/virtualization.nix + ./modules/laptop/printing.nix + ./modules/laptop/power.nix + ]; + + # Enable bootloader + boot.loader.systemd-boot.enable = true; + boot.loader.efi.canTouchEfiVariables = true; + + # Enable optional features via custom options + custom.gaming.enable = true; + custom.gaming.enableXpadneo = true; + + custom.virtualization.docker.enable = true; + custom.virtualization.virtualbox.enable = true; + + custom.printing.enable = true; + custom.printing.printers = [ + { + name = "TOSHIBA_5eme_Luminy"; + location = "Work"; + deviceUri = "http://139.124.5.114"; + model = "drv:///sample.drv/generic.ppd"; + ppdOptions = { + PageSize = "A4"; + }; + } + ]; + custom.printing.defaultPrinter = "TOSHIBA_5eme_Luminy"; + + custom.power.enable = true; + custom.power.cpuGovernor = "powersave"; + + custom.bluetooth.enable = true; + custom.bluetooth.powerOnBoot = true; + + custom.zwift.enable = true; +} diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..8bb4739 --- /dev/null +++ b/flake.lock @@ -0,0 +1,320 @@ +{ + "nodes": { + "claude-desktop": { + "inputs": { + "flake-utils": [ + "flake-utils" + ], + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1764098187, + "narHash": "sha256-H6JjWXhKqxZ8QLMoqndZx9e5x0Sv5AiipSmqvIxIbgo=", + "owner": "k3d3", + "repo": "claude-desktop-linux-flake", + "rev": "b2b040cb68231d2118906507d9cc8fd181ca6308", + "type": "github" + }, + "original": { + "owner": "k3d3", + "repo": "claude-desktop-linux-flake", + "type": "github" + } + }, + "fenix": { + "inputs": { + "nixpkgs": [ + "parsec-cloud-nix", + "nixpkgs" + ], + "rust-analyzer-src": "rust-analyzer-src" + }, + "locked": { + "lastModified": 1773040819, + "narHash": "sha256-9sFursJ9PJoYQFyARzQEKcv5D5SaGU3xJtZDSqEMtek=", + "owner": "nix-community", + "repo": "fenix", + "rev": "6ed2afab20d32920f0984e619ff5f58b2b5d2948", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "fenix", + "type": "github" + } + }, + "flake-utils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1731533236, + "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_2": { + "inputs": { + "systems": "systems_2" + }, + "locked": { + "lastModified": 1726560853, + "narHash": "sha256-X6rJYSESBVr3hBoH0WbKE5KvhPU5bloyZ2L4K60/fPQ=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "c1dfcf08411b08f6b8615f7d8971a2bfa81d5e8a", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "nix-github-actions": { + "inputs": { + "nixpkgs": [ + "parsec-cloud-nix", + "poetry2nix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1729742964, + "narHash": "sha256-B4mzTcQ0FZHdpeWcpDYPERtyjJd/NIuaQ9+BV1h+MpA=", + "owner": "nix-community", + "repo": "nix-github-actions", + "rev": "e04df33f62cdcf93d73e9a04142464753a16db67", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "nix-github-actions", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1772963539, + "narHash": "sha256-9jVDGZnvCckTGdYT53d/EfznygLskyLQXYwJLKMPsZs=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "9dcb002ca1690658be4a04645215baea8b95f31d", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_2": { + "locked": { + "lastModified": 1770141374, + "narHash": "sha256-yD4K/vRHPwXbJf5CK3JkptBA6nFWUKNX/jlFp2eKEQc=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "41965737c1797c1d83cfb0b644ed0840a6220bd1", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "parsec-cloud-nix": { + "inputs": { + "fenix": "fenix", + "nixpkgs": [ + "nixpkgs" + ], + "poetry2nix": "poetry2nix" + }, + "locked": { + "lastModified": 1773132441, + "narHash": "sha256-fv5MurEa6CZt6gwZ2Gr7CU8g4OyuMfTrmmEKO8MYPvc=", + "owner": "FirelightFlagboy", + "repo": "parsec-cloud-nix", + "rev": "cc60bedad264efec120f87a9fb536317878ee3c7", + "type": "github" + }, + "original": { + "owner": "FirelightFlagboy", + "repo": "parsec-cloud-nix", + "type": "github" + } + }, + "poetry2nix": { + "inputs": { + "flake-utils": "flake-utils_2", + "nix-github-actions": "nix-github-actions", + "nixpkgs": [ + "parsec-cloud-nix", + "nixpkgs" + ], + "systems": "systems_3", + "treefmt-nix": "treefmt-nix" + }, + "locked": { + "lastModified": 1743690424, + "narHash": "sha256-cX98bUuKuihOaRp8dNV1Mq7u6/CQZWTPth2IJPATBXc=", + "owner": "nix-community", + "repo": "poetry2nix", + "rev": "ce2369db77f45688172384bbeb962bc6c2ea6f94", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "poetry2nix", + "type": "github" + } + }, + "root": { + "inputs": { + "claude-desktop": "claude-desktop", + "flake-utils": "flake-utils", + "nixpkgs": "nixpkgs", + "parsec-cloud-nix": "parsec-cloud-nix", + "sops-nix": "sops-nix", + "zwift": "zwift" + } + }, + "rust-analyzer-src": { + "flake": false, + "locked": { + "lastModified": 1772938598, + "narHash": "sha256-cxHbp8na0qO5U3SPGkSLzg3g9C81gJEG/7WbYPktD6o=", + "owner": "rust-lang", + "repo": "rust-analyzer", + "rev": "51966da92da795f1cda89bef70d7c61266d4123a", + "type": "github" + }, + "original": { + "owner": "rust-lang", + "ref": "nightly", + "repo": "rust-analyzer", + "type": "github" + } + }, + "sops-nix": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1773096132, + "narHash": "sha256-M3zEnq9OElB7zqc+mjgPlByPm1O5t2fbUrH3t/Hm5Ag=", + "owner": "Mic92", + "repo": "sops-nix", + "rev": "d1ff3b1034d5bab5d7d8086a7803c5a5968cd784", + "type": "github" + }, + "original": { + "owner": "Mic92", + "repo": "sops-nix", + "type": "github" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "systems_2": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "systems_3": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "treefmt-nix": { + "inputs": { + "nixpkgs": [ + "parsec-cloud-nix", + "poetry2nix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1730120726, + "narHash": "sha256-LqHYIxMrl/1p3/kvm2ir925tZ8DkI0KA10djk8wecSk=", + "owner": "numtide", + "repo": "treefmt-nix", + "rev": "9ef337e492a5555d8e17a51c911ff1f02635be15", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "treefmt-nix", + "type": "github" + } + }, + "zwift": { + "inputs": { + "nixpkgs": "nixpkgs_2" + }, + "locked": { + "lastModified": 1772604980, + "narHash": "sha256-LepcA4EUgPHmQ05nYYmRvSkAB27oqm8CjfJuxPNp12k=", + "owner": "netbrain", + "repo": "zwift", + "rev": "1cd77e180d6963e843d3b56793adaaecafe83214", + "type": "github" + }, + "original": { + "owner": "netbrain", + "repo": "zwift", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..da59d7d --- /dev/null +++ b/flake.nix @@ -0,0 +1,56 @@ +{ + inputs = { + sops-nix.url = "github:Mic92/sops-nix"; + sops-nix.inputs.nixpkgs.follows = "nixpkgs"; + + nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; + flake-utils.url = "github:numtide/flake-utils"; + + parsec-cloud-nix = { + url = "github:FirelightFlagboy/parsec-cloud-nix"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + + claude-desktop = { + url = "github:k3d3/claude-desktop-linux-flake"; + inputs.nixpkgs.follows = "nixpkgs"; + inputs.flake-utils.follows = "flake-utils"; + }; + + zwift.url = "github:netbrain/zwift"; + }; + + outputs = { self, nixpkgs, sops-nix, zwift, flake-utils, parsec-cloud-nix, claude-desktop, ... }: + let + customConfig = import ./config.nix; + in + flake-utils.lib.eachDefaultSystem (system: + let + pkgs = import nixpkgs { + inherit system; + config.allowUnfree = true; + }; + in { + }) // + { + nixosConfigurations.laptop = nixpkgs.lib.nixosSystem { + modules = [ + sops-nix.nixosModules.sops + zwift.nixosModules.zwift + ./configuration.nix + ({ pkgs, lib, ...}: + { + environment.systemPackages = with pkgs; [ + claude-desktop.packages.${pkgs.stdenv.hostPlatform.system}.claude-desktop-with-fhs + ]; + }) + ]; + + specialArgs = { + inherit customConfig; + parsec-cloud-nix = parsec-cloud-nix; + claude-desktop = claude-desktop; + }; + }; + }; +} diff --git a/hosts/laptop/configuration.nix b/hosts/laptop/configuration.nix new file mode 100644 index 0000000..5a6eb80 --- /dev/null +++ b/hosts/laptop/configuration.nix @@ -0,0 +1,41 @@ +# Do not modify this file! It was generated by ‘nixos-generate-config’ +# and may be overwritten by future invocations. Please make changes +# to /etc/nixos/configuration.nix instead. +{ config, lib, pkgs, modulesPath, ... }: + +{ + imports = + [ (modulesPath + "/installer/scan/not-detected.nix") + ]; + + boot.initrd.availableKernelModules = [ "xhci_pci" "thunderbolt" "nvme" "usb_storage" "usbhid" "sd_mod" ]; + boot.initrd.kernelModules = [ ]; + boot.kernelModules = [ "kvm-intel" ]; + boot.extraModulePackages = [ ]; + + fileSystems."/" = + { device = "/dev/disk/by-uuid/e9209e4f-94b4-45ef-bed6-9435c96ee864"; + fsType = "ext4"; + }; + + fileSystems."/boot" = + { device = "/dev/disk/by-uuid/E59B-B8FC"; + fsType = "vfat"; + options = [ "fmask=0077" "dmask=0077" ]; + }; + + swapDevices = + [ { device = "/dev/disk/by-uuid/e8cd6918-bc63-4d24-b8eb-6a1170844a80"; } + ]; + + # Enables DHCP on each ethernet and wireless interface. In case of scripted networking + # (the default) this is the recommended approach. When using systemd-networkd it's + # still possible to use this option, but it's recommended to use it in conjunction + # with explicit per-interface declarations with `networking.interfaces..useDHCP`. + networking.useDHCP = lib.mkDefault true; + # networking.interfaces.enp0s31f6.useDHCP = lib.mkDefault true; + # networking.interfaces.wlp0s20f3.useDHCP = lib.mkDefault true; + + nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; + hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; +} diff --git a/modules/laptop/bluetooth.nix b/modules/laptop/bluetooth.nix new file mode 100644 index 0000000..18b1e6d --- /dev/null +++ b/modules/laptop/bluetooth.nix @@ -0,0 +1,33 @@ +# Module: Bluetooth Configuration +# Description: Enables Bluetooth with dual controller mode and experimental features +# Services: bluetooth, blueman (GUI manager) + +{ config, lib, ... }: + +{ + options.custom.bluetooth = { + enable = lib.mkEnableOption "Bluetooth support with blueman GUI"; + + powerOnBoot = lib.mkOption { + type = lib.types.bool; + default = true; + description = "Power on Bluetooth adapter on boot"; + }; + }; + + config = lib.mkIf config.custom.bluetooth.enable { + hardware.bluetooth = { + enable = true; + powerOnBoot = config.custom.bluetooth.powerOnBoot; + settings = { + General = { + ControllerMode = "dual"; + Privacy = "device"; + JustWorksRepairing = "always"; + Experimental = true; + }; + }; + }; + services.blueman.enable = true; + }; +} \ No newline at end of file diff --git a/modules/laptop/default.nix b/modules/laptop/default.nix new file mode 100644 index 0000000..6cb4cf6 --- /dev/null +++ b/modules/laptop/default.nix @@ -0,0 +1,36 @@ +# Module: Laptop Secrets & Base Configuration +# Description: Secrets management (sops-nix) and keyboard layout +# Services: sops-nix +# Dependencies: sops-nix for secrets management +# Note: Other laptop features (gaming, virtualization, etc.) are in separate modules + +{ customConfig, ... }: + +let + userHome = "/home/${customConfig.username}"; +in +{ + sops.validateSopsFiles = false; + sops.age.keyFile = "${userHome}/.config/sops/age/keys.txt"; + + # WiFi networks configuration - entire network list encrypted + sops.secrets.wifi-networks = { + path = "/run/secrets/wifi-networks.conf"; + sopsFile = ../../secrets/wifi-networks.yaml; + format = "yaml"; + key = "wifi-networks"; + owner = "wpa_supplicant"; + group = "wpa_supplicant"; + mode = "0400"; + }; + + sops.secrets.zwift = { + path = "${userHome}/.config/zwift/config"; + sopsFile = ../../secrets/zwift.yaml; + owner = customConfig.username; + group = "users"; + mode = "0400"; + }; + + services.xserver.xkb.layout = "fr"; +} \ No newline at end of file diff --git a/modules/laptop/fingerprint.nix b/modules/laptop/fingerprint.nix new file mode 100644 index 0000000..49fa588 --- /dev/null +++ b/modules/laptop/fingerprint.nix @@ -0,0 +1,10 @@ +{ pkgs, ... }: + +{ + services.fprintd.enable = true; + services.fprintd.tod.enable = true; + services.fprintd.tod.driver = pkgs.libfprint-2-tod1-goodix-550a; + + security.pam.services.login.fprintAuth = true; + security.pam.services.sudo.fprintAuth = true; +} diff --git a/modules/laptop/gaming.nix b/modules/laptop/gaming.nix new file mode 100644 index 0000000..7f31447 --- /dev/null +++ b/modules/laptop/gaming.nix @@ -0,0 +1,29 @@ +# Module: Gaming Support +# Description: Enables Steam and gamepad drivers (xpadneo for Xbox controllers) +# Services: Steam, steam-hardware + +{ config, lib, pkgs, ... }: + +{ + options.custom.gaming = { + enable = lib.mkEnableOption "gaming support (Steam, gamepad drivers)"; + + enableXpadneo = lib.mkOption { + type = lib.types.bool; + default = true; + description = "Enable xpadneo driver for Xbox controllers"; + }; + }; + + config = lib.mkIf config.custom.gaming.enable { + hardware.steam-hardware.enable = true; + + programs.steam = { + enable = true; + }; + + boot.extraModulePackages = lib.mkIf config.custom.gaming.enableXpadneo [ + pkgs.linuxPackages.xpadneo + ]; + }; +} diff --git a/modules/laptop/power.nix b/modules/laptop/power.nix new file mode 100644 index 0000000..777b382 --- /dev/null +++ b/modules/laptop/power.nix @@ -0,0 +1,21 @@ +# Module: Power Management +# Description: CPU frequency governor and power management settings +# Services: powerManagement + +{ config, lib, ... }: + +{ + options.custom.power = { + enable = lib.mkEnableOption "power management configuration"; + + cpuGovernor = lib.mkOption { + type = lib.types.str; + default = "powersave"; + description = "CPU frequency governor (powersave, performance, ondemand, etc.)"; + }; + }; + + config = lib.mkIf config.custom.power.enable { + powerManagement.cpuFreqGovernor = config.custom.power.cpuGovernor; + }; +} diff --git a/modules/laptop/printing.nix b/modules/laptop/printing.nix new file mode 100644 index 0000000..1273861 --- /dev/null +++ b/modules/laptop/printing.nix @@ -0,0 +1,33 @@ +# Module: Printing Configuration +# Description: CUPS printing service with configured printers +# Services: printing (CUPS) + +{ config, lib, ... }: + +{ + options.custom.printing = { + enable = lib.mkEnableOption "printing support (CUPS)"; + + printers = lib.mkOption { + type = lib.types.listOf lib.types.attrs; + default = []; + description = "List of printers to configure"; + }; + + defaultPrinter = lib.mkOption { + type = lib.types.nullOr lib.types.str; + default = null; + description = "Default printer name"; + }; + }; + + config = lib.mkIf config.custom.printing.enable { + services.printing.enable = true; + + hardware.printers = lib.mkIf (config.custom.printing.printers != []) { + ensurePrinters = config.custom.printing.printers; + ensureDefaultPrinter = lib.mkIf (config.custom.printing.defaultPrinter != null) + config.custom.printing.defaultPrinter; + }; + }; +} diff --git a/modules/laptop/users.nix b/modules/laptop/users.nix new file mode 100644 index 0000000..4f7df1b --- /dev/null +++ b/modules/laptop/users.nix @@ -0,0 +1,60 @@ +# Module: User Configuration +# Description: Defines the main user 'alice' with groups, permissions, and user packages +# Packages: Browsers (Firefox), Office (LibreOffice), Development (VSCode, Git), +# Media (VLC, Spotify), Communication (Slack, Thunderbird), and more + +{ pkgs, customConfig, ... }: + +{ + users.users."${customConfig.username}" = { + isNormalUser = true; + home = "/home/${customConfig.username}"; + # Base groups - docker/vboxusers are added by virtualization.nix if enabled + extraGroups = [ "wheel" "audio" "dialout" "plugdev" ]; + packages = with pkgs; [ + # Browsers & Web + firefox + + # Office & Productivity + libreoffice + onlyoffice-desktopeditors + obsidian + ticktick + nextcloud-client + + # Development + neovim + git + vscode + zotero + tcpdump + pandoc + libsecret + + # Communication + slack + thunderbird + discord + + # Media & Creative + vlc + spotify + mixxx + pympress + + # Gaming & Entertainment + prismlauncher # Minecraft launcher + widelands # Strategy game + wasistlos # Game + moonlight-qt # Game streaming + + # System & Cloud + rclone + fuse3 + pavucontrol + tree + sops + age + ]; + }; +} \ No newline at end of file diff --git a/modules/laptop/virtualization.nix b/modules/laptop/virtualization.nix new file mode 100644 index 0000000..91c2a1d --- /dev/null +++ b/modules/laptop/virtualization.nix @@ -0,0 +1,42 @@ +# Module: Virtualization +# Description: Docker and VirtualBox virtualization support +# Services: Docker daemon, VirtualBox + +{ config, lib, pkgs, customConfig, ... }: + +{ + options.custom.virtualization = { + docker = { + enable = lib.mkEnableOption "Docker container runtime"; + + dnsServers = lib.mkOption { + type = lib.types.listOf lib.types.str; + default = [ "172.17.0.1" ]; + description = "DNS servers for Docker containers (points to dnscrypt-proxy)"; + }; + }; + + virtualbox = { + enable = lib.mkEnableOption "VirtualBox virtualization"; + }; + }; + + config = lib.mkMerge [ + (lib.mkIf config.custom.virtualization.docker.enable { + virtualisation.docker = { + enable = true; + daemon.settings = { + # Docker DNS points to dnscrypt-proxy configured in net.nix + dns = config.custom.virtualization.docker.dnsServers; + }; + }; + + users.users."${customConfig.username}".extraGroups = [ "docker" ]; + }) + + (lib.mkIf config.custom.virtualization.virtualbox.enable { + virtualisation.virtualbox.host.enable = true; + users.users."${customConfig.username}".extraGroups = [ "vboxusers" ]; + }) + ]; +} diff --git a/modules/laptop/zwift.nix b/modules/laptop/zwift.nix new file mode 100644 index 0000000..b6c0f9a --- /dev/null +++ b/modules/laptop/zwift.nix @@ -0,0 +1,35 @@ +# Module: Zwift Configuration +# Description: Configures Zwift cycling simulator via Docker with proper networking +# Services: Zwift Docker container +# Ports: UDP 3022, 3024 / TCP 21587, 21588 + +{ config, lib, pkgs, customConfig, ... }: + +{ + options.custom.zwift = { + enable = lib.mkEnableOption "Zwift cycling simulator"; + }; + + config = lib.mkIf config.custom.zwift.enable { + programs.zwift = { + enable = true; + image = "docker.io/netbrain/zwift"; + version = "latest"; # FIXME: Pin to specific version for reproducibility + containerTool = "docker"; + zwiftWorkoutDir = "/var/lib/zwift/workouts"; + zwiftActivityDir = "/var/lib/zwift/activities"; + zwiftLogDir = "/var/lib/zwift/logs"; + zwiftScreenshotsDir = "/var/lib/zwift/screenshots"; + zwiftFg = true; + networking = "bridge"; + # Use actual user UID/GID instead of hardcoded 1000 + zwiftUid = toString config.users.users."${customConfig.username}".uid; + zwiftGid = toString config.users.groups.users.gid; + }; + + networking.firewall = { + allowedUDPPorts = [ 3022 3024 ]; + allowedTCPPorts = [ 21587 21588 ]; + }; + }; +} diff --git a/modules/nixos/base.nix b/modules/nixos/base.nix new file mode 100644 index 0000000..2396cb2 --- /dev/null +++ b/modules/nixos/base.nix @@ -0,0 +1,63 @@ +# Module: Base System Configuration +# Description: Core NixOS configuration with Nix settings, base packages, fonts, +# localization (FR), Fish shell, and security (GPG) +# Services: gvfs, udisks2, gnupg-agent + +{ pkgs, customConfig, ... }: + +{ + nix.settings = { + experimental-features = [ "nix-command" "flakes" ]; + substituters = [ + "https://cache.nixos.org/" + "https://parsec-cloud.cachix.org" + ]; + trusted-public-keys = [ + "parsec-cloud.cachix.org-1:MuWfCBKBfuUWqwB6xKFK0armIJ+A+Mi++HohuB6YvTk=" + ]; + }; + + programs.nh = { + enable = true; + clean.enable = true; + clean.extraArgs = "--keep-since 4d --keep 3"; + flake = builtins.toString customConfig.configFlakePath; + }; + + nixpkgs.config.allowUnfree = true; + + time.timeZone = customConfig.timezone; + + services.gvfs.enable = true; + services.udisks2.enable = true; + + i18n.defaultLocale = customConfig.locale; + + programs.fish.enable = true; + users.defaultUserShell = pkgs.fish; + + environment.systemPackages = with pkgs; [ + wget + jq + linuxPackages.cpupower + + element-desktop + ntfs3g + zip + unzip + ]; + + fonts.packages = with pkgs; [ + nerd-fonts.dejavu-sans-mono + nerd-fonts.droid-sans-mono + ]; + + programs.gnupg.agent = { + enable = true; + enableSSHSupport = true; + }; + + # WARNING: DO NOT CHANGE this value after installation! + # See: https://nixos.org/manual/nixos/stable/options#opt-system.stateVersion + system.stateVersion = "24.05"; +} \ No newline at end of file diff --git a/modules/nixos/desktop-i3.nix b/modules/nixos/desktop-i3.nix new file mode 100644 index 0000000..feb51c2 --- /dev/null +++ b/modules/nixos/desktop-i3.nix @@ -0,0 +1,31 @@ +# Module: i3 Window Manager Configuration +# Description: Enables X11 with i3 window manager and associated desktop tools +# Services: xserver with i3 +# Packages: alacritty (terminal), tint2 (panel), rofi (launcher), i3lock, dunst + +{ pkgs, ... }: + +{ + services.xserver.enable = true; + services.xserver.windowManager.i3.enable = true; + services.xserver.autorun = true; + + environment.systemPackages = with pkgs; [ + alacritty + tint2 + awesome + maim + xclip + dunst + xss-lock + dex + rofi + i3status + i3blocks + oh-my-posh + glances + arandr + nautilus + brightnessctl + ]; +} \ No newline at end of file diff --git a/modules/nixos/net.nix b/modules/nixos/net.nix new file mode 100644 index 0000000..63bb8a3 --- /dev/null +++ b/modules/nixos/net.nix @@ -0,0 +1,98 @@ +# Module: Network Configuration +# Description: Network setup with dnscrypt-proxy for encrypted DNS, WiFi networks +# configuration via wpa_supplicant, and hostname settings +# Services: dnscrypt-proxy (primary + backup), wpa_supplicant +# Security: WiFi credentials stored via sops-nix secrets + +{ config, lib, pkgs, customConfig, ... }: + +let + backupToml = pkgs.writeText "dnscrypt-proxy-backup.toml" '' + listen_addresses = ["127.0.0.2:53"] + server_names = ["dns0-eu"] + + [sources.public-resolvers] + urls = ['https://raw.githubusercontent.com/DNSCrypt/dnscrypt-resolvers/master/v3/public-resolvers.md'] + cache_file = '/var/lib/dnscrypt-proxy-backup/public-resolvers.md' + minisign_key = 'RWQf6LRCGA9i53mlYecO4IzT51TGPpvWucNSCh1CBM0QTaLn73Y7GFO3' + refresh_delay = 72 + ''; + + userHome = "/home/${customConfig.username}"; +in + +{ + networking.nftables.enable = true; + networking.firewall = { + enable = true; + allowPing = true; + # allowedTCPPorts = [ ... ]; # keep closed by default + interfaces.docker0 = { + allowedUDPPorts = [ 53 ]; + allowedTCPPorts = [ 53 ]; + }; + }; + + networking.hostName = customConfig.hostname; + # Pick only one of the below networking options. + networking.wireless.enable = true; + # networking.wireless.userControlled = true; + # networking.wireless.secretsFile = config.sops.secrets.wifi.path; + + # Load encrypted WiFi networks configuration via wpa_supplicant include files. + # This is supported by the NixOS module and keeps SSIDs out of the Nix store. + networking.wireless.extraConfigFiles = lib.mkIf (config.sops.secrets ? wifi-networks) [ + config.sops.secrets.wifi-networks.path + ]; + + networking.wireless.enableHardening = false; + + # systemd.services.wpa_supplicant.after = [ "sops-install-secrets.service" ]; + # systemd.services.wpa_supplicant.requires = [ "sops-install-secrets.service" ]; + + # You can also define networks in Nix if you prefer (less secure - names visible): + # networking.wireless.networks = { ... }; + + networking.interfaces.lo.ipv4.addresses = [ + { address = "127.0.0.1"; prefixLength = 8; } + { address = "127.0.0.2"; prefixLength = 8; } + ]; + + networking.nameservers = [ "127.0.0.1" "127.0.0.2" ]; + + # networking.networkmanager.dns = "none"; + services.resolved.enable = false; + + services.dnscrypt-proxy = { + enable = true; + settings = { + listen_addresses = [ "127.0.0.1:53" "172.17.0.1:53" ]; + server_names = [ "amaury" ]; + bootstrap_resolvers = []; + sources = {}; + static = { + "amaury".stamp = "sdns://AgcAAAAAAAAADTgyLjY0LjIzNy4yNDYADWFtYXVyeWpvbHkuZnIUL2Rucy1xdWVyeS9pZC1hbWF1cnk"; + }; + cache = true; + ignore_system_dns = true; + timeout = 5000; + }; + }; + + systemd.services."dnscrypt-proxy-backup" = { + description = "dnscrypt-proxy backup (dns0-eu)"; + after = [ "network.target" ]; + wantedBy = [ "multi-user.target" ]; + serviceConfig = { + ExecStart = "${pkgs.dnscrypt-proxy}/bin/dnscrypt-proxy -config ${backupToml}"; + Restart = "on-failure"; + NoNewPrivileges = true; + DynamicUser = true; + AmbientCapabilities = "CAP_NET_BIND_SERVICE"; + }; + }; + + systemd.services.dnscrypt-proxy.serviceConfig = { + StateDirectory = "dnscrypt-proxy"; + }; +} \ No newline at end of file diff --git a/modules/nixos/parsec.nix b/modules/nixos/parsec.nix new file mode 100644 index 0000000..9736b82 --- /dev/null +++ b/modules/nixos/parsec.nix @@ -0,0 +1,28 @@ +# Module: Parsec Cloud Client +# Description: Installs Parsec Cloud client (v3) with CLI and GUI +# Dependencies: parsec-cloud-nix flake input +# Note: Requires increased Node.js heap size during build (workaround) + +{ pkgs, parsec-cloud-nix, ... }: + +let + pc = parsec-cloud-nix.packages.${pkgs.stdenv.hostPlatform.system}; + + # WORKAROUND: Parsec build runs out of memory without increased heap size + # This increases Node.js memory limit from default 512MB to 8GB + nativeBuildPatched = pc.parsec-cloud.v3.native-client-build.overrideAttrs (old: { + NODE_OPTIONS = "--max-old-space-size=8192"; + }); + + parsecClientPatched = pc.parsec-cloud.v3.client.override { + native-client-build = nativeBuildPatched; + }; + + parsecCli = pc.parsec-cloud.v3.cli; +in +{ + environment.systemPackages = [ + parsecClientPatched + parsecCli + ]; +} diff --git a/modules/nixos/wireless-networks.nix b/modules/nixos/wireless-networks.nix new file mode 100644 index 0000000..9f2f8ff --- /dev/null +++ b/modules/nixos/wireless-networks.nix @@ -0,0 +1,16 @@ +# Module: Wireless Networks Configuration (Encrypted) +# Description: WiFi networks configuration fully encrypted with sops-nix +# Security: Network names, SSIDs, and all configuration stored in encrypted secrets +# Files: ~/.config/secrets/wifi-networks.yaml (encrypted with sops) +# Note: The actual networks are loaded at runtime from the encrypted file + +{ config, lib, pkgs, ... }: + +{ + # WiFi networks are loaded from encrypted file at runtime + # The file is in wpa_supplicant.conf format and gets included by wpa_supplicant + # This approach keeps network names and configuration completely private + + # Note: If wifi-networks secret doesn't exist yet, this won't cause errors + # You can still use the old method (networking.wireless.networks in Nix) if needed +} diff --git a/modules/nixos/yubikey.nix b/modules/nixos/yubikey.nix new file mode 100644 index 0000000..ed35506 --- /dev/null +++ b/modules/nixos/yubikey.nix @@ -0,0 +1,13 @@ +# Module: YubiKey Authentication +# Description: Enables YubiKey-based PAM auth for login and sudo across systems + +{ pkgs, ... }: + +{ + security.pam.services = { + login.u2fAuth = true; + sudo.u2fAuth = true; + }; + + services.udev.packages = [ pkgs.yubikey-personalization ]; +} diff --git a/secrets.example/wifi-networks.yaml.example b/secrets.example/wifi-networks.yaml.example new file mode 100644 index 0000000..688d52f --- /dev/null +++ b/secrets.example/wifi-networks.yaml.example @@ -0,0 +1,54 @@ +# Example WiFi Networks Configuration (to be encrypted with sops) +# This file should be encrypted and stored at: ~/.config/secrets/wifi-networks.yaml +# +# Format: wpa_supplicant.conf syntax +# After editing, encrypt with: sops ~/.config/secrets/wifi-networks.yaml +# +# This example shows different network types: +# - WPA-PSK (simple password) +# - WPA-EAP (enterprise, eduroam) +# - Hidden networks +# - Priority settings + +# Home WiFi (WPA-PSK) +network={ + ssid="My_Home_Network" + psk="my_secure_password_here" + priority=100 +} + +# Work WiFi (WPA-EAP with TTLS) +network={ + ssid="Work_Network" + key_mgmt=WPA-EAP + eap=TTLS + identity="username@company.com" + password="my_work_password" + phase2="auth=PAP" + priority=10 +} + +# Eduroam (university) +network={ + ssid="eduroam" + key_mgmt=WPA-EAP + eap=PEAP + identity="student.id@university.edu" + password="university_password" + priority=5 +} + +# Mobile hotspot (hidden network) +network={ + ssid="MyPhone" + psk="phone_hotspot_password" + scan_ssid=1 + priority=50 +} + +# Public network (open, no password) +network={ + ssid="PublicWiFi" + key_mgmt=NONE + priority=1 +} diff --git a/secrets/wifi-networks.yaml b/secrets/wifi-networks.yaml new file mode 100644 index 0000000..8f9d286 --- /dev/null +++ b/secrets/wifi-networks.yaml @@ -0,0 +1,16 @@ +wifi-networks: ENC[AES256_GCM,data:dl44GBBxdbWbk8loC5aH5RYwL3CwRMwf25VptiRQBNKjWpdY8SBI2mEm3rNPmeXXI/aElcCukr/OJx/uFTK6QfgUYJHz+Hybhu06k0+Iti3RUrWc/yk8OTiqhamMIdxNf3Jz330wTWHx87fCvVFveRti74Ccr0xcvS94Uj/JyCmZVs6Bj7koxnoI2ixsiziNBzK/iCT9t/z0LJWlpmCeaNfdqxnjTKuaCgYDOpe3Ukt/YPL6VTSv4kkMnEKNi+yvlpcjp2QfXXbYMLv6rf59nZcz8Ml7OL2y3DfbFbi2yarr2ZPbYYa5HbvyZm4C19/otspzazl2dXkApmgYg1i49UGla0Y1V0v91nIDbazg10w6T3hcluQvK5UNIPbntb4dq+boy1OzrojrnI8vzdydck7dluMPoAxxaGpCP1vj4+Mgq7v1R4jytrWpJFiRkZQW55UmK7R/BkinkyhTUoHh9a3yOC2KM3oyeR+LnHlzBhcItWqhvozMs/pGmQHU3+OkXvcDf4I2tQYJ5jXoNJsG/jseYsNDhgcatlb/MmuJf2Bjc1lPSGCd8jCyXyz9tZx468boczazsSO5OsPIVL76Z/x4zZj6JFXz9rUTtD8nE1juJO2JWFxMkihrtfvIWxE0+kMrxBUlE8Nw8jeBaa9E69a44SKT3N2q5ZlFZGbRj+2l7Eo7i3T61gmTrUCLZ/nyQOlZcr7T0LnJxvbbJo3GvkiZddA9HMWxRRqX8Ee1QKOvk1ufBhW3CqNtaVWxewE4Fkf/f2ejI2666NYo3fn+voUNPEwYPNobLgvtQZd8AckAiw==,iv:o8zTQ7Z7Ycq/0Q3shVM4hQmBgQp3UIlKkq25lF0Puu8=,tag:Vs84synGs0VBJmCGOcTqlg==,type:str] +sops: + age: + - recipient: age1hhyew9sv8lqqfeza92jkxsdudhsgaef66cxalp06ez2cm9k6aqysc7mlf7 + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAwdktBTVA2d2dmNkt0Sm9N + QnpTKzhRK3FpRlFZOXR1RElFZkRRdUJhY244Cjl5blh3MFBlZ0RWMnA4Ly84OVVS + Ti9FRUh1WmtOTTAxVFArUjZVdFdpQjQKLS0tIEQvZnZXZWlvd2ZqMjIyTFRaYWxv + NENiek9YeUhXNFhuZkZzRnBIYXdGY2cKpfSlzP7uK6VFl71OYfoHBxAwrKfpJSNT + QQUngSh6VBrWeJIxoMkJ7O+xSgwZnWc0fnrB+OpoRqy5YVctSmHERg== + -----END AGE ENCRYPTED FILE----- + lastmodified: "2026-03-06T15:09:08Z" + mac: ENC[AES256_GCM,data:IaMzycI+z+icBoTlIdNfQ/wSm4KRVKj4KoDCvXhQivGdScnOiC4a/fKz1pzL7/PNRgjETUmZ0MJhicT0lTS7FJ+dTgjkDAvpXx+24ML8iVoufny7ho6VOMlPPAVkmtbIAgXq6BFTABTHu9/Y/qKGjHAA0MgPUhPn3Ku1pROQTVc=,iv:y6hUJibLuojG4WAGq85e39Qpj3b1kj9GVqzzIoNRq3w=,tag:jv4thwXAJUHciEi2Mn8VcQ==,type:str] + unencrypted_suffix: _unencrypted + version: 3.12.1 diff --git a/secrets/zwift.yaml b/secrets/zwift.yaml new file mode 100644 index 0000000..e8de8ef --- /dev/null +++ b/secrets/zwift.yaml @@ -0,0 +1,16 @@ +zwift: ENC[AES256_GCM,data:4tgwyldDGDSPqkgJGG/8jOO0Gd9lvj1gallBbylzXOSev3FR8HdQZVVAtmdBv+krrhxyfXZI/IdH9SBkkZbMaH3UrtXqOEtNIFF8iLSU9hFYG1DGC0yRYCg=,iv:h22Ew6slSvT1MD2DzwxkDe88o3FgFQyiWQioANB/uKs=,tag:IbmwhF7TYA/SH8jmPAWZvw==,type:str] +sops: + age: + - recipient: age1hhyew9sv8lqqfeza92jkxsdudhsgaef66cxalp06ez2cm9k6aqysc7mlf7 + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBjWEhTTnZ0NkVtZXJVTFZQ + cWFGVCtKZmhwMWw3bkZWNzZKbTR0VGVmVFZFCkREdnJ2TTBmaTByZEg4cU92STFZ + Tk9EMUs5YkN1TnFEMlZxR1dsT0kvVmsKLS0tIE9XQlVwTUFyM0FzcnNHTUppdUVt + VjRrejZZUSs0QlQ0TXlIM1FOZU1MZEkK0ZYeL/LWgpMW72pghDlD6kilNgWUgirf + 7ZPdbf3Y+vWh+ifYUSIWbsvWtx0w0e1zeI/TuJ6R6dYgTZZTuffBMA== + -----END AGE ENCRYPTED FILE----- + lastmodified: "2026-03-05T12:41:54Z" + mac: ENC[AES256_GCM,data:ifyhtI2m5dCPqxLbA6aRTBBdWgDfIG0LOHF036amyUKbg1xv8ZliEwsVWF+ADuAhZo5IeasdstbzUBF2Fw6yv+/6IvdH0MmX65mJega5XTFXAZRskdZBqOgXNGuKSJ71YUR8nt0EdHfFNuPR53iLmSDKYSJSXza1wA3Hjsku8WE=,iv:uv904RwND4wPRty9tIdYZfAG94H4q6AGqaDh2nOH/TI=,tag:VpCt+LKmuoNCVcNHGeWGeg==,type:str] + unencrypted_suffix: _unencrypted + version: 3.12.1