diff --git a/config/apps/default.nix b/config/apps/default.nix
index ca9030f..b41be50 100644
--- a/config/apps/default.nix
+++ b/config/apps/default.nix
@@ -2,6 +2,8 @@
imports = [
./firefox.nix
./sway.nix
+ ./waybar.nix
./alacritty.nix
+ ./zsh.nix
];
}
diff --git a/config/apps/firefox.nix b/config/apps/firefox.nix
index f265027..282120b 100644
--- a/config/apps/firefox.nix
+++ b/config/apps/firefox.nix
@@ -3,6 +3,18 @@
in{
programs.firefox = {
enable = true;
+
+ policies = {
+ CaptivePortal = false;
+ DisablePocket = true;
+ DisableTelemetry = true;
+ DisableFirefoxStudies = true;
+ FirefoxHome = {
+ Pocket = false;
+ Snippets = false;
+ };
+ };
+
profiles = {
default = {
isDefault = true;
@@ -14,13 +26,96 @@ in{
};
settings = {
+ # disable warning when editing about:config
"browser.aboutConfig.showWarning" = false;
- "browser.toolbars.bookmarks.visibility" = "never";
+ # webgpu
"dom.webgpu.enabled" = true;
"gfx.webrender.all" = true;
"signon.rememberSignons" = false;
+ # mozilla syncserver
"identity.sync.tokenserver.uri" = "https://nirgendswo.com:8001/1.0/sync/1.5";
"services.sync.username" = user.email;
+ "browser.startup.page" = 3; # resume previous session
+ "browser.startup.homepage" = "about:home";
+ "browser.toolbars.bookmarks.visibility" = "never";
+
+ # hardening
+ "browser.newtabpage.enabled" = false;
+ "browser.newtabpage.activity-stream.feeds.telemetry" = false;
+ "browser.newtabpage.activity-stream.telemetry" = false;
+ "browser.newtabpage.activity-stream.feeds.snippets" = false;
+ "browser.newtabpage.activity-stream.feeds.section.topstories" = false;
+ "browser.newtabpage.activity-stream.showSponsoredTopSites" = false;
+ "browser.newtabpage.activity-stream.showSponsored" = false;
+ "browser.newtabpage.activity-stream.feeds.discoverystreamfeed" = false;
+ "browser.newtabpage.activity-stream.default.sites" = "";
+ "browser.newtab.preload" = false;
+ "geo.provider.network.url" = "https://location.services.mozilla.com/v1/geolocate?key=%MOZILLA_API_KEY%";
+ "geo.provider.ms-windows-location" = false;
+ "geo.provider.use_corelocation" = false;
+ "geo.provider.use_gpsd" = false;
+ "geo.provider.use_geoclue" = false;
+ "browser.region.network.url" = "";
+ "browser.region.update.enabled" = false;
+ "intl.accept_languages" = "en-US,en-GB,en";
+ "javascript.use_us_language_locale" = true;
+ "app.update.auto" = false;
+
+ "extensions.discover.enabled" = false;
+ "extensions.htmlaboutaddons.recommendations.enabled" = false;
+ "extenisons.getAddons.showPane" = false;
+
+ "datareporting.healthreport.uploadEnabled" = false;
+ "datareporting.policy.dataSubmissionEnabled" = false;
+ "toolkit.telemetry.enabled" = false;
+ "toolkit.telemetry.unified" = false;
+ "toolkit.telemetry.server" = "data:,";
+ "toolkit.telemetry.archive.enabled" = false;
+ "toolkit.telemetry.newProfilePing.enabled" = false;
+ "toolkit.telemetry.shutdownPingSender.enabled" = false;
+ "toolkit.telemetry.updatePing.enabled" = false;
+ "toolkit.telemetry.bhrPing.enabled" = false;
+ "toolkit.telemetry.firstShutdownPing.enabled" = false;
+ "toolkit.telemetry.coverage.opt-out" = true;
+ "toolkit.coverage.opt-out" = true;
+ "beacon.enabled" = false;
+
+ "app.shield.optoutstudies.enabled" = false;
+
+ "captivedetect.canonicalURL" = "";
+ "network.captive-portal-service.enabled" = false;
+ "network.connectivity-service.enabled" = false;
+
+ "browser.safebrowsing.malware.enabled" = false;
+ "browser.safebrowsing.phishing.enabled" = false;
+ "browser.safebrowsing.blockedURIs.enabled" = false;
+ "browser.safebrowsing.provider.google4.gethashURL" = "";
+ "browser.safebrowsing.provider.google4.updateURL" = "";
+ "browser.safebrowsing.provider.google4.dataSharingURL" = "";
+ "browser.safebrowsing.provider.google.gethashURL" = "";
+ "browser.safebrowsing.provider.google.updateURL" = "";
+
+ "browser.safebrowsing.downloads.enabled" = false;
+ "browser.safebrowsing.downloads.remote.enabled" = false;
+ "browser.safebrowsing.downloads.remote.url" = "";
+ "browser.safebrowsing.allowOverride" = false;
+
+ "network.prefetch-next" = false;
+ "network.dns.disablePrefetch" = true;
+ "network.predictor.enabled" = false;
+
+ "browser.fixup.alternate.enabled" = false;
+ "browser.urlbar.trimURLs" = false;
+
+ "browser.contentblocking.category" = "strict";
+ "privacy.partition.serviceWorkers" = true;
+ "privacy.partition.always_partition_third_party_non_cookie_storage" = true;
+ "privacy.partition.always_partition_third_party_non_cookie_storage.exempt_sessionstorage" = true;
+ "privacy.resistFingerprinting" = true;
+ "privacy.resistFingerprinting.block_mozAddonManager" = true;
+
+ "app.normandy.enabled" = false;
+ "app.normandy.api_url" = "";
};
extensions.packages = with pkgs.nur.repos.rycee.firefox-addons; [
diff --git a/config/apps/sway.nix b/config/apps/sway.nix
index 949ce82..0f53377 100644
--- a/config/apps/sway.nix
+++ b/config/apps/sway.nix
@@ -22,6 +22,10 @@ in {
inner = 8;
};
+ bars = [{
+ command = "${pkgs.waybar}/bin/waybar";
+ }];
+
window = {
border = 3;
titlebar = false;
@@ -132,9 +136,4 @@ in {
};
};
};
-
- programs.waybar = {
- enable = true;
- systemd.enable = true;
- };
}
diff --git a/config/apps/waybar.nix b/config/apps/waybar.nix
new file mode 100644
index 0000000..9b0160c
--- /dev/null
+++ b/config/apps/waybar.nix
@@ -0,0 +1,233 @@
+{lib, config, ...}:
+let
+ theme = import ../data/theme.nix {inherit config; };
+ utils = import ../utils.nix {inherit lib; };
+in let
+ self = rec {
+ # ModuleDesc has the shape {name, config?, background?, color?, style?}
+ module-descs = [
+ {
+ name = "custom/left-most";
+ background = theme.background;
+ }
+ {
+ name = "pulseaudio";
+ config = {
+ format = "{volume}% {icon} {format_source}";
+ format-bluetooth = "{volume}% {icon} {format_source}";
+ format-muted = "{format_source}";
+ format-source = "{volume}% ";
+ format-source-muted = "";
+ format-icons = {
+ headphones = "";
+ default = ["" "" ""];
+ };
+ on-click = "pavucontrol";
+ };
+ background = theme.normal.yellow;
+ }
+ {
+ name = "network";
+ config = {
+ format-wifi = "{essid} {signalStrength}% {icon}";
+ format-ethernet = "{ipaddr} ";
+ format-disconnected = "Disconnected ";
+ tooltip-format = ''Interface: {ifname}
+IP: {ipaddr}
+Speed: {bandwidthUpBytes} / {bandwidthDownBytes}
+Signal: {signalStrength}%
+SSID: {essid} {frequency}'';
+ on-click = "iwgtk";
+ format-icons = ["" "" "" "" ""];
+ };
+ background = theme.normal.green;
+ }
+ {
+ name = "custom/vpn";
+ config = {
+ format = "{}";
+ excape = true;
+ interval = 30;
+ exec = "nordvpn-rofi.sh --status-json";
+ return-type = "json";
+ on-click = "rofi -show vpn -modes 'vpn:nordvpn-rofi.sh'";
+ };
+ style = {
+ connected.color = theme.normal.black;
+ disconnected.color = theme.normal.yellow;
+ };
+ background = theme.extra.teal;}
+ ]
+ ++ (if (config.has_battery) then [{
+ name = "battery";
+ config = {
+ states = {
+ critical = 15;
+ warning = 25;
+ good = 80;
+ full = 90;
+ };
+ interval = 30;
+ format = "{capacity}% {icon}";
+ format-charging = "{capacity}% ";
+ format-plugged = "{capacity}% ";
+ format-icons = ["" "" "" "" ""];
+ };
+ background = theme.extra.aqua;
+ }] else [])
+ ++ [
+ {
+ name = "cpu";
+ config = {
+ format = "{}% ";
+ };
+ background = theme.extra.brown;
+ }
+ {
+ name = "memory";
+ config = {
+ format = "{}% ";
+ };
+ background = theme.extra.darkbrown;
+ }
+ {
+ name = "temperature";
+ config = {
+ critical-threshold = 80;
+ hwmon-path = "/sys/class/hwmon/hwmon5/temp1_input";
+ format = "{temperatureC}°C {icon}";
+ format-icons = ["" "" ""];
+ };
+ background = theme.extra.darkerbrown;
+ }
+ {
+ name = "clock";
+ config = {
+ format = "{:%H:%M} ";
+ tooltip-format = "{calendar}";
+ calendar = {
+ mode = "month";
+ weeks-pos = "left";
+ on-scroll = 1;
+ format = {
+ months = "{}";
+ days = "{}";
+ weekdays = "{}";
+ today = "{}";
+ };
+ on-scroll-up = "shift_up";
+ on-scroll-down = "shift_down";
+ };
+ };
+ background = theme.normal.black;
+ }
+ {name = "tray"; config = { spacing = 10; }; background = theme.background;}
+ ];
+
+ # default style for modules
+ default-style = "padding-left: 8pt; padding-right: 8pt;";
+
+ # ModuleDesc -> Module
+ mkModule = desc: let
+ background = desc.background or theme.background;
+ color = desc.color or theme.foreground;
+ config = desc.config or {};
+ # style = module.style or "";
+ style = default-style;
+ style-name = builtins.replaceStrings ["/"] ["-"] desc.name;
+ in {
+ inherit (desc) name;
+ setting = {
+ } // config;
+
+ style = "#${style-name} {" + default-style + ''background: ${background};color: ${color};'' + "}\n";
+ };
+
+ mkSpacer = idx: left: right: {
+ name = "custom/arrow${toString idx}";
+ setting = {
+ format = "";
+ tooltip = false;
+ };
+ style = "#custom-arrow${toString idx} {font-size: 14pt;background: ${left.background};color: ${right.background};}\n";
+ };
+
+ # modules interlaced with spacers
+ # [ModuleDesc] -> [Module]
+ mkSpacedModules = descs: with builtins;
+ let
+ len = length descs;
+ in lib.lists.flatten
+ (lib.lists.imap0
+ (n: descs: let
+ left = elemAt descs 0;
+ right = elemAt descs 1;
+ in if n == len then [
+ (mkModule left)
+ (mkSpacer n left right)
+ (mkModule right)
+ ] else [
+ (mkModule left)
+ (mkSpacer n left right)
+ ])
+ (utils.windows 2 descs)
+ );
+
+ # Module -> {"name" = setting}
+ mkModuleConfig = {name, setting, ...}: lib.attrsets.optionalAttrs (!utils.isEmptySet setting) {
+ "${name}" = setting;
+ };
+
+ # builds bar configuration with left, center, and right modules
+ # right modules get spacers in between them.
+ # {left: [ModuleDesc], center: [ModuleDesc], right: [ModuleDesc], config: {}} -> {config, style}
+ mkBar = {left, center, right, config, ...}:
+ let
+ # Create modules from the descriptions
+ right' = mkSpacedModules right;
+ left' = map (module: mkModule module) left;
+ center' = map (module: mkModule module) center;
+ in let
+ # Create lists of module names for the config
+ modules-left = map (module: module.name) left';
+ modules-center = map (module: module.name) center';
+ modules-right = map (module: module.name) right';
+ # Combine all modules into a single list
+ modules = lib.lists.flatten [left' center' right'];
+ in {
+ config = lib.attrsets.mergeAttrsList (lib.lists.flatten [
+ {
+ inherit modules-left modules-center modules-right;
+ }
+ config
+ (map mkModuleConfig modules)
+ ]);
+ style = lib.strings.concatStringsSep "\n" (map (module: module.style) modules);
+ };
+ };
+
+ bar = self.mkBar {
+ left = [ {name = "sway/workspaces";} {name = "sway/mode";} ];
+ center = [ {name = "sway/window";} ];
+ right = self.module-descs;
+ config = {
+ height = 25;
+ spacing = 0;
+ position = "top";
+ };
+ };
+in {
+ programs.waybar = {
+ enable = true;
+
+ settings = {
+ mainBar = bar.config;
+ };
+
+ style = ''
+* {border: none; border-radius: 0; min-height: 0; margin: 0; padding: 0; box-shadow: none; text-shadow: none;}
+#waybar { background: rgba(40, 40, 40, 0.3); color: #ffffff; font-family: "sans-serif"; font-size: 12pt; font-weight: 500; }
+''
+ + bar.style;
+ };
+}
diff --git a/config/apps/zsh.nix b/config/apps/zsh.nix
new file mode 100644
index 0000000..2a9cc9f
--- /dev/null
+++ b/config/apps/zsh.nix
@@ -0,0 +1,39 @@
+{pkgs, ...}:
+let
+ aliases = import ../data/zsh-aliases.nix {};
+in {
+ home.packages = with pkgs; [ pure-prompt ];
+ programs.zsh = {
+ enable = true;
+ enableCompletion = true;
+ shellAliases = aliases;
+
+ history = {
+ size = 10000000;
+ save = 10000000;
+ findNoDups = true;
+ saveNoDups = true;
+ ignoreDups = true;
+ share = true;
+ extended = true;
+ append = true;
+ path = "$HOME/.zsh_history";
+ };
+
+ initExtra = ''
+prompt pure
+zstyle :prompt:pure:path color cyan
+zstyle :prompt:pure:prompt:error color red
+zstyle :prompt:pure:prompt:success color green
+bindkey -v
+autoload -Uz edit-command-line
+zle -N edit-command-line
+bindkey '^X^E' edit-command-line
+'';
+ };
+
+ programs.fzf = {
+ enable = true;
+ enableZshIntegration = true;
+ };
+}
diff --git a/config/configuration.nix b/config/configuration.nix
index 8bdbd48..fcf2a76 100644
--- a/config/configuration.nix
+++ b/config/configuration.nix
@@ -1,4 +1,4 @@
-{ ... }:
+{ lib, ... }:
{
imports =
[ # Include the results of the hardware scan.
@@ -6,6 +6,8 @@
# inputs.home-manager.nixosModules.default
./nixos
./users/alice.nix
+ ./variables.nix
+ ./hosts/vm.nix
];
# to use zsh as a login shell, it has to be enabled globally.
diff --git a/config/data/theme.nix b/config/data/theme.nix
new file mode 100644
index 0000000..2fc5a08
--- /dev/null
+++ b/config/data/theme.nix
@@ -0,0 +1,21 @@
+{config, ...}:
+let
+ theme = if config.darkMode then import ./gruvbox-dark.nix {}
+ else import ./gruvbox-light.nix {};
+in
+{
+ inherit (theme) background foreground normal bright;
+
+ extra = {
+ red = "#bd574e";
+ orange = "#eb8242";
+ yellow = "#ede06b";
+ green = "#9bb67c";
+ teal = "#87a7b3";
+ purple = "#ad6989";
+ brown = "#ad8b73";
+ darkbrown = "#85603f";
+ darkerbrown = "#5e454b";
+ cream = "#fefcf3";
+ };
+}
diff --git a/config/data/zsh-aliases.nix b/config/data/zsh-aliases.nix
new file mode 100644
index 0000000..a21009c
--- /dev/null
+++ b/config/data/zsh-aliases.nix
@@ -0,0 +1,13 @@
+{...}: {
+ ll = "ls -l";
+ la = "ls -la";
+ git-tree = "git log --graph --oneline --all";
+ c = "clear";
+ cl = "clear; ls --color=auto";
+ q = "exit";
+ ssh = "TERM=xterm-256color ssh";
+ emacs = "emacs -nw"; # Use emacs in terminal mode.
+
+ # dotfiles
+ dotfiles = "git --git-dir=$HOME/.dotfiles/ --work-tree=$HOME";
+}
diff --git a/config/hosts/common.nix b/config/hosts/common.nix
new file mode 100644
index 0000000..e69de29
diff --git a/config/hosts/default.nix b/config/hosts/default.nix
new file mode 100644
index 0000000..d854dcc
--- /dev/null
+++ b/config/hosts/default.nix
@@ -0,0 +1,3 @@
+{...}: {
+ imports = [];
+}
diff --git a/config/hosts/laptop.nix b/config/hosts/laptop.nix
new file mode 100644
index 0000000..dbb925f
--- /dev/null
+++ b/config/hosts/laptop.nix
@@ -0,0 +1,4 @@
+{config, ...}: {
+ imports = [ ../variables.nix ];
+ config.has_battery = true;
+}
diff --git a/config/hosts/vm.nix b/config/hosts/vm.nix
new file mode 100644
index 0000000..dea1914
--- /dev/null
+++ b/config/hosts/vm.nix
@@ -0,0 +1,5 @@
+{...}: {
+ imports = [ ../variables.nix ];
+ # config.has_battery = true;
+ config.vmGuest = true;
+}
diff --git a/config/nixos/system.nix b/config/nixos/system.nix
index fc583e5..31acd03 100644
--- a/config/nixos/system.nix
+++ b/config/nixos/system.nix
@@ -1,7 +1,11 @@
-{pkgs, ...}:
+{config, pkgs, ...}:
let
base = import ../options.nix {};
in {
+ imports = [
+ ../variables.nix
+ ];
+
system.stateVersion = "${base.stateVersion}";
nix.settings.experimental-features = [
@@ -25,6 +29,9 @@ in {
# useXkbConfig = true; # use xkb.options in tty.
};
+ services.qemuGuest.enable = config.vmGuest;
+ services.spice-vdagentd.enable = config.vmGuest;
+
security.rtkit.enable = true; # Enable real-time scheduling for audio applications.
services = {
diff --git a/config/users/alice.nix b/config/users/alice.nix
index 5093740..3ccfd70 100644
--- a/config/users/alice.nix
+++ b/config/users/alice.nix
@@ -11,21 +11,6 @@ inputs @ { pkgs, lib, ...}: let
htop
]; # Default packages for the owner account.
};
-
- # configure the shell
- programs.zsh = {
- enable = true; # Enable zsh shell.
- enableCompletion = true; # Enable zsh completion.
- shellAliases = {
- ll = "ls -l";
- la = "ls -la";
- git-tree = "git log --graph --oneline --all";
- c = "clear";
- q = "exit";
- ssh = "TERM=xterm-256color ssh";
- emacs = "emacs -nw"; # Use emacs in terminal mode.
- };
- };
};
in {
imports = [(lib.modules.importApply ./user.nix {
diff --git a/config/users/user.nix b/config/users/user.nix
index 614ab3d..18844e0 100644
--- a/config/users/user.nix
+++ b/config/users/user.nix
@@ -27,7 +27,7 @@ in {
};
home-manager.users.${username} = {...}: {
- imports = [ user.userModule ];
+ imports = [ ../variables.nix user.userModule ];
# programs.home-manager.enable = true;
diff --git a/config/utils.nix b/config/utils.nix
new file mode 100644
index 0000000..cd69dfc
--- /dev/null
+++ b/config/utils.nix
@@ -0,0 +1,20 @@
+{lib, ...}: rec {
+ min = a: b: if a < b then a else b;
+ max = a: b: if a > b then a else b;
+ # build list of `len` lists of `n` elements of `xs`
+ windows = with builtins; n: xs: let
+ len = length xs;
+ n' = min n len;
+ # when len = n, there is still one window
+ num-windows = max 0 (len - n' + 1);
+ in
+ genList
+ # for i in 0..len
+ (i: genList
+ # for j in 0..n -> xs[i + j]
+ (j: elemAt xs (i + j))
+ n')
+ num-windows;
+
+ isEmptySet = set: with builtins; length (attrNames set) == 0;
+}
diff --git a/config/variables.nix b/config/variables.nix
new file mode 100644
index 0000000..c47bfc3
--- /dev/null
+++ b/config/variables.nix
@@ -0,0 +1,21 @@
+{lib, ...}: {
+ options = {
+ has_battery = lib.mkOption {
+ type = lib.types.bool;
+ default = false;
+ description = "Whether the system has a battery.";
+ };
+
+ vmGuest = lib.mkOption {
+ type = lib.types.bool;
+ default = false;
+ description = "Enable VM guest services.";
+ };
+
+ darkMode = lib.mkOption {
+ type = lib.types.bool;
+ default = false;
+ description = "Enable dark mode for the system.";
+ };
+ };
+}