diff --git a/new/configuration.nix b/new/configuration.nix new file mode 100644 index 0000000..4b4bbe0 --- /dev/null +++ b/new/configuration.nix @@ -0,0 +1,7 @@ +{...}: { + imports = [ + # ./hardware-configuration.nix + ./user + ./system + ]; +} diff --git a/new/data/gruvbox-dark.nix b/new/data/gruvbox-dark.nix new file mode 100644 index 0000000..a5bd438 --- /dev/null +++ b/new/data/gruvbox-dark.nix @@ -0,0 +1,26 @@ +{...}: { + background = "#282828"; + foreground = "#ebdbb2"; + + normal = { + black = "#282828"; + red = "#cc241d"; + green = "#98971a"; + yellow = "#d79921"; + blue = "#458588"; + magenta = "#b16286"; + cyan = "#689d6a"; + white = "#a89984"; + }; + + bright = { + black = "#928374"; + red = "#fb4934"; + green = "#b8bb26"; + yellow = "#fabd2f"; + blue = "#83a598"; + magenta = "#d3869b"; + cyan = "#8ec07c"; + white = "#ebdbb2"; + }; +} diff --git a/new/data/gruvbox-light.nix b/new/data/gruvbox-light.nix new file mode 100644 index 0000000..9058095 --- /dev/null +++ b/new/data/gruvbox-light.nix @@ -0,0 +1,26 @@ +{...}: { + background = "#fbf1c7"; + foreground = "#3c3836"; + + normal = { + black = "#fbf1c7"; + red = "#cc241d"; + green = "#98971a"; + yellow = "#d79921"; + blue = "#458588"; + magenta = "#b16286"; + cyan = "#689d6a"; + white = "#7c6f64"; + }; + + bright = { + black = "#928374"; + red = "#9d0006"; + green = "#79740e"; + yellow = "#b57614"; + blue = "#076678"; + magenta = "#8f3f71"; + cyan = "#427b58"; + white = "#3c3836"; + }; +} diff --git a/new/data/theme.nix b/new/data/theme.nix new file mode 100644 index 0000000..2fc5a08 --- /dev/null +++ b/new/data/theme.nix @@ -0,0 +1,21 @@ +{config, ...}: +let + theme = if config.darkMode then import ./gruvbox-dark.nix {} + else import ./gruvbox-light.nix {}; +in +{ + inherit (theme) background foreground normal bright; + + extra = { + red = "#bd574e"; + orange = "#eb8242"; + yellow = "#ede06b"; + green = "#9bb67c"; + teal = "#87a7b3"; + purple = "#ad6989"; + brown = "#ad8b73"; + darkbrown = "#85603f"; + darkerbrown = "#5e454b"; + cream = "#fefcf3"; + }; +} diff --git a/new/data/user.nix b/new/data/user.nix new file mode 100644 index 0000000..659b642 --- /dev/null +++ b/new/data/user.nix @@ -0,0 +1,4 @@ +{...}: { + email = "janis@nirgendwo.xyz"; + username = "alice"; +} diff --git a/new/data/zsh-aliases.nix b/new/data/zsh-aliases.nix new file mode 100644 index 0000000..a21009c --- /dev/null +++ b/new/data/zsh-aliases.nix @@ -0,0 +1,13 @@ +{...}: { + ll = "ls -l"; + la = "ls -la"; + git-tree = "git log --graph --oneline --all"; + c = "clear"; + cl = "clear; ls --color=auto"; + q = "exit"; + ssh = "TERM=xterm-256color ssh"; + emacs = "emacs -nw"; # Use emacs in terminal mode. + + # dotfiles + dotfiles = "git --git-dir=$HOME/.dotfiles/ --work-tree=$HOME"; +} diff --git a/new/flake.nix b/new/flake.nix new file mode 100644 index 0000000..6a008f8 --- /dev/null +++ b/new/flake.nix @@ -0,0 +1,59 @@ +{ + inputs = { + nixpkgs.url = "github:NixOS/nixpkgs/nixos-25.05"; + home-manager = { + url = "github:nix-community/home-manager"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + disko = { + url = "github:nix-community/disko"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + nur.url = "github:nix-community/nur"; + }; + + outputs = inputs @ { self, disko, nixpkgs, home-manager, ... }: + let + system = "x86_64-linux"; + in rec { + mkSystem = {host, ...}: nixpkgs.lib.nixosSystem { + inherit system; + + modules = [ + ./configuration.nix + host + home-manager.nixosModules.home-manager + disko.nixosModules.disko + { + home-manager.useGlobalPkgs = true; # Use global packages in home-manager + home-manager.useUserPackages = true; # Use user packages in home-manager + + home-manager.extraSpecialArgs = { + inherit inputs; + }; + } + ]; + + specialArgs = { + inherit inputs home-manager; + }; + + pkgs = import nixpkgs { + inherit system; + config.allowUnfree = true; # Allow unfree packages globally + overlays = [ + inputs.nur.overlays.default + ]; + }; + }; + + nixosConfigurations = { + vm = mkSystem { + host = ./hosts/vm.nix; + }; + laptop = mkSystem { + host = ./hosts/laptop; + }; + }; + }; +} diff --git a/new/home/alacritty.nix b/new/home/alacritty.nix new file mode 100644 index 0000000..c2b1beb --- /dev/null +++ b/new/home/alacritty.nix @@ -0,0 +1,35 @@ +{config, ...}: +let + theme = import ../data/theme.nix {inherit config; }; + +in { + programs.alacritty = { + enable = true; + settings = { + font.normal.family = "monospace"; + window = { + dynamic_title = true; + title = "Alacritty"; + }; + + # gruvbox dark theme + colors = { + primary = { + inherit (theme) background foreground; + }; + + inherit (theme) normal bright; + }; + + keyboard = { + bindings = [ + { + key = "Return"; + mods = "Shift|Control"; + action = "SpawnNewInstance"; + } + ]; + }; + }; + }; +} diff --git a/new/home/default.nix b/new/home/default.nix new file mode 100644 index 0000000..6106265 --- /dev/null +++ b/new/home/default.nix @@ -0,0 +1,37 @@ +{pkgs, ...}: +let + user = import ../data/user.nix {}; +in { + imports = [ + ./alacritty.nix + ./firefox.nix + ./sway.nix + ./waybar.nix + ./zsh.nix + ./rofi.nix + ]; + + fonts.fontconfig.enable = true; + home = { + stateVersion = "25.05"; + homeDirectory = "/home/${user.username}"; + username = user.username; + + sessionVariables = { + EDITOR = "nvim"; + VISUAL = "nvim"; + }; + + packages = with pkgs; [ + # Add your global packages here + neovim + git + wget + curl + htop + tree + htop + pavucontrol + ]; + }; +} diff --git a/new/home/firefox.nix b/new/home/firefox.nix new file mode 100644 index 0000000..fe70c0e --- /dev/null +++ b/new/home/firefox.nix @@ -0,0 +1,127 @@ +{pkgs, ...}: let + user = import ../data/user.nix {}; +in{ + programs.firefox = { + enable = true; + + policies = { + CaptivePortal = false; + DisablePocket = true; + DisableTelemetry = true; + DisableFirefoxStudies = true; + FirefoxHome = { + Pocket = false; + Snippets = false; + }; + }; + + profiles = { + default = { + isDefault = true; + + search = { + default = "ddg"; + force = true; + privateDefault = "ddg"; + }; + + settings = { + # disable warning when editing about:config + "browser.aboutConfig.showWarning" = false; + # webgpu + "dom.webgpu.enabled" = true; + "gfx.webrender.all" = true; + "signon.rememberSignons" = false; + # mozilla syncserver + "identity.sync.tokenserver.uri" = "https://nirgendswo.com:8001/1.0/sync/1.5"; + "services.sync.username" = user.email; + "browser.startup.page" = 3; # resume previous session + "browser.startup.homepage" = "about:home"; + "browser.toolbars.bookmarks.visibility" = "never"; + + # hardening + "browser.newtabpage.enabled" = false; + "browser.newtabpage.activity-stream.feeds.telemetry" = false; + "browser.newtabpage.activity-stream.telemetry" = false; + "browser.newtabpage.activity-stream.feeds.snippets" = false; + "browser.newtabpage.activity-stream.feeds.section.topstories" = false; + "browser.newtabpage.activity-stream.showSponsoredTopSites" = false; + "browser.newtabpage.activity-stream.showSponsored" = false; + "browser.newtabpage.activity-stream.feeds.discoverystreamfeed" = false; + "browser.newtabpage.activity-stream.default.sites" = ""; + "browser.newtab.preload" = false; + "geo.provider.network.url" = "https://location.services.mozilla.com/v1/geolocate?key=%MOZILLA_API_KEY%"; + "geo.provider.ms-windows-location" = false; + "geo.provider.use_corelocation" = false; + "geo.provider.use_gpsd" = false; + "geo.provider.use_geoclue" = false; + "browser.region.network.url" = ""; + "browser.region.update.enabled" = false; + "intl.accept_languages" = "en-US,en-GB,en"; + "javascript.use_us_language_locale" = true; + "app.update.auto" = false; + + "extensions.discover.enabled" = false; + "extensions.htmlaboutaddons.recommendations.enabled" = false; + "extenisons.getAddons.showPane" = false; + + "datareporting.healthreport.uploadEnabled" = false; + "datareporting.policy.dataSubmissionEnabled" = false; + "toolkit.telemetry.enabled" = false; + "toolkit.telemetry.unified" = false; + "toolkit.telemetry.server" = "data:,"; + "toolkit.telemetry.archive.enabled" = false; + "toolkit.telemetry.newProfilePing.enabled" = false; + "toolkit.telemetry.shutdownPingSender.enabled" = false; + "toolkit.telemetry.updatePing.enabled" = false; + "toolkit.telemetry.bhrPing.enabled" = false; + "toolkit.telemetry.firstShutdownPing.enabled" = false; + "toolkit.telemetry.coverage.opt-out" = true; + "toolkit.coverage.opt-out" = true; + "beacon.enabled" = false; + + "app.shield.optoutstudies.enabled" = false; + + "captivedetect.canonicalURL" = ""; + "network.captive-portal-service.enabled" = false; + "network.connectivity-service.enabled" = false; + + "browser.safebrowsing.malware.enabled" = false; + "browser.safebrowsing.phishing.enabled" = false; + "browser.safebrowsing.blockedURIs.enabled" = false; + "browser.safebrowsing.provider.google4.gethashURL" = ""; + "browser.safebrowsing.provider.google4.updateURL" = ""; + "browser.safebrowsing.provider.google4.dataSharingURL" = ""; + "browser.safebrowsing.provider.google.gethashURL" = ""; + "browser.safebrowsing.provider.google.updateURL" = ""; + + "browser.safebrowsing.downloads.enabled" = false; + "browser.safebrowsing.downloads.remote.enabled" = false; + "browser.safebrowsing.downloads.remote.url" = ""; + "browser.safebrowsing.allowOverride" = false; + + "network.prefetch-next" = false; + "network.dns.disablePrefetch" = true; + "network.predictor.enabled" = false; + + "browser.fixup.alternate.enabled" = false; + "browser.urlbar.trimURLs" = false; + + "browser.contentblocking.category" = "strict"; + "privacy.partition.serviceWorkers" = true; + "privacy.partition.always_partition_third_party_non_cookie_storage" = true; + "privacy.partition.always_partition_third_party_non_cookie_storage.exempt_sessionstorage" = true; + "privacy.resistFingerprinting" = true; + "privacy.resistFingerprinting.block_mozAddonManager" = true; + + "app.normandy.enabled" = false; + "app.normandy.api_url" = ""; + }; + + extensions.packages = with pkgs.nur.repos.rycee.firefox-addons; [ + ublock-origin bitwarden rust-search-extension betterttv + ]; + }; + }; + }; +} diff --git a/new/home/libinput.nix b/new/home/libinput.nix new file mode 100644 index 0000000..7285fd0 --- /dev/null +++ b/new/home/libinput.nix @@ -0,0 +1,19 @@ +{pkgs, config, ...}: { + home.packages = with pkgs; [ + libinput + libinput-gestures + ]; + + # Ensure libinput-gestures service is enabled + wayland.windowManager.sway.systemd.extraCommands = [ + "systemctl --user enable libinput-gestures.service" + "systemctl --user start libinput-gestures.service" + ]; + + xdg.configFile."libinput-gestures.conf".text = '' + gesture swipe left 4 swaymsg workspace next + gesture swipe right 4 swaymsg workspace next + gesture swipe down 4 swaylock-wrapper + gesture pinch in 4 rofi -combi-modi window,drun,run,ssh,combi -show combi -show-icons +''; +} diff --git a/new/home/rofi.nix b/new/home/rofi.nix new file mode 100644 index 0000000..f54e60b --- /dev/null +++ b/new/home/rofi.nix @@ -0,0 +1,239 @@ +{pkgs, config, ...}: let + theme = import ../data/theme.nix { inherit config; }; +in { + xdg.dataFile."rofi/themes/launcher.rasi".text = '' +/** + * + * Author : Aditya Shakya (adi1090x) + * Github : @adi1090x + * + * Rofi Theme File + * Rofi Version: 1.7.3 + **/ + +/*****----- Configuration -----*****/ +configuration { + modi: "drun,run,filebrowser,window"; + show-icons: false; + display-drun: ""; + display-run: ""; + display-filebrowser: ""; + display-window: ""; + drun-display-format: "{name}"; + window-format: "{w} · {c} · {t}"; +} + +/*****----- Global Properties -----*****/ +* { + font: "JetBrains Mono Nerd Font 10"; + background: #101010; + background-alt: #252525; + foreground: #FFFFFF; + selected: #505050; + active: #909090; + urgent: #707070; +} + +/*****----- Main Window -----*****/ +window { + /* properties for window widget */ + transparency: "real"; + location: center; + anchor: center; + fullscreen: false; + width: 400px; + x-offset: 0px; + y-offset: 0px; + + /* properties for all widgets */ + enabled: true; + border-radius: 20px; + cursor: "default"; + background-color: @background; +} + +/*****----- Main Box -----*****/ +mainbox { + enabled: true; + spacing: 0px; + background-color: transparent; + orientation: vertical; + children: [ "inputbar", "listbox" ]; +} + +listbox { + spacing: 20px; + padding: 20px; + background-color: transparent; + orientation: vertical; + children: [ "message", "listview", "mode-switcher" ]; +} + +/*****----- Inputbar -----*****/ +inputbar { + enabled: true; + spacing: 10px; + padding: 100px 40px; + background-color: transparent; + background-image: url("~/.config/rofi/images/g.png", width); + text-color: @foreground; + orientation: horizontal; + children: [ "textbox-prompt-colon", "entry" ]; +} +textbox-prompt-colon { + enabled: true; + expand: false; + str: ""; + padding: 12px 15px; + border-radius: 100%; + background-color: @background-alt; + text-color: inherit; +} +entry { + enabled: true; + expand: true; + padding: 12px 16px; + border-radius: 100%; + background-color: @background-alt; + text-color: inherit; + cursor: text; + placeholder: "Search"; + placeholder-color: inherit; +} + +/*****----- Mode Switcher -----*****/ +mode-switcher{ + enabled: true; + spacing: 10px; + background-color: transparent; + text-color: @foreground; +} +button { + padding: 12px; + border-radius: 100%; + background-color: @background-alt; + text-color: inherit; + cursor: pointer; +} +button selected { + background-color: @selected; + text-color: @foreground; +} + +/*****----- Listview -----*****/ +listview { + enabled: true; + columns: 1; + lines: 5; + cycle: true; + dynamic: true; + scrollbar: false; + layout: vertical; + reverse: false; + fixed-height: true; + fixed-columns: true; + + spacing: 10px; + background-color: transparent; + text-color: @foreground; + cursor: "default"; +} + +/*****----- Elements -----*****/ +element { + enabled: true; + spacing: 10px; + padding: 12px; + border-radius: 100%; + background-color: transparent; + text-color: @foreground; + cursor: pointer; +} +element normal.normal { + background-color: inherit; + text-color: inherit; +} +element normal.urgent { + background-color: @urgent; + text-color: @foreground; +} +element normal.active { + background-color: @active; + text-color: @foreground; +} +element selected.normal { + background-color: @selected; + text-color: @foreground; +} +element selected.urgent { + background-color: @urgent; + text-color: @foreground; +} +element selected.active { + background-color: @urgent; + text-color: @foreground; +} +element-icon { + background-color: transparent; + text-color: inherit; + size: 32px; + cursor: inherit; +} +element-text { + background-color: transparent; + text-color: inherit; + cursor: inherit; + vertical-align: 0.5; + horizontal-align: 0.0; +} + +/*****----- Message -----*****/ +message { + background-color: transparent; +} +textbox { + padding: 12px; + border-radius: 100%; + background-color: @background-alt; + text-color: @foreground; + vertical-align: 0.5; + horizontal-align: 0.0; +} +error-message { + padding: 15px; + border-radius: 0px; + background-color: @background; + text-color: @foreground; +} +''; + + xdg.configFile."rofi/launcher.rasi".text = '' +configuration { + modi: "drun,run,ssh,filebrowser,window"; + terminal: "${pkgs.alacritty}/bin/alacritty"; + show-icons: true; + display-drun: ""; + display-run: ""; + display-ssh: ""; + + drun-display-format: "{name}"; + run-display-format: "{name}"; + ssh-display-format: "{name}"; + combi-display-format: "{mode} {name}"; + + combi-modi: "window,drun,run,filebrowser"; + + kb-mode-previous: "Control+h"; + kb-mode-next: "Control+l"; + kb-mode-complete: ""; + kb-remove-char-back: "BackSpace,Shift+BackSpace"; +} +''; + programs.rofi = { + enable = true; + package = pkgs.rofi-wayland; + terminal = "{pkgs.alacritty}/bin/alacritty"; + + theme = "launcher.rasi"; + }; +} diff --git a/new/home/sway.nix b/new/home/sway.nix new file mode 100644 index 0000000..46145ea --- /dev/null +++ b/new/home/sway.nix @@ -0,0 +1,150 @@ +{pkgs, lib, config, ...}: +let + mod = "Mod4"; + left = "h"; + right = "l"; + up = "k"; + down = "j"; + + launcher = "${pkgs.rofi}/bin/rofi -config ${config.xdg.configHome}/rofi/launcher.rasi -theme ${config.xdg.dataHome}/rofi/themes/launcher.rasi -show drun -show-icons"; + +in { + home.packages = with pkgs; [ + brightnessctl + wmctrl + wireplumber + alacritty + waybar + sway + rofi-wayland + ]; + wayland = { + windowManager = { + sway = { + enable = true; + systemd = { + enable = true; + }; + + config = { + modifier = "${mod}"; + + gaps = { + inner = 8; + }; + + bars = [{ + command = "${pkgs.waybar}/bin/waybar"; + }]; + + window = { + border = 3; + titlebar = false; + }; + + input = { + "type:pointer" = { + pointer_accel = "-1"; + }; + + "type:keyboard" = { + xkb_layout = "gb,dk"; + xkb_options = + "caps:escape,grp:menu_toggle,grp:rctrl_toggle"; + repeat_delay = "250"; + repeat_rate = "25"; + }; + + "type:touchpad" = { + natural_scroll = "enabled"; + tap = "enabled"; + tap_button_map = "lrm"; + pointer_accel = "0"; + }; + }; + + keybindings = with pkgs; { + "Print" = "exec screenshot"; + "${mod}+Print" = "exec screenshot --area"; + "${mod}+Shift+Print" = "exec screenshot --current-window"; + + "XF86AudioRaiseVolume" = "exec ${wireplumber}/bin/wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%+"; + "XF86AudioLowerVolume" = "exec ${wireplumber}/bin/wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%-"; + "XF86AudioMute" = "exec ${wireplumber}/bin/wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle"; + "XF86AudioMicMute" = "exec ${wireplumber}/bin/wpctl set-mute @DEFAULT_AUDIO_SOURCE@ toggle"; + + "XF86AudioPlay" = "mpc toggle"; + "XF86AudioNext" = "mpc next"; + "XF86AudioPrev" = "mpc prev"; + + "XF86MonBrightnessUp" = "exec ${brightnessctl}/bin/brightnessctl set +10%"; + "XF86MonBrightnessDown" = "exec ${brightnessctl}/bin/brightnessctl set 10%-"; + + "${mod}+Shift+Return" = "exec ${alacritty}/bin/alacritty"; + "${mod}+q" = "kill"; + "${mod}+p" = "exec ${launcher}"; + "${mod}+Shift+e" = "exec ${pkgs.emacs}/bin/emacsclient -c -a ''"; + "${mod}+Shift+b" = "exec ${pkgs.firefox}/bin/firefox"; + "${mod}+Shift+c" = "reload"; + "${mod}+Shift+q" = "exec ${pkgs.sway}/bin/swaymsg exit"; + + "${mod}+${left}" = "focus left"; + "${mod}+${right}" = "focus right"; + "${mod}+${up}" = "focus up"; + "${mod}+${down}" = "focus down"; + + "${mod}+Shift+${left}" = "move left"; + "${mod}+Shift+${right}" = "move right"; + "${mod}+Shift+${up}" = "move up"; + "${mod}+Shift+${down}" = "move down"; + + "${mod}+Ctrl+${left}" = "move workspace to output left"; + "${mod}+Ctrl+${right}" = "move workspace to output right"; + + "${mod}+b" = "splith"; + "${mod}+v" = "splitv"; + + "${mod}+s" = "layout stacking"; + "${mod}+w" = "layout tabbed"; + "${mod}+e" = "layout toggle split"; + + "${mod}+Shift+space" = "layout toggle floating"; + "${mod}+space" = "focus mode_toggle"; + "${mod}+Shift+f" = "fullscreen"; + + } // lib.attrsets.mergeAttrsList (map + (n: let workspace = toString n; in { + "${mod}+${workspace}" = "workspace ${workspace}"; + "${mod}+Shift+${workspace}" = "move container to workspace ${workspace}"; + }) + [1 2 3 4 5 6 7 8 9 0] + ); + + colors = { + focused = { + background = "#A7C080"; + text = "#272E33"; + indicator = "#A7C080"; + border = "#A7C080"; + childBorder = "#A7C080"; + }; + unfocused = { + background = "#9DA9A0"; + text = "#272E33"; + indicator = "#9DA9A0"; + border = "#9DA9A0"; + childBorder = "#9DA9A0"; + }; + urgent = { + background = "#E67E80"; + text = "#272E33"; + indicator = "#E67E80"; + border = "#E67E80"; + childBorder = "#E67E80"; + }; + }; + }; + }; + }; + }; +} diff --git a/new/home/waybar.nix b/new/home/waybar.nix new file mode 100644 index 0000000..1055409 --- /dev/null +++ b/new/home/waybar.nix @@ -0,0 +1,234 @@ +{lib, config, ...}: +let + theme = import ../data/theme.nix {inherit config; }; + utils = import ../utils.nix {inherit lib; }; +in let + self = rec { + # ModuleDesc has the shape {name, config?, background?, color?, style?} + module-descs = [ + { + name = "custom/left-most"; + background = theme.background; + } + { + name = "pulseaudio"; + config = { + format = "{volume}% {icon} {format_source}"; + format-bluetooth = "{volume}% {icon} {format_source}"; + format-muted = "{format_source}"; + format-source = "{volume}% "; + format-source-muted = ""; + format-icons = { + headphones = ""; + default = ["" "" ""]; + }; + on-click = "pavucontrol"; + }; + background = theme.normal.yellow; + } + { + name = "network"; + config = { + format-wifi = "{essid} {signalStrength}% {icon}"; + format-ethernet = "{ipaddr} 󰈀"; + format-disconnected = "Disconnected 󰤮"; + tooltip-format = ''Interface: {ifname} +IP: {ipaddr} +Speed: {bandwidthUpBytes} / {bandwidthDownBytes} +Signal: {signalStrength}% +SSID: {essid} {frequency}''; + on-click = "iwgtk"; + format-icons = ["󰤯" "󰤟" "󰤢" "󰤥" "󰤨"]; + }; + background = theme.normal.green; + } + { + name = "custom/vpn"; + config = { + format = "{}"; + excape = true; + interval = 30; + exec = "nordvpn-rofi.sh --status-json"; + return-type = "json"; + on-click = "rofi -show vpn -modes 'vpn:nordvpn-rofi.sh'"; + }; + style = { + connected.color = theme.normal.black; + disconnected.color = theme.normal.yellow; + }; + background = theme.extra.teal;} + ] + ++ (if (config.has_battery) then [{ + name = "battery"; + config = { + states = { + critical = 15; + warning = 25; + good = 80; + full = 90; + }; + interval = 30; + format = "{capacity}% {icon}"; + format-charging = "{capacity}% "; + format-plugged = "{capacity}% "; + format-icons = ["" "" "" "" ""]; + }; + background = theme.extra.aqua; + }] else []) + ++ [ + { + name = "cpu"; + config = { + format = "{}% "; + }; + background = theme.extra.brown; + } + { + name = "memory"; + config = { + format = "{}% "; + }; + background = theme.extra.darkbrown; + } + { + name = "temperature"; + config = { + critical-threshold = 80; + hwmon-path = "/sys/class/hwmon/hwmon5/temp1_input"; + format = "{temperatureC}°C {icon}"; + format-icons = ["" "" ""]; + }; + background = theme.extra.darkerbrown; + } + { + name = "clock"; + config = { + format = "{:%H:%M} 󰥔"; + tooltip-format = "{calendar}"; + calendar = { + mode = "month"; + weeks-pos = "left"; + on-scroll = 1; + format = { + months = "{}"; + days = "{}"; + weekdays = "{}"; + today = "{}"; + }; + on-scroll-up = "shift_up"; + on-scroll-down = "shift_down"; + }; + }; + background = theme.normal.black; + } + {name = "tray"; config = { spacing = 10; }; background = theme.background;} + ]; + + # default style for modules + default-style = "padding-left: 8pt; padding-right: 8pt;"; + + # ModuleDesc -> Module + mkModule = desc: let + background = desc.background or theme.background; + color = desc.color or theme.foreground; + config = desc.config or {}; + # style = module.style or ""; + style = default-style; + style-name = builtins.replaceStrings ["/"] ["-"] desc.name; + in { + inherit (desc) name; + setting = { + } // config; + + style = "#${style-name} {" + default-style + ''background: ${background};color: ${color};'' + "}\n"; + }; + + mkSpacer = idx: left: right: { + name = "custom/arrow${toString idx}"; + setting = { + format = ""; + tooltip = false; + }; + style = "#custom-arrow${toString idx} {font-size: 14pt;background: ${left.background};color: ${right.background};}\n"; + }; + + # modules interlaced with spacers + # [ModuleDesc] -> [Module] + mkSpacedModules = descs: with builtins; + let + len = length descs; + in lib.lists.flatten + (lib.lists.imap0 + (n: descs: let + left = elemAt descs 0; + right = elemAt descs 1; + in if n == len then [ + (mkModule left) + (mkSpacer n left right) + (mkModule right) + ] else [ + (mkModule left) + (mkSpacer n left right) + ]) + (utils.windows 2 descs) + ); + + # Module -> {"name" = setting} + mkModuleConfig = {name, setting, ...}: lib.attrsets.optionalAttrs (!utils.isEmptySet setting) { + "${name}" = setting; + }; + + # builds bar configuration with left, center, and right modules + # right modules get spacers in between them. + # {left: [ModuleDesc], center: [ModuleDesc], right: [ModuleDesc], config: {}} -> {config, style} + mkBar = {left, center, right, config, ...}: + let + # Create modules from the descriptions + right' = mkSpacedModules right; + left' = map (module: mkModule module) left; + center' = map (module: mkModule module) center; + in let + # Create lists of module names for the config + modules-left = map (module: module.name) left'; + modules-center = map (module: module.name) center'; + modules-right = map (module: module.name) right'; + # Combine all modules into a single list + modules = lib.lists.flatten [left' center' right']; + in { + config = lib.attrsets.mergeAttrsList (lib.lists.flatten [ + { + inherit modules-left modules-center modules-right; + } + config + (map mkModuleConfig modules) + ]); + style = lib.strings.concatStringsSep "\n" (map (module: module.style) modules); + }; + }; + + bar = self.mkBar { + left = [ {name = "sway/workspaces";} {name = "sway/mode";} ]; + center = [ {name = "sway/window";} ]; + right = self.module-descs; + config = { + height = 25; + spacing = 0; + position = "top"; + }; + }; +in { + imports = [ ../options.nix ]; + programs.waybar = { + enable = true; + + settings = { + mainBar = bar.config; + }; + + style = '' +* {border: none; border-radius: 0; min-height: 0; margin: 0; padding: 0; box-shadow: none; text-shadow: none;} +#waybar { background: rgba(40, 40, 40, 0.3); color: #ffffff; font-family: "sans-serif"; font-size: 12pt; font-weight: 500; } +'' + + bar.style; + }; +} diff --git a/new/home/zsh.nix b/new/home/zsh.nix new file mode 100644 index 0000000..2a9cc9f --- /dev/null +++ b/new/home/zsh.nix @@ -0,0 +1,39 @@ +{pkgs, ...}: +let + aliases = import ../data/zsh-aliases.nix {}; +in { + home.packages = with pkgs; [ pure-prompt ]; + programs.zsh = { + enable = true; + enableCompletion = true; + shellAliases = aliases; + + history = { + size = 10000000; + save = 10000000; + findNoDups = true; + saveNoDups = true; + ignoreDups = true; + share = true; + extended = true; + append = true; + path = "$HOME/.zsh_history"; + }; + + initExtra = '' +prompt pure +zstyle :prompt:pure:path color cyan +zstyle :prompt:pure:prompt:error color red +zstyle :prompt:pure:prompt:success color green +bindkey -v +autoload -Uz edit-command-line +zle -N edit-command-line +bindkey '^X^E' edit-command-line +''; + }; + + programs.fzf = { + enable = true; + enableZshIntegration = true; + }; +} diff --git a/new/hosts/laptop/default.nix b/new/hosts/laptop/default.nix new file mode 100644 index 0000000..59e58c0 --- /dev/null +++ b/new/hosts/laptop/default.nix @@ -0,0 +1,6 @@ +{modulesPath, ...}: { + imports = [ + ./disks.nix + (modulesPath + "/installer/scan/not-detected.nix") + ]; +} diff --git a/new/hosts/laptop/disks.nix b/new/hosts/laptop/disks.nix new file mode 100644 index 0000000..840923c --- /dev/null +++ b/new/hosts/laptop/disks.nix @@ -0,0 +1,78 @@ +{ + disko.devices = { + disk = { + root = { + type = "disk"; + device = "/dev/nvme0n1"; + content = { + type = "gpt"; + partitions = { + ESP = { + label = "boot"; + name = "ESP"; + type = "EF00"; + size = "512M"; + content = { + type = "filesystem"; + format = "vfat"; + mountpoint = "/boot"; + mountOptions = [ "umask=0077" ]; + }; + }; + + luks = { + size = "100%"; + label = "luks"; + content = { + type = "luks"; + name = "cryptroot"; + extraOpenArgs = [ + "--allow-discards" + "--perf-no_read_workqueue" + "--perf-no_write_workqueue" + ]; + # https://0pointer.net/blog/unlocking-luks2-volumes-with-tpm2-fido2-pkcs11-security-hardware-on-systemd-248.html + settings = {crypttabExtraOpts = ["tpm2-device=auto" "token-timeout=10"];}; + content = { + type = "btrfs"; + extraArgs = ["-L" "nixos" "-f"]; + subvolumes = { + "@root" = { + mountpoint = "/"; + mountOptions = ["subvol=@root" "compress=zstd" "noatime"]; + }; + "@home" = { + mountpoint = "/home"; + mountOptions = ["subvol=@home" "compress=zstd" "noatime"]; + }; + "@nix" = { + mountpoint = "/nix"; + mountOptions = ["subvol=@nix" "compress=zstd" "noatime"]; + }; + "@persist" = { + mountpoint = "/persist"; + mountOptions = ["subvol=@persist" "compress=zstd" "noatime"]; + }; + "@log" = { + mountpoint = "/var/log"; + mountOptions = ["subvol=@log" "compress=zstd" "noatime"]; + }; + "@snapshots" = { + }; + "@swap" = { + mountpoint = "/swap"; + swap.swapfile.size = "32G"; + }; + }; + }; + }; + }; + }; + }; + }; + }; + }; + + fileSystems."/persist".neededForBoot = true; + fileSystems."/var/log".neededForBoot = true; +} diff --git a/new/hosts/vm.nix b/new/hosts/vm.nix new file mode 100644 index 0000000..1a2c661 --- /dev/null +++ b/new/hosts/vm.nix @@ -0,0 +1,29 @@ +{config, lib, modulesPath, ...}: { + imports = [ + ../options.nix + (modulesPath + "/profiles/qemu-guest.nix") + ]; + + vmGuest = true; + + boot = { + kernelModules = [ "kvm-intel" ]; + initrd.availableKernelModules = [ "virtio_pci" "ahci" "xhci_pci" "sr_mod" "virtio_blk" ]; + }; + + networking.useDHCP = lib.mkDefault true; + nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; + + fileSystems."/" = + { device = "/dev/disk/by-uuid/723e4a6a-97b9-49ff-999f-806b12ea26b6"; + fsType = "ext4"; + }; + + fileSystems."/boot" = + { device = "/dev/disk/by-uuid/15E6-98FA"; + fsType = "vfat"; + options = [ "fmask=0077" "dmask=0077" ]; + }; + + swapDevices = [ ]; +} diff --git a/new/options.nix b/new/options.nix new file mode 100644 index 0000000..c47bfc3 --- /dev/null +++ b/new/options.nix @@ -0,0 +1,21 @@ +{lib, ...}: { + options = { + has_battery = lib.mkOption { + type = lib.types.bool; + default = false; + description = "Whether the system has a battery."; + }; + + vmGuest = lib.mkOption { + type = lib.types.bool; + default = false; + description = "Enable VM guest services."; + }; + + darkMode = lib.mkOption { + type = lib.types.bool; + default = false; + description = "Enable dark mode for the system."; + }; + }; +} diff --git a/new/system/default.nix b/new/system/default.nix new file mode 100644 index 0000000..a2c8206 --- /dev/null +++ b/new/system/default.nix @@ -0,0 +1,114 @@ +{pkgs, config, ...}: { + imports = [ + ../options.nix + ]; + + environment.systemPackages = with pkgs; [ + # Basic utilities + zsh + wget + curl + git + vim + + htop + + linux-firmware + linuxHeaders + ]; + + nix.settings.experimental-features = [ + "nix-command" + "flakes" + ]; + + system.stateVersion = "25.05"; + + boot = { + loader.systemd-boot.enable = true; + loader.efi.canTouchEfiVariables = true; + + # kernelModules = []; + kernelPackages = pkgs.linuxPackages_zen; + }; + + hardware = { + enableAllFirmware = true; + amdgpu.initrd.enable = true; + graphics = { + enable = true; + enable32Bit = true; + }; + }; + + security = { + polkit.enable = true; + rtkit.enable = true; + }; + + fonts = { + enableDefaultPackages = true; + packages = with pkgs; [ + noto-fonts + noto-fonts-cjk-sans + noto-fonts-emoji + liberation_ttf + roboto + roboto-mono + twitter-color-emoji + nerd-fonts.fira-code + nerd-fonts.fira-mono + unicode-emoji + fira-sans + font-awesome + fira-mono + fira-code + material-icons + source-sans + source-code-pro + pkgs.nur.repos.redpz.sf-mono + ]; + fontconfig = { + defaultFonts = { + monospace = ["SF Mono" "Fira Mono" "Noto Mono"]; + serif = ["Liberation Serif" "Noto Serif"]; + sansSerif = ["Liberation Sans" "Noto Sans" "Roboto"]; + emoji = ["Twitter Color Emoji" "Noto Emoji"]; + }; + }; + }; + + networking = { + networkmanager.enable = true; + nameservers = ["1.1.1.1" "9.9.9.9"]; + }; + time.timeZone = "Europe/Amsterdam"; + i18n.defaultLocale = "en_GB.UTF-8"; + + console = { + font = "Lat2-Terminus16"; + keyMap = "uk"; + }; + + services = { + qemuGuest.enable = config.vmGuest; + spice-vdagentd.enable = config.vmGuest; + + pipewire = { + enable = true; + pulse.enable = true; + alsa.enable = true; + alsa.support32Bit = true; + }; + + openssh = { + enable = true; + settings = { + PasswordAuthentication = true; # Enable password authentication. + PermitRootLogin = "yes"; # Allow root login (not recommended for production). + }; + }; + + libinput.enable = true; + }; +} diff --git a/new/user/default.nix b/new/user/default.nix new file mode 100644 index 0000000..57d68f7 --- /dev/null +++ b/new/user/default.nix @@ -0,0 +1,31 @@ +{pkgs, ...}: +let + user = import ../data/user.nix {}; +in { + users.users.${user.username} = { + shell = pkgs.zsh; + group = "users"; + home = "/home/${user.username}"; + createHome = true; + isNormalUser = true; + extraGroups = [ "wheel" "input" ]; + }; + + programs.zsh.enable = true; + + services = { + greetd = { + enable = true; + settings = { + default_session = { + command = "${pkgs.greetd.tuigreet}/bin/tuigreet --time --cmd sway"; + user = "greeter"; + }; + }; + }; + }; + + home-manager.users.${user.username} = { ... }: { + imports = [ ../home ]; + }; +} diff --git a/new/utils.nix b/new/utils.nix new file mode 100644 index 0000000..cd69dfc --- /dev/null +++ b/new/utils.nix @@ -0,0 +1,20 @@ +{lib, ...}: rec { + min = a: b: if a < b then a else b; + max = a: b: if a > b then a else b; + # build list of `len` lists of `n` elements of `xs` + windows = with builtins; n: xs: let + len = length xs; + n' = min n len; + # when len = n, there is still one window + num-windows = max 0 (len - n' + 1); + in + genList + # for i in 0..len + (i: genList + # for j in 0..n -> xs[i + j] + (j: elemAt xs (i + j)) + n') + num-windows; + + isEmptySet = set: with builtins; length (attrNames set) == 0; +}