.
675 |
--------------------------------------------------------------------------------
/README.org:
--------------------------------------------------------------------------------
1 | #+OPTIONS: toc:nil broken-links:t
2 | #+PROPERTY: header-args :noweb yes :results silent :mkdirp yes
3 |
4 | #+HTML:
5 | #+HTML:
6 | #+HTML:

7 | #+HTML:

8 | #+HTML:
9 | #+HTML:
10 | #+HTML:
Sandeep's Literate System Configuration
11 | #+HTML:
12 | #+HTML:
13 | #+HTML:
14 | #+HTML:
31 | #+HTML:
32 | #+HTML:
33 | #+HTML:
34 |
35 | * Introduction
36 | #+HTML:
37 | Hello! Welcome to my literate file that describes (and generates) the configuration for all my computers.
38 |
39 | For people who are confused, this file has a bunch of source blocks that are then put into individual files using emacs+org's tangle mode.
40 |
41 | Once the files are generated, they are converted into an immutable system configuration using nixos.
42 |
43 | This repository consists of configuration for my main machine
44 | - =smallbox= -- my wfh computer and main laptop
45 |
46 | To generate the actual nix files, you need to open this file in emacs and then execute =M-x org-babel-tangle=.
47 |
48 | Or run the following from the command line
49 | #+begin_src bash :tangle no
50 | emacs README.org --batch -f org-babel-tangle
51 | #+end_src
52 |
53 | Once the nix files are ready, you can deploy using
54 | #+begin_src bash :tangle no
55 | nixos-rebuild switch --flake .#
56 | #+end_src
57 |
58 | Other files in this repo are :-
59 | - ~flake.lock~ so as to keep my versions intact. More on that later.
60 | - ~assets/*~ contains images like the wallpaper that cannot be part of this.
61 | - ~secrets/secrets.yaml~ contains encrypted keys and is edited using ~sopsx~.
62 |
63 | The other files in this repository are generated. They ideally shouldn't be edited directly.
64 |
65 | ** Emacs + Org + Tangle
66 | - [[https://www.gnu.org/software/emacs/][Emacs]] is the text editor that I use. Some people might take offense at me calling it a [[https://karl-voit.at/2015/10/23/Emacs-is-not-just-an-editor/][text editor]].
67 | - [[https://orgmode.org/][Org mode]] is an inbuilt plugin for emacs that helps with managing org files like this one. Org files are similar to markdown but with [[https://www.youtube.com/watch?v=fgizHHd7nOo][superpowers]].
68 | - Tangle is an org mode option that lets us export snippets to other files. In this case, the configuration snippets you see are written to individual files.
69 | - Anything that appears in ~<>~ is like a variable that gets filled in later.
70 | You will see them in the snippets below where they are filled in by other snippets later in the file.
71 | ** Nix & Nixos
72 | - [[https://nix.dev/][Nix]] is a bespoke programming language, used mainly to configure environments and dependencies.
73 | - [[https://nixos.org/][Nixos]] is a linux distro where you define your operating system and other things using nix.
74 | The expectation is that the output of evaluating the nix files is a "configuration" that can be applied.
75 | This way your operating system is always defined by configuration files. You almost never install anything.
76 | Make a change to the configuration, reapply and repeat. You need vim? Add it to the config, and rebuild.
77 |
78 | ~YourNixCode(Input) -> System Configuration~
79 |
80 | I use [[https://nixos.wiki/wiki/Flakes][nix flakes]] which means that the entry point for the nix evaluation is a file called ~flake.nix~ which has two parts (among other things)
81 |
82 | #+begin_src nix
83 | {
84 | inputs: # describes the function input, consisting mainly of package sources
85 | outputs: # what the function outputs, a nixos configuration in our case
86 | }
87 | #+end_src
88 |
89 | Nix flakes is still behind an ~experimental~ flag, but it is considered the standard by most of the community.
90 | Flakes allow us to pin the input package versions using a ~flake.lock~ file.
91 | This prevents unwanted and surprise updates when rebuilding without changing the configuration.
92 |
93 | * TLDR App List
94 |
95 | | Window Manager | [[https://hyprland.org/][Hyprland]] |
96 | | Bar | [[https://github.com/Alexays/Waybar][Waybar]] |
97 | | Application Launcher | [[https://github.com/philj56/tofi][Tofi]] |
98 | | Notification Daemon | [[https://github.com/dunst-project/dunst][Dunst]] |
99 | | Terminal Emulator | [[https://alacritty.org/][Alacritty]] |
100 | | Shell | [[https://ohmyz.sh/][zsh + ohmyzsh]] |
101 | | Text Editor | [[https://www.gnu.org/software/emacs/][Emacs]] |
102 | | File Manager | [[https://docs.xfce.org/xfce/thunar/start][Thunar]] |
103 | | Fonts | [[https://typeof.net/Iosevka/][Iosevka]] |
104 | | Colors | [[https://www.nordtheme.com/][Nord]] |
105 | | Icons | [[https://github.com/alvatip/Nordzy-icon][Nordzy]] |
106 | | Lock Screen | [[https://wiki.hyprland.org/Hypr-Ecosystem/hyprlock/][Hyprlock]] |
107 | | Wallpapers | [[https://github.com/linuxdotexe/nordic-wallpapers][Nordic]] + [[https://github.com/hyprwm/hyprpaper][Hyprpaper]] |
108 |
109 | * Configuration Variables
110 | I have a bunch of constant strings that I would rather put in a file. Thats what ~user.nix~ is.
111 | The values are imported at the beginning and are available to almost all the functions being called to configure the system.
112 | #+begin_src nix :tangle user.nix
113 | {
114 | system = "x86_64-linux";
115 | username = "nambiar";
116 | stateVersion = "25.05";
117 | locale = "sv_SE.UTF-8";
118 | }
119 | #+end_src
120 |
121 | * Flake Inputs
122 | The inputs for my system's configuration are very simple
123 | 1. [[https://search.nixos.org/packages][nixpkgs]] - the main nix repository of packages. Its huge and growing. Pinned to the unstable release channel.
124 | Sometimes pinned to a specific commit because unstable broke something and the fix hasn't made it into the release yet.
125 | 2. [[https://nix-community.github.io/home-manager/][home-manager]] - a nix module that helps keep track of user specific dotfiles and configurations as part of my nix config.
126 | 3. [[https://github.com/nix-community/emacs-overlay][emacs-overlay]] - this has more configuration options and generally a newer emacs available provided by the community.
127 |
128 | #+begin_src nix :tangle flake.nix :noweb tangle
129 | {
130 | description = "Sandeep's nixos configuration";
131 |
132 | inputs = {
133 | nixpkgs.url = "github:nixos/nixpkgs/nixpkgs-unstable";
134 |
135 | home-manager = {
136 | url = "github:nix-community/home-manager";
137 | inputs.nixpkgs.follows = "nixpkgs";
138 | };
139 |
140 | emacs-overlay.url = "github:nix-community/emacs-overlay";
141 |
142 | sops-nix.url = "github:Mic92/sops-nix";
143 | };
144 |
145 | <>
146 | }
147 | #+end_src
148 |
149 | * Flake Output
150 | Now that the inputs are ready, the outputs define what the system will actually look like. I also define the machines that this configuration specifies early on. Finally, I iterate over the ~machines~ list and pull files from ~/.machines/${name}~ subdirectory. This allows me to have configuration that has machine specific configuration limited to those files while also keeping a modular reusable base.
151 | We also add a devshell that makes editing this repository easier in emacs.
152 |
153 | #+name: flake-outputs
154 | #+begin_src nix :noweb no-export
155 | outputs = {
156 | nixpkgs,
157 | home-manager,
158 | emacs-overlay,
159 | sops-nix,
160 | ...
161 | }:
162 | let
163 | user = import ./user.nix;
164 | lib = nixpkgs.lib;
165 | machines = [
166 | "smallbox"
167 | ];
168 | pkgs = import nixpkgs {
169 | inherit (user) system;
170 | };
171 | in
172 | {
173 | nixosConfigurations = builtins.listToAttrs (
174 | builtins.map (machine: {
175 | name = machine;
176 | value = lib.nixosSystem {
177 | modules = [
178 | <>
179 | <>
180 | <>
181 | sops-nix.nixosModules.sops # sops
182 | ];
183 | specialArgs = {
184 | hostname = machine;
185 | inherit user;
186 | };
187 | };
188 | }) machines
189 | );
190 | devShells.${user.system}.default = pkgs.mkShell {
191 | buildInputs = with pkgs; [
192 | nil # nix lsp server
193 | nixfmt-rfc-style # nix formatter
194 | sops # used to edit secrets
195 | ];
196 | };
197 | };
198 | #+end_src
199 |
200 | Lets look at the individual modules
201 | 1. Emacs
202 | The first is the emacs overlay so that it uses the nix-community emacs overlay from the inputs instead of the nixpkgs one.
203 | Overlays are a special nix way to override existing packages within a repository.
204 |
205 | #+name: flake-emacs-module
206 | #+begin_src nix
207 | ({ ... }: {
208 | nixpkgs.overlays = [ emacs-overlay.overlays.default ];
209 | })
210 | #+end_src
211 |
212 | 2. Then the machine specific configuration
213 | #+name: flake-config-module
214 | #+begin_src nix
215 | ./machines/${machine}/configuration.nix
216 | #+end_src
217 |
218 | 3. And finally the home-manager module.
219 | This can be initialized and managed on its own but I'd rather use the ~nixos-rebuild~ command to build everything instead of managing userland dotfiles separately.
220 |
221 | #+name: flake-home-module
222 | #+begin_src nix :noweb no-export
223 | home-manager.nixosModules.home-manager
224 | {
225 | home-manager.useGlobalPkgs = true;
226 | home-manager.useUserPackages = true;
227 | home-manager.extraSpecialArgs = {
228 | inherit user;
229 | };
230 | <>
231 | <>
232 | }
233 | #+end_src
234 |
235 | - Home-Manager will not overwrite existing configuration files and that is good in most cases, but when everything is declarative like it is here, I'd rather that home-manager create a ~.backup~ and replace the file.
236 | #+name: flake-home-backup
237 | #+begin_src nix
238 | home-manager.backupFileExtension = "backup";
239 | #+end_src
240 |
241 | - Finally I pull in the machine specific home configuration.
242 | #+name: flake-home-config
243 | #+begin_src nix
244 | home-manager.users.${user.username} = {
245 | imports = [./machines/${machine}/home.nix];
246 | };
247 | #+end_src
248 |
249 | ** Envrc + Direnv
250 | Editing this file will be much nicer if we have the dev environment configured.
251 | That is done in the devshells section. But to auto load this dev shell, we need a .envrc file.
252 | This tells [[https://direnv.net/][direnv]] to load the devshell in the flake.
253 | Finally, we also look for a .envrc-private file and try to load that. That contains devshell specific secrets.
254 |
255 | #+begin_src nix :tangle .envrc
256 | use flake
257 |
258 | watch_file .envrc.private
259 | if [[ -f .envrc.private ]]; then
260 | source_env .envrc.private
261 | fi
262 | #+end_src
263 |
264 | * Machines
265 | The individual machines subdirectory is configured as follows :-
266 | #+name: tree
267 | #+begin_src ditaa
268 | +--machine
269 | | +--configuration.nix
270 | | +--home.nix
271 | | +--hardware-configuration.nix
272 | #+end_src
273 |
274 | - configuration.nix has the system configuration.
275 | - home.nix has the user level configuration.
276 | - hardware-configuration.nix has the unique hardware configuration.
277 |
278 | ~nixos-rebuild switch --flake .#smallbox~ looks for the smallbox configuration (in ~/machines/smallbox~) and returns the configuration that is specific to that computer.
279 |
280 | - Note about imports
281 | ~imports = []~ in a nix file will pull in the function/object from the list of files provided.
282 | This imported object (or function result) is just trivially merged into a common object.
283 |
284 | We can take a look at that the common hardware options I have for all my machines.
285 | *** Other Utils
286 | **** Updates
287 | To update the computer, I just need to update the ~flake.lock~ file to have references to the latest repository. This is done with :-
288 | #+begin_src bash
289 | nix flake update
290 | #+end_src
291 |
292 | **** Editing secrets
293 | The age key needs to exist. Then I can edit the secrets using :-
294 | #+begin_src bash
295 | sops edit secrets/secrets.yaml
296 | #+end_src
297 |
298 | * Hardware
299 | I'll let the code comments explain the file here.
300 |
301 | #+begin_src nix :tangle hardware/hardware.nix :noweb tangle :mkdirp yes
302 | { pkgs, lib, user, config, ...} :
303 | {
304 | # allow automatic ip assignment when connecting to a network
305 | networking.useDHCP = lib.mkDefault true;
306 |
307 | # let wifi info be NOT declarative, allowing user to configure wifi.
308 | networking.wireless.userControlled.enable = true;
309 |
310 | nixpkgs.hostPlatform = lib.mkDefault user.system; # x86_64-linux
311 | powerManagement.cpuFreqGovernor = lib.mkDefault "powersave"; # enable power saving on the cpu
312 |
313 | # update cpu microcode with firmware that allows redistribution
314 | hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
315 |
316 | hardware = {
317 | # always enable bluetooth
318 | bluetooth.enable = true;
319 |
320 | # always enable graphics drivers and enable a bunch of layers for it (including vulkan validation)
321 | graphics = {
322 | enable = true;
323 | extraPackages = with pkgs; [
324 | vulkan-validation-layers # helps catch and debug vulkan crashes
325 | ];
326 | };
327 | };
328 |
329 | hardware.enableAllFirmware = true; # enable all firmware regardless of license
330 | }
331 | #+end_src
332 | * Configuration
333 | This section describes the main system configuration for the computers that I have. Nix will look for a ~default.nix~ file if you give it a path to a folder to import. And ~default.nix~ looks as follows :-
334 |
335 | #+begin_src nix :tangle configuration/default.nix :noweb tangle :mkdirp yes
336 | { pkgs, user, ... } :
337 | {
338 | imports = [
339 | ./boot.nix
340 | ./login.nix
341 | ./cli.nix
342 | ./files.nix
343 | ./locale.nix
344 | ./nix-settings.nix
345 | ./networking.nix
346 | ./hyprland.nix
347 | ./services.nix
348 | ./audio.nix
349 | ./steam.nix
350 | ./sops.nix
351 | ];
352 |
353 | <>
354 |
355 | <>
356 |
357 | <>
358 |
359 | <>
360 |
361 | system.stateVersion = user.stateVersion;
362 | }
363 | #+end_src
364 |
365 | Whoa. Thats a lot of imports. Lets go through them one by one.
366 |
367 | ** Nix Settings
368 | These are global nix settings that configure the settings for the actual tool.
369 |
370 | #+begin_src nix :tangle configuration/nix-settings.nix :noweb tangle :mkdirp yes
371 | { pkgs, user, ... } :
372 | {
373 | nix.settings = {
374 | # enable flakes
375 | experimental-features = ["nix-command" "flakes"];
376 |
377 | # add a cache that speed up new applications by downloading binaries
378 | # from the trusted cache instead of compiling from source
379 | substituters = [ "https://nix-community.cachix.org" ];
380 | # trust the cache public key
381 | trusted-public-keys = [
382 | "nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs="
383 | ];
384 | };
385 |
386 | # allow proprietary software on this machine. I'm not a purist.
387 | nixpkgs.config.allowUnfree = true;
388 |
389 | # this declares how often old configurations are cleared up.
390 | # i cleanup anything older than a week, every week.
391 | nix.gc = {
392 | automatic = true;
393 | options = "--delete-older-than 7d";
394 | dates = "weekly";
395 | };
396 |
397 | programs = {
398 | # command line utility that makes applying changes easy and pretty
399 | nh = {
400 | enable = true;
401 | flake = "/home/${user.username}/system";
402 | };
403 | };
404 | }
405 | #+end_src
406 |
407 | ** Boot
408 | This file has most of the settings the control how the computer boots up.
409 |
410 | #+begin_src nix :tangle configuration/boot.nix :noweb tangle :mkdirp yes
411 | { pkgs, ... } :
412 | {
413 | boot = {
414 | initrd = {
415 | verbose = false; # its a lot of logs. dont need it, unless we do.
416 | kernelModules = [ ]; # no kernel modules on boot
417 | };
418 |
419 | extraModulePackages = [ ]; # no extra packages on boot either
420 | kernelPackages = pkgs.linuxPackages_latest; # latest greatest linux kernel
421 | kernelParams = [ "silent" ]; # quiet those logs
422 |
423 | consoleLogLevel = 0; # quiten more logs
424 | plymouth.enable = true; # graphical boot animation instead
425 |
426 | supportedFilesystems = [ "ntfs" ]; # should see the ntfs (windows)
427 |
428 | loader = {
429 | systemd-boot.enable = true; # systemd-boot
430 | efi.canTouchEfiVariables = true; # allow editing efi to edit the boot loader
431 |
432 | grub = {
433 | # this keeps old versions of my applied configurations
434 | # 50 is high, but i have disk space
435 | configurationLimit = 50;
436 | };
437 |
438 | timeout = 5; # grub timeout to make a selection
439 | };
440 | };
441 | }
442 | #+end_src
443 |
444 | ** Login
445 | Here we control what the login screen would look like. I'm using greetd's [[https://github.com/apognu/tuigreet][tuigreet]] for the ui.
446 | Doesn't match the rest of the aesthetic of the system (with hyprland), but I like its simplicity.
447 |
448 | #+begin_src nix :tangle configuration/login.nix :noweb tangle :mkdirp yes
449 | { pkgs, user, ... } :
450 | {
451 | environment.systemPackages = with pkgs; [
452 | greetd.tuigreet
453 | ];
454 |
455 | services.greetd = {
456 | enable = true;
457 | settings = {
458 | default_session = {
459 | command = pkgs.lib.mkForce "${pkgs.greetd.tuigreet}/bin/tuigreet --remember --time --time-format '%I:%M %p | %a • %h | %F'";
460 | };
461 | };
462 | };
463 | }
464 |
465 | #+end_src
466 |
467 | ** CLI
468 | This is the initial system level configuration for the terminal that I use on this machine. Its just [[https://ohmyz.sh/][zsh]].
469 |
470 | #+begin_src nix :tangle configuration/cli.nix :noweb tangle :mkdirp yes
471 | { pkgs, user, ... }:
472 | {
473 | console.useXkbConfig = true;
474 | users.users.${user.username}.shell = pkgs.zsh;
475 |
476 | environment.shells = with pkgs; [ zsh ];
477 | programs.zsh.enable = true;
478 | }
479 | #+end_src
480 |
481 | ** Files
482 | I use Thunar as the file explorer. Also setup a few plugins for [[https://docs.xfce.org/xfce/thunar/start][Thunar]] in this config.
483 | Along with that, a few other utilities like zip and enabling services to automount usb drives.
484 |
485 | #+begin_src nix :tangle configuration/files.nix :noweb tangle :mkdirp yes
486 | { pkgs, ... } :
487 | {
488 | environment.systemPackages = with pkgs; [
489 | zip
490 | unzip
491 | p7zip
492 | usbutils
493 | udiskie
494 | ];
495 |
496 | programs.thunar = {
497 | enable = true;
498 | plugins = with pkgs.xfce; [
499 | thunar-archive-plugin
500 | thunar-media-tags-plugin
501 | thunar-volman
502 | ];
503 | };
504 |
505 | programs.file-roller.enable = true; # thunar zip support
506 | programs.xfconf.enable = true; # to save thunar settings
507 |
508 | services = {
509 | gvfs.enable = true; # Mount, trash, and other functionalities
510 | tumbler.enable = true; # Thumbnail support for images
511 | udisks2.enable = true; # Auto mount usb drives
512 | };
513 | }
514 | #+end_src
515 |
516 | ** Locale
517 | I live in Sweden and would like all my locale and timezone settings to match. Except my default locale.
518 | #+begin_src nix :tangle configuration/locale.nix :noweb tangle :mkdirp yes
519 | { user, ... } :
520 | let
521 | locale = user.locale;
522 | in
523 | {
524 | # Set your time zone.
525 | time.timeZone = "Europe/Stockholm";
526 |
527 | # Select internationalisation properties.
528 | i18n.defaultLocale = "en_US.UTF-8";
529 |
530 | i18n.extraLocaleSettings = {
531 | LC_ADDRESS = locale;
532 | LC_IDENTIFICATION = locale;
533 | LC_MEASUREMENT = locale;
534 | LC_MONETARY = locale;
535 | LC_NAME = locale;
536 | LC_NUMERIC = locale;
537 | LC_PAPER = locale;
538 | LC_TELEPHONE = locale;
539 | LC_TIME = locale;
540 | };
541 | }
542 | #+end_src
543 |
544 | ** Networking
545 | Not much to see here. I want networking to be enabled. I want firewall as well.
546 | #+begin_src nix :tangle configuration/networking.nix :noweb tangle :mkdirp yes
547 | {
548 | networking = {
549 | networkmanager.enable = true;
550 | firewall.enable = true;
551 | };
552 | }
553 | #+end_src
554 |
555 | ** Hyprland
556 | This is a big one because the DE needs so much configuration. This section mostly installs [[https://hyprland.org/][Hyprland]].
557 | The configuration is done in the home manager section.
558 | #+begin_src nix :tangle configuration/hyprland.nix :noweb tangle :mkdirp yes
559 | { pkgs, ... }:
560 | {
561 | nix.settings = {
562 | # add the hyprland cache so that we dont build hyprland from source
563 | substituters = [ "https://hyprland.cachix.org" ];
564 | trusted-public-keys = [
565 | "hyprland.cachix.org-1:a7pgxzMz7+chwVL3/pzj6jIBMioiJM7ypFP8PwtkuGc="
566 | ];
567 | };
568 |
569 | # these extra portals allow for things like screen sharing
570 | xdg = {
571 | portal = {
572 | enable = true;
573 | extraPortals = [
574 | pkgs.xdg-desktop-portal-wlr
575 | pkgs.xdg-desktop-portal-gtk
576 | ];
577 | };
578 | };
579 |
580 | environment.systemPackages = with pkgs; [
581 | hyprland # the actual package
582 | tofi # launcher
583 | uwsm # wayland session manager
584 | hyprland-qtutils # needed by hyprland
585 | hyprpolkitagent # polkit agent
586 | ];
587 |
588 | # we use uwsm to manage launching hyprland
589 | # uswm will add hyprland to the login sessions with greetd.
590 | programs = {
591 | uwsm.enable = true;
592 | uwsm.waylandCompositors = {
593 | hyprland = {
594 | prettyName = "Hyprland";
595 | comment = "Hyprland compositor managed by UWSM";
596 | binPath = "/run/current-system/sw/bin/Hyprland";
597 | };
598 | };
599 |
600 | hyprland = {
601 | withUWSM = true;
602 | enable = true;
603 | xwayland.enable = true;
604 | };
605 | };
606 |
607 | # this is mainly for the lock screen
608 | # lock.png is provided elsewhere
609 | services.xserver = {
610 | enable = true;
611 |
612 | desktopManager = {
613 | xterm.enable = false;
614 | };
615 |
616 |
617 | displayManager = {
618 | lightdm.background = ./lock.png;
619 | };
620 | };
621 |
622 | # this is a lot of env vars.
623 | # and this requires some cleanup
624 | # but hyprland moves fast and some of these are probably outdated already
625 | environment.sessionVariables = {
626 | XDG_SESSION_TYPE="wayland";
627 | XDG_CURRENT_DESKTOP="Hyprland";
628 | XDG_SESSION_DESKTOP="Hyprland";
629 | NIXOS_OZONE_WL="1";
630 | GTK_THEME="Nordic";
631 | XCURSOR_THEME="Nordzy-cursors";
632 | XCURSOR_SIZE="24";
633 | HYPRCURSOR_THEME="Nordzy-cursors";
634 | HYPRCURSOR_SIZE="24";
635 | };
636 |
637 | # allow hyprlock (lockscreen) to lock user session
638 | security.pam.services.hyprlock = { };
639 | security.polkit.enable = true;
640 | security.pam.services.gdm.enableGnomeKeyring = true;
641 | }
642 |
643 | #+end_src
644 |
645 | ** Services
646 | These are some of the services that I enable at the system level. Explanation in the comments.
647 | #+begin_src nix :tangle configuration/services.nix :noweb tangle :mkdirp yes
648 | { user, ...} :
649 | {
650 | services = {
651 | blueman.enable = true; # bluetooth manager
652 | fwupd.enable = true; # firmware updating service
653 | fstrim.enable = true; # ssd maintenance service
654 | thermald.enable = true; # thermal regulation service
655 | printing.enable = true; # printing services, cups
656 | gnome.gnome-keyring.enable = true; # keyring
657 | flatpak.enable = true; # allow installing things from flatpaks
658 |
659 | # printer discovery
660 | avahi = {
661 | enable = true;
662 | nssmdns4 = true;
663 | openFirewall = true;
664 | };
665 |
666 | # syncthing
667 | syncthing = {
668 | enable = true;
669 | openDefaultPorts = true;
670 | user = "${user.username}";
671 | configDir = "/home/${user.username}/.conifg/syncthing";
672 | settings = {
673 | devices = {
674 | "phone" = { id = "AC6CP4C-TBXMOU5-DSLTDSJ-B2ZJ65D-EXILKVV-U4QEDVA-AIAJZNJ-MX2RHQP"; };
675 | };
676 |
677 | folders = {
678 | "OrgSync" = {
679 | path = "/home/${user.username}/org";
680 | devices = [ "phone" ];
681 | ignorePerms = true;
682 | };
683 | };
684 | };
685 | };
686 | };
687 |
688 | systemd.services.syncthing.environment.STNODEFAULTFOLDER = "true"; # Don't create default ~/Sync folder
689 |
690 | virtualisation.docker.enable = true; # enable docker
691 | users.users.${user.username}.extraGroups = [ "docker" ];
692 | }
693 | #+end_src
694 |
695 | ** Audio
696 | This is still a work in progress, but it almost works. I enable all the audio related services, hoping everything is going to be okay.
697 | #+begin_src nix :tangle configuration/audio.nix :noweb tangle :mkdirp yes
698 | { pkgs, ...}:
699 | {
700 | environment.systemPackages = with pkgs; [
701 | pamixer
702 | ];
703 | services.pipewire = {
704 | enable = true;
705 | alsa.enable = true;
706 | alsa.support32Bit = true;
707 | pulse.enable = true;
708 | jack.enable = true;
709 | };
710 |
711 | # pipewire needs realtime scheduling access
712 | security.rtkit.enable = true;
713 | }
714 | #+end_src
715 |
716 | ** Steam
717 | Finally, I have steam installed and it requires a few extra things as well.
718 | #+begin_src nix :tangle configuration/steam.nix :noweb tangle :mkdirp yes
719 | { pkgs, ... } :
720 | {
721 | environment.systemPackages = with pkgs; [
722 | steam-run # also used for random executables that expect fhs
723 | ];
724 |
725 | programs.steam = {
726 | enable = true;
727 | # Open ports in the firewall for Steam Remote Play
728 | remotePlay.openFirewall = true;
729 | # Open ports in the firewall for Source Dedicated Server
730 | dedicatedServer.openFirewall = true;
731 | };
732 | }
733 | #+end_src
734 |
735 | ** Sops
736 | We use [[https://github.com/Mic92/sops-nix][sops]] to manage secrets on this machine.
737 | #+begin_src nix :tangle configuration/sops.nix :noweb tangle :mkdirp yes
738 | { user, ...} :
739 | {
740 | sops.defaultSopsFile = ../secrets/secrets.yaml;
741 | sops.defaultSopsFormat = "yaml";
742 | sops.age.keyFile = "/home/${user.username}/.config/sops/age/keys.txt";
743 |
744 | sops.secrets.claude_key = { # anthropic claude api key, used in emacs
745 | owner = "${user.username}";
746 | };
747 | }
748 | #+end_src
749 |
750 | Sops requires a public ~.sops.yaml~ that dictates how the secrets are encrypted.
751 | This contains the public key and path to the secrets file.
752 |
753 | #+begin_src yaml :tangle .sops.yaml :mkdirp yes
754 | keys:
755 | - &primary age1yq35g6mmlem0rhr47u6ewh8dctlwp9hj0s0ac60e4hrw9hjzlqms6crf7n
756 | creation_rules:
757 | - path_regex: secrets/secrets.yaml$
758 | key_groups:
759 | - age:
760 | - *primary
761 | #+end_src
762 |
763 | ** Miscellaneous Packages and Programs
764 | #+name: config-system-packages
765 | #+begin_src nix
766 | environment.systemPackages = with pkgs; [
767 | wget # fetch utility
768 | curl # more fetch utility
769 | binutils # executable utilities, like ld
770 | dmidecode # tool for dumping system info
771 | libnotify # notification daemon
772 | python3 # nice to have this ready for quick things
773 | cacert # certificate authority
774 | remmina # remote desktop app
775 | ];
776 | #+end_src
777 |
778 | #+name: config-programs
779 | #+begin_src nix
780 | programs = {
781 | nix-ld.enable = true; # helps with linking troubles with dynamic libraries
782 | appimage.enable = true; # allow appimage installations
783 | dconf.enable = true; # to save user settings
784 | gnupg.agent = {
785 | # pgp client
786 | enable = true;
787 | enableSSHSupport = true;
788 | };
789 | firefox.enable = true; # browser
790 | wireshark.enable = true; # vpn
791 | };
792 | #+end_src
793 |
794 | ** Fonts
795 | Nothing much to see here. I love [[https://typeof.net/Iosevka/][iosevka]], and I use it everywhere.
796 | #+name: config-fonts
797 | #+begin_src nix
798 | fonts.packages = with pkgs; [
799 | iosevka
800 | nerd-fonts.iosevka
801 | ];
802 | #+end_src
803 |
804 | ** User Config
805 | This creates the user profile that I login with. Initially created during install.
806 | #+name: config-user
807 | #+begin_src nix
808 | users.users.${user.username} = {
809 | isNormalUser = true;
810 | description = "Sandeep Nambiar";
811 | extraGroups = [
812 | "networkmanager" # allow editing network connections
813 | "wheel" # can do sudo
814 | "scanner" # access to the network scanner
815 | "lp" # access to the printer
816 | ];
817 | };
818 | #+end_src
819 |
820 | * Home
821 | I use home-manager to manage my user level dotfiles and configurations.
822 | Most of the "theme" of the system is decided here.
823 | I also use it to install programs that are okay with being installed at the user level instead of the system.
824 |
825 | #+begin_src nix :tangle home/default.nix :noweb tangle :mkdirp yes
826 | { pkgs, user, ... } :
827 | {
828 | imports = [
829 | ./waybar.nix
830 | ./wallpaper.nix
831 | ./lock.nix
832 | ./unity.nix
833 | ./hyprland.nix
834 | ./tofi.nix
835 | ./theme.nix
836 | ./terminal.nix
837 | ./dev.nix
838 | ./emacs
839 | ];
840 |
841 | <>
842 |
843 | <>
844 |
845 | programs.home-manager.enable = true;
846 | }
847 | #+end_src
848 | Oof! Again with all the imports! We can go through them one at a time!
849 |
850 | ** Waybar
851 | [[./.github/images/waybar.png]]
852 |
853 | Mostly styling and enabling modules in the [[https://github.com/Alexays/Waybar][top bar]].
854 | #+begin_src nix :tangle home/waybar.nix :noweb tangle :mkdirp yes
855 | {
856 | programs.waybar = {
857 | enable = true;
858 | settings = {
859 | mainBar = {
860 | layer = "top";
861 | height = 24;
862 | modules-left = [ "hyprland/workspaces" "hyprland/window" ];
863 | modules-right = [
864 | "idle_inhibitor"
865 | "pulseaudio"
866 | "network"
867 | "cpu"
868 | "memory"
869 | "temperature"
870 | "battery"
871 | "tray"
872 | "clock"
873 | ];
874 | "idle_inhibitor" = {
875 | format = "{icon}";
876 | format-icons = {
877 | activated = " ";
878 | deactivated = " ";
879 | };
880 | };
881 | "pulseaudio" = {
882 | "format" = "{volume}% {icon}";
883 | "format-bluetooth" = "{volume}% {icon}";
884 | "format-muted" = "";
885 | "format-icons"= {
886 | "headphones"= "";
887 | "headset"= "";
888 | "phone"= "";
889 | "portab le"= "";
890 | "default"= ["" ""];
891 | };
892 | "on-click"= "pavucontrol";
893 | };
894 | "network" = {
895 | "format-wifi" = " ({bandwidthDownBits})";
896 | "format-ethernet" = " ({bandwidthDownBits})";
897 | "format-disconnected" = "Disconnected ⚠";
898 | "tooltip-format-wifi" = "{essid} ({signalStrength}%)";
899 | "tooltip-format-ethernet" = "{ifname}: {ipaddr}/{cidr}";
900 | };
901 | "cpu".format = "{usage}% ";
902 | "cpu".tooltip = false;
903 | "temperature" = {
904 | "format" = "{temperatureC}°C ";
905 | };
906 | "temperature".tooltip = false;
907 | "tray".spacing = 10;
908 | "tray".icon-size = 14;
909 | "clock".format = "{:%a, %d %b %Y - %H:%M}";
910 | "clock".tooltip = false;
911 | "battery" = {
912 | "bat" = "BAT0";
913 | "states" = {
914 | "good" = 95;
915 | "warning" = 30;
916 | "critical" = 15;
917 | };
918 | "format" = "{capacity}% {icon}";
919 | "format-charging" = "{capacity}% ";
920 | "format-plugged" = "{capacity}% ";
921 | "format-icons" = ["" "" "" "" " "];
922 | };
923 | "memory".format = "{percentage}% ";
924 | };
925 | };
926 | style = ''
927 | ,* {
928 | font-family: Iosevka Nerd Font, Roboto, Helvetica, Arial, sans-serif;
929 | font-size: 13px;
930 | }
931 |
932 | window#waybar {
933 | background-color: #4c566a;
934 | color: #ffffff;
935 | transition-property: background-color;
936 | border-bottom: 0px solid rgba(0, 0, 0, 0);
937 | transition-duration: .5s;
938 | }
939 |
940 | #workspaces button {
941 | padding: 0 5px;
942 | background-color: transparent;
943 | border: none;
944 | border-radius: 0;
945 | }
946 |
947 | #workspaces button:hover {
948 | background: #2e3440;
949 | color: white;
950 | }
951 |
952 | #workspaces button.active {
953 | background-color: #5e81ac;
954 | box-shadow: inset 0 -3px #ffffff;
955 | }
956 |
957 | #clock,
958 | #idle_inhibitor
959 | #battery,
960 | #cpu,
961 | #memory,
962 | #temperature,
963 | #network,
964 | #pulseaudio,
965 | #tray {
966 | margin: 0 5px;
967 | padding: 0 2px;
968 | }
969 |
970 | #idle_inhibitor.activated {
971 | background-color: #a3be8c;
972 | }
973 |
974 | #battery.charging {
975 | color: #a3be8c;
976 | }
977 |
978 | @keyframes blink {
979 | to {
980 | background-color: #ffffff;
981 | color: black;
982 | }
983 | }
984 |
985 | #battery.warning:not(.charging) {
986 | color: white;
987 | animation-name: blink;
988 | animation-duration: 0.5s;
989 | animation-timing-function: linear;
990 | animation-iteration-count: infinite;
991 | animation-direction: alternate;
992 | }
993 |
994 | #window,
995 | #workspaces {
996 | margin: 0 4px;
997 | }
998 |
999 | .modules-left > widget:first-child > #workspaces {
1000 | margin-left: 0;
1001 | }
1002 |
1003 | .modules-right > widget:last-child > #workspaces {
1004 | margin-right: 0;
1005 | }
1006 |
1007 | #network.disconnected {
1008 | background-color: #f53c3c;
1009 | }
1010 |
1011 | #temperature.critical {
1012 | background-color: #eb4d4b;
1013 | }
1014 | '';
1015 | };
1016 | }
1017 |
1018 | #+end_src
1019 |
1020 | ** Wallpaper
1021 |
1022 | [[./assets/background.png]]
1023 | I use [[https://wiki.hyprland.org/Hypr-Ecosystem/hyprpaper/][hyprpaper]] for setting the wallpaper. The image is copied into the home folder when applying this configuration and the tool picks it from there.
1024 | #+begin_src nix :tangle home/wallpaper.nix :noweb tangle :mkdirp yes
1025 | { pkgs, ... }:
1026 | {
1027 | home.packages = with pkgs; [
1028 | hyprpaper
1029 | ];
1030 |
1031 | services.hyprpaper.enable = true;
1032 | services.hyprpaper.settings = {
1033 | ipc = "on";
1034 | splash = false;
1035 | splash_offset = 2.0;
1036 |
1037 | preload = [ "~/.background-image.png" ];
1038 | wallpaper = [ ",~/.background-image.png" ];
1039 | };
1040 |
1041 | home.file = {
1042 | background = {
1043 | source = ../assets/background.png;
1044 | target = ".background-image.png";
1045 | };
1046 |
1047 | me = {
1048 | source = ../assets/me.jpg;
1049 | target = ".me.jpg";
1050 | };
1051 | };
1052 | }
1053 |
1054 | #+end_src
1055 | ** Lock Screen
1056 | The lock screen configured using [[https://wiki.hyprland.org/Hypr-Ecosystem/hyprlock/][hyprlock]].
1057 | I use [[https://wiki.hyprland.org/Hypr-Ecosystem/hypridle/][hypridle]] to detect idle time and use wlogout to show a logout menu.
1058 | They are configured below.
1059 | #+begin_src nix :tangle home/lock.nix :noweb tangle :mkdirp yes
1060 | { pkgs, ... } :
1061 | {
1062 | home.packages = with pkgs; [
1063 | hyprlock
1064 | hypridle
1065 | wlogout
1066 | ];
1067 |
1068 |
1069 | home.file = {
1070 | lock = {
1071 | source = ../assets/lock.png;
1072 | target = ".lock.png";
1073 | };
1074 | };
1075 |
1076 | services = {
1077 | # hypridle to
1078 | # 150 seconds - turn of monitor
1079 | # 300 seconds - lock screen
1080 | # 330 seconds - turn of monitor
1081 | # 30 minutes - put to sleep
1082 | hypridle = {
1083 | enable = true;
1084 | settings = {
1085 | general = {
1086 | lock_cmd = "pidof hyprlock || hyprlock"; # avoid starting multiple hyprlock instances.
1087 | before_sleep_cmd = "loginctl lock-session"; # lock before suspend.
1088 | after_sleep_cmd = "hyprctl dispatch dpms on"; # to avoid having to press a key twice to turn on the display.
1089 | };
1090 |
1091 | listener = [
1092 | {
1093 | timeout = 150; # 2.5min.
1094 | on-timeout = "brightnessctl -s set 10"; # set monitor backlight to minimum, avoid 0 on OLED monitor.
1095 | on-resume = "brightnessctl -r"; # monitor backlight restore.
1096 | }
1097 | {
1098 | timeout = 300; # 5min
1099 | on-timeout = "loginctl lock-session"; # lock screen when timeout has passed
1100 | }
1101 | {
1102 | timeout = 330; # 5.5min
1103 | on-timeout = "hyprctl dispatch dpms off"; # screen off when timeout has passed
1104 | on-resume = "hyprctl dispatch dpms on && brightnessctl -r"; # screen on when activity is detected after timeout has fired.
1105 | }
1106 | {
1107 | timeout = 1800; # 30min
1108 | on-timeout = "systemctl suspend"; # suspend pc
1109 | }
1110 | ];
1111 |
1112 | };
1113 | };
1114 | };
1115 |
1116 | programs.wlogout = {
1117 | enable = true;
1118 | layout = [
1119 | {
1120 | "label" = "lock";
1121 | "action" = "hyprlock";
1122 | "text" = "Lock";
1123 | "keybind" = "l";
1124 | }
1125 | {
1126 | "label" = "shutdown";
1127 | "action" = "systemctl poweroff";
1128 | "text" = "Shutdown";
1129 | "keybind" = "s";
1130 | }
1131 | {
1132 | "label" = "suspend";
1133 | "action" = "systemctl suspend";
1134 | "text" = "Suspend";
1135 | "keybind" = "u";
1136 | }
1137 | {
1138 | "label" = "reboot";
1139 | "action" = "systemctl reboot";
1140 | "text" = "Reboot";
1141 | "keybind" = "r";
1142 | }
1143 | {
1144 | "label" = "hibernate";
1145 | "action" = "systemctl hibernate";
1146 | "text" = "Hibernate";
1147 | "keybind" = "h";
1148 | }
1149 | {
1150 | "label" = "reboot";
1151 | "action" = "systemctl reboot";
1152 | "text" = "Reboot";
1153 | "keybind" = "r";
1154 | }
1155 | ];
1156 | };
1157 | }
1158 |
1159 | #+end_src
1160 | ** Unity
1161 | I work with the [[https://unity.com/][Unity Game Engine]] and I have the unity hub installed globally, instead of in a project flake.
1162 | Often I work with dotnet directly inside of unity and so we set that up too.
1163 | #+begin_src nix :tangle home/unity.nix :noweb tangle :mkdirp yes.
1164 | { pkgs, ... }:
1165 | {
1166 | home.packages = with pkgs; [
1167 | (pkgs.unityhub.override {
1168 | extraPkgs = pkgs: with pkgs; [
1169 | dotnet-sdk
1170 | ];
1171 | })
1172 | ];
1173 | }
1174 | #+end_src
1175 |
1176 | ** Hyprland
1177 | This configures the desktop environment along with the peripherals. The comments should explain whats happening.
1178 | #+begin_src nix :tangle home/hyprland.nix :noweb tangle :mkdirp yes.
1179 | {
1180 | # required for the default Hyprland config
1181 | programs.kitty.enable = true;
1182 |
1183 | services.hyprpolkitagent.enable = true;
1184 |
1185 | # enable Hyprland
1186 | wayland.windowManager.hyprland.enable = true;
1187 |
1188 | # we start hyprland using uwsm
1189 | wayland.windowManager.hyprland.systemd.enable = false;
1190 |
1191 | # hyprland.conf
1192 | wayland.windowManager.hyprland.settings = {
1193 | exec-once = [
1194 | # read in env vars
1195 | "dbus-update-activation-environment --systemd --all"
1196 | # start waybar
1197 | "uwsm app -- waybar"
1198 | # start the policykit agent
1199 | "uwsm app -- lxqt-policykit-agent"
1200 | ];
1201 |
1202 | input = {
1203 | follow_mouse = "1";
1204 |
1205 | touchpad = {
1206 | natural_scroll = "no";
1207 | scroll_factor = 0.5;
1208 | };
1209 |
1210 | accel_profile = "adaptive";
1211 | sensitivity = -0.5; # -1.0 - 1.0, 0 means no modification.
1212 |
1213 | kb_layout = "us";
1214 |
1215 | # very emacs specific, i use caps as an extra ctrl key
1216 | kb_options = "ctrl:nocaps";
1217 | };
1218 |
1219 | cursor = {
1220 | no_hardware_cursors = "true";
1221 | };
1222 |
1223 | general = {
1224 | gaps_in = 2;
1225 | gaps_out = 4;
1226 | border_size = 2;
1227 | "col.active_border" = "rgba(33ccffee) rgba(00ff99ee) 45deg";
1228 | "col.inactive_border" = "rgba(595959aa)";
1229 |
1230 | layout = "dwindle";
1231 | };
1232 |
1233 | decoration = {
1234 | rounding = 5;
1235 | };
1236 |
1237 | animations = {
1238 | enabled = "yes";
1239 | bezier = "myBezier, 0.05, 0.9, 0.1, 1.05";
1240 |
1241 | animation = [
1242 | "windows, 1, 7, myBezier"
1243 | "windowsOut, 1, 7, default, popin 80%"
1244 | "border, 1, 10, default"
1245 | "borderangle, 1, 8, default"
1246 | "fade, 1, 7, default"
1247 | "workspaces, 1, 6, default"
1248 | ];
1249 | };
1250 |
1251 | dwindle = {
1252 | pseudotile = "yes";
1253 | preserve_split = "yes";
1254 | };
1255 |
1256 | gestures = {
1257 | workspace_swipe = "off";
1258 | };
1259 |
1260 | misc = {
1261 | disable_hyprland_logo = true;
1262 | focus_on_activate = true;
1263 | };
1264 |
1265 | "$mainMod" = "SUPER";
1266 |
1267 | bind = [
1268 | "$mainMod, Return, exec, uwsm app -- alacritty"
1269 | "$mainMod_SHIFT, Q, killactive"
1270 | "$mainMod_SHIFT, M, exit"
1271 | "$mainMod, F, exec, thunar"
1272 | "$mainMod_SHIFT, Space, togglefloating"
1273 |
1274 | # use tofi to show exec menu
1275 | "$mainMod, Space, exec, uwsm app -- tofi-run | xargs hyprctl dispatch -- exec"
1276 | "$mainMod, P, pseudo"
1277 | "$mainMod, J, togglesplit"
1278 |
1279 | "$mainMod_SHIFT, left, movewindow, l"
1280 | "$mainMod_SHIFT, right, movewindow, r"
1281 | "$mainMod_SHIFT, up, movewindow, u"
1282 | "$mainMod_SHIFT, down, movewindow, d"
1283 |
1284 | "$mainMod_CTRL, left, movecurrentworkspacetomonitor, l"
1285 | "$mainMod_CTRL, right, movecurrentworkspacetomonitor, r"
1286 |
1287 | "$mainMod, left, movefocus, l"
1288 | "$mainMod, right, movefocus, r"
1289 | "$mainMod, up, movefocus, u"
1290 | "$mainMod, down, movefocus, d"
1291 |
1292 | "$mainMod, mouse_down, workspace, e+1"
1293 | "$mainMod, mouse_up, workspace, e-1"
1294 |
1295 | "$mainMod_SHIFT, S, exec, wlogout"
1296 | ] ++ (
1297 | # workspaces
1298 | # binds $mod + [shift +] {1..9} to [move to] workspace {1..9}
1299 | builtins.concatLists (builtins.genList (i:
1300 | let ws = i + 1;
1301 | in [
1302 | "$mainMod, ${toString ws}, workspace, ${toString ws}"
1303 | "$mainMod SHIFT, ${toString ws}, movetoworkspace, ${toString ws}"
1304 | ]
1305 | )
1306 | 9)
1307 | );
1308 |
1309 | bindm = [
1310 | "$mainMod, mouse:272, movewindow"
1311 | "$mainMod, mouse:273, resizewindow"
1312 | ];
1313 | };
1314 |
1315 | programs.hyprlock = {
1316 | enable = true;
1317 |
1318 | # hyprlock.conf
1319 | settings = {
1320 | background = {
1321 | monitor = "";
1322 | path = "~/.background-image.png";
1323 | blur_passes = 2;
1324 | contrast = 1;
1325 | brightness = 0.5;
1326 | vibrancy = 0.2;
1327 | vibrancy_darkness = 0.2;
1328 | };
1329 |
1330 | auth = {
1331 | fingerprint = {
1332 | enabled = true;
1333 | };
1334 | };
1335 |
1336 | # GENERAL
1337 | general = {
1338 | hide_cursor = false;
1339 | grace = 0;
1340 | };
1341 |
1342 | # INPUT FIELD
1343 | input-field = [
1344 | {
1345 | size = "250, 60";
1346 | outline_thickness = 2;
1347 | dots_size = 0.2;
1348 | dots_spacing = 0.35;
1349 | dots_center = true;
1350 | outer_color = "rgba(216,222,233,0.2)";
1351 | inner_color = "rgba(216,222,233,1)";
1352 | font_color = "rgba(41,46,57,1)";
1353 | fade_on_empty = false;
1354 | rounding = -1;
1355 | check_color = "rgb(163,190,140)";
1356 | placeholder_text = ''Password'';
1357 | hide_input = false;
1358 | position = "0, -400";
1359 | halign = "center";
1360 | valign = "center";
1361 | }
1362 | ];
1363 |
1364 | # DATE
1365 | label = [
1366 | {
1367 | monitor = "";
1368 | text = ''cmd[update:1000] echo "$(date +"%A, %B %d")"'';
1369 | color = "rgba(242, 243, 244, 0.75)";
1370 | font_size = 22;
1371 | font_family = "Iosevka";
1372 | position = "0, 300";
1373 | halign = "center";
1374 | valign = "center";
1375 | }
1376 | # TIME
1377 | {
1378 | monitor = "";
1379 | text = ''cmd[update:1000] echo "$(date +"%-I:%M")"'';
1380 | color = "rgba(242, 243, 244, 0.75)";
1381 | font_size = 95;
1382 | font_family = "Iosevka";
1383 | position = "0, 200";
1384 | halign = "center";
1385 | valign = "center";
1386 | }
1387 | # USER
1388 | {
1389 | monitor = "";
1390 | text = ''cmd[update:1000] echo $USER'';
1391 | color = "rgba(242, 243, 244, 0.75)";
1392 | font_size = 30;
1393 | font_family = "Iosevka";
1394 | position = "0, -250";
1395 | halign = "center";
1396 | valign = "center";
1397 | }
1398 |
1399 | # battery
1400 | {
1401 | monitor = "";
1402 | text = ''cmd[update:1000] echo "$(cat /sys/class/power_supply/BAT0/capacity) "'';
1403 | color = "rgba(242, 243, 244, 0.75)";
1404 | font_size = 20;
1405 | font_family = "Iosevka";
1406 | position = "-20, -20";
1407 | halign = "right";
1408 | valign = "top";
1409 | }
1410 | ];
1411 |
1412 | # Profile Picture
1413 | image = [
1414 | {
1415 | monitor = "";
1416 | path = "~/.me.jpg";
1417 | size = 200;
1418 | border_size = 2;
1419 | position = "0, -100";
1420 | halign = "center";
1421 | valign = "center";
1422 | }
1423 | ];
1424 | };
1425 | };
1426 | }
1427 | #+end_src
1428 |
1429 | ** Tofi
1430 | [[https://github.com/philj56/tofi][This]] is how I launch applications. It is bound to Win+Space in the hyprland config above.
1431 | Configuration is mostly for visual things here.
1432 | #+begin_src nix :tangle home/tofi.nix :noweb tangle :mkdirp yes.
1433 | {
1434 | programs.tofi.enable = true;
1435 | programs.tofi.settings = {
1436 | font = "Iosevka";
1437 | font-size = 16;
1438 | selection-color = "#a3be8c";
1439 | prompt-text = ":";
1440 | width = 600;
1441 | height = 480;
1442 | background-color = "#2e3440";
1443 | outline-width = 0;
1444 | outline-color = "#080800";
1445 | border-width = 1;
1446 | border-color = "#8fbcbb";
1447 | corner-radius = 10;
1448 | padding-top = 4;
1449 | padding-bottom = 4;
1450 | padding-left = 4;
1451 | padding-right = 4;
1452 | matching-algorithm = "fuzzy";
1453 | };
1454 | }
1455 | #+end_src
1456 |
1457 | ** Theme
1458 | I use the [[https://www.nordtheme.com/][Nord palette]] almost everywhere. I've heard that stylix is good for this, but for now, its manual.
1459 | You'll notice the color values in multiple places outside this as well.
1460 | #+begin_src nix :tangle home/theme.nix :noweb tangle :mkdirp yes.
1461 | { pkgs, ...}:
1462 | {
1463 | home.packages = with pkgs; [
1464 | nordzy-cursor-theme
1465 | nordic
1466 | ];
1467 |
1468 | gtk = {
1469 | enable = true;
1470 | iconTheme = {
1471 | name = "Nordic-bluish";
1472 | package = pkgs.nordic;
1473 | };
1474 | theme = {
1475 | name = "Nordic";
1476 | package = pkgs.nordic;
1477 | };
1478 | cursorTheme = {
1479 | name = "Nordzy-cursors";
1480 | package = pkgs.nordzy-cursor-theme;
1481 | };
1482 | };
1483 | }
1484 | #+end_src
1485 |
1486 | ** Terminal
1487 | [[https://alacritty.org/][Alacritty]] is my terminal program. The snippet below configures how it looks. Mostly nord palette things.
1488 | #+begin_src nix :tangle home/terminal.nix :noweb tangle :mkdirp yes
1489 | {
1490 | programs = {
1491 | alacritty = {
1492 | enable = true;
1493 | settings = {
1494 | font.normal.family = "Iosevka Nerd Font";
1495 | font.size = 12;
1496 | terminal.shell.program = "zsh";
1497 |
1498 | window = {
1499 | padding.x = 4;
1500 | padding.y = 4;
1501 | };
1502 |
1503 | colors = {
1504 | primary = {
1505 | background = "#1f222d";
1506 | foreground = "#d8dee9";
1507 | dim_foreground = "#a5abb6";
1508 | };
1509 | cursor = {
1510 | text = "#2e3440";
1511 | cursor = "#d8dee9";
1512 | };
1513 | normal = {
1514 | black = "#3b4252";
1515 | red = "#bf616a";
1516 | green = "#a3be8c";
1517 | yellow = "#ebcb8b";
1518 | blue = "#81a1c1";
1519 | magenta = "#b48ead";
1520 | cyan = "#88c0d0";
1521 | white = "#e5e9f0";
1522 | };
1523 | };
1524 | };
1525 | };
1526 | };
1527 | }
1528 |
1529 | #+end_src
1530 |
1531 | ** Dev Tools
1532 | All the miscellaneous dev tools on this computer.
1533 | #+begin_src nix :tangle home/dev.nix :noweb tangle :mkdirp yes
1534 | { user, ... }:
1535 | {
1536 | programs = {
1537 | vscode.enable = true; # yes, sometimes i like to dabble
1538 | vim.enable = true; # and this one too
1539 | ripgrep.enable = true; # fast text search across projects
1540 | htop.enable = true; # task manager
1541 |
1542 | # this is mainly for integration with nix flakes in individual projects
1543 | direnv = {
1544 | enable = true;
1545 | enableZshIntegration = true;
1546 | nix-direnv.enable = true;
1547 | };
1548 |
1549 | # zsh everywhere with oh-my-zsh
1550 | zsh = {
1551 | enable = true;
1552 | oh-my-zsh = {
1553 | enable = true;
1554 | plugins = [ "git" ];
1555 | theme = "robbyrussell";
1556 | };
1557 | };
1558 |
1559 | # git with lfs
1560 | git = {
1561 | lfs.enable = true;
1562 | enable = true;
1563 | };
1564 | };
1565 | }
1566 | #+end_src
1567 |
1568 | ** Other Settings
1569 | Some repeated info from the configuration.
1570 | *** Home User
1571 | #+name: home-user
1572 | #+begin_src nix
1573 | home.username = "${user.username}";
1574 | home.homeDirectory = pkgs.lib.mkDefault "/home/${user.username}";
1575 | home.stateVersion = user.stateVersion;
1576 | #+end_src
1577 |
1578 | *** Home Packages
1579 | A bunch of programs that I use.
1580 | #+name: home-packages
1581 | #+begin_src nix
1582 | home.packages = with pkgs; [
1583 | audacity # audio recording
1584 | zoom-us # meetings
1585 | handbrake # video transcoding
1586 | sway-contrib.grimshot # screenshot tool
1587 | xdg-utils # utils, for screensharing
1588 | vlc # media player
1589 | discord # other chat
1590 | slack # work chat
1591 | pavucontrol # audio control
1592 | everdo # gtd tool
1593 | spotify # music player
1594 | simple-scan # scanner software
1595 | ];
1596 | services.dunst.enable = true; # notifications daemon
1597 | programs.obs-studio.enable = true; # screen recording tool
1598 | #+end_src
1599 |
1600 | * Emacs
1601 | I practically live inside emacs. The configuration for it is a mix between init.el and the nix configuration.
1602 | Nix allows me to install emacs packages as part of the configuration which is most of the following file.
1603 | I install the nix community provided emacs overlay that lets me have the latest emacs with pgtk ui (for wayland).
1604 | Comments describe the emacs package and what it does.
1605 | #+begin_src nix :tangle home/emacs/default.nix :noweb tangle :mkdirp yes
1606 | { pkgs, ... }:
1607 | {
1608 | programs.emacs = {
1609 | enable = true;
1610 | # install with tree sitter enabled
1611 | package = (pkgs.emacs-git-pgtk.override { withTreeSitter = true; });
1612 | extraPackages = epkgs: [
1613 | # also install all tree sitter grammars
1614 | epkgs.manualPackages.treesit-grammars.with-all-grammars
1615 | pkgs.nodejs # some emacs deps need node installed
1616 | pkgs.omnisharp-roslyn # c# lsp
1617 | epkgs.nerd-icons # nerd fonts support
1618 | epkgs.doom-modeline # model line
1619 | epkgs.doom-themes # for doom-nord theme
1620 | epkgs.diminish # hides modes from modeline
1621 | epkgs.eldoc # doc support
1622 | epkgs.whitespace-cleanup-mode # cleanup accidental whitespace
1623 | epkgs.pulsar # pulses the cursor when jumping about
1624 | epkgs.which-key # help porcelain
1625 | epkgs.expreg # expand region
1626 | epkgs.vundo # undo tree
1627 | epkgs.puni # structured editing
1628 | epkgs.avy # jumping utility
1629 | epkgs.consult # emacs right click
1630 | epkgs.vertico # minibuffer completion
1631 | epkgs.marginalia # annotations for completions
1632 | epkgs.crux # utilities
1633 | epkgs.magit # git porcelain
1634 | epkgs.nerd-icons-corfu # nerd icons for completion
1635 | epkgs.corfu # completion
1636 | epkgs.cape # completion extensions
1637 | epkgs.orderless # search paradigm
1638 | epkgs.yasnippet # snippets support
1639 | epkgs.yasnippet-snippets # commonly used snippets
1640 | epkgs.projectile # project management
1641 | epkgs.rg # ripgrep
1642 | epkgs.exec-path-from-shell # load env and path
1643 | epkgs.flycheck # error integration
1644 | epkgs.lsp-mode # lsp
1645 | epkgs.lsp-ui # ui for lsp
1646 | epkgs.rust-mode # rust mode (when rust-ts doesn't cut it)
1647 | epkgs.nix-mode # nix lang
1648 | epkgs.eat # better shell
1649 | epkgs.hcl-mode # hashicorp file mode
1650 | epkgs.shell-pop # quick shell popup
1651 | epkgs.f # string + file utilities
1652 | epkgs.gptel # llm chat (mainly claude)
1653 | epkgs.copilot # emacs copilot plugin
1654 | epkgs.envrc # support for loading .envrc
1655 | epkgs.nixpkgs-fmt # format nix files
1656 | ];
1657 | };
1658 |
1659 | home.sessionVariables = {
1660 | EDITOR = "emacs";
1661 | };
1662 |
1663 | home.file = {
1664 | emacs-init = {
1665 | source = ./early-init.el;
1666 | target = ".emacs.d/early-init.el";
1667 | };
1668 |
1669 | emacs = {
1670 | source = ./init.el;
1671 | target = ".emacs.d/init.el";
1672 | };
1673 | };
1674 | }
1675 | #+end_src
1676 |
1677 | ** Early Initialization
1678 | There are some emacs settings that can be configured before the gui shows up.
1679 | And some of them help increase performance and let the gui show up that much faster.
1680 | These are listed here.
1681 |
1682 | #+begin_src emacs-lisp :tangle home/emacs/early-init.el :mkdirp yes
1683 | ;;; package --- early init -*- lexical-binding: t -*-
1684 |
1685 | ;;; Commentary:
1686 | ;;; Prevents white flash and better Emacs defaults
1687 |
1688 | ;;; Code:
1689 | (set-language-environment "UTF-8")
1690 |
1691 | (setq-default
1692 | default-frame-alist
1693 | '((background-color . "#3F3F3F")
1694 | (bottom-divider-width . 1) ; Thin horizontal window divider
1695 | (foreground-color . "#DCDCCC") ; Default foreground color
1696 | (fullscreen . maximized) ; Maximize the window by default
1697 | (horizontal-scroll-bars . nil) ; No horizontal scroll-bars
1698 | (left-fringe . 8) ; Thin left fringe
1699 | (menu-bar-lines . 0) ; No menu bar
1700 | (right-divider-width . 1) ; Thin vertical window divider
1701 | (right-fringe . 8) ; Thin right fringe
1702 | (tool-bar-lines . 0) ; No tool bar
1703 | (undecorated . t) ; Remove extraneous X decorations
1704 | (vertical-scroll-bars . nil)) ; No vertical scroll-bars
1705 |
1706 | user-full-name "Sandeep Nambiar" ; ME!
1707 |
1708 | ;; memory configuration
1709 | ;; Higher garbage collection threshold, prevents frequent gc locks
1710 | gc-cons-threshold most-positive-fixnum
1711 | ;; Ignore warnings for (obsolete) elisp compilations
1712 | byte-compile-warnings '(not obsolete)
1713 | ;; And other log types completely
1714 | warning-suppress-log-types '((comp) (bytecomp))
1715 | ;; Large files are okay in the new millenium.
1716 | large-file-warning-threshold 100000000
1717 |
1718 | ;; Read more based on system pipe capacity
1719 | read-process-output-max (max (* 10240 10240) read-process-output-max)
1720 |
1721 | ;; scroll configuration
1722 | scroll-margin 0 ; Lets scroll to the end of the margin
1723 | scroll-conservatively 100000 ; Never recenter the window
1724 | scroll-preserve-screen-position 1 ; Scrolling back and forth
1725 |
1726 | ;; frame config
1727 | ;; Improve emacs startup time by not resizing to adjust for custom settings
1728 | frame-inhibit-implied-resize t
1729 | ;; Dont resize based on character height / width but to exact pixels
1730 | frame-resize-pixelwise t
1731 |
1732 | ;; backups & files
1733 | backup-directory-alist '(("." . "~/.backups/")) ; Don't clutter
1734 | backup-by-copying t ; Don't clobber symlinks
1735 | create-lockfiles nil ; Don't have temp files
1736 | delete-old-versions t ; Cleanup automatically
1737 | kept-new-versions 6 ; Update every few times
1738 | kept-old-versions 2 ; And cleanup even more
1739 | version-control t ; Version them backups
1740 | delete-by-moving-to-trash t ; Dont delete, send to trash instead
1741 |
1742 | ;; startup
1743 | inhibit-startup-screen t ; I have already done the tutorial. Twice
1744 | inhibit-startup-message t ; I know I am ready
1745 | inhibit-startup-echo-area-message t ; Yep, still know it
1746 | initial-scratch-message nil ; I know it is the scratch buffer!
1747 |
1748 | ;; tabs
1749 | tab-width 4 ; Always tab 4 spaces.
1750 | indent-tabs-mode nil ; Never use actual tabs.
1751 |
1752 | ;; rendering
1753 | cursor-in-non-selected-windows nil ; dont render cursors other windows
1754 |
1755 | ;; packages
1756 | use-package-always-defer t
1757 |
1758 | ;; custom
1759 | custom-file (concat user-emacs-directory "custom.el")
1760 |
1761 | load-prefer-newer t
1762 |
1763 | default-input-method nil
1764 | )
1765 | ;;; early-init.el ends here
1766 | #+end_src
1767 |
1768 | ** Initialization
1769 | Now starts the main emacs configuration.
1770 |
1771 | #+begin_src emacs-lisp :tangle home/emacs/init.el :mkdirp yes
1772 | ;;; package --- Summary - My minimal Emacs init file -*- lexical-binding: t -*-
1773 |
1774 | ;;; Commentary:
1775 | ;;; Simple Emacs setup I carry everywhere
1776 |
1777 | ;;; Code:
1778 | (load custom-file 'noerror) ;; no error on missing custom file
1779 |
1780 | (require 'package)
1781 | (add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/") t)
1782 | (add-to-list 'package-archives '("nongnu" . "https://elpa.nongnu.org/nongnu/") t)
1783 | (package-initialize)
1784 |
1785 | (use-package emacs
1786 | :init
1787 | (global-auto-revert-mode t) ;; revert automatically on external file changes
1788 | (savehist-mode) ;; save minibuffer history
1789 |
1790 | ;; base visual
1791 | (menu-bar-mode -1) ;; no menu bar
1792 | (toggle-scroll-bar -1) ;; no scroll bar
1793 | (tool-bar-mode -1) ;; no tool bar either
1794 | (global-hl-line-mode +1) ;; always highlight current line
1795 | (blink-cursor-mode -1) ;; stop blinking
1796 | (global-display-line-numbers-mode 1) ;; always show line numbers
1797 | (column-number-mode t) ;; column number in the mode line
1798 | (size-indication-mode t) ;; file size in the mode line
1799 | (pixel-scroll-precision-mode) ;; smooth mouse scroll
1800 | (fset 'yes-or-no-p 'y-or-n-p) ;; y/n is good enough
1801 | (electric-pair-mode) ;; i mean ... parens should auto create
1802 | (recentf-mode) ;; keep track of recently opened files
1803 |
1804 | ;; font of the century
1805 | (set-frame-font "Iosevka Nerd Font 12" nil t)
1806 |
1807 | :bind
1808 | (("C-" . pixel-scroll-precision) ; dont zoom in please, just scroll
1809 | ("C-" . pixel-scroll-precision) ; dont zoom in either, just scroll
1810 | ("C-x k" . kill-current-buffer)) ; kill the buffer, dont ask
1811 | )
1812 |
1813 | (use-package nerd-icons
1814 | :custom
1815 | ;; disable bright icon colors
1816 | (nerd-icons-color-icons nil))
1817 |
1818 | (use-package doom-modeline
1819 | :custom
1820 | (inhibit-compacting-font-caches t) ;; speed
1821 | (doom-modeline-buffer-file-name-style 'relative-from-project)
1822 | (doom-modeline-major-mode-icon nil) ;; distracting icons, no thank you
1823 | (doom-modeline-buffer-encoding nil) ;; everything is utf-8 anyway
1824 | (doom-modeline-buffer-state-icon nil) ;; the filename already shows me
1825 | (doom-modeline-lsp nil) ;; lsp state is too distracting, too often
1826 | :hook (after-init . doom-modeline-mode))
1827 |
1828 | (use-package doom-themes
1829 | :commands doom-themes-visual-bell-config
1830 | :custom
1831 | (doom-themes-enable-bold t)
1832 | (doom-themes-enable-italic t)
1833 | :init
1834 | (load-theme 'doom-nord t)
1835 | (doom-themes-visual-bell-config))
1836 |
1837 | (use-package diminish :demand t) ;; declutter the modeline
1838 | (use-package eldoc :diminish eldoc-mode) ;; docs for everything
1839 |
1840 | (use-package whitespace-cleanup-mode
1841 | :commands global-whitespace-cleanup-mode
1842 | :custom
1843 | (whitespace-cleanup-mode-only-if-initially-clean nil)
1844 | :hook
1845 | (after-init . global-whitespace-cleanup-mode))
1846 |
1847 | (use-package pulsar
1848 | :commands pulsar-global-mode pulsar-recenter-top pulsar-reveal-entry
1849 | :init
1850 | (defface pulsar-nord
1851 | '((default :extend t)
1852 | (((class color) (min-colors 88) (background light))
1853 | :background "#2e3440")
1854 | (((class color) (min-colors 88) (background dark))
1855 | :background "#81a1c1")
1856 | (t :inverse-video t))
1857 | "Alternative nord face for `pulsar-face'."
1858 | :group 'pulsar-faces)
1859 | :custom
1860 | (pulsar-face 'pulsar-nord)
1861 | :hook
1862 | (after-init . pulsar-global-mode))
1863 |
1864 | (use-package which-key
1865 | :commands which-key-mode
1866 | :diminish which-key-mode
1867 | :hook
1868 | (after-init . which-key-mode))
1869 |
1870 | (use-package expreg
1871 | :bind ("M-m" . expreg-expand))
1872 |
1873 | (use-package vundo) ;; undo tree
1874 |
1875 | ;; better structured editing
1876 | (use-package puni
1877 | :commands puni-global-mode
1878 | :hook
1879 | (after-init . puni-global-mode))
1880 |
1881 | (use-package avy
1882 | :bind
1883 | ("M-i" . avy-goto-char-2)
1884 | :custom
1885 | (avy-background t))
1886 |
1887 | (use-package consult
1888 | :bind
1889 | ("C-x b" . consult-buffer) ;; orig. switch-to-buffer
1890 | ("M-y" . consult-yank-pop) ;; orig. yank-pop
1891 | ("M-g M-g" . consult-goto-line) ;; orig. goto-line
1892 | :custom
1893 | (consult-narrow-key "<"))
1894 |
1895 | (use-package vertico
1896 | :commands vertico-mode
1897 | :custom
1898 | (read-file-name-completion-ignore-case t)
1899 | (read-buffer-completion-ignore-case t)
1900 | (completion-ignore-case t)
1901 | (enable-recursive-minibuffers t)
1902 | :init
1903 | (vertico-mode)
1904 | :config
1905 | (setq minibuffer-prompt-properties
1906 | '(read-only t cursor-intangible t face minibuffer-prompt))
1907 | :hook
1908 | (minibuffer-setup-hook . cursor-intangible-mode))
1909 |
1910 | (use-package marginalia
1911 | :commands marginalia-mode
1912 | :hook (after-init . marginalia-mode))
1913 |
1914 | (use-package crux
1915 | :bind
1916 | ("C-c M-e" . crux-find-user-init-file)
1917 | ("C-c C-w" . crux-transpose-windows)
1918 | ("C-a" . crux-move-beginning-of-line))
1919 |
1920 | (use-package magit
1921 | :bind (("C-M-g" . magit-status)))
1922 |
1923 | (use-package nerd-icons-corfu
1924 | :commands nerd-icons-corfu-formatter
1925 | :defines corfu-margin-formatters)
1926 |
1927 | (use-package corfu
1928 | :commands global-corfu-mode
1929 | :custom
1930 | (corfu-cycle t)
1931 | (corfu-auto t)
1932 | (corfu-auto-delay 1)
1933 | (corfu-auto-prefix 3)
1934 | (corfu-separator ?_)
1935 | :hook
1936 | (after-init . global-corfu-mode)
1937 | :config
1938 | (add-to-list 'corfu-margin-formatters #'nerd-icons-corfu-formatter))
1939 |
1940 | (use-package cape)
1941 |
1942 | (use-package orderless
1943 | :custom
1944 | (completion-styles '(orderless partial-completion basic))
1945 | (completion-category-defaults nil)
1946 | (completion-category-overrides nil))
1947 |
1948 | (use-package yasnippet
1949 | :commands yas-global-mode
1950 | :diminish yas-minor-mode
1951 | :hook
1952 | (after-init . yas-global-mode))
1953 |
1954 | (use-package yasnippet-snippets :after yasnippet)
1955 |
1956 | (use-package projectile
1957 | :commands projectile-mode
1958 | :diminish projectile-mode
1959 | :custom
1960 | (projectile-globally-ignored-directories (append '("node_modules")))
1961 | :bind-keymap ("C-c p" . projectile-command-map)
1962 | :config
1963 | (projectile-mode +1))
1964 |
1965 | (use-package exec-path-from-shell
1966 | :commands exec-path-from-shell-initialize
1967 | :custom
1968 | (exec-path-from-shell-arguments nil)
1969 | :hook
1970 | (after-init . exec-path-from-shell-initialize))
1971 |
1972 | (use-package flycheck
1973 | :commands global-flycheck-mode
1974 | :diminish
1975 | :hook
1976 | (after-init . global-flycheck-mode))
1977 |
1978 | (use-package lsp-mode
1979 | :commands (lsp lsp-deferred lsp-format-buffer
1980 | lsp-organize-imports
1981 | orderless-dispatch-flex-first
1982 | cape-capf-buster lsp-completion-at-point)
1983 | :defines lsp-file-watch-ignored-directories
1984 | :diminish lsp-lens-mode
1985 | :bind-keymap
1986 | ("C-c l" . lsp-command-map)
1987 | :custom
1988 | (lsp-lens-enable nil)
1989 | (lsp-idle-delay 0.500)
1990 | (lsp-modeline-code-actions-enable t)
1991 | (lsp-modeline-diagnostics-enable t)
1992 | (lsp-csharp-omnisharp-roslyn-binary-path "OmniSharp")
1993 | (lsp-completion-provider :none) ;; we use Corfu!
1994 | (lsp-eldoc-render-all t)
1995 | :init
1996 | (defun orderless-dispatch-flex-first (_pattern index _total)
1997 | (and (eq index 0) 'orderless-flex))
1998 |
1999 | ;; Configure the first word as flex filtered.
2000 | (add-hook 'orderless-style-dispatchers #'orderless-dispatch-flex-first nil 'local)
2001 |
2002 | (defun lsp-mode-setup-completion ()
2003 | (setf (alist-get 'styles (alist-get 'lsp-capf completion-category-defaults))
2004 | '(orderless)))
2005 |
2006 | ;; Optionally configure the cape-capf-buster.
2007 | (setq-local completion-at-point-functions
2008 | (list (cape-capf-buster #'lsp-completion-at-point)))
2009 | :config
2010 | (add-to-list 'lsp-file-watch-ignored-directories "[/\\\\]\\Temp\\'")
2011 | (add-to-list 'lsp-file-watch-ignored-directories "[/\\\\]\\Logs\\'")
2012 | (defun lsp-cleanup ()
2013 | (lsp-format-buffer)
2014 | (lsp-organize-imports)
2015 | (whitespace-cleanup))
2016 | :hook
2017 | (lsp-completion-mode . lsp-mode-setup-completion)
2018 | (lsp-mode . lsp-enable-which-key-integration)
2019 | (before-save . lsp-cleanup)
2020 | (prog-mode . lsp-deferred))
2021 |
2022 | (use-package lsp-ui :commands lsp-ui-mode
2023 | :custom
2024 | (lsp-ui-doc-enable t)
2025 | (lsp-ui-sideline-diagnostic-max-lines 4)
2026 | (lsp-ui-doc-show-with-mouse nil)
2027 | (lsp-ui-doc-position 'bottom)
2028 | (lsp-ui-doc-show-with-cursor t)
2029 | (lsp-eldoc-enable-hover nil)
2030 | )
2031 |
2032 | (use-package nixpkgs-fmt
2033 | :custom
2034 | (nixpkgs-fmt-command "nixfmt"))
2035 |
2036 | (use-package rust-mode
2037 | :custom
2038 | (rust-mode-treesitter-derive t)
2039 | (lsp-rust-analyzer-cargo-watch-command "clippy")
2040 | (lsp-rust-analyzer-exclude-dirs ["Temp/**"]))
2041 |
2042 | (use-package typescript-ts-mode
2043 | :custom
2044 | (lsp-javascript-preferences-import-module-specifier :relative)
2045 | (typescript-indent-level 2)
2046 | (typescript-ts-mode-indent-offset 2))
2047 |
2048 | (use-package eat)
2049 | (use-package hcl-mode)
2050 | (use-package jinja2-mode)
2051 | (use-package f :demand t)
2052 |
2053 | (use-package envrc
2054 | :commands envrc-global-mode
2055 | :hook
2056 | (after-init . envrc-global-mode))
2057 |
2058 | (use-package nix-mode
2059 | :hook (nix-mode . lsp-deferred))
2060 |
2061 | (use-package shell-pop
2062 | :custom
2063 | (shell-pop-universal-key "M-o"))
2064 |
2065 | (use-package copilot
2066 | :defines copilot-completion-map
2067 | :bind
2068 | (:map copilot-completion-map
2069 | ("" . copilot-accept-completion)
2070 | ("M-n" . copilot-next-completion)
2071 | ("M-p" . copilot-previous-completion)
2072 | ("C-g" . copilot-clear-overlay)))
2073 |
2074 | (use-package gptel
2075 | :commands gptel-make-anthropic f-read-text
2076 | :config
2077 | (gptel-make-anthropic "Claude"
2078 | :stream t :key (f-read-text "/run/secrets/claude_key")))
2079 |
2080 | (provide 'init)
2081 |
2082 | ;;; init.el ends here
2083 | #+end_src
2084 |
2085 | * Machines
2086 | Only a few more things left. Specifically the machine level extra settings.
2087 | ** Smallbox
2088 | The configuration for the laptop does not change much. Most changes are because the hardware is different.
2089 | *** System Level
2090 | Nothing specific for the laptop.
2091 |
2092 | #+begin_src nix :tangle machines/smallbox/configuration.nix :noweb tangle :mkdirp yes
2093 | { user, ... } : {
2094 | imports =
2095 | [
2096 | ./hardware-configuration.nix
2097 | ../../configuration
2098 | ];
2099 |
2100 | <>
2101 | }
2102 | #+end_src
2103 |
2104 | *** Hardware
2105 | This is the most different. Mostly taken from hardware-configuration.nix setup at first install.
2106 | As you might notice, there are a lot more kernel modules. This device has thunderbolt for example.
2107 |
2108 | #+begin_src nix :tangle machines/smallbox/hardware-configuration.nix :noweb tangle :mkdirp yes
2109 | {
2110 | hostname,
2111 | pkgs,
2112 | lib,
2113 | modulesPath,
2114 | user,
2115 | ...
2116 | }:
2117 | {
2118 | imports = [
2119 | (modulesPath + "/installer/scan/not-detected.nix")
2120 | ../../hardware/hardware.nix
2121 | ];
2122 |
2123 | boot.initrd.availableKernelModules = [
2124 | "xhci_pci" # usb wake up (usb host controller)
2125 | "thunderbolt" # :/
2126 | "nvme" # support for the nvme disk in here
2127 | "usb_storage" # :/
2128 | "sd_mod" # hard drive controller
2129 | ];
2130 |
2131 | boot.kernelParams = [ "amd_pstate=active"
2132 | "acpi.ec_no_wakeup=1"
2133 | # Force use of the thinkpad_acpi driver for backlight control.
2134 | # This allows the backlight save/load systemd service to work.
2135 | "acpi_backlight=native"
2136 | # Needed for touchpad to work properly (click doesn't register by pushing down the touchpad).
2137 | "psmouse.synaptics_intertouch=0"
2138 | ];
2139 | boot.kernelModules = [ "kvm-amd" ];
2140 | boot.loader.grub.efiSupport = true;
2141 | boot.loader.grub.useOSProber = true; # detect windows since thats on a partition here
2142 | boot.loader.grub.devices = [ "/dev/nvme0n1" ];
2143 |
2144 | fileSystems."/" = {
2145 | device = "/dev/disk/by-uuid/0bda9355-76f4-4b55-9012-0a14a73ac6b9";
2146 | fsType = "ext4";
2147 | };
2148 |
2149 | boot.initrd.luks.devices."luks-f400c0ed-57e0-4b5a-b701-c1a10c19480f".device = "/dev/disk/by-uuid/f400c0ed-57e0-4b5a-b701-c1a10c19480f";
2150 |
2151 | fileSystems."/boot" = {
2152 | device = "/dev/disk/by-uuid/5A5A-DEFE";
2153 | fsType = "vfat";
2154 | options = [ "fmask=0077" "dmask=0077" ];
2155 | };
2156 |
2157 | # external disk
2158 | fileSystems."/home/${user.username}/external" = {
2159 | device = "/dev/disk/by-uuid/18818348-1ee4-4fa5-9984-e4e01b9fa304";
2160 | fsType = "ext4";
2161 | };
2162 |
2163 | swapDevices = [];
2164 |
2165 | hardware.graphics = {
2166 | enable = lib.mkDefault true;
2167 | enable32Bit = lib.mkDefault true;
2168 | };
2169 |
2170 | hardware.amdgpu.initrd.enable = lib.mkDefault true;
2171 | networking.hostName = hostname;
2172 |
2173 | # enalbe fingerprinting services
2174 | services.fprintd.enable = true;
2175 | }
2176 | #+end_src
2177 |
2178 | *** Home
2179 | This is mostly about configuring the monitor and key bindings. And laptop specific utilities.
2180 | #+begin_src nix :tangle machines/smallbox/home.nix :noweb tangle :mkdirp yes
2181 | { pkgs, ... } : {
2182 | imports = [
2183 | ../../home
2184 | ];
2185 |
2186 | home.packages = with pkgs; [
2187 | brightnessctl
2188 | ];
2189 |
2190 | wayland.windowManager.hyprland.settings = {
2191 | bind = [
2192 | ", XF86MonBrightnessUp, exec, brightnessctl set 5%+"
2193 | ", XF86MonBrightnessDown, exec, brightnessctl set 5%-"
2194 | ", XF86AudioRaiseVolume, exec, wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%+"
2195 | ", XF86AudioLowerVolume, exec, wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%-"
2196 | ", XF86AudioMute, exec, wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle"
2197 | ", XF86AudioMicMute, exec, wpctl set-mute @DEFAULT_AUDIO_SOURCE@ toggle"
2198 | ];
2199 |
2200 | bindl = [
2201 | '', switch:on:Lid Switch, exec, hyprctl keyword monitor "eDP-1, disable"''
2202 | '', switch:off:Lid Switch, exec, hyprctl keyword monitor "eDP-1, preferred, 2560x0, 2"''
2203 | ];
2204 |
2205 | monitor = [
2206 | "desc:AOC Q3279WG5B 0x00000161, preferred, 0x0, 1, vrr, 2" # main monitor
2207 | "eDP-1, preferred, 2560x0, 2" # laptop monitor
2208 | ];
2209 |
2210 | workspace = [
2211 | "1,monitor:desc:AOC Q3279WG5B 0x00000161, default:true"
2212 | "2,monitor:desc:AOC Q3279WG5B 0x00000161, default:true"
2213 | "3,monitor:desc:AOC Q3279WG5B 0x00000161, default:true"
2214 | "5,monitor:eDP-1, default:true"
2215 | "6,monitor:eDP-1, default:tru"e
2216 | ];
2217 |
2218 | windowrule = [
2219 | "workspace:1, class:firefox"
2220 | "workspace:2, class:emacs"
2221 | "workspace:5, class:Slack"
2222 | ];
2223 |
2224 | exec-once = [
2225 | "[workspace 1 silent] firefox"
2226 | "[workspace 2 silent] emacs"
2227 | "[workspace 5 silent] slack"
2228 | ];
2229 | };
2230 | }
2231 | #+end_src
2232 |
2233 | *** Secrets
2234 | #+name: smallbox-secrets
2235 | #+begin_src nix
2236 | sops.secrets."ssh/smallbox/private" = { # ssh private key
2237 | owner = "${user.username}";
2238 | mode = "600";
2239 | path = "/home/${user.username}/.ssh/id_ed25519";
2240 | };
2241 | sops.secrets."ssh/smallbox/public" = { # ssh public key
2242 | owner = "${user.username}";
2243 | mode = "644";
2244 | path = "/home/${user.username}/.ssh/id_ed25519.pub";
2245 | };
2246 | sops.secrets."ssh/wavefunk/private" = { # ssh private key
2247 | owner = "${user.username}";
2248 | mode = "600";
2249 | path = "/home/${user.username}/.ssh/wavefunk";
2250 | };
2251 | sops.secrets."ssh/wavefunk/public" = { # ssh public key
2252 | owner = "${user.username}";
2253 | mode = "644";
2254 | path = "/home/${user.username}/.ssh/wavefunk.pub";
2255 | };
2256 | sops.secrets."ssh/wavefunk_dev/private" = { # ssh private key
2257 | owner = "${user.username}";
2258 | mode = "600";
2259 | path = "/home/${user.username}/.ssh/wavefunk_dev";
2260 | };
2261 | sops.secrets."ssh/wavefunk_dev/public" = { # ssh public key
2262 | owner = "${user.username}";
2263 | mode = "644";
2264 | path = "/home/${user.username}/.ssh/wavefunk_dev.pub";
2265 | };
2266 | #+end_src
2267 | * README Utils
2268 | *** Headers
2269 | This script adds a =DO NOT MODIFY= header to all the generated nix files.
2270 | #+NAME: startup
2271 | #+BEGIN_SRC emacs-lisp
2272 | (progn
2273 | (defun add-tangle-headers ()
2274 | (message "running in %s" (buffer-file-name))
2275 | (when (string= (file-name-extension (buffer-file-name)) "nix")
2276 | (goto-char (point-min))
2277 | (insert "# WARNING : This file was generated by README.org\n# DO NOT MODIFY THIS FILE!\n# Any changes made here will be overwritten.\n")
2278 | (save-buffer))
2279 | (save-buffer))
2280 | (add-hook 'org-babel-post-tangle-hook 'add-tangle-headers))
2281 | #+END_SRC
2282 |
2283 | # Local Variables:
2284 | # org-confirm-babel-evaluate: nil
2285 | # eval: (progn (org-babel-goto-named-src-block "startup") (org-babel-execute-src-block) (outline-hide-sublevels 1))
2286 | # End:
2287 |
--------------------------------------------------------------------------------
/assets/background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gamedolphin/system/5091b6df059a46fa1ce3d8791add589404281375/assets/background.png
--------------------------------------------------------------------------------
/assets/lock.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gamedolphin/system/5091b6df059a46fa1ce3d8791add589404281375/assets/lock.png
--------------------------------------------------------------------------------
/assets/me.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gamedolphin/system/5091b6df059a46fa1ce3d8791add589404281375/assets/me.jpg
--------------------------------------------------------------------------------
/configuration/audio.nix:
--------------------------------------------------------------------------------
1 | # WARNING : This file was generated by README.org
2 | # DO NOT MODIFY THIS FILE!
3 | # Any changes made here will be overwritten.
4 | { pkgs, ...}:
5 | {
6 | environment.systemPackages = with pkgs; [
7 | pamixer
8 | ];
9 | services.pipewire = {
10 | enable = true;
11 | alsa.enable = true;
12 | alsa.support32Bit = true;
13 | pulse.enable = true;
14 | jack.enable = true;
15 | };
16 |
17 | # pipewire needs realtime scheduling access
18 | security.rtkit.enable = true;
19 | }
20 |
--------------------------------------------------------------------------------
/configuration/boot.nix:
--------------------------------------------------------------------------------
1 | # WARNING : This file was generated by README.org
2 | # DO NOT MODIFY THIS FILE!
3 | # Any changes made here will be overwritten.
4 | { pkgs, ... } :
5 | {
6 | boot = {
7 | initrd = {
8 | verbose = false; # its a lot of logs. dont need it, unless we do.
9 | kernelModules = [ ]; # no kernel modules on boot
10 | };
11 |
12 | extraModulePackages = [ ]; # no extra packages on boot either
13 | kernelPackages = pkgs.linuxPackages_latest; # latest greatest linux kernel
14 | kernelParams = [ "silent" ]; # quiet those logs
15 |
16 | consoleLogLevel = 0; # quiten more logs
17 | plymouth.enable = true; # graphical boot animation instead
18 |
19 | supportedFilesystems = [ "ntfs" ]; # should see the ntfs (windows)
20 |
21 | loader = {
22 | systemd-boot.enable = true; # systemd-boot
23 | efi.canTouchEfiVariables = true; # allow editing efi to edit the boot loader
24 |
25 | grub = {
26 | # this keeps old versions of my applied configurations
27 | # 50 is high, but i have disk space
28 | configurationLimit = 50;
29 | };
30 |
31 | timeout = 5; # grub timeout to make a selection
32 | };
33 | };
34 | }
35 |
--------------------------------------------------------------------------------
/configuration/cli.nix:
--------------------------------------------------------------------------------
1 | # WARNING : This file was generated by README.org
2 | # DO NOT MODIFY THIS FILE!
3 | # Any changes made here will be overwritten.
4 | { pkgs, user, ... }:
5 | {
6 | console.useXkbConfig = true;
7 | users.users.${user.username}.shell = pkgs.zsh;
8 |
9 | environment.shells = with pkgs; [ zsh ];
10 | programs.zsh.enable = true;
11 | }
12 |
--------------------------------------------------------------------------------
/configuration/default.nix:
--------------------------------------------------------------------------------
1 | # WARNING : This file was generated by README.org
2 | # DO NOT MODIFY THIS FILE!
3 | # Any changes made here will be overwritten.
4 | { pkgs, user, ... } :
5 | {
6 | imports = [
7 | ./boot.nix
8 | ./login.nix
9 | ./cli.nix
10 | ./files.nix
11 | ./locale.nix
12 | ./nix-settings.nix
13 | ./networking.nix
14 | ./hyprland.nix
15 | ./services.nix
16 | ./audio.nix
17 | ./steam.nix
18 | ./sops.nix
19 | ];
20 |
21 | environment.systemPackages = with pkgs; [
22 | wget # fetch utility
23 | curl # more fetch utility
24 | binutils # executable utilities, like ld
25 | dmidecode # tool for dumping system info
26 | libnotify # notification daemon
27 | python3 # nice to have this ready for quick things
28 | cacert # certificate authority
29 | remmina # remote desktop app
30 | ];
31 |
32 | users.users.${user.username} = {
33 | isNormalUser = true;
34 | description = "Sandeep Nambiar";
35 | extraGroups = [
36 | "networkmanager" # allow editing network connections
37 | "wheel" # can do sudo
38 | "scanner" # access to the network scanner
39 | "lp" # access to the printer
40 | ];
41 | };
42 |
43 | programs = {
44 | nix-ld.enable = true; # helps with linking troubles with dynamic libraries
45 | appimage.enable = true; # allow appimage installations
46 | dconf.enable = true; # to save user settings
47 | gnupg.agent = {
48 | # pgp client
49 | enable = true;
50 | enableSSHSupport = true;
51 | };
52 | firefox.enable = true; # browser
53 | wireshark.enable = true; # vpn
54 | };
55 |
56 | fonts.packages = with pkgs; [
57 | iosevka
58 | nerd-fonts.iosevka
59 | ];
60 |
61 | system.stateVersion = user.stateVersion;
62 | }
63 |
--------------------------------------------------------------------------------
/configuration/files.nix:
--------------------------------------------------------------------------------
1 | # WARNING : This file was generated by README.org
2 | # DO NOT MODIFY THIS FILE!
3 | # Any changes made here will be overwritten.
4 | { pkgs, ... } :
5 | {
6 | environment.systemPackages = with pkgs; [
7 | zip
8 | unzip
9 | p7zip
10 | usbutils
11 | udiskie
12 | ];
13 |
14 | programs.thunar = {
15 | enable = true;
16 | plugins = with pkgs.xfce; [
17 | thunar-archive-plugin
18 | thunar-media-tags-plugin
19 | thunar-volman
20 | ];
21 | };
22 |
23 | programs.file-roller.enable = true; # thunar zip support
24 | programs.xfconf.enable = true; # to save thunar settings
25 |
26 | services = {
27 | gvfs.enable = true; # Mount, trash, and other functionalities
28 | tumbler.enable = true; # Thumbnail support for images
29 | udisks2.enable = true; # Auto mount usb drives
30 | };
31 | }
32 |
--------------------------------------------------------------------------------
/configuration/hyprland.nix:
--------------------------------------------------------------------------------
1 | # WARNING : This file was generated by README.org
2 | # DO NOT MODIFY THIS FILE!
3 | # Any changes made here will be overwritten.
4 | { pkgs, ... }:
5 | {
6 | nix.settings = {
7 | # add the hyprland cache so that we dont build hyprland from source
8 | substituters = [ "https://hyprland.cachix.org" ];
9 | trusted-public-keys = [
10 | "hyprland.cachix.org-1:a7pgxzMz7+chwVL3/pzj6jIBMioiJM7ypFP8PwtkuGc="
11 | ];
12 | };
13 |
14 | # these extra portals allow for things like screen sharing
15 | xdg = {
16 | portal = {
17 | enable = true;
18 | extraPortals = [
19 | pkgs.xdg-desktop-portal-wlr
20 | pkgs.xdg-desktop-portal-gtk
21 | ];
22 | };
23 | };
24 |
25 | environment.systemPackages = with pkgs; [
26 | hyprland # the actual package
27 | tofi # launcher
28 | uwsm # wayland session manager
29 | hyprland-qtutils # needed by hyprland
30 | hyprpolkitagent # polkit agent
31 | ];
32 |
33 | # we use uwsm to manage launching hyprland
34 | # uswm will add hyprland to the login sessions with greetd.
35 | programs = {
36 | uwsm.enable = true;
37 | uwsm.waylandCompositors = {
38 | hyprland = {
39 | prettyName = "Hyprland";
40 | comment = "Hyprland compositor managed by UWSM";
41 | binPath = "/run/current-system/sw/bin/Hyprland";
42 | };
43 | };
44 |
45 | hyprland = {
46 | withUWSM = true;
47 | enable = true;
48 | xwayland.enable = true;
49 | };
50 | };
51 |
52 | # this is mainly for the lock screen
53 | # lock.png is provided elsewhere
54 | services.xserver = {
55 | enable = true;
56 |
57 | desktopManager = {
58 | xterm.enable = false;
59 | };
60 |
61 |
62 | displayManager = {
63 | lightdm.background = ./lock.png;
64 | };
65 | };
66 |
67 | # this is a lot of env vars.
68 | # and this requires some cleanup
69 | # but hyprland moves fast and some of these are probably outdated already
70 | environment.sessionVariables = {
71 | XDG_SESSION_TYPE="wayland";
72 | XDG_CURRENT_DESKTOP="Hyprland";
73 | XDG_SESSION_DESKTOP="Hyprland";
74 | NIXOS_OZONE_WL="1";
75 | GTK_THEME="Nordic";
76 | XCURSOR_THEME="Nordzy-cursors";
77 | XCURSOR_SIZE="24";
78 | HYPRCURSOR_THEME="Nordzy-cursors";
79 | HYPRCURSOR_SIZE="24";
80 | };
81 |
82 | # allow hyprlock (lockscreen) to lock user session
83 | security.pam.services.hyprlock = { };
84 | security.polkit.enable = true;
85 | security.pam.services.gdm.enableGnomeKeyring = true;
86 | }
87 |
--------------------------------------------------------------------------------
/configuration/locale.nix:
--------------------------------------------------------------------------------
1 | # WARNING : This file was generated by README.org
2 | # DO NOT MODIFY THIS FILE!
3 | # Any changes made here will be overwritten.
4 | { user, ... } :
5 | let
6 | locale = user.locale;
7 | in
8 | {
9 | # Set your time zone.
10 | time.timeZone = "Europe/Stockholm";
11 |
12 | # Select internationalisation properties.
13 | i18n.defaultLocale = "en_US.UTF-8";
14 |
15 | i18n.extraLocaleSettings = {
16 | LC_ADDRESS = locale;
17 | LC_IDENTIFICATION = locale;
18 | LC_MEASUREMENT = locale;
19 | LC_MONETARY = locale;
20 | LC_NAME = locale;
21 | LC_NUMERIC = locale;
22 | LC_PAPER = locale;
23 | LC_TELEPHONE = locale;
24 | LC_TIME = locale;
25 | };
26 | }
27 |
--------------------------------------------------------------------------------
/configuration/login.nix:
--------------------------------------------------------------------------------
1 | # WARNING : This file was generated by README.org
2 | # DO NOT MODIFY THIS FILE!
3 | # Any changes made here will be overwritten.
4 | { pkgs, user, ... } :
5 | {
6 | environment.systemPackages = with pkgs; [
7 | greetd.tuigreet
8 | ];
9 |
10 | services.greetd = {
11 | enable = true;
12 | settings = {
13 | default_session = {
14 | command = pkgs.lib.mkForce "${pkgs.greetd.tuigreet}/bin/tuigreet --remember --time --time-format '%I:%M %p | %a • %h | %F'";
15 | };
16 | };
17 | };
18 | }
19 |
--------------------------------------------------------------------------------
/configuration/networking.nix:
--------------------------------------------------------------------------------
1 | # WARNING : This file was generated by README.org
2 | # DO NOT MODIFY THIS FILE!
3 | # Any changes made here will be overwritten.
4 | {
5 | networking = {
6 | networkmanager.enable = true;
7 | firewall.enable = true;
8 | };
9 | }
10 |
--------------------------------------------------------------------------------
/configuration/nix-settings.nix:
--------------------------------------------------------------------------------
1 | # WARNING : This file was generated by README.org
2 | # DO NOT MODIFY THIS FILE!
3 | # Any changes made here will be overwritten.
4 | { pkgs, user, ... } :
5 | {
6 | nix.settings = {
7 | # enable flakes
8 | experimental-features = ["nix-command" "flakes"];
9 |
10 | # add a cache that speed up new applications by downloading binaries
11 | # from the trusted cache instead of compiling from source
12 | substituters = [ "https://nix-community.cachix.org" ];
13 | # trust the cache public key
14 | trusted-public-keys = [
15 | "nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs="
16 | ];
17 | };
18 |
19 | # allow proprietary software on this machine. I'm not a purist.
20 | nixpkgs.config.allowUnfree = true;
21 |
22 | # this declares how often old configurations are cleared up.
23 | # i cleanup anything older than a week, every week.
24 | nix.gc = {
25 | automatic = true;
26 | options = "--delete-older-than 7d";
27 | dates = "weekly";
28 | };
29 |
30 | programs = {
31 | # command line utility that makes applying changes easy and pretty
32 | nh = {
33 | enable = true;
34 | flake = "/home/${user.username}/system";
35 | };
36 | };
37 | }
38 |
--------------------------------------------------------------------------------
/configuration/services.nix:
--------------------------------------------------------------------------------
1 | # WARNING : This file was generated by README.org
2 | # DO NOT MODIFY THIS FILE!
3 | # Any changes made here will be overwritten.
4 | { user, ...} :
5 | {
6 | services = {
7 | blueman.enable = true; # bluetooth manager
8 | fwupd.enable = true; # firmware updating service
9 | fstrim.enable = true; # ssd maintenance service
10 | thermald.enable = true; # thermal regulation service
11 | printing.enable = true; # printing services, cups
12 | gnome.gnome-keyring.enable = true; # keyring
13 | flatpak.enable = true; # allow installing things from flatpaks
14 |
15 | # printer discovery
16 | avahi = {
17 | enable = true;
18 | nssmdns4 = true;
19 | openFirewall = true;
20 | };
21 |
22 | # syncthing
23 | syncthing = {
24 | enable = true;
25 | openDefaultPorts = true;
26 | user = "${user.username}";
27 | configDir = "/home/${user.username}/.conifg/syncthing";
28 | settings = {
29 | devices = {
30 | "phone" = { id = "AC6CP4C-TBXMOU5-DSLTDSJ-B2ZJ65D-EXILKVV-U4QEDVA-AIAJZNJ-MX2RHQP"; };
31 | };
32 |
33 | folders = {
34 | "OrgSync" = {
35 | path = "/home/${user.username}/org";
36 | devices = [ "phone" ];
37 | ignorePerms = true;
38 | };
39 | };
40 | };
41 | };
42 | };
43 |
44 | systemd.services.syncthing.environment.STNODEFAULTFOLDER = "true"; # Don't create default ~/Sync folder
45 |
46 | virtualisation.docker.enable = true; # enable docker
47 | users.users.${user.username}.extraGroups = [ "docker" ];
48 | }
49 |
--------------------------------------------------------------------------------
/configuration/sops.nix:
--------------------------------------------------------------------------------
1 | # WARNING : This file was generated by README.org
2 | # DO NOT MODIFY THIS FILE!
3 | # Any changes made here will be overwritten.
4 | { user, ...} :
5 | {
6 | sops.defaultSopsFile = ../secrets/secrets.yaml;
7 | sops.defaultSopsFormat = "yaml";
8 | sops.age.keyFile = "/home/${user.username}/.config/sops/age/keys.txt";
9 |
10 | sops.secrets.claude_key = { # anthropic claude api key, used in emacs
11 | owner = "${user.username}";
12 | };
13 | }
14 |
--------------------------------------------------------------------------------
/configuration/steam.nix:
--------------------------------------------------------------------------------
1 | # WARNING : This file was generated by README.org
2 | # DO NOT MODIFY THIS FILE!
3 | # Any changes made here will be overwritten.
4 | { pkgs, ... } :
5 | {
6 | environment.systemPackages = with pkgs; [
7 | steam-run # also used for random executables that expect fhs
8 | ];
9 |
10 | programs.steam = {
11 | enable = true;
12 | # Open ports in the firewall for Steam Remote Play
13 | remotePlay.openFirewall = true;
14 | # Open ports in the firewall for Source Dedicated Server
15 | dedicatedServer.openFirewall = true;
16 | };
17 | }
18 |
--------------------------------------------------------------------------------
/flake.lock:
--------------------------------------------------------------------------------
1 | {
2 | "nodes": {
3 | "emacs-overlay": {
4 | "inputs": {
5 | "nixpkgs": "nixpkgs",
6 | "nixpkgs-stable": "nixpkgs-stable"
7 | },
8 | "locked": {
9 | "lastModified": 1749201656,
10 | "narHash": "sha256-02cv0yMUlrCpA6El5itI/KmZLbGRSBfP3gf4PpIeTzA=",
11 | "owner": "nix-community",
12 | "repo": "emacs-overlay",
13 | "rev": "98f08847b3f1b9d0efc6ecffadce6311370e8306",
14 | "type": "github"
15 | },
16 | "original": {
17 | "owner": "nix-community",
18 | "repo": "emacs-overlay",
19 | "type": "github"
20 | }
21 | },
22 | "home-manager": {
23 | "inputs": {
24 | "nixpkgs": [
25 | "nixpkgs"
26 | ]
27 | },
28 | "locked": {
29 | "lastModified": 1749178927,
30 | "narHash": "sha256-bXcEx1aZUNm5hMLVJeuofcOrZyOiapzvQ7K36HYK3YQ=",
31 | "owner": "nix-community",
32 | "repo": "home-manager",
33 | "rev": "91287a0e9d42570754487b7e38c6697e15a9aab2",
34 | "type": "github"
35 | },
36 | "original": {
37 | "owner": "nix-community",
38 | "repo": "home-manager",
39 | "type": "github"
40 | }
41 | },
42 | "nixpkgs": {
43 | "locked": {
44 | "lastModified": 1748929857,
45 | "narHash": "sha256-lcZQ8RhsmhsK8u7LIFsJhsLh/pzR9yZ8yqpTzyGdj+Q=",
46 | "owner": "NixOS",
47 | "repo": "nixpkgs",
48 | "rev": "c2a03962b8e24e669fb37b7df10e7c79531ff1a4",
49 | "type": "github"
50 | },
51 | "original": {
52 | "owner": "NixOS",
53 | "ref": "nixos-unstable",
54 | "repo": "nixpkgs",
55 | "type": "github"
56 | }
57 | },
58 | "nixpkgs-stable": {
59 | "locked": {
60 | "lastModified": 1748995628,
61 | "narHash": "sha256-bFufQGSAEYQgjtc4wMrobS5HWN0hDP+ZX+zthYcml9U=",
62 | "owner": "NixOS",
63 | "repo": "nixpkgs",
64 | "rev": "8eb3b6a2366a7095939cd22f0dc0e9991313294b",
65 | "type": "github"
66 | },
67 | "original": {
68 | "owner": "NixOS",
69 | "ref": "nixos-24.11",
70 | "repo": "nixpkgs",
71 | "type": "github"
72 | }
73 | },
74 | "nixpkgs_2": {
75 | "locked": {
76 | "lastModified": 1749111037,
77 | "narHash": "sha256-V5fbB7XUPz8qtuJntul/7PABtP35tlmcYpriRvJ3EBw=",
78 | "owner": "nixos",
79 | "repo": "nixpkgs",
80 | "rev": "ec62ae342c340d24289735e31eb9155261cd5fe7",
81 | "type": "github"
82 | },
83 | "original": {
84 | "owner": "nixos",
85 | "ref": "nixpkgs-unstable",
86 | "repo": "nixpkgs",
87 | "type": "github"
88 | }
89 | },
90 | "nixpkgs_3": {
91 | "locked": {
92 | "lastModified": 1744868846,
93 | "narHash": "sha256-5RJTdUHDmj12Qsv7XOhuospjAjATNiTMElplWnJE9Hs=",
94 | "owner": "NixOS",
95 | "repo": "nixpkgs",
96 | "rev": "ebe4301cbd8f81c4f8d3244b3632338bbeb6d49c",
97 | "type": "github"
98 | },
99 | "original": {
100 | "owner": "NixOS",
101 | "ref": "nixpkgs-unstable",
102 | "repo": "nixpkgs",
103 | "type": "github"
104 | }
105 | },
106 | "root": {
107 | "inputs": {
108 | "emacs-overlay": "emacs-overlay",
109 | "home-manager": "home-manager",
110 | "nixpkgs": "nixpkgs_2",
111 | "sops-nix": "sops-nix"
112 | }
113 | },
114 | "sops-nix": {
115 | "inputs": {
116 | "nixpkgs": "nixpkgs_3"
117 | },
118 | "locked": {
119 | "lastModified": 1747603214,
120 | "narHash": "sha256-lAblXm0VwifYCJ/ILPXJwlz0qNY07DDYdLD+9H+Wc8o=",
121 | "owner": "Mic92",
122 | "repo": "sops-nix",
123 | "rev": "8d215e1c981be3aa37e47aeabd4e61bb069548fd",
124 | "type": "github"
125 | },
126 | "original": {
127 | "owner": "Mic92",
128 | "repo": "sops-nix",
129 | "type": "github"
130 | }
131 | }
132 | },
133 | "root": "root",
134 | "version": 7
135 | }
136 |
--------------------------------------------------------------------------------
/flake.nix:
--------------------------------------------------------------------------------
1 | # WARNING : This file was generated by README.org
2 | # DO NOT MODIFY THIS FILE!
3 | # Any changes made here will be overwritten.
4 | {
5 | description = "Sandeep's nixos configuration";
6 |
7 | inputs = {
8 | nixpkgs.url = "github:nixos/nixpkgs/nixpkgs-unstable";
9 |
10 | home-manager = {
11 | url = "github:nix-community/home-manager";
12 | inputs.nixpkgs.follows = "nixpkgs";
13 | };
14 |
15 | emacs-overlay.url = "github:nix-community/emacs-overlay";
16 |
17 | sops-nix.url = "github:Mic92/sops-nix";
18 | };
19 |
20 | outputs = {
21 | nixpkgs,
22 | home-manager,
23 | emacs-overlay,
24 | sops-nix,
25 | ...
26 | }:
27 | let
28 | user = import ./user.nix;
29 | lib = nixpkgs.lib;
30 | machines = [
31 | "smallbox"
32 | ];
33 | pkgs = import nixpkgs {
34 | inherit (user) system;
35 | };
36 | in
37 | {
38 | nixosConfigurations = builtins.listToAttrs (
39 | builtins.map (machine: {
40 | name = machine;
41 | value = lib.nixosSystem {
42 | modules = [
43 | ({ ... }: {
44 | nixpkgs.overlays = [ emacs-overlay.overlays.default ];
45 | })
46 | ./machines/${machine}/configuration.nix
47 | home-manager.nixosModules.home-manager
48 | {
49 | home-manager.useGlobalPkgs = true;
50 | home-manager.useUserPackages = true;
51 | home-manager.extraSpecialArgs = {
52 | inherit user;
53 | };
54 | home-manager.backupFileExtension = "backup";
55 | home-manager.users.${user.username} = {
56 | imports = [./machines/${machine}/home.nix];
57 | };
58 | }
59 | sops-nix.nixosModules.sops # sops
60 | ];
61 | specialArgs = {
62 | hostname = machine;
63 | inherit user;
64 | };
65 | };
66 | }) machines
67 | );
68 | devShells.${user.system}.default = pkgs.mkShell {
69 | buildInputs = with pkgs; [
70 | nil # nix lsp server
71 | nixfmt-rfc-style # nix formatter
72 | sops # used to edit secrets
73 | ];
74 | };
75 | };
76 | }
77 |
--------------------------------------------------------------------------------
/hardware/hardware.nix:
--------------------------------------------------------------------------------
1 | # WARNING : This file was generated by README.org
2 | # DO NOT MODIFY THIS FILE!
3 | # Any changes made here will be overwritten.
4 | { pkgs, lib, user, config, ...} :
5 | {
6 | # allow automatic ip assignment when connecting to a network
7 | networking.useDHCP = lib.mkDefault true;
8 |
9 | # let wifi info be NOT declarative, allowing user to configure wifi.
10 | networking.wireless.userControlled.enable = true;
11 |
12 | nixpkgs.hostPlatform = lib.mkDefault user.system; # x86_64-linux
13 | powerManagement.cpuFreqGovernor = lib.mkDefault "powersave"; # enable power saving on the cpu
14 |
15 | # update cpu microcode with firmware that allows redistribution
16 | hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
17 |
18 | hardware = {
19 | # always enable bluetooth
20 | bluetooth.enable = true;
21 |
22 | # always enable graphics drivers and enable a bunch of layers for it (including vulkan validation)
23 | graphics = {
24 | enable = true;
25 | extraPackages = with pkgs; [
26 | vulkan-validation-layers # helps catch and debug vulkan crashes
27 | ];
28 | };
29 | };
30 |
31 | hardware.enableAllFirmware = true; # enable all firmware regardless of license
32 | }
33 |
--------------------------------------------------------------------------------
/home/default.nix:
--------------------------------------------------------------------------------
1 | # WARNING : This file was generated by README.org
2 | # DO NOT MODIFY THIS FILE!
3 | # Any changes made here will be overwritten.
4 | { pkgs, user, ... } :
5 | {
6 | imports = [
7 | ./waybar.nix
8 | ./wallpaper.nix
9 | ./lock.nix
10 | ./unity.nix
11 | ./hyprland.nix
12 | ./tofi.nix
13 | ./theme.nix
14 | ./terminal.nix
15 | ./dev.nix
16 | ./emacs
17 | ];
18 |
19 | home.username = "${user.username}";
20 | home.homeDirectory = pkgs.lib.mkDefault "/home/${user.username}";
21 | home.stateVersion = user.stateVersion;
22 |
23 | home.packages = with pkgs; [
24 | audacity # audio recording
25 | zoom-us # meetings
26 | handbrake # video transcoding
27 | sway-contrib.grimshot # screenshot tool
28 | xdg-utils # utils, for screensharing
29 | vlc # media player
30 | discord # other chat
31 | slack # work chat
32 | pavucontrol # audio control
33 | everdo # gtd tool
34 | spotify # music player
35 | simple-scan # scanner software
36 | ];
37 | services.dunst.enable = true; # notifications daemon
38 | programs.obs-studio.enable = true; # screen recording tool
39 |
40 | programs.home-manager.enable = true;
41 | }
42 |
--------------------------------------------------------------------------------
/home/dev.nix:
--------------------------------------------------------------------------------
1 | # WARNING : This file was generated by README.org
2 | # DO NOT MODIFY THIS FILE!
3 | # Any changes made here will be overwritten.
4 | { user, ... }:
5 | {
6 | programs = {
7 | vscode.enable = true; # yes, sometimes i like to dabble
8 | vim.enable = true; # and this one too
9 | ripgrep.enable = true; # fast text search across projects
10 | htop.enable = true; # task manager
11 |
12 | # this is mainly for integration with nix flakes in individual projects
13 | direnv = {
14 | enable = true;
15 | enableZshIntegration = true;
16 | nix-direnv.enable = true;
17 | };
18 |
19 | # zsh everywhere with oh-my-zsh
20 | zsh = {
21 | enable = true;
22 | oh-my-zsh = {
23 | enable = true;
24 | plugins = [ "git" ];
25 | theme = "robbyrussell";
26 | };
27 | };
28 |
29 | # git with lfs
30 | git = {
31 | lfs.enable = true;
32 | enable = true;
33 | };
34 | };
35 | }
36 |
--------------------------------------------------------------------------------
/home/emacs/default.nix:
--------------------------------------------------------------------------------
1 | # WARNING : This file was generated by README.org
2 | # DO NOT MODIFY THIS FILE!
3 | # Any changes made here will be overwritten.
4 | { pkgs, ... }:
5 | {
6 | programs.emacs = {
7 | enable = true;
8 | # install with tree sitter enabled
9 | package = (pkgs.emacs-git-pgtk.override { withTreeSitter = true; });
10 | extraPackages = epkgs: [
11 | # also install all tree sitter grammars
12 | epkgs.manualPackages.treesit-grammars.with-all-grammars
13 | pkgs.nodejs # some emacs deps need node installed
14 | pkgs.omnisharp-roslyn # c# lsp
15 | epkgs.nerd-icons # nerd fonts support
16 | epkgs.doom-modeline # model line
17 | epkgs.doom-themes # for doom-nord theme
18 | epkgs.diminish # hides modes from modeline
19 | epkgs.eldoc # doc support
20 | epkgs.whitespace-cleanup-mode # cleanup accidental whitespace
21 | epkgs.pulsar # pulses the cursor when jumping about
22 | epkgs.which-key # help porcelain
23 | epkgs.expreg # expand region
24 | epkgs.vundo # undo tree
25 | epkgs.puni # structured editing
26 | epkgs.avy # jumping utility
27 | epkgs.consult # emacs right click
28 | epkgs.vertico # minibuffer completion
29 | epkgs.marginalia # annotations for completions
30 | epkgs.crux # utilities
31 | epkgs.magit # git porcelain
32 | epkgs.nerd-icons-corfu # nerd icons for completion
33 | epkgs.corfu # completion
34 | epkgs.cape # completion extensions
35 | epkgs.orderless # search paradigm
36 | epkgs.yasnippet # snippets support
37 | epkgs.yasnippet-snippets # commonly used snippets
38 | epkgs.projectile # project management
39 | epkgs.rg # ripgrep
40 | epkgs.exec-path-from-shell # load env and path
41 | epkgs.flycheck # error integration
42 | epkgs.lsp-mode # lsp
43 | epkgs.lsp-ui # ui for lsp
44 | epkgs.rust-mode # rust mode (when rust-ts doesn't cut it)
45 | epkgs.nix-mode # nix lang
46 | epkgs.eat # better shell
47 | epkgs.hcl-mode # hashicorp file mode
48 | epkgs.shell-pop # quick shell popup
49 | epkgs.f # string + file utilities
50 | epkgs.gptel # llm chat (mainly claude)
51 | epkgs.copilot # emacs copilot plugin
52 | epkgs.envrc # support for loading .envrc
53 | epkgs.nixpkgs-fmt # format nix files
54 | ];
55 | };
56 |
57 | home.sessionVariables = {
58 | EDITOR = "emacs";
59 | };
60 |
61 | home.file = {
62 | emacs-init = {
63 | source = ./early-init.el;
64 | target = ".emacs.d/early-init.el";
65 | };
66 |
67 | emacs = {
68 | source = ./init.el;
69 | target = ".emacs.d/init.el";
70 | };
71 | };
72 | }
73 |
--------------------------------------------------------------------------------
/home/emacs/early-init.el:
--------------------------------------------------------------------------------
1 | ;;; package --- early init -*- lexical-binding: t -*-
2 |
3 | ;;; Commentary:
4 | ;;; Prevents white flash and better Emacs defaults
5 |
6 | ;;; Code:
7 | (set-language-environment "UTF-8")
8 |
9 | (setq-default
10 | default-frame-alist
11 | '((background-color . "#3F3F3F")
12 | (bottom-divider-width . 1) ; Thin horizontal window divider
13 | (foreground-color . "#DCDCCC") ; Default foreground color
14 | (fullscreen . maximized) ; Maximize the window by default
15 | (horizontal-scroll-bars . nil) ; No horizontal scroll-bars
16 | (left-fringe . 8) ; Thin left fringe
17 | (menu-bar-lines . 0) ; No menu bar
18 | (right-divider-width . 1) ; Thin vertical window divider
19 | (right-fringe . 8) ; Thin right fringe
20 | (tool-bar-lines . 0) ; No tool bar
21 | (undecorated . t) ; Remove extraneous X decorations
22 | (vertical-scroll-bars . nil)) ; No vertical scroll-bars
23 |
24 | user-full-name "Sandeep Nambiar" ; ME!
25 |
26 | ;; memory configuration
27 | ;; Higher garbage collection threshold, prevents frequent gc locks
28 | gc-cons-threshold most-positive-fixnum
29 | ;; Ignore warnings for (obsolete) elisp compilations
30 | byte-compile-warnings '(not obsolete)
31 | ;; And other log types completely
32 | warning-suppress-log-types '((comp) (bytecomp))
33 | ;; Large files are okay in the new millenium.
34 | large-file-warning-threshold 100000000
35 |
36 | ;; Read more based on system pipe capacity
37 | read-process-output-max (max (* 10240 10240) read-process-output-max)
38 |
39 | ;; scroll configuration
40 | scroll-margin 0 ; Lets scroll to the end of the margin
41 | scroll-conservatively 100000 ; Never recenter the window
42 | scroll-preserve-screen-position 1 ; Scrolling back and forth
43 |
44 | ;; frame config
45 | ;; Improve emacs startup time by not resizing to adjust for custom settings
46 | frame-inhibit-implied-resize t
47 | ;; Dont resize based on character height / width but to exact pixels
48 | frame-resize-pixelwise t
49 |
50 | ;; backups & files
51 | backup-directory-alist '(("." . "~/.backups/")) ; Don't clutter
52 | backup-by-copying t ; Don't clobber symlinks
53 | create-lockfiles nil ; Don't have temp files
54 | delete-old-versions t ; Cleanup automatically
55 | kept-new-versions 6 ; Update every few times
56 | kept-old-versions 2 ; And cleanup even more
57 | version-control t ; Version them backups
58 | delete-by-moving-to-trash t ; Dont delete, send to trash instead
59 |
60 | ;; startup
61 | inhibit-startup-screen t ; I have already done the tutorial. Twice
62 | inhibit-startup-message t ; I know I am ready
63 | inhibit-startup-echo-area-message t ; Yep, still know it
64 | initial-scratch-message nil ; I know it is the scratch buffer!
65 |
66 | ;; tabs
67 | tab-width 4 ; Always tab 4 spaces.
68 | indent-tabs-mode nil ; Never use actual tabs.
69 |
70 | ;; rendering
71 | cursor-in-non-selected-windows nil ; dont render cursors other windows
72 |
73 | ;; packages
74 | use-package-always-defer t
75 |
76 | ;; custom
77 | custom-file (concat user-emacs-directory "custom.el")
78 |
79 | load-prefer-newer t
80 |
81 | default-input-method nil
82 | )
83 | ;;; early-init.el ends here
84 |
--------------------------------------------------------------------------------
/home/emacs/init.el:
--------------------------------------------------------------------------------
1 | ;;; package --- Summary - My minimal Emacs init file -*- lexical-binding: t -*-
2 |
3 | ;;; Commentary:
4 | ;;; Simple Emacs setup I carry everywhere
5 |
6 | ;;; Code:
7 | (load custom-file 'noerror) ;; no error on missing custom file
8 |
9 | (require 'package)
10 | (add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/") t)
11 | (add-to-list 'package-archives '("nongnu" . "https://elpa.nongnu.org/nongnu/") t)
12 | (package-initialize)
13 |
14 | (use-package emacs
15 | :init
16 | (global-auto-revert-mode t) ;; revert automatically on external file changes
17 | (savehist-mode) ;; save minibuffer history
18 |
19 | ;; base visual
20 | (menu-bar-mode -1) ;; no menu bar
21 | (toggle-scroll-bar -1) ;; no scroll bar
22 | (tool-bar-mode -1) ;; no tool bar either
23 | (global-hl-line-mode +1) ;; always highlight current line
24 | (blink-cursor-mode -1) ;; stop blinking
25 | (global-display-line-numbers-mode 1) ;; always show line numbers
26 | (column-number-mode t) ;; column number in the mode line
27 | (size-indication-mode t) ;; file size in the mode line
28 | (pixel-scroll-precision-mode) ;; smooth mouse scroll
29 | (fset 'yes-or-no-p 'y-or-n-p) ;; y/n is good enough
30 | (electric-pair-mode) ;; i mean ... parens should auto create
31 | (recentf-mode) ;; keep track of recently opened files
32 |
33 | ;; font of the century
34 | (set-frame-font "Iosevka Nerd Font 12" nil t)
35 |
36 | :bind
37 | (("C-" . pixel-scroll-precision) ; dont zoom in please, just scroll
38 | ("C-" . pixel-scroll-precision) ; dont zoom in either, just scroll
39 | ("C-x k" . kill-current-buffer)) ; kill the buffer, dont ask
40 | )
41 |
42 | (use-package nerd-icons
43 | :custom
44 | ;; disable bright icon colors
45 | (nerd-icons-color-icons nil))
46 |
47 | (use-package doom-modeline
48 | :custom
49 | (inhibit-compacting-font-caches t) ;; speed
50 | (doom-modeline-buffer-file-name-style 'relative-from-project)
51 | (doom-modeline-major-mode-icon nil) ;; distracting icons, no thank you
52 | (doom-modeline-buffer-encoding nil) ;; everything is utf-8 anyway
53 | (doom-modeline-buffer-state-icon nil) ;; the filename already shows me
54 | (doom-modeline-lsp nil) ;; lsp state is too distracting, too often
55 | :hook (after-init . doom-modeline-mode))
56 |
57 | (use-package doom-themes
58 | :commands doom-themes-visual-bell-config
59 | :custom
60 | (doom-themes-enable-bold t)
61 | (doom-themes-enable-italic t)
62 | :init
63 | (load-theme 'doom-nord t)
64 | (doom-themes-visual-bell-config))
65 |
66 | (use-package diminish :demand t) ;; declutter the modeline
67 | (use-package eldoc :diminish eldoc-mode) ;; docs for everything
68 |
69 | (use-package whitespace-cleanup-mode
70 | :commands global-whitespace-cleanup-mode
71 | :custom
72 | (whitespace-cleanup-mode-only-if-initially-clean nil)
73 | :hook
74 | (after-init . global-whitespace-cleanup-mode))
75 |
76 | (use-package pulsar
77 | :commands pulsar-global-mode pulsar-recenter-top pulsar-reveal-entry
78 | :init
79 | (defface pulsar-nord
80 | '((default :extend t)
81 | (((class color) (min-colors 88) (background light))
82 | :background "#2e3440")
83 | (((class color) (min-colors 88) (background dark))
84 | :background "#81a1c1")
85 | (t :inverse-video t))
86 | "Alternative nord face for `pulsar-face'."
87 | :group 'pulsar-faces)
88 | :custom
89 | (pulsar-face 'pulsar-nord)
90 | :hook
91 | (after-init . pulsar-global-mode))
92 |
93 | (use-package which-key
94 | :commands which-key-mode
95 | :diminish which-key-mode
96 | :hook
97 | (after-init . which-key-mode))
98 |
99 | (use-package expreg
100 | :bind ("M-m" . expreg-expand))
101 |
102 | (use-package vundo) ;; undo tree
103 |
104 | ;; better structured editing
105 | (use-package puni
106 | :commands puni-global-mode
107 | :hook
108 | (after-init . puni-global-mode))
109 |
110 | (use-package avy
111 | :bind
112 | ("M-i" . avy-goto-char-2)
113 | :custom
114 | (avy-background t))
115 |
116 | (use-package consult
117 | :bind
118 | ("C-x b" . consult-buffer) ;; orig. switch-to-buffer
119 | ("M-y" . consult-yank-pop) ;; orig. yank-pop
120 | ("M-g M-g" . consult-goto-line) ;; orig. goto-line
121 | :custom
122 | (consult-narrow-key "<"))
123 |
124 | (use-package vertico
125 | :commands vertico-mode
126 | :custom
127 | (read-file-name-completion-ignore-case t)
128 | (read-buffer-completion-ignore-case t)
129 | (completion-ignore-case t)
130 | (enable-recursive-minibuffers t)
131 | :init
132 | (vertico-mode)
133 | :config
134 | (setq minibuffer-prompt-properties
135 | '(read-only t cursor-intangible t face minibuffer-prompt))
136 | :hook
137 | (minibuffer-setup-hook . cursor-intangible-mode))
138 |
139 | (use-package marginalia
140 | :commands marginalia-mode
141 | :hook (after-init . marginalia-mode))
142 |
143 | (use-package crux
144 | :bind
145 | ("C-c M-e" . crux-find-user-init-file)
146 | ("C-c C-w" . crux-transpose-windows)
147 | ("C-a" . crux-move-beginning-of-line))
148 |
149 | (use-package magit
150 | :bind (("C-M-g" . magit-status)))
151 |
152 | (use-package nerd-icons-corfu
153 | :commands nerd-icons-corfu-formatter
154 | :defines corfu-margin-formatters)
155 |
156 | (use-package corfu
157 | :commands global-corfu-mode
158 | :custom
159 | (corfu-cycle t)
160 | (corfu-auto t)
161 | (corfu-auto-delay 1)
162 | (corfu-auto-prefix 3)
163 | (corfu-separator ?_)
164 | :hook
165 | (after-init . global-corfu-mode)
166 | :config
167 | (add-to-list 'corfu-margin-formatters #'nerd-icons-corfu-formatter))
168 |
169 | (use-package cape)
170 |
171 | (use-package orderless
172 | :custom
173 | (completion-styles '(orderless partial-completion basic))
174 | (completion-category-defaults nil)
175 | (completion-category-overrides nil))
176 |
177 | (use-package yasnippet
178 | :commands yas-global-mode
179 | :diminish yas-minor-mode
180 | :hook
181 | (after-init . yas-global-mode))
182 |
183 | (use-package yasnippet-snippets :after yasnippet)
184 |
185 | (use-package projectile
186 | :commands projectile-mode
187 | :diminish projectile-mode
188 | :custom
189 | (projectile-globally-ignored-directories (append '("node_modules")))
190 | :bind-keymap ("C-c p" . projectile-command-map)
191 | :config
192 | (projectile-mode +1))
193 |
194 | (use-package exec-path-from-shell
195 | :commands exec-path-from-shell-initialize
196 | :custom
197 | (exec-path-from-shell-arguments nil)
198 | :hook
199 | (after-init . exec-path-from-shell-initialize))
200 |
201 | (use-package flycheck
202 | :commands global-flycheck-mode
203 | :diminish
204 | :hook
205 | (after-init . global-flycheck-mode))
206 |
207 | (use-package lsp-mode
208 | :commands (lsp lsp-deferred lsp-format-buffer
209 | lsp-organize-imports
210 | orderless-dispatch-flex-first
211 | cape-capf-buster lsp-completion-at-point)
212 | :defines lsp-file-watch-ignored-directories
213 | :diminish lsp-lens-mode
214 | :bind-keymap
215 | ("C-c l" . lsp-command-map)
216 | :custom
217 | (lsp-lens-enable nil)
218 | (lsp-idle-delay 0.500)
219 | (lsp-modeline-code-actions-enable t)
220 | (lsp-modeline-diagnostics-enable t)
221 | (lsp-csharp-omnisharp-roslyn-binary-path "OmniSharp")
222 | (lsp-completion-provider :none) ;; we use Corfu!
223 | (lsp-eldoc-render-all t)
224 | :init
225 | (defun orderless-dispatch-flex-first (_pattern index _total)
226 | (and (eq index 0) 'orderless-flex))
227 |
228 | ;; Configure the first word as flex filtered.
229 | (add-hook 'orderless-style-dispatchers #'orderless-dispatch-flex-first nil 'local)
230 |
231 | (defun lsp-mode-setup-completion ()
232 | (setf (alist-get 'styles (alist-get 'lsp-capf completion-category-defaults))
233 | '(orderless)))
234 |
235 | ;; Optionally configure the cape-capf-buster.
236 | (setq-local completion-at-point-functions
237 | (list (cape-capf-buster #'lsp-completion-at-point)))
238 | :config
239 | (add-to-list 'lsp-file-watch-ignored-directories "[/\\\\]\\Temp\\'")
240 | (add-to-list 'lsp-file-watch-ignored-directories "[/\\\\]\\Logs\\'")
241 | (defun lsp-cleanup ()
242 | (lsp-format-buffer)
243 | (lsp-organize-imports)
244 | (whitespace-cleanup))
245 | :hook
246 | (lsp-completion-mode . lsp-mode-setup-completion)
247 | (lsp-mode . lsp-enable-which-key-integration)
248 | (before-save . lsp-cleanup)
249 | (prog-mode . lsp-deferred))
250 |
251 | (use-package lsp-ui :commands lsp-ui-mode
252 | :custom
253 | (lsp-ui-doc-enable t)
254 | (lsp-ui-sideline-diagnostic-max-lines 4)
255 | (lsp-ui-doc-show-with-mouse nil)
256 | (lsp-ui-doc-position 'bottom)
257 | (lsp-ui-doc-show-with-cursor t)
258 | (lsp-eldoc-enable-hover nil)
259 | )
260 |
261 | (use-package nixpkgs-fmt
262 | :custom
263 | (nixpkgs-fmt-command "nixfmt"))
264 |
265 | (use-package rust-mode
266 | :custom
267 | (rust-mode-treesitter-derive t)
268 | (lsp-rust-analyzer-cargo-watch-command "clippy")
269 | (lsp-rust-analyzer-exclude-dirs ["Temp/**"]))
270 |
271 | (use-package typescript-ts-mode
272 | :custom
273 | (lsp-javascript-preferences-import-module-specifier :relative)
274 | (typescript-indent-level 2)
275 | (typescript-ts-mode-indent-offset 2))
276 |
277 | (use-package eat)
278 | (use-package hcl-mode)
279 | (use-package jinja2-mode)
280 | (use-package f :demand t)
281 |
282 | (use-package envrc
283 | :commands envrc-global-mode
284 | :hook
285 | (after-init . envrc-global-mode))
286 |
287 | (use-package nix-mode
288 | :hook (nix-mode . lsp-deferred))
289 |
290 | (use-package shell-pop
291 | :custom
292 | (shell-pop-universal-key "M-o"))
293 |
294 | (use-package copilot
295 | :defines copilot-completion-map
296 | :bind
297 | (:map copilot-completion-map
298 | ("" . copilot-accept-completion)
299 | ("M-n" . copilot-next-completion)
300 | ("M-p" . copilot-previous-completion)
301 | ("C-g" . copilot-clear-overlay)))
302 |
303 | (use-package gptel
304 | :commands gptel-make-anthropic f-read-text
305 | :config
306 | (gptel-make-anthropic "Claude"
307 | :stream t :key (f-read-text "/run/secrets/claude_key")))
308 |
309 | (provide 'init)
310 |
311 | ;;; init.el ends here
312 |
--------------------------------------------------------------------------------
/home/hyprland.nix:
--------------------------------------------------------------------------------
1 | # WARNING : This file was generated by README.org
2 | # DO NOT MODIFY THIS FILE!
3 | # Any changes made here will be overwritten.
4 | {
5 | # required for the default Hyprland config
6 | programs.kitty.enable = true;
7 |
8 | services.hyprpolkitagent.enable = true;
9 |
10 | # enable Hyprland
11 | wayland.windowManager.hyprland.enable = true;
12 |
13 | # we start hyprland using uwsm
14 | wayland.windowManager.hyprland.systemd.enable = false;
15 |
16 | # hyprland.conf
17 | wayland.windowManager.hyprland.settings = {
18 | exec-once = [
19 | # read in env vars
20 | "dbus-update-activation-environment --systemd --all"
21 | # start waybar
22 | "uwsm app -- waybar"
23 | # start the policykit agent
24 | "uwsm app -- lxqt-policykit-agent"
25 | ];
26 |
27 | input = {
28 | follow_mouse = "1";
29 |
30 | touchpad = {
31 | natural_scroll = "no";
32 | scroll_factor = 0.5;
33 | };
34 |
35 | accel_profile = "adaptive";
36 | sensitivity = -0.5; # -1.0 - 1.0, 0 means no modification.
37 |
38 | kb_layout = "us";
39 |
40 | # very emacs specific, i use caps as an extra ctrl key
41 | kb_options = "ctrl:nocaps";
42 | };
43 |
44 | cursor = {
45 | no_hardware_cursors = "true";
46 | };
47 |
48 | general = {
49 | gaps_in = 2;
50 | gaps_out = 4;
51 | border_size = 2;
52 | "col.active_border" = "rgba(33ccffee) rgba(00ff99ee) 45deg";
53 | "col.inactive_border" = "rgba(595959aa)";
54 |
55 | layout = "dwindle";
56 | };
57 |
58 | decoration = {
59 | rounding = 5;
60 | };
61 |
62 | animations = {
63 | enabled = "yes";
64 | bezier = "myBezier, 0.05, 0.9, 0.1, 1.05";
65 |
66 | animation = [
67 | "windows, 1, 7, myBezier"
68 | "windowsOut, 1, 7, default, popin 80%"
69 | "border, 1, 10, default"
70 | "borderangle, 1, 8, default"
71 | "fade, 1, 7, default"
72 | "workspaces, 1, 6, default"
73 | ];
74 | };
75 |
76 | dwindle = {
77 | pseudotile = "yes";
78 | preserve_split = "yes";
79 | };
80 |
81 | gestures = {
82 | workspace_swipe = "off";
83 | };
84 |
85 | misc = {
86 | disable_hyprland_logo = true;
87 | focus_on_activate = true;
88 | };
89 |
90 | "$mainMod" = "SUPER";
91 |
92 | bind = [
93 | "$mainMod, Return, exec, uwsm app -- alacritty"
94 | "$mainMod_SHIFT, Q, killactive"
95 | "$mainMod_SHIFT, M, exit"
96 | "$mainMod, F, exec, thunar"
97 | "$mainMod_SHIFT, Space, togglefloating"
98 |
99 | # use tofi to show exec menu
100 | "$mainMod, Space, exec, uwsm app -- tofi-run | xargs hyprctl dispatch -- exec"
101 | "$mainMod, P, pseudo"
102 | "$mainMod, J, togglesplit"
103 |
104 | "$mainMod_SHIFT, left, movewindow, l"
105 | "$mainMod_SHIFT, right, movewindow, r"
106 | "$mainMod_SHIFT, up, movewindow, u"
107 | "$mainMod_SHIFT, down, movewindow, d"
108 |
109 | "$mainMod_CTRL, left, movecurrentworkspacetomonitor, l"
110 | "$mainMod_CTRL, right, movecurrentworkspacetomonitor, r"
111 |
112 | "$mainMod, left, movefocus, l"
113 | "$mainMod, right, movefocus, r"
114 | "$mainMod, up, movefocus, u"
115 | "$mainMod, down, movefocus, d"
116 |
117 | "$mainMod, mouse_down, workspace, e+1"
118 | "$mainMod, mouse_up, workspace, e-1"
119 |
120 | "$mainMod_SHIFT, S, exec, wlogout"
121 | ] ++ (
122 | # workspaces
123 | # binds $mod + [shift +] {1..9} to [move to] workspace {1..9}
124 | builtins.concatLists (builtins.genList (i:
125 | let ws = i + 1;
126 | in [
127 | "$mainMod, ${toString ws}, workspace, ${toString ws}"
128 | "$mainMod SHIFT, ${toString ws}, movetoworkspace, ${toString ws}"
129 | ]
130 | )
131 | 9)
132 | );
133 |
134 | bindm = [
135 | "$mainMod, mouse:272, movewindow"
136 | "$mainMod, mouse:273, resizewindow"
137 | ];
138 | };
139 |
140 | programs.hyprlock = {
141 | enable = true;
142 |
143 | # hyprlock.conf
144 | settings = {
145 | background = {
146 | monitor = "";
147 | path = "~/.background-image.png";
148 | blur_passes = 2;
149 | contrast = 1;
150 | brightness = 0.5;
151 | vibrancy = 0.2;
152 | vibrancy_darkness = 0.2;
153 | };
154 |
155 | auth = {
156 | fingerprint = {
157 | enabled = true;
158 | };
159 | };
160 |
161 | # GENERAL
162 | general = {
163 | hide_cursor = false;
164 | grace = 0;
165 | };
166 |
167 | # INPUT FIELD
168 | input-field = [
169 | {
170 | size = "250, 60";
171 | outline_thickness = 2;
172 | dots_size = 0.2;
173 | dots_spacing = 0.35;
174 | dots_center = true;
175 | outer_color = "rgba(216,222,233,0.2)";
176 | inner_color = "rgba(216,222,233,1)";
177 | font_color = "rgba(41,46,57,1)";
178 | fade_on_empty = false;
179 | rounding = -1;
180 | check_color = "rgb(163,190,140)";
181 | placeholder_text = ''Password'';
182 | hide_input = false;
183 | position = "0, -400";
184 | halign = "center";
185 | valign = "center";
186 | }
187 | ];
188 |
189 | # DATE
190 | label = [
191 | {
192 | monitor = "";
193 | text = ''cmd[update:1000] echo "$(date +"%A, %B %d")"'';
194 | color = "rgba(242, 243, 244, 0.75)";
195 | font_size = 22;
196 | font_family = "Iosevka";
197 | position = "0, 300";
198 | halign = "center";
199 | valign = "center";
200 | }
201 | # TIME
202 | {
203 | monitor = "";
204 | text = ''cmd[update:1000] echo "$(date +"%-I:%M")"'';
205 | color = "rgba(242, 243, 244, 0.75)";
206 | font_size = 95;
207 | font_family = "Iosevka";
208 | position = "0, 200";
209 | halign = "center";
210 | valign = "center";
211 | }
212 | # USER
213 | {
214 | monitor = "";
215 | text = ''cmd[update:1000] echo $USER'';
216 | color = "rgba(242, 243, 244, 0.75)";
217 | font_size = 30;
218 | font_family = "Iosevka";
219 | position = "0, -250";
220 | halign = "center";
221 | valign = "center";
222 | }
223 |
224 | # battery
225 | {
226 | monitor = "";
227 | text = ''cmd[update:1000] echo "$(cat /sys/class/power_supply/BAT0/capacity) "'';
228 | color = "rgba(242, 243, 244, 0.75)";
229 | font_size = 20;
230 | font_family = "Iosevka";
231 | position = "-20, -20";
232 | halign = "right";
233 | valign = "top";
234 | }
235 | ];
236 |
237 | # Profile Picture
238 | image = [
239 | {
240 | monitor = "";
241 | path = "~/.me.jpg";
242 | size = 200;
243 | border_size = 2;
244 | position = "0, -100";
245 | halign = "center";
246 | valign = "center";
247 | }
248 | ];
249 | };
250 | };
251 | }
252 |
--------------------------------------------------------------------------------
/home/lock.nix:
--------------------------------------------------------------------------------
1 | # WARNING : This file was generated by README.org
2 | # DO NOT MODIFY THIS FILE!
3 | # Any changes made here will be overwritten.
4 | { pkgs, ... } :
5 | {
6 | home.packages = with pkgs; [
7 | hyprlock
8 | hypridle
9 | wlogout
10 | ];
11 |
12 |
13 | home.file = {
14 | lock = {
15 | source = ../assets/lock.png;
16 | target = ".lock.png";
17 | };
18 | };
19 |
20 | services = {
21 | # hypridle to
22 | # 150 seconds - turn of monitor
23 | # 300 seconds - lock screen
24 | # 330 seconds - turn of monitor
25 | # 30 minutes - put to sleep
26 | hypridle = {
27 | enable = true;
28 | settings = {
29 | general = {
30 | lock_cmd = "pidof hyprlock || hyprlock"; # avoid starting multiple hyprlock instances.
31 | before_sleep_cmd = "loginctl lock-session"; # lock before suspend.
32 | after_sleep_cmd = "hyprctl dispatch dpms on"; # to avoid having to press a key twice to turn on the display.
33 | };
34 |
35 | listener = [
36 | {
37 | timeout = 150; # 2.5min.
38 | on-timeout = "brightnessctl -s set 10"; # set monitor backlight to minimum, avoid 0 on OLED monitor.
39 | on-resume = "brightnessctl -r"; # monitor backlight restore.
40 | }
41 | {
42 | timeout = 300; # 5min
43 | on-timeout = "loginctl lock-session"; # lock screen when timeout has passed
44 | }
45 | {
46 | timeout = 330; # 5.5min
47 | on-timeout = "hyprctl dispatch dpms off"; # screen off when timeout has passed
48 | on-resume = "hyprctl dispatch dpms on && brightnessctl -r"; # screen on when activity is detected after timeout has fired.
49 | }
50 | {
51 | timeout = 1800; # 30min
52 | on-timeout = "systemctl suspend"; # suspend pc
53 | }
54 | ];
55 |
56 | };
57 | };
58 | };
59 |
60 | programs.wlogout = {
61 | enable = true;
62 | layout = [
63 | {
64 | "label" = "lock";
65 | "action" = "hyprlock";
66 | "text" = "Lock";
67 | "keybind" = "l";
68 | }
69 | {
70 | "label" = "shutdown";
71 | "action" = "systemctl poweroff";
72 | "text" = "Shutdown";
73 | "keybind" = "s";
74 | }
75 | {
76 | "label" = "suspend";
77 | "action" = "systemctl suspend";
78 | "text" = "Suspend";
79 | "keybind" = "u";
80 | }
81 | {
82 | "label" = "reboot";
83 | "action" = "systemctl reboot";
84 | "text" = "Reboot";
85 | "keybind" = "r";
86 | }
87 | {
88 | "label" = "hibernate";
89 | "action" = "systemctl hibernate";
90 | "text" = "Hibernate";
91 | "keybind" = "h";
92 | }
93 | {
94 | "label" = "reboot";
95 | "action" = "systemctl reboot";
96 | "text" = "Reboot";
97 | "keybind" = "r";
98 | }
99 | ];
100 | };
101 | }
102 |
--------------------------------------------------------------------------------
/home/terminal.nix:
--------------------------------------------------------------------------------
1 | # WARNING : This file was generated by README.org
2 | # DO NOT MODIFY THIS FILE!
3 | # Any changes made here will be overwritten.
4 | {
5 | programs = {
6 | alacritty = {
7 | enable = true;
8 | settings = {
9 | font.normal.family = "Iosevka Nerd Font";
10 | font.size = 12;
11 | terminal.shell.program = "zsh";
12 |
13 | window = {
14 | padding.x = 4;
15 | padding.y = 4;
16 | };
17 |
18 | colors = {
19 | primary = {
20 | background = "#1f222d";
21 | foreground = "#d8dee9";
22 | dim_foreground = "#a5abb6";
23 | };
24 | cursor = {
25 | text = "#2e3440";
26 | cursor = "#d8dee9";
27 | };
28 | normal = {
29 | black = "#3b4252";
30 | red = "#bf616a";
31 | green = "#a3be8c";
32 | yellow = "#ebcb8b";
33 | blue = "#81a1c1";
34 | magenta = "#b48ead";
35 | cyan = "#88c0d0";
36 | white = "#e5e9f0";
37 | };
38 | };
39 | };
40 | };
41 | };
42 | }
43 |
--------------------------------------------------------------------------------
/home/theme.nix:
--------------------------------------------------------------------------------
1 | # WARNING : This file was generated by README.org
2 | # DO NOT MODIFY THIS FILE!
3 | # Any changes made here will be overwritten.
4 | { pkgs, ...}:
5 | {
6 | home.packages = with pkgs; [
7 | nordzy-cursor-theme
8 | nordic
9 | ];
10 |
11 | gtk = {
12 | enable = true;
13 | iconTheme = {
14 | name = "Nordic-bluish";
15 | package = pkgs.nordic;
16 | };
17 | theme = {
18 | name = "Nordic";
19 | package = pkgs.nordic;
20 | };
21 | cursorTheme = {
22 | name = "Nordzy-cursors";
23 | package = pkgs.nordzy-cursor-theme;
24 | };
25 | };
26 | }
27 |
--------------------------------------------------------------------------------
/home/tofi.nix:
--------------------------------------------------------------------------------
1 | # WARNING : This file was generated by README.org
2 | # DO NOT MODIFY THIS FILE!
3 | # Any changes made here will be overwritten.
4 | {
5 | programs.tofi.enable = true;
6 | programs.tofi.settings = {
7 | font = "Iosevka";
8 | font-size = 16;
9 | selection-color = "#a3be8c";
10 | prompt-text = ":";
11 | width = 600;
12 | height = 480;
13 | background-color = "#2e3440";
14 | outline-width = 0;
15 | outline-color = "#080800";
16 | border-width = 1;
17 | border-color = "#8fbcbb";
18 | corner-radius = 10;
19 | padding-top = 4;
20 | padding-bottom = 4;
21 | padding-left = 4;
22 | padding-right = 4;
23 | matching-algorithm = "fuzzy";
24 | };
25 | }
26 |
--------------------------------------------------------------------------------
/home/unity.nix:
--------------------------------------------------------------------------------
1 | # WARNING : This file was generated by README.org
2 | # DO NOT MODIFY THIS FILE!
3 | # Any changes made here will be overwritten.
4 | { pkgs, ... }:
5 | {
6 | home.packages = with pkgs; [
7 | (pkgs.unityhub.override {
8 | extraPkgs = pkgs: with pkgs; [
9 | dotnet-sdk
10 | ];
11 | })
12 | ];
13 | }
14 |
--------------------------------------------------------------------------------
/home/wallpaper.nix:
--------------------------------------------------------------------------------
1 | # WARNING : This file was generated by README.org
2 | # DO NOT MODIFY THIS FILE!
3 | # Any changes made here will be overwritten.
4 | { pkgs, ... }:
5 | {
6 | home.packages = with pkgs; [
7 | hyprpaper
8 | ];
9 |
10 | services.hyprpaper.enable = true;
11 | services.hyprpaper.settings = {
12 | ipc = "on";
13 | splash = false;
14 | splash_offset = 2.0;
15 |
16 | preload = [ "~/.background-image.png" ];
17 | wallpaper = [ ",~/.background-image.png" ];
18 | };
19 |
20 | home.file = {
21 | background = {
22 | source = ../assets/background.png;
23 | target = ".background-image.png";
24 | };
25 |
26 | me = {
27 | source = ../assets/me.jpg;
28 | target = ".me.jpg";
29 | };
30 | };
31 | }
32 |
--------------------------------------------------------------------------------
/home/waybar.nix:
--------------------------------------------------------------------------------
1 | # WARNING : This file was generated by README.org
2 | # DO NOT MODIFY THIS FILE!
3 | # Any changes made here will be overwritten.
4 | {
5 | programs.waybar = {
6 | enable = true;
7 | settings = {
8 | mainBar = {
9 | layer = "top";
10 | height = 24;
11 | modules-left = [ "hyprland/workspaces" "hyprland/window" ];
12 | modules-right = [
13 | "idle_inhibitor"
14 | "pulseaudio"
15 | "network"
16 | "cpu"
17 | "memory"
18 | "temperature"
19 | "battery"
20 | "tray"
21 | "clock"
22 | ];
23 | "idle_inhibitor" = {
24 | format = "{icon}";
25 | format-icons = {
26 | activated = " ";
27 | deactivated = " ";
28 | };
29 | };
30 | "pulseaudio" = {
31 | "format" = "{volume}% {icon}";
32 | "format-bluetooth" = "{volume}% {icon}";
33 | "format-muted" = "";
34 | "format-icons"= {
35 | "headphones"= "";
36 | "headset"= "";
37 | "phone"= "";
38 | "portab le"= "";
39 | "default"= ["" ""];
40 | };
41 | "on-click"= "pavucontrol";
42 | };
43 | "network" = {
44 | "format-wifi" = " ({bandwidthDownBits})";
45 | "format-ethernet" = " ({bandwidthDownBits})";
46 | "format-disconnected" = "Disconnected ⚠";
47 | "tooltip-format-wifi" = "{essid} ({signalStrength}%)";
48 | "tooltip-format-ethernet" = "{ifname}: {ipaddr}/{cidr}";
49 | };
50 | "cpu".format = "{usage}% ";
51 | "cpu".tooltip = false;
52 | "temperature" = {
53 | "format" = "{temperatureC}°C ";
54 | };
55 | "temperature".tooltip = false;
56 | "tray".spacing = 10;
57 | "tray".icon-size = 14;
58 | "clock".format = "{:%a, %d %b %Y - %H:%M}";
59 | "clock".tooltip = false;
60 | "battery" = {
61 | "bat" = "BAT0";
62 | "states" = {
63 | "good" = 95;
64 | "warning" = 30;
65 | "critical" = 15;
66 | };
67 | "format" = "{capacity}% {icon}";
68 | "format-charging" = "{capacity}% ";
69 | "format-plugged" = "{capacity}% ";
70 | "format-icons" = ["" "" "" "" " "];
71 | };
72 | "memory".format = "{percentage}% ";
73 | };
74 | };
75 | style = ''
76 | * {
77 | font-family: Iosevka Nerd Font, Roboto, Helvetica, Arial, sans-serif;
78 | font-size: 13px;
79 | }
80 |
81 | window#waybar {
82 | background-color: #4c566a;
83 | color: #ffffff;
84 | transition-property: background-color;
85 | border-bottom: 0px solid rgba(0, 0, 0, 0);
86 | transition-duration: .5s;
87 | }
88 |
89 | #workspaces button {
90 | padding: 0 5px;
91 | background-color: transparent;
92 | border: none;
93 | border-radius: 0;
94 | }
95 |
96 | #workspaces button:hover {
97 | background: #2e3440;
98 | color: white;
99 | }
100 |
101 | #workspaces button.active {
102 | background-color: #5e81ac;
103 | box-shadow: inset 0 -3px #ffffff;
104 | }
105 |
106 | #clock,
107 | #idle_inhibitor
108 | #battery,
109 | #cpu,
110 | #memory,
111 | #temperature,
112 | #network,
113 | #pulseaudio,
114 | #tray {
115 | margin: 0 5px;
116 | padding: 0 2px;
117 | }
118 |
119 | #idle_inhibitor.activated {
120 | background-color: #a3be8c;
121 | }
122 |
123 | #battery.charging {
124 | color: #a3be8c;
125 | }
126 |
127 | @keyframes blink {
128 | to {
129 | background-color: #ffffff;
130 | color: black;
131 | }
132 | }
133 |
134 | #battery.warning:not(.charging) {
135 | color: white;
136 | animation-name: blink;
137 | animation-duration: 0.5s;
138 | animation-timing-function: linear;
139 | animation-iteration-count: infinite;
140 | animation-direction: alternate;
141 | }
142 |
143 | #window,
144 | #workspaces {
145 | margin: 0 4px;
146 | }
147 |
148 | .modules-left > widget:first-child > #workspaces {
149 | margin-left: 0;
150 | }
151 |
152 | .modules-right > widget:last-child > #workspaces {
153 | margin-right: 0;
154 | }
155 |
156 | #network.disconnected {
157 | background-color: #f53c3c;
158 | }
159 |
160 | #temperature.critical {
161 | background-color: #eb4d4b;
162 | }
163 | '';
164 | };
165 | }
166 |
--------------------------------------------------------------------------------
/machines/smallbox/configuration.nix:
--------------------------------------------------------------------------------
1 | # WARNING : This file was generated by README.org
2 | # DO NOT MODIFY THIS FILE!
3 | # Any changes made here will be overwritten.
4 | { user, ... } : {
5 | imports =
6 | [
7 | ./hardware-configuration.nix
8 | ../../configuration
9 | ];
10 |
11 | sops.secrets."ssh/smallbox/private" = { # ssh private key
12 | owner = "${user.username}";
13 | mode = "600";
14 | path = "/home/${user.username}/.ssh/id_ed25519";
15 | };
16 | sops.secrets."ssh/smallbox/public" = { # ssh public key
17 | owner = "${user.username}";
18 | mode = "644";
19 | path = "/home/${user.username}/.ssh/id_ed25519.pub";
20 | };
21 | sops.secrets."ssh/wavefunk/private" = { # ssh private key
22 | owner = "${user.username}";
23 | mode = "600";
24 | path = "/home/${user.username}/.ssh/wavefunk";
25 | };
26 | sops.secrets."ssh/wavefunk/public" = { # ssh public key
27 | owner = "${user.username}";
28 | mode = "644";
29 | path = "/home/${user.username}/.ssh/wavefunk.pub";
30 | };
31 | sops.secrets."ssh/wavefunk_dev/private" = { # ssh private key
32 | owner = "${user.username}";
33 | mode = "600";
34 | path = "/home/${user.username}/.ssh/wavefunk_dev";
35 | };
36 | sops.secrets."ssh/wavefunk_dev/public" = { # ssh public key
37 | owner = "${user.username}";
38 | mode = "644";
39 | path = "/home/${user.username}/.ssh/wavefunk_dev.pub";
40 | };
41 | }
42 |
--------------------------------------------------------------------------------
/machines/smallbox/hardware-configuration.nix:
--------------------------------------------------------------------------------
1 | # WARNING : This file was generated by README.org
2 | # DO NOT MODIFY THIS FILE!
3 | # Any changes made here will be overwritten.
4 | {
5 | hostname,
6 | pkgs,
7 | lib,
8 | modulesPath,
9 | user,
10 | ...
11 | }:
12 | {
13 | imports = [
14 | (modulesPath + "/installer/scan/not-detected.nix")
15 | ../../hardware/hardware.nix
16 | ];
17 |
18 | boot.initrd.availableKernelModules = [
19 | "xhci_pci" # usb wake up (usb host controller)
20 | "thunderbolt" # :/
21 | "nvme" # support for the nvme disk in here
22 | "usb_storage" # :/
23 | "sd_mod" # hard drive controller
24 | ];
25 |
26 | boot.kernelParams = [ "amd_pstate=active"
27 | "acpi.ec_no_wakeup=1"
28 | # Force use of the thinkpad_acpi driver for backlight control.
29 | # This allows the backlight save/load systemd service to work.
30 | "acpi_backlight=native"
31 | # Needed for touchpad to work properly (click doesn't register by pushing down the touchpad).
32 | "psmouse.synaptics_intertouch=0"
33 | ];
34 | boot.kernelModules = [ "kvm-amd" ];
35 | boot.loader.grub.efiSupport = true;
36 | boot.loader.grub.useOSProber = true; # detect windows since thats on a partition here
37 | boot.loader.grub.devices = [ "/dev/nvme0n1" ];
38 |
39 | fileSystems."/" = {
40 | device = "/dev/disk/by-uuid/0bda9355-76f4-4b55-9012-0a14a73ac6b9";
41 | fsType = "ext4";
42 | };
43 |
44 | boot.initrd.luks.devices."luks-f400c0ed-57e0-4b5a-b701-c1a10c19480f".device = "/dev/disk/by-uuid/f400c0ed-57e0-4b5a-b701-c1a10c19480f";
45 |
46 | fileSystems."/boot" = {
47 | device = "/dev/disk/by-uuid/5A5A-DEFE";
48 | fsType = "vfat";
49 | options = [ "fmask=0077" "dmask=0077" ];
50 | };
51 |
52 | # external disk
53 | fileSystems."/home/${user.username}/external" = {
54 | device = "/dev/disk/by-uuid/18818348-1ee4-4fa5-9984-e4e01b9fa304";
55 | fsType = "ext4";
56 | };
57 |
58 | swapDevices = [];
59 |
60 | hardware.graphics = {
61 | enable = lib.mkDefault true;
62 | enable32Bit = lib.mkDefault true;
63 | };
64 |
65 | hardware.amdgpu.initrd.enable = lib.mkDefault true;
66 | networking.hostName = hostname;
67 |
68 | # enalbe fingerprinting services
69 | services.fprintd.enable = true;
70 | }
71 |
--------------------------------------------------------------------------------
/machines/smallbox/home.nix:
--------------------------------------------------------------------------------
1 | # WARNING : This file was generated by README.org
2 | # DO NOT MODIFY THIS FILE!
3 | # Any changes made here will be overwritten.
4 | { pkgs, ... } : {
5 | imports = [
6 | ../../home
7 | ];
8 |
9 | home.packages = with pkgs; [
10 | brightnessctl
11 | ];
12 |
13 | wayland.windowManager.hyprland.settings = {
14 | bind = [
15 | ", XF86MonBrightnessUp, exec, brightnessctl set 5%+"
16 | ", XF86MonBrightnessDown, exec, brightnessctl set 5%-"
17 | ", XF86AudioRaiseVolume, exec, wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%+"
18 | ", XF86AudioLowerVolume, exec, wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%-"
19 | ", XF86AudioMute, exec, wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle"
20 | ", XF86AudioMicMute, exec, wpctl set-mute @DEFAULT_AUDIO_SOURCE@ toggle"
21 | ];
22 |
23 | bindl = [
24 | '', switch:on:Lid Switch, exec, hyprctl keyword monitor "eDP-1, disable"''
25 | '', switch:off:Lid Switch, exec, hyprctl keyword monitor "eDP-1, preferred, 2560x0, 2"''
26 | ];
27 |
28 | monitor = [
29 | "desc:AOC Q3279WG5B 0x00000161, preferred, 0x0, 1, vrr, 2" # main monitor
30 | "eDP-1, preferred, 2560x0, 2" # laptop monitor
31 | ];
32 |
33 | workspace = [
34 | "1,monitor:desc:AOC Q3279WG5B 0x00000161, default:true"
35 | "2,monitor:desc:AOC Q3279WG5B 0x00000161, default:true"
36 | "3,monitor:desc:AOC Q3279WG5B 0x00000161, default:true"
37 | "5,monitor:eDP-1, default:true"
38 | "6,monitor:eDP-1, default:tru"e
39 | ];
40 |
41 | windowrule = [
42 | "workspace:1, class:firefox"
43 | "workspace:2, class:emacs"
44 | "workspace:5, class:Slack"
45 | ];
46 |
47 | exec-once = [
48 | "[workspace 1 silent] firefox"
49 | "[workspace 2 silent] emacs"
50 | "[workspace 5 silent] slack"
51 | ];
52 | };
53 | }
54 |
--------------------------------------------------------------------------------
/secrets/secrets.yaml:
--------------------------------------------------------------------------------
1 | claude_key: ENC[AES256_GCM,data:PMPcEfsKZCALRdgQf5J12k8IsxlNT7R+zfSgmy3LbVhvQQzpCEVr5Xjh6ABhDRGjsTssXc1Vh7FA03oud40i5YxoYwJ2i2EqrRmpp/QNVAfbPrOzfCcwUxlbgJOUEMVv/1RJFYeqddi+bf1F,iv:lD1bRtBtnBf0ub5mGznVuoxLcFcJhxdp+mGv5TMBcKQ=,tag:TP6YLujPHFmFnK5gWwTREg==,type:str]
2 | ssh:
3 | smallbox:
4 | private: ENC[AES256_GCM,data:YxDFGYAFJzayuxfE5hSXZXuWf8s1yqe/84vhOrrGVOvtuGZV8z63f47YtLwNBsi3zMs23cvygDRYO0SA9QujtNNBSiLff4lnD7T4sMAveSs6IrAu1PH4tYoJPSGnpuml6Llp9D3IjMxKZjYwan8DdJpk6nLLwvl9VjTQa3PJjUPiha866XvBaXWlwkr2sCcihVYE2MAk/ILStNKc2T89ScRXItkAk5fDuCpjlU9RA4g85HthND4NXyW19i7lvHXJHx4zkMyqTUSoPGYpdnCvMi0vvLxPgz/d4y60wtqdKluNaoEWoODFMqOz6082g8thki6wkfl779zcR09ZtSckWPcAkp1sUSjoLvvWFJgcGWcs+BJV7QwagKxNJv6t7tfKfMEPzK4OdFo/HcLt//BEXJtPlQZOd2/soXDKU9oCvGiWwIuzRu7Ynr5bAO+DJJH0BJDJqkapJFSOjiOsxMIz8nQX+XWe3vfKmAW7oq0RvhY63Tl/h3FI4tjU3BzUmE2p1pozq+iLWY9QM9EVevzDooYkqlO25wJqWg3HINMaKoH+i2Y=,iv:g59H/fJm3wukyjchUbB0r3KMxZhhu5k9AX45II2AY0Q=,tag:9wP+A+u3rvGYW9UlBVSVxQ==,type:str]
5 | public: ENC[AES256_GCM,data:fNnCb06n1/E10PzpaYENaUwPOEM7HN9ndei6r0eaiDyougpk8gyPszhKiObG5Qx9sQjt/KBWSgZkg2YcF65oj8HUK+AWqNuK8wARuxnecwCSXI1lRCflxMX1WuNsDR/2dZ5SDQQo9Q==,iv:JJhWdu4wr5KefTtkkea+dVhLyds03pf1ofDYGXwi/XY=,tag:zT3oRE1EXn4L5odALLTh0Q==,type:str]
6 | wavefunk:
7 | private: ENC[AES256_GCM,data:i6KQtOVZviAKIh8U8brH8UCZ6oJLloXzbPvL00j8P/F1ax2kr2ba2F04oGDMlukYhSNca3VIYsoB9BaHxlRJNfLfxcEQPOYPNS7LThl8mR0lLlI8V+zdbxN7hIKlSRI5WttvRGQsPkVjfqkA3SNqpATSESHCI1Y5NuxgyaZXxVVn4PKUSoM+qD50QIJ7np6ghl57UPl9jHOcVvtl7XTJILLaTjzBjlXQsW1txeNMnE2E2AiXDmL7ckBjqmqLQ9Qv3XugOwalBis6ITT2X6sjgApdcargH7GFKyfT+DP+GnjtfRZMkQFTlbdX4Duze5cGkTKOEhzkpM58uDefti5XD64NCBVBJTPSFepzC2BFswigtGur6XlUPbAiU6NVKx3P4MJAfFVUeeNZGRQwz2mQRYSqSaCjw81UmNSSfn+ug04vbHDimTnti1d0lJXEb5Kxre/w5ssHfgwexUWE2HJPNPXDeUGNMl/eqT1IrZ5wegBqrg4OpjVV7bcro4J930FCUDb82o9AIhT9oaMA3zXhKDmKCBIEjp0Ea9EU,iv:PMfGreR0RPjCy3cRRDRp6rjncQD1Ub0d9T8zZjh6Ojk=,tag:LLeMhNUcvHa6qgECEnlBfQ==,type:str]
8 | public: ENC[AES256_GCM,data:JRiSErA2GbIY95CVYwN1qOk4SsrN9R+f9oxp2SvcuqHtTBw7JYSpPmLmfgVojfazr0X69cZ6D473uj64TuKce2UR6gG4B7KXkXlSFgg6v79zfia1QZhL5GsMlObs+JCU4J0Ipg==,iv:zoad3D+x43rHdM+H5Ql+gOh7yr1P0ZVLLPeiPfNgTH4=,tag:YPA8bC96AzNgssbgftgS9g==,type:str]
9 | wavefunk_dev:
10 | private: ENC[AES256_GCM,data:mnCKG4wE98iiX9W+ahD2D/7c6oLty9XUHhUkdE4EkJzSowOiHoJeHGBQrETl39k84YVANPf1VkDiQDjdXsiA5JraXLfVcUKancPSlNDQotrtybngJSSYzFVS3046oMig8+C7RVpcHjbTK6rX1jgfLvUTTsYsdLcsRcQVO5fv6OrZ1rahrvLw+fM2V9g4R+a6K94AaPZqcChzcTCojeUzQBTZhWQUGkH03fps9ZHOp948kUGiURpo7kPEgQUo3KmBl3c9FQ8m0Im8Vs40EjNo6ywcqM4Dlz7fHdiDNVqK013SOMK/Erdo0ItQJWKofpW+XXKUmlt3+bDVGJ5pItrYPIjfu0kHyonE2SR6fqb1XACxXzFMkI3kcZLDr3VdToTufiArmDgPrrW7JNNxTgYCjEuXGOLPQ8VELAKZQwiWxKtR+C1SLrnDvUeHjLwZaQ8L2a9CYYbhT8/0C/zOIOBnaPYKG0Mt/6rpzH36hirtoJoVYU8gZvATfcwSPGeiWABV26/EJEwyPQ7ZertK5Ns0hfJcUw4qLRMwOS58,iv:RxYn4OLLTKPClZYVt2oBHwTkPWndmOtEAfQKUGnAQwc=,tag:eD7eYPeLKlipAjiTvFHivA==,type:str]
11 | public: ENC[AES256_GCM,data:ZHbpufd2N7B/pMjRrN5jPGvrLPdv5pM9llzN/EUkuBDowCbrU8/sItN04CF7W8+DkrXMxV6Mbcgv3H/LOtBiC/O5ZdDNOGOsDRNwv/YjP23qQ/Tx1YU+hJLnA+jvhTXWyXdj04OT,iv:5aBQSQbrlZT3G6Q+fjdXriDOHuO9WlSaHW7GqnRZ8Ck=,tag:LA5jT5Qqb+ZqrTuPLd1klw==,type:str]
12 | sops:
13 | age:
14 | - recipient: age1yq35g6mmlem0rhr47u6ewh8dctlwp9hj0s0ac60e4hrw9hjzlqms6crf7n
15 | enc: |
16 | -----BEGIN AGE ENCRYPTED FILE-----
17 | YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBnWWRBUlNqZWlqOHlVN3N0
18 | TjN1YldwRzAxTnBFS25LeUxsREpsUWI5UHlZCmN5aGI2OUFnVXc4aXl1bjltM2Vl
19 | d3daR1BzMG8ySEhyWWd2SUY4Rm9wRVkKLS0tIHN0L1BuNHl3bXZQSTJmdmkrN3Zz
20 | cGFUQWlzOCtFWVI0RGIxUm5PbDAyYWMKXYg9uTPFbHuEoe8XPOsV2qgS/ZKCJ9IG
21 | uwGcQPfvISTENUGS+aw5gRuJY058K9FRdPEq0lXjDaYwAQlb2lVI7A==
22 | -----END AGE ENCRYPTED FILE-----
23 | lastmodified: "2025-04-15T12:16:14Z"
24 | mac: ENC[AES256_GCM,data:poXj4Gb0RoiCiW8dfKgk5LB/jNHWpeZ19VvGtdnc8SHdvlTaRzlJlRJj1NC3mCak4wUHP15sTc1lv53eIEeQKpPVnCo7Pf64jrvY1W1Vfo8IAfLrt9ecYUhZMS3+rEHcvbHlkssg1SQ8/6miogHL2Asb8nSPArdSM04mNbKjzNo=,iv:m5oXElsO1HTg0KzNcl3//VtZGOQDhWdFKVpU7xHQGlU=,tag:khoZPqFolaVJETAAtsudsA==,type:str]
25 | unencrypted_suffix: _unencrypted
26 | version: 3.10.1
27 |
--------------------------------------------------------------------------------
/user.nix:
--------------------------------------------------------------------------------
1 | # WARNING : This file was generated by README.org
2 | # DO NOT MODIFY THIS FILE!
3 | # Any changes made here will be overwritten.
4 | {
5 | system = "x86_64-linux";
6 | username = "nambiar";
7 | stateVersion = "25.05";
8 | locale = "sv_SE.UTF-8";
9 | }
10 |
--------------------------------------------------------------------------------