From 8a35a324453908c08e8906058e22b6a0ead915c3 Mon Sep 17 00:00:00 2001 From: Zoty Date: Fri, 22 May 2026 15:51:43 -0300 Subject: [PATCH] proper repo --- .envrc | 1 + .gitignore | 11 +++++ Justfile | 49 ++++++++++++++++++++++ README.md | 84 ++++++++++++++++++++++++++++++++++++++ flake.nix | 16 ++++++-- modules/_home/git.nix | 24 ++++------- modules/_home/niri.nix | 44 ++++++++++---------- modules/_home/xdg-dirs.nix | 15 +++++++ modules/core.nix | 6 +-- modules/creative.nix | 26 ++++++++++++ modules/den.nix | 12 +++++- modules/desktop.nix | 9 +--- modules/dev.nix | 76 ++++++++++++++++++---------------- modules/identity.nix | 27 ++++++++++++ modules/notebook.nix | 8 ---- modules/secrets.nix | 19 ++++----- modules/wayland.nix | 20 +++++++++ 17 files changed, 338 insertions(+), 109 deletions(-) create mode 100644 .envrc create mode 100644 .gitignore create mode 100644 Justfile create mode 100644 README.md create mode 100644 modules/_home/xdg-dirs.nix create mode 100644 modules/creative.nix create mode 100644 modules/identity.nix create mode 100644 modules/wayland.nix diff --git a/.envrc b/.envrc new file mode 100644 index 0000000..3550a30 --- /dev/null +++ b/.envrc @@ -0,0 +1 @@ +use flake diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5464327 --- /dev/null +++ b/.gitignore @@ -0,0 +1,11 @@ +# Nix build outputs +result +result-* + +# direnv cache +.direnv/ + +# Editor artifacts +.vscode/ +*.swp +*.swo diff --git a/Justfile b/Justfile new file mode 100644 index 0000000..79a7504 --- /dev/null +++ b/Justfile @@ -0,0 +1,49 @@ +# List all available recipes +default: + @just --list + +# Rebuild and switch to the new configuration (uses current hostname by default) +switch hostname=`hostname`: + sudo nixos-rebuild switch --flake .#{{hostname}} + +# Build without switching — useful to check the result before applying +build hostname=`hostname`: + nixos-rebuild build --flake .#{{hostname}} + +# Apply the new configuration temporarily (reverts on next boot) +test hostname=`hostname`: + sudo nixos-rebuild test --flake .#{{hostname}} + +# Update all flake inputs to their latest locked versions +update: + nix flake update + +# Update a single flake input (e.g. just update-input nixpkgs) +update-input input: + nix flake update {{input}} + +# Check the flake for evaluation errors +check: + nix flake check + +# Open a Nix REPL with the flake loaded +repl: + nix repl --expr 'builtins.getFlake (toString ./.)' + +# Delete Nix store paths older than 7 days and run the garbage collector +gc: + sudo nix-collect-garbage --delete-older-than 7d + nix-collect-garbage --delete-older-than 7d + +# List all system generations +generations: + sudo nix-env --list-generations --profile /nix/var/nix/profiles/system + +# Edit the SOPS-encrypted secrets file +secrets: + sops secrets/secrets.yaml + +# Show a diff between the running system and the current build +diff hostname=`hostname`: + nix build .#nixosConfigurations.{{hostname}}.config.system.build.toplevel --no-link + nvd diff /run/current-system $(nix path-info .#nixosConfigurations.{{hostname}}.config.system.build.toplevel) diff --git a/README.md b/README.md new file mode 100644 index 0000000..fcc04cf --- /dev/null +++ b/README.md @@ -0,0 +1,84 @@ +# NixOS Configuration + +Personal NixOS configuration using the [den](https://github.com/vic/den) framework (dendritic pattern). + +## Hosts + +| Hostname | Profile | GPU | +|------------|----------------------|--------| +| `desktop` | Gaming + development | Nvidia | +| `notebook` | Portable development | Intel | + +## Prerequisites + +- [just](https://github.com/casey/just): `nix shell nixpkgs#just` +- [nvd](https://github.com/khumba/nvd) for `just diff`: `nix shell nixpkgs#nvd` + +## Usage + +```bash +# Rebuild and switch (uses current hostname automatically) +just switch + +# Target a specific host +just switch desktop +just switch notebook + +# Build only, without switching +just build + +# Test (applies temporarily, reverts on next boot) +just test + +# Update all inputs +just update + +# Update a single input +just update-input nixpkgs + +# Run garbage collection +just gc + +# See what changed before switching +just diff +``` + +## Secrets (SOPS + age) + +Secrets are stored encrypted in `secrets/secrets.yaml` and decrypted at boot by [sops-nix](https://github.com/Mic92/sops-nix). + +### First-time setup on a new machine + +1. Generate an age key: + ```bash + mkdir -p /etc/sops/age + age-keygen -o /etc/sops/age/keys.txt + ``` + +2. Add the new public key to `.sops.yaml` under `keys:`. + +3. Re-encrypt secrets for all keys: + ```bash + sops updatekeys secrets/secrets.yaml + ``` + +### Adding a new secret + +1. Edit the secrets file: `just secrets` +2. Declare it in `modules/secrets.nix` under `sops.secrets`. + +### Rotating the age key + +1. Generate a new key (step 1 above). +2. Update `.sops.yaml` with the new public key. +3. Run `sops updatekeys secrets/secrets.yaml` to re-encrypt. + +## Identity + +All user identity (name, email, SSH key) lives in `modules/identity.nix`. Override the defaults there or in a profile-specific module when creating a new user profile. + +## Adding a new host + +1. Run `nixos-generate-config` on the target machine and copy the output to `modules/_hardware/-hardware.nix`. +2. Add the host in `modules/den.nix` under `den.hosts`. +3. Define or reuse an aspect for the host profile. diff --git a/flake.nix b/flake.nix index 7b5c6e5..b899f21 100644 --- a/flake.nix +++ b/flake.nix @@ -22,8 +22,16 @@ }; outputs = inputs: - (inputs.nixpkgs.lib.evalModules { - modules = [ (inputs.import-tree ./modules) ]; - specialArgs.inputs = inputs; - }).config.flake; + let + system = "x86_64-linux"; + pkgs = inputs.nixpkgs.legacyPackages.${system}; + flake = (inputs.nixpkgs.lib.evalModules { + modules = [ (inputs.import-tree ./modules) ]; + specialArgs.inputs = inputs; + }).config.flake; + in flake // { + devShells.${system}.default = pkgs.mkShell { + packages = [ pkgs.just ]; + }; + }; } diff --git a/modules/_home/git.nix b/modules/_home/git.nix index 96f3e01..2833673 100644 --- a/modules/_home/git.nix +++ b/modules/_home/git.nix @@ -1,21 +1,15 @@ -{ pkgs, ... }: -let - gitUsername = "Zoty"; - gitEmail = "zotydev@gmail.com"; - myPublicKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIK8fKj0nQMJt9nnXbYgT4ggYuj6ieGCy6KL53frwoNHa"; -in -{ +{ config, identity, pkgs, ... }: { home.packages = with pkgs; [ diff-so-fancy ]; - home.file.".ssh/id_ed25519.pub".text = myPublicKey; + home.file.".ssh/id_ed25519.pub".text = identity.sshPublicKey; programs.git = { enable = true; settings = { user = { - name = gitUsername; - email = gitEmail; - signingKey = "/home/zoty/.ssh/id_ed25519"; + name = identity.fullName; + email = identity.email; + signingKey = "${config.home.homeDirectory}/.ssh/id_ed25519"; }; core = { compression = 9; @@ -29,8 +23,8 @@ in }; init.defaultBranch = "main"; status = { - branch = true; - showStash = true; + branch = true; + showStash = true; showUntrackedFiles = "all"; }; diff = { @@ -70,9 +64,9 @@ in commit.gpgSign = true; gpg.format = "ssh"; url = { - "git@github.com:ZotyDev/".insteadOf = "zoty:"; + "git@github.com:ZotyDev/".insteadOf = "zoty:"; "git@github.com:UnnamedEngine/".insteadOf = "unen:"; - "git@github.com:Taumaturgo/".insteadOf = "taumaturgo:"; + "git@github.com:Taumaturgo/".insteadOf = "taumaturgo:"; }; }; }; diff --git a/modules/_home/niri.nix b/modules/_home/niri.nix index 673dc48..4b4d2c8 100644 --- a/modules/_home/niri.nix +++ b/modules/_home/niri.nix @@ -3,17 +3,16 @@ let wallpaper = ../../wallpapers/miku.png; in { home.sessionVariables = { - XDG_SESSION_TYPE = "wayland"; - XDG_CURRENT_DESKTOP = "niri"; - XDG_SESSION_DESKTOP = "niri"; - QT_QPA_PLATFORM = "wayland;xcb"; - QT_AUTO_SCREEN_SCALE_FACTOR = "1"; - QT_ENABLE_HIGHDPI_SCALING = "1"; - QT_SCALE_FACTOR_ROUNDING_POLICY = "RoundPreferFloor"; + XDG_CURRENT_DESKTOP = "niri"; + XDG_SESSION_DESKTOP = "niri"; + QT_QPA_PLATFORM = "wayland;xcb"; + QT_AUTO_SCREEN_SCALE_FACTOR = "1"; + QT_ENABLE_HIGHDPI_SCALING = "1"; + QT_SCALE_FACTOR_ROUNDING_POLICY = "RoundPreferFloor"; QT_WAYLAND_DISABLE_WINDOWDECORATION = "1"; - XDG_MENU_PREFIX = "plasma-"; - }; - + XDG_MENU_PREFIX = "plasma-"; + }; + home.packages = with pkgs; [ grim slurp @@ -26,7 +25,7 @@ in { text = '' #!/usr/bin/env bash MODE="''${1:-region}" - SAVE_DIR="$HOME/Images/screenshots" + SAVE_DIR="${config.xdg.userDirs.pictures}/screenshots" mkdir -p "$SAVE_DIR" FILENAME="$SAVE_DIR/$(date '+%Y%m%d-%H%M%S').png" @@ -44,12 +43,11 @@ in { esac ''; }; - + xdg.configFile."quickshell".source = config.lib.file.mkOutOfStoreSymlink "${config.home.homeDirectory}/repos/nixos/quickshell"; xdg.configFile."niri/config.kdl".text = '' - // Modificadores: Mod = Super (tecla Windows) input { keyboard { xkb { @@ -67,7 +65,7 @@ in { border { width 2 active-color "#fabd2f" - inactive-color "#504945" + inactive-color "#504945" } focus-ring { @@ -75,7 +73,7 @@ in { active-color "#fabd2f" inactive-color "transparent" } - } + } prefer-no-csd @@ -83,21 +81,21 @@ in { spawn-at-startup "swww" "img" "${wallpaper}" "--transition-type" "none" spawn-at-startup "quickshell" - screenshot-path "~/Imagens/screenshots/%Y-%m-%d %H-%M-%S.png" + screenshot-path "${config.xdg.userDirs.pictures}/screenshots/%Y-%m-%d %H-%M-%S.png" binds { - // Aplicativos + // Applications Mod+Return { spawn "kitty"; } Mod+D { spawn "fuzzel"; } Mod+Q { close-window; } - // Foco + // Focus Mod+Left { focus-column-left; } Mod+Right { focus-column-right; } Mod+Up { focus-window-up; } Mod+Down { focus-window-down; } - // Mover janelas + // Move windows Mod+Shift+Left { move-column-left; } Mod+Shift+Right { move-column-right; } Mod+Shift+Up { move-window-up; } @@ -115,7 +113,7 @@ in { Mod+Shift+4 { move-window-to-workspace 4; } Mod+Shift+5 { move-window-to-workspace 5; } - // Sistema + // System Mod+Shift+E { quit; } Mod+L { spawn "swaylock" "-i" "${wallpaper}" "--scaling" "fill"; } @@ -124,16 +122,16 @@ in { XF86AudioLowerVolume { spawn "wpctl" "set-volume" "@DEFAULT_AUDIO_SINK@" "5%-"; } XF86AudioMute { spawn "wpctl" "set-mute" "@DEFAULT_AUDIO_SINK@" "toggle"; } - // Zen mode (toggle quickshell bar) + // Toggle quickshell bar (zen mode) Mod+Z { spawn "quickshell" "ipc" "call" "zen" "toggle"; } // Input layout Mod+Space { switch-layout "next"; } - // Screenshot + // Screenshots Mod+Shift+S { spawn "bash" "-c" "$HOME/.local/bin/screenshot region"; } Mod+Shift+Alt+S { spawn "bash" "-c" "$HOME/.local/bin/screenshot screen"; } Mod+Shift+Ctrl+S { spawn "bash" "-c" "$HOME/.local/bin/screenshot monitor"; } - } + } ''; } diff --git a/modules/_home/xdg-dirs.nix b/modules/_home/xdg-dirs.nix new file mode 100644 index 0000000..ec00dce --- /dev/null +++ b/modules/_home/xdg-dirs.nix @@ -0,0 +1,15 @@ +{ config, ... }: { + xdg.userDirs = { + enable = true; + createDirectories = true; + + desktop = "${config.home.homeDirectory}/Desktop"; + download = "${config.home.homeDirectory}/Downloads"; + templates = "${config.home.homeDirectory}/Templates"; + publicShare = "${config.home.homeDirectory}/Public"; + documents = "${config.home.homeDirectory}/Documents"; + music = "${config.home.homeDirectory}/Music"; + pictures = "${config.home.homeDirectory}/Pictures"; + videos = "${config.home.homeDirectory}/Videos"; + }; +} diff --git a/modules/core.nix b/modules/core.nix index 7363d12..fdc8578 100644 --- a/modules/core.nix +++ b/modules/core.nix @@ -36,6 +36,7 @@ ncdu unrar p7zip + nvd ]; networking.networkmanager.enable = true; @@ -46,11 +47,6 @@ programs.dconf.enable = true; environment.sessionVariables = { - XDG_SESSION_TYPE = "wayland"; - CLUTTER_BACKEND = "wayland"; - SDL_VIDEODRIVER = "wayland"; - MOZ_ENABLE_WAYLAND = "1"; - ELECTRON_OZONE_PLATFORM_HINT = "wayland"; EDITOR = "nvim"; }; }; diff --git a/modules/creative.nix b/modules/creative.nix new file mode 100644 index 0000000..39adfd7 --- /dev/null +++ b/modules/creative.nix @@ -0,0 +1,26 @@ +{ den, inputs, ... }: { + den.aspects.creative.nixos = { pkgs, ... }: + let + pkgs-unstable = import inputs.nixpkgs-unstable { + system = pkgs.system; + config.allowUnfree = true; + }; + in { + environment.systemPackages = with pkgs-unstable; [ + # 3D + blender + goxel + + # Pixel art + aseprite + + # Image editing + gimp + krita + + # Video + obs-studio + kdePackages.kdenlive + ]; + }; +} diff --git a/modules/den.nix b/modules/den.nix index 1a9692b..858358d 100644 --- a/modules/den.nix +++ b/modules/den.nix @@ -1,4 +1,7 @@ -{ inputs, den, lib, ... }: { +{ inputs, den, lib, config, ... }: +let + identity = config.local.identity; +in { imports = [ inputs.den.flakeModule ]; den.schema.user.classes = lib.mkDefault [ "homeManager" ]; @@ -18,9 +21,11 @@ includes = [ den.provides.hostname den.aspects.core + den.aspects.wayland den.aspects.niri den.aspects.notebook-specific den.aspects.dev + den.aspects.creative den.aspects.secrets ]; nixos = { @@ -32,9 +37,11 @@ includes = [ den.provides.hostname den.aspects.core + den.aspects.wayland den.aspects.niri den.aspects.desktop-specific den.aspects.dev + den.aspects.creative den.aspects.secrets den.aspects.steam den.aspects.prismlauncher @@ -62,7 +69,7 @@ useGlobalPkgs = true; useUserPackages = true; backupFileExtension = "backup"; - extraSpecialArgs = { inherit inputs; }; + extraSpecialArgs = { inherit inputs identity; }; }; security.sudo.wheelNeedsPassword = false; }; @@ -74,6 +81,7 @@ ./_home/git.nix ./_home/dolphin.nix ./_home/theme.nix + ./_home/xdg-dirs.nix ]; }; }; diff --git a/modules/desktop.nix b/modules/desktop.nix index 1e9aedd..64591f9 100644 --- a/modules/desktop.nix +++ b/modules/desktop.nix @@ -14,7 +14,6 @@ }; nvidia = { - # Required by Wayland modesetting.enable = true; open = false; nvidiaSettings = true; @@ -44,13 +43,9 @@ }; environment.sessionVariables = { - NIXOS_OZONE_WL = "1"; - GBM_BACKEND = "nvidia-drm"; + # Nvidia-specific Wayland backend overrides + GBM_BACKEND = "nvidia-drm"; __GLX_VENDOR_LIBRARY_NAME = "nvidia"; - MOZ_ENABLE_WAYLAND = "1"; - MOZ_USE_XINPUT2 = "1"; - __GL_SYNC_TO_VBLANK = "0"; - __GL_MaxFramesAllowed = "1"; }; }; } diff --git a/modules/dev.nix b/modules/dev.nix index 6f06cb0..85b5496 100644 --- a/modules/dev.nix +++ b/modules/dev.nix @@ -1,51 +1,57 @@ -{ den, inputs, pkgs, ... }: { +{ den, inputs, config, ... }: +let + username = config.local.identity.username; +in { den.aspects.dev.nixos = { pkgs, ... }: let pkgs-unstable = inputs.nixpkgs-unstable.legacyPackages.${pkgs.system}; - in - { - environment.systemPackages = (with pkgs-unstable; [ - # Basic + in { + environment.systemPackages = with pkgs-unstable; [ + # CLI utilities gcc fzf + just tree-sitter - # LSPs - bash-language-server # Bash - lua-language-server # lua - nixd # Nix - vscode-langservers-extracted # Json & CSS - yaml-language-server # Yaml - dockerfile-language-server # Docker - marksman # Markdown - clang-tools # C++ - jdt-language-server # Java - typescript-language-server # Typescript - pyright # Python - taplo # TOML and rust crates - sqls # SQL - astro-language-server # Astro - angular-language-server # Angular - vue-language-server # Vue - tailwindcss-language-server # Tailwind - qt6Packages.qtdeclarative # qmlls (QML/Quickshell LSP) - wgsl-analyzer - # Extra - chafa ripgrep - ]) ++ (with pkgs; [ - # Other + chafa + + # Infrastructure + docker-compose + + # IDE + jetbrains.idea-oss + + # Neovim vimPlugins.blink-cmp - jetbrains.idea-community - aseprite - goxel - ]); + + # LSPs + bash-language-server + lua-language-server + nixd + vscode-langservers-extracted + yaml-language-server + dockerfile-language-server + marksman + clang-tools + jdt-language-server + typescript-language-server + pyright + taplo + sqls + astro-language-server + angular-language-server + vue-language-server + tailwindcss-language-server + qt6Packages.qtdeclarative + wgsl-analyzer + ]; programs.java = { enable = true; - package = pkgs.jdk17; + package = pkgs-unstable.jdk17; }; virtualisation.docker.enable = true; - users.users.zoty.extraGroups = [ "docker" ]; + users.users.${username}.extraGroups = [ "docker" ]; }; } diff --git a/modules/identity.nix b/modules/identity.nix new file mode 100644 index 0000000..7a711dc --- /dev/null +++ b/modules/identity.nix @@ -0,0 +1,27 @@ +{ lib, ... }: { + options.local.identity = { + username = lib.mkOption { + type = lib.types.str; + default = "zoty"; + description = "Primary system username."; + }; + + fullName = lib.mkOption { + type = lib.types.str; + default = "Zoty"; + description = "Full display name used in git and similar tools."; + }; + + email = lib.mkOption { + type = lib.types.str; + default = "zotydev@gmail.com"; + description = "Primary email address."; + }; + + sshPublicKey = lib.mkOption { + type = lib.types.str; + default = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIK8fKj0nQMJt9nnXbYgT4ggYuj6ieGCy6KL53frwoNHa"; + description = "Primary SSH public key."; + }; + }; +} diff --git a/modules/notebook.nix b/modules/notebook.nix index fcb0496..f91c1a7 100644 --- a/modules/notebook.nix +++ b/modules/notebook.nix @@ -34,13 +34,5 @@ efi.canTouchEfiVariables = true; }; }; - - environment.sessionVariables = { - NIXOS_OZONE_WL = "1"; - MOZ_ENABLE_WAYLAND = "1"; - MOZ_USE_XINPUT2 = "1"; - __GL_SYNC_TO_VBLANK = "0"; - __GL_MaxFramesAllowed = "1"; - }; }; } diff --git a/modules/secrets.nix b/modules/secrets.nix index 5628e13..35487a3 100644 --- a/modules/secrets.nix +++ b/modules/secrets.nix @@ -1,27 +1,26 @@ -{ inputs, den, ... }: { +{ inputs, den, config, ... }: +let + username = config.local.identity.username; +in { den.aspects.secrets.nixos = { ... }: { imports = [ inputs.sops-nix.nixosModules.sops ]; sops = { defaultSopsFile = ../secrets/secrets.yaml; - # NOTE: This thing gave me a huge headache to setup. - # If you are ME from future, don't forget to place - # your age keys here! + # Place your age keys at /etc/sops/age/keys.txt before deploying. + # See README.md for setup instructions. age.keyFile = "/etc/sops/age/keys.txt"; - # Define secrets to be used. secrets = { - # Literally the user password. "user-password" = { neededForUsers = true; }; - # SSH private key. "ssh-private-key" = { - path = "/home/zoty/.ssh/id_ed25519"; - owner = "zoty"; - mode = "0400"; + path = "/home/${username}/.ssh/id_ed25519"; + owner = username; + mode = "0400"; }; }; }; diff --git a/modules/wayland.nix b/modules/wayland.nix new file mode 100644 index 0000000..ca43e30 --- /dev/null +++ b/modules/wayland.nix @@ -0,0 +1,20 @@ +{ den, ... }: { + den.aspects.wayland.nixos = { + environment.sessionVariables = { + # Core Wayland session + XDG_SESSION_TYPE = "wayland"; + CLUTTER_BACKEND = "wayland"; + SDL_VIDEODRIVER = "wayland"; + + # Browser / Electron Wayland backends + MOZ_ENABLE_WAYLAND = "1"; + MOZ_USE_XINPUT2 = "1"; + ELECTRON_OZONE_PLATFORM_HINT = "wayland"; + NIXOS_OZONE_WL = "1"; + + # OpenGL / frame pacing + __GL_SYNC_TO_VBLANK = "0"; + __GL_MaxFramesAllowed = "1"; + }; + }; +}