Ports the classic dotfiles Omarchy setup to a no-home-manager NixOS
system module (configs/omarchy.nix), scoped to straylight only so the
other desktop hosts keep i3.
- Hyprland (programs.hyprland) becomes the default lightdm session; i3
stays enabled and selectable as a fallback.
- Omarchy config layout under ~/.config/{hypr,waybar,rofi,wlogout,
swayosd,alacritty} symlinked from the store; mutable theme/wallpaper
state in ~/.config/omarchy/current.
- omarchy-dots generates 8 themes (hyprland/hyprlock/waybar/rofi/
swayosd/wlogout/alacritty/mako colour files) from each theme's
palette, with wallpapers fetched from the Omarchy v3.8.4 tag.
- Helper scripts: omarchy-theme-set/bg-next/bg-set/apply, omarchy-menu
(rofi power/theme/background menus), waybar toggle, screenshot, lock.
- Shared desktop modules (desktop.nix / desktop-light.nix) untouched.
345 lines
14 KiB
Nix
345 lines
14 KiB
Nix
# Omarchy-style Hyprland desktop (classic dotfiles Omarchy, ported to a
|
|
# no-home-manager NixOS system module). Imported ONLY by hw/straylight, so
|
|
# the other desktop hosts (imladris, ono-sendai) keep i3.
|
|
#
|
|
# Layout mirrors Omarchy v3:
|
|
# ~/.config/{hypr,waybar,rofi,wlogout,swayosd,alacritty} -> read-only store links
|
|
# ~/.local/share/omarchy -> store payload (themes/, bin/)
|
|
# ~/.config/omarchy/current/ -> mutable state
|
|
# (theme + background)
|
|
#
|
|
# Theme colours are generated at build time from each theme's palette
|
|
# (Omarchy themes/<name>/colors.toml) into themes/<name>/{hyprland.conf,
|
|
# hyprlock.conf,waybar.css,rofi.rasi,swayosd.css,wlogout.css,alacritty.toml,
|
|
# mako.ini}. Wallpapers are fetched from the Omarchy v3.8.4 tag.
|
|
|
|
{ config, lib, pkgs, ... }:
|
|
let
|
|
inherit (lib) mkForce mapAttrsToList concatMapStrings;
|
|
|
|
user = "kyle";
|
|
home = "/home/${user}";
|
|
omarchyPath = "${home}/.local/share/omarchy";
|
|
current = "${home}/.config/omarchy/current";
|
|
defaultTheme = "tokyo-night";
|
|
|
|
# ---- Omarchy themes/*/colors.toml ----
|
|
themes = {
|
|
tokyo-night = {
|
|
accent = "#7aa2f7"; cursor = "#c0caf5"; foreground = "#a9b1d6"; background = "#1a1b26";
|
|
selection_foreground = "#c0caf5"; selection_background = "#7aa2f7";
|
|
color0 = "#32344a"; color1 = "#f7768e"; color2 = "#9ece6a"; color3 = "#e0af68";
|
|
color4 = "#7aa2f7"; color5 = "#ad8ee6"; color6 = "#449dab"; color7 = "#787c99";
|
|
color8 = "#444b6a"; color9 = "#ff7a93"; color10 = "#b9f27c"; color11 = "#ff9e64";
|
|
color12 = "#7da6ff"; color13 = "#bb9af7"; color14 = "#0db9d7"; color15 = "#acb0d0";
|
|
};
|
|
catppuccin = {
|
|
accent = "#89b4fa"; cursor = "#f5e0dc"; foreground = "#cdd6f4"; background = "#1e1e2e";
|
|
selection_foreground = "#1e1e2e"; selection_background = "#f5e0dc";
|
|
color0 = "#45475a"; color1 = "#f38ba8"; color2 = "#a6e3a1"; color3 = "#f9e2af";
|
|
color4 = "#89b4fa"; color5 = "#f5c2e7"; color6 = "#94e2d5"; color7 = "#bac2de";
|
|
color8 = "#585b70"; color9 = "#f38ba8"; color10 = "#a6e3a1"; color11 = "#f9e2af";
|
|
color12 = "#89b4fa"; color13 = "#f5c2e7"; color14 = "#94e2d5"; color15 = "#a6adc8";
|
|
};
|
|
gruvbox = {
|
|
accent = "#7daea3"; cursor = "#bdae93"; foreground = "#d4be98"; background = "#282828";
|
|
selection_foreground = "#ebdbb2"; selection_background = "#d65d0e";
|
|
color0 = "#3c3836"; color1 = "#ea6962"; color2 = "#a9b665"; color3 = "#d8a657";
|
|
color4 = "#7daea3"; color5 = "#d3869b"; color6 = "#89b482"; color7 = "#d4be98";
|
|
color8 = "#3c3836"; color9 = "#ea6962"; color10 = "#a9b665"; color11 = "#d8a657";
|
|
color12 = "#7daea3"; color13 = "#d3869b"; color14 = "#89b482"; color15 = "#d4be98";
|
|
};
|
|
kanagawa = {
|
|
accent = "#7e9cd8"; cursor = "#c8c093"; foreground = "#dcd7ba"; background = "#1f1f28";
|
|
selection_foreground = "#c8c093"; selection_background = "#2d4f67";
|
|
color0 = "#090618"; color1 = "#c34043"; color2 = "#76946a"; color3 = "#c0a36e";
|
|
color4 = "#7e9cd8"; color5 = "#957fb8"; color6 = "#6a9589"; color7 = "#c8c093";
|
|
color8 = "#727169"; color9 = "#e82424"; color10 = "#98bb6c"; color11 = "#e6c384";
|
|
color12 = "#7fb4ca"; color13 = "#938aa9"; color14 = "#7aa89f"; color15 = "#dcd7ba";
|
|
};
|
|
everforest = {
|
|
accent = "#7fbbb3"; cursor = "#d3c6aa"; foreground = "#d3c6aa"; background = "#2d353b";
|
|
selection_foreground = "#2d353b"; selection_background = "#d3c6aa";
|
|
color0 = "#475258"; color1 = "#e67e80"; color2 = "#a7c080"; color3 = "#dbbc7f";
|
|
color4 = "#7fbbb3"; color5 = "#d699b6"; color6 = "#83c092"; color7 = "#d3c6aa";
|
|
color8 = "#475258"; color9 = "#e67e80"; color10 = "#a7c080"; color11 = "#dbbc7f";
|
|
color12 = "#7fbbb3"; color13 = "#d699b6"; color14 = "#83c092"; color15 = "#d3c6aa";
|
|
};
|
|
nord = {
|
|
accent = "#81a1c1"; cursor = "#d8dee9"; foreground = "#d8dee9"; background = "#2e3440";
|
|
selection_foreground = "#d8dee9"; selection_background = "#4c566a";
|
|
color0 = "#3b4252"; color1 = "#bf616a"; color2 = "#a3be8c"; color3 = "#ebcb8b";
|
|
color4 = "#81a1c1"; color5 = "#b48ead"; color6 = "#88c0d0"; color7 = "#e5e9f0";
|
|
color8 = "#4c566a"; color9 = "#bf616a"; color10 = "#a3be8c"; color11 = "#ebcb8b";
|
|
color12 = "#81a1c1"; color13 = "#b48ead"; color14 = "#8fbcbb"; color15 = "#eceff4";
|
|
};
|
|
rose-pine = {
|
|
accent = "#56949f"; cursor = "#cecacd"; foreground = "#575279"; background = "#faf4ed";
|
|
selection_foreground = "#575279"; selection_background = "#dfdad9";
|
|
color0 = "#f2e9e1"; color1 = "#b4637a"; color2 = "#286983"; color3 = "#ea9d34";
|
|
color4 = "#56949f"; color5 = "#907aa9"; color6 = "#d7827e"; color7 = "#575279";
|
|
color8 = "#9893a5"; color9 = "#b4637a"; color10 = "#286983"; color11 = "#ea9d34";
|
|
color12 = "#56949f"; color13 = "#907aa9"; color14 = "#d7827e"; color15 = "#575279";
|
|
};
|
|
hackerman = {
|
|
accent = "#82FB9C"; cursor = "#ddf7ff"; foreground = "#ddf7ff"; background = "#0B0C16";
|
|
selection_foreground = "#0B0C16"; selection_background = "#ddf7ff";
|
|
color0 = "#3E4058"; color1 = "#50f872"; color2 = "#4fe88f"; color3 = "#50f7d4";
|
|
color4 = "#829dd4"; color5 = "#86a7df"; color6 = "#7cf8f7"; color7 = "#85E1FB";
|
|
color8 = "#6a6e95"; color9 = "#85ff9d"; color10 = "#9cf7c2"; color11 = "#a4ffec";
|
|
color12 = "#c4d2ed"; color13 = "#cddbf4"; color14 = "#d1fffe"; color15 = "#ddf7ff";
|
|
};
|
|
};
|
|
|
|
# ---- Omarchy themes/<name>/backgrounds/<file> (v3.8.4) ----
|
|
wallpapers = {
|
|
tokyo-night = [
|
|
{ file = "1-sunset-lake.png"; hash = "sha256-Bt+5/OAp7DWttA6jk5KWd3wrFA0SMrWhaXsVBS1XU2I="; }
|
|
{ file = "2-pawel-czerwinski.jpg"; hash = "sha256-acxN1KQHwH9VRgD549BP7AKTuMiF3dhR/lg+/C6ty1I="; }
|
|
{ file = "4-oma-cityscape.jpg"; hash = "sha256-IuHWOXIrM/pvDTrCczRQtLrpYbSB9WZcsWOXvF9xTlw="; }
|
|
];
|
|
catppuccin = [
|
|
{ file = "1-totoro.png"; hash = "sha256-O8+rFOjnsEEwfLd9cAxpWRYP5/bV3mMbFb0C3gz42f8="; }
|
|
{ file = "2-waves.png"; hash = "sha256-VjGQ35WJvrLVEX1A2wLGSSMqtrw8Py622Xqfs1haDP0="; }
|
|
];
|
|
gruvbox = [
|
|
{ file = "1-the-backwater.jpg"; hash = "sha256-E8/GrjcK+YTAioIP+BtWoP67D7/pcSptsSi5TRTsqsY="; }
|
|
{ file = "4-idyllic-procession.jpg"; hash = "sha256-vgrnMmOl62lBb7E1R4JqYIBoWaoxuwMQU6/HPeYKVcU="; }
|
|
{ file = "5-leaves.jpg"; hash = "sha256-zb0817NKLI5+dIGK9RAahTF4aHiwo6/Lj2mFsnOU9m0="; }
|
|
];
|
|
kanagawa = [
|
|
{ file = "1-kanagawa.jpg"; hash = "sha256-m4F9cXaIU58NuHYDtmGZKDnDy7XUkYoCpO/AXJ+Isn0="; }
|
|
];
|
|
everforest = [
|
|
{ file = "1-tree-tops.jpg"; hash = "sha256-DwCl4tD3jV51x6L0gQH23uaRecbZTp9OvG+3wPOUYr8="; }
|
|
];
|
|
nord = [
|
|
{ file = "1-city-view.png"; hash = "sha256-sRhvp+5OnZAIe4aTTE3jGoZ9qkojxAGIUYGwe6Ev/3U="; }
|
|
{ file = "2-night-hawks.png"; hash = "sha256-YaS8ScE3ERId6H9ffyQH/4I1BRzRf5ze1+IOFbGdVpI="; }
|
|
];
|
|
rose-pine = [
|
|
{ file = "1-funky-shapes.jpg"; hash = "sha256-b1qeo9wiP76RBGfMc5Z7pt2ffoCn2Aa8FemFVj0V/gM="; }
|
|
];
|
|
hackerman = [
|
|
{ file = "1-synth-scape.jpg"; hash = "sha256-x9JZSTXyBODfG0Pf56EjieocHT/Y5XqSqfCEl/J6N34="; }
|
|
];
|
|
};
|
|
|
|
# ---- helpers ----
|
|
hexDigits = {
|
|
"0" = 0; "1" = 1; "2" = 2; "3" = 3; "4" = 4; "5" = 5; "6" = 6; "7" = 7;
|
|
"8" = 8; "9" = 9; "a" = 10; "b" = 11; "c" = 12; "d" = 13; "e" = 14; "f" = 15;
|
|
};
|
|
hexToRgb = hex:
|
|
let
|
|
s = lib.toLower (lib.removePrefix "#" hex);
|
|
dig = i: hexDigits.${builtins.substring i 1 s};
|
|
byte = i: (dig (i * 2)) * 16 + (dig (i * 2 + 1));
|
|
in "${toString (byte 0)},${toString (byte 1)},${toString (byte 2)}";
|
|
strip = hex: lib.removePrefix "#" hex;
|
|
mkFile = name: text: pkgs.writeText name text;
|
|
|
|
themeDir = name: t:
|
|
let
|
|
bgs = wallpapers.${name} or [ ];
|
|
hyprlandConf = mkFile "hyprland.conf" ''
|
|
$activeBorderColor = rgb(${strip t.accent})
|
|
|
|
general {
|
|
col.active_border = $activeBorderColor
|
|
}
|
|
|
|
group {
|
|
col.border_active = $activeBorderColor
|
|
}
|
|
'';
|
|
hyprlockConf = mkFile "hyprlock.conf" ''
|
|
$color = rgba(${hexToRgb t.background}, 1.0)
|
|
$inner_color = rgba(${hexToRgb t.background}, 0.8)
|
|
$outer_color = rgba(${hexToRgb t.foreground}, 1.0)
|
|
$font_color = rgba(${hexToRgb t.foreground}, 1.0)
|
|
$check_color = rgba(${hexToRgb t.accent}, 1.0)
|
|
'';
|
|
waybarCss = mkFile "waybar.css" ''
|
|
@define-color foreground ${t.foreground};
|
|
@define-color background ${t.background};
|
|
'';
|
|
swayosdCss = mkFile "swayosd.css" ''
|
|
@define-color background ${t.background};
|
|
@define-color border-color ${t.foreground};
|
|
@define-color label ${t.foreground};
|
|
@define-color image ${t.foreground};
|
|
@define-color progress ${t.accent};
|
|
'';
|
|
wlogoutCss = mkFile "wlogout.css" ''
|
|
@define-color background ${t.background};
|
|
@define-color foreground ${t.foreground};
|
|
@define-color accent ${t.accent};
|
|
'';
|
|
rofiRasi = mkFile "rofi.rasi" ''
|
|
* {
|
|
bg: ${t.background};
|
|
fg: ${t.foreground};
|
|
accent: ${t.accent};
|
|
|
|
background-color: @bg;
|
|
text-color: @fg;
|
|
border: 2px;
|
|
border-color: @accent;
|
|
border-radius: 0;
|
|
padding: 8px;
|
|
spacing: 6px;
|
|
font: "JetBrainsMono Nerd Font 12";
|
|
}
|
|
|
|
window { width: 40%; background-color: @bg; border: 2px; border-color: @accent; }
|
|
inputbar { background-color: @bg; text-color: @fg; }
|
|
listview { lines: 10; background-color: @bg; }
|
|
element { padding: 4px; }
|
|
element selected { background-color: @accent; text-color: @bg; }
|
|
'';
|
|
alacrittyToml = mkFile "alacritty.toml" ''
|
|
[colors.primary]
|
|
background = "${t.background}"
|
|
foreground = "${t.foreground}"
|
|
|
|
[colors.cursor]
|
|
text = "${t.background}"
|
|
cursor = "${t.cursor}"
|
|
|
|
[colors.vi_mode_cursor]
|
|
text = "${t.background}"
|
|
cursor = "${t.cursor}"
|
|
|
|
[colors.selection]
|
|
text = "${t.selection_foreground}"
|
|
background = "${t.selection_background}"
|
|
|
|
[colors.normal]
|
|
black = "${t.color0}"
|
|
red = "${t.color1}"
|
|
green = "${t.color2}"
|
|
yellow = "${t.color3}"
|
|
blue = "${t.color4}"
|
|
magenta = "${t.color5}"
|
|
cyan = "${t.color6}"
|
|
white = "${t.color7}"
|
|
|
|
[colors.bright]
|
|
black = "${t.color8}"
|
|
red = "${t.color9}"
|
|
green = "${t.color10}"
|
|
yellow = "${t.color11}"
|
|
blue = "${t.color12}"
|
|
magenta = "${t.color13}"
|
|
cyan = "${t.color14}"
|
|
white = "${t.color15}"
|
|
'';
|
|
makoIni = mkFile "mako.ini" ''
|
|
text-color=${t.foreground}
|
|
border-color=${t.accent}
|
|
background-color=${t.background}
|
|
width=420
|
|
height=110
|
|
padding=10
|
|
margin=10
|
|
border-size=2
|
|
border-radius=0
|
|
anchor=top-right
|
|
layer=overlay
|
|
default-timeout=5000
|
|
max-visible=5
|
|
font=JetBrainsMono Nerd Font 10
|
|
'';
|
|
in
|
|
pkgs.runCommand "omarchy-theme-${name}" { } ''
|
|
mkdir -p $out/backgrounds
|
|
cp ${hyprlandConf} $out/hyprland.conf
|
|
cp ${hyprlockConf} $out/hyprlock.conf
|
|
cp ${waybarCss} $out/waybar.css
|
|
cp ${swayosdCss} $out/swayosd.css
|
|
cp ${wlogoutCss} $out/wlogout.css
|
|
cp ${rofiRasi} $out/rofi.rasi
|
|
cp ${alacrittyToml} $out/alacritty.toml
|
|
cp ${makoIni} $out/mako.ini
|
|
${concatMapStrings (b: ''
|
|
cp ${pkgs.fetchurl {
|
|
url = "https://raw.githubusercontent.com/omacom/omarchy/v3.8.4/themes/${name}/backgrounds/${b.file}";
|
|
hash = b.hash;
|
|
}} $out/backgrounds/${b.file}
|
|
'') bgs}
|
|
'';
|
|
|
|
themesTree = pkgs.linkFarm "omarchy-themes"
|
|
(mapAttrsToList (n: t: { name = n; path = themeDir n t; }) themes);
|
|
|
|
omarchyDots = pkgs.runCommand "omarchy-dots" { } ''
|
|
mkdir -p $out
|
|
cp -r ${./omarchy/hypr} $out/hypr
|
|
cp -r ${./omarchy/waybar} $out/waybar
|
|
cp -r ${./omarchy/rofi} $out/rofi
|
|
cp -r ${./omarchy/wlogout} $out/wlogout
|
|
cp -r ${./omarchy/swayosd} $out/swayosd
|
|
cp -r ${./omarchy/alacritty} $out/alacritty
|
|
cp -r ${themesTree} $out/themes
|
|
'';
|
|
|
|
omarchyBin = pkgs.runCommand "omarchy-bin" { } ''
|
|
mkdir -p $out/bin
|
|
cp ${./omarchy/bin}/* $out/bin/
|
|
chmod +x $out/bin/*
|
|
'';
|
|
|
|
polkitAgent = pkgs.writeShellScriptBin "omarchy-polkit-agent" ''
|
|
exec ${pkgs.polkit_gnome}/libexec/polkit-gnome-authentication-agent-1
|
|
'';
|
|
in
|
|
{
|
|
programs.hyprland = {
|
|
enable = true;
|
|
systemd.setPath.enable = true;
|
|
};
|
|
|
|
# Hyprland is the default login session. i3 stays enabled (configs/desktop-light.nix)
|
|
# and remains selectable in lightdm as a fallback.
|
|
services.displayManager.defaultSession = "hyprland";
|
|
|
|
# Hyprland's own portal should be the default (desktop-light.nix sets gtk).
|
|
xdg.portal = {
|
|
config.common.default = mkForce "hyprland";
|
|
extraPortals = [ pkgs.xdg-desktop-portal-hyprland ];
|
|
};
|
|
|
|
environment.systemPackages = with pkgs; [
|
|
omarchyBin
|
|
polkitAgent
|
|
waybar rofi wlogout hyprlock hypridle swayosd mako clipse
|
|
wl-clipboard wl-clip-persist grim slurp hyprpicker
|
|
brightnessctl pamixer playerctl alacritty swaybg jq
|
|
gnome-calculator pavucontrol nautilus
|
|
nerd-fonts.jetbrains-mono
|
|
];
|
|
|
|
# Link the read-only config into ~/.config, seed the mutable theme state, and
|
|
# resolve the active theme/background symlinks. Runs on every switch/boot.
|
|
system.activationScripts.omarchy-dots = {
|
|
deps = [ "users" ];
|
|
text = ''
|
|
set -eu
|
|
export PATH=${lib.makeBinPath [ pkgs.coreutils pkgs.findutils pkgs.bash ]}:$PATH
|
|
install -d -m0755 -o ${user} -g users ${home}/.config ${home}/.local/share ${current}
|
|
ln -sfnT ${omarchyDots}/hypr ${home}/.config/hypr
|
|
ln -sfnT ${omarchyDots}/waybar ${home}/.config/waybar
|
|
ln -sfnT ${omarchyDots}/rofi ${home}/.config/rofi
|
|
ln -sfnT ${omarchyDots}/wlogout ${home}/.config/wlogout
|
|
ln -sfnT ${omarchyDots}/swayosd ${home}/.config/swayosd
|
|
ln -sfnT ${omarchyDots}/alacritty ${home}/.config/alacritty
|
|
ln -sfnT ${omarchyDots} ${omarchyPath}
|
|
[ -f ${current}/theme.name ] || printf '%s\n' ${defaultTheme} > ${current}/theme.name
|
|
chown -R ${user}:users ${home}/.config/omarchy
|
|
HOME=${home} OMARCHY_PATH=${omarchyPath} ${omarchyBin}/bin/omarchy-theme-apply
|
|
chown -h ${user}:users ${current}/theme ${current}/background 2>/dev/null || true
|
|
'';
|
|
};
|
|
}
|