From a0f9f4baa46bda5611985045612f20e666df8224 Mon Sep 17 00:00:00 2001 From: Tom Alexander Date: Sat, 21 Dec 2024 10:18:28 -0500 Subject: [PATCH] Set up waybar and building ISOs. --- nix/configuration/boot.nix | 44 +++- nix/configuration/configuration.nix | 34 +-- nix/configuration/flake.nix | 128 ++++------- nix/configuration/hosts/odo/disk-config.nix | 7 + nix/configuration/roles/emacs/default.nix | 2 +- nix/configuration/roles/firefox/default.nix | 4 +- nix/configuration/roles/gpg/default.nix | 2 +- nix/configuration/roles/iso/default.nix | 18 ++ nix/configuration/roles/qemu/default.nix | 14 ++ nix/configuration/roles/sway/default.nix | 82 ++++++- nix/configuration/roles/waybar/default.nix | 28 +++ .../roles/waybar/files/style.css | 211 ++++++++++++++++++ .../roles/waybar/files/waybar_config.json | 57 +++++ 13 files changed, 500 insertions(+), 131 deletions(-) create mode 100644 nix/configuration/roles/iso/default.nix create mode 100644 nix/configuration/roles/qemu/default.nix create mode 100644 nix/configuration/roles/waybar/default.nix create mode 100644 nix/configuration/roles/waybar/files/style.css create mode 100644 nix/configuration/roles/waybar/files/waybar_config.json diff --git a/nix/configuration/boot.nix b/nix/configuration/boot.nix index 1e77b4c..432ba18 100644 --- a/nix/configuration/boot.nix +++ b/nix/configuration/boot.nix @@ -1,3 +1,4 @@ +# ISO does not work with systemd initrd yet https://github.com/NixOS/nixpkgs/pull/291750 { config, lib, @@ -8,16 +9,43 @@ { imports = [ ]; - boot.loader.grub.enable = false; - # Use the systemd-boot EFI boot loader. - boot.loader.systemd-boot.enable = true; - # TODO: make not write bootx64.efi - boot.loader.efi.canTouchEfiVariables = false; + config = lib.mkIf (!config.me.buildingIso) { - # Automatically delete old generations - boot.loader.systemd-boot.configurationLimit = 3; + boot.loader.grub.enable = false; + # Use the systemd-boot EFI boot loader. + boot.loader.systemd-boot.enable = true; + # TODO: make not write bootx64.efi + boot.loader.efi.canTouchEfiVariables = false; + + # Automatically delete old generations + boot.loader.systemd-boot.configurationLimit = 3; + + # Check what will be lost with `zfs diff zroot/linux/root@blank` + boot.initrd.systemd.enable = lib.mkDefault true; + boot.initrd.systemd.services.zfs-rollback = { + description = "Rollback ZFS root dataset to blank snapshot"; + wantedBy = [ + "initrd.target" + ]; + after = [ + "zfs-import-zroot.service" + ]; + before = [ + "sysroot.mount" + ]; + path = with pkgs; [ + zfs + ]; + unitConfig.DefaultDependencies = "no"; + serviceConfig.Type = "oneshot"; + script = '' + zfs rollback -r zroot/linux/nix/root@blank + zfs rollback -r zroot/linux/nix/home@blank + echo "rollback complete" + ''; + }; + }; } - # efibootmgr -c -d /dev/sda -p 1 -L NixOS-boot -l '\EFI\NixOS-boot\grubx64.efi' # Text-only: diff --git a/nix/configuration/configuration.nix b/nix/configuration/configuration.nix index c0dd571..5d5d037 100644 --- a/nix/configuration/configuration.nix +++ b/nix/configuration/configuration.nix @@ -10,6 +10,7 @@ { imports = [ ./roles/reset + ./roles/iso ./hosts/odo "${ builtins.fetchTarball { @@ -30,6 +31,8 @@ ./roles/git ./roles/fonts ./roles/gpg + ./roles/waybar + ./roles/qemu ]; nix.settings.experimental-features = [ @@ -134,38 +137,17 @@ ]; }; - # Check what will be lost with `zfs diff zroot/linux/root@blank` - boot.initrd.systemd.enable = lib.mkDefault true; - boot.initrd.systemd.services.zfs-rollback = { - description = "Rollback ZFS root dataset to blank snapshot"; - wantedBy = [ - "initrd.target" - ]; - after = [ - "zfs-import-zroot.service" - ]; - before = [ - "sysroot.mount" - ]; - path = with pkgs; [ - zfs - ]; - unitConfig.DefaultDependencies = "no"; - serviceConfig.Type = "oneshot"; - script = '' - zfs rollback -r zroot/linux/nix/root@blank - zfs rollback -r zroot/linux/nix/home@blank - echo "rollback complete" - ''; - }; - - environment.persistence."/persist" = { + environment.persistence."/persist" = lib.mkIf (!config.me.buildingIso) { hideMounts = true; directories = [ "/var/lib/iwd" # Wifi settings "/var/lib/nixos" # Contains user information (uids/gids) + "/var/lib/systemd" # Systemd state directory for random seed, persistent timers, core dumps, persist hardware state like backlight and rfkill + "/var/log/journal" # Logs, alternatively set `services.journald.storage = "volatile";` to write to /run/log/journal + "/etc/zfs/zpool.cache" # Which zpools to import, the root zpool is already imported and does not need this cache file but this captures additional pools. TODO consider setting cachefile=none on main pool. ]; files = [ + "/etc/machine-id" # Systemd unique machine id "otherwise, the system journal may fail to list earlier boots, etc" "/etc/ssh/ssh_host_rsa_key" "/etc/ssh/ssh_host_rsa_key.pub" "/etc/ssh/ssh_host_ed25519_key" diff --git a/nix/configuration/flake.nix b/nix/configuration/flake.nix index 4771227..3fc688a 100644 --- a/nix/configuration/flake.nix +++ b/nix/configuration/flake.nix @@ -1,5 +1,30 @@ # Build ISO image -# doas nix run github:nix-community/nixos-generators -- --flake .#odo --format iso +# nix build --extra-experimental-features nix-command --extra-experimental-features flakes .#iso.odo +# output: result/iso/nixos.iso + +# Run the ISO image +# "$(nix-build '' --no-out-link -A 'qemu')/bin/qemu-system-x86_64" \ +# -accel kvm \ +# -cpu host \ +# -smp cores=8 \ +# -m 32768 \ +# -drive "file=$(nix-build '' --no-out-link -A 'OVMF.fd')/FV/OVMF.fd,if=pflash,format=raw,readonly=on" \ +# -drive if=pflash,format=raw,file="/tmp/OVMF_VARS.fd" \ +# -nic user,hostfwd=tcp::60022-:22 \ +# -boot order=d \ +# -cdrom "$(readlink -f ./result/iso/nixos.iso)" \ +# -display vnc=127.0.0.1:0 +# +# doas cp "$(nix-build '' --no-out-link -A 'OVMF.fd')/FV/OVMF_VARS.fd" /tmp/OVMF_VARS.fd +# doas "$(nix-build '' --no-out-link -A 'qemu')/bin/qemu-system-x86_64" -accel kvm -cpu host -smp cores=8 -m 32768 -drive "file=$(nix-build '' --no-out-link -A 'OVMF.fd')/FV/OVMF.fd,if=pflash,format=raw,readonly=on" -drive if=pflash,format=raw,file="/tmp/OVMF_VARS.fd" -nic user,hostfwd=tcp::60022-:22 -boot order=d -cdrom /persist/machine_setup/nix/configuration/result/iso/nixos.iso -display vnc=127.0.0.1:0 + +# Get a repl for this flake +# nix repl --expr "builtins.getFlake \"$PWD\"" + +# TODO maybe use `nix eval --raw .#iso.odo.outPath` +# iso.odo.isoName == "nixos.iso" +# full path = / iso / + { description = "My system configuration"; @@ -23,17 +48,14 @@ ... }@inputs: let - base-system = { }; - odoqemu = nixpkgs.lib.nixosSystem rec { + base_x86_64_linux = rec { system = "x86_64-linux"; specialArgs = { pkgs-b93b4e9b5 = import nixpkgs-b93b4e9b5 { inherit system; - # config.allowUnfree = true; }; pkgs-unstable = import nixpkgs-unstable { inherit system; - # config.allowUnfree = true; }; }; modules = [ @@ -44,88 +66,30 @@ home-manager.useUserPackages = true; } ./configuration.nix - ( - { lib, ... }: - { - imports = [ ]; - virtualisation.qemu.options = [ - "-device virtio-vga" - ]; - virtualisation.vmVariant = { - # following configuration is added only when building VM with build-vm - virtualisation = { - memorySize = 2048; # Use 2048MiB memory. - cores = 3; - graphics = false; - }; - }; - networking.dhcpcd.enable = lib.mkForce true; - networking.useDHCP = lib.mkForce true; - boot.loader.efi.canTouchEfiVariables = lib.mkForce true; - # doas nixos-rebuild build-vm --flake .#odoqemu - #./result/bin/run-nixos-vm - } - ) ]; }; - odo = nixpkgs.lib.nixosSystem rec { - system = "x86_64-linux"; - specialArgs = { - pkgs-b93b4e9b5 = import nixpkgs-b93b4e9b5 { - inherit system; - # config.allowUnfree = true; - }; - pkgs-unstable = import nixpkgs-unstable { - inherit system; - # config.allowUnfree = true; - }; + systems = { + odo = { + main = nixpkgs.lib.nixosSystem (base_x86_64_linux // { }); + iso = nixpkgs.lib.nixosSystem ( + base_x86_64_linux + // { + modules = base_x86_64_linux.modules ++ [ + (nixpkgs + "/nixos/modules/installer/cd-dvd/iso-image.nix") + # TODO: maybe? imports = [ "${modulesPath}/profiles/image-based-appliance.nix" ]; + { + isoImage.makeEfiBootable = true; + isoImage.makeUsbBootable = true; + me.buildingIso = true; + } + ]; + } + ); }; - modules = [ - impermanence.nixosModules.impermanence - home-manager.nixosModules.home-manager - { - home-manager.useGlobalPkgs = true; - home-manager.useUserPackages = true; - } - ./configuration.nix - ]; }; in { - # doas nix build --extra-experimental-features nix-command --extra-experimental-features flakes .#vms.odo - # ./result/bin/run-nixos-vim - vms.odo = odoqemu.config.system.build.vm; - odoiso = odo.config.system.build.isoImage; - nixosConfigurations.odo = odo; - nixosConfigurations.odovm = nixpkgs.lib.nixosSystem rec { - system = "x86_64-linux"; - specialArgs = { - pkgs-b93b4e9b5 = import nixpkgs-b93b4e9b5 { - inherit system; - # config.allowUnfree = true; - }; - pkgs-unstable = import nixpkgs-unstable { - inherit system; - # config.allowUnfree = true; - }; - }; - modules = [ - impermanence.nixosModules.impermanence - home-manager.nixosModules.home-manager - { - home-manager.useGlobalPkgs = true; - home-manager.useUserPackages = true; - } - ./configuration.nix - ( - { lib, ... }: - { - networking.dhcpcd.enable = lib.mkForce true; - networking.useDHCP = lib.mkForce true; - boot.loader.efi.canTouchEfiVariables = lib.mkForce true; - } - ) - ]; - }; + nixosConfigurations.odo = systems.odo.main; + iso.odo = systems.odo.iso.config.system.build.isoImage; }; } diff --git a/nix/configuration/hosts/odo/disk-config.nix b/nix/configuration/hosts/odo/disk-config.nix index cb54e2f..e13af29 100644 --- a/nix/configuration/hosts/odo/disk-config.nix +++ b/nix/configuration/hosts/odo/disk-config.nix @@ -1,4 +1,11 @@ { + config, + lib, + pkgs, + ... +}: + +lib.mkIf (!config.me.buildingIso) { disko.devices = { disk = { main = { diff --git a/nix/configuration/roles/emacs/default.nix b/nix/configuration/roles/emacs/default.nix index 06763c2..1d14883 100644 --- a/nix/configuration/roles/emacs/default.nix +++ b/nix/configuration/roles/emacs/default.nix @@ -61,7 +61,7 @@ in }; }; - environment.persistence."/state" = { + environment.persistence."/state" = lib.mkIf (!config.me.buildingIso) { hideMounts = true; users.talexander = { directories = [ diff --git a/nix/configuration/roles/firefox/default.nix b/nix/configuration/roles/firefox/default.nix index cd6e1e1..159865d 100644 --- a/nix/configuration/roles/firefox/default.nix +++ b/nix/configuration/roles/firefox/default.nix @@ -84,7 +84,7 @@ }; }; - environment.persistence."/persist" = { + environment.persistence."/persist" = lib.mkIf (!config.me.buildingIso) { hideMounts = true; users.talexander = { directories = [ @@ -97,7 +97,7 @@ ]; }; }; - environment.persistence."/state" = { + environment.persistence."/state" = lib.mkIf (!config.me.buildingIso) { hideMounts = true; users.talexander = { directories = [ diff --git a/nix/configuration/roles/gpg/default.nix b/nix/configuration/roles/gpg/default.nix index ba2819c..cb30de5 100644 --- a/nix/configuration/roles/gpg/default.nix +++ b/nix/configuration/roles/gpg/default.nix @@ -18,7 +18,7 @@ enableSSHSupport = true; }; - environment.persistence."/persist" = { + environment.persistence."/persist" = lib.mkIf (!config.me.buildingIso) { hideMounts = true; users.talexander = { directories = [ diff --git a/nix/configuration/roles/iso/default.nix b/nix/configuration/roles/iso/default.nix new file mode 100644 index 0000000..58efa42 --- /dev/null +++ b/nix/configuration/roles/iso/default.nix @@ -0,0 +1,18 @@ +{ + config, + lib, + pkgs, + ... +}: + +{ + imports = [ ]; + + options.me.buildingIso = lib.mkOption { + type = lib.types.bool; + default = false; + example = true; + description = "Whether we are building an ISO image."; + }; + +} diff --git a/nix/configuration/roles/qemu/default.nix b/nix/configuration/roles/qemu/default.nix new file mode 100644 index 0000000..2ec04a7 --- /dev/null +++ b/nix/configuration/roles/qemu/default.nix @@ -0,0 +1,14 @@ +{ + config, + lib, + pkgs, + ... +}: + +{ + imports = [ ]; + + environment.systemPackages = with pkgs; [ + qemu + ]; +} diff --git a/nix/configuration/roles/sway/default.nix b/nix/configuration/roles/sway/default.nix index ace154a..65b3d1b 100644 --- a/nix/configuration/roles/sway/default.nix +++ b/nix/configuration/roles/sway/default.nix @@ -44,6 +44,8 @@ let include ${disable-focus-follows-mouse} include ${background} include ${touchpad_input} + include ${waybar} + include ${announce_sway_start} ''; }; base-hotkeys = pkgs.writeTextFile { @@ -229,6 +231,36 @@ let } ''; }; + waybar = pkgs.writeTextFile { + name = "waybar.conf"; + text = '' + # + # Status Bar: + # + # Read `man 5 sway-bar` for more information about this section. + bar { + position top + + font pango:Cascadia Mono, FontAwesome 10 + swaybar_command waybar + + colors { + statusline #ffffff + background #323232 + inactive_workspace #32323200 #32323200 #5c5c5c + } + } + ''; + }; + announce_sway_start = pkgs.writeTextFile { + name = "announce_sway_start.conf"; + text = '' + # announce a running sway session to systemd + exec systemctl --user import-environment XDG_SESSION_TYPE XDG_CURRENT_DESKTOP + exec dbus-update-activation-environment --systemd WAYLAND_DISPLAY XDG_CURRENT_DESKTOP=sway + ''; + }; + start_screen_share = pkgs.writeShellScriptBin "start_screen_share" '' # Disable displaying notifications. This is useful for video conference screen sharing. set -euo pipefail @@ -261,23 +293,37 @@ in stop_screen_share ]; - environment.sessionVariables = { - # WLR_RENDERER_ALLOW_SOFTWARE = "1"; - WLR_RENDERER = "vulkan"; - }; + # Probably would be cleaner to use environment.sessionVariables but programs.sway.extraSessionCommands is sway-specific. + programs.sway.extraSessionCommands = + if config.me.buildingIso then + '' + export WLR_RENDERER_ALLOW_SOFTWARE=1; + '' + else + '' + export WLR_RENDERER=vulkan + ''; programs.sway = { enable = true; wrapperFeatures.gtk = true; - extraOptions = [ - "--debug" - "--config" - "${sway-config}" - # "--unsupported-gpu" - ]; + extraOptions = + if config.me.buildingIso then + [ + "--debug" + "--config" + "${sway-config}" + "--unsupported-gpu" + ] + else + [ + "--debug" + "--config" + "${sway-config}" + ]; }; - environment.persistence."/state" = { + environment.persistence."/state" = lib.mkIf (!config.me.buildingIso) { hideMounts = true; users.talexander = { files = [ @@ -293,6 +339,20 @@ in xdg-desktop-portal-wlr xdg-desktop-portal-gtk ]; + wlr = { + enable = true; + settings = { + # uninteresting for this problem, for completeness only + screencast = { + # output_name = "eDP-1"; + max_fps = 30; + exec_before = "${start_screen_share}"; + exec_after = "${stop_screen_share}"; + chooser_type = "simple"; + chooser_cmd = "${pkgs.slurp}/bin/slurp -f %o -or"; + }; + }; + }; }; }; } diff --git a/nix/configuration/roles/waybar/default.nix b/nix/configuration/roles/waybar/default.nix new file mode 100644 index 0000000..3720340 --- /dev/null +++ b/nix/configuration/roles/waybar/default.nix @@ -0,0 +1,28 @@ +{ + config, + lib, + pkgs, + ... +}: + +{ + imports = [ ]; + + environment.systemPackages = with pkgs; [ + waybar + ]; + + home-manager.users.talexander = + { pkgs, ... }: + { + home.file = { + ".config/waybar/config" = { + source = ./files/waybar_config.json; + }; + ".config/waybar/style.css" = { + source = ./files/style.css; + }; + }; + }; + +} diff --git a/nix/configuration/roles/waybar/files/style.css b/nix/configuration/roles/waybar/files/style.css new file mode 100644 index 0000000..83edc94 --- /dev/null +++ b/nix/configuration/roles/waybar/files/style.css @@ -0,0 +1,211 @@ +/* Work-around for regressions introduced in 0.9.15 */ +* { + all: unset; +} + +/* Reset all styles */ +* { + border: none; + border-radius: 0; + min-height: 0; + margin: 0; + padding: 0; +} + +/* ----------------------------------------------------------------------------- + * Keyframes + * -------------------------------------------------------------------------- */ + +@keyframes blink-warning { + 70% { + color: white; + } + + to { + color: white; + background-color: orange; + } +} + +@keyframes blink-critical { + 70% { + color: white; + } + + to { + color: white; + background-color: red; + } +} + +/* ----------------------------------------------------------------------------- + * Base styles + * -------------------------------------------------------------------------- */ + +/* The whole bar */ +#waybar { + background: #323232; + color: white; + font-family: + Cascadia Mono, + monospace; + font-size: 10px; +} + +tooltip { + background-color: #323232; +} + +/* Each module */ +#battery, +#clock, +#cpu, +#custom-available_memory, +#custom-battery, +#custom-clock, +#custom-night_mode, +#custom-sound, +#custom-temperature, +#idle_inhibitor, +#memory, +#mode, +#network, +#pulseaudio, +#temperature, +#tray { + padding-left: 10px; + padding-right: 10px; + border: 1px solid white; +} + +/* ----------------------------------------------------------------------------- + * Module styles + * -------------------------------------------------------------------------- */ + +#battery { + animation-timing-function: linear; + animation-iteration-count: infinite; + animation-direction: alternate; +} + +#custom-battery.warning { + color: orange; +} + +#custom-battery.critical { + color: red; +} + +#battery.warning.discharging { + animation-name: blink-warning; + animation-duration: 3s; +} + +#battery.critical.discharging { + animation-name: blink-critical; + animation-duration: 2s; +} + +#clock { + font-weight: bold; +} + +#custom-clock { + font-weight: bold; +} + +#cpu { + /* No styles */ +} + +#cpu.warning { + color: orange; +} + +#cpu.critical { + color: red; +} + +#memory { + animation-timing-function: linear; + animation-iteration-count: infinite; + animation-direction: alternate; +} + +#memory.warning { + color: orange; +} + +#memory.critical { + color: red; + animation-name: blink-critical; + animation-duration: 2s; +} + +#mode { + background: #64727d; + border-top: 2px solid white; + /* To compensate for the top border and still have vertical centering */ + padding-bottom: 2px; +} + +#window { + padding-left: 10px; + padding-right: 10px; +} + +#network { + /* No styles */ +} + +#network.disconnected { + color: orange; +} + +#pulseaudio { + /* No styles */ +} + +#pulseaudio.muted { + /* No styles */ +} + +#custom-spotify { + color: rgb(102, 220, 105); +} + +#temperature { + /* No styles */ +} + +#temperature.critical { + color: red; +} + +#tray { + /* No styles */ +} + +#window { + font-weight: bold; +} + +#workspaces button { + border-top: 2px solid transparent; + /* To compensate for the top border and still have vertical centering */ + padding-bottom: 2px; + padding-left: 10px; + padding-right: 10px; + color: #888888; +} + +#workspaces button.focused { + border-color: #4c7899; + color: white; + background-color: #285577; +} + +#workspaces button.urgent { + border-color: #c9545d; + color: #c9545d; +} diff --git a/nix/configuration/roles/waybar/files/waybar_config.json b/nix/configuration/roles/waybar/files/waybar_config.json new file mode 100644 index 0000000..a3f4e3a --- /dev/null +++ b/nix/configuration/roles/waybar/files/waybar_config.json @@ -0,0 +1,57 @@ +{ + // "height": 10, // Waybar height (to be removed for auto height) + "modules-left": ["sway/workspaces", "sway/mode"], + "modules-center": ["sway/window"], + "modules-right": ["custom/night_mode", "custom/temperature", "custom/sound", "custom/available_memory", "custom/battery", "idle_inhibitor", "custom/clock", "tray"], + "sway/workspaces": { + "disable-scroll": true + }, + "sway/mode": { + "format": "{}" + }, + "sway/window": { + "format": "{title}" + }, + "idle_inhibitor": { + "format": "{icon}", + "format-icons": { + "activated": "☕",//☕ + "deactivated": "💤"//☾☁⛾⛔⏾⌛⏳💤 + } + }, + "tray": { + // "icon-size": 21, + "spacing": 10 + }, + "custom/clock": { + "exec": "waybar_custom_clock", + "return-type": "json", + "restart-interval": 30 + }, + "custom/battery": { + "exec": "waybar_custom_battery", + "return-type": "json", + "restart-interval": 30 + }, + "custom/available_memory": { + "exec": "waybar_custom_available_memory", + "return-type": "json", + "restart-interval": 30 + }, + "custom/sound": { + "exec": "waybar_custom_sound", + "return-type": "json", + "restart-interval": 30 + }, + "custom/temperature": { + "exec": "waybar_custom_temperature", + "return-type": "json", + "restart-interval": 30 + }, + "custom/night_mode": { + "exec": "waybar_night_mode", + "return-type": "json", + "restart-interval": 30, + "on-click": "pkill -USR1 -f waybar_night_mode" + } +}