From 81353cd437532e7d09c1a636cd84616c1a24f37a Mon Sep 17 00:00:00 2001 From: Victor Mignot Date: Sun, 22 Oct 2023 17:12:42 +0200 Subject: [PATCH] Create initial flake structure with london configuration --- .sops.yaml | 13 + configurations/london/default.nix | 128 ++++++++ configurations/london/secrets/secrets.yaml | 21 ++ flake.lock | 137 +++++++++ flake.nix | 72 +++++ machines.nix | 9 + modules/common/boot.nix | 62 ++++ modules/common/default.nix | 62 ++++ modules/common/filesystem.nix | 67 +++++ modules/common/hardware.nix | 26 ++ modules/common/linux.nix | 53 ++++ modules/common/network.nix | 38 +++ modules/common/nix.nix | 26 ++ modules/common/users.nix | 50 ++++ modules/server/default.nix | 3 + modules/workstation/bluetooth.nix | 19 ++ modules/workstation/default.nix | 50 ++++ modules/workstation/desktop.nix | 17 ++ .../home-manager/communication.nix | 38 +++ modules/workstation/home-manager/default.nix | 73 +++++ .../home-manager/desktop/alacritty.nix | 88 ++++++ .../home-manager/desktop/default.nix | 52 ++++ .../workstation/home-manager/desktop/mako.nix | 29 ++ .../workstation/home-manager/desktop/sway.nix | 245 ++++++++++++++++ .../home-manager/desktop/swaylock.nix | 52 ++++ .../home-manager/desktop/waybar.nix | 275 ++++++++++++++++++ .../workstation/home-manager/desktop/wofi.nix | 74 +++++ .../home-manager/development/default.nix | 35 +++ .../home-manager/development/embedded.nix | 22 ++ modules/workstation/home-manager/fish.nix | 31 ++ modules/workstation/home-manager/gpg.nix | 24 ++ modules/workstation/home-manager/mail.nix | 125 ++++++++ .../home-manager/neovim/default.nix | 165 +++++++++++ .../neovim/luaconfig/keybindings.lua | 11 + .../neovim/luaconfig/lspconfig.lua | 94 ++++++ .../neovim/luaconfig/settings.lua | 17 ++ modules/workstation/home-manager/termux.nix | 46 +++ modules/workstation/sound.nix | 11 + 38 files changed, 2360 insertions(+) create mode 100644 .sops.yaml create mode 100644 configurations/london/default.nix create mode 100644 configurations/london/secrets/secrets.yaml create mode 100644 flake.lock create mode 100644 flake.nix create mode 100644 machines.nix create mode 100644 modules/common/boot.nix create mode 100644 modules/common/default.nix create mode 100644 modules/common/filesystem.nix create mode 100644 modules/common/hardware.nix create mode 100644 modules/common/linux.nix create mode 100644 modules/common/network.nix create mode 100644 modules/common/nix.nix create mode 100644 modules/common/users.nix create mode 100644 modules/server/default.nix create mode 100644 modules/workstation/bluetooth.nix create mode 100644 modules/workstation/default.nix create mode 100644 modules/workstation/desktop.nix create mode 100644 modules/workstation/home-manager/communication.nix create mode 100644 modules/workstation/home-manager/default.nix create mode 100644 modules/workstation/home-manager/desktop/alacritty.nix create mode 100644 modules/workstation/home-manager/desktop/default.nix create mode 100644 modules/workstation/home-manager/desktop/mako.nix create mode 100644 modules/workstation/home-manager/desktop/sway.nix create mode 100644 modules/workstation/home-manager/desktop/swaylock.nix create mode 100644 modules/workstation/home-manager/desktop/waybar.nix create mode 100644 modules/workstation/home-manager/desktop/wofi.nix create mode 100644 modules/workstation/home-manager/development/default.nix create mode 100644 modules/workstation/home-manager/development/embedded.nix create mode 100644 modules/workstation/home-manager/fish.nix create mode 100644 modules/workstation/home-manager/gpg.nix create mode 100644 modules/workstation/home-manager/mail.nix create mode 100644 modules/workstation/home-manager/neovim/default.nix create mode 100644 modules/workstation/home-manager/neovim/luaconfig/keybindings.lua create mode 100644 modules/workstation/home-manager/neovim/luaconfig/lspconfig.lua create mode 100644 modules/workstation/home-manager/neovim/luaconfig/settings.lua create mode 100644 modules/workstation/home-manager/termux.nix create mode 100644 modules/workstation/sound.nix diff --git a/.sops.yaml b/.sops.yaml new file mode 100644 index 0000000..4880a05 --- /dev/null +++ b/.sops.yaml @@ -0,0 +1,13 @@ +keys: + - &london_system age1rr2u4kk5jc0zk5mmgcfzlddzz82u9ldqwnd2mkcspnps7pzegsms7fys7u + - &london_dala age19m7s6rl4l88nv0f7el70k9u9mv6fd0nq5nw5a3f6p3ffzch274lsksu3y7 + +creation_rules: + - path_regex: configurations/london/secrets/secrets.yaml$ + key_groups: + - age: + - *london_system + - path_regex: configurations/london/secrets/users/dala.yaml$ + key_groups: + - age: + - *london_dala diff --git a/configurations/london/default.nix b/configurations/london/default.nix new file mode 100644 index 0000000..d44330a --- /dev/null +++ b/configurations/london/default.nix @@ -0,0 +1,128 @@ +{ pkgs, config, lib, extraInfo, ... }: +{ + boot.initrd.availableKernelModules = [ "nvme" "xhci_pci" "ahci" "usbhid" ]; + boot.initrd.kernelModules = [ "dm-snapshot" ]; + boot.kernelModules = [ "kvm-amd" ]; + boot.extraModulePackages = [ ]; + + hardware.cpu.amd.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; + + /* Meta */ + isProfessional = false; + + /* Volumes */ + luksDevices = [ + { + name = "crypted-nixos"; + deviceUUID = "5a1ac4ae-d74f-4599-bc5a-fc0a3501a196"; + isPreLVM = true; + } + ]; + + filesystems = [ + { + mountpoint = "/"; + deviceUUID = "8dd700f8-7bf7-426c-8869-d31687e343df"; + fsType = "ext4"; + } + + { + mountpoint = "/boot"; + deviceUUID = "F2B6-C8CA"; + fsType = "vfat"; + } + + { + mountpoint = "/nix"; + deviceUUID = "b7a643f6-a78e-4e32-a1a3-22b321465bf6"; + fsType = "ext4"; + } + + { + mountpoint = "/home"; + deviceUUID = "e26f6727-3712-4830-b8e8-fdbce5e3584b"; + fsType = "ext4"; + } + ]; + + swapDeviceUUID = "5fe5e76b-df3d-43ce-abf9-d2b63078df09"; + + + /* Linux kernel */ + useLatestKernel = true; + + + /* Nix */ + allowUnfreePackages = true; + + /* Hardware acceleration */ + hwAccelerationGPU = "nvidia"; + + /* System secrets */ + sops = { + gnupg.sshKeyPaths = [ ]; + age = { + sshKeyPaths = [ ]; + keyFile = "/var/lib/sops-nix/key.txt"; + }; + defaultSopsFile = ./secrets/secrets.yaml; + secrets.wg0_private = { }; + }; + + /* Wireguard */ + networking.wg-quick.interfaces.wg0 = { + address = [ "10.100.0.4/24" ]; + dns = [ "10.100.0.1" ]; + + listenPort = 51820; + privateKeyFile = config.sops.secrets.wg0_private.path; + + peers = [ + { + # Rock Pro 64 + publicKey = "XVmG3/rNsCqc8KCmOx3+UUn9DJOnJ40Uxid5JGdChR4="; + endpoint = "${extraInfo.wireguard.rockProEndpoint}:51820"; + allowedIPs = [ "10.100.0.1" ]; + persistentKeepalive = 25; + } + + { + # VPS + publicKey = "x45YsLDpMJw1pwKOvkyzdesen3lFcKpxCXACGz+xtDs="; + endpoint = "${extraInfo.wireguard.VPSEndpoint}:51820"; + allowedIPs = [ "10.100.0.2" ]; + persistentKeepalive = 25; + } + ]; + }; + + /* User config */ + machineUsers = { + dala = { + description = "Dala"; + groups = [ "wheel" "video" "audio" "seat" "keys" "lp" "dialout" "network" ]; + uid = 1000; + shell = pkgs.fish; + enableHomeManagerProfile = true; + homeManagerConfig = { + desktop.monitors = [ + { + name = "Iiyama North America PL2470H 0x0000047B"; + resolution = "1920x1080@165.003Hz"; + position = "1920 0"; + defaultWorkspace = 1; + } + { + name = "Iiyama North America PL2530H 1154392601941"; + resolution = "1920x1080@74.973Hz"; + position = "0 0"; + defaultWorkspace = 2; + } + ]; + + nixpkgs.config.allowUnfree = true; + development.embedded.enableTools = true; + }; + }; + }; +} diff --git a/configurations/london/secrets/secrets.yaml b/configurations/london/secrets/secrets.yaml new file mode 100644 index 0000000..ddb2ba8 --- /dev/null +++ b/configurations/london/secrets/secrets.yaml @@ -0,0 +1,21 @@ +wg0_private: ENC[AES256_GCM,data:z5G2EFh1vZk1yEwj0pFIU49u84bOjBZRzvKgqluWoQ6vqm+cMQt/dyGqXg4=,iv:XOiExUWxJczO+aJ+BogtlibqVshEkc6r8xeTPmdru4Y=,tag:+v/3JE1rqTm2x2MJUNltqw==,type:str] +sops: + kms: [] + gcp_kms: [] + azure_kv: [] + hc_vault: [] + age: + - recipient: age1rr2u4kk5jc0zk5mmgcfzlddzz82u9ldqwnd2mkcspnps7pzegsms7fys7u + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBNOVhvOFRQQ1ppenZQdEN6 + S3FPYkNTTnZWUnBFUXMxNEFWcUQ4WVhzK1g4CitLWktOamUyU2dPOHBUaG40WWxN + Nkw5M2pCWFBtTWtQMjQ0azN3Rjh3ZDAKLS0tIFNyNGxiNE41RUdDVkZmNUxyVVR5 + dXhiMUhVc1ZBb0F0bFArZU5OU1ZRK0EKdjtUBIRrw1AhNPczQJiDw6GywJL/jm2r + 4o3XkFqMkP93YAoprHw7egH6t/6QVCFQTZPU4cAwJ0y1bLx9ju44uQ== + -----END AGE ENCRYPTED FILE----- + lastmodified: "2023-11-01T17:15:27Z" + mac: ENC[AES256_GCM,data:zL3UgmKuyzZzBTlBAyP7+nN1If7AMjq1qGkbbXKW2rlzl41x6orMdZQfOWG06eBdd7CGBoNgBNV7A9SE11RhXUvr1gdQGILie0ER2/UCEkEgXIV3tpto1C/tsEYDL7z8LSlcuPt3GJkca1Ym6yhIoe576ho7du3HclUCFBPIBQY=,iv:O3/aYlFPiueoByTyvefahrmFwGq5DAEdUaYvJXB1TFI=,tag:1Al7Lw18AZZ8spnITBuGMw==,type:str] + pgp: [] + unencrypted_suffix: _unencrypted + version: 3.7.3 diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..6841ecb --- /dev/null +++ b/flake.lock @@ -0,0 +1,137 @@ +{ + "nodes": { + "flake-utils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1694529238, + "narHash": "sha256-zsNZZGTGnMOf9YpHKJqMSsa0dXbfmxeoJ7xHlrt+xmY=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "ff7b65b44d01cf9ba6a71320833626af21126384", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "home-manager": { + "inputs": { + "nixpkgs": [ + "nixpkgs-unstable" + ] + }, + "locked": { + "lastModified": 1699368917, + "narHash": "sha256-nUtGIWf86BOkUbtksWtfglvCZ/otP0FTZlQH8Rzc7PA=", + "owner": "nix-community", + "repo": "home-manager", + "rev": "6a8444467c83c961e2f5ff64fb4f422e303c98d3", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "home-manager", + "type": "github" + } + }, + "nixpkgs-stable": { + "locked": { + "lastModified": 1699291058, + "narHash": "sha256-5ggduoaAMPHUy4riL+OrlAZE14Kh7JWX4oLEs22ZqfU=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "41de143fda10e33be0f47eab2bfe08a50f234267", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-23.05", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-stable_2": { + "locked": { + "lastModified": 1699110214, + "narHash": "sha256-L2TU4RgtiqF69W8Gacg2jEkEYJrW+Kp0Mp4plwQh5b8=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "78f3a4ae19f0e99d5323dd2e3853916b8ee4afee", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "release-23.05", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-unstable": { + "locked": { + "lastModified": 1699099776, + "narHash": "sha256-X09iKJ27mGsGambGfkKzqvw5esP1L/Rf8H3u3fCqIiU=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "85f1ba3e51676fa8cc604a3d863d729026a6b8eb", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "flake-utils": "flake-utils", + "home-manager": "home-manager", + "nixpkgs-stable": "nixpkgs-stable", + "nixpkgs-unstable": "nixpkgs-unstable", + "sops-nix": "sops-nix" + } + }, + "sops-nix": { + "inputs": { + "nixpkgs": [ + "nixpkgs-unstable" + ], + "nixpkgs-stable": "nixpkgs-stable_2" + }, + "locked": { + "lastModified": 1699311858, + "narHash": "sha256-W/sQrghPAn5J9d+9kMnHqi4NPVWVpy0V/qzQeZfS/dM=", + "owner": "Mic92", + "repo": "sops-nix", + "rev": "664187539871f63857bda2d498f452792457b998", + "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" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..c26685e --- /dev/null +++ b/flake.nix @@ -0,0 +1,72 @@ +{ + description = "Dala's unified NixOS configuration"; + inputs = { + # As we have machine using the unstable channel, and other machines using the stable one, + # we import both, and we will select for each machine which one to use. + nixpkgs-unstable.url = "github:NixOS/nixpkgs/nixos-unstable"; + nixpkgs-stable.url = "github:NixOS/nixpkgs/nixos-23.05"; + flake-utils.url = "github:numtide/flake-utils"; + + # Home-manager isn't used for anything except my workstations, which all use the unstable channel. + home-manager = { + url = "github:nix-community/home-manager"; + inputs.nixpkgs.follows = "nixpkgs-unstable"; + }; + + # For sops-nix, we keep the unstable nixpkgs, as it shouldn't break anything. + # This input is made to manage secrets on this repository. + sops-nix = { + url = "github:Mic92/sops-nix"; + inputs.nixpkgs.follows = "nixpkgs-unstable"; + }; + }; + + outputs = { self, nixpkgs-unstable, nixpkgs-stable, home-manager, sops-nix, flake-utils }: + let + machines = import ./machines.nix; + in + { + nixosConfigurations = builtins.mapAttrs + (name: value: + let + nixpkgs = + if value.nixpkgsUnstable + then nixpkgs-unstable + else nixpkgs-stable; + in + nixpkgs.lib.nixosSystem { + system = value.system; + + specialArgs = { + machineInfos = { + hostname = name; + } // value; + + sopsHmModule = sops-nix.homeManagerModules.sops; + }; + + modules = [ + ./configurations/${name} + ./modules/common + (if (value.machineType == "workstation") + then ./modules/workstation + else ./modules/server) + (if (value.machineType == "workstation" && value.enableHomeManager) + then home-manager.nixosModules.home-manager + else { }) + sops-nix.nixosModules.sops + ]; + } + ) + machines; + + formatter = builtins.listToAttrs (map + (system: + { + name = system; + value = nixpkgs-unstable.legacyPackages.${system}.nixpkgs-fmt; + } + ) + flake-utils.lib.defaultSystems); + }; +} diff --git a/machines.nix b/machines.nix new file mode 100644 index 0000000..f63e013 --- /dev/null +++ b/machines.nix @@ -0,0 +1,9 @@ +{ + london = { + machineType = "workstation"; + nixpkgsUnstable = true; + system = "x86_64-linux"; + enableHomeManager = true; + stateVersion = "23.11"; + }; +} diff --git a/modules/common/boot.nix b/modules/common/boot.nix new file mode 100644 index 0000000..9ffc50b --- /dev/null +++ b/modules/common/boot.nix @@ -0,0 +1,62 @@ +{ lib, config, ... }: +with lib; +let + luksDevicesModule = types.submodule { + options.name = mkOption { + type = types.str; + description = '' + The partition name. + ''; + }; + + options.deviceUUID = mkOption { + type = types.str; + description = '' + The partition device UUID. + ''; + }; + + options.isPreLVM = mkOption { + type = types.bool; + default = false; + example = true; + description = '' + Whether the decrypted partition will be a LVM device. + ''; + }; + }; +in +{ + options.enableDefaultSystemdBoot = mkOption { + type = types.bool; + default = true; + example = false; + description = '' + Whether or not enable the default SystemD boot system. + Can be useful for devices using u-boot. + ''; + }; + + options.luksDevices = mkOption { + type = types.listOf luksDevicesModule; + default = [ ]; + description = '' + List of LUKS devices. + ''; + }; + + config = { + boot.initrd.luks.devices = builtins.listToAttrs (map + (fs: { + name = fs.name; + value = { + device = "/dev/disk/by-uuid/${fs.deviceUUID}"; + preLVM = fs.isPreLVM; + }; + }) + config.luksDevices); + + boot.loader.systemd-boot.enable = config.enableDefaultSystemdBoot; + boot.loader.efi.canTouchEfiVariables = true; + }; +} diff --git a/modules/common/default.nix b/modules/common/default.nix new file mode 100644 index 0000000..650c07a --- /dev/null +++ b/modules/common/default.nix @@ -0,0 +1,62 @@ +{ lib, config, pkgs, machineInfos, modulesPath, ... }: +with lib; +{ + imports = [ + ./filesystem.nix + ./boot.nix + ./linux.nix + ./nix.nix + ./network.nix + ./hardware.nix + ./users.nix + (modulesPath + "/installer/scan/not-detected.nix") + ]; + + options.machineType = mkOption { + type = types.enum [ "workstation" "server" ]; + default = "workstation"; + example = "server"; + description = '' + What is the type of this machine. + ''; + }; + + options.isProfessional = mkOption { + type = types.bool; + default = false; + example = true; + description = '' + Whether or not this machine is used for professionnal purposes. + ''; + }; + + options.enableDocker = mkOption { + type = types.bool; + default = false; + example = true; + description = '' + Whether or not to enable the docker stack. + ''; + }; + + config = { + machineType = machineInfos.machineType; + system.stateVersion = machineInfos.stateVersion; + networking.hostName = machineInfos.hostname; + virtualisation.docker.enable = config.enableDocker; + + # Only enable fish shell if there is at least one user using it. + programs.fish.enable = builtins.any (user: user.shell == pkgs.fish) (builtins.attrValues config.machineUsers); + + # We always want to disable the X server as only workstation use windows manager + # and they always use wayland. + services.xserver.enable = false; + + assertions = [ + { + assertion = !(config.machineType == "server" && config.isProfessional); + message = "Only workstations can be professionnal hardware"; + } + ]; + }; +} diff --git a/modules/common/filesystem.nix b/modules/common/filesystem.nix new file mode 100644 index 0000000..263530c --- /dev/null +++ b/modules/common/filesystem.nix @@ -0,0 +1,67 @@ +{ lib, config, ... }: +with lib; +let + fsModule = types.submodule { + options = { + + mountpoint = mkOption { + type = types.str; + description = '' + The filesystem mountpoint. + ''; + }; + + deviceUUID = mkOption { + type = types.str; + description = '' + The volume UUID. + ''; + }; + + fsType = mkOption { + type = types.str; + description = '' + The volume filesystem. + ''; + }; + + }; + }; +in +{ + options.filesystems = mkOption { + type = types.listOf fsModule; + default = [ ]; + example = [ + { + mountpoint = "/"; + deviceUUID = "XXXXX-YYYYYY-AJDKKSKSJ"; + fsType = "ext4"; + } + ]; + description = '' + The machine filesystem tree description. + ''; + }; + + options.swapDeviceUUID = mkOption { + type = types.nullOr types.str; + default = null; + }; + + config = { + fileSystems = builtins.listToAttrs (map + (fs: { + name = fs.mountpoint; + value = { + device = "/dev/disk/by-uuid/${fs.deviceUUID}"; + fsType = fs.fsType; + }; + }) + config.filesystems); + + swapDevices = mkIf (config.swapDeviceUUID != null) [ + { device = "/dev/disk/by-uuid/${config.swapDeviceUUID}"; } + ]; + }; +} diff --git a/modules/common/hardware.nix b/modules/common/hardware.nix new file mode 100644 index 0000000..9e6758c --- /dev/null +++ b/modules/common/hardware.nix @@ -0,0 +1,26 @@ +{ lib, config, pkgs, ... }: +with lib; +{ + options.hwAccelerationGPU = mkOption { + type = types.nullOr (types.enum [ "nvidia" "intel" ]); + default = null; + example = "nvidia"; + description = '' + The GPU type. + ''; + }; + + config = { + hardware.opengl = { + enable = config.hwAccelerationGPU != null; + extraPackages = with pkgs; [ + libvdpau-va-gl + vaapiVdpau + ]; + }; + + services.xserver.videoDrivers = [ + (mkIf (config.hwAccelerationGPU == "nvidia") "nouveau") + ]; + }; +} diff --git a/modules/common/linux.nix b/modules/common/linux.nix new file mode 100644 index 0000000..130cd6f --- /dev/null +++ b/modules/common/linux.nix @@ -0,0 +1,53 @@ +{ lib, config, pkgs, ... }: +with lib; +{ + options.useLatestKernel = mkOption { + type = types.bool; + default = false; + example = true; + description = '' + Whether or not to use the latest Linux kernel version. + ''; + }; + + options.consoleFont = mkOption { + type = types.str; + default = "Lat2-Terminus16"; + description = '' + The font to use in the Linux console. + ''; + }; + + options.timeZone = mkOption { + type = types.str; + default = "Europe/Paris"; + description = '' + The system time zone. + ''; + }; + + options.locale = mkOption { + type = types.str; + default = "en_US.utf8"; + description = '' + The system locale. + ''; + }; + + options.keymap = mkOption { + type = types.str; + default = "fr"; + example = "fr"; + description = '' + The keyboard map used. + ''; + }; + + config = { + boot.kernelPackages = mkIf config.useLatestKernel pkgs.linuxPackages_latest; + time.timeZone = config.timeZone; + console.font = config.consoleFont; + console.keyMap = config.keymap; + i18n.defaultLocale = config.locale; + }; +} diff --git a/modules/common/network.nix b/modules/common/network.nix new file mode 100644 index 0000000..093a339 --- /dev/null +++ b/modules/common/network.nix @@ -0,0 +1,38 @@ +{ lib, config, ... }: +with lib; +{ + options.enableFirewall = mkOption { + type = types.bool; + default = true; + example = false; + description = '' + Whether or not to enable firewall. + ''; + }; + + options.extraAllowedTCPPorts = mkOption { + type = types.listOf types.port; + default = [ ]; + example = [ 53 ]; + description = '' + List of custom TCP ports to open in the firewall. + ''; + }; + + options.extraAllowedUDPPorts = mkOption { + type = types.listOf types.port; + default = [ ]; + example = [ 53 ]; + description = '' + List of custom UDP ports to open in the firewall. + ''; + }; + + config = { + networking.networkmanager.enable = true; + networking.useDHCP = mkDefault true; + networking.firewall.enable = true; + networking.firewall.allowedTCPPorts = config.extraAllowedTCPPorts; + networking.firewall.allowedUDPPorts = config.extraAllowedUDPPorts; + }; +} diff --git a/modules/common/nix.nix b/modules/common/nix.nix new file mode 100644 index 0000000..b856f69 --- /dev/null +++ b/modules/common/nix.nix @@ -0,0 +1,26 @@ +{ pkgs, lib, config, ... }: +with lib; +{ + options.allowUnfreePackages = mkOption { + type = types.bool; + default = false; + example = true; + description = '' + Whether the system can use unfree derivations. + ''; + }; + + config = { + nix = { + settings.sandbox = true; + + package = pkgs.nixVersions.stable; + + extraOptions = '' + experimental-features = nix-command flakes + ''; + }; + + nixpkgs.config.allowUnfree = config.allowUnfreePackages; + }; +} diff --git a/modules/common/users.nix b/modules/common/users.nix new file mode 100644 index 0000000..62afaa4 --- /dev/null +++ b/modules/common/users.nix @@ -0,0 +1,50 @@ +{ lib, config, ... }: +with lib; +let + userModule = types.submodule { + options = { + description = mkOption { + type = types.str; + }; + + groups = mkOption { + type = types.listOf types.str; + }; + + uid = mkOption { + type = types.nullOr types.int; + }; + + shell = mkOption { + type = types.package; + }; + + enableHomeManagerProfile = mkOption { + type = types.bool; + default = false; + }; + + homeManagerConfig = mkOption { + default = { }; + }; + }; + }; +in +{ + options.machineUsers = mkOption { + type = types.attrsOf userModule; + }; + + config = { + users.users = builtins.mapAttrs + (name: value: { + isNormalUser = true; + home = "/home/${name}"; + description = value.description; + extraGroups = value.groups; + shell = value.shell; + uid = mkIf (value.uid != null) value.uid; + }) + config.machineUsers; + }; +} diff --git a/modules/server/default.nix b/modules/server/default.nix new file mode 100644 index 0000000..f1a624c --- /dev/null +++ b/modules/server/default.nix @@ -0,0 +1,3 @@ +{ lib, config, ... }: +with lib; +{ } diff --git a/modules/workstation/bluetooth.nix b/modules/workstation/bluetooth.nix new file mode 100644 index 0000000..6dd6f04 --- /dev/null +++ b/modules/workstation/bluetooth.nix @@ -0,0 +1,19 @@ +{ lib, config, ... }: +with lib; +{ + options.enableBluetooth = mkOption { + type = types.bool; + default = true; + example = false; + description = '' + Enable the bluetooth stack + ''; + }; + + config = mkIf config.enableBluetooth { + hardware.bluetooth = { + enable = true; + }; + services.blueman.enable = true; + }; +} diff --git a/modules/workstation/default.nix b/modules/workstation/default.nix new file mode 100644 index 0000000..256f062 --- /dev/null +++ b/modules/workstation/default.nix @@ -0,0 +1,50 @@ +{ lib, config, pkgs, machineInfos, sopsHmModule, ... }: +with lib; +{ + + imports = [ + ./sound.nix + ./desktop.nix + ./bluetooth.nix + ]; + + options.enableHomeManager = mkOption { + type = types.bool; + default = true; + example = false; + description = '' + Whether to install and use home-manager on this machine. + ''; + }; + + config = { + enableHomeManager = machineInfos.enableHomeManager; + + home-manager.useGlobalPkgs = mkIf config.enableHomeManager true; + home-manager.useUserPackages = mkIf config.enableHomeManager true; + home-manager.sharedModules = mkIf config.enableHomeManager [ + ./home-manager + sopsHmModule + ]; + home-manager.users = builtins.mapAttrs + (name: value: + mkIf value.enableHomeManagerProfile ({ + home.username = name; + home.homeDirectory = "/home/${name}"; + home.stateVersion = machineInfos.stateVersion; + programs.home-manager.enable = true; + enableFishShell = value.shell == pkgs.fish; + isProfessional = config.isProfessional; + } // value.homeManagerConfig) + ) + config.machineUsers; + + programs.dconf.enable = true; + security.polkit.enable = true; + services.dbus.enable = true; + + fonts.fontconfig.enable = true; + + services.gnome.gnome-keyring.enable = true; + }; +} diff --git a/modules/workstation/desktop.nix b/modules/workstation/desktop.nix new file mode 100644 index 0000000..388d411 --- /dev/null +++ b/modules/workstation/desktop.nix @@ -0,0 +1,17 @@ +{ config, lib, pkgs, ... }: +with lib; +let + usersHasSway = builtins.any + (user: + config.home-manager.users.${user}.desktop.enableSwayStack + ) + (builtins.attrNames config.machineUsers); +in +{ + programs.sway.enable = usersHasSway; + xdg.portal = mkIf usersHasSway { + enable = true; + wlr.enable = true; + extraPortals = [ pkgs.xdg-desktop-portal-gtk ]; + }; +} diff --git a/modules/workstation/home-manager/communication.nix b/modules/workstation/home-manager/communication.nix new file mode 100644 index 0000000..cda44e3 --- /dev/null +++ b/modules/workstation/home-manager/communication.nix @@ -0,0 +1,38 @@ +{ lib, pkgs, config, ... }: +with lib; +{ + options = { + communication.discord.enable = mkOption { + type = types.bool; + default = !config.isProfessional; + example = true; + }; + + communication.slack.enable = mkOption { + type = types.bool; + default = config.isProfessional; + example = true; + }; + + communication.weechat.enable = mkOption { + type = types.bool; + default = true; + example = false; + }; + + communication.matrix.enable = mkOption { + type = types.bool; + default = !config.isProfessional; + example = false; + }; + }; + + config.home.packages = with pkgs; [ + (mkIf config.communication.discord.enable (discord.override { + nss = nss_latest; + })) + (mkIf config.communication.slack.enable slack) + (mkIf config.communication.weechat.enable weechat) + (mkIf config.communication.matrix.enable element) + ]; +} diff --git a/modules/workstation/home-manager/default.nix b/modules/workstation/home-manager/default.nix new file mode 100644 index 0000000..732e540 --- /dev/null +++ b/modules/workstation/home-manager/default.nix @@ -0,0 +1,73 @@ +{ pkgs, lib, ... }: +with lib; +let + multimediaPackages = with pkgs; [ + qpwgraph + feh + gimp + vlc + ]; + + soundPackages = with pkgs; [ + pulseaudio + pavucontrol + pamixer + ]; + + yubikeyTools = with pkgs; [ + yubikey-personalization + yubico-pam + yubikey-manager + ]; + +in +{ + imports = [ + ./desktop + ./development + ./neovim + ./fish.nix + ./termux.nix + ./gpg.nix + ./communication.nix + ./mail.nix + ]; + + options.isProfessional = mkOption { + type = types.bool; + }; + + config = { + + fonts.fontconfig.enable = true; + + home.packages = with pkgs; [ + htop + firefox + autojump + nextcloud-client + keepassxc + ranger + libreoffice + tldr + zathura + lazygit + ] ++ multimediaPackages + ++ soundPackages + ++ yubikeyTools; + + # XDG-Mime configuration + xdg.mime.enable = true; + xdg.mimeApps.enable = true; + xdg.mimeApps.associations.added = { + "x-scheme-handler/https" = "firefox.desktop"; + "x-scheme-handler/http" = "firefox.desktop"; + }; + xdg.mimeApps.defaultApplications = { + "x-scheme-handler/https" = "firefox.desktop"; + "x-scheme-handler/http" = "firefox.desktop"; + "text/html" = "firefox.desktop"; + }; + }; + +} diff --git a/modules/workstation/home-manager/desktop/alacritty.nix b/modules/workstation/home-manager/desktop/alacritty.nix new file mode 100644 index 0000000..8a76c64 --- /dev/null +++ b/modules/workstation/home-manager/desktop/alacritty.nix @@ -0,0 +1,88 @@ +{ config, lib, ... }: +with lib; +let + tmuxFix = { + env = { + TERM = "xterm-256color"; + }; + }; +in +{ + programs.alacritty = mkIf config.desktop.enableSwayStack { + enable = true; + settings = { + font = { + normal = { + family = "JetBrainsMono Nerd Font Mono"; + style = "Regular"; + }; + size = 10.0; + }; + + colors = { + primary = { + background = "#2e3440"; + foreground = "#d8dee9"; + dim_foreground = "#a5abb6"; + }; + cursor = { + text = "#2e3440"; + cursor = "#d8dee9"; + }; + vi_mode_cursor = { + text = "#2e3440"; + cursor = "#d8dee9"; + }; + selection = { + text = "CellForeground"; + background = "#4c566a"; + }; + search = { + matches = { + foreground = "CellBackground"; + background = "#88c0d0"; + }; + }; + + footer_bar = { + background = "#434c5e"; + foreground = "#d8dee9"; + }; + normal = { + black = "#3b4252"; + red = "#bf616a"; + green = "#a3be8c"; + yellow = "#ebcb8b"; + blue = "#81a1c1"; + magenta = "#b48ead"; + cyan = "#88c0d0"; + white = "#e5e9f0"; + }; + bright = { + black = "#4c566a"; + red = "#bf616a"; + green = "#a3be8c"; + yellow = "#ebcb8b"; + blue = "#81a1c1"; + magenta = "#b48ead"; + cyan = "#8fbcbb"; + white = "#eceff4"; + }; + dim = { + black = "#373e4d"; + red = "#94545d"; + green = "#809575"; + yellow = "#b29e75"; + blue = "#68809a"; + magenta = "#8c738c"; + cyan = "#6d96a5"; + white = "#aeb3bb"; + }; + }; + + window = { + opacity = 1; + }; + } // tmuxFix; + }; +} diff --git a/modules/workstation/home-manager/desktop/default.nix b/modules/workstation/home-manager/desktop/default.nix new file mode 100644 index 0000000..d0f2cd5 --- /dev/null +++ b/modules/workstation/home-manager/desktop/default.nix @@ -0,0 +1,52 @@ +{ lib, config, pkgs, ... }: +with lib; +let + desktopPackages = with pkgs; [ + xwayland + grim + slurp + wl-clipboard + clipman + wf-recorder + (nerdfonts.override { fonts = [ "JetBrainsMono" ]; }) + qt5ct + libsForQt5.qtstyleplugin-kvantum + font-awesome + nordzy-cursor-theme + jetbrains-mono + xdg-utils + libnotify + ]; +in +{ + imports = [ + ./sway.nix + ./alacritty.nix + ./swaylock.nix + ./waybar.nix + ./wofi.nix + ./mako.nix + ]; + + options.desktop.enableSwayStack = mkOption { + type = types.bool; + default = true; + }; + + config = mkIf config.desktop.enableSwayStack { + home.packages = desktopPackages; + + # Theming GTK + gtk = { + enable = true; + theme = { + name = "Nordic-darker"; + package = pkgs.nordic; + }; + cursorTheme = { + name = "Nordzy-cursors"; + package = pkgs.nordzy-cursor-theme; + }; + }; + }; +} diff --git a/modules/workstation/home-manager/desktop/mako.nix b/modules/workstation/home-manager/desktop/mako.nix new file mode 100644 index 0000000..07b57c1 --- /dev/null +++ b/modules/workstation/home-manager/desktop/mako.nix @@ -0,0 +1,29 @@ +{ lib, config, ... }: +with lib; +{ + services.mako = mkIf config.desktop.enableSwayStack { + enable = true; + + layer = "overlay"; + anchor = "top-right"; + font = "JetBrainsMono Nerd Font 10"; + backgroundColor = "#3b4252"; + textColor = "#d8dee9"; + width = 330; + height = 100; + borderRadius = 2; + defaultTimeout = 15000; + + extraConfig = '' + [urgency=low] + border-color=#434c5e + + [urgency=normal] + border-color=#4c566a + + [urgency=high] + default-timeout=0 + border-color=#bf616a + ''; + }; +} diff --git a/modules/workstation/home-manager/desktop/sway.nix b/modules/workstation/home-manager/desktop/sway.nix new file mode 100644 index 0000000..8a144f1 --- /dev/null +++ b/modules/workstation/home-manager/desktop/sway.nix @@ -0,0 +1,245 @@ +{ config, pkgs, lib, ... }: +with lib; +let + gnomeSchema = "org.gnome.desktop.interface"; + monitorModule = types.submodule { + options = { + name = mkOption { + type = types.str; + }; + resolution = mkOption { + type = types.str; + }; + position = mkOption { + type = types.str; + }; + defaultWorkspace = mkOption { + type = types.int; + }; + }; + }; +in +{ + options = { + desktop.monitors = mkOption { + type = types.listOf monitorModule; + }; + }; + + config.wayland.windowManager.sway = mkIf config.desktop.enableSwayStack { + enable = true; + #systemd.enable = false; + + config = rec { + modifier = "Mod4"; + + left = "left"; + right = "right"; + up = "up"; + down = "down"; + + terminal = "${pkgs.alacritty}/bin/alacritty"; + menu = "${pkgs.wofi}/bin/wofi --show drun,run"; + + fonts = { + names = [ "pango:JetBrainsMono Nerd Font Mono" ]; + size = 11.0; + }; + + input = { + "*" = { + xkb_layout = "fr"; + # xkb_options = "compose:ralt"; + }; + }; + + seat = { + "seat0" = { + "xcursor_theme" = "Nordzy-cursors"; + }; + }; + output = builtins.listToAttrs + (builtins.map + (monitor: { + name = monitor.name; + value = { + resolution = monitor.resolution; + position = monitor.position; + }; + }) + config.desktop.monitors) // { + "*".bg = "/home/dala/Perso/wallpapers/tanuki.jpg fill"; + }; + workspaceOutputAssign = map + (monitor: { + output = monitor.name; + workspace = builtins.toString monitor.defaultWorkspace; + }) + config.desktop.monitors; + startup = [ + { + command = '' + ${pkgs.swayidle}/bin/swayidle -w \ + timeout 1200 '${pkgs.swaylock}/bin/swaylock -f' \ + timeout 1800 'swaymsg "output * dpms off"' resume 'swaymsg "output * dpms on"' \ + before-sleep '${pkgs.swaylock}/bin/swaylock -f' + ''; + } + { command = "${pkgs.nextcloud-client}/bin/nextcloud --background"; } + { command = "${pkgs.keepassxc}/bin/keepassxc"; } + { + command = '' + ${pkgs.wl-clipboard}/bin/wl-paste -t text --watch ${pkgs.clipman}/bin/clipman store --no-persist + ''; + } + { + command = "${pkgs.glib}/bin/gsettings set ${gnomeSchema} gtk-theme 'Nordic'"; + always = true; + } + { + command = "${pkgs.glib}/bin/gsettings set ${gnomeSchema} cursor-theme 'Nordzy-cursors'"; + always = true; + } + { + command = "${pkgs.glib}/bin/gsettings set ${gnomeSchema} font-name 'JetBrainsMono Nerd Font Mono'"; + always = true; + } + ]; + + modes = { + resize = { + "Left" = "resize shrink width 10px"; + "Down" = "resize grow height 10px"; + "Up" = "resize shrink height 10px"; + "Right" = "resize grow width 10px"; + + "Return" = "mode default"; + "Escape" = "mode default"; + }; + }; + + gaps = { + inner = 5; + smartGaps = true; + }; + + floating = { + modifier = "${modifier} normal"; + }; + + bars = [{ + command = "${pkgs.waybar}/bin/waybar"; + }]; + + keybindings = { + "${modifier}+Return" = "exec ${terminal}"; + "${modifier}+Shift+q" = "kill"; + "${modifier}+d" = "exec ${menu}"; + "${modifier}+Shift+r" = "reload"; + "${modifier}+Shift+e" = "exec swaymsg exit"; + "${modifier}+Shift+l" = "exec swaylock -f"; + + "${modifier}+Left" = "focus left"; + "${modifier}+Down" = "focus down"; + "${modifier}+Up" = "focus up"; + "${modifier}+Right" = "focus right"; + + "${modifier}+Shift+Left" = "move left"; + "${modifier}+Shift+Down" = "move down"; + "${modifier}+Shift+Up" = "move up"; + "${modifier}+Shift+Right" = "move right"; + + "${modifier}+1" = "workspace 1"; + "${modifier}+2" = "workspace 2"; + "${modifier}+3" = "workspace 3"; + "${modifier}+4" = "workspace 4"; + "${modifier}+5" = "workspace 5"; + "${modifier}+6" = "workspace 6"; + "${modifier}+7" = "workspace 7"; + "${modifier}+8" = "workspace 8"; + "${modifier}+9" = "workspace 9"; + "${modifier}+0" = "workspace 10"; + + "${modifier}+ampersand" = "workspace 1"; + "${modifier}+eacute" = "workspace 2"; + "${modifier}+quotedbl" = "workspace 3"; + "${modifier}+apostrophe" = "workspace 4"; + "${modifier}+parenleft" = "workspace 5"; + "${modifier}+minus" = "workspace 6"; + "${modifier}+egrave" = "workspace 7"; + "${modifier}+underscore" = "workspace 8"; + "${modifier}+ccedilla" = "workspace 9"; + "${modifier}+agrave" = "workspace 10"; + + "${modifier}+Shift+1" = "move container to workspace 1"; + "${modifier}+Shift+2" = "move container to workspace 2"; + "${modifier}+Shift+3" = "move container to workspace 3"; + "${modifier}+Shift+4" = "move container to workspace 4"; + "${modifier}+Shift+5" = "move container to workspace 5"; + "${modifier}+Shift+6" = "move container to workspace 6"; + "${modifier}+Shift+7" = "move container to workspace 7"; + "${modifier}+Shift+8" = "move container to workspace 8"; + "${modifier}+Shift+9" = "move container to workspace 9"; + "${modifier}+Shift+0" = "move container to workspace 10"; + + "${modifier}+Shift+ampersand" = "move container to workspace 1"; + "${modifier}+Shift+eacute" = "move container to workspace 2"; + "${modifier}+Shift+quotedbl" = "move container to workspace 3"; + "${modifier}+Shift+apostrophe" = "move container to workspace 4"; + "${modifier}+Shift+parenleft" = "move container to workspace 5"; + "${modifier}+Shift+minus" = "move container to workspace 6"; + "${modifier}+Shift+egrave" = "move container to workspace 7"; + "${modifier}+Shift+underscore" = "move container to workspace 8"; + "${modifier}+Shift+ccedilla" = "move container to workspace 9"; + "${modifier}+Shift+agrave" = "move container to workspace 10"; + + "${modifier}+h" = "splith"; + "${modifier}+v" = "splitv"; + + "${modifier}+s" = "layout stacking"; + "${modifier}+w" = "layout tabbed"; + "${modifier}+e" = "layout toggle split"; + + "${modifier}+f" = "fullscreen"; + "${modifier}+Shift+space" = "floating toggle"; + "${modifier}+space" = "focus mode_toggle"; + "${modifier}+a" = "focus parent"; + + "${modifier}+Shift+parenright" = "move scratchpad"; + + "${modifier}+parenright" = "scratchpad show"; + + "${modifier}+r" = "mode resize"; + + "XF86AudioRaiseVolume" = "exec --no-startup-id pactl set-sink-volume 0 +5%"; #increase sound volume + "XF86AudioLowerVolume" = "exec --no-startup-id pactl set-sink-volume 0 -5%"; #decrease sound volume + "XF86AudioMute" = "exec --no-startup-id pactl set-sink-mute 0 toggle"; # mute sound + + "XF86MonBrightnessUp" = "exec --no-startup-id light -A 10"; + "XF86MonBrightnessDown" = "exec --no-startup-id light -U 10"; + + "Control+XF86AudioMute" = "exec --no-startup-id pactl set-source-mute @DEFAULT_SOURCE@ toggle"; + + "Print" = "exec grim -g \"$(${pkgs.slurp}/bin/slurp)\" -t png - | wl-copy --type image/png"; + }; + }; + + extraConfig = '' + default_border pixel + for_window [class=".*"] inhibit_idle fullscreen + for_window [app_id=".*"] inhibit_idle fullscreen + ''; + + extraSessionCommands = '' + export WLR_NO_HARDWARE_CURSORS=1 + export XDG_CURRENT_DESKTOP=sway + export _JAVA_AWT_WM_NONREPARENTING=1 + export NIXOS_OZONE_WL=1 + export QT_QPA_PLATFORM=wayland + export QT_QPA_PLATFORMTHEME=qt5ct + export QT_WAYLAND_DISABLE_WINDOWDECORATION=1 + export MOZ_ENABLE_WAYLAND=1 + export SDL_VIDEODRIVER=wayland + ''; + }; +} diff --git a/modules/workstation/home-manager/desktop/swaylock.nix b/modules/workstation/home-manager/desktop/swaylock.nix new file mode 100644 index 0000000..c94cc75 --- /dev/null +++ b/modules/workstation/home-manager/desktop/swaylock.nix @@ -0,0 +1,52 @@ +{ lib, config, ... }: +with lib; +{ + programs.swaylock = mkIf config.desktop.enableSwayStack { + enable = true; + + settings = { + scaling = "fill"; + font = "JetBrainsMono"; + font-size = 20; + show-keyboard-layout = true; + disable-caps-lock-text = true; + indicator-caps-lock = true; + ignore-empty-password = true; + show-failed-attempts = true; + line-uses-inside = true; + + indicator-radius = 70; + indicator-thickness = 15; + + color = "#00000000"; + inside-color = "#2e3440a0"; + inside-ver-color = "#4c566aa0"; + inside-wrong-color = "#bf616aa0"; + inside-clear-color = "#434c5ea0"; + inside-caps-lock-color = "#d08770a0"; + + text-color = "#d8dee9d0"; + text-clear-color = "#d8dee9d0"; + text-ver-color = "#d8dee9d0"; + text-wrong-color = "#d8dee9d0"; + layout-bg-color = "#00000000"; + layout-text-color = "#d8dee9d0"; + + line-color = "#2e3440e0"; + line-clear-color = "#2e3440e0"; + line-caps-lock-color = "#2e3440e0"; + line-ver-color = "#2e3440e0"; + line-wrong-color = "#2e3440e0"; + separator-color = "#2e3440e0"; + + ring-color = "#5e81acf0"; + ring-clear-color = "#5e81aca0"; + ring-caps-lock-color = "#bf616af0"; + ring-ver-color = "#81a1c1f0"; + ring-wrong-color = "#d08770f0"; + + bs-hl-color = "#d08770a0"; + key-hl-color = "#81a1c1a0"; + }; + }; +} diff --git a/modules/workstation/home-manager/desktop/waybar.nix b/modules/workstation/home-manager/desktop/waybar.nix new file mode 100644 index 0000000..e725ba7 --- /dev/null +++ b/modules/workstation/home-manager/desktop/waybar.nix @@ -0,0 +1,275 @@ +{ config, lib, ... }: +with lib; +{ + programs.waybar = mkIf config.desktop.enableSwayStack { + enable = true; + #systemd.enable = false; + + settings = [{ + layer = "top"; + position = "top"; + height = 30; + + modules-left = [ + "sway/workspaces" + "sway/mode" + ]; + + modules-center = [ + "sway/window" + ]; + + modules-right = [ + "memory" + "cpu" + "pulseaudio" + "network" + "battery" + "tray" + "sway/language" + "clock" + ]; + + "sway/workspaces" = { + "disable-scroll" = true; + "all-outputs" = false; + "format" = "{icon}"; + "format-icons" = { + "1:term" = ""; + "2:web" = ""; + "3:email" = ""; + "4:im" = ""; + "5:dev" = ""; + "6:music" = ""; + "7:graph" = ""; + "8:any" = ""; + "9:any" = ""; + "10:aux" = ""; + }; + }; + + "tray" = { + "icon-size" = 18; + "spacing" = 12; + }; + + "memory" = { + "format" = "{percentage:3}% 󰍛"; + "states" = { + "warning" = 70; + "critical" = 90; + }; + }; + + "cpu" = { + "format" = "{usage:3}% "; + "states" = { + "warning" = 70; + "critical" = 90; + }; + }; + + "pulseaudio" = { + "format" = "{volume:3}% {icon}"; + "format-bluetooth" = "{icon}"; + "format-muted" = "󰝟<\big>"; + "format-icons" = { + "headphone" = ""; + "hands-free" = ""; + "headset" = ""; + "phone" = ""; + "portable" = ""; + "car" = ""; + "default" = [ "" ]; + }; + + "on-click" = "pavucontrol"; + "on-scroll-up" = "pamixer -ui 2 && pamixer --get-volume > $SWAYSOCK.wob"; + "on-scroll-down" = "pamixer -ud 2 && pamixer --get-volume > $SWAYSOCK.wob"; + }; + + "network" = { + "format-wifi" = "{essid} "; + "format-ethernet" = ""; + "format-disconnected" = "󰌙"; + "format-linked" = ""; + "format-alt" = "{ifname}: {ipaddr}/{cidr}"; + "tooltip-format-ethernet" = " {bandwidthDownBits} {bandwidthUpBits}"; + "tooltip-format-wifi" = "{bandwidthDownBits} {bandwidthUpBits}"; + }; + + "battery" = { + "states" = { + "5pct" = 5; + "10pct" = 10; + "20pct" = 20; + "30pct" = 30; + "40pct" = 40; + "50pct" = 50; + "60pct" = 60; + "70pct" = 70; + "80pct" = 80; + "90pct" = 90; + "full" = 100; + }; + + "format" = "{capacity:3}% {icon}"; + "format-icons" = { + "5pct" = "󰂃"; + "10pct" = "󰁺"; + "20pct" = "󰁻"; + "30pct" = "󰁼"; + "40pct" = "󰁽"; + "50pct" = "󰁾"; + "60pct" = "󰁿"; + "70pct" = "󰂀"; + "80pct" = "󰂁"; + "90pct" = "󰂂"; + "full" = "󰁹"; + }; + "on-click" = "notify-send -u low -t 3000 'Battery Status' \"$(acpi)\""; + }; + + "clock" = { + "format-alt" = "{:%A, %B %d}"; + "tooltip-format" = "{:%Y %B}\n{calendar}"; + }; + }]; + + style = '' + @keyframes blink-warning { + to { + background-color: #bf616a; + } + } + + @keyframes blink-critical { + to { + color: #2e3440; + background-color: #bf616a; + } + } + + * { + border: none; + border-radius: 0; + font-family: JetBrainsMono, JetBrainsMono Nerd Font Mono, monospace; + font-size: 14px; + min-height: 0; + box-shadow: none; + text-shadow: none; + } + + window#waybar { + background-color: #3b4252; + color: #e5e9f0; + opacity: 0.9; + } + + #window { + font-family: JetBrainsMono, JetBrainsMono Nerd Font Mono, sans-serif; + } + + #workspaces { + background-color: #4c566a; + } + + #workspaces button { + padding: 3px 9px 0px 9px; + background: transparent; + color: #e5e9f0; + border-bottom: 3px solid transparent; + font-weight: 900; + } + + #workspaces button.focused { + background-color: #434c5e; + color: #eceff4; + border-bottom: 3px solid #ebcb8b; + } + + #workspaces button:hover { + background-color: #5e81ac; + } + + #mode { + padding: 0px 9px; + background-color: #a3be8c; + color: #3b4252; + font-family: JetBrains Mono, sans-serif; + font-size: 14px; + font-weight: bold; + } + + #clock, #language, #pulseaudio, #tray, #memory, #cpu, #battery, #network { + padding: 0px 8px; + color: #d8dee9; + font-size: 14px; + } + + #clock { + background-color: #4c566a; + font-weight: bold; + } + + #language { + color: #d8dee9; + font-weight: bold; + } + + #pulseaudio { + } + + #pulseaudio.muted { + color: #d08770; + } + + #tray { + margin-left: 10px; + } + + #cpu { + padding-left: 0px; + font-size: 14px; + } + + #cpu.warning { + color: #ebcb8b; + } + + #cpu.critical { + color: #d08770; + } + + #memory { + padding-left: 0px; + font-size: 14px; + } + + #memory.warning { + color: #ebcb8b; + } + + #memory.critical { + color: #d08770; + } + + #battery { + font-size: 14px; + animation-timing-function: ease-in-out; + animation-iteration-count: infinite; + animation-direction: alternate; + } + + #battery.20pct.discharging { + animation-name: blink-warning; + animation-duration: 3s; + } + + #battery.10pct.discharging { + animation-name: blink-critical; + animation-duration: 2s; + } + ''; + }; +} diff --git a/modules/workstation/home-manager/desktop/wofi.nix b/modules/workstation/home-manager/desktop/wofi.nix new file mode 100644 index 0000000..8574ecc --- /dev/null +++ b/modules/workstation/home-manager/desktop/wofi.nix @@ -0,0 +1,74 @@ +{ pkgs, config, lib, ... }: +with lib; +{ + programs.wofi = mkIf config.desktop.enableSwayStack { + enable = true; + + settings = { + allow_images = true; + allow_markup = true; + insensitive = true; + hide_scroll = true; + no_actions = false; + term = "${pkgs.alacritty}/bin/alacritty"; + width = "35%"; + lines = 8; + always_parse_args = true; + }; + + style = '' + #window { + background-color: transparent; + border-radius: 15px; + font-family: sans-serif; + animation: fadeIn; + animation-duration: 0.2s; + } + + @keyframes fadeIn { + from { opacity: 0; } + to { opacity: 1; } + } + + #outer-box { + margin: 15px; + border-radius: 15px; + background-color: #3b4252; + box-shadow: 0px 0px 5px 0 #0F0F0F; + } + + #inner-box { + color: #d8dee9; + padding: 10px; + padding-top: 5px; + } + + #input { + color: #e5e9f0; + border: 2px solid #5e81ac; + background-color: #4c566a; + padding: 6px; + margin: 15px; + margin-bottom: 0px; + font-size: 16px; + border-radius: 5px; + } + + #entry { + border-radius: 5px; + padding: 7px; + margin: 0px 5px 0px 5px; + } + + #text { + font-size: 16px; + padding: 7px; + color: #d8dee9; + } + + #img { + padding: 4px; + } + ''; + }; +} diff --git a/modules/workstation/home-manager/development/default.nix b/modules/workstation/home-manager/development/default.nix new file mode 100644 index 0000000..d9a9903 --- /dev/null +++ b/modules/workstation/home-manager/development/default.nix @@ -0,0 +1,35 @@ +{ config, lib, pkgs, ... }: +with lib; +{ + imports = [ + ./embedded.nix + ]; + + options.development.enableGit = mkOption { + type = types.bool; + default = true; + example = false; + description = '' + Enable git and its configuration. + ''; + }; + + config.programs.git = mkIf config.development.enableGit { + enable = true; + package = pkgs.gitAndTools.gitFull; + userName = "Victor Mignot"; + userEmail = "dala@dalaran.fr"; + signing = mkIf config.enableGPGKeyring { + key = "BEAFED3D"; + signByDefault = true; + }; + extraConfig = { + init = { + defaultBranch = "main"; + }; + core = { + editor = "${pkgs.neovim}/bin/nvim"; + }; + }; + }; +} diff --git a/modules/workstation/home-manager/development/embedded.nix b/modules/workstation/home-manager/development/embedded.nix new file mode 100644 index 0000000..569b657 --- /dev/null +++ b/modules/workstation/home-manager/development/embedded.nix @@ -0,0 +1,22 @@ +{ lib, config, pkgs, ... }: +with lib; +{ + options.development.embedded.enableTools = mkOption { + type = types.bool; + default = false; + example = true; + description = '' + Enable embedded tools. + ''; + }; + + options.development.embedded.toolsList = mkOption { + type = types.listOf types.package; + default = with pkgs; [ + qemu + minicom + ]; + }; + + config.home.packages = lib.mkIf config.development.embedded.enableTools config.development.embedded.toolsList; +} diff --git a/modules/workstation/home-manager/fish.nix b/modules/workstation/home-manager/fish.nix new file mode 100644 index 0000000..85e0952 --- /dev/null +++ b/modules/workstation/home-manager/fish.nix @@ -0,0 +1,31 @@ +{ lib, pkgs, config, ... }: +with lib; +{ + options.enableFishShell = mkOption { + type = types.bool; + }; + + config.programs.fish = mkIf config.enableFishShell { + enable = true; + + plugins = [ + { + name = "bobthefish"; + src = pkgs.fetchFromGitHub { + owner = "oh-my-fish"; + repo = "theme-bobthefish"; + rev = "c2c47dc964a257131b3df2a127c2631b4760f3ec"; + sha256 = "sha256-LB4g+EA3C7OxTuHfcxfgl8IVBe5NufFc+5z9VcS0Bt0="; + fetchSubmodules = true; + }; + } + ]; + + shellInit = '' + set -g theme_color_scheme nord + if [ -z $DISPLAY ] && [ "$(tty)" = /dev/tty1 ] + exec ${pkgs.sway}/bin/sway + end + ''; + }; +} diff --git a/modules/workstation/home-manager/gpg.nix b/modules/workstation/home-manager/gpg.nix new file mode 100644 index 0000000..b1d0926 --- /dev/null +++ b/modules/workstation/home-manager/gpg.nix @@ -0,0 +1,24 @@ +{ config, lib, ... }: +with lib; +{ + options.enableGPGKeyring = mkOption { + type = types.bool; + default = true; + example = false; + description = '' + Add GPG keyring and GPG Agent configuration. + ''; + }; + + config = mkIf config.enableGPGKeyring { + programs.gpg.enable = true; + + services.gpg-agent = { + enable = true; + enableScDaemon = true; + enableSshSupport = true; + sshKeys = [ "40DE2FEE4D3C5E2C" ]; + pinentryFlavor = "curses"; + }; + }; +} diff --git a/modules/workstation/home-manager/mail.nix b/modules/workstation/home-manager/mail.nix new file mode 100644 index 0000000..415aeb2 --- /dev/null +++ b/modules/workstation/home-manager/mail.nix @@ -0,0 +1,125 @@ +{ lib, pkgs, config, ... }: +with lib; +let + mailAccountModule = types.submodule { + isPrimary = mkOption { + type = types.bool; + default = false; + }; + + mailAddress = mkOption { + type = types.str; + }; + + mailPasswdEval = mkOption { + type = types.str; + }; + + imapHost = mkOption { + type = types.str; + }; + + smtpHost = mkOption { + type = types.str; + }; + }; + + defaultExtraMailboxes = [ + "Archive" + "Receipts" + "Junk" + "Drafts" + "Sent" + "Trash" + ]; + + signature = { + text = '' + Victor Mignot + ''; + showSignature = "append"; + }; + + hasNoAddress = config.communication.mailAccounts == null; +in +{ + options.communication.mailAccounts = mkOption { + type = types.nullOr (types.attrsOf mailAccountModule); + default = null; + }; + + config = mkIf (!hasNoAddress) { + + accounts.email.accounts = builtins.mapAttrs + (name: value: { + primary = value.isPrimary; + address = value.mailAddress; + userName = value.mailAddress; + realName = "Victor Mignot"; + imap.host = value.imapHost; + smtpHost = value.smtpHost; + passwordCommand = value.mailPasswdEval; + inherit signature; + + mbsync = { + enable = true; + create = "both"; + expunge = "both"; + patterns = [ "*" ]; + subFolders = "Verbatim"; + }; + + msmtp.enable = true; + + neomutt = { + enable = true; + mailboxName = "${name}/Inbox"; + extraMailboxes = map + (mb: { + mailbox = mb; + name = "${name}/${mb}"; + }) + defaultExtraMailboxes; + }; + }) + config.communication.mailAccounts; + + services.mbsync.enable = true; + programs.mbsync.enable = true; + + accounts.email.maildirBasePath = "Mail"; + programs.neomutt = { + enable = true; + sidebar.enable = true; + checkStatsInterval = 30; + sort = "reverse-date"; + extraConfig = '' + set edit_headers = yes + set use_from = yes + set send_charset = "utf-8" + + color body brightwhite default ^[[:space:]].* + color body yellow default ^(diff).* + color body brightwhite default ^(\s).* + color body cyan default ^(Signed-off-by).* + color body cyan default ^(Docker-DCO-1.1-Signed-off-by).* + color body brightwhite default ^(Cc) + color body yellow default "^diff \-.*" + color body brightwhite default "^index [a-f0-9].*" + color body brightblue default "^---$" + color body white default "^\-\-\- .*" + color body white default "^[\+]{3} .*" + color body green default "^[\+][^\+]+.*" + color body red default "^\-[^\-]+.*" + color body brightblue default "^@@ .*" + color body green default "LGTM" + color body brightmagenta default "-- Commit Summary --" + color body brightmagenta default "-- File Changes --" + color body brightmagenta default "-- Patch Links --" + color body green default "^Merged #.*" + color body red default "^Closed #.*" + color body brightblue default "^Reply to this email.*" + ''; + }; + }; +} diff --git a/modules/workstation/home-manager/neovim/default.nix b/modules/workstation/home-manager/neovim/default.nix new file mode 100644 index 0000000..18a1448 --- /dev/null +++ b/modules/workstation/home-manager/neovim/default.nix @@ -0,0 +1,165 @@ +{ lib, config, pkgs, ... }: +with lib; +{ + options.desktop.enableNeovim = mkOption { + type = types.bool; + default = true; + example = false; + description = '' + Whether to use Neovim and its config. + ''; + }; + + config.home.sessionVariables."EDITOR" = mkIf config.desktop.enableNeovim "${pkgs.neovim}/bin/nvim"; + + config.programs.neovim = mkIf config.desktop.enableNeovim { + enable = true; + + viAlias = true; + vimAlias = true; + vimdiffAlias = true; + + extraConfig = '' + luafile ${./luaconfig/settings.lua} + luafile ${./luaconfig/keybindings.lua} + luafile ${./luaconfig/lspconfig.lua} + ''; + + extraPackages = with pkgs; [ + nixfmt + rnix-lsp + nil + ripgrep + entr + ]; + + plugins = with pkgs.vimPlugins; [ + + # Theming + { + plugin = onenord-nvim; + type = "lua"; + config = '' + require('onenord').setup() + ''; + } + { + plugin = lualine-nvim; + type = "lua"; + config = '' + require('lualine').setup() + ''; + } + vim-devicons + + # Utility plugins + { + plugin = nerdtree; + type = "lua"; + config = '' + vim.g.NERDTreeShowHidden = 1 + + vim.keymap.set('n', '', ':NERDTreeToggle', { desc = 'Toogle NERDTree pane' }) + vim.keymap.set('n', '', ':NERDTreeFind', { desc = 'Search file in NERDTree' }) + vim.keymap.set('n', '', ':NERDTreeFocus', { desc = 'Focus on the NERDTreePane' }) + + -- Keep the same NERDTree pane on each window + vim.api.nvim_create_autocmd("BufWinEnter", { pattern = "*", command = "if getcmdwintype() == \'\' | silent NERDTreeMirror | endif" }) + ''; + } + nerdtree-git-plugin + { + plugin = toggleterm-nvim; + type = "lua"; + config = '' + require("toggleterm").setup{} + + vim.keymap.set('n', 'tf', ':ToggleTerm direction=float', { desc = 'Open a new terminal in float buffer' }) + vim.keymap.set('n', 'tt', ':ToggleTerm direction=tab', { desc = 'Open a new terminal in a new tab' }) + vim.keymap.set('n', 'tv', ':ToggleTerm direction=vertical', { desc = 'Open in a vertical splitted buffer' }) + vim.keymap.set('n', 'th', ':ToggleTerm', { desc = 'Open in a horizontal splitted buffer' }) + ''; + } + { + plugin = neogit; + type = "lua"; + config = '' + require('neogit').setup {} + ''; + } + { + plugin = gitsigns-nvim; + type = "lua"; + config = '' + require('gitsigns').setup() + ''; + } + vim-multiple-cursors + vim-sleuth + vim-commentary + { + plugin = telescope-nvim; + type = "lua"; + config = '' + local telescope = require('telescope.builtin') + + vim.keymap.set('n', 'ff', telescope.find_files, { desc = 'Search file with Telescope' }) + vim.keymap.set('n', 'fg', telescope.live_grep, { desc = 'Live grep with Telescope'}) + vim.keymap.set('n', 'fb', telescope.buffers, { desc = 'Search amongst current buffers (opened files)'}) + vim.keymap.set('n', 'fh', telescope.help_tags, { desc = 'Search within nvim manual'}) + vim.keymap.set('n', 'fs', telescope.lsp_workspace_symbols, { desc = 'Search symbol' }) + ''; + } + plenary-nvim + telescope-fzy-native-nvim + + # Language support plugins + vim-nix + vim-nixhash + { + plugin = rust-vim; + type = "lua"; + config = '' + vim.g.rustfmt_autosave = 1 + ''; + } + vim-markdown + markdown-preview-nvim + + { + plugin = vimtex; + type = "viml"; + config = '' + let g:vimtex_view_method = 'zathura' + let g:vimtex_compiler_method = 'tectonic' + + let g:vimtex_compiler_tectonic = { + \'out_dir' : ' ', + \'hooks' : [], + \'options' : [ + \ '--keep-logs', + \ '--synctex', + \ '-Zshell-escape', + \ '-Zshell-escape-cwd=$PWD' + \], + \} + + ''; + } + + # Autocompletion and LSP server + nvim-lspconfig + nvim-cmp + cmp-path + cmp-cmdline + cmp-buffer + cmp-nvim-lsp + vim-vsnip + ]; + }; + + config.xdg.configFile.nvim = mkIf config.desktop.enableNeovim { + source = ./luaconfig; + recursive = true; + }; +} diff --git a/modules/workstation/home-manager/neovim/luaconfig/keybindings.lua b/modules/workstation/home-manager/neovim/luaconfig/keybindings.lua new file mode 100644 index 0000000..4e7a878 --- /dev/null +++ b/modules/workstation/home-manager/neovim/luaconfig/keybindings.lua @@ -0,0 +1,11 @@ +-- Navigate around panes +vim.keymap.set('n', '', 'h', { desc = 'Navigate to left pane' }) +vim.keymap.set('n', '', 'l', { desc = 'Navigate to right pane' }) +vim.keymap.set('n', '', 'k', { desc = 'Navigate to upper pane' }) +vim.keymap.set('n', '', 'j', { desc = 'Toogle lower pane' }) + +-- Move panes position +vim.keymap.set('n', '', 'H', { desc = 'Navigate to left pane' }) +vim.keymap.set('n', '', 'L', { desc = 'Navigate to right pane' }) +vim.keymap.set('n', '', 'K', { desc = 'Navigate to upper pane' }) +vim.keymap.set('n', '', 'J', { desc = 'Toogle lower pane' }) diff --git a/modules/workstation/home-manager/neovim/luaconfig/lspconfig.lua b/modules/workstation/home-manager/neovim/luaconfig/lspconfig.lua new file mode 100644 index 0000000..816475d --- /dev/null +++ b/modules/workstation/home-manager/neovim/luaconfig/lspconfig.lua @@ -0,0 +1,94 @@ +-- Nvim LSP Config + +local map_opts = { noremap=true, silent=true } + +vim.keymap.set('n', 'e', vim.diagnostic.open_float, map_opts) +vim.keymap.set('n', 'p', vim.diagnostic.goto_prev, map_opts) +vim.keymap.set('n', 'n', vim.diagnostic.goto_next, map_opts) +vim.keymap.set('n', 'l', vim.diagnostic.setloclist, map_opts) + + +-- Enable keybinds on LSP server attach +local on_attach = function(client, bufnr) + -- Enable completion triggered by + vim.api.nvim_buf_set_option(bufnr, 'omnifunc', 'v:lua.vim.lsp.omnifunc') + + -- Mappings + local bufopts = { noremap=true, silent=true, buffer=bufnr } + vim.keymap.set('n', 'gD', vim.lsp.buf.declaration, bufopts) + vim.keymap.set('n', 'gd', vim.lsp.buf.definition, bufopts) + vim.keymap.set('n', 'K', vim.lsp.buf.hover, bufopts) + vim.keymap.set('n', 'gi', vim.lsp.buf.implementation, bufopts) + vim.keymap.set('n', '', vim.lsp.buf.signature_help, bufopts) + vim.keymap.set('n', 'wa', vim.lsp.buf.add_workspace_folder, bufopts) + vim.keymap.set('n', 'wr', vim.lsp.buf.remove_workspace_folder, bufopts) + vim.keymap.set('n', 'wl', function() + print(vim.inspect(vim.lsp.buf.list_workspace_folders())) + end, bufopts) + vim.keymap.set('n', 'D', vim.lsp.buf.type_definition, bufopts) + vim.keymap.set('n', 'rn', vim.lsp.buf.rename, bufopts) + vim.keymap.set('n', 'ca', vim.lsp.buf.code_action, bufopts) + vim.keymap.set('n', 'gr', vim.lsp.buf.references, bufopts) + vim.keymap.set('n', 'f', function() vim.lsp.buf.format { async = true } end, bufopts) +end + +-- Set-up autocompletion + +local cmp = require('cmp') +vim.opt.completeopt = {'menu', 'menuone', 'noselect'} + +cmp.setup({ + snippet = { + -- Necessary snippet engine + expand = function (args) + vim.fn["vsnip#anonymous"](args.body) + end, + }, + + window = { + -- completion = cmp.config.window.bordered(), + -- documentation = cmp.config.window.bordered, + }, + + mapping = cmp.mapping.preset.insert({ + [''] = cmp.mapping.scroll_docs(4), + [''] = cmp.mapping.scroll_docs(-4), + [''] = cmp.mapping.complete(), + [''] = cmp.mapping.abort(), + [''] = cmp.mapping.confirm({select = true}), + }), + + sources = cmp.config.sources({ + { name = 'nvim_lsp' }, + { name = 'vsnip' }, + }, { { name = 'buffer' } }), +}) + + +-- Language servers setup +local capabilities = require('cmp_nvim_lsp').default_capabilities() + +require('lspconfig')['rust_analyzer'].setup { + on_attach = on_attach, + capabilities = capabilities, +} + +require('lspconfig')['rnix'].setup { + on_attach = on_attach, + capabilities = capabilities +} + +require('lspconfig')["nil_ls"].setup { + on_attach = on_attach, + capabilities = capabilities +} + +require('lspconfig')['ltex'].setup { + on_attach = on_attach, + capabilities = capabilities +} + +require('lspconfig')['texlab'].setup { + on_attach = on_attach, + capabilities = capabilities +} diff --git a/modules/workstation/home-manager/neovim/luaconfig/settings.lua b/modules/workstation/home-manager/neovim/luaconfig/settings.lua new file mode 100644 index 0000000..1b1887a --- /dev/null +++ b/modules/workstation/home-manager/neovim/luaconfig/settings.lua @@ -0,0 +1,17 @@ +-- Set line numbers +vim.opt.number = true + +-- Replace tab with whitespaces +vim.opt.expandtab = true + +-- Set tabs as 4 whitespaces +vim.opt.tabstop = 4 + +-- Set indentation adaptability +vim.opt.autoindent = true + +-- Set default level of identation +vim.opt.shiftwidth = 4 + +-- Use the system clipboard +vim.opt.clipboard = 'unnamedplus' diff --git a/modules/workstation/home-manager/termux.nix b/modules/workstation/home-manager/termux.nix new file mode 100644 index 0000000..10aaf84 --- /dev/null +++ b/modules/workstation/home-manager/termux.nix @@ -0,0 +1,46 @@ +{ lib, config, pkgs, ... }: +with lib; +let + tmuxExtraConfig = '' + set -ag terminal-overrides ",xterm-256color:RGB" + ''; +in +{ + options.enableTermux = mkOption { + type = types.bool; + default = true; + example = false; + description = '' + Enable termux and the associated config. + ''; + }; + + config.programs.tmux = mkIf config.enableTermux { + enable = true; + + # Make windows count start to 1 + baseIndex = 1; + + # Use 24h clock + clock24 = true; + + shell = if config.enableFishShell then "${pkgs.fish}/bin/fish" else "${pkgs.bash}/bin/bash"; + + keyMode = "vi"; + + tmuxp.enable = true; + + terminal = "tmux-256color"; + + plugins = with pkgs.tmuxPlugins; [ + { + plugin = nord; + extraConfig = '' + set -g @plugin "arcticicestudio/nord-tmux" + ''; + } + ]; + + extraConfig = tmuxExtraConfig; + }; +} diff --git a/modules/workstation/sound.nix b/modules/workstation/sound.nix new file mode 100644 index 0000000..5f90ecc --- /dev/null +++ b/modules/workstation/sound.nix @@ -0,0 +1,11 @@ +{ ... }: +{ + services.pipewire = { + enable = true; + alsa.enable = true; + alsa.support32Bit = true; + pulse.enable = true; + }; + + programs.noisetorch.enable = true; +}