Nixos is not your regular distro. Its “immutable” and “reproducible” and all that, things that most the of arch linux elites ignore before jumping into the nixos hype train. Instead of configuring your programs through ~/.config/appname
files, we do it through .nix
files. Instead of starting and stopping services with systemctl
, we do it through .nix
files. Instead of installing programs via a package manager, we do it through, you guessed it, .nix
files. Most of the linux youtubers and average users do not fully explore nixos before going back to their old distro. They just configure their stuff in a big and ugly configuration.nix
file. This blog will try to get you working hyprland
on a flake
powered nixos setup.
$ sudo nixos-rebuild switch# with flakes$ sudo nixos-rebuild switch --flake '/etc/nixos#frostbyte'
$ home-manager switch
# with flakes$ home-manager switch --flake '/etc/nixos#namish' # replace namish with your user
$ nix flake update
A nix flake is a directory with a flake.nix
and flake.lock
that returns Nix expressions that can be used to install packages, run programs or in out case, create a whole ass NixOs configuration. Each flake consists of two parts defined in the flake.nix
, inputs
and outputs
Inputs: inputs
are the equivalent of dependencies. They are the external resources or Flakes that a particular Flake needs to accomplish its tasks
Outpus: outputs
refer to the different results or artifacts that a Flake can produce when it’s built or evaluated. Think of them as the things that a Flake can create or provide. In this case it provides us with a nixos configuration
NixOS Flakes is a feature that enhances the Nix package manager’s capabilities by providing a structured and reproducible way to define and manage software packages and system configurations. It promotes consistency, immutability, and composability, making it particularly valuable for system administrators and developers who need to manage complex and reliable computing environments
Currently flakes is a beta experimental feature that we have to manually enable
{ pkgs, ... }: { nix.settings.experimental-features = [ "nix-command" "flakes" ];}
Then rebuild system with sudo nixos-rebuild switch
{ description = "i have no idea how this works";
inputs = { # Package sources. master.url = "github:nixos/nixpkgs/master"; stable.url = "github:nixos/nixpkgs/nixos-22.11"; unstable.url = "github:nixos/nixpkgs/nixos-unstable"; home-manager.url = "github:nix-community/home-manager"; nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; hyprland.url = "github:hyprwm/Hyprland"; spicetify-nix.url = "github:the-argus/spicetify-nix"; nixpkgs-f2k.url = "github:fortuneteller2k/nixpkgs-f2k"; hyprland-plugins.url = "github:hyprwm/hyprland-plugins";
# Channel to follow. home-manager.inputs.nixpkgs.follows = "unstable"; nixpkgs.follows = "unstable"; }; outputs = { self, nixpkgs, home-manager, hyprland, hyprland-plugins, ... } @inputs: let inherit (self) outputs; forSystems = nixpkgs.lib.genAttrs nixpkgs.lib.systems.flakeExposed; system = "x86_64-linux"; pkgs = import nixpkgs { inherit system; }; in { # host configurations nixosConfigurations = { frostbyte = nixpkgs.lib.nixosSystem { specialArgs = { inherit inputs outputs home-manager hyprland hyprland-plugins; }; modules = [ # > Our main nixos configuration file < home-manager.nixosModule ./hosts/frostbyte/configuration.nix ]; }; }; home-manager = home-manager.packages.${nixpkgs.system}."home-manager"; # user configurations homeConfigurations = { namish = home-manager.lib.homeManagerConfiguration { pkgs = nixpkgs.legacyPackages.x86_64-linux; # Home-manager requires 'pkgs' instance extraSpecialArgs = { inherit inputs outputs home-manager self; }; modules = [ ./home/namish/home.nix ]; }; }; frostbyte = self.nixosConfigurations.frostbyte.config.system.build.toplevel; };}
Now of course this will not work, we still have to configure home manager and our system. Be sure to replace namish
with your username.
This section is very important to understand. These two topics are really important to install programs that are not in the nix repos. In our config derivs will be placed at ./derivs
and overlays are at ./overlays/default.nix
At a basic level, deriviations are just a way to build packages on your system. The structure of a Nix derivation is a set of specifications and instructions that define how to build and package a software component within the Nix package management system
Common Pieces of a nix deriviation:
name = "example";version = "1.0";
tar
, github repo
, a url
or even local files src = fetchFromGitHub { owner = "ozwaldorf"; repo = "lutgen-rs"; rev = "621db41b10e5a1a923ef67094ce1fc05c618d6ae"; sha256 = "0dwj3cksf62z89ihqnhhxj1wgzjqqwlc40hwdfw18yqwr3byzfxf"; };
buildPhase = '' make'';
installPhase = '' make install'';
buildInputs = with pkgs;[ gcc autoconf ];
meta = with lib; { description = "An example software package"; license = licenses.mit;};
{ lib, buildPythonPackage, fetchFromGitHub, pkgs, ... }\:
buildPythonPackage rec { pname = "imagecolorizer"; version = "git"; preBuild = '' cat > setup.py << EOF from setuptools import setup setup( name='ImageColorizer', version='1.2', packages=['ImageColorizer'], entry_points = { 'console_scripts': ['ImageColorizer = ImageColorizer.__main__:main'] } ) EOF ''; propagatedBuildInputs = with pkgs;[ python310Packages.pillow ]; src = fetchFromGitHub { repo = "ImageColorizer"; owner = "kiddae"; rev = "48623031e3106261093723cd536a4dae74309c5d"; sha256 = "0ai4i3qmk55z3zc2gd8nicgx04pmfxl5wcq43ryy6l4c6gj2ik5r"; }; meta = { description = "ImageColorizer is a Python module and a CLI tool that you can easily use to colorize wallpapers for them to fit a terminal colorscheme."; homepage = "https://github.com/kiddae/ImageColorizer"; license = lib.licenses.mit; platforms = lib.platforms.unix; };}
{ lib, fetchFromGitHub, rustPlatform, pkgs }:rustPlatform.buildRustPackage rec { pname = "lutgen"; name = "lutgen";
src = fetchFromGitHub { owner = "ozwaldorf"; repo = "lutgen-rs"; rev = "621db41b10e5a1a923ef67094ce1fc05c618d6ae"; sha256 = "0dwj3cksf62z89ihqnhhxj1wgzjqqwlc40hwdfw18yqwr3byzfxf"; }; nativeBuildInputs = with pkgs;[ cargo rustc ]; cargoSha256 = "sha256-s5ejGEFMxDg+ENLg0Y1ZXgk2bDyy4H5C7tNMjVEp8kY=";}
Nix overlays are a mechanism in the Nix package manager that allows you to extend or modify the package set provided by the Nixpkgs repository. They are a way to add, replace, or customize packages and configurations without altering the global Nixpkgs repository. For example to use a custom fork of st we can make an overlay like this
{ inputs }:{ additions = final: _prev: import ../pkgs { pkgs = final; inherit inputs; }; modifications = final: prev: { # WE WILL ADD OUR OVERLAYS HERE st = prev.st.overrideAttrs (oldAttrs: { buildInputs = oldAttrs.buildInputs ++ [ prev.harfbuzz ]; src = prev.fetchFromGitHub { owner = "chadcat7"; repo = "st"; rev = "3d9eb51d43981963638a1b5a8a6aa1ace4b90fbb"; sha256 = "007pvimfpnmjz72is4y4g9a0vpq4sl1w6n9sdjq2xb2igys2jsyg"; }; }); };}
For this to work, you need ./nixpkgs.nix
and ./pkgs/default.nix
# A nixpkgs instance that is grabbed from the pinned nixpkgs commit in the lock file# This is useful to avoid using channels when using legacy nix commandslet lock = (builtins.fromJSON (builtins.readFile ./flake.lock)).nodes.nixpkgs.locked;inimport (fetchTarball { url = "https://github.com/nixos-unstable/nixpkgs/archive/${lock.rev}.tar.gz"; sha256 = lock.narHash;})
# Custom packages, that can be defined similarly to ones from nixpkgs# You can build them using 'nix build .#example' or (legacy) 'nix-build -A example'{ pkgs ? (import ../nixpkgs.nix) { }, inputs }: { # example = pkgs.callPackage ./example { };}
We can even use our deriviations to create an overlay
modifications = final: prev: { imgclr = prev.callPackage ../derivs/imagecolorizer.nix { buildPythonPackage = prev.python310Packages.buildPythonPackage; }; lutgen = prev.callPackage ../derivs/lutgen.nix { }; };
{ lib, buildPythonPackage, fetchFromGitHub, pkgs, ... }:
buildPythonPackage rec { pname = "imagecolorizer"; version = "git"; preBuild = '' cat > setup.py << EOF from setuptools import setup setup( name='ImageColorizer', version='1.2', packages=['ImageColorizer'], entry_points = { 'console_scripts': ['ImageColorizer = ImageColorizer.__main__:main'] } ) EOF ''; propagatedBuildInputs = with pkgs;[ python310Packages.pillow ]; src = fetchFromGitHub { repo = "ImageColorizer"; owner = "kiddae"; rev = "48623031e3106261093723cd536a4dae74309c5d"; sha256 = "0ai4i3qmk55z3zc2gd8nicgx04pmfxl5wcq43ryy6l4c6gj2ik5r"; }; meta = { description = "ImageColorizer is a Python module and a CLI tool that you can easily use to colorize wallpapers for them to fit a terminal colorscheme."; homepage = "https://github.com/kiddae/ImageColorizer"; license = lib.licenses.mit; platforms = lib.platforms.unix; };}
{ lib, fetchFromGitHub, rustPlatform, pkgs }:rustPlatform.buildRustPackage rec { pname = "lutgen"; name = "lutgen";
src = fetchFromGitHub { owner = "ozwaldorf"; repo = "lutgen-rs"; rev = "621db41b10e5a1a923ef67094ce1fc05c618d6ae"; sha256 = "0dwj3cksf62z89ihqnhhxj1wgzjqqwlc40hwdfw18yqwr3byzfxf"; }; nativeBuildInputs = with pkgs;[ cargo rustc ]; cargoSha256 = "sha256-s5ejGEFMxDg+ENLg0Y1ZXgk2bDyy4H5C7tNMjVEp8kY=";}
Nix overlays are a mechanism in the Nix package manager that allows you to extend or modify the package set provided by the Nixpkgs repository. They are a way to add, replace, or customize packages and configurations without altering the global Nixpkgs repository. For example to use a custom fork of st we can make an overlay like this
{ inputs }:{ additions = final: _prev: import ../pkgs { pkgs = final; inherit inputs; }; modifications = final: prev: { # WE WILL ADD OUR OVERLAYS HERE st = prev.st.overrideAttrs (oldAttrs: { buildInputs = oldAttrs.buildInputs ++ [ prev.harfbuzz ]; src = prev.fetchFromGitHub { owner = "chadcat7"; repo = "st"; rev = "3d9eb51d43981963638a1b5a8a6aa1ace4b90fbb"; sha256 = "007pvimfpnmjz72is4y4g9a0vpq4sl1w6n9sdjq2xb2igys2jsyg"; }; }); };}
For this to work, you need ./nixpkgs.nix
and ./pkgs/default.nix
# A nixpkgs instance that is grabbed from the pinned nixpkgs commit in the lock file# This is useful to avoid using channels when using legacy nix commandslet lock = (builtins.fromJSON (builtins.readFile ./flake.lock)).nodes.nixpkgs.locked;inimport (fetchTarball { url = "https://github.com/nixos-unstable/nixpkgs/archive/${lock.rev}.tar.gz"; sha256 = lock.narHash;})
# Custom packages, that can be defined similarly to ones from nixpkgs# You can build them using 'nix build .#example' or (legacy) 'nix-build -A example'{ pkgs ? (import ../nixpkgs.nix) { }, inputs }: { # example = pkgs.callPackage ./example { };}
We can even use our deriviations to create an overlay
modifications = final: prev: { ... imgclr = prev.callPackage ../derivs/imagecolorizer.nix { buildPythonPackage = prev.python310Packages.buildPythonPackage; }; lutgen = prev.callPackage ../derivs/lutgen.nix { };};
First we will make two directories, ./hosts/frostbyte
and ./hosts/shared
. The first one would be for the main system itself and shared would be for setttings that would be common for each system (if you have more than 1 devices)
Also copy your existing hardware-configuration.nix
to ./hosts/frostbyte/hardware-configuration.nix
This will consist of:
{ pkgs, outputs, overlays, lib, inputs, ... }:let # DEFINING VARIABLES flake-compat = builtins.fetchTarball "https://github.com/edolstra/flake-compat/archive/master.tar.gz";in{ # USING SYSTEMD-BOOT INSTEAD OF GRUB boot.loader.systemd-boot.enable = true; boot.loader.efi.canTouchEfiVariables = true; boot.loader.efi.efiSysMountPoint = "/boot/efi"; programs.zsh.enable = true;
# REQUIRED TO ENABLE SWAYLOCK TO AUTHENTICATE PASSWORDS security.pam.services.swaylock = { text = '' auth include login ''; }; networking = { networkmanager.enable = true; firewall.enable = false; }; security = { sudo.enable = true; }; services.blueman = { enable = true; };
# SETTING TIME ZONE time = { hardwareClockInLocalTime = true; timeZone = "Asia/Kolkata"; }; i18n.defaultLocale = "en_US.UTF-8"; console = { font = "Lat2-Terminus16"; useXkbConfig = true; }; users = { users.namish = { isNormalUser = true; extraGroups = [ "wheel" "networkmanager" "audio" "video" "libvirtd" ]; packages = with pkgs; [ ]; }; defaultUserShell = pkgs.zsh; }; fonts.packages = with pkgs; [ inter dosis rubik ibm-plex (nerdfonts.override { fonts = [ "Iosevka" "CascadiaCode" "JetBrainsMono" ]; }) ]; # STILL USING PULSEAUDIO (SOWWY) sound.enable = true; hardware.pulseaudio.enable = true; hardware.pulseaudio.extraConfig = "load-module module-native-protocol-tcp auth-ip-acl=127.0.0.1"; security.rtkit.enable = true; virtualisation = { libvirtd.enable = true; }; services.dbus.enable = true; xdg.portal = { enable = true; wlr.enable = true; # gtk portal needed to make gtk apps happy extraPortals = [ pkgs.xdg-desktop-portal-gtk ]; };
environment.systemPackages = with pkgs; [ nodejs lutgen home-manager blueman inotify-tools udiskie rnix-lsp xorg.xwininfo pulseaudio libnotify xdg-utils gtk3 jq st spotdl discord firefox unzip imgclr grim eww-wayland wayland swaylock-effects swaybg git pstree mpv xdotool spotify brightnessctl pamixer nix-prefetch-git python3 brillo slop ripgrep maim wirelesstools xorg.xf86inputevdev xorg.xf86inputsynaptics xorg.xf86inputlibinput xorg.xorgserver xorg.xf86videoati ]; # SETTING THE DEFAULT SHELL environment.shells = with pkgs; [ zsh ];
programs.dconf.enable = true; qt = { enable = true; platformTheme = "gtk2"; style = "gtk2"; };
# PRINTING // BLUETOOTH services.printing.enable = true; hardware.bluetooth = { enable = true; powerOnBoot = false; }; services.xserver = { layout = "us"; xkbVariant = "us,"; }; security.polkit.enable = true; nix = { settings = { experimental-features = [ "nix-command" "flakes" ]; trusted-users = [ "root" "@wheel" ]; auto-optimise-store = true; warn-dirty = false; }; gc = { ## AUTOMATICALLY DELETEING OLD BUILDS AFTER 5 DAYS automatic = true; options = "--delete-older-than 5d"; }; optimise.automatic = true; }; system = { copySystemConfiguration = false; stateVersion = "22.11"; };}
Now this is used for:
BONUS — also learn how to install awesomewm
{ inputs, outputs, config, pkgs, lib, self, ... }:{
imports = [ ./hardware-configuration.nix ../shared ];
nixpkgs = { overlays = [ outputs.overlays.modifications outputs.overlays.additions inputs.nixpkgs-f2k.overlays.stdenvs inputs.nixpkgs-f2k.overlays.compositors (final: prev: { awesome = inputs.nixpkgs-f2k.packages.${pkgs.system}.awesome-git; }) ]; config = { # Disable if you don't want unfree packages allowUnfreePredicate = _: true; allowUnfree = true; }; };
networking.hostName = "frostbyte"; networking.useDHCP = false; networking.interfaces.wlo1.useDHCP = true; boot.kernelPackages = pkgs.linuxPackages_5_15; environment.systemPackages = lib.attrValues { inherit (pkgs) brightnessctl wayland android-tools; };
services = { gvfs.enable = true; power-profiles-daemon.enable = false; tlp.enable = true; upower.enable = true; xserver = { enable = true; videoDrivers = [ "amdgpu" ]; libinput = { enable = true; touchpad = { tapping = true; middleEmulation = true; naturalScrolling = true; }; }; displayManager = { defaultSession = "none+awesome"; startx.enable = true; }; windowManager.awesome = { enable = true;
}; desktopManager.gnome.enable = false; }; };}
If you are wondering, we will be installing hyprland
via home-manager
Home Manager gives you control over the user’s home environment. Home-Manager fosters user-specific profiles, accommodating distinct configurations for different users on the same system. Each user can have their own tailored environment, making it versatile and adaptable for both personal and multi-user systems
For this too, we will make two directories ./home/USER
(replace USER with your username) and ./home/shared
. The first one would be for user itself and shared would be for setttings that would be common for each user
{}:rec { wallpaper = "birdseye.jpg"; foreground = "d7e0e0"; cursorColor = "d7e0e0"; background = "0a1011"; darker = "080c0d";
color0 = "0d1617"; color8 = "253336";
color1 = "df5b61"; color9 = "f16269";
color2 = "6ec587"; color10 = "8dd5a0";
color3 = "de8c6a"; color11 = "e59575";
color4 = "659bdb"; color12 = "739bdf";
color5 = "c167d9"; color13 = "d16ee0";
color6 = "6fd1d5"; color14 = "7bd3e0";
color7 = "c5d7d7"; color15 = "cedcd9";
bg2 = "101a1b"; mbg = "0e1718";
contrast = "111a1b"; cursorline = "111a1b";
comment = "505758"; name = "wave"; neofetchpic = "verycool.png";}
This is how the theme looks on awesome
rec
is the programming equivalent of return
. Now we can use this file to get the colors, whereever we want
{ inputs, config, pkgs, lib, ... }:let spicetify-nix = inputs.spicetify-nix; colors = import ../shared/cols/wave.nix { }; hyprland = inputs.hyprland; hyprland-plugins = inputs.hyprland-plugins; unstable = import (builtins.fetchTarball "https://github.com/nixos/nixpkgs/archive/master.tar.gz") { config = config.nixpkgs.config; }; nixpkgs-f2k = inputs.nixpkgs-f2k;in{ # some general info home.username = "namish"; home.homeDirectory = "/home/namish"; home.stateVersion = "22.11"; programs.home-manager.enable = true; home.file.".icons/default".source = "${pkgs.phinger-cursors}/share/icons/phinger-cursors";
nixpkgs.overlays = [ ]; imports = [ ]; ## THIS CODE IS RUN WHENEVER HOME MANAGER REBUILDS THE HOME DIRECTORY home = { activation = { installConfig = '' if [ ! -d "${config.home.homeDirectory}/.config/nvim" ]; then ${pkgs.git}/bin/git clone --depth 1 https://github.com/chadcat7/kodo ${config.home.homeDirectory}/.config/nvim fi ''; ## if there is no ~/.config/nvim, git clone my nvim config }; packages = with pkgs; [ bc chromium dunst wl-clipboard sway-contrib.grimshot xss-lock htop recode gcc go gopls playerctl scc cinnamon.nemo neofetch rust-analyzer hsetroot notion-app-enhanced mpc-cli pfetch ffmpeg_5-full neovim xdg-desktop-portal imagemagick procps killall moreutils cava mpdris2 socat pavucontrol fzf feh exa ]; };
## IMPORTANT nixpkgs.config = { allowUnfree = true; allowBroken = true; allowUnfreePredicate = _: true; };}
{ colors }:
with colors; { xresources = { path = ".Xresources"; extraConfig = '' ''; properties = { "*.background" = "#${background}"; "*.darker" = "#${darker}"; "*.color0" = "#${color0}"; "*.color8" = "#${color8}"; "*.color7" = "#${color7}"; "*.color15" = "#${color15}"; "*.foreground" = "#${foreground}"; "*.color1" = "#${color1}"; "*.color9" = "#${color9}"; "*.color2" = "#${color2}"; "*.color10" = "#${color10}"; "*.color3" = "#${color3}"; "*.color11" = "#${color11}"; "*.color4" = "#${color4}"; "*.color12" = "#${color12}"; "*.color5" = "#${color5}"; "*.color13" = "#${color13}"; "*.color6" = "#${color6}"; "*.color14" = "#${color14}"; "*.contrast" = "#${contrast}"; "*.cursorline" = "#${cursorline}"; "*.comment" = "#${comment}"; "st.borderpx" = 32; }; };}
I think this piece of code pretty self explanantory
imports = [ (import ../shared/xresources.nix { inherit colors; })];
And then also import it
The only thing we have to do for installing hyprland is enable it. (now that i read this sentence again, it feels really dumb). Anyways create file ./home/USER/conf/ui/hyprland/default.nix
{ config, lib, pkgs, hyprland, colors, ... }:
{ systemd.user.targets.hyprland-session.Unit.Wants = [ "xdg-desktop-autostart.target" ]; wayland.windowManager.hyprland = with colors; { enable = true; package = hyprland.packages.${pkgs.system}.hyprland; systemdIntegration = true; extraConfig = '' ..... exec = swaybg -i ~/.wallpapers/${name}/${wallpaper} & ..... ''; };}
This was done considering you have wallpapers in .wallpapers/wave/wallpaper.png
or something like that. And also do not forget to add in your extra config duh. 😑
And then import this file in your home.nix
imports = [ ... (import ./conf/ui/hyprland/default.nix { inherit config pkgs lib hyprland colors; })];
Instead of using the waybar in official nix packages repositories, we will use the one available from hyprland
flake input we used.
{ config, lib, pkgs, hyprland, colors, ... }:
{ programs.waybar = with colors; { enable = true; package = hyprland.packages.${pkgs.system}.waybar-hyprland; systemd = { enable = false; target = "graphical-session.target"; }; style = '' window#waybar { background-color: #${background}; color: #${foreground}; border-bottom: none; } * { font-size: 16px; min-height: 0; font-family: "Iosevka Nerd Font", "Material Design Icons Desktop"; } .... ''; settings = [{ height = 35; layer = "top"; position = "top"; tray = { spacing = 10; }; modules-center = [ "clock" ]; modules-left = [ "hyprland/workspaces" ]; modules-right = [ "network" "tray" ]; "hyprland/workspaces" = { on-click = "activate"; all-outputs = true; format = "{icon}"; disable-scroll = true; active-only = false; format-icons = { default = " "; persistent = " "; focused = " "; }; persistent_workspaces = { "1" = [ ]; "2" = [ ]; "3" = [ ]; "4" = [ ]; "5" = [ ]; }; }; clock = { format = "{:%d %A %H:%M}"; tooltip-format = "{:%Y-%m-%d | %H:%M}"; }; network = { interval = 1; on-click = "eww open --toggle control"; format-disconnected = " "; format-wifi = " "; }; "custom/power" = { on-click = "powermenu &"; format = " "; }; }]; };}
and ofc import this too
imports = [ ... (import ./conf/utils/dunst/default.nix { inherit colors pkgs; })];
Wezterm may not be the most minimal terminal, but is still better than that bloated piece of shit. Yes I have changed my terminal yet again. (future blog probably soon). Wezterms font rendering is the most alike to ST and it can also change colorschemes instantly, also has ligature support, and much more. (and i am not even using the git version). Create a directory ./home/USER/conf/term/wezterm
and create two files default.nix
and colors.nix
{ colors, ... }:with colors; { followSystem = { # basic colors background = "#${background}"; cursor_bg = "#${foreground}"; cursor_border = "#${foreground}"; cursor_fg = "#${color8}"; foreground = "#${foreground}"; selection_bg = "#${color15}"; selection_fg = "#${background}"; split = "#${mbg}";
# base16 ansi = [ "#${color0}" "#${color1}" "#${color2}" "#${color3}" "#${color4}" "#${color5}" "#${color6}" "#${color7}" ]; brights = [ "#${color8}" "#${color9}" "#${color10}" "#${color11}" "#${color12}" "#${color13}" "#${color14}" "#${color15}" ];
# tabbar tab_bar = { background = "#${color8}"; active_tab = { bg_color = "#${background}"; fg_color = "#${foreground}"; }; inactive_tab = { bg_color = "#${color8}"; fg_color = "#${foreground}"; }; inactive_tab_hover = { bg_color = "#${color0}"; fg_color = "#${foreground}"; }; inactive_tab_edge = "#${color0}"; new_tab = { bg_color = "#${color8}"; fg_color = "#${color7}"; }; new_tab_hover = { bg_color = "#${color0}"; fg_color = "#${foreground}"; }; }; };}
{ pkgs, colors, ... }:
with colors; { programs.wezterm = { enable = true; colorSchemes = import ./colors.nix { inherit colors; }; extraConfig = '' local wez = require('wezterm') return { default_prog = { 'zsh' }, cell_width = 0.85, front_end = "OpenGL", enable_wayland = true, scrollback_lines = 1024, font = wez.font_with_fallback({ "Iosevka Nerd Font", "Material Design Icons", }), dpi = 96.0, bold_brightens_ansi_colors = true, font_rules = { { italic = true, font = wez.font("Iosevka Nerd Font", { italic = true }) } }, font_size = 14.0, line_height = 1.15, harfbuzz_features = { 'calt=1', 'clig=1', 'liga=1' }, color_scheme = "followSystem", window_padding = { left = "24pt", right = "24pt", bottom = "24pt", top = "24pt" }, default_cursor_style = "SteadyUnderline", enable_scroll_bar = false, warn_about_missing_glyphs = false, enable_tab_bar = true, use_fancy_tab_bar = false, hide_tab_bar_if_only_one_tab = true, show_tab_index_in_tab_bar = false, window_close_confirmation = "NeverPrompt", inactive_pane_hsb = { saturation = 1.0, brightness = 0.8 }, check_for_updates = false, } ''; };}
imports = [ ... (import ./conf/term/wezterm/default.nix { inherit pkgs colors; })];
For notifications, there are now many options for wayland but I am still going to be using dunst because I had the least trouble configuring it. Nix considers dunst
to be service instead of program, therefore, programs.dunst
becomes services.dunst
. The configuration file for dunst will be at ./home/USER/conf/utils/dunst/default.nix
{ colors, pkgs }: with colors;{ services.dunst = { enable = true; settings = { global = { follow = "mouse"; width = 500; origin = "top-center"; alignment = "left"; vertical_alignment = "center"; ellipsize = "middle"; offset = "15x15"; padding = 15; horizontal_padding = 15; text_icon_padding = 15; icon_position = "left"; min_icon_size = 48; max_icon_size = 64; progress_bar = true; progress_bar_height = 8; progress_bar_frame_width = 1; progress_bar_min_width = 150; progress_bar_max_width = 300; separator_height = 2; frame_width = 2; frame_color = "#${mbg}"; separator_color = "frame"; corner_radius = 8; transparency = 0; gap_size = 8; line_height = 0; notification_limit = 0; idle_threshold = 120; history_length = 20; show_age_threshold = 60; markup = "full"; font = "Iosevka Nerd Font 12"; word_wrap = "yes"; sort = "yes"; shrink = "no"; indicate_hidden = "yes"; sticky_history = "yes"; ignore_newline = "no"; show_indicators = "no"; stack_duplicates = true; always_run_script = true; hide_duplicate_count = false; ignore_dbusclose = false; force_xwayland = false; force_xinerama = false; mouse_left_click = "do_action"; mouse_middle_click = "close_all"; mouse_right_click = "close_current"; };
fullscreen_delay_everything = { fullscreen = "delay"; }; urgency_low = { timeout = 3; background = "#${background}"; foreground = "#${foreground}"; highlight = "#${color4}"; }; urgency_normal = { timeout = 6; background = "#${background}"; foreground = "#${foreground}"; highlight = "#${color4}"; }; urgency_critical = { timeout = 0; background = "#${background}"; foreground = "#${foreground}"; highlight = "#${color9}"; }; }; };
}
and the tradition continues
imports = [ ... (import ./conf/ui/waybar/default.nix { inherit config pkgs lib hyprland colors; }) ];
zsh is my preferred shell (sorry fish noobs) so i will cover how to configure use zsh, create a file ./home/USER/conf/shell/zsh/default.nix
{ config, colors, pkgs, lib, ... }:
{ programs.zsh = { enable = true; enableAutosuggestions = true; syntaxHighlighting.enable = true; enableCompletion = true; history = { expireDuplicatesFirst = true; save = 512; }; initExtra = '' bindkey "^[[H" beginning-of-line bindkey "^[[4\~" end-of-line bindkey "^[[3\~" delete-char export PATH=${config.home.homeDirectory}/.local/bin:${config.home.homeDirectory}/.local/share/nvim/mason/bin:$PATH ''; };
}
** ADDING PLUGINS- **
Instead of using something like zplug, zgen, zpm, we will just install them, through, you guessed it, nix. We will use this to install powerlevel10k
programs.zsh = { plugins = [ { name = "powerlevel10k"; src = pkgs.zsh-powerlevel10k; file = "share/zsh-powerlevel10k/powerlevel10k.zsh-theme"; } { name = "powerlevel10k-config"; src = lib.cleanSource ./conf; file = "powerlevel.zsh"; } ];};
You will also need ./conf/shell/zsh/conf/powerlevel.zsh
which tou can get from here
SHELL ALIASES-
Instead of adding aliases in initExtra
we will do this
programs.zsh = { shellAliases = { la = "exa -l"; ls = "ls --color=auto"; v = "nvim"; nf = "neofetch"; suda = "sudo -E -s"; nix-pkgs = "nix --extra-experimental-features 'nix-command flakes' search nixpkgs"; };
}
And in the end:
imports = [ ... (import ./conf/shell/zsh/default.nix { inherit config colors pkgs lib; }) ];
This section will teach you how to set up mpd, ncmpcpp and playerctl on your system. It plays audio files, organizes playlists and maintains a music database, all while using very few resources. In order to interface with it, a separate client is needed. The client here is ncmpcpp
Here is the mpd configuration in nix
{ config, pkgs }:
{ services.mpd = { enable = true; musicDirectory = "${config.home.homeDirectory}/Music"; dataDir = "${config.home.homeDirectory}/.config/mpd"; extraConfig = '' auto_update "yes" restore_paused "yes" audio_output { type "pulse" name "Pulseaudio" server "127.0.0.1" # add this line - MPD must connect to the local sound server }
audio_output { type "fifo" name "Visualizer" format "44100:16:2" path "/tmp/mpd.fifo" } audio_output { type "httpd" name "lossless" encoder "flac" port "8000" max_client "8" mixer_type "software" format "44100:16:2" } ''; network.startWhenNeeded = true;
# Allows mpd to work with playerctl. home.packages = [ pkgs.playerctl ]; services.mpdris2.enable = true; services.playerctld.enable = true; };}
According to the arch wiki: Ncmpcpp is an mpd client (compatible with mopidy) with a UI very similar to ncmpc, but it provides new useful features such as support for regular expressions for library searches, extended song format, items filtering, the ability to sort playlists, and a local filesystem browser.
For ncmpcpp
{config, pkgs }:{ programs.ncmpcpp = { enable = true; package = pkgs.ncmpcpp.override { visualizerSupport = true; clockSupport = true; taglibSupport = true; }; mpdMusicDir = "${config.home.homeDirectory}/Music"; settings = { # Miscelaneous ncmpcpp_directory = "${config.home.homeDirectory}/.config/ncmpcpp"; ignore_leading_the = true; external_editor = "nvim"; message_delay_time = 1; playlist_disable_highlight_delay = 2; autocenter_mode = "yes"; centered_cursor = "yes"; allow_for_physical_item_deletion = "no"; lines_scrolled = "0"; follow_now_playing_lyrics = "yes"; lyrics_fetchers = "musixmatch";
# visualizer visualizer_data_source = "/tmp/mpd.fifo"; visualizer_output_name = "mpd_visualizer"; visualizer_type = "ellipse"; visualizer_look = "●●"; visualizer_color = "blue, green";
# appearance colors_enabled = "yes"; playlist_display_mode = "classic"; user_interface = "classic"; volume_color = "white";
# window song_window_title_format = "Music"; statusbar_visibility = "no"; header_visibility = "no"; titles_visibility = "no"; # progress bar progressbar_look = "━━━"; progressbar_color = "black"; progressbar_elapsed_color = "blue";
# song list song_status_format = "$7%t"; song_list_format = "$(008)%t$R $(247)%a$R$5 %l$8"; song_columns_list_format = "(53)[blue]{tr} (45)[blue]{a}";
current_item_prefix = "$b$2| "; current_item_suffix = "$/b$5";
now_playing_prefix = "$b$5| "; now_playing_suffix = "$/b$5";
# colors main_window_color = "blue";
current_item_inactive_column_prefix = "$b$5"; current_item_inactive_column_suffix = "$/b$5";
color1 = "white"; color2 = "blue"; }; };}
to write on a file on rebuilding home manager you can use home.file
for eg writing the .xinitrc
file
{}:{ home.file.".xinitrc".text = '' #!/usr/bin/env bash exec dbus-run-session awesome '';}
you can also make bin files with this, just set executable
to true
{ colors }:{ home.file.".local/bin/lock" = { executable = true; text = '' #!/bin/sh playerctl pause sleep 0.2 swaylock -i ~/.config/awesome/theme/wallpapers/${colors.name}/${colors.wallpaper} --effect-blur 10x10 ''; };}
For dynamic themeing, we will just use phocus and then just subsititute the colors with patches. You are recommended to get your patches from here. So this is the derivation we need for it -
{ stdenvNoCC, fetchFromGitHub, nodePackages, colors,}:stdenvNoCC.mkDerivation rec { pname = "phocus"; version = "0cf0eb35a927bffcb797db8a074ce240823d92de";
src = fetchFromGitHub { owner = "phocus"; repo = "gtk"; rev = version; sha256 = "sha256-URuoDJVRQ05S+u7mkz1EN5HWquhTC4OqY8MqAbl0crk="; };
patches = [ ../patches/npm.diff ../patches/gradients.diff ../patches/substitute.diff ];
postPatch = '' substituteInPlace scss/gtk-3.0/_colors.scss \ --replace "@bg0@" "#${colors.background}" \ --replace "@bg1@" "#${colors.contrast}" \ --replace "@bg2@" "#${colors.color8}"\ --replace "@bg3@" "#${colors.color0}" \ --replace "@bg4@" "#${colors.comment}" \ --replace "@red@" "#${colors.color1}" \ --replace "@lred@" "#${colors.color9}" \ --replace "@orange@" "#${colors.color3}" \ --replace "@lorange@" "#${colors.color11}" \ --replace "@yellow@" "#${colors.color3}" \ --replace "@lyellow@" "#${colors.color11}" \ --replace "@green@" "#${colors.color2}" \ --replace "@lgreen@" "#${colors.color10}" \ --replace "@cyan@" "#${colors.color6}" \ --replace "@lcyan@" "#${colors.color15}" \ --replace "@blue@" "#${colors.color4}" \ --replace "@lblue@" "#${colors.color12}" \ --replace "@purple@" "#${colors.color5}" \ --replace "@lpurple@" "#${colors.color14}" \ --replace "@pink@" "#${colors.color5}" \ --replace "@lpink@" "#${colors.color14}" \ --replace "@primary@" "#${colors.foreground}" \ --replace "@secondary@" "#${colors.color15}" '';
nativeBuildInputs = [ nodePackages.sass ]; installFlags = [ "DESTDIR=$(out)" "PREFIX=" ];}
And then we can call it in the home.nix file
gtk = { enable = true; gtk3.extraConfig.gtk-decoration-layout = "menu:"; theme.name = "phocus"; };
Nix-shell is a command-line tool and concept within the Nix package manager that enables the creation of isolated development environments for software projects. It allows developers to specify the exact dependencies and environment required for a project, ensuring consistency and reproducibility across different systems and projects.
Here is an example shell.nix
{ pkgs ? import <nixpkgs> {} }: pkgs.mkShell { # nativeBuildInputs is usually what you want -- tools you need to run nativeBuildInputs = with pkgs.buildPackages; [ lua52Packages.lua cmake gcc pam gnumake ];}
To enter the shell we will use
$ nix-shell shell.nix
whew, if you made it there, i hope you learned something from this. if there is an error you can contact me at discord @ chadcat7
. For a reference you can check out my dots
Namish Pande