feat(*): dual boot
11 files changed, -87/+452
flake.lock
@@ -1,18 +1,22 @@ { "nodes": {- "flake-compat": {- "flake": false,+ "disko": {+ "inputs": {+ "nixpkgs": [+ "nixpkgs"+ ]+ }, "locked": {- "lastModified": 1767039857,- "narHash": "sha256-vNpUSpF5Nuw8xvDLj2KCwwksIbjua2LZCqhV1LNRDns=",- "owner": "edolstra",- "repo": "flake-compat",- "rev": "5edf11c44bc78a0d334f6334cdaf7d60d732daab",+ "lastModified": 1772420042,+ "narHash": "sha256-naZz40TUFMa0E0CutvwWsSPhgD5JldyTUDEgP9ADpfU=",+ "owner": "nix-community",+ "repo": "disko",+ "rev": "5af7af10f14706e4095bd6bc0d9373eb097283c6", "type": "github" }, "original": {- "owner": "edolstra",- "repo": "flake-compat",+ "owner": "nix-community",+ "repo": "disko", "type": "github" } },@@ -36,29 +40,64 @@ "type": "sourcehut" } },- "nixos-wsl": {+ "home-manager_2": { "inputs": {- "flake-compat": "flake-compat", "nixpkgs": [+ "impermanence", "nixpkgs" ] }, "locked": {- "lastModified": 1769217863,- "narHash": "sha256-RY9kJDXD6+2Td/59LkZ0PFSereCXHdBX9wIkbYjRKCY=",+ "lastModified": 1768598210,+ "narHash": "sha256-kkgA32s/f4jaa4UG+2f8C225Qvclxnqs76mf8zvTVPg=",+ "owner": "nix-community",+ "repo": "home-manager",+ "rev": "c47b2cc64a629f8e075de52e4742de688f930dc6",+ "type": "github"+ },+ "original": {+ "owner": "nix-community",+ "repo": "home-manager",+ "type": "github"+ }+ },+ "impermanence": {+ "inputs": {+ "home-manager": "home-manager_2",+ "nixpkgs": "nixpkgs"+ },+ "locked": {+ "lastModified": 1769548169,+ "narHash": "sha256-03+JxvzmfwRu+5JafM0DLbxgHttOQZkUtDWBmeUkN8Y=", "owner": "nix-community",- "repo": "NixOS-WSL",- "rev": "38a5250e57f583662eac3b944830e4b9e169e965",+ "repo": "impermanence",+ "rev": "7b1d382faf603b6d264f58627330f9faa5cba149", "type": "github" }, "original": { "owner": "nix-community",- "repo": "NixOS-WSL",+ "repo": "impermanence", "type": "github" } }, "nixpkgs": { "locked": {+ "lastModified": 1768564909,+ "narHash": "sha256-Kell/SpJYVkHWMvnhqJz/8DqQg2b6PguxVWOuadbHCc=",+ "owner": "nixos",+ "repo": "nixpkgs",+ "rev": "e4bae1bd10c9c57b2cf517953ab70060a828ee6f",+ "type": "github"+ },+ "original": {+ "owner": "nixos",+ "ref": "nixos-unstable",+ "repo": "nixpkgs",+ "type": "github"+ }+ },+ "nixpkgs_2": {+ "locked": { "lastModified": 1770197578, "narHash": "sha256-AYqlWrX09+HvGs8zM6ebZ1pwUqjkfpnv8mewYwAo+iM=", "owner": "nixos",@@ -75,9 +114,10 @@ }, "root": { "inputs": {+ "disko": "disko", "home-manager": "home-manager",- "nixos-wsl": "nixos-wsl",- "nixpkgs": "nixpkgs"+ "impermanence": "impermanence",+ "nixpkgs": "nixpkgs_2" } } },
flake.nix
@@ -1,9 +1,10 @@ { inputs = { nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";+ impermanence.url = "github:nix-community/impermanence"; - nixos-wsl.url = "github:nix-community/NixOS-WSL";- nixos-wsl.inputs.nixpkgs.follows = "nixpkgs";+ disko.url = "github:nix-community/disko";+ disko.inputs.nixpkgs.follows = "nixpkgs"; home-manager.url = "sourcehut:~rycee/home-manager"; home-manager.inputs.nixpkgs.follows = "nixpkgs";
home/features/global.nix
@@ -14,6 +14,19 @@ GOTOOLCHAIN = "local"; }; - packages = with pkgs; [ pass ];+ packages = with pkgs; [ pass vesktop ];++ persistence."/persist" = {+ files = [+ ".local/share/opencode/auth.json"+ ];+ directories = [+ "documents"+ ".mozilla"+ ".gnupg"+ ".password-store"+ ".config/vesktop"+ ];+ }; }; }
home/features/wayland/dwl.nix
@@ -0,0 +1,5 @@+{ pkgs, ... }:++{+ home.packages = with pkgs; [ dwl dmenu wl-clipboard xdg-utils ];+}
home/features/wayland/foot.nix
@@ -0,0 +1,11 @@+{+ programs.foot = {+ enable = true;+ settings = {+ main = {+ font = "ComicShannsMono Nerd Font:size=11";+ line-height = "16px";+ };+ };+ };+}
home/profiles/sunflower.nix
@@ -9,21 +9,8 @@ ../features/cli/opencode.nix ../features/misc/xdg.nix- ]; - # TMP: neovim suck tbh but it work- programs.neovim.extraConfig = ''- let g:clipboard = {- \ 'name': 'WslClipboard',- \ 'copy': {- \ '+': 'clip.exe',- \ '*': 'clip.exe',- \ },- \ 'paste': {- \ '+': 'powershell.exe -NoLogo -NoProfile -c [Console]::Out.Write($(Get-Clipboard -Raw).tostring().replace("`r", ""))',- \ '*': 'powershell.exe -NoLogo -NoProfile -c [Console]::Out.Write($(Get-Clipboard -Raw).tostring().replace("`r", ""))',- \ },- \ 'cache_enabled': 0,- \ }- '';+ ../features/wayland/dwl.nix+ ../features/wayland/foot.nix+ ]; }
nixos/features/global.nix
@@ -1,6 +1,8 @@-{ inputs, outputs, lib, pkgs, ... }:+{ inputs, outputs, config, lib, pkgs, ... }: {+ imports = [ inputs.impermanence.nixosModules.impermanence ];+ i18n.defaultLocale = "en_US.UTF-8"; time.timeZone = "UTC"; @@ -9,7 +11,7 @@ gc = { automatic = true;- dates = "weekly";+ dates = "daily"; options = "--delete-older-than 7d"; }; @@ -18,7 +20,7 @@ keep-derivations = false; auto-optimise-store = true; - trusted-users = [ "@wheel" ];+ trusted-users = [ "root" "@wheel" ]; experimental-features = [ "nix-command" "flakes" ]; }; };@@ -68,7 +70,7 @@ audit = { enable = true;- rules = [ "-a exit,always, -F arch=b64 -S execve" ];+ rules = [ "-a exit,always -F arch=b64 -S execve" ]; }; sudo = {@@ -86,5 +88,59 @@ users.root.hashedPassword = lib.mkForce "!"; }; - environment.defaultPackages = lib.mkForce [];+ environment = {+ defaultPackages = lib.mkForce [];++ persistence."/persist" = {+ hideMounts = false;++ directories = [+ "/srv"+ "/var/lib/nixos"+ "/var/lib/systemd"+ ];+ };+ };++ boot.initrd = let+ rootDevice = config.fileSystems."/".device;+ systemdStage1 = config.boot.initrd.systemd.enable;++ script = ''+ mkdir -p /tmp+ MNTPOINT=$(mktemp -d)+ (+ mount ${rootDevice} "$MNTPOINT"+ trap 'umount "$MNTPOINT"' EXIT++ echo "Moving old root..."+ mv "$MNTPOINT/@" "$MNTPOINT/@_old"++ echo "Creating a blank root subvolume..."+ btrfs sub cre "$MNTPOINT/@"++ echo "Cleaning old root..."+ btrfs sub del -R "$MNTPOINT/@_old"+ rm -rf "$MNTPOINT/@_old"+ )+ '';+ in {+ supportedFilesystems = [ "btrfs" ];+ postDeviceCommands = lib.mkIf (!systemdStage1) (lib.mkBefore script);++ systemd.services.wipe-root = lib.mkIf (systemdStage1) {+ wantedBy = [ "initrd.target" ];+ requires = [ "dev-mapper-crypted.device" ];+ before = [ "sysroot.mount" ];+ after = [ "dev-mapper-crypted.device" "[email protected]" ];+ unitConfig.DefaultDependencies = "no";+ serviceConfig = {+ Type = "oneshot";+ RemainAfterExit = true;+ };+ script = script;+ };+ };++ fileSystems."/persist".neededForBoot = true; }
nixos/hosts/sunflower.nix
@@ -1,20 +1,23 @@-{ pkgs, inputs, modulesPath, ... }:+{ inputs, modulesPath, pkgs, ... }: { imports = [- inputs.nixos-wsl.nixosModules.default+ inputs.disko.nixosModules.disko ( modulesPath + "/installer/scan/not-detected.nix" ) ]; - wsl = {- enable = true;- defaultUser = "lostduk";- useWindowsDriver = true;+ boot = {+ kernelModules = [ "kvm-intel" ]; - usbip = {- enable = true;- autoAttach = [ "1-14" ];+ loader = {+ systemd-boot.enable = true;+ efi.canTouchEfiVariables = true;+ };++ initrd = {+ systemd.enable = true;+ availableKernelModules = [ "xhci_pci" "ahci" "usbhid" "usb_storage" "sd_mod" ]; }; }; @@ -28,7 +31,58 @@ }; hardware = {- graphics.enable = true;+ graphics = {+ enable = true;+ extraPackages = with pkgs; [ libGL ];+ }; cpu.intel.updateMicrocode = true; };++ disko.devices.disk.main = {+ type = "disk";+ device = "/dev/sda";+ content = {+ type = "gpt";+ partitions = {+ ESP = {+ size = "512M";+ type = "EF00";+ content = {+ type = "filesystem";+ format = "vfat";+ mountpoint = "/boot";+ mountOptions = [ "defaults" "uid=0" "gid=0" "fmask=0077" "dmask=0077" ];+ };+ };+ luks = {+ size = "100%";+ content = {+ name = "crypted";+ type = "luks";+ extraFormatArgs = [ "--type luks2" ];+ content = {+ type = "btrfs";+ extraArgs = [ "-f" ];+ subvolumes = let+ options = [ "compress=zstd" "noatime" "space_cache=v2" "discard=async" "ssd" ];+ in {+ "/@" = {+ mountpoint = "/";+ mountOptions = options;+ };+ "/@nix" = {+ mountpoint = "/nix";+ mountOptions = options;+ };+ "/@persist" = {+ mountpoint = "/persist";+ mountOptions = options;+ };+ };+ };+ };+ };+ };+ };+ }; }
nixos/roles/workstation.nix
@@ -15,42 +15,112 @@ in { users.lostduk = outputs.homeConfigurations.${config.networking.hostName}; }; - systemd.services.wipe-trash = {- restartIfChanged = false;- wantedBy = [ "multi-user.target" ];- serviceConfig = {- Type = "oneshot";- RemainAfterExit = true;- ExecStart = pkgs.writeShellScript "" ''- set -e-- TARGET="/home/lostduk"-- find "$TARGET" -mindepth 1 -maxdepth 1 \- ! -name 'documents' \- ! -name '.gnupg' \- ! -name '.password-store' \- ! -name '.local' \- -exec rm -r {} +-- if [ -d "$TARGET/.local" ]; then- find "$TARGET/.local" -mindepth 1 -maxdepth 1 \- ! -name 'share' \- -exec rm -r {} +- fi-- if [ -d "$TARGET/.local/share" ]; then- find "$TARGET/.local/share" -mindepth 1 -maxdepth 1 \- ! -name 'opencode' \- -exec rm -r {} +- fi-- if [ -d "$TARGET/.local/share/opencode" ]; then- find "$TARGET/.local/share/opencode" -mindepth 1 -maxdepth 1 \- ! -name 'auth.json' \- -exec rm -r {} +- fi+ programs.fuse.userAllowOther = true;++ xdg.portal = {+ enable = true;+ extraPortals = [ pkgs.xdg-desktop-portal-wlr ];+ configPackages = [ pkgs.xdg-desktop-portal-gtk pkgs.xdg-desktop-portal-wlr ];++ wlr.enable = true;++ config.common = {+ default = [ "wlr" ];+ };+ };++ system.activationScripts.persistent-dirs.text =+ let+ mkHomePersist = user: lib.optionalString user.createHome ''+ mkdir -p /persist/${user.home}+ chown ${user.name}:${user.group} /persist/${user.home}+ chmod ${user.homeMode} /persist/${user.home} '';+ users = lib.attrValues config.users.users;+ in+ lib.concatLines (map mkHomePersist users);++ fonts = {+ enableDefaultPackages = false;++ packages = with pkgs; [+ noto-fonts+ noto-fonts-cjk-sans+ noto-fonts-cjk-serif+ noto-fonts-color-emoji++ #(nerdfonts.override { fonts = [ "ComicShannsMono" ]; })+ nerd-fonts.comic-shanns-mono+ ];++ fontconfig = {+ hinting.autohint = true;++ defaultFonts = {+ serif = [ "Noto Serif" "Noto Color Emoji" ];+ sansSerif = [ "Noto Sans" "Noto Color Emoji" ];+ monospace = [ "ComicShannsMono Nerd Font" "Noto Color Emoji" ];+ emoji = [ "Noto Color Emoji" ];+ };+ };+ };++ services = {+ udisks2.enable = true;++ pipewire = {+ enable = true;++ alsa.enable = true;+ alsa.support32Bit = true;++ pulse.enable = true;+ jack.enable = true;++ wireplumber = {+ enable = true;++ # https://github.com/NixOS/nixpkgs/pull/292115+ extraConfig."alsa-lowlatency" = {+ "monitor.alsa.rules" = [{+ matches = [{ "node.name" = "~alsa_output.*"; }];++ actions.update-props = {+ "audio.format" = "S32LE";+ "audio.rate" = "96000";+ "api.alsa.period-size" = 2;+ };+ }];+ };+ };++ extraConfig.pipewire."92-low-latency" = {+ context = {+ properties.default.clock = {+ rate = 48000;+ quantum = 64;+ };++ modules = [{+ name = "libpipewire-module-protocol-pulse";++ args.pulse = {+ min = {+ req = "64/48000";+ quantum = "64/48000";+ frag = "64/48000";+ };++ default.req = "64/48000";+ };+ }];+ };+ + stream.properties = {+ node.latency = "64/48000";+ resample.quality = 1;+ };+ }; }; }; })];
overlays/default.nix
@@ -13,4 +13,14 @@ ) inputs; };++ modifications = final: prev: {+ dwl = prev.dwl.overrideAttrs (oldAttrs: {+ enableXWayland = true;+ + postPatch = ''+ cp ${./dwl_config.h} config.h+ '';+ });+ }; }
overlays/dwl_config.h
@@ -0,0 +1,118 @@+/* general */+#define TAGCOUNT (6)++static int log_level = WLR_ERROR;+static const int sloppyfocus = 1;+static const int bypass_surface_visibility = 0;++/* appearance */+static const unsigned int borderpx = 1;+static const float rootcolor[] = {0.1f, 0.1f, 0.1f, 1.0f};+static const float bordercolor[] = {0.2f, 0.2f, 0.2f, 1.0f};+static const float focuscolor[] = {0.0f, 0.3f, 0.4f, 1.0f};+static const float urgentcolor[] = {0.1f, 0.0f, 0.0f, 1.0f};+static const float fullscreen_bg[] = {0.1f, 0.1f, 0.1f, 1.0f};++/* rules */+static const Rule rules[] = {+ { "Gimp_EXAMPLE", NULL, 0, 1, -1 },+};++/* layouts */+static const Layout layouts[] = {+ { "[T]", tile },+ { "[F]", NULL },+ { "[M]", monocle },+};++/* monitors */+static const MonitorRule monrules[] = {+ { NULL, 0.55f, 1, 1, &layouts[0], WL_OUTPUT_TRANSFORM_NORMAL, -1, -1 },+};++/* keyboard */+static const int repeat_rate = 25;+static const int repeat_delay = 600;++static const struct xkb_rule_names xkb_rules = {+ .layout = "us,th",+ .options = "grp:alt_shift_toggle",+};+++/* trackpad */+static const int tap_to_click = 1;+static const int tap_and_drag = 1;+static const int drag_lock = 1;+static const int natural_scrolling = 0;+static const int disable_while_typing = 1;+static const int left_handed = 0;+static const int middle_button_emulation = 0;++static const enum libinput_config_scroll_method scroll_method = LIBINPUT_CONFIG_SCROLL_2FG;+static const enum libinput_config_click_method click_method = LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS;+static const uint32_t send_events_mode = LIBINPUT_CONFIG_SEND_EVENTS_ENABLED;+static const enum libinput_config_accel_profile accel_profile = LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE;+static const double accel_speed = 0.0;+static const enum libinput_config_tap_button_map button_map = LIBINPUT_CONFIG_TAP_MAP_LRM;++/* commands */+#define MODKEY WLR_MODIFIER_LOGO+#define MODALT WLR_MODIFIER_ALT+#define MODCTRL WLR_MODIFIER_CTRL+#define MODSHIFT WLR_MODIFIER_SHIFT++#define TAGKEYS(KEY, SKEY, TAG) \+ { MODKEY, KEY, view, {.ui = 1 << TAG} }, \+ { MODKEY|MODCTRL, KEY, toggleview, {.ui = 1 << TAG} }, \+ { MODKEY|MODSHIFT, SKEY, tag, {.ui = 1 << TAG} }, \+ { MODKEY|MODCTRL|MODSHIFT, SKEY, toggletag, {.ui = 1 << TAG} }++#define CHVT(n) { MODCTRL|MODALT, XKB_KEY_XF86Switch_VT_##n, chvt, {.ui = (n)} }++static const char *termcmd[] = { "foot", NULL };+static const char *menucmd[] = { "dmenu_run", NULL };++static const Key keys[] = {+ { MODKEY, XKB_KEY_d, spawn, {.v = menucmd} },+ { MODKEY, XKB_KEY_Return, spawn, {.v = termcmd} },+ { MODKEY, XKB_KEY_j, focusstack, {.i = +1} },+ { MODKEY, XKB_KEY_h, setmfact, {.f = -0.05f} },+ { MODKEY, XKB_KEY_l, setmfact, {.f = +0.05f} },+ { MODKEY, XKB_KEY_i, incnmaster, {.i = +1} },+ { MODKEY, XKB_KEY_o, incnmaster, {.i = -1} },+ { MODKEY, XKB_KEY_k, focusstack, {.i = -1} },+ { MODKEY, XKB_KEY_q, killclient, {0} },+ { MODKEY|MODSHIFT, XKB_KEY_Tab, view, {0} },+ { MODKEY|MODSHIFT, XKB_KEY_Return, zoom, {0} },+ { MODKEY|MODSHIFT, XKB_KEY_T, setlayout, {.v = &layouts[0]} },+ { MODKEY|MODSHIFT, XKB_KEY_F, setlayout, {.v = &layouts[1]} },+ { MODKEY|MODSHIFT, XKB_KEY_M, setlayout, {.v = &layouts[2]} },+ { MODKEY, XKB_KEY_space, togglefloating, {0} },+ { MODKEY, XKB_KEY_f, togglefullscreen, {0} },+ { MODKEY, XKB_KEY_comma, focusmon, {.i = WLR_DIRECTION_LEFT} },+ { MODKEY, XKB_KEY_period, focusmon, {.i = WLR_DIRECTION_RIGHT} },+ { MODKEY|MODSHIFT, XKB_KEY_less, tagmon, {.i = WLR_DIRECTION_LEFT} },+ { MODKEY|MODSHIFT, XKB_KEY_greater, tagmon, {.i = WLR_DIRECTION_RIGHT} },+ { MODKEY|MODSHIFT, XKB_KEY_P, quit, {0} },++ /* Ctrl-Alt-Backspace and Ctrl-Alt-Fx used to be handled by X server */+ { MODCTRL|MODALT, XKB_KEY_Terminate_Server, quit, {0} },++ TAGKEYS(XKB_KEY_1, XKB_KEY_exclam, 0),+ TAGKEYS(XKB_KEY_2, XKB_KEY_at, 1),+ TAGKEYS(XKB_KEY_3, XKB_KEY_numbersign, 2),+ TAGKEYS(XKB_KEY_4, XKB_KEY_dollar, 3),+ TAGKEYS(XKB_KEY_5, XKB_KEY_percent, 4),+ TAGKEYS(XKB_KEY_6, XKB_KEY_asciicircum, 5),++ /* Ctrl-Alt-Fx is used to switch to another VT */+ CHVT(1), CHVT(2), CHVT(3), CHVT(4), CHVT(5), CHVT(6),+ CHVT(7), CHVT(8), CHVT(9), CHVT(10), CHVT(11), CHVT(12),+};++static const Button buttons[] = {+ { MODKEY, BTN_LEFT, moveresize, {.ui = CurMove} },+ { MODKEY, BTN_RIGHT, moveresize, {.ui = CurResize} },+ { MODKEY, BTN_MIDDLE, togglefloating, {0} },+};