diff --git a/flake.lock b/flake.lock
new file mode 100644
index 0000000..2ee90bf
--- /dev/null
+++ b/flake.lock
@@ -0,0 +1,64 @@
+{
+ "nodes": {
+ "home-manager": {
+ "inputs": {
+ "nixpkgs": [
+ "nixpkgs"
+ ],
+ "utils": "utils"
+ },
+ "locked": {
+ "lastModified": 1672244468,
+ "narHash": "sha256-xaZb8AZqoXRCSqPusCk4ouf+fUNP8UJdafmMTF1Ltlw=",
+ "owner": "nix-community",
+ "repo": "home-manager",
+ "rev": "89a8ba0b5b43b3350ff2e3ef37b66736b2ef8706",
+ "type": "github"
+ },
+ "original": {
+ "owner": "nix-community",
+ "ref": "release-22.11",
+ "repo": "home-manager",
+ "type": "github"
+ }
+ },
+ "nixpkgs": {
+ "locked": {
+ "lastModified": 1672353432,
+ "narHash": "sha256-oZfgp/44/o2tWiylV30cR+DLyWTJ+5dhsdWZVpzs3e4=",
+ "owner": "NixOS",
+ "repo": "nixpkgs",
+ "rev": "913a47cd064cc06440ea84e5e0452039a85781f0",
+ "type": "github"
+ },
+ "original": {
+ "id": "nixpkgs",
+ "ref": "nixos-22.11",
+ "type": "indirect"
+ }
+ },
+ "root": {
+ "inputs": {
+ "home-manager": "home-manager",
+ "nixpkgs": "nixpkgs"
+ }
+ },
+ "utils": {
+ "locked": {
+ "lastModified": 1667395993,
+ "narHash": "sha256-nuEHfE/LcWyuSWnS8t12N1wc105Qtau+/OdUAjtQ0rA=",
+ "owner": "numtide",
+ "repo": "flake-utils",
+ "rev": "5aed5285a952e0b949eb3ba02c12fa4fcfef535f",
+ "type": "github"
+ },
+ "original": {
+ "owner": "numtide",
+ "repo": "flake-utils",
+ "type": "github"
+ }
+ }
+ },
+ "root": "root",
+ "version": 7
+}
diff --git a/flake.nix b/flake.nix
new file mode 100644
index 0000000..b79d490
--- /dev/null
+++ b/flake.nix
@@ -0,0 +1,46 @@
+{
+ description = "NixOS/Darwin system configuration";
+
+ inputs = {
+ nixpkgs.url = "nixpkgs/nixos-22.11";
+ home-manager = {
+ url = "github:nix-community/home-manager/release-22.11";
+ inputs.nixpkgs.follows = "nixpkgs";
+ };
+ };
+
+ outputs = inputs @ { nixpkgs, home-manager, ... }:
+ let
+ inherit (lib) attrValues;
+ inherit (lib.my) mapModules mapModulesRec;
+
+ mkPkgs = pkgs:
+ import pkgs {
+ config.allowUnfree = true;
+ };
+ pkgs = mkPkgs nixpkgs;
+
+ lib = nixpkgs.lib.extend (self: super: {
+ my = import ./lib {
+ inherit pkgs inputs;
+ lib = self;
+ };
+ });
+ in {
+ lib = lib.my;
+
+ nixosModules = mapModulesRec ./modules import;
+
+ nixosConfigurations = {
+ atlas = nixpkgs.lib.nixosSystem {
+ system = "x86_64-linux";
+ modules = [
+ inputs.home-manager.nixosModules.home-manager
+ (import ./modules)
+ ./hosts/atlas
+ ];
+ specialArgs = { inherit lib inputs; };
+ };
+ };
+ };
+}
diff --git a/hosts/atlas/README.md b/hosts/atlas/README.md
new file mode 100644
index 0000000..e9132cb
--- /dev/null
+++ b/hosts/atlas/README.md
@@ -0,0 +1,19 @@
+# Atlas
+
+## Overview
+A general purpose mini computer used for web browsing and multimedia.
+
+## Specs
+* CPU - Intel Core i7-4790K @ 4.00GHz
+* Memory - 8 GB DDR3
+* Motherboard - ASRock Z97M-ITX
+* GPU - AMD Radeon R9 290X 4GB
+
+### Disks
+Device | Partitions _(filesystem, usage)_
+--- | ---
+Samsung SSD 850 | `/dev/sda1` (NTFS, Windows XP)
+Samsung SSD 850 | `/dev/sdb1` (EFI, NixOS Boot)
`/dev/sdb2` (ext4, NixOS Root)
+
+### Networks
+DHCP on `10.0.1.0/24` subnet.
diff --git a/hosts/atlas/default.nix b/hosts/atlas/default.nix
new file mode 100644
index 0000000..2c06821
--- /dev/null
+++ b/hosts/atlas/default.nix
@@ -0,0 +1,45 @@
+{ config, lib, pkgs, ... }:
+
+with lib.my;
+{
+ imports = [
+ ./hardware-configuration.nix
+ ../desktop.nix
+ ];
+
+ boot.loader.systemd-boot.enable = true;
+ boot.loader.efi.canTouchEfiVariables = true;
+ boot.loader.efi.efiSysMountPoint = "/boot/efi";
+
+ networking.hostName = "atlas";
+ networking.networkmanager.enable = true;
+
+ nix.package = pkgs.nixFlakes;
+ nix.extraOptions = ''
+ experimental-features = nix-command flakes
+ '';
+
+ users.defaultUserShell = pkgs.zsh;
+
+ system.stateVersion = "22.11";
+
+ modules = {
+ desktop = {
+ firefox.enable = true;
+ };
+ editors = {
+ neovim.enable = true;
+ vscode.enable = true;
+ };
+ security = {
+ gpg.enable = true;
+ pass.enable = true;
+ };
+ shell = {
+ fzf.enable = true;
+ git.enable = true;
+ nnn.enable = true;
+ zsh.enable = true;
+ };
+ };
+}
\ No newline at end of file
diff --git a/hosts/atlas/hardware-configuration.nix b/hosts/atlas/hardware-configuration.nix
new file mode 100644
index 0000000..9cdd1c4
--- /dev/null
+++ b/hosts/atlas/hardware-configuration.nix
@@ -0,0 +1,41 @@
+# Do not modify this file! It was generated by ‘nixos-generate-config’
+# and may be overwritten by future invocations. Please make changes
+# to /etc/nixos/configuration.nix instead.
+{ config, lib, pkgs, modulesPath, ... }:
+
+{
+ imports =
+ [ (modulesPath + "/installer/scan/not-detected.nix")
+ ];
+
+ boot.initrd.availableKernelModules = [ "xhci_pci" "ehci_pci" "ahci" "usbhid" "usb_storage" "sd_mod" ];
+ boot.initrd.kernelModules = [ ];
+ boot.kernelModules = [ "kvm-intel" "wl" ];
+ boot.extraModulePackages = [ config.boot.kernelPackages.broadcom_sta ];
+
+ fileSystems."/" =
+ { device = "/dev/disk/by-uuid/db92d689-50d4-4301-90f9-122aab198e38";
+ fsType = "ext4";
+ };
+
+ fileSystems."/boot/efi" =
+ { device = "/dev/disk/by-uuid/0720-9BE0";
+ fsType = "vfat";
+ };
+
+ swapDevices =
+ [ { device = "/dev/disk/by-uuid/fb217be3-c5df-4e70-8032-78bfbe7325cb"; }
+ ];
+
+ # Enables DHCP on each ethernet and wireless interface. In case of scripted networking
+ # (the default) this is the recommended approach. When using systemd-networkd it's
+ # still possible to use this option, but it's recommended to use it in conjunction
+ # with explicit per-interface declarations with `networking.interfaces..useDHCP`.
+ networking.useDHCP = lib.mkDefault true;
+ # networking.interfaces.enp0s25.useDHCP = lib.mkDefault true;
+
+ nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
+ hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
+ # high-resolution display
+ hardware.video.hidpi.enable = lib.mkDefault true;
+}
diff --git a/hosts/desktop.nix b/hosts/desktop.nix
new file mode 100644
index 0000000..a85c66a
--- /dev/null
+++ b/hosts/desktop.nix
@@ -0,0 +1,36 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+with lib.my;
+{
+ time.timeZone = "Europe/London";
+
+ i18n.defaultLocale = "en_GB.UTF-8";
+ i18n.extraLocaleSettings = {
+ LC_ADDRESS = "en_GB.UTF-8";
+ LC_IDENTIFICATION = "en_GB.UTF-8";
+ LC_MEASUREMENT = "en_GB.UTF-8";
+ LC_MONETARY = "en_GB.UTF-8";
+ LC_NAME = "en_GB.UTF-8";
+ LC_NUMERIC = "en_GB.UTF-8";
+ LC_PAPER = "en_GB.UTF-8";
+ LC_TELEPHONE = "en_GB.UTF-8";
+ LC_TIME = "en_GB.UTF-8";
+ };
+
+ console.keyMap = "uk";
+
+ services.printing.enable = true;
+
+ sound.enable = true;
+ hardware.pulseaudio.enable = false;
+ security.rtkit.enable = true;
+ services.pipewire = {
+ enable = true;
+ alsa.enable = true;
+ alsa.support32Bit = true;
+ pulse.enable = true;
+ };
+
+ modules.desktop.gnome.enable = true;
+}
\ No newline at end of file
diff --git a/install b/install
deleted file mode 100755
index 75d02f6..0000000
--- a/install
+++ /dev/null
@@ -1,110 +0,0 @@
-#!/bin/sh -e
-
-repo_dir=$(readlink -f $(dirname "$0"))
-
-link() {
- [ -L "$HOME/.config" ] && return 0
-
- for file in ".profile" ".zprofile" ".config"; do
- ln -sf "$repo_dir/$file" "$HOME/$file"
- done
-
- source ~/.profile
-}
-
-install() {
- sudo pacman -S --needed \
- base-devel \
- bind \
- bmon \
- cgdb \
- expect \
- fd \
- ffmpeg \
- firefox \
- fzf \
- git \
- gdb \
- grim \
- gtk-layer-shell \
- iotop \
- imagemagick \
- isync \
- kitty \
- lynx \
- mpd \
- mpv \
- msmtp \
- ncmpcpp \
- neomutt \
- neovim \
- newsboat \
- ninja \
- nnn \
- notmuch \
- noto-fonts \
- nodejs \
- npm \
- ntfs-3g \
- otf-font-awesome \
- pass \
- pass-otp \
- playerctl \
- powertop \
- python \
- python-pip \
- python-neovim \
- qt5-wayland \
- qt6-wayland \
- ripgrep \
- rsync \
- slurp \
- sway \
- tcpdump \
- tokei \
- transmission-cli \
- tree \
- ttf-ubuntu-font-family \
- yt-dlp \
- waybar \
- wf-recorder \
- wl-clipboard \
- zathura \
- zathura-pdf-mupdf \
- zsh \
- zsh-autosuggestions \
- zsh-history-substring-search
-
- [ -d "/usr/share/zsh/plugins/fast-syntax-highlighting" ] || sudo git clone \
- https://github.com/zdharma-continuum/fast-syntax-highlighting \
- /usr/share/zsh/plugins/fast-syntax-highlighting
-
- [ -d "/usr/share/zsh/plugins/zsh-vim-mode" ] || sudo git clone \
- https://github.com/softmoth/zsh-vim-mode \
- /usr/share/zsh/plugins/zsh-vim-mode
-
- [ -x "/usr/bin/pam_exec-ssh" ] || {
- sudo install -m755 \
- "$repo_dir/.config/ssh-agent/pam_exec-ssh" \
- /usr/bin/pam_exec-ssh
- mkdir ~/.ssh/unlock.d
- ln -s ~/.ssh/id_ed25519 ~/.ssh/unlock.d/id_ed25519
- sudo sed -i '$a auth optional pam_exec.so expose_authtok /usr/bin/pam_exec-ssh' \
- /etc/pam.d/system-local-login
- }
-
- [ -x "/usr/bin/sirula" ] || {
- tmp_dir="$(mktemp -d)" && pushd "$tmp_dir" && {
- curl -sSfO "https://jordanholt.xyz/sirula"
- sudo install -m755 sirula /usr/bin/
- popd
- rm -rf $tmp_dir
- }
- }
-}
-
-configure() {
- loginctl enable-linger $UID
-}
-
-install && link && configure
diff --git a/lib/attrs.nix b/lib/attrs.nix
new file mode 100644
index 0000000..b83e826
--- /dev/null
+++ b/lib/attrs.nix
@@ -0,0 +1,26 @@
+{ lib, ... }:
+
+with builtins;
+with lib;
+rec {
+ # attrsToList
+ attrsToList = attrs:
+ mapAttrsToList (name: value: { inherit name value; }) attrs;
+
+ # mapFilterAttrs ::
+ # (name -> value -> bool)
+ # (name -> value -> { name = any; value = any; })
+ # attrs
+ mapFilterAttrs = pred: f: attrs: filterAttrs pred (mapAttrs' f attrs);
+
+ # Generate an attribute set by mapping a function over a list of values.
+ genAttrs' = values: f: listToAttrs (map f values);
+
+ # anyAttrs :: (name -> value -> bool) attrs
+ anyAttrs = pred: attrs:
+ any (attr: pred attr.name attr.value) (attrsToList attrs);
+
+ # countAttrs :: (name -> value -> bool) attrs
+ countAttrs = pred: attrs:
+ count (attr: pred attr.name attr.value) (attrsToList attrs);
+}
\ No newline at end of file
diff --git a/lib/default.nix b/lib/default.nix
new file mode 100644
index 0000000..158a538
--- /dev/null
+++ b/lib/default.nix
@@ -0,0 +1,19 @@
+
+{ inputs, lib, pkgs, ... }:
+
+let
+ inherit (lib) makeExtensible attrValues foldr;
+ inherit (modules) mapModules;
+
+ modules = import ./modules.nix {
+ inherit lib;
+ self.attrs = import ./attrs.nix { inherit lib; self = {}; };
+ };
+
+ mylib = makeExtensible (self:
+ with self; mapModules ./.
+ (file: import file { inherit self lib pkgs inputs; }));
+in
+mylib.extend
+ (self: super:
+ foldr (a: b: a // b) {} (attrValues super))
diff --git a/lib/modules.nix b/lib/modules.nix
new file mode 100644
index 0000000..2124f6c
--- /dev/null
+++ b/lib/modules.nix
@@ -0,0 +1,53 @@
+{ self, lib, ... }:
+
+let
+ inherit (builtins) attrValues readDir pathExists concatLists;
+ inherit (lib) id mapAttrsToList filterAttrs hasPrefix hasSuffix nameValuePair removeSuffix;
+ inherit (self.attrs) mapFilterAttrs;
+in
+rec {
+ mapModules = dir: fn:
+ mapFilterAttrs
+ (n: v:
+ v != null &&
+ !(hasPrefix "_" n))
+ (n: v:
+ let path = "${toString dir}/${n}"; in
+ if v == "directory" && pathExists "${path}/default.nix"
+ then nameValuePair n (fn path)
+ else if v == "regular" &&
+ n != "default.nix" &&
+ hasSuffix ".nix" n
+ then nameValuePair (removeSuffix ".nix" n) (fn path)
+ else nameValuePair "" null)
+ (readDir dir);
+
+ mapModules' = dir: fn:
+ attrValues (mapModules dir fn);
+
+ mapModulesRec = dir: fn:
+ mapFilterAttrs
+ (n: v:
+ v != null &&
+ !(hasPrefix "_" n))
+ (n: v:
+ let path = "${toString dir}/${n}"; in
+ if v == "directory"
+ then nameValuePair n (mapModulesRec path fn)
+ else if v == "regular" && n != "default.nix" && hasSuffix ".nix" n
+ then nameValuePair (removeSuffix ".nix" n) (fn path)
+ else nameValuePair "" null)
+ (readDir dir);
+
+ mapModulesRec' = dir: fn:
+ let
+ dirs =
+ mapAttrsToList
+ (k: _: "${dir}/${k}")
+ (filterAttrs
+ (n: v: v == "directory" && !(hasPrefix "_" n))
+ (readDir dir));
+ files = attrValues (mapModules dir id);
+ paths = files ++ concatLists (map (d: mapModulesRec' d id) dirs);
+ in map fn paths;
+}
\ No newline at end of file
diff --git a/lib/nixos.nix b/lib/nixos.nix
new file mode 100644
index 0000000..4595af7
--- /dev/null
+++ b/lib/nixos.nix
@@ -0,0 +1,25 @@
+{ inputs, lib, pkgs, ... }:
+
+with lib;
+with lib.my;
+let sys = "x86_64-linux";
+in {
+ mkHost = path: attrs @ { system ? sys, ... }:
+ nixosSystem {
+ inherit system;
+ specialArgs = { inherit lib inputs system; };
+ modules = [
+ {
+ nixpkgs.pkgs = pkgs;
+ networking.hostName = mkDefault (removeSuffix ".nix" (baseNameOf path));
+ }
+ (filterAttrs (n: v: !elem n [ "system" ]) attrs)
+ ../. # /default.nix
+ (import path)
+ ];
+ };
+
+ mapHosts = dir: attrs @ { system ? system, ... }:
+ mapModules dir
+ (hostPath: mkHost hostPath attrs);
+}
diff --git a/lib/options.nix b/lib/options.nix
new file mode 100644
index 0000000..da61a5a
--- /dev/null
+++ b/lib/options.nix
@@ -0,0 +1,35 @@
+{ lib, ... }:
+
+let
+ inherit (lib) mkOption types;
+in
+rec {
+ mkOpt = type: default:
+ mkOption { inherit type default; };
+
+ mkOpt' = type: default: description:
+ mkOption { inherit type default description; };
+
+ mkBoolOpt = default: mkOption {
+ inherit default;
+ type = types.bool;
+ example = true;
+ };
+
+ mkStringOpt = default: mkOption {
+ inherit default;
+ type = types.lines;
+ example = "";
+ };
+
+ mkListOfStringOpt = default: mkOption {
+ inherit default;
+ type = types.listOf types.lines;
+ example = [ "a" "b" "c" ];
+ };
+
+ mkPath = path:
+ if path != null
+ then toString path
+ else "";
+}
\ No newline at end of file
diff --git a/modules/default.nix b/modules/default.nix
new file mode 100644
index 0000000..5613449
--- /dev/null
+++ b/modules/default.nix
@@ -0,0 +1,15 @@
+{
+ imports = [
+ ./options.nix
+ ./desktop/firefox.nix
+ ./desktop/gnome.nix
+ ./editors/neovim.nix
+ ./editors/vscode.nix
+ ./security/gpg.nix
+ ./security/pass.nix
+ ./shell/fzf.nix
+ ./shell/git.nix
+ ./shell/nnn.nix
+ ./shell/zsh.nix
+ ];
+}
\ No newline at end of file
diff --git a/modules/desktop/firefox.nix b/modules/desktop/firefox.nix
new file mode 100644
index 0000000..b79e909
--- /dev/null
+++ b/modules/desktop/firefox.nix
@@ -0,0 +1,16 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+with lib.my;
+let cfg = config.modules.desktop.firefox;
+in {
+ options.modules.desktop.firefox = {
+ enable = mkBoolOpt false;
+ };
+
+ config = mkIf cfg.enable {
+ home.programs.firefox = {
+ enable = true;
+ };
+ };
+}
\ No newline at end of file
diff --git a/modules/desktop/gnome.nix b/modules/desktop/gnome.nix
new file mode 100644
index 0000000..7d20962
--- /dev/null
+++ b/modules/desktop/gnome.nix
@@ -0,0 +1,37 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+with lib.my;
+let cfg = config.modules.desktop.gnome;
+in {
+ options.modules.desktop.gnome = {
+ enable = mkBoolOpt false;
+ };
+
+ config = mkIf cfg.enable {
+ services.xserver = {
+ enable = true;
+ displayManager.gdm.enable = true;
+ desktopManager.gnome.enable = true;
+ };
+
+ fonts.fonts = with pkgs; [
+ noto-fonts
+ ubuntu_font_family
+ ];
+
+ environment.systemPackages = with pkgs; [
+ bind
+ bmon
+ fd
+ ffmpeg
+ iotop
+ ripgrep
+ rsync
+ tcpdump
+ tokei
+ tree
+ wl-clipboard
+ ];
+ };
+}
\ No newline at end of file
diff --git a/modules/editors/neovim.nix b/modules/editors/neovim.nix
new file mode 100644
index 0000000..15b761a
--- /dev/null
+++ b/modules/editors/neovim.nix
@@ -0,0 +1,18 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+with lib.my;
+let cfg = config.modules.editors.neovim;
+in {
+ options.modules.editors.neovim = {
+ enable = mkBoolOpt false;
+ };
+
+ config = mkIf cfg.enable {
+ home.programs.neovim = {
+ enable = true;
+ vimAlias = true;
+ vimdiffAlias = true;
+ };
+ };
+}
\ No newline at end of file
diff --git a/modules/editors/vscode.nix b/modules/editors/vscode.nix
new file mode 100644
index 0000000..69c4b98
--- /dev/null
+++ b/modules/editors/vscode.nix
@@ -0,0 +1,16 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+with lib.my;
+let cfg = config.modules.editors.vscode;
+in {
+ options.modules.editors.vscode = {
+ enable = mkBoolOpt false;
+ };
+
+ config = mkIf cfg.enable {
+ home.programs.vscode = {
+ enable = true;
+ };
+ };
+}
\ No newline at end of file
diff --git a/modules/options.nix b/modules/options.nix
new file mode 100644
index 0000000..8c61e15
--- /dev/null
+++ b/modules/options.nix
@@ -0,0 +1,69 @@
+{ config, options, lib, home-manager, ... }:
+
+with lib;
+with lib.my;
+{
+ options = with types; {
+ user = mkOpt attrs { };
+
+ home = {
+ configFile = mkOpt' attrs { } "Files to place in $XDG_CONFIG_HOME";
+ dataFile = mkOpt' attrs { } "Files to place in $XDG_DATA_HOME";
+ file = mkOpt' attrs { } "Files to place directly in $HOME";
+ packages = mkOpt' attrs { } "User-level installed packages";
+ programs = mkOpt' attrs { } "Programs managed directly from home-manager";
+ services = mkOpt' attrs { } "Services managed directly from home-manager";
+ };
+
+ env = mkOption {
+ type = attrsOf (oneOf [ str path (listOf (either str path)) ]);
+ apply = mapAttrs (n: v:
+ if isList v then
+ concatMapStringsSep ":" (x: toString x) v
+ else
+ (toString v));
+ default = { };
+ description = "";
+ };
+ };
+
+ config = {
+ user =
+ let user = builtins.getEnv "USER";
+ name = if elem user [ "" "root" ] then "jordan" else user;
+ in {
+ inherit name;
+ isNormalUser = true;
+ extraGroups = [ "networkmanager" "wheel" ];
+ description = "Jordan Holt";
+ useDefaultShell = true;
+ home = "/home/${name}";
+ group = "users";
+ uid = 1000;
+ };
+
+ home-manager = {
+ useGlobalPkgs = true;
+ useUserPackages = true;
+
+ users.${config.user.name} = {
+ home = {
+ file = mkAliasDefinitions options.home.file;
+ stateVersion = config.system.stateVersion;
+ };
+ home.packages = mkAliasDefinitions options.home.packages;
+ programs = mkAliasDefinitions options.home.programs;
+ services = mkAliasDefinitions options.home.services;
+ xdg = {
+ enable = true;
+ configFile = mkAliasDefinitions options.home.configFile;
+ dataFile = mkAliasDefinitions options.home.dataFile;
+ };
+ };
+ };
+
+ users.users.${config.user.name} = mkAliasDefinitions options.user;
+
+ nixpkgs.config.allowUnfree = true;
+ };
+}
\ No newline at end of file
diff --git a/modules/security/gpg.nix b/modules/security/gpg.nix
new file mode 100644
index 0000000..deb4d6c
--- /dev/null
+++ b/modules/security/gpg.nix
@@ -0,0 +1,21 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+with lib.my;
+let cfg = config.modules.security.gpg;
+in {
+ options.modules.security.gpg = {
+ enable = mkBoolOpt false;
+ };
+
+ config = mkIf cfg.enable {
+ home.programs.gpg = {
+ enable = true;
+ };
+
+ home.services.gpg-agent = {
+ enable = true;
+ enableSshSupport = true;
+ };
+ };
+}
\ No newline at end of file
diff --git a/modules/security/pass.nix b/modules/security/pass.nix
new file mode 100644
index 0000000..511e6d8
--- /dev/null
+++ b/modules/security/pass.nix
@@ -0,0 +1,17 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+with lib.my;
+let cfg = config.modules.security.pass;
+in {
+ options.modules.security.pass = {
+ enable = mkBoolOpt false;
+ };
+
+ config = mkIf cfg.enable {
+ home.programs.password-store = {
+ enable = true;
+ package = pkgs.pass.withExtensions (exts: [ exts.pass-otp ]);
+ };
+ };
+}
\ No newline at end of file
diff --git a/modules/shell/fzf.nix b/modules/shell/fzf.nix
new file mode 100644
index 0000000..e821166
--- /dev/null
+++ b/modules/shell/fzf.nix
@@ -0,0 +1,21 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+with lib.my;
+let cfg = config.modules.shell.fzf;
+in {
+ options.modules.shell.fzf = {
+ enable = mkBoolOpt false;
+ };
+
+ config = mkIf cfg.enable {
+ home.packages = with pkgs; [
+ bind
+ ];
+ home.programs.fzf = {
+ enable = true;
+ enableZshIntegration = true;
+ defaultCommand = "fd --type f --hidden --follow --exclude .git";
+ };
+ };
+}
\ No newline at end of file
diff --git a/modules/shell/git.nix b/modules/shell/git.nix
new file mode 100644
index 0000000..ac1c883
--- /dev/null
+++ b/modules/shell/git.nix
@@ -0,0 +1,34 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+with lib.my;
+let cfg = config.modules.shell.git;
+in {
+ options.modules.shell.git = {
+ enable = mkBoolOpt false;
+ };
+
+ config = mkIf cfg.enable {
+ home.programs.git = {
+ enable = true;
+ aliases = {
+ amend = "commit --amend";
+ lg = "log --color --graph --abbrev-commit --";
+ ls = "ls-files";
+ unadd = "reset HEAD";
+ undo-commit = "reset --soft \"HEAD^\"";
+ };
+ userEmail = "jordan@vimium.com";
+ userName = "Jordan Holt";
+ signing = {
+ key = "B8CFFF61F1CCF520";
+ signByDefault = true;
+ };
+ extraConfig = {
+ rebase.autosquash = true;
+ push.default = "current";
+ pull.rebase = true;
+ };
+ };
+ };
+}
\ No newline at end of file
diff --git a/modules/shell/nnn.nix b/modules/shell/nnn.nix
new file mode 100644
index 0000000..3268c3c
--- /dev/null
+++ b/modules/shell/nnn.nix
@@ -0,0 +1,16 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+with lib.my;
+let cfg = config.modules.shell.nnn;
+in {
+ options.modules.shell.nnn = {
+ enable = mkBoolOpt false;
+ };
+
+ config = mkIf cfg.enable {
+ home.programs.nnn = {
+ enable = true;
+ };
+ };
+}
\ No newline at end of file
diff --git a/modules/shell/zsh.nix b/modules/shell/zsh.nix
new file mode 100644
index 0000000..0d60e10
--- /dev/null
+++ b/modules/shell/zsh.nix
@@ -0,0 +1,35 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+with lib.my;
+let cfg = config.modules.shell.zsh;
+in {
+ options.modules.shell.zsh = {
+ enable = mkBoolOpt false;
+ };
+
+ config = mkIf cfg.enable {
+ home.packages = with pkgs; [
+ zsh-autosuggestions
+ zsh-fast-syntax-highlighting
+ zsh-history-substring-search
+ ];
+
+ home.programs.zsh = {
+ enable = true;
+ enableCompletion = true;
+ shellAliases = {
+ cp = "cp -iv";
+ mv = "mv -iv";
+ rm = "rm -v";
+ mkdir = "mkdir -v";
+ ls = "ls -h --color=auto --group-directories-first";
+ e = "nvim";
+ f = "nnn";
+ g = "git";
+ n = "nnn";
+ v = "nvim";
+ };
+ };
+ };
+}
\ No newline at end of file