init
This commit is contained in:
33
modules/laptop/bluetooth.nix
Normal file
33
modules/laptop/bluetooth.nix
Normal file
@@ -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;
|
||||
};
|
||||
}
|
||||
36
modules/laptop/default.nix
Normal file
36
modules/laptop/default.nix
Normal file
@@ -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";
|
||||
}
|
||||
10
modules/laptop/fingerprint.nix
Normal file
10
modules/laptop/fingerprint.nix
Normal file
@@ -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;
|
||||
}
|
||||
29
modules/laptop/gaming.nix
Normal file
29
modules/laptop/gaming.nix
Normal file
@@ -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
|
||||
];
|
||||
};
|
||||
}
|
||||
21
modules/laptop/power.nix
Normal file
21
modules/laptop/power.nix
Normal file
@@ -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;
|
||||
};
|
||||
}
|
||||
33
modules/laptop/printing.nix
Normal file
33
modules/laptop/printing.nix
Normal file
@@ -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;
|
||||
};
|
||||
};
|
||||
}
|
||||
60
modules/laptop/users.nix
Normal file
60
modules/laptop/users.nix
Normal file
@@ -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
|
||||
];
|
||||
};
|
||||
}
|
||||
42
modules/laptop/virtualization.nix
Normal file
42
modules/laptop/virtualization.nix
Normal file
@@ -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" ];
|
||||
})
|
||||
];
|
||||
}
|
||||
35
modules/laptop/zwift.nix
Normal file
35
modules/laptop/zwift.nix
Normal file
@@ -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 ];
|
||||
};
|
||||
};
|
||||
}
|
||||
63
modules/nixos/base.nix
Normal file
63
modules/nixos/base.nix
Normal file
@@ -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";
|
||||
}
|
||||
31
modules/nixos/desktop-i3.nix
Normal file
31
modules/nixos/desktop-i3.nix
Normal file
@@ -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
|
||||
];
|
||||
}
|
||||
98
modules/nixos/net.nix
Normal file
98
modules/nixos/net.nix
Normal file
@@ -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";
|
||||
};
|
||||
}
|
||||
28
modules/nixos/parsec.nix
Normal file
28
modules/nixos/parsec.nix
Normal file
@@ -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
|
||||
];
|
||||
}
|
||||
16
modules/nixos/wireless-networks.nix
Normal file
16
modules/nixos/wireless-networks.nix
Normal file
@@ -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
|
||||
}
|
||||
13
modules/nixos/yubikey.nix
Normal file
13
modules/nixos/yubikey.nix
Normal file
@@ -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 ];
|
||||
}
|
||||
Reference in New Issue
Block a user