aboutsummaryrefslogtreecommitdiff
path: root/modules
diff options
context:
space:
mode:
Diffstat (limited to 'modules')
-rw-r--r--modules/home/apps/cmus/default.nix77
-rw-r--r--modules/home/apps/default.nix46
-rw-r--r--modules/home/apps/discord/default.nix57
-rw-r--r--modules/home/apps/fastfetch/assets/mem.pngbin0 -> 185313 bytes
-rw-r--r--modules/home/apps/fastfetch/assets/nonon.pngbin0 -> 108707 bytes
-rw-r--r--modules/home/apps/fastfetch/assets/ryo.pngbin0 -> 128547 bytes
-rw-r--r--modules/home/apps/fastfetch/default.nix81
-rw-r--r--modules/home/apps/feh/default.nix15
-rw-r--r--modules/home/apps/firefox/default.nix23
-rw-r--r--modules/home/apps/flameshot/default.nix38
-rw-r--r--modules/home/apps/kitty/default.nix84
-rw-r--r--modules/home/apps/mpv/default.nix20
-rw-r--r--modules/home/apps/obsidian/default.nix24
-rw-r--r--modules/home/apps/prismlauncher/default.nix35
-rw-r--r--modules/home/apps/steam/default.nix30
-rw-r--r--modules/home/apps/vscode/default.nix75
-rw-r--r--modules/home/desktop/bg/SOURCES.md6
-rw-r--r--modules/home/desktop/bg/lycoris.pngbin0 -> 28947690 bytes
-rw-r--r--modules/home/desktop/bg/matama.pngbin0 -> 9543767 bytes
-rw-r--r--modules/home/desktop/bg/mem.pngbin0 -> 6454104 bytes
-rw-r--r--modules/home/desktop/bg/nonon.pngbin0 -> 145618 bytes
-rw-r--r--modules/home/desktop/bg/ryo.pngbin0 -> 5189063 bytes
-rw-r--r--modules/home/desktop/bg/shinobu.pngbin0 -> 4879909 bytes
-rw-r--r--modules/home/desktop/bg/skull.pngbin0 -> 2651560 bytes
-rw-r--r--modules/home/desktop/components/eww/assets/album_art_placeholder.pngbin0 -> 10274 bytes
-rw-r--r--modules/home/desktop/components/eww/default.nix105
-rw-r--r--modules/home/desktop/components/eww/eww/eww.css86
-rw-r--r--modules/home/desktop/components/eww/eww/eww.yuck3
-rw-r--r--modules/home/desktop/components/eww/eww/panels/bar.css39
-rw-r--r--modules/home/desktop/components/eww/eww/panels/bar.yuck102
-rw-r--r--modules/home/desktop/components/eww/eww/panels/cpu.yuck45
-rw-r--r--modules/home/desktop/components/eww/eww/panels/default.css4
-rw-r--r--modules/home/desktop/components/eww/eww/panels/default.yuck7
-rw-r--r--modules/home/desktop/components/eww/eww/panels/fs.css13
-rw-r--r--modules/home/desktop/components/eww/eww/panels/fs.yuck74
-rw-r--r--modules/home/desktop/components/eww/eww/panels/launcher.css7
-rw-r--r--modules/home/desktop/components/eww/eww/panels/launcher.yuck27
-rw-r--r--modules/home/desktop/components/eww/eww/panels/memory.yuck28
-rw-r--r--modules/home/desktop/components/eww/eww/panels/music.css38
-rw-r--r--modules/home/desktop/components/eww/eww/panels/music.yuck102
-rw-r--r--modules/home/desktop/components/eww/eww/panels/volume.yuck40
-rw-r--r--modules/home/desktop/components/eww/eww/widgets/default.css1
-rw-r--r--modules/home/desktop/components/eww/eww/widgets/default.yuck2
-rw-r--r--modules/home/desktop/components/eww/eww/widgets/meter.css9
-rw-r--r--modules/home/desktop/components/eww/eww/widgets/meter.yuck41
-rw-r--r--modules/home/desktop/components/eww/eww/widgets/stat.yuck24
-rw-r--r--modules/home/desktop/components/eww/eww/windows/default.yuck2
-rw-r--r--modules/home/desktop/components/eww/eww/windows/music.yuck19
-rw-r--r--modules/home/desktop/components/eww/eww/windows/net.yuck35
-rw-r--r--modules/home/desktop/components/eww/eww/windows/sys.yuck84
-rw-r--r--modules/home/desktop/components/fcitx5/default.nix82
-rw-r--r--modules/home/desktop/components/gtk/default.nix26
-rw-r--r--modules/home/desktop/components/i3/default.nix257
-rw-r--r--modules/home/desktop/components/picom/default.nix30
-rw-r--r--modules/home/desktop/components/polybar/default.nix278
-rw-r--r--modules/home/desktop/components/rofi/default.nix58
-rw-r--r--modules/home/desktop/default.nix55
-rw-r--r--modules/home/desktop/theme/gruvbox.nix26
-rw-r--r--modules/home/impermanence/default.nix52
-rw-r--r--modules/home/suites/common/default.nix23
-rw-r--r--modules/home/suites/desktop/default.nix32
-rw-r--r--modules/home/suites/dev/default.nix31
-rw-r--r--modules/home/suites/gaming/default.nix19
-rw-r--r--modules/home/suites/media/default.nix26
-rw-r--r--modules/home/suites/misc/default.nix23
-rw-r--r--modules/home/tools/bash/default.nix15
-rw-r--r--modules/home/tools/btop/default.nix15
-rw-r--r--modules/home/tools/default.nix15
-rw-r--r--modules/home/tools/git/default.nix45
-rw-r--r--modules/home/tools/gpg/default.nix32
-rw-r--r--modules/home/tools/ssh/default.nix20
-rw-r--r--modules/home/tools/tmux/default.nix15
-rw-r--r--modules/home/tools/vim/default.nix43
-rw-r--r--modules/home/tools/zoxide/default.nix15
-rw-r--r--modules/nixos/apps/i3/default.nix50
-rw-r--r--modules/nixos/apps/playerctl/default.nix18
-rw-r--r--modules/nixos/apps/steam/default.nix18
-rw-r--r--modules/nixos/hardware/audio/default.nix25
-rw-r--r--modules/nixos/hardware/keyboard/default.nix43
-rw-r--r--modules/nixos/services/minecraft/default.nix25
-rw-r--r--modules/nixos/services/minecraft/stargazers/default.nix83
-rw-r--r--modules/nixos/services/minecraft/zenith/default.nix21
-rw-r--r--modules/nixos/services/ssh/default.nix28
-rw-r--r--modules/nixos/services/web/default.nix23
-rw-r--r--modules/nixos/services/web/images/default.nix34
-rw-r--r--modules/nixos/services/web/landing/default.nix34
-rw-r--r--modules/nixos/services/web/personal/default.nix63
-rw-r--r--modules/nixos/services/web/stargazers/default.nix34
-rw-r--r--modules/nixos/suites/common/default.nix25
-rw-r--r--modules/nixos/suites/desktop/default.nix27
-rw-r--r--modules/nixos/suites/gaming/default.nix17
-rw-r--r--modules/nixos/system/default.nix30
-rw-r--r--modules/nixos/system/fonts/default.nix38
-rw-r--r--modules/nixos/system/impermanence/default.nix49
-rw-r--r--modules/nixos/tools/bash/default.nix29
-rw-r--r--modules/nixos/tools/bash/prompt.sh84
-rw-r--r--modules/nixos/tools/git/default.nix16
-rw-r--r--modules/nixos/tools/misc/default.nix19
-rw-r--r--modules/nixos/tools/rebuild/default.nix16
-rw-r--r--modules/nixos/tools/vim/default.nix19
100 files changed, 3649 insertions, 0 deletions
diff --git a/modules/home/apps/cmus/default.nix b/modules/home/apps/cmus/default.nix
new file mode 100644
index 0000000..3124d07
--- /dev/null
+++ b/modules/home/apps/cmus/default.nix
@@ -0,0 +1,77 @@
+{ options, config, lib, pkgs, namespace, ... }:
+
+with lib; with lib.${namespace}; let
+ cfg = config.${namespace}.apps.cmus;
+ impermanence = config.${namespace}.impermanence;
+in {
+ options.${namespace}.apps.cmus = with types; {
+ enable = mkEnableOption "cmus";
+ };
+
+ config = mkIf cfg.enable {
+ home.packages = with pkgs; [
+ cmus
+ ];
+
+ home.persistence.${impermanence.location} = {
+ directories = [
+ ".config/cmus"
+ ];
+ };
+
+ xdg.desktopEntries.cmus = {
+ name = "cmus";
+ genericName = "Music Player";
+ exec = "${pkgs.kitty}/bin/kitty ${pkgs.cmus}/bin/cmus";
+ categories = [ "Music" "Player" "Audio" "ConsoleOnly" ];
+ };
+
+ xdg.configFile."cmus/rc".text = ''
+ set auto_expand_albums_follow=false
+ set pause_on_output_change=true
+ set repeat=true
+ set shuffle=tracks
+
+ fset unheard=play_count=0
+ factivate
+
+ set color_cmdline_attr=default
+ set color_cmdline_bg=default
+ set color_cmdline_fg=default
+ set color_cur_sel_attr=default
+ set color_error=231
+ set color_info=lightyellow
+ set color_separator=black
+ set color_statusline_attr=default
+ set color_statusline_bg=237
+ set color_statusline_fg=248
+ set color_titleline_attr=bold
+ set color_titleline_bg=239
+ set color_titleline_fg=default
+ set color_trackwin_album_attr=bold
+ set color_trackwin_album_bg=black
+ set color_trackwin_album_fg=default
+ set color_win_attr=default
+ set color_win_bg=default
+ set color_win_cur=231
+ set color_win_cur_attr=default
+ set color_win_cur_sel_attr=bold
+ set color_win_cur_sel_bg=231
+ set color_win_cur_sel_fg=black
+ set color_win_dir=lightblue
+ set color_win_fg=default
+ set color_win_inactive_cur_sel_attr=bold
+ set color_win_inactive_cur_sel_bg=237
+ set color_win_inactive_cur_sel_fg=231
+ set color_win_inactive_sel_attr=bold
+ set color_win_inactive_sel_bg=237
+ set color_win_inactive_sel_fg=default
+ set color_win_sel_attr=bold
+ set color_win_sel_bg=250
+ set color_win_sel_fg=black
+ set color_win_title_attr=bold
+ set color_win_title_bg=250
+ set color_win_title_fg=black
+ '';
+ };
+}
diff --git a/modules/home/apps/default.nix b/modules/home/apps/default.nix
new file mode 100644
index 0000000..2c26354
--- /dev/null
+++ b/modules/home/apps/default.nix
@@ -0,0 +1,46 @@
+{ lib, pkgs, namespace, ... }:
+
+with lib; with lib.${namespace}; {
+ imports = with pkgs; [
+ (mkSimpleApp "gimp" {})
+ (mkSimpleApp "jellyfin" { packages = [ jellyfin-media-player ]; })
+ (mkSimpleApp "lutris" { persist = [ ".local/share/lutris" ]; })
+ (mkSimpleApp "irssi" { persist = [ ".irssi" ]; })
+
+ (mkSimpleApp "intellij" {
+ packages = [ jetbrains.idea-community ];
+ persist = [
+ ".config/JetBrains"
+ ".local/share/JetBrains"
+ ".cache/JetBrains"
+ ];
+ })
+
+ (mkSimpleApp "anki" {
+ packages = [ anki-bin ];
+ persist = [ ".local/share/Anki2" ];
+ })
+
+ (mkSimpleApp "qbittorrent" {
+ persist = [
+ ".config/qBittorrent"
+ ".local/share/qBittorrent"
+ ".cache/qBittorrent"
+ ];
+ })
+ (mkSimpleApp "nicotine" {
+ packages = [ nicotine-plus ];
+ persist = [
+ ".config/nicotine"
+ ".local/share/nicotine"
+ ];
+ })
+
+ (mkSimpleApp "pfetch" {})
+ (mkSimpleApp "cmatrix" {})
+ (mkSimpleApp "asciiquarium" {})
+ (mkSimpleApp "pipes" {})
+ (mkSimpleApp "cowsay" {})
+ (mkSimpleApp "figlet" {})
+ ];
+}
diff --git a/modules/home/apps/discord/default.nix b/modules/home/apps/discord/default.nix
new file mode 100644
index 0000000..7766cd8
--- /dev/null
+++ b/modules/home/apps/discord/default.nix
@@ -0,0 +1,57 @@
+{ options, config, lib, pkgs, namespace, ... }:
+
+with lib; with lib.${namespace}; let
+ cfg = config.${namespace}.apps.discord;
+ impermanence = config.${namespace}.impermanence;
+ desktop = config.${namespace}.desktop;
+in {
+ options.${namespace}.apps.discord = with types; {
+ enable = mkEnableOption "discord";
+ };
+
+ config = mkIf cfg.enable {
+ home.packages = with pkgs; [
+ (discord.override {
+ withVencord = false;
+ withOpenASAR = false;
+ })
+ vesktop
+ ];
+
+ home.persistence.${impermanence.location} = {
+ directories = [
+ ".config/discord"
+ ".config/Vencord"
+ ".config/vesktop"
+ ];
+ };
+
+ xdg.configFile."Vencord/themes/nix.theme.css".text = let c = desktop.theme.colors; in ''
+ @import url(https://mwittrien.github.io/BetterDiscordAddons/Themes/BasicBackground/BasicBackground.css);
+
+ :root {
+ --transparencycolor: 0, 0, 0;
+ --transparencyalpha: 0.0;
+ --messagetransparency: 0.0;
+ --guildchanneltransparency: 0.15;
+ --chatinputtransparency: 0.0;
+ --memberlisttransparency: 0.15;
+ --settingsicons: 0;
+ /* A discord update messed up transparancy, and for now eyeballing it works fine */
+ /* --background: rgba(0, 0, 0, 0.8); */
+ --background: rgba(0, 0, 0, 0.55);
+ --backdrop: rgba(0, 0, 0, 0);
+ --version1_0_5: none;
+
+ --accentcolor: ${hexToRGBString ", " c.accent};
+
+ --textbrightest: ${hexToRGBString ", " c.fg0};
+ --textbrighter: ${hexToRGBString ", " c.fg1};
+ --textbright: ${hexToRGBString ", " c.fg2};
+ --textdark: ${hexToRGBString ", " c.fg3};
+ --textdarker: ${hexToRGBString ", " c.fg4};
+ --textdarkest: ${hexToRGBString ", " c.brightBlack};
+ }
+ '';
+ };
+}
diff --git a/modules/home/apps/fastfetch/assets/mem.png b/modules/home/apps/fastfetch/assets/mem.png
new file mode 100644
index 0000000..999c4dd
--- /dev/null
+++ b/modules/home/apps/fastfetch/assets/mem.png
Binary files differ
diff --git a/modules/home/apps/fastfetch/assets/nonon.png b/modules/home/apps/fastfetch/assets/nonon.png
new file mode 100644
index 0000000..57056ce
--- /dev/null
+++ b/modules/home/apps/fastfetch/assets/nonon.png
Binary files differ
diff --git a/modules/home/apps/fastfetch/assets/ryo.png b/modules/home/apps/fastfetch/assets/ryo.png
new file mode 100644
index 0000000..852df37
--- /dev/null
+++ b/modules/home/apps/fastfetch/assets/ryo.png
Binary files differ
diff --git a/modules/home/apps/fastfetch/default.nix b/modules/home/apps/fastfetch/default.nix
new file mode 100644
index 0000000..aa901e6
--- /dev/null
+++ b/modules/home/apps/fastfetch/default.nix
@@ -0,0 +1,81 @@
+{ options, config, lib, pkgs, namespace, ... }:
+
+with lib; with lib.${namespace}; let
+ cfg = config.${namespace}.apps.fastfetch;
+in {
+ options.${namespace}.apps.fastfetch = with types; {
+ enable = mkEnableOption "fastfetch";
+ };
+
+ config = mkIf cfg.enable {
+ programs.fastfetch = {
+ enable = true;
+ package = (pkgs.fastfetch.overrideAttrs (finalAttrs: previousAttrs: {
+ cmakeFlags = [(cmakeBool "ENABLE_IMAGEMAGICK6" true)];
+ }));
+
+ settings = {
+ logo = {
+ type = "kitty-direct";
+ source = "$(ls ${./assets}/*.png | shuf -n 1)";
+
+ width = 36;
+ height = 32;
+
+ padding = {
+ left = 4;
+ right = 4;
+ };
+ };
+
+ display = {
+ separator = "";
+ };
+
+ modules = [
+ { type = "custom"; format = " ハードウェア "; }
+ { type = "custom"; format = "┌──────────────────────────────────────────────────┐"; }
+
+ { type = "cpu"; key = " CPU "; }
+ { type = "gpu"; key = " GPU "; format = "{2} [{6}]"; }
+ { type = "memory"; key = " MEM "; }
+ "break"
+ {
+ type = "disk";
+ folders = "/nix:/persist";
+ key = " 󰋊 ";
+ }
+
+ { type = "custom"; format = "└──────────────────────────────────────────────────┘"; }
+ "break"
+
+ { type = "custom"; format = " ソフトウェア "; }
+ { type = "custom"; format = "┌──────────────────────────────────────────────────┐"; }
+
+ { type = "title"; key = " 󰁥 "; format = "{1}@{2}"; }
+ "break"
+ { type = "os"; key = "  "; }
+ { type = "kernel"; key = " 󰌽 "; format = "{1} {2}"; }
+ { type = "packages"; key = " 󰆧 "; }
+ "break"
+ { type = "terminal"; key = "  "; }
+ { type = "shell"; key = " 󱆃 "; }
+ # { type = "font"; key = " 󰬈 "; }
+ { type = "font"; key = " 󰬈 "; format = "Caskaydia Mono (8pt)"; }
+ "break"
+ { type = "wm"; key = "  "; }
+ # { type = "theme"; key = " 󰏘 "; }
+ { type = "theme"; key = " 󰏘 "; format = "gruvbox"; }
+ "break"
+ { type = "media"; key = " 󰝚 "; }
+ { type = "datetime"; key = " 󰃰 "; }
+
+ { type = "custom"; format = "└──────────────────────────────────────────────────┘"; }
+ "break"
+
+ "colors"
+ ];
+ };
+ };
+ };
+}
diff --git a/modules/home/apps/feh/default.nix b/modules/home/apps/feh/default.nix
new file mode 100644
index 0000000..af14289
--- /dev/null
+++ b/modules/home/apps/feh/default.nix
@@ -0,0 +1,15 @@
+{ options, config, lib, namespace, ... }:
+
+with lib; with lib.${namespace}; let
+ cfg = config.${namespace}.apps.feh;
+in {
+ options.${namespace}.apps.feh = with types; {
+ enable = mkEnableOption "feh";
+ };
+
+ config = mkIf cfg.enable {
+ programs.feh = {
+ enable = true;
+ };
+ };
+}
diff --git a/modules/home/apps/firefox/default.nix b/modules/home/apps/firefox/default.nix
new file mode 100644
index 0000000..981fb9a
--- /dev/null
+++ b/modules/home/apps/firefox/default.nix
@@ -0,0 +1,23 @@
+{ options, config, lib, namespace, ... }:
+
+with lib; with lib.${namespace}; let
+ cfg = config.${namespace}.apps.firefox;
+ impermanence = config.${namespace}.impermanence;
+in {
+ options.${namespace}.apps.firefox = with types; {
+ enable = mkEnableOption "firefox";
+ };
+
+ config = mkIf cfg.enable {
+ #TODO: migrate to declarative config
+ home.persistence.${impermanence.location} = {
+ directories = [
+ ".mozilla"
+ ];
+ };
+
+ programs.firefox = {
+ enable = true;
+ };
+ };
+}
diff --git a/modules/home/apps/flameshot/default.nix b/modules/home/apps/flameshot/default.nix
new file mode 100644
index 0000000..9a91604
--- /dev/null
+++ b/modules/home/apps/flameshot/default.nix
@@ -0,0 +1,38 @@
+{ options, config, lib, namespace, ... }:
+
+with lib; with lib.${namespace}; let
+ cfg = config.${namespace}.apps.flameshot;
+ desktop = config.${namespace}.desktop;
+in {
+ options.${namespace}.apps.flameshot = with types; {
+ enable = mkEnableOption "flameshot";
+ };
+
+ config = mkIf cfg.enable {
+ services.flameshot = {
+ enable = true;
+
+ settings = let c = desktop.theme.colors; in {
+ General = {
+ savePath = "Pictures/Screenshots";
+ filenamePattern = "%F_%T";
+
+ saveAfterCopy = true;
+
+ uiColor = "#${c.bg}";
+ contrastUiColor = "#${c.accent}";
+
+ startupLaunch = false;
+ };
+ };
+ };
+
+ #TODO: relocate. target.tray required for flameshot
+ systemd.user.targets.tray = {
+ Unit = {
+ Description = "Home Manager System Tray";
+ Requires = [ "graphical-session-pre.target" ];
+ };
+ };
+ };
+}
diff --git a/modules/home/apps/kitty/default.nix b/modules/home/apps/kitty/default.nix
new file mode 100644
index 0000000..dd64af6
--- /dev/null
+++ b/modules/home/apps/kitty/default.nix
@@ -0,0 +1,84 @@
+{ options, config, lib, namespace, ... }:
+
+with lib; with lib.${namespace}; let
+ cfg = config.${namespace}.apps.kitty;
+ desktop = config.${namespace}.desktop;
+in {
+ options.${namespace}.apps.kitty = with types; {
+ enable = mkEnableOption "kitty";
+ };
+
+ config = mkIf cfg.enable {
+ programs.kitty = {
+ enable = true;
+
+ font = { name = "monospace"; size = 8.0; };
+
+ settings = let c = desktop.theme.colors; in {
+ foreground = "#${c.fg}";
+ background = "#000000";
+
+ color0 = "#${c.black}";
+ color1 = "#${c.red}";
+ color2 = "#${c.green}";
+ color3 = "#${c.yellow}";
+ color4 = "#${c.blue}";
+ color5 = "#${c.magenta}";
+ color6 = "#${c.cyan}";
+ color7 = "#${c.white}";
+
+ color8 = "#${c.brightBlack}";
+ color9 = "#${c.brightRed}";
+ color10 = "#${c.brightGreen}";
+ color11 = "#${c.brightYellow}";
+ color12 = "#${c.brightBlue}";
+ color13 = "#${c.brightMagenta}";
+ color14 = "#${c.brightCyan}";
+ color15 = "#${c.brightWhite}";
+
+
+ color124 = "#${c.brightRed}";
+ color106 = "#${c.brightGreen}";
+ color172 = "#${c.brightYellow}";
+ color66 = "#${c.brightBlue}";
+ color132 = "#${c.brightMagenta}";
+ color72 = "#${c.brightCyan}";
+
+ color167 = "#${c.red}";
+ color142 = "#${c.green}";
+ color214 = "#${c.yellow}";
+ color109 = "#${c.blue}";
+ color175 = "#${c.magenta}";
+ color108 = "#${c.cyan}";
+
+ color234 = "#${c.bg0}";
+ color237 = "#${c.bg1}";
+ color239 = "#${c.bg2}";
+ color241 = "#${c.bg3}";
+ color243 = "#${c.bg4}";
+ color245 = "#${c.white}";
+
+ color246 = "#${c.fg4}";
+ color248 = "#${c.fg3}";
+ color250 = "#${c.fg2}";
+ color223 = "#${c.fg1}";
+ color229 = "#${c.fg0}";
+
+ color166 = "#${c.orange}";
+ color208 = "#${c.brightOrange}";
+
+ color231 = "#${c.accent}";
+ };
+
+ shellIntegration = {
+ mode = "no-cursor";
+ enableBashIntegration = true;
+ };
+
+ extraConfig = ''
+ background_opacity 0.8
+ confirm_os_window_close 0
+ '';
+ };
+ };
+}
diff --git a/modules/home/apps/mpv/default.nix b/modules/home/apps/mpv/default.nix
new file mode 100644
index 0000000..e7a62db
--- /dev/null
+++ b/modules/home/apps/mpv/default.nix
@@ -0,0 +1,20 @@
+{ options, config, lib, namespace, ... }:
+
+with lib; with lib.${namespace}; let
+ cfg = config.${namespace}.apps.mpv;
+in {
+ options.${namespace}.apps.mpv = with types; {
+ enable = mkEnableOption "mpv";
+ };
+
+ config = mkIf cfg.enable {
+ programs.mpv = {
+ enable = true;
+
+ config = {
+ screenshot-format = "png";
+ screenshot-template = "~/Pictures/Screenshots/mpv/%F/%P";
+ };
+ };
+ };
+}
diff --git a/modules/home/apps/obsidian/default.nix b/modules/home/apps/obsidian/default.nix
new file mode 100644
index 0000000..0815ab6
--- /dev/null
+++ b/modules/home/apps/obsidian/default.nix
@@ -0,0 +1,24 @@
+{ options, config, lib, pkgs, namespace, ... }:
+
+#NOTE: mkSimpleApp doesnt work for obsidian
+# Best guess is that the unfree predicate doesnt apply to /lib
+with lib; with lib.${namespace}; let
+ cfg = config.${namespace}.apps.obsidian;
+ impermanence = config.${namespace}.impermanence;
+in {
+ options.${namespace}.apps.obsidian = with types; {
+ enable = mkEnableOption "obsidian";
+ };
+
+ config = mkIf cfg.enable {
+ home.packages = with pkgs; [
+ obsidian
+ ];
+
+ home.persistence.${impermanence.location} = {
+ directories = [
+ ".config/Obsidian"
+ ];
+ };
+ };
+}
diff --git a/modules/home/apps/prismlauncher/default.nix b/modules/home/apps/prismlauncher/default.nix
new file mode 100644
index 0000000..c6830ba
--- /dev/null
+++ b/modules/home/apps/prismlauncher/default.nix
@@ -0,0 +1,35 @@
+{ options, config, lib, pkgs, namespace, ... }:
+
+with lib; with lib.${namespace}; let
+ cfg = config.${namespace}.apps.prismlauncher;
+ impermanence = config.${namespace}.impermanence;
+in {
+ options.${namespace}.apps.prismlauncher = with types; {
+ enable = mkEnableOption "prismlauncher";
+
+ extra = {
+ rusherhack.enable = mkEnableOption "rusherhack";
+ };
+ };
+
+ config = mkIf cfg.enable {
+ home.packages = with pkgs; [
+ prismlauncher
+ ];
+
+ home.persistence.${impermanence.location} = {
+ directories = [
+ ".local/share/PrismLauncher"
+ ] ++ optionals cfg.extra.rusherhack.enable [
+ #TODO: migrate to proper a secrets management setup, eg agenix/sops-nix
+ ".rusherhack"
+ ];
+ };
+
+ home.file = {
+ "Links/PrismLauncher Instances".source = config.lib.file.mkOutOfStoreSymlink (
+ "${config.home.homeDirectory}/.local/share/PrismLauncher/instances"
+ );
+ };
+ };
+}
diff --git a/modules/home/apps/steam/default.nix b/modules/home/apps/steam/default.nix
new file mode 100644
index 0000000..9148b9d
--- /dev/null
+++ b/modules/home/apps/steam/default.nix
@@ -0,0 +1,30 @@
+{ options, config, osConfig, lib, pkgs, namespace, ... }:
+
+#NOTE: steam must be installed system-wide.
+# This module does nothing unless steam is enabled at the
+# system level as well. This is only a separate toggle so
+# that not every user gets steam files in their home.
+with lib; with lib.${namespace}; let
+ cfg = config.${namespace}.apps.steam;
+ oscfg = osConfig.${namespace}.apps.steam;
+ impermanence = config.${namespace}.impermanence;
+in {
+ options.${namespace}.apps.steam = with types; {
+ enable = mkEnableOption "steam";
+ };
+
+ config = mkIf (cfg.enable && oscfg.enable) {
+ home.persistence.${impermanence.location} = {
+ directories = [{
+ directory = ".local/share/Steam";
+ method = "symlink";
+ }];
+ };
+
+ home.file = {
+ "Links/Steam Games".source = config.lib.file.mkOutOfStoreSymlink (
+ "${config.home.homeDirectory}/.local/share/Steam/steamapps/common"
+ );
+ };
+ };
+}
diff --git a/modules/home/apps/vscode/default.nix b/modules/home/apps/vscode/default.nix
new file mode 100644
index 0000000..bf4b5da
--- /dev/null
+++ b/modules/home/apps/vscode/default.nix
@@ -0,0 +1,75 @@
+{ options, config, lib, pkgs, namespace, ... }:
+
+with lib; with lib.${namespace}; let
+ cfg = config.${namespace}.apps.vscode;
+in {
+ options.${namespace}.apps.vscode = with types; {
+ enable = mkEnableOption "vscode";
+ };
+
+ config = mkIf cfg.enable {
+ programs.vscode = {
+ enable = true;
+ package = pkgs.vscodium;
+
+ extensions = with pkgs.vscode-extensions; [
+ jdinhlife.gruvbox
+ vscode-icons-team.vscode-icons
+
+ jnoortheen.nix-ide
+ golang.go
+ ziglang.vscode-zig
+ ] ++ pkgs.vscode-utils.extensionsFromVscodeMarketplace [
+ {
+ name = "shader";
+ publisher = "slevesque";
+ version = "1.1.5";
+ sha256 = "sha256-Pf37FeQMNlv74f7LMz9+CKscF6UjTZ7ZpcaZFKtX2ZM=";
+ }
+ {
+ name = "yuck";
+ publisher = "eww-yuck";
+ version = "0.0.3";
+ sha256 = "sha256-DITgLedaO0Ifrttu+ZXkiaVA7Ua5RXc4jXQHPYLqrcM=";
+ }
+ ];
+
+ userSettings = {
+ "workbench.colorTheme" = "Gruvbox Dark Medium";
+ "workbench.iconTheme" = "vscode-icons";
+ "window.titleBarStyle" = "custom";
+ "editor.fontFamily" = "monospace";
+
+ "git.confirmSync" = false;
+
+ "vsicons.dontShowNewVersionMessage" = true;
+
+ "files.associations" = {
+ "*.vsh" = "glsl";
+ "*.fsh" = "glsl";
+ "*.gsh" = "glsl";
+ };
+
+ # Zig
+ "zig.initialSetupDone" = true;
+ "zig.path" = "";
+ "zig.formattingProvider" = "off";
+
+ "zig.zls.path" = "";
+ "zig.zls.enableAutofix" = false;
+ "zig.zls.enableInlayHints" = false;
+ };
+ };
+
+ xdg.desktopEntries.nixeditor = {
+ name = "NixOS Config";
+ genericName = "Edit in VSCode";
+ icon = "nix-snowflake";
+ exec = "${pkgs.vscodium}/bin/codium /etc/nixos";
+ };
+
+ home.shellAliases = {
+ "c" = "codium .";
+ };
+ };
+}
diff --git a/modules/home/desktop/bg/SOURCES.md b/modules/home/desktop/bg/SOURCES.md
new file mode 100644
index 0000000..893f894
--- /dev/null
+++ b/modules/home/desktop/bg/SOURCES.md
@@ -0,0 +1,6 @@
+# Background Image Sources
+- `matama.png`: Mahou Shoujo ni Akogarete S01E09 (Edited)
+- `mem.png`: Oshi no Ko S01 OP
+- `shinobu.png`: Kizumonogatari I: Tekketsu (Edited)
+- `skull.png`: [Akiakane](https://akiakane.net)
+
diff --git a/modules/home/desktop/bg/lycoris.png b/modules/home/desktop/bg/lycoris.png
new file mode 100644
index 0000000..8c8ba19
--- /dev/null
+++ b/modules/home/desktop/bg/lycoris.png
Binary files differ
diff --git a/modules/home/desktop/bg/matama.png b/modules/home/desktop/bg/matama.png
new file mode 100644
index 0000000..248d18e
--- /dev/null
+++ b/modules/home/desktop/bg/matama.png
Binary files differ
diff --git a/modules/home/desktop/bg/mem.png b/modules/home/desktop/bg/mem.png
new file mode 100644
index 0000000..1cd2007
--- /dev/null
+++ b/modules/home/desktop/bg/mem.png
Binary files differ
diff --git a/modules/home/desktop/bg/nonon.png b/modules/home/desktop/bg/nonon.png
new file mode 100644
index 0000000..b16de01
--- /dev/null
+++ b/modules/home/desktop/bg/nonon.png
Binary files differ
diff --git a/modules/home/desktop/bg/ryo.png b/modules/home/desktop/bg/ryo.png
new file mode 100644
index 0000000..d268a89
--- /dev/null
+++ b/modules/home/desktop/bg/ryo.png
Binary files differ
diff --git a/modules/home/desktop/bg/shinobu.png b/modules/home/desktop/bg/shinobu.png
new file mode 100644
index 0000000..176ac0c
--- /dev/null
+++ b/modules/home/desktop/bg/shinobu.png
Binary files differ
diff --git a/modules/home/desktop/bg/skull.png b/modules/home/desktop/bg/skull.png
new file mode 100644
index 0000000..0cd2deb
--- /dev/null
+++ b/modules/home/desktop/bg/skull.png
Binary files differ
diff --git a/modules/home/desktop/components/eww/assets/album_art_placeholder.png b/modules/home/desktop/components/eww/assets/album_art_placeholder.png
new file mode 100644
index 0000000..2cdcbab
--- /dev/null
+++ b/modules/home/desktop/components/eww/assets/album_art_placeholder.png
Binary files differ
diff --git a/modules/home/desktop/components/eww/default.nix b/modules/home/desktop/components/eww/default.nix
new file mode 100644
index 0000000..226ccc0
--- /dev/null
+++ b/modules/home/desktop/components/eww/default.nix
@@ -0,0 +1,105 @@
+{ options, config, lib, pkgs, namespace, ... }:
+
+with lib; with lib.${namespace}; let
+ cfg = config.${namespace}.desktop.components.eww;
+ desktop = config.${namespace}.desktop;
+in {
+ options.${namespace}.desktop.components.eww = with types; {
+ enable = mkEnableOption "eww";
+ };
+
+ config = mkIf cfg.enable {
+ home.packages = with pkgs; [
+ eww
+
+ (writeShellScriptBin "eww-toggle" ''
+ if ${pkgs.eww}/bin/eww active-windows | grep $1; then
+ ${pkgs.eww}/bin/eww close $1
+ else
+ ${pkgs.eww}/bin/eww open $@
+ fi
+ '')
+
+ (writeShellScriptBin "get-album-art" ''
+ OUTFILE=".mpris-art"
+
+ while read -r line; do
+ if [[ -n $line ]]; then
+ rm -f ~/$OUTFILE
+
+ cmus_path=$(${pkgs.cmus}/bin/cmus-remote -Q | grep file | cut -c 6-)
+ if [[ -n $cmus_path ]]; then
+ if [[ -f $(dirname "$cmus_path")/cover.jpg ]]; then
+ cp "$(dirname "$cmus_path")/cover.jpg" ~/$OUTFILE
+ else
+ ${pkgs.ffmpeg}/bin/ffmpeg -y -v quiet -i "$cmus_path" -c:v copy -f mjpeg ~/$OUTFILE
+ fi
+ else
+ mpris=$(${pkgs.playerctl}/bin/playerctl --player=cmus,firefox,%any metadata mpris:artUrl)
+
+ if [[ $mpris == data:image* ]]; then
+ echo $mpris | sed s/.*,//g | base64 --decode > ~/$OUTFILE
+ elif [[ -n $mpris ]]; then
+ curl -s -o ~/$OUTFILE $mpris
+ fi
+ fi
+
+ if [[ -f ~/$OUTFILE ]]; then
+ :
+ else
+ cp ${./assets/album_art_placeholder.png} ~/$OUTFILE
+ fi
+
+ echo ~/$OUTFILE
+ fi
+ done
+ '')
+ ];
+
+ xdg.configFile."eww/eww.yuck".source = eww/eww.yuck;
+ xdg.configFile."eww/eww.css".source = eww/eww.css;
+
+ xdg.configFile."eww/panels".source = eww/panels;
+ xdg.configFile."eww/windows".source = eww/windows;
+ xdg.configFile."eww/widgets".source = eww/widgets;
+
+ xdg.configFile."eww/colors.css".text = let c = desktop.theme.colors; in ''
+ @define-color accent #${c.accent};
+
+ @define-color black #${c.black};
+ @define-color red #${c.red};
+ @define-color green #${c.green};
+ @define-color yellow #${c.yellow};
+ @define-color blue #${c.blue};
+ @define-color magenta #${c.magenta};
+ @define-color cyan #${c.cyan};
+ @define-color white #${c.white};
+
+ @define-color brightBlack #${c.brightBlack};
+ @define-color brightRed #${c.brightRed};
+ @define-color brightGreen #${c.brightGreen};
+ @define-color brightYellow #${c.brightYellow};
+ @define-color brightBlue #${c.brightBlue};
+ @define-color brightMagenta #${c.brightMagenta};
+ @define-color brightCyan #${c.brightCyan};
+ @define-color brightWhite #${c.brightWhite};
+
+ @define-color bg #${c.bg};
+ @define-color bg0 #${c.bg0};
+ @define-color bg1 #${c.bg1};
+ @define-color bg2 #${c.bg2};
+ @define-color bg3 #${c.bg3};
+ @define-color bg4 #${c.bg4};
+
+ @define-color fg #${c.fg};
+ @define-color fg0 #${c.fg0};
+ @define-color fg1 #${c.fg1};
+ @define-color fg2 #${c.fg2};
+ @define-color fg3 #${c.fg3};
+ @define-color fg4 #${c.fg4};
+
+ @define-color orange #${c.orange};
+ @define-color brightOrange #${c.brightOrange};
+ '';
+ };
+}
diff --git a/modules/home/desktop/components/eww/eww/eww.css b/modules/home/desktop/components/eww/eww/eww.css
new file mode 100644
index 0000000..a715970
--- /dev/null
+++ b/modules/home/desktop/components/eww/eww/eww.css
@@ -0,0 +1,86 @@
+@import "colors.css";
+@import "panels/default.css";
+@import "widgets/default.css";
+
+window {
+ color: @fg;
+ background-color: rgba(0, 0, 0, 0);
+ /*border: 2px solid @yellow;*/
+ font-family: monospace, sans-serif;
+}
+
+.panel {
+ color: @fg;
+ background-color: @bg;
+ opacity: 1;
+ border: 2px solid @bg1;
+ outline: 2px solid red;
+ outline-offset: -20px;
+ font-family: monospace, sans-serif;
+ padding: 8px;
+}
+
+.unpadded {
+ padding: 0px;
+}
+
+.padded {
+ padding: 8px;
+}
+
+button {
+ color: @fg;
+ background: @bg;
+
+ border: none;
+ border-radius: 0;
+ box-shadow: none;
+ text-shadow: none;
+ margin: 0;
+ padding: 0;
+}
+
+button:hover {
+ background: @bg1;
+}
+
+button:active {
+ background: @bg2;
+}
+
+button.icon {
+ font-family: 'monospace';
+ font-size: 24;
+}
+
+.cutout {
+ background: @bg1;
+}
+
+.faint {
+ font-weight: normal;
+ color: @fg4;
+}
+
+graph {
+ color: @accent;
+ background: alpha(@accent, 0.2);
+}
+
+scale trough {
+ background: @bg2;
+ min-height: 4px;
+ min-width: 4px;
+}
+
+scale highlight {
+ background: @accent;
+}
+
+scale slider {
+ box-shadow: none;
+ background: @accent;
+ margin: -6px;
+ min-height: 0;
+ min-width: 0;
+}
diff --git a/modules/home/desktop/components/eww/eww/eww.yuck b/modules/home/desktop/components/eww/eww/eww.yuck
new file mode 100644
index 0000000..320a207
--- /dev/null
+++ b/modules/home/desktop/components/eww/eww/eww.yuck
@@ -0,0 +1,3 @@
+(include "./panels/default.yuck")
+(include "./widgets/default.yuck")
+(include "./windows/default.yuck")
diff --git a/modules/home/desktop/components/eww/eww/panels/bar.css b/modules/home/desktop/components/eww/eww/panels/bar.css
new file mode 100644
index 0000000..a07c3b1
--- /dev/null
+++ b/modules/home/desktop/components/eww/eww/panels/bar.css
@@ -0,0 +1,39 @@
+.bar .shutdown {
+ color: @brightRed;
+}
+
+.bar .restart {
+ color: @brightGreen;
+}
+
+.bar .sleep {
+ color: @brightYellow;
+}
+
+.bar .dismiss {
+ color: @red;
+}
+
+.bar .ws {
+ font-family: 'Symbols Nerd Font Mono';
+ font-size: 18;
+
+ color: @bg2;
+}
+
+.bar .ws.active {
+ color: @fg4;
+}
+
+.bar .ws.visible {
+ color: @fg;
+}
+
+.bar .ws.focused {
+ background: @bg1;
+ color: @fg0;
+}
+
+.bar .ws.urgent {
+ background: @red;
+}
diff --git a/modules/home/desktop/components/eww/eww/panels/bar.yuck b/modules/home/desktop/components/eww/eww/panels/bar.yuck
new file mode 100644
index 0000000..6dc4771
--- /dev/null
+++ b/modules/home/desktop/components/eww/eww/panels/bar.yuck
@@ -0,0 +1,102 @@
+(defwidget bar []
+ (centerbox :class "bar"
+ :orientation "h"
+
+ (box
+ :orientation "h"
+ :spacing 8
+ :space-evenly false
+
+ (tooltip :class "panel"
+ {EWW_TIME}
+ {formattime(EWW_TIME, "%T", "America/Los_Angeles")}
+ )
+
+ (tooltip :class "panel"
+ {formattime(EWW_TIME, "%F", "America/Los_Angeles")}
+ {formattime(EWW_TIME, "%A, %B %d, %Y", "America/Los_Angeles")}
+ )
+ )
+
+ (box
+ :orientation "h"
+ :spacing 8
+ :space-evenly false
+
+ ;(label :class "panel"
+ ; :text "i have no idea what to put here :3"
+ ;)
+
+ (box :class "unpadded panel"
+ (ws :num 0 :icon "󱄅" :name "Main")
+ (ws :num 1 :icon "" :name "Terminal")
+ (ws :num 2 :icon "󰈹" :name "Browser")
+ (ws :num 3 :icon "󰙯" :name "Chat")
+ (ws :num 4 :icon "󰓓" :name "Gaming")
+ (ws :num 5 :icon "󰎱" :name "5")
+ (ws :num 6 :icon "󰎳" :name "6")
+ (ws :num 7 :icon "󰎶" :name "7")
+ (ws :num 8 :icon "󰄛" :name "Meow")
+ (ws :num 9 :icon "󰲸" :name "Music")
+ (ws :num 10 :icon "󰁴" :name "Misc")
+ )
+ )
+
+ (box
+ :orientation "h"
+ :spacing 8
+ :space-evenly false
+ :halign "end"
+
+ (box :class "unpadded panel"
+ :space-evenly false
+ (button :class "sleep icon"
+ :width 31
+ "󰤄"
+ )
+
+ (button :class "restart icon"
+ :width 33
+ "󰜉"
+ )
+
+ (button :class "shutdown icon"
+ :width 31
+ "󰐥"
+ )
+ )
+
+ (box :class "unpadded panel"
+ (button :class "dismiss icon"
+ :width 29
+ :onclick `${EWW_CMD} close sys`
+ "󰅖"
+ )
+ )
+ )
+ )
+)
+
+(defwidget ws [num icon name]
+ (tooltip {name}
+ (button :class {"ws"
+ + (ws-status[num].active ? " active" : "")
+ + (ws-status[num].visible ? " visible" : "")
+ + (ws-status[num].focused ? " focused" : "")
+ + (ws-status[num].urgent ? " urgent" : "")
+ }
+ :width {
+ num == 0 ? 31 :
+ num == 10 ? 31 :
+ 33
+ }
+
+ {icon}
+ )
+ )
+)
+
+(defpoll ws-status
+ :interval "0.1s"
+ `i3-msg -t get_workspaces | jq -caM 'map({"ws-\\(.num)": {visible, focused, urgent, active: true}}) | add as $orig | [range(0;11)] | [.[] as $i | $orig."ws-\\($i)" // {visible: false, focused: false, urgent: false, active: false}]'`
+)
diff --git a/modules/home/desktop/components/eww/eww/panels/cpu.yuck b/modules/home/desktop/components/eww/eww/panels/cpu.yuck
new file mode 100644
index 0000000..ef57fa6
--- /dev/null
+++ b/modules/home/desktop/components/eww/eww/panels/cpu.yuck
@@ -0,0 +1,45 @@
+(defwidget cpu []
+ (box :class "panel"
+ :orientation "h"
+ :spacing 8
+ :space-evenly false
+
+ (tooltip :class "cutout"
+ {round(EWW_CPU.avg, 2) + "%"}
+ (graph
+ :value {EWW_CPU.avg}
+ :time-range "30s"
+ :width 76
+ :height 76
+ :hexpand true
+ )
+ )
+
+ (box :orientation "v"
+ :spacing 8
+ :space-evenly false
+ :hexpand true
+
+ (label :halign "start" :markup {"<b>" + cpu-name + "</b>"})
+
+ (stat :key "Temperature" :value {round(EWW_TEMPS.K10TEMP_TCTL, 2) + "°C"})
+ (stat :key "Frequency" :value {round(cpu-max-freq * cpu-freq/100, 0) + " MHz"})
+ (stat :key "Usage" :value {round(EWW_CPU.avg, 2) + "%"})
+ )
+ )
+)
+
+(defpoll cpu-freq
+ :interval "2s"
+ `lscpu | sed -n '/CPU(s) scaling MHz/ s/.*:\\s*\\(.*\\)%/\\1/p'`
+)
+
+(defpoll cpu-max-freq
+ :interval "9999s"
+ `lscpu | sed -n '/CPU max MHz/ s/.*:\\s*\\(.*\\)/\\1/p'`
+)
+
+(defpoll cpu-name
+ :interval "9999s"
+ `lscpu | sed -n '/Model name/ s/.*:\\s*\\(.*\\)/\\1/p'`
+)
diff --git a/modules/home/desktop/components/eww/eww/panels/default.css b/modules/home/desktop/components/eww/eww/panels/default.css
new file mode 100644
index 0000000..8cd39a3
--- /dev/null
+++ b/modules/home/desktop/components/eww/eww/panels/default.css
@@ -0,0 +1,4 @@
+@import "bar.css";
+@import "fs.css";
+@import "launcher.css";
+@import "music.css";
diff --git a/modules/home/desktop/components/eww/eww/panels/default.yuck b/modules/home/desktop/components/eww/eww/panels/default.yuck
new file mode 100644
index 0000000..3c20c4b
--- /dev/null
+++ b/modules/home/desktop/components/eww/eww/panels/default.yuck
@@ -0,0 +1,7 @@
+(include "./panels/bar.yuck")
+(include "./panels/cpu.yuck")
+(include "./panels/fs.yuck")
+(include "./panels/launcher.yuck")
+(include "./panels/memory.yuck")
+(include "./panels/music.yuck")
+(include "./panels/volume.yuck")
diff --git a/modules/home/desktop/components/eww/eww/panels/fs.css b/modules/home/desktop/components/eww/eww/panels/fs.css
new file mode 100644
index 0000000..8ca2dd2
--- /dev/null
+++ b/modules/home/desktop/components/eww/eww/panels/fs.css
@@ -0,0 +1,13 @@
+.disks .meter.almost-full .progress {
+ color: @orange;
+ background: rgba(0, 0, 0, 0);
+}
+
+.disks .meter.full .progress {
+ color: @red;
+ background: rgba(0, 0, 0, 0);
+}
+
+.zfs .total {
+ font-weight: bold;
+}
diff --git a/modules/home/desktop/components/eww/eww/panels/fs.yuck b/modules/home/desktop/components/eww/eww/panels/fs.yuck
new file mode 100644
index 0000000..54bbd46
--- /dev/null
+++ b/modules/home/desktop/components/eww/eww/panels/fs.yuck
@@ -0,0 +1,74 @@
+(defwidget disks []
+ (box :class "panel disks"
+ :orientation "h"
+ :spacing 8
+ :space-evenly false
+ :height {100+16}
+
+ (disk :mount "total"
+ :zfs true
+ :name "zpool"
+ )
+
+ (disk :mount "/mnt/4tb"
+ :name "4tb"
+ )
+ (disk :mount "/mnt/ssd"
+ :name "ssd"
+ )
+ )
+)
+
+(defwidget zfs []
+ (box :class "panel zfs"
+ :orientation "v"
+ :spacing 8
+ :space-evenly false
+ :hexpand true
+
+ (label :halign "start" :markup "<b>ZFS Volumes</b>")
+
+ (zvol :mount "/nix")
+ (zvol :mount "/persist")
+
+ (zvol :class "faint"
+ :mount "/home"
+ )
+
+ (zvol :class "faint"
+ :mount "/"
+ )
+
+ (zvol :class "total"
+ :mount "total"
+ :name "Total"
+ )
+ )
+)
+
+(defwidget disk [mount ?name ?zfs]
+ (meter
+ :value {
+ (zfs == true ? zpool : disks)[mount].used / ((zfs == true ? zpool : disks)[mount].used + (zfs == true ? zpool : disks)[mount].free) * 100}
+ :label {name != "" ? name : mount}
+
+ {round((zfs == true ? zpool : disks)[mount].used/1024/1024, 0) + " GiB"}
+ )
+)
+
+(defwidget zvol [mount ?name ?class]
+ (stat :class {class}
+ :key {name != "" ? name : mount}
+ :value {round(zpool[mount].used/1024/1024, 2) + " GiB"}
+ )
+)
+
+(defpoll disks
+ :interval "10s"
+ `df -x fuse -x tmpfs -x efivarfs -x devtmpfs -x zfs | tail -n +2 | awk '{ printf "%s free %d\\n%s used %d\\n", $6, $4, $6, $3 }' | xargs printf '{"%s": {"%s": %d}}\\n' | jq -scaM 'map(to_entries) | flatten | group_by(.key) | map({"\\(.[0].key)": map(.value | to_entries) | flatten | from_entries}) | add'`
+)
+
+(defpoll zpool
+ :interval "10s"
+ `df -t zfs --total | tail -n +2 | awk '{ printf "%s free %d\\n%s used %d\\n", $6, $4, $6, $3 }' | xargs printf '{"%s": {"%s": %d}}\\n' | jq -scaM 'map(to_entries) | flatten | group_by(.key) | map({"\\(.[0].key)": map(.value | to_entries) | flatten | from_entries}) | add | .total = ."-" | del(."-") | .total.free = ."/zpool".free'`
+)
diff --git a/modules/home/desktop/components/eww/eww/panels/launcher.css b/modules/home/desktop/components/eww/eww/panels/launcher.css
new file mode 100644
index 0000000..5055191
--- /dev/null
+++ b/modules/home/desktop/components/eww/eww/panels/launcher.css
@@ -0,0 +1,7 @@
+.launcher entry {
+ border-radius: 0;
+}
+
+.launcher entry:focus {
+ box-shadow: 0 0 0 2px @accent inset;
+}
diff --git a/modules/home/desktop/components/eww/eww/panels/launcher.yuck b/modules/home/desktop/components/eww/eww/panels/launcher.yuck
new file mode 100644
index 0000000..a568346
--- /dev/null
+++ b/modules/home/desktop/components/eww/eww/panels/launcher.yuck
@@ -0,0 +1,27 @@
+(defwidget launcher []
+ (box :class "launcher panel"
+ :orientation "v"
+ :spacing 8
+ :space-evenly false
+ :height {556 - ((128 + 16 + 4) + 8)}
+ :width 768
+
+ (input
+ :valign "start"
+ )
+
+ (scroll
+ :vscroll true
+ :hscroll false
+ :vexpand true
+
+ (literal :content {lunch})
+ )
+ )
+)
+
+(defpoll lunch
+ :interval "60s"
+ ;`~/lunch.sh`
+ `~/code/lunch/zig-out/bin/lunch`
+)
diff --git a/modules/home/desktop/components/eww/eww/panels/memory.yuck b/modules/home/desktop/components/eww/eww/panels/memory.yuck
new file mode 100644
index 0000000..4f6633a
--- /dev/null
+++ b/modules/home/desktop/components/eww/eww/panels/memory.yuck
@@ -0,0 +1,28 @@
+(defwidget memory []
+ (box :class "panel"
+ :orientation "v"
+ :spacing 8
+ :space-evenly false
+
+ (box
+ (label :markup "<b>Memory</b>"
+ :halign "start"
+ )
+
+ (label :markup {round(EWW_RAM.used_mem/1024/1024/1024, 2) + " GiB / " + round(EWW_RAM.total_mem/1024/1024/1024, 2) + " GiB"}
+ :halign "end"
+ )
+ )
+
+ (tooltip :class "cutout"
+ {round(EWW_RAM.used_mem_perc, 2) + "%"}
+ (graph
+ :hexpand true
+ :value {EWW_RAM.used_mem}
+ :max {EWW_RAM.total_mem}
+ :time-range "30s"
+ :height 100
+ )
+ )
+ )
+)
diff --git a/modules/home/desktop/components/eww/eww/panels/music.css b/modules/home/desktop/components/eww/eww/panels/music.css
new file mode 100644
index 0000000..e5bbc60
--- /dev/null
+++ b/modules/home/desktop/components/eww/eww/panels/music.css
@@ -0,0 +1,38 @@
+.music {
+ padding: 8px;
+ opacity: 1.0;
+}
+
+.music .right {
+ margin-top: 8px;
+}
+
+.music .song-title {
+ font-size: 17px;
+ font-weight: bold;
+}
+
+.music .song-album {
+ color: @fg2;
+}
+
+.music .song-artist {
+ color: @fg2;
+}
+
+.music scale trough {
+ background: @bg2;
+ min-height: 4px;
+}
+
+.music scale highlight {
+ background: @accent;
+}
+
+.music scale slider {
+ box-shadow: none;
+ background: @accent;
+ margin: -6px;
+ min-height: 0;
+ min-width: 0;
+}
diff --git a/modules/home/desktop/components/eww/eww/panels/music.yuck b/modules/home/desktop/components/eww/eww/panels/music.yuck
new file mode 100644
index 0000000..feae96a
--- /dev/null
+++ b/modules/home/desktop/components/eww/eww/panels/music.yuck
@@ -0,0 +1,102 @@
+
+(defwidget music []
+ (box :class "panel music"
+ :orientation "h"
+ :spacing 8
+ :space-evenly false
+ :height {128 + 16 + 4}
+
+ (image
+ :path song-cover
+ :image-width 128
+ :image-height 128
+ )
+
+ (box :class "right"
+ :orientation "v"
+ :spacing 0
+ :space-evenly true
+ :hexpand true
+
+ (box :class "info"
+ :orientation "v"
+ :space-evenly false
+ :valign "center"
+
+ (tooltip {song.title}
+ (label :class "song-title"
+ :text {song.title}
+ :halign "start"
+ :truncate true
+ )
+ )
+ (tooltip {song.album}
+ (label :class "song-album"
+ :text {song.album}
+ :halign "start"
+ :truncate true
+ )
+ )
+ (tooltip {song.artist}
+ (label :class "song-artist"
+ :text {song.artist}
+ :halign "start"
+ :truncate true
+ )
+ )
+ )
+
+ (box
+ :valign "end"
+ :space-evenly false
+
+ (box :class "control"
+ :space-evenly false
+
+ (button :class "icon"
+ :width 36
+ :onclick `playerctl --player=cmus,firefox,%any previous`
+
+ "󰒮"
+ )
+ (button :class "icon"
+ :onclick `playerctl --player=cmus,firefox,%any play-pause`
+ :width 36
+
+ { song.status == "Playing" ? "󰏤" : "󰐊" }
+ )
+ (button :class "icon"
+ :width 36
+ :onclick `playerctl --player=cmus,firefox,%any next`
+
+ "󰒭"
+ )
+ )
+
+ (scale
+ :hexpand true
+ :value {song-position}
+ :max {song.length/1000/1000}
+ ;:onchange `/home/c/seek.sh {}`
+ )
+
+ {formattime(round(song-position, 0), "%M:%S") + " / " + formattime(round(song.length/1000/1000, 0), "%M:%S")}
+
+ (box :width 16)
+ )
+ )
+ )
+)
+
+(deflisten song-cover
+ `playerctl --player=cmus,firefox,%any -F metadata title | get-album-art`
+)
+
+(deflisten song
+ `playerctl --player=cmus,firefox,%any -F metadata --format='{"title": "{{title}}", "album": "{{album}}", "artist": "{{artist}}", "status": "{{status}}", "length": "{{mpris:length}}"}'`
+)
+
+(defpoll song-position
+ :interval "0.2s"
+ `playerctl --player=cmus,firefox,%any position`
+)
diff --git a/modules/home/desktop/components/eww/eww/panels/volume.yuck b/modules/home/desktop/components/eww/eww/panels/volume.yuck
new file mode 100644
index 0000000..0c342c3
--- /dev/null
+++ b/modules/home/desktop/components/eww/eww/panels/volume.yuck
@@ -0,0 +1,40 @@
+(defwidget volume []
+ (box :class "volume panel"
+ :orientation "v"
+ :space-evenly false
+
+ (label :markup "<b>Volume</b>")
+
+ (box
+ :orientation "h"
+ :vexpand true
+
+ (box
+ :orientation "v"
+ :space-evenly false
+ :vexpand true
+
+ (scale
+ :orientation "v"
+ :flipped true
+ :value {sink-volume}
+ :max 101
+ :onchange `pactl set-sink-volume @DEFAULT_SINK@ {}%`
+ :vexpand true
+ )
+
+ {sink-volume + "%"}
+ )
+ )
+ )
+)
+
+(defpoll sink-volume
+ :interval "0.2s"
+ `pactl get-sink-volume @DEFAULT_SINK@ | head -n1 | awk '{print substr($5, 1, length($5)-1)}'`
+)
+
+;(defpoll source-volume
+; :interval "0.2s"
+; `pactl get-source-volume @DEFAULT_SOURCE@ | head -n1 | awk '{print substr($5, 1, length($5)-1)}'`
+;)
diff --git a/modules/home/desktop/components/eww/eww/widgets/default.css b/modules/home/desktop/components/eww/eww/widgets/default.css
new file mode 100644
index 0000000..e6d3764
--- /dev/null
+++ b/modules/home/desktop/components/eww/eww/widgets/default.css
@@ -0,0 +1 @@
+@import "meter.css";
diff --git a/modules/home/desktop/components/eww/eww/widgets/default.yuck b/modules/home/desktop/components/eww/eww/widgets/default.yuck
new file mode 100644
index 0000000..bedb80e
--- /dev/null
+++ b/modules/home/desktop/components/eww/eww/widgets/default.yuck
@@ -0,0 +1,2 @@
+(include "./widgets/meter.yuck")
+(include "./widgets/stat.yuck")
diff --git a/modules/home/desktop/components/eww/eww/widgets/meter.css b/modules/home/desktop/components/eww/eww/widgets/meter.css
new file mode 100644
index 0000000..df65382
--- /dev/null
+++ b/modules/home/desktop/components/eww/eww/widgets/meter.css
@@ -0,0 +1,9 @@
+.meter .background {
+ color: @bg1;
+ background: rgba(0, 0, 0, 0);
+}
+
+.meter .progress {
+ color: @accent;
+ background: rgba(0, 0, 0, 0);
+}
diff --git a/modules/home/desktop/components/eww/eww/widgets/meter.yuck b/modules/home/desktop/components/eww/eww/widgets/meter.yuck
new file mode 100644
index 0000000..af2c3f3
--- /dev/null
+++ b/modules/home/desktop/components/eww/eww/widgets/meter.yuck
@@ -0,0 +1,41 @@
+(defwidget meter [value label]
+ (overlay :class {"meter"
+ + (value >= 90 ? " almost-full" : "")
+ + (value >= 99 ? " full" : "")
+ + (value <= 10 ? " almost-empty" : "")
+ + (value <= 1 ? " empty" : "")
+ }
+
+ :width 100
+
+ (circular-progress :class "background"
+ :value 80
+ :start-at 35
+ :thickness 10
+ :width 100
+ )
+
+ (circular-progress :class "progress"
+ :value {value*0.8}
+ :start-at 35
+ :thickness 10
+ :width 100
+ )
+
+ (box
+ :orientation "v"
+ :valign "center"
+ :space-evenly false
+ :spacing 2
+
+ (children)
+
+ {round(value, 2)+"%"}
+ )
+
+ (transform
+ :translate-y "44px"
+ (label :markup {"<b>"+label+"</b>"})
+ )
+ )
+)
diff --git a/modules/home/desktop/components/eww/eww/widgets/stat.yuck b/modules/home/desktop/components/eww/eww/widgets/stat.yuck
new file mode 100644
index 0000000..1ef76f2
--- /dev/null
+++ b/modules/home/desktop/components/eww/eww/widgets/stat.yuck
@@ -0,0 +1,24 @@
+(defwidget stat [key value ?class]
+ (overlay
+ (box :class {class}
+ :orientation "h"
+ :spacing 45
+
+ (label
+ :text {key}
+ :halign "start"
+ :hexpand true
+ )
+
+ (label
+ :text {value}
+ :halign "end"
+ :hexpand true
+ )
+ )
+
+ (label :class "faint"
+ :text "..."
+ )
+ )
+)
diff --git a/modules/home/desktop/components/eww/eww/windows/default.yuck b/modules/home/desktop/components/eww/eww/windows/default.yuck
new file mode 100644
index 0000000..77e8cf3
--- /dev/null
+++ b/modules/home/desktop/components/eww/eww/windows/default.yuck
@@ -0,0 +1,2 @@
+(include "./windows/sys.yuck")
+(include "./windows/music.yuck")
diff --git a/modules/home/desktop/components/eww/eww/windows/music.yuck b/modules/home/desktop/components/eww/eww/windows/music.yuck
new file mode 100644
index 0000000..f83340b
--- /dev/null
+++ b/modules/home/desktop/components/eww/eww/windows/music.yuck
@@ -0,0 +1,19 @@
+(defwindow music [pos gaps]
+ :monitor "<primary>"
+ :geometry (geometry
+ :x {
+ pos == "right"
+ ? gaps == "true"
+ ? "-8px" : "2px"
+ : "0px"
+ }
+ :y { gaps == "true" ? "-8px" : "2px" }
+ :width 512
+ :anchor { pos == "right" ? "bottom right" : "bottom center" }
+ )
+ :stacking "fg"
+ :windowtype "dock"
+ :wm-ignore true
+
+ (music)
+)
diff --git a/modules/home/desktop/components/eww/eww/windows/net.yuck b/modules/home/desktop/components/eww/eww/windows/net.yuck
new file mode 100644
index 0000000..8c5c299
--- /dev/null
+++ b/modules/home/desktop/components/eww/eww/windows/net.yuck
@@ -0,0 +1,35 @@
+(box :class "panel"
+ :orientation "v"
+ :spacing 8
+ :space-evenly true
+ :height {100+16}
+ :width {(100+8)*3+8}
+
+ (graph
+ :value {net.rx}
+ :thickness 2
+ :time-range "30s"
+ :min 0
+ :max 100
+ :dynamic true
+ :line-style "round"
+ )
+
+ {"Download: " + round(net.rx/1024/1024, 2) + " MiB/s (peak: " + round(net.rx_peak/1024/1024, 2) + " MiB/s)"}
+
+ (graph
+ :value {net.tx}
+ :thickness 2
+ :time-range "30s"
+ :min 0
+ :max 100
+ :dynamic true
+ :line-style "round"
+ )
+
+ {"Upload: " + round(net.tx/1024/1024, 2) + " MiB/s (peak: " + round(net.tx_peak/1024/1024, 2) + " MiB/s)"}
+)
+
+(deflisten net
+ `/home/c/net.sh`
+)
diff --git a/modules/home/desktop/components/eww/eww/windows/sys.yuck b/modules/home/desktop/components/eww/eww/windows/sys.yuck
new file mode 100644
index 0000000..fa6a719
--- /dev/null
+++ b/modules/home/desktop/components/eww/eww/windows/sys.yuck
@@ -0,0 +1,84 @@
+(defwindow sys
+ :monitor "<primary>"
+ ;:monitor "HDMI-A-0"
+ :geometry (geometry
+ :x "0px"
+ :y "0px"
+ :anchor "center"
+ )
+ :stacking "fg"
+ :windowtype "dialog"
+ :wm-ignore false
+
+ (box :class "main"
+ :orientation "v"
+ :spacing 8
+ :space-evenly false
+
+ (bar)
+
+ (box
+ :orientation "h"
+ :spacing 8
+ :space-evenly false
+
+ (box
+ :orientation "v"
+ :spacing 8
+ :space-evenly false
+
+ (disks)
+
+ (box
+ :orientation "h"
+ :spacing 8
+ :space-evenly false
+
+ (zfs)
+
+ (box :class "unpadded panel"
+ (image
+ :path "/home/c/Pictures/suit ryo.png"
+ :image-width 134
+ )
+ )
+ )
+
+ (centerbox :class "panel"
+ (image
+ :path "/home/c/Pictures/car.png"
+ :image-height 13
+ )
+
+ "silly zone :3"
+
+ (image
+ :path "/home/c/Pictures/car.png"
+ :image-height 13
+ )
+ )
+
+ (memory)
+ (cpu)
+ )
+
+ (box
+ :orientation "v"
+ :spacing 8
+ :space-evenly false
+
+ (launcher)
+
+ (box
+ :orientation "h"
+ :spacing 8
+ :space-evenly false
+
+ (box :hexpand true (music))
+
+ (volume)
+ )
+ )
+ )
+ )
+)
diff --git a/modules/home/desktop/components/fcitx5/default.nix b/modules/home/desktop/components/fcitx5/default.nix
new file mode 100644
index 0000000..0eb0a4c
--- /dev/null
+++ b/modules/home/desktop/components/fcitx5/default.nix
@@ -0,0 +1,82 @@
+{ options, config, osConfig, lib, pkgs, namespace, ... }:
+
+with lib; with lib.${namespace}; let
+ cfg = config.${namespace}.desktop.components.fcitx5;
+ oscfg = osConfig.${namespace}.hardware.keyboard.jp;
+ desktop = config.${namespace}.desktop;
+ impermanence = config.${namespace}.impermanence;
+in {
+ options.${namespace}.desktop.components.fcitx5 = with types; {
+ enable = mkEnableOption "fcitx5 theming";
+ };
+
+ config = mkIf (cfg.enable && oscfg.enable) {
+ #TODO: investigate generating config files instead of persisting
+ home.persistence.${impermanence.location} = {
+ directories = [
+ ".config/fcitx"
+ ".config/fcitx5"
+ ];
+ };
+
+ xdg.dataFile."fcitx5/themes/nix-theme/theme.conf".source = let
+ c = desktop.theme.colors;
+ in (pkgs.formats.ini {}).generate "fcitx5-theme.conf" {
+ "Metadata" = {
+ Name = "nix-theme";
+ Author = "CartConnoisseur";
+ Description = "Theme generated by NixOS";
+ Version = 1;
+ };
+
+ "InputPanel" = {
+ NormalColor = "#${c.fg}";
+ HighlightColor = "#${c.fg}";
+ HighlightBackgroundColor = "#00000000";
+ HighlightCandidateColor = "#${c.bg}";
+
+ FullWidthHighlight = true;
+ PageButtonAlignment = "Last Candidate";
+ };
+
+ "InputPanel/Background" = {
+ Color = "#${c.bg}";
+ BorderColor = "#${c.fg1}";
+ BorderWidth = 2;
+ };
+
+ # "InputPanel/Background/Margin" = {
+ # Left = 10;
+ # Right = 10;
+ # Top = 10;
+ # Bottom = 10;
+ # };
+
+ "InputPanel/Highlight" = {
+ Color = "#${c.fg}";
+ BorderWidth = 0;
+ };
+
+ "InputPanel/Highlight/Margin" = {
+ Left = 2;
+ Right = 2;
+ Top = 2;
+ Bottom = 2;
+ };
+
+ "InputPanel/ContentMargin" = {
+ Left = 2;
+ Right = 2;
+ Top = 2;
+ Bottom = 2;
+ };
+
+ "InputPanel/TextMargin" = {
+ Left = 5;
+ Right = 5;
+ Top = 5;
+ Bottom = 5;
+ };
+ };
+ };
+}
diff --git a/modules/home/desktop/components/gtk/default.nix b/modules/home/desktop/components/gtk/default.nix
new file mode 100644
index 0000000..a20cc1f
--- /dev/null
+++ b/modules/home/desktop/components/gtk/default.nix
@@ -0,0 +1,26 @@
+{ options, config, lib, pkgs, namespace, ... }:
+
+with lib; with lib.${namespace}; let
+ cfg = config.${namespace}.desktop.components.gtk;
+in {
+ options.${namespace}.desktop.components.gtk = with types; {
+ enable = mkEnableOption "gtk";
+ };
+
+ config = mkIf cfg.enable {
+ gtk = {
+ enable = true;
+
+ #TODO: dynamic theming
+ theme = {
+ package = pkgs.gruvbox-gtk-theme;
+ name = "Gruvbox-Dark";
+ };
+
+ font = {
+ name = "monospace";
+ size = 8;
+ };
+ };
+ };
+}
diff --git a/modules/home/desktop/components/i3/default.nix b/modules/home/desktop/components/i3/default.nix
new file mode 100644
index 0000000..cf9ed91
--- /dev/null
+++ b/modules/home/desktop/components/i3/default.nix
@@ -0,0 +1,257 @@
+{ options, config, lib, pkgs, namespace, ... }:
+
+with lib; with lib.${namespace}; let
+ cfg = config.${namespace}.desktop.components.i3;
+ desktop = config.${namespace}.desktop;
+in {
+ options.${namespace}.desktop.components.i3 = with types; {
+ enable = mkEnableOption "i3";
+ };
+
+ config = mkIf cfg.enable {
+ #TODO: these probably shouldnt go here
+ home.packages = with pkgs; [
+ kdePackages.breeze
+ ];
+
+ home.file.".Xresources".text = ''
+ Xcursor.size: 24
+ Xcursor.theme: breeze_cursors
+ '';
+
+ xsession.windowManager.i3 = {
+ enable = true;
+ config = let
+ #NOTE: Alt (Mod1) and meta (Mod4) have been swapped by keyd.
+ mod = "Mod4";
+
+ ws0 = "0:Main";
+ ws1 = "1:Terminal";
+ ws2 = "2:Browser";
+ ws3 = "3:Chat";
+ ws4 = "4:Gaming";
+ ws5 = "5";
+ ws6 = "6";
+ ws7 = "7";
+ ws8 = "8:Meow";
+ ws9 = "9:Music";
+ ws10 = "10:Misc";
+ ws11 = "11:Empty";
+
+ output = {
+ primary = "primary";
+ left = "DVI-D-0";
+ right = "DisplayPort-1 HDMI-A-0";
+ };
+ in {
+ modifier = "${mod}";
+
+ fonts = {
+ names = [ "monospace" ];
+ size = 8.0;
+ };
+
+ colors = let c = desktop.theme.colors; in {
+ focused = {
+ border = "#${c.fg2}";
+ background = "#${c.fg2}";
+ text = "#${c.bg}";
+ indicator = "#${c.fg2}";
+ childBorder = "#${c.fg2}";
+ };
+
+ focusedInactive = {
+ border = "#${c.bg1}";
+ background = "#${c.bg1}";
+ text = "#${c.fg}";
+ indicator = "#${c.bg1}";
+ childBorder = "#${c.bg1}";
+ };
+
+ unfocused = {
+ border = "#${c.bg}";
+ background = "#${c.bg}";
+ text = "#${c.fg}";
+ indicator = "#${c.bg}";
+ childBorder = "#${c.bg}";
+ };
+ };
+
+ gaps.inner = 8;
+
+ workspaceOutputAssign = [
+ { workspace = "${ws0}"; output = output.primary; }
+ { workspace = "${ws1}"; output = output.primary; }
+
+ { workspace = "${ws2}"; output = output.left; }
+ { workspace = "${ws3}"; output = output.left; }
+
+ { workspace = "${ws4}"; output = output.primary; }
+
+ { workspace = "${ws5}"; output = output.primary; }
+ { workspace = "${ws6}"; output = output.primary; }
+ { workspace = "${ws7}"; output = output.primary; }
+
+ { workspace = "${ws8}"; output = output.primary; }
+ { workspace = "${ws9}"; output = output.right; }
+ { workspace = "${ws10}"; output = output.primary; }
+
+ { workspace = "${ws11}"; output = output.primary; }
+ ];
+
+ assigns = {
+ "${ws2}" = [ { class = "firefox"; } ];
+ "${ws3}" = [ { class = "discord"; } ];
+ "${ws4}" = [
+ { class = "steam"; }
+ { class = "prismlauncher"; }
+ ];
+
+ "${ws8}" = [ { class = "qbittorrent"; } ];
+ "${ws9}" = [ { title = "cmus"; } ];
+ };
+
+ startup = [
+ { command = "polybar-msg cmd quit; polybar"; always = true; notification = false; }
+ { command = "systemctl --user restart picom"; always = true; notification = false; }
+ { command = "${pkgs.feh}/bin/feh --bg-fill ${desktop.background}"; always = true; notification = false; }
+ ] ++ optionals desktop.components.fcitx5.enable [
+ { command = "fcitx5 -dr"; always = true; notification = false; }
+ ];
+
+ keybindings = {
+ "${mod}+Shift+c" = "reload";
+ "${mod}+Shift+r" = "restart";
+ "${mod}+Shift+e" = "exec \"i3-nagbar -t warning -m 'You pressed the exit shortcut. Do you really want to exit i3? This will end your X session.' -B 'Yes, exit i3' 'i3-msg exit'\"";
+
+ "${mod}+q" = "kill";
+ "${mod}+d" = "exec \"rofi -modi drun,run -show drun\"";
+ "${mod}+Return" = "exec ${pkgs.kitty}/bin/kitty";
+
+ "${mod}+Num_Lock" = "exec --no-startup-id polybar-msg cmd toggle";
+
+ # Screenshots
+ #TODO: screen and full should be swapped, but currently screen is fucky :'(
+ "Shift+Print" = "exec --no-startup-id ${pkgs.flameshot}/bin/flameshot screen -c";
+ "Print" = "exec --no-startup-id ${pkgs.flameshot}/bin/flameshot full -c";
+ "${mod}+Shift+s" = "exec --no-startup-id ${pkgs.flameshot}/bin/flameshot gui -c";
+ "Mod1+Shift+s" = "exec --no-startup-id ${pkgs.flameshot}/bin/flameshot gui -c";
+ "${mod}+Ctrl+Shift+s" = "exec --no-startup-id ${pkgs.flameshot}/bin/flameshot launcher -c";
+
+ # Media keys
+ "XF86AudioRaiseVolume" = "exec --no-startup-id ${pkgs.pulseaudio}/bin/pactl set-sink-volume @DEFAULT_SINK@ +2%";
+ "XF86AudioLowerVolume" = "exec --no-startup-id ${pkgs.pulseaudio}/bin/pactl set-sink-volume @DEFAULT_SINK@ -2%";
+ "XF86AudioMute" = "exec --no-startup-id ${pkgs.pulseaudio}/bin/pactl set-sink-mute @DEFAULT_SINK@ toggle";
+ "XF86AudioMicMute" = "exec --no-startup-id ${pkgs.pulseaudio}/bin/pactl set-source-mute @DEFAULT_SOURCE@ toggle";
+
+ "XF86AudioPlay" = "exec --no-startup-id \"playerctl --player=cmus,firefox,%any play-pause\"";
+ "XF86AudioPause" = "exec --no-startup-id \"playerctl --player=cmus,firefox,%any play-pause\"";
+ "XF86AudioStop" = "exec --no-startup-id \"playerctl --player=cmus,firefox,%any stop\"";
+ "XF86AudioNext" = "exec --no-startup-id \"playerctl --player=cmus,firefox,%any next\"";
+ "XF86AudioPrev" = "exec --no-startup-id \"playerctl --player=cmus,firefox,%any previous\"";
+
+ # Media controller widget
+ "${mod}+m" = "exec --no-startup-id eww-toggle music --arg pos=center --arg gaps=false";
+ "${mod}+Ctrl+m" = "exec --no-startup-id eww-toggle music --arg pos=right --arg gaps=true";
+ "${mod}+Shift+m" = "exec --no-startup-id eww-toggle music --arg pos=center --arg gaps=true";
+ "${mod}+Shift+Ctrl+m" = "exec --no-startup-id eww-toggle music --arg pos=right --arg gaps=false";
+
+ # Workspaces
+ "${mod}+grave" = "workspace number ${ws0}";
+ "${mod}+1" = "workspace number ${ws1}";
+ "${mod}+2" = "workspace number ${ws2}";
+ "${mod}+3" = "workspace number ${ws3}";
+ "${mod}+4" = "workspace number ${ws4}";
+ "${mod}+5" = "workspace number ${ws5}";
+ "${mod}+6" = "workspace number ${ws6}";
+ "${mod}+7" = "workspace number ${ws7}";
+ "${mod}+8" = "workspace number ${ws8}";
+ "${mod}+9" = "workspace number ${ws9}";
+ "${mod}+0" = "workspace number ${ws10}";
+ "${mod}+equal" = "workspace number ${ws11}";
+
+ # Move active workspace
+ "${mod}+comma" = "move workspace to output ${output.left}";
+ "${mod}+period" = "move workspace to output ${output.primary}";
+ "${mod}+slash" = "move workspace to output ${output.right}";
+
+ # Layout
+ "${mod}+z" = "layout stacking";
+ "${mod}+x" = "layout tabbed";
+ "${mod}+c" = "layout toggle split";
+
+ # Focus
+ "${mod}+h" = "focus left";
+ "${mod}+j" = "focus down";
+ "${mod}+k" = "focus up";
+ "${mod}+l" = "focus right";
+
+ "${mod}+Left" = "focus left";
+ "${mod}+Down" = "focus down";
+ "${mod}+Up" = "focus up";
+ "${mod}+Right" = "focus right";
+
+ "${mod}+space" = "focus mode_toggle";
+ "${mod}+a" = "focus parent";
+
+ # Move focused container
+ "${mod}+Shift+h" = "move left";
+ "${mod}+Shift+j" = "move down";
+ "${mod}+Shift+k" = "move up";
+ "${mod}+Shift+l" = "move right";
+
+ "${mod}+Shift+Left" = "move left";
+ "${mod}+Shift+Down" = "move down";
+ "${mod}+Shift+Up" = "move up";
+ "${mod}+Shift+Right" = "move right";
+
+ # Misc container binds
+ "${mod}+Shift+space" = "floating toggle";
+ "${mod}+f" = "fullscreen toggle";
+
+ "${mod}+w" = "split h";
+ "${mod}+e" = "split v";
+
+ "${mod}+r" = "mode resize";
+
+ # Move focused container to workspace
+ "${mod}+Shift+grave" = "move container to workspace number ${ws0}";
+ "${mod}+Shift+1" = "move container to workspace number ${ws1}";
+ "${mod}+Shift+2" = "move container to workspace number ${ws2}";
+ "${mod}+Shift+3" = "move container to workspace number ${ws3}";
+ "${mod}+Shift+4" = "move container to workspace number ${ws4}";
+ "${mod}+Shift+5" = "move container to workspace number ${ws5}";
+ "${mod}+Shift+6" = "move container to workspace number ${ws6}";
+ "${mod}+Shift+7" = "move container to workspace number ${ws7}";
+ "${mod}+Shift+8" = "move container to workspace number ${ws8}";
+ "${mod}+Shift+9" = "move container to workspace number ${ws9}";
+ "${mod}+Shift+0" = "move container to workspace number ${ws10}";
+ };
+
+ modes = {
+ resize = {
+ "h" = "resize shrink width 10 px or 10 ppt";
+ "j" = "resize grow height 10 px or 10 ppt";
+ "k" = "resize shrink height 10 px or 10 ppt";
+ "l" = "resize grow width 10 px or 10 ppt";
+
+ "Left" = "resize shrink width 10 px or 10 ppt";
+ "Down" = "resize grow height 10 px or 10 ppt";
+ "Up" = "resize shrink height 10 px or 10 ppt";
+ "Right" = "resize grow width 10 px or 10 ppt";
+
+ "Return" = "mode default";
+ "Escape" = "mode default";
+ "${mod}+r" = "mode default";
+ };
+ };
+
+ bars = [];
+ };
+
+ extraConfig = ''
+ default_border normal 0
+ '';
+ };
+ };
+}
diff --git a/modules/home/desktop/components/picom/default.nix b/modules/home/desktop/components/picom/default.nix
new file mode 100644
index 0000000..698e06c
--- /dev/null
+++ b/modules/home/desktop/components/picom/default.nix
@@ -0,0 +1,30 @@
+{ options, config, lib, namespace, ... }:
+
+with lib; with lib.${namespace}; let
+ cfg = config.${namespace}.desktop.components.picom;
+in {
+ options.${namespace}.desktop.components.picom = with types; {
+ enable = mkEnableOption "picom";
+ };
+
+ config = mkIf cfg.enable {
+ services.picom = {
+ enable = true;
+
+ backend = "glx";
+ vSync = true;
+
+ settings = {
+ blur = {
+ method = "gaussian";
+ size = 10;
+ deviation = 2;
+ };
+
+ blur-background-exclude = [
+ "window_type = 'dock'"
+ ];
+ };
+ };
+ };
+}
diff --git a/modules/home/desktop/components/polybar/default.nix b/modules/home/desktop/components/polybar/default.nix
new file mode 100644
index 0000000..d7ee363
--- /dev/null
+++ b/modules/home/desktop/components/polybar/default.nix
@@ -0,0 +1,278 @@
+{ options, config, lib, pkgs, namespace, ... }:
+
+with lib; with lib.${namespace}; let
+ cfg = config.${namespace}.desktop.components.polybar;
+ desktop = config.${namespace}.desktop;
+in {
+ options.${namespace}.desktop.components.polybar = with types; {
+ enable = mkEnableOption "polybar";
+ };
+
+ config = mkIf cfg.enable {
+ services.polybar = {
+ enable = true;
+ script = "";
+
+ package = pkgs.polybar.override {
+ i3Support = true;
+ pulseSupport = true;
+ };
+
+ settings = let c = desktop.theme.colors; in {
+ "bar/main" = {
+ width = "100%";
+ height = "24pt";
+ radius = 0;
+
+ background = "#${c.bg}";
+ foreground = "#${c.fg}";
+
+ font = [
+ "Symbols Nerd Font:size=16;2"
+ "monospace:size=11;2"
+ "Sauce Code Pro Nerd Font:size=11;2"
+ "Noto Sans CJK JP:size=11;1"
+ "sans-serif:size=11;1"
+ ];
+
+ border = {
+ top = "8px";
+ left = "8px";
+ right = "8px";
+
+ color = "#00000000";
+ };
+
+ padding = {
+ left = 2;
+ right = 2;
+ };
+
+ cursor = {
+ click = "pointer";
+ scroll = "ns-resize";
+ };
+
+ enable-ipc = true;
+
+ line.size = "3pt";
+
+ separator = {
+ text = "|";
+ foreground = "#${c.bg3}";
+ };
+
+ module.margin = 1;
+ modules = {
+ left = "stat music";
+ center = "i3";
+ right = "wlan eth filesystem keyboard xkeyboard pulseaudio date";
+ };
+ };
+
+ "module/keyboard" = {
+ type = "custom/script";
+
+ exec = "if [[ $(fcitx5-remote -n) == 'mozc' ]]; then printf 'jp'; else printf 'en'; fi";
+ interval = 1;
+
+ click.left = "${pkgs.fcitx5}/bin/fcitx5-remote -t";
+
+ format = {
+ prefix = {
+ text = "󰌌 ";
+ foreground = "#${c.accent}";
+ };
+ };
+ };
+
+ "module/music" = {
+ type = "custom/script";
+
+ exec = "playerctl --player=cmus,firefox,%any -F metadata --format='{{title}} - {{artist}}'";
+ tail = true;
+
+ format = {
+ prefix = {
+ text = "󰎄 ";
+ foreground = "#${c.accent}";
+ };
+ };
+ };
+
+ "module/stat" = {
+ type = "custom/script";
+
+ exec = "vmstat -n 2 | awk '{printf \"%.0f%% %.2f GiB\\\\n\", 100-$15, (31998756-($4+$5+$6))/1024/1024};fflush()'";
+ tail = true;
+
+ format = {
+ prefix = {
+ text = "󱕍 ";
+ foreground = "#${c.accent}";
+ };
+ };
+ };
+
+ "module/i3" = {
+ type = "internal/i3";
+
+ strip-wsnumbers = true;
+ index-sort = true;
+
+ ws.icon = [
+ "0:Main;󱄅" "1:Terminal;" "2:Browser;󰈹" "3:Chat;󰙯" "4:Gaming;󰓓"
+ "5;󰎱" "6;󰎳" "7;󰎶"
+ "8:Meow;󰄛" "9:Music;󰲸" "10:Misc;󰁴"
+ ];
+
+ label = {
+ focused = {
+ text = "%icon%";
+ padding = 2;
+
+ foreground = "#${c.fg0}";
+ background = "#${c.bg1}";
+ underline = "#${c.accent}";
+ };
+
+ visible = {
+ text = "%icon%";
+ padding = 2;
+
+ underline = "#${c.fg4}";
+ };
+
+ unfocused = {
+ text = "%icon%";
+ padding = 2;
+ };
+
+ urgent = {
+ text = "%icon%";
+ padding = 2;
+
+ foreground = "#${c.bg}";
+ background = "#${c.accent}";
+ };
+ };
+ };
+
+ "module/xwindow" = {
+ type = "internal/xwindow";
+ label = "%title:0:64:...%";
+ };
+
+
+ "module/pulseaudio" = {
+ type = "internal/pulseaudio";
+
+ format.volume = "<ramp-volume> <label-volume>";
+
+ label = {
+ volume = "%percentage%%";
+ muted = {
+ text = "󰝟 %percentage%%";
+ foreground = "#${c.bg3}";
+ };
+ };
+
+ ramp.volume = {
+ text = [ "󰕿" "󰖀" "󰕾" ];
+ foreground = "#${c.accent}";
+ };
+ };
+
+ "module/xkeyboard" = {
+ type = "internal/xkeyboard";
+ blacklist = [ "num lock" ];
+
+ indicator.icon = [ "caps lock;;󰌎" ];
+
+ format = {
+ text = "<label-indicator>";
+ };
+
+ label = {
+ indicator.on = "%icon%";
+ };
+ };
+
+ "module/cpu" = {
+ type = "internal/cpu";
+ interval = 2;
+
+ format.prefix = {
+ text = "CPU ";
+ foreground = "#${c.accent}";
+ };
+
+ label = "%percentage%%";
+ };
+
+ "module/memory" = {
+ type = "internal/memory";
+ interval = 2;
+
+ format.prefix = {
+ text = "MEM ";
+ foreground = "#${c.accent}";
+ };
+
+ label = "%gb_used%";
+ };
+
+ "module/filesystem" = {
+ type = "internal/fs";
+ interval = 25;
+
+ mount = [ "/nix" "/persist" ];
+
+ label = {
+ mounted = "%{F#${c.accent}}󰋊%{F-} %used%";
+ unmounted = {
+ text = "%mountpoint%";
+ foreground = "#${c.bg3}";
+ };
+ };
+ };
+
+ "module/eth" = {
+ type = "internal/network";
+ interface.type = "wired";
+ interval = 2;
+
+ format.connected = "<label-connected>";
+ label.connected = "%{F#${c.accent}}󰈀%{F-} 󰄼 %downspeed% 󰄿 %upspeed%";
+ };
+
+ "module/wlan" = {
+ type = "internal/network";
+ interface.type = "wireless";
+ interval = 2;
+
+ format.connected = "<ramp-signal> <label-connected>";
+ label.connected = "󰄼 %downspeed% 󰄿 %upspeed%";
+
+ ramp-signal = {
+ text = [ "󰤯" "󰤟" "󰤢" "󰤥" "󰤨" ];
+ foreground = "#${c.accent}";
+ };
+ };
+
+ "module/date" = {
+ type = "internal/date";
+ interval = 1;
+
+ date = "%H:%M";
+ date-alt = "%Y-%m-%d %H:%M:%S";
+
+ format.prefix = {
+ text = "󰃰 ";
+ foreground = "#${c.accent}";
+ };
+ };
+ };
+ };
+ };
+}
diff --git a/modules/home/desktop/components/rofi/default.nix b/modules/home/desktop/components/rofi/default.nix
new file mode 100644
index 0000000..a1dbe33
--- /dev/null
+++ b/modules/home/desktop/components/rofi/default.nix
@@ -0,0 +1,58 @@
+{ options, config, lib, namespace, ... }:
+
+with lib; with lib.${namespace}; let
+ cfg = config.${namespace}.desktop.components.rofi;
+ desktop = config.${namespace}.desktop;
+in {
+ options.${namespace}.desktop.components.rofi = with types; {
+ enable = mkEnableOption "rofi";
+ };
+
+ config = mkIf cfg.enable {
+ programs.rofi = {
+ enable = true;
+
+ font = "monospace 12";
+
+ theme = let
+ inherit (config.lib.formats.rasi) mkLiteral;
+ c = desktop.theme.colors;
+ in {
+ "@import" = "default";
+
+ "*" = {
+ background = mkLiteral "#${c.bg}";
+ foreground = mkLiteral "#${c.fg}";
+ foreground-alt = mkLiteral "#${c.bg3}";
+
+ alternate-normal-background = mkLiteral "var(background)";
+
+ selected-normal-foreground = mkLiteral "var(background)";
+ selected-normal-background = mkLiteral "#${c.accent}";
+
+ border-color = mkLiteral "var(background)";
+ separatorcolor = mkLiteral "#${c.bg3}";
+ };
+
+ inputbar = {
+ children = map mkLiteral [ "entry" "num-filtered-rows" "textbox-num-sep" "num-rows" ];
+ };
+
+ element = {
+ children = map mkLiteral [ "element-icon" "element-text" ];
+ };
+
+ entry.placeholder = "";
+
+ scrollbar.handle-color = mkLiteral "var(foreground-alt)";
+ num-rows.text-color = mkLiteral "var(foreground-alt)";
+ num-filtered-rows.text-color = mkLiteral "var(foreground-alt)";
+ textbox-num-sep.text-color = mkLiteral "var(foreground-alt)";
+
+ message.border = mkLiteral "1px solid 0px 0px";
+ listview.border = mkLiteral "1px solid 0px 0px";
+ sidebar.border = mkLiteral "1px solid 0px 0px";
+ };
+ };
+ };
+}
diff --git a/modules/home/desktop/default.nix b/modules/home/desktop/default.nix
new file mode 100644
index 0000000..e89ec86
--- /dev/null
+++ b/modules/home/desktop/default.nix
@@ -0,0 +1,55 @@
+{ options, config, lib, namespace, ... }:
+
+with lib; with lib.${namespace}; let
+ cfg = config.${namespace}.desktop;
+in {
+ options.${namespace}.desktop = with types; {
+ background = mkOption {
+ type = enum [
+ "lycoris.png"
+ "matama.png"
+ "mem.png"
+ "nonon.png"
+ "ryo.png"
+ "shinobu.png"
+ "skull.png"
+ ];
+ apply = value: ./bg/${value};
+ };
+
+ theme = {
+ name = mkOption {
+ type = enum [ "gruvbox" ];
+ default = "gruvbox";
+ };
+
+ colors = let
+ mkColorOption = name: {
+ inherit name;
+ value = mkOption {
+ type = strMatching "[a-fA-F0-9]{6}";
+ default = "ff00ff";
+ example = "23ce94";
+ description = ''
+ Hex value for color "${name}".
+ '';
+ };
+ };
+ in listToAttrs (map mkColorOption [
+ "accent"
+
+ "black" "red" "green" "yellow" "blue" "magenta" "cyan" "white"
+ "brightBlack" "brightRed" "brightGreen" "brightYellow" "brightBlue" "brightMagenta" "brightCyan" "brightWhite"
+
+ "bg" "bg0" "bg1" "bg2" "bg3" "bg4"
+ "fg" "fg0" "fg1" "fg2" "fg3" "fg4"
+
+ "orange" "brightOrange"
+ ]);
+ };
+ };
+
+ config = {
+ cxl.desktop.theme.colors = import ./theme/${cfg.theme.name}.nix;
+ };
+}
diff --git a/modules/home/desktop/theme/gruvbox.nix b/modules/home/desktop/theme/gruvbox.nix
new file mode 100644
index 0000000..0bfb043
--- /dev/null
+++ b/modules/home/desktop/theme/gruvbox.nix
@@ -0,0 +1,26 @@
+{
+ accent = "cc241d";
+
+ black = "282828"; brightBlack = "928374";
+ red = "cc241d"; brightRed = "fb4934";
+ green = "98971a"; brightGreen = "b8bb26";
+ yellow = "d79921"; brightYellow = "fabd2f";
+ blue = "458588"; brightBlue = "83a598";
+ magenta = "b16286"; brightMagenta = "d3869b";
+ cyan = "689d6a"; brightCyan = "8ec07c";
+ white = "a89984"; brightWhite = "ebdbb2";
+
+ bg = "282828";
+ bg0 = "282828";
+ bg1 = "3c3836";
+ bg2 = "504945";
+ bg3 = "665c54";
+ bg4 = "7c6f64";
+
+ fg = "ebdbb2";
+ fg0 = "fbf1c7";
+ fg1 = "ebdbb2";
+ fg2 = "d5c4a1";
+ fg3 = "bdae93";
+ fg4 = "a89984";
+}
diff --git a/modules/home/impermanence/default.nix b/modules/home/impermanence/default.nix
new file mode 100644
index 0000000..081946c
--- /dev/null
+++ b/modules/home/impermanence/default.nix
@@ -0,0 +1,52 @@
+{ options, config, osConfig, lib, namespace, inputs, host, ... }:
+
+with lib; with lib.${namespace}; let
+ cfg = config.${namespace}.impermanence // {
+ inherit (osConfig.${namespace}.system.impermanence.home) enable location secure;
+ };
+in {
+ imports = [
+ inputs.impermanence.nixosModules.home-manager.impermanence
+ ];
+
+ options.${namespace}.impermanence = with types; {
+ skeleton = mkOption {
+ type = bool;
+ default = true;
+ };
+
+ enable = mkOption { type = uniq bool; };
+ location = mkOption { type = uniq str; };
+ secure.location = mkOption { type = uniq str; };
+ };
+
+ config = {
+ ${namespace}.impermanence = {
+ inherit (cfg) enable location secure;
+ };
+
+ home.persistence.${cfg.location} = {
+ enable = cfg.enable;
+ allowOther = true;
+
+ directories = mkIf cfg.skeleton [
+ ".local/share/applications"
+ ".local/bin"
+
+ "Downloads"
+ "Documents"
+ "Pictures"
+ "Videos"
+ "Music"
+ "Games"
+ "Links"
+ "Persist"
+ ];
+ };
+
+ home.persistence.${cfg.secure.location} = {
+ enable = cfg.enable;
+ allowOther = false;
+ };
+ };
+}
diff --git a/modules/home/suites/common/default.nix b/modules/home/suites/common/default.nix
new file mode 100644
index 0000000..63ea042
--- /dev/null
+++ b/modules/home/suites/common/default.nix
@@ -0,0 +1,23 @@
+{ options, config, lib, namespace, ... }:
+
+with lib; with lib.${namespace}; let
+ cfg = config.${namespace}.suites.common;
+in {
+ options.${namespace}.suites.common = with types; {
+ enable = mkEnableOption "common";
+ };
+
+ config = mkIf cfg.enable {
+ cxl = {
+ tools = {
+ bash.enable = true;
+ vim.enable = true;
+ git.enable = true;
+ ssh.enable = true;
+ gpg.enable = true;
+ btop.enable = true;
+ zoxide.enable = true;
+ };
+ };
+ };
+}
diff --git a/modules/home/suites/desktop/default.nix b/modules/home/suites/desktop/default.nix
new file mode 100644
index 0000000..077843a
--- /dev/null
+++ b/modules/home/suites/desktop/default.nix
@@ -0,0 +1,32 @@
+{ options, config, lib, namespace, ... }:
+
+with lib; with lib.${namespace}; let
+ cfg = config.${namespace}.suites.desktop;
+in {
+ options.${namespace}.suites.desktop = with types; {
+ enable = mkEnableOption "desktop";
+ };
+
+ config = mkIf cfg.enable {
+ cxl = {
+ apps = {
+ kitty.enable = true;
+ flameshot.enable = true;
+ firefox.enable = true;
+ };
+
+ desktop.components = {
+ i3.enable = true;
+
+ polybar.enable = true;
+ rofi.enable = true;
+ picom.enable = true;
+ eww.enable = true;
+
+ gtk.enable = true;
+ fcitx5.enable = true;
+ };
+ };
+ };
+}
+
diff --git a/modules/home/suites/dev/default.nix b/modules/home/suites/dev/default.nix
new file mode 100644
index 0000000..eb1fef9
--- /dev/null
+++ b/modules/home/suites/dev/default.nix
@@ -0,0 +1,31 @@
+{ options, config, lib, namespace, ... }:
+
+with lib; with lib.${namespace}; let
+ cfg = config.${namespace}.suites.dev;
+ impermanence = config.${namespace}.impermanence;
+ desktop = config.${namespace}.suites.desktop;
+in {
+ options.${namespace}.suites.dev = with types; {
+ enable = mkEnableOption "dev";
+ };
+
+ config = mkIf cfg.enable {
+ home.persistence.${impermanence.location} = {
+ directories = [
+ "code"
+ ];
+ };
+
+ cxl = {
+ apps = {
+ vscode.enable = desktop.enable;
+ intellij.enable = desktop.enable;
+ };
+
+ tools = {
+ cloc.enable = true;
+ tmux.enable = true;
+ };
+ };
+ };
+}
diff --git a/modules/home/suites/gaming/default.nix b/modules/home/suites/gaming/default.nix
new file mode 100644
index 0000000..f72af27
--- /dev/null
+++ b/modules/home/suites/gaming/default.nix
@@ -0,0 +1,19 @@
+{ options, config, lib, namespace, ... }:
+
+with lib; with lib.${namespace}; let
+ cfg = config.${namespace}.suites.gaming;
+in {
+ options.${namespace}.suites.gaming = with types; {
+ enable = mkEnableOption "gaming";
+ };
+
+ config = mkIf cfg.enable {
+ cxl = {
+ apps = {
+ steam.enable = true;
+ prismlauncher.enable = true;
+ lutris.enable = true;
+ };
+ };
+ };
+}
diff --git a/modules/home/suites/media/default.nix b/modules/home/suites/media/default.nix
new file mode 100644
index 0000000..b99d064
--- /dev/null
+++ b/modules/home/suites/media/default.nix
@@ -0,0 +1,26 @@
+{ options, config, lib, namespace, ... }:
+
+with lib; with lib.${namespace}; let
+ cfg = config.${namespace}.suites.media;
+in {
+ options.${namespace}.suites.media = with types; {
+ enable = mkEnableOption "media";
+ };
+
+ config = mkIf cfg.enable {
+ cxl = {
+ apps = {
+ feh.enable = true;
+ mpv.enable = true;
+
+ cmus.enable = true;
+
+ jellyfin.enable = true;
+ };
+
+ tools = {
+ ffmpeg.enable = true;
+ };
+ };
+ };
+}
diff --git a/modules/home/suites/misc/default.nix b/modules/home/suites/misc/default.nix
new file mode 100644
index 0000000..61cfbed
--- /dev/null
+++ b/modules/home/suites/misc/default.nix
@@ -0,0 +1,23 @@
+{ options, config, lib, namespace, ... }:
+
+with lib; with lib.${namespace}; let
+ cfg = config.${namespace}.suites.misc;
+in {
+ options.${namespace}.suites.misc = with types; {
+ enable = mkEnableOption "misc";
+ };
+
+ config = mkIf cfg.enable {
+ cxl = {
+ apps = {
+ fastfetch.enable = true;
+ pfetch.enable = true;
+ cmatrix.enable = true;
+ asciiquarium.enable = true;
+ pipes.enable = true;
+ cowsay.enable = true;
+ figlet.enable = true;
+ };
+ };
+ };
+}
diff --git a/modules/home/tools/bash/default.nix b/modules/home/tools/bash/default.nix
new file mode 100644
index 0000000..d0f0d9d
--- /dev/null
+++ b/modules/home/tools/bash/default.nix
@@ -0,0 +1,15 @@
+{ options, config, lib, pkgs, namespace, ... }:
+
+with lib; with lib.${namespace}; let
+ cfg = config.${namespace}.tools.bash;
+in {
+ options.${namespace}.tools.bash = with types; {
+ enable = mkEnableOption "bash";
+ };
+
+ config = mkIf cfg.enable {
+ programs.bash = {
+ enable = true;
+ };
+ };
+}
diff --git a/modules/home/tools/btop/default.nix b/modules/home/tools/btop/default.nix
new file mode 100644
index 0000000..87528a1
--- /dev/null
+++ b/modules/home/tools/btop/default.nix
@@ -0,0 +1,15 @@
+{ options, config, lib, namespace, ... }:
+
+with lib; with lib.${namespace}; let
+ cfg = config.${namespace}.tools.btop;
+in {
+ options.${namespace}.tools.btop = with types; {
+ enable = mkEnableOption "btop";
+ };
+
+ config = mkIf cfg.enable {
+ programs.btop = {
+ enable = true;
+ };
+ };
+}
diff --git a/modules/home/tools/default.nix b/modules/home/tools/default.nix
new file mode 100644
index 0000000..9627d0f
--- /dev/null
+++ b/modules/home/tools/default.nix
@@ -0,0 +1,15 @@
+{ lib, pkgs, namespace, ... }:
+
+with lib; with lib.${namespace}; {
+ imports = with pkgs; [
+ (mkSimpleTool "cloc" {})
+ (mkSimpleTool "ffmpeg" {})
+ (mkSimpleTool "wine" {
+ packages = [
+ wineWowPackages.stable
+ winetricks
+ ];
+ persist = [ ".wine" ];
+ })
+ ];
+}
diff --git a/modules/home/tools/git/default.nix b/modules/home/tools/git/default.nix
new file mode 100644
index 0000000..1780d80
--- /dev/null
+++ b/modules/home/tools/git/default.nix
@@ -0,0 +1,45 @@
+{ options, config, lib, namespace, ... }:
+
+with lib; with lib.${namespace}; let
+ cfg = config.${namespace}.tools.git;
+in {
+ options.${namespace}.tools.git = with types; {
+ enable = mkEnableOption "git";
+
+ name = mkOption {
+ type = str;
+ };
+
+ email = mkOption {
+ type = str;
+ };
+
+ key = mkOption {
+ type = nullOr str;
+ };
+
+ sign = mkOption {
+ type = bool;
+ default = true;
+ };
+ };
+
+ config = mkIf cfg.enable {
+ programs.git = {
+ enable = true;
+
+ userName = cfg.name;
+ userEmail = cfg.email;
+
+ signing = {
+ key = cfg.key;
+ signByDefault = cfg.sign;
+ };
+
+ ignores = [
+ "*~"
+ "*.swp"
+ ];
+ };
+ };
+}
diff --git a/modules/home/tools/gpg/default.nix b/modules/home/tools/gpg/default.nix
new file mode 100644
index 0000000..297d9d0
--- /dev/null
+++ b/modules/home/tools/gpg/default.nix
@@ -0,0 +1,32 @@
+{ options, config, lib, pkgs, namespace, ... }:
+
+with lib; with lib.${namespace}; let
+ cfg = config.${namespace}.tools.gpg;
+ impermanence = config.${namespace}.impermanence;
+in {
+ options.${namespace}.tools.gpg = with types; {
+ enable = mkEnableOption "gpg";
+ };
+
+ config = mkIf cfg.enable {
+ home.persistence.${impermanence.secure.location} = {
+ directories = [
+ ".gnupg"
+ ];
+ };
+
+ programs.gpg.enable = true;
+
+ services.gpg-agent = {
+ enable = true;
+ enableSshSupport = true;
+ pinentryPackage = (pkgs.writeShellScriptBin "pinentry-wrapper" ''
+ if [[ -v DISPLAY ]]; then
+ exec ${pkgs.pinentry-gnome3}/bin/pinentry-gnome3 "$@"
+ fi
+
+ exec ${pkgs.pinentry-gnome3}/bin/pinentry-tty "$@"
+ '');
+ };
+ };
+}
diff --git a/modules/home/tools/ssh/default.nix b/modules/home/tools/ssh/default.nix
new file mode 100644
index 0000000..10139df
--- /dev/null
+++ b/modules/home/tools/ssh/default.nix
@@ -0,0 +1,20 @@
+{ options, config, lib, pkgs, namespace, ... }:
+
+with lib; with lib.${namespace}; let
+ cfg = config.${namespace}.tools.ssh;
+ impermanence = config.${namespace}.impermanence;
+in {
+ options.${namespace}.tools.ssh = with types; {
+ enable = mkEnableOption "ssh";
+ };
+
+ config = mkIf cfg.enable {
+ home.persistence.${impermanence.secure.location} = {
+ directories = [
+ ".ssh"
+ ];
+ };
+
+ programs.ssh.enable = true;
+ };
+}
diff --git a/modules/home/tools/tmux/default.nix b/modules/home/tools/tmux/default.nix
new file mode 100644
index 0000000..3f9b7a0
--- /dev/null
+++ b/modules/home/tools/tmux/default.nix
@@ -0,0 +1,15 @@
+{ options, config, lib, namespace, ... }:
+
+with lib; with lib.${namespace}; let
+ cfg = config.${namespace}.tools.tmux;
+in {
+ options.${namespace}.tools.tmux = with types; {
+ enable = mkEnableOption "tmux";
+ };
+
+ config = mkIf cfg.enable {
+ programs.tmux = {
+ enable = true;
+ };
+ };
+}
diff --git a/modules/home/tools/vim/default.nix b/modules/home/tools/vim/default.nix
new file mode 100644
index 0000000..b07f8d4
--- /dev/null
+++ b/modules/home/tools/vim/default.nix
@@ -0,0 +1,43 @@
+{ options, config, lib, namespace, ... }:
+
+with lib; with lib.${namespace}; let
+ cfg = config.${namespace}.tools.vim;
+ theme = config.${namespace}.desktop.theme;
+in {
+ options.${namespace}.tools.vim = with types; {
+ enable = mkEnableOption "vim";
+ };
+
+ config = mkIf cfg.enable {
+ home.file.".vim/vimrc".text = ''
+ set number
+ set relativenumber
+ set showcmd
+
+ set termguicolors
+ set background=dark
+ colorscheme ${theme.name}
+
+ syntax on
+
+ highlight Normal guibg=#000000
+
+ " Awesome magical color override from
+ " https://gist.github.com/romainl/379904f91fa40533175dfaec4c833f2f
+ augroup MyColors
+ autocmd!
+ autocmd ColorScheme * highlight Normal guibg=#000000
+ augroup END
+ '';
+
+ home.file.".vim/pack/default/start/gruvbox".source = builtins.fetchGit {
+ url = "https://github.com/morhetz/gruvbox.git";
+ rev = "f1ecde848f0cdba877acb0c740320568252cc482";
+ };
+
+ home.file.".vim/pack/all/start/vim-nix".source = builtins.fetchGit {
+ url = "https://github.com/LnL7/vim-nix.git";
+ rev = "e25cd0f2e5922f1f4d3cd969f92e35a9a327ffb0";
+ };
+ };
+}
diff --git a/modules/home/tools/zoxide/default.nix b/modules/home/tools/zoxide/default.nix
new file mode 100644
index 0000000..75db246
--- /dev/null
+++ b/modules/home/tools/zoxide/default.nix
@@ -0,0 +1,15 @@
+{ options, config, lib, namespace, ... }:
+
+with lib; with lib.${namespace}; let
+ cfg = config.${namespace}.tools.zoxide;
+in {
+ options.${namespace}.tools.zoxide = with types; {
+ enable = mkEnableOption "zoxide";
+ };
+
+ config = mkIf cfg.enable {
+ programs.zoxide = {
+ enable = true;
+ };
+ };
+}
diff --git a/modules/nixos/apps/i3/default.nix b/modules/nixos/apps/i3/default.nix
new file mode 100644
index 0000000..e01c6c2
--- /dev/null
+++ b/modules/nixos/apps/i3/default.nix
@@ -0,0 +1,50 @@
+{ options, config, lib, namespace, ... }:
+
+with lib; with lib.${namespace}; let
+ cfg = config.${namespace}.apps.i3;
+in {
+ options.${namespace}.apps.i3 = with types; {
+ enable = mkEnableOption "i3";
+
+ videoDrivers = mkOption {
+ type = types.listOf types.str;
+ default = [ "modesetting" "fbdev" ];
+ };
+
+ setupCommands = mkOption {
+ type = types.lines;
+ default = "";
+ description = ''
+ Shell commands executed just after the X server has started.
+ '';
+ };
+ };
+
+ config = mkIf cfg.enable {
+ services = {
+ displayManager = {
+ enable = true;
+ defaultSession = "none+i3";
+ };
+
+ xserver = {
+ enable = true;
+ windowManager.i3.enable = true;
+
+ displayManager = {
+ lightdm.enable = true;
+ setupCommands = cfg.setupCommands;
+ };
+
+ videoDrivers = cfg.videoDrivers;
+ xkb.layout = "us";
+ };
+
+ libinput = {
+ enable = true;
+ mouse.accelProfile = "flat";
+ touchpad.naturalScrolling = true;
+ };
+ };
+ };
+}
diff --git a/modules/nixos/apps/playerctl/default.nix b/modules/nixos/apps/playerctl/default.nix
new file mode 100644
index 0000000..9bf95d7
--- /dev/null
+++ b/modules/nixos/apps/playerctl/default.nix
@@ -0,0 +1,18 @@
+{ options, config, lib, pkgs, namespace, ... }:
+
+with lib; with lib.${namespace}; let
+ cfg = config.${namespace}.apps.playerctl;
+in {
+ options.${namespace}.apps.playerctl = with types; {
+ enable = mkEnableOption "playerctl";
+ };
+
+ config = mkIf cfg.enable {
+ environment.systemPackages = with pkgs; [
+ playerctl
+ ];
+
+ #TODO: enable, eventually
+ services.playerctld.enable = false;
+ };
+}
diff --git a/modules/nixos/apps/steam/default.nix b/modules/nixos/apps/steam/default.nix
new file mode 100644
index 0000000..b9baebf
--- /dev/null
+++ b/modules/nixos/apps/steam/default.nix
@@ -0,0 +1,18 @@
+{ options, config, lib, pkgs, namespace, ... }:
+
+with lib; with lib.${namespace}; let
+ cfg = config.${namespace}.apps.steam;
+in {
+ options.${namespace}.apps.steam = with types; {
+ enable = mkEnableOption "steam";
+ };
+
+ config = mkIf cfg.enable {
+ nixpkgs.config.allowUnfreePredicate = pkg: builtins.elem (lib.getName pkg) [
+ "steam"
+ "steam-unwrapped"
+ ];
+
+ programs.steam.enable = true;
+ };
+}
diff --git a/modules/nixos/hardware/audio/default.nix b/modules/nixos/hardware/audio/default.nix
new file mode 100644
index 0000000..d2bfa96
--- /dev/null
+++ b/modules/nixos/hardware/audio/default.nix
@@ -0,0 +1,25 @@
+{ options, config, lib, pkgs, namespace, ... }:
+
+with lib; with lib.${namespace}; let
+ cfg = config.${namespace}.hardware.audio;
+in {
+ options.${namespace}.hardware.audio = with types; {
+ enable = mkEnableOption "audio support";
+ };
+
+ config = mkIf cfg.enable {
+ environment.systemPackages = with pkgs; [
+ pulseaudio
+ ];
+
+ security.rtkit.enable = true;
+ services.pipewire = {
+ enable = true;
+
+ pulse.enable = true;
+ alsa.enable = true;
+ alsa.support32Bit = true;
+ #jack.enable = true;
+ };
+ };
+}
diff --git a/modules/nixos/hardware/keyboard/default.nix b/modules/nixos/hardware/keyboard/default.nix
new file mode 100644
index 0000000..0ea2aa6
--- /dev/null
+++ b/modules/nixos/hardware/keyboard/default.nix
@@ -0,0 +1,43 @@
+{ options, config, lib, pkgs, namespace, ... }:
+
+with lib; with lib.${namespace}; let
+ cfg = config.${namespace}.hardware.keyboard;
+in {
+ options.${namespace}.hardware.keyboard = with types; {
+ enable = mkEnableOption "keyboard hardware tweaks";
+ jp.enable = mkEnableOption "japanese ime support";
+ };
+
+ config = mkIf cfg.enable {
+ services.keyd = {
+ enable = true;
+
+ keyboards."*".settings = {
+ main = {
+ # Swap alt and meta keys.
+ # I prefer (physical) alt as my WM modifier key because it
+ # is easier to reach. This can collide with some programs
+ # shortcuts if they inlcude alt. Swapping alt and meta fixes
+ # this by making my WM mod key (software) meta, freeing up alt.
+
+ leftalt = "leftmeta";
+ leftmeta = "leftalt";
+
+ rightalt = "rightmeta";
+ rightmeta = "rightalt";
+ };
+ };
+ };
+
+ i18n.inputMethod = mkIf cfg.jp.enable {
+ enable = true;
+ type = "fcitx5";
+ fcitx5.addons = with pkgs; [ fcitx5-mozc ];
+ };
+
+ environment.variables = mkIf cfg.jp.enable {
+ # Required for fcitx5 support in kitty
+ GLFW_IM_MODULE = "ibus";
+ };
+ };
+}
diff --git a/modules/nixos/services/minecraft/default.nix b/modules/nixos/services/minecraft/default.nix
new file mode 100644
index 0000000..7705c1c
--- /dev/null
+++ b/modules/nixos/services/minecraft/default.nix
@@ -0,0 +1,25 @@
+{ options, config, lib, namespace, inputs, ... }:
+
+with lib; with lib.${namespace}; let
+ cfg = config.${namespace}.services.minecraft;
+ impermanence = config.${namespace}.system.impermanence;
+in {
+ options.${namespace}.services.minecraft = with types; {
+ enable = mkEnableOption "minecraft server support";
+ };
+
+ config = mkIf cfg.enable {
+ nixpkgs = {
+ overlays = [ inputs.nix-minecraft.overlay ];
+ config.allowUnfreePredicate = pkg: builtins.elem (lib.getName pkg) [
+ "minecraft-server"
+ ];
+ };
+
+ services.minecraft-servers = {
+ enable = true;
+ eula = true;
+ openFirewall = true;
+ };
+ };
+}
diff --git a/modules/nixos/services/minecraft/stargazers/default.nix b/modules/nixos/services/minecraft/stargazers/default.nix
new file mode 100644
index 0000000..cb934f8
--- /dev/null
+++ b/modules/nixos/services/minecraft/stargazers/default.nix
@@ -0,0 +1,83 @@
+{ options, config, lib, pkgs, namespace, ... }:
+
+with lib; with lib.${namespace}; let
+ cfg = config.${namespace}.services.minecraft.stargazers;
+ impermanence = config.${namespace}.system.impermanence;
+in {
+ options.${namespace}.services.minecraft.stargazers = with types; {
+ enable = mkEnableOption "stargazers minecraft server";
+
+ port = mkOption {
+ type = types.port;
+ default = 25565;
+ description = "server port";
+ };
+
+ start = mkOption {
+ type = types.bool;
+ default = true;
+ description = "autostart";
+ };
+ };
+
+ config = mkIf cfg.enable {
+ cxl.services.minecraft.enable = true;
+
+ #TODO: enable tmux
+ #cxl.tools.tmux.enable = true;
+
+ environment.persistence.${impermanence.location} = {
+ directories = [
+ "/srv/minecraft/stargazers"
+ ];
+ };
+
+ services.minecraft-servers.servers.stargazers = {
+ enable = true;
+ openFirewall = true;
+ autoStart = cfg.start;
+
+ package = pkgs.fabricServers.fabric-1_21;
+
+ operators = {
+ "grippysockjail" = "9448c89d-34eb-4e2c-a231-8112eb1a9e4a";
+ "antonymph" = "6b1f7a3c-a1c3-491a-8514-12b6b90d9152";
+ };
+
+ serverProperties = {
+ white-list = true;
+ enforce-whitelist = true;
+
+ gamemode = "survival";
+ difficulty = "hard";
+ level-seed = "4167799982467607063";
+ spawn-protection = 0;
+
+ max-players = 69;
+ motd = "\\u00a7r \\u00a75\\u00a7lstrge gazrer\\u00a7r\\n join or i will rip your bones out and eat them";
+
+ server-port = cfg.port;
+ query-port = cfg.port;
+ };
+
+ symlinks.mods = pkgs.linkFarmFromDrvs "mods" (builtins.attrValues {
+ fabric = pkgs.fetchurl {
+ url = "https://cdn.modrinth.com/data/P7dR8mSH/versions/vMQdA5QJ/fabric-api-0.100.7%2B1.21.jar";
+ sha256 = "sha256-grNmYgSekBaTztR1SLbqZCOC6+QNUDLe4hp105qfibA=";
+ };
+ lithium = pkgs.fetchurl {
+ url = "https://cdn.modrinth.com/data/gvQqBUqZ/versions/my7uONjU/lithium-fabric-mc1.21-0.12.7.jar";
+ sha256 = "sha256-Qku6c545jVgrdxDSNe3BULVQlMtgGuXebNqirRcmsh0=";
+ };
+ noChatReports = pkgs.fetchurl {
+ url = "https://cdn.modrinth.com/data/qQyHxfxd/versions/riMhCAII/NoChatReports-FABRIC-1.21-v2.8.0.jar";
+ sha256 = "sha256-jskscOeK3ri2dt3mvWLPVmzddwPqBHJ8Ps+VfZ6l9os=";
+ };
+ appleskin = pkgs.fetchurl {
+ url = "https://cdn.modrinth.com/data/EsAfCjCV/versions/YxFxnyd4/appleskin-fabric-mc1.21-3.0.2.jar";
+ sha256 = "sha256-8XaZREWzA5Mi2/LTs/a6ACvDKmHWYIy8JcOfQaq4yiE=";
+ };
+ });
+ };
+ };
+}
diff --git a/modules/nixos/services/minecraft/zenith/default.nix b/modules/nixos/services/minecraft/zenith/default.nix
new file mode 100644
index 0000000..0bc19f7
--- /dev/null
+++ b/modules/nixos/services/minecraft/zenith/default.nix
@@ -0,0 +1,21 @@
+{ options, config, lib, pkgs, namespace, ... }:
+
+#TODO: nix-ify zenithproxy
+with lib; with lib.${namespace}; let
+ cfg = config.${namespace}.services.minecraft.zenith;
+ impermanence = config.${namespace}.system.impermanence;
+in {
+ options.${namespace}.services.minecraft.zenith = with types; {
+ enable = mkEnableOption "zenithproxy server";
+
+ port = mkOption {
+ type = types.port;
+ default = 25565;
+ description = "server port";
+ };
+ };
+
+ config = mkIf cfg.enable {
+ networking.firewall.allowedTCPPorts = mkIf cfg.openFirewall [ cfg.port ];
+ };
+}
diff --git a/modules/nixos/services/ssh/default.nix b/modules/nixos/services/ssh/default.nix
new file mode 100644
index 0000000..6856897
--- /dev/null
+++ b/modules/nixos/services/ssh/default.nix
@@ -0,0 +1,28 @@
+{ options, config, lib, namespace, ... }:
+
+with lib; with lib.${namespace}; let
+ cfg = config.${namespace}.services.ssh;
+ impermanence = config.${namespace}.system.impermanence;
+in {
+ options.${namespace}.services.ssh = with types; {
+ enable = mkEnableOption "ssh server";
+
+ port = mkOption {
+ type = types.port;
+ default = 22;
+ description = "ssh server port";
+ };
+ };
+
+ config = mkIf cfg.enable {
+ openssh = {
+ enable = true;
+ ports = [ cfg.port ];
+
+ settings = {
+ PermitRootLogin = "no";
+ PasswordAuthentication = false;
+ };
+ };
+ };
+}
diff --git a/modules/nixos/services/web/default.nix b/modules/nixos/services/web/default.nix
new file mode 100644
index 0000000..1e1e854
--- /dev/null
+++ b/modules/nixos/services/web/default.nix
@@ -0,0 +1,23 @@
+{ options, config, lib, namespace, ... }:
+
+with lib; with lib.${namespace}; let
+ cfg = config.${namespace}.services.web;
+ impermanence = config.${namespace}.system.impermanence;
+in {
+ options.${namespace}.services.web = with types; {
+ enable = mkEnableOption "web";
+ };
+
+ config = mkIf cfg.enable {
+ environment.persistence.${impermanence.location} = {
+ directories = [
+ "/var/lib/acme"
+ ];
+ };
+
+ security.acme = {
+ acceptTerms = true;
+ defaults.email = "caroline@larimo.re";
+ };
+ };
+}
diff --git a/modules/nixos/services/web/images/default.nix b/modules/nixos/services/web/images/default.nix
new file mode 100644
index 0000000..b1c44e6
--- /dev/null
+++ b/modules/nixos/services/web/images/default.nix
@@ -0,0 +1,34 @@
+{ options, config, lib, namespace, ... }:
+
+with lib; with lib.${namespace}; let
+ cfg = config.${namespace}.services.web.images;
+ impermanence = config.${namespace}.system.impermanence;
+in {
+ options.${namespace}.services.web.images = with types; {
+ enable = mkEnableOption "image webserver";
+ };
+
+ config = mkIf cfg.enable {
+ cxl.services.web.enable = true;
+
+ environment.persistence.${impermanence.location} = {
+ directories = [
+ "/srv/web/images"
+ ];
+ };
+
+ networking.firewall.allowedTCPPorts = [ 80 443 ];
+
+ services.nginx = {
+ enable = true;
+ virtualHosts = {
+ "i.cxl.sh" = {
+ addSSL = true;
+ enableACME = true;
+
+ root = "/srv/web/images";
+ };
+ };
+ };
+ };
+}
diff --git a/modules/nixos/services/web/landing/default.nix b/modules/nixos/services/web/landing/default.nix
new file mode 100644
index 0000000..fe9e92b
--- /dev/null
+++ b/modules/nixos/services/web/landing/default.nix
@@ -0,0 +1,34 @@
+{ options, config, lib, namespace, ... }:
+
+with lib; with lib.${namespace}; let
+ cfg = config.${namespace}.services.web.landing;
+ impermanence = config.${namespace}.system.impermanence;
+in {
+ options.${namespace}.services.web.landing = with types; {
+ enable = mkEnableOption "cxl.sh landing page webserver";
+ };
+
+ config = mkIf cfg.enable {
+ cxl.services.web.enable = true;
+
+ environment.persistence.${impermanence.location} = {
+ directories = [
+ "/srv/web/landing"
+ ];
+ };
+
+ networking.firewall.allowedTCPPorts = [ 80 443 ];
+
+ services.nginx = {
+ enable = true;
+ virtualHosts = {
+ "cxl.sh" = {
+ addSSL = true;
+ enableACME = true;
+
+ root = "/srv/web/landing";
+ };
+ };
+ };
+ };
+}
diff --git a/modules/nixos/services/web/personal/default.nix b/modules/nixos/services/web/personal/default.nix
new file mode 100644
index 0000000..daf94c1
--- /dev/null
+++ b/modules/nixos/services/web/personal/default.nix
@@ -0,0 +1,63 @@
+{ options, config, lib, pkgs, namespace, ... }:
+
+with lib; with lib.${namespace}; let
+ cfg = config.${namespace}.services.web.personal;
+ impermanence = config.${namespace}.system.impermanence;
+
+ package = (pkgs.buildGoModule rec {
+ pname = "site";
+ version = "6612d84c63a7bbc2a5b70607f2ec32ea070c4659";
+
+ src = pkgs.fetchFromGitHub {
+ owner = "CartConnoisseur";
+ repo = "site";
+ rev = "${version}";
+ hash = "sha256-n54+LdtMyjoLfaFqd7tcDQqBiYCdUW/Rs67Vc4QwEJ0=";
+ };
+
+ # kinda a hack, but whatever
+ postBuild = ''
+ mkdir -p $out/share/site
+ cp -r $src/* $out/share/site/
+ '';
+
+ vendorHash = "sha256-2/4Wv7nsaT0wnUzkRgHKpSswigDj9nOvlmYXK29rvLU=";
+ });
+in {
+ options.${namespace}.services.personal.images = with types; {
+ enable = mkEnableOption "personal site webserver";
+ };
+
+ config = mkIf cfg.enable {
+ cxl.services.web.enable = true;
+
+ networking.firewall.allowedTCPPorts = [ 80 443 ];
+
+ services.nginx = {
+ enable = true;
+ virtualHosts = {
+ "caroline.larimo.re" = {
+ # serverAliases = [ "cxl.sh" ];
+
+ addSSL = true;
+ enableACME = true;
+
+ locations."/" = {
+ recommendedProxySettings = true;
+ proxyPass = "http://127.0.0.1:8080/";
+ };
+ };
+ };
+ };
+
+ systemd.services."cxl.web.personal" = {
+ enable = true;
+ wantedBy = [ "multi-user.target" ];
+
+ serviceConfig = {
+ WorkingDirectory = "${package}/share/site";
+ ExecStart = "${package}/bin/site";
+ };
+ };
+ };
+}
diff --git a/modules/nixos/services/web/stargazers/default.nix b/modules/nixos/services/web/stargazers/default.nix
new file mode 100644
index 0000000..3e9b46e
--- /dev/null
+++ b/modules/nixos/services/web/stargazers/default.nix
@@ -0,0 +1,34 @@
+{ options, config, lib, namespace, ... }:
+
+with lib; with lib.${namespace}; let
+ cfg = config.${namespace}.services.web.stargazers;
+ impermanence = config.${namespace}.system.impermanence;
+in {
+ options.${namespace}.services.web.stargazers = with types; {
+ enable = mkEnableOption "stargazers webserver";
+ };
+
+ config = mkIf cfg.enable {
+ cxl.services.web.enable = true;
+
+ environment.persistence.${impermanence.location} = {
+ directories = [
+ "/srv/web/stargazers"
+ ];
+ };
+
+ networking.firewall.allowedTCPPorts = [ 80 443 ];
+
+ services.nginx = {
+ enable = true;
+ virtualHosts = {
+ "stargazers.xn--6frz82g" = {
+ addSSL = true;
+ enableACME = true;
+
+ root = "/srv/web/stargazers";
+ };
+ };
+ };
+ };
+}
diff --git a/modules/nixos/suites/common/default.nix b/modules/nixos/suites/common/default.nix
new file mode 100644
index 0000000..1e7a053
--- /dev/null
+++ b/modules/nixos/suites/common/default.nix
@@ -0,0 +1,25 @@
+{ options, config, lib, namespace, ... }:
+
+with lib; with lib.${namespace}; let
+ cfg = config.${namespace}.suites.common;
+in {
+ options.${namespace}.suites.common = with types; {
+ enable = mkEnableOption "common";
+ };
+
+ config = mkIf cfg.enable {
+ cxl = {
+ hardware = {
+ keyboard.enable = true;
+ };
+
+ tools = {
+ bash.enable = true;
+ vim.enable = true;
+ git.enable = true;
+ misc.enable = true;
+ rebuild.enable = true;
+ };
+ };
+ };
+}
diff --git a/modules/nixos/suites/desktop/default.nix b/modules/nixos/suites/desktop/default.nix
new file mode 100644
index 0000000..246f38c
--- /dev/null
+++ b/modules/nixos/suites/desktop/default.nix
@@ -0,0 +1,27 @@
+{ options, config, lib, namespace, ... }:
+
+with lib; with lib.${namespace}; let
+ cfg = config.${namespace}.suites.desktop;
+in {
+ options.${namespace}.suites.desktop = with types; {
+ enable = mkEnableOption "desktop";
+ };
+
+ config = mkIf cfg.enable {
+ cxl = {
+ hardware = {
+ audio.enable = true;
+ keyboard.jp.enable = true;
+ };
+
+ apps = {
+ i3.enable = true;
+ playerctl.enable = true;
+ };
+
+ system.fonts.enable = true;
+ };
+
+ programs.dconf.enable = true;
+ };
+}
diff --git a/modules/nixos/suites/gaming/default.nix b/modules/nixos/suites/gaming/default.nix
new file mode 100644
index 0000000..e95e1cd
--- /dev/null
+++ b/modules/nixos/suites/gaming/default.nix
@@ -0,0 +1,17 @@
+{ options, config, lib, namespace, ... }:
+
+with lib; with lib.${namespace}; let
+ cfg = config.${namespace}.suites.gaming;
+in {
+ options.${namespace}.suites.gaming = with types; {
+ enable = mkEnableOption "gaming";
+ };
+
+ config = mkIf cfg.enable {
+ cxl = {
+ apps = {
+ steam.enable = true;
+ };
+ };
+ };
+}
diff --git a/modules/nixos/system/default.nix b/modules/nixos/system/default.nix
new file mode 100644
index 0000000..96c5654
--- /dev/null
+++ b/modules/nixos/system/default.nix
@@ -0,0 +1,30 @@
+{ options, config, lib, namespace, ... }:
+
+with lib; with lib.${namespace}; let
+ cfg = config.${namespace}.system;
+in {
+ options.${namespace}.system = with types; {
+ hostname = mkOption {
+ type = strMatching "^$|^[[:alnum:]]([[:alnum:]_-]{0,61}[[:alnum:]])?$";
+ };
+
+ id = mkOption {
+ default = null;
+ type = nullOr str;
+ };
+
+ timezone = mkOption {
+ default = "America/Los_Angeles";
+ type = nullOr str;
+ };
+ };
+
+ config = {
+ nix.settings.experimental-features = [ "nix-command" "flakes" ];
+
+ networking.hostName = cfg.hostname;
+ networking.hostId = cfg.id;
+
+ time.timeZone = cfg.timezone;
+ };
+}
diff --git a/modules/nixos/system/fonts/default.nix b/modules/nixos/system/fonts/default.nix
new file mode 100644
index 0000000..c510679
--- /dev/null
+++ b/modules/nixos/system/fonts/default.nix
@@ -0,0 +1,38 @@
+{ options, config, lib, pkgs, namespace, ... }:
+
+with lib; with lib.${namespace}; let
+ cfg = config.${namespace}.system.fonts;
+in {
+ options.${namespace}.system.fonts = with types; {
+ enable = mkEnableOption "fonts";
+ nerdfonts = mkEnableOption "nerdfonts";
+ extra = mkOption {
+ type = listOf package;
+ default = [];
+ description = ''
+ additional fonts to install
+ '';
+ };
+ };
+
+ config = mkIf cfg.enable {
+ fonts = {
+ packages = with pkgs; [
+ noto-fonts
+ noto-fonts-cjk-sans
+ noto-fonts-cjk-serif
+ noto-fonts-emoji
+ ] ++ (
+ optionals cfg.nerdfonts (
+ builtins.filter lib.attrsets.isDerivation (builtins.attrValues pkgs.nerd-fonts)
+ )
+ ) ++ cfg.extra;
+
+ fontconfig.defaultFonts = {
+ monospace = [ "CaskaydiaMono Nerd Font" ];
+ sansSerif = [ "DejaVu Sans" "Noto Sans CJK JP" "Noto Sans" ];
+ serif = [ "DejaVu Serif" "Noto Serif CJK JP" "Noto Serif" ];
+ };
+ };
+ };
+}
diff --git a/modules/nixos/system/impermanence/default.nix b/modules/nixos/system/impermanence/default.nix
new file mode 100644
index 0000000..b82579b
--- /dev/null
+++ b/modules/nixos/system/impermanence/default.nix
@@ -0,0 +1,49 @@
+{ options, config, lib, namespace, ... }:
+
+with lib; with lib.${namespace}; let
+ cfg = config.${namespace}.system.impermanence;
+in {
+ options.${namespace}.system.impermanence = with types; {
+ enable = mkEnableOption "root impermanence";
+
+ location = mkOption {
+ type = str;
+ default = "/persist/system";
+ };
+
+ #TODO: multi-user support
+ home = {
+ enable = mkEnableOption "home impermanence";
+
+ location = mkOption {
+ type = str;
+ default = "/persist/home";
+ };
+
+ secure.location = mkOption {
+ type = str;
+ default = "/persist/secure/home";
+ };
+ };
+ };
+
+ config = mkIf cfg.enable {
+ programs.fuse.userAllowOther = true;
+
+ environment.persistence.${cfg.location} = {
+ hideMounts = true;
+
+ directories = [
+ "/etc/nixos"
+ "/var/log"
+ "/var/lib/nixos"
+ "/var/lib/systemd/coredump"
+ # "/var/lib/bluetooth"
+ ];
+
+ files = [
+ "/etc/machine-id"
+ ];
+ };
+ };
+}
diff --git a/modules/nixos/tools/bash/default.nix b/modules/nixos/tools/bash/default.nix
new file mode 100644
index 0000000..180db1f
--- /dev/null
+++ b/modules/nixos/tools/bash/default.nix
@@ -0,0 +1,29 @@
+{ options, config, lib, namespace, ... }:
+
+with lib; with lib.${namespace}; let
+ cfg = config.${namespace}.tools.bash;
+in {
+ options.${namespace}.tools.bash = with types; {
+ enable = mkEnableOption "tools";
+ };
+
+ config = mkIf cfg.enable {
+ environment.localBinInPath = true;
+
+ programs.bash = {
+ shellAliases = {
+ lsa = "ls -lAsh";
+ p = "nix-shell -p";
+ };
+
+ interactiveShellInit = ''
+ source "${./prompt.sh}"
+
+ mkcd() {
+ mkdir -p "$1"
+ cd "$1"
+ }
+ '';
+ };
+ };
+}
diff --git a/modules/nixos/tools/bash/prompt.sh b/modules/nixos/tools/bash/prompt.sh
new file mode 100644
index 0000000..d4d7c69
--- /dev/null
+++ b/modules/nixos/tools/bash/prompt.sh
@@ -0,0 +1,84 @@
+PROMPT_CHAR='❯'
+
+if [[ "$TERM" == "xterm-kitty" ]]; then
+ function prompt.bubble {
+ printf '\[\e[49m\e[38;5;237m\]◖\[\e[48;5;237m\e[39m\]%s\[\e[0m\e[49m\e[38;5;237m\]◗\[\e[0m\]' "$@";
+ }
+elif [[ "$TERM" == "xterm-256color" ]]; then
+ function prompt.bubble {
+ printf '\[\e[38;5;237m\](\[\e[0m\]%s\[\e[0m\e[38;5;237m\])\[\e[0m\]' "$@";
+ }
+else
+ PROMPT_CHAR='>'
+ function prompt.bubble {
+ printf '\[\e[2;39m\](\[\e[0m\]%s\[\e[0m\e[2;39m\])\[\e[0m\]' "$@";
+ }
+fi
+
+function prompt.git {
+ GIT_PS1_STATESEPARATOR=';'
+ GIT_PS1_SHOWDIRTYSTATE=1
+ GIT_PS1_SHOWUNTRACKEDFILES=
+ GIT_PS1_SHOWUPSTREAM=
+
+ GIT_PS1_HIDE_IF_PWD_IGNORED=1
+
+ local git_ps1="$(__git_ps1)"
+ git_ps1="${git_ps1##' ('}"
+ git_ps1="${git_ps1%')'}"
+
+ IFS=';' read -r branch state _ <<< "$git_ps1"
+
+ if [[ -n "$branch" ]]; then
+ printf ' '
+
+ if [[ "$state" == '*' ]]; then
+ prompt.bubble "$(printf '\[\e[4;32m\]%s' "$branch")"
+ else
+ prompt.bubble "$(printf '\[\e[32m\]%s' "$branch")"
+ fi
+ fi
+}
+
+function prompt.prepare {
+ local err=$?
+ PS1="\\[\e[0m\\]\n"
+
+ local subshell=''
+ local base_shlvl=1
+ local shlvl=$((SHLVL-base_shlvl))
+
+ if [[ -n "$IN_NIX_SHELL" ]]; then
+ subshell="\\[\e[33m\\]nix"
+ fi
+ if [[ $shlvl != 0 && ! ($shlvl == 1 && -n "$IN_NIX_SHELL") ]]; then
+ if [[ -n "$subshell" ]]; then subshell+="\\[\e[39m\\] "; fi
+ subshell+="\\[\e[2;37m\\]$shlvl"
+ fi
+ if [[ -n "$subshell" ]]; then
+ PS1+="$(prompt.bubble "$subshell") "
+ fi
+
+ if [[ $EUID == 0 ]]; then
+ PS1+="$(prompt.bubble "\\[\e[4m\\]\u@\H")"
+ else
+ PS1+="$(prompt.bubble "\u@\H")"
+ fi
+
+ PS1+=" $(prompt.bubble "\\[\e[34m\\]\w")"
+ PS1+="$(prompt.git)"
+ if [[ $err != 0 ]]; then
+ PS1+=" $(prompt.bubble "\\[\e[31m\\]$err")"
+ fi
+ PS1+=" $(prompt.bubble "$PROMPT_CHAR") "
+
+ if [[ $err != 0 ]]; then
+ (exit "$err")
+ fi
+}
+
+PROMPT_COMMAND='prompt.prepare'
+
+function baller {
+ printf '🮲🮳⚽︎ \n'
+}
diff --git a/modules/nixos/tools/git/default.nix b/modules/nixos/tools/git/default.nix
new file mode 100644
index 0000000..f58ed62
--- /dev/null
+++ b/modules/nixos/tools/git/default.nix
@@ -0,0 +1,16 @@
+{ options, config, lib, namespace, ... }:
+
+with lib; with lib.${namespace}; let
+ cfg = config.${namespace}.tools.git;
+in {
+ options.${namespace}.tools.git = with types; {
+ enable = mkEnableOption "git";
+ };
+
+ config = mkIf cfg.enable {
+ programs.git = {
+ enable = true;
+ prompt.enable = true;
+ };
+ };
+}
diff --git a/modules/nixos/tools/misc/default.nix b/modules/nixos/tools/misc/default.nix
new file mode 100644
index 0000000..a06a141
--- /dev/null
+++ b/modules/nixos/tools/misc/default.nix
@@ -0,0 +1,19 @@
+{ options, config, lib, pkgs, namespace, ... }:
+
+with lib; with lib.${namespace}; let
+ cfg = config.${namespace}.tools.misc;
+in {
+ options.${namespace}.tools.misc = with types; {
+ enable = mkEnableOption "misc tools";
+ };
+
+ config = mkIf cfg.enable {
+ environment.systemPackages = with pkgs; [
+ jq
+ killall
+ moreutils
+ unzip
+ wget
+ ];
+ };
+}
diff --git a/modules/nixos/tools/rebuild/default.nix b/modules/nixos/tools/rebuild/default.nix
new file mode 100644
index 0000000..368f29f
--- /dev/null
+++ b/modules/nixos/tools/rebuild/default.nix
@@ -0,0 +1,16 @@
+{ options, config, lib, pkgs, namespace, ... }:
+
+with lib; with lib.${namespace}; let
+ cfg = config.${namespace}.tools.rebuild;
+in {
+ options.${namespace}.tools.rebuild = with types; {
+ enable = mkEnableOption "rebuild scripts";
+ };
+
+ config = mkIf cfg.enable {
+ environment.systemPackages = with pkgs; [
+ (writeShellScriptBin "rb" "sudo nixos-rebuild switch --flake /etc/nixos")
+ (writeShellScriptBin "rbf" "sudo nixos-rebuild switch --flake path:/etc/nixos")
+ ];
+ };
+}
diff --git a/modules/nixos/tools/vim/default.nix b/modules/nixos/tools/vim/default.nix
new file mode 100644
index 0000000..9aa0a2c
--- /dev/null
+++ b/modules/nixos/tools/vim/default.nix
@@ -0,0 +1,19 @@
+{ options, config, lib, pkgs, namespace, ... }:
+
+with lib; with lib.${namespace}; let
+ cfg = config.${namespace}.tools.vim;
+in {
+ options.${namespace}.tools.vim = with types; {
+ enable = mkEnableOption "vim";
+ };
+
+ config = mkIf cfg.enable {
+ environment.systemPackages = with pkgs; [
+ vim
+ ];
+
+ environment.variables = {
+ EDITOR = "${pkgs.vim}/bin/vim";
+ };
+ };
+}