diff --git a/config/neovim/coc-settings.nix b/config/neovim/coc-settings.nix new file mode 100644 index 0000000..0bd9218 --- /dev/null +++ b/config/neovim/coc-settings.nix @@ -0,0 +1,30 @@ +{ + languageserver = { + dhall = { + command = "dhall-lsp-server"; + filetypes = [ "dhall" ]; + }; + + haskell = { + command = "haskell-language-server-wrapper"; + args = [ "--lsp" ]; + rootPatterns = [ + "stack.yaml" + "hie.yaml" + ".hie-bios" + "BUILD.bazel" + ".cabal" + "cabal.project" + "package.yaml" + ]; + filetypes = [ "hs" "lhs" "haskell" ]; + }; + + nix = { + command = "rnix-lsp"; + filetypes = [ "nix" ]; + }; + }; + + "yank.highlight.duration" = 700; +} diff --git a/config/neovim/coc.vim b/config/neovim/coc.vim new file mode 100644 index 0000000..9c747ae --- /dev/null +++ b/config/neovim/coc.vim @@ -0,0 +1,96 @@ +" ------------------- COC config ----------------------- + +set updatetime=300 + +set shortmess+=c + +set signcolumn=yes + +set nobackup +set nowritebackup + +set cmdheight=2 + +" Use for trigger completion. +inoremap coc#refresh() + +" Use for confirm completion, `u` means break undo chain at current position. +" Coc only does snippet and additional edit on confirm. +inoremap pumvisible() ? "\" : "\u\" + +" Use `[c` and `]c` for navigate diagnostics +nmap [c (coc-diagnostic-prev) +nmap ]c (coc-diagnostic-next) + +" Remap keys for gotos +nmap gd (coc-definition) +nmap gy (coc-type-definition) +nmap gi (coc-implementation) +nmap gr (coc-references) + +" Remap for do codeAction of current line +nmap ac (coc-codeaction) + +" Remap for do action format +"nmap F (coc-action-format) "does not work +nnoremap F :call CocAction('format') + +" Temporary command to run brittany in Haskell projects (ghcide does not support it yet) +nnoremap af :r !brittany --write-mode=inplace %:p + +" Temporary command to run hlint in Haskell projects (ghcide does not support it yet) +nnoremap al :AsyncRun hlint %:p + +" Show signature help +autocmd User CocJumpPlaceholder call CocActionAsync('showSignatureHelp') + +" Use K for show documentation in preview window +nnoremap K :call show_documentation() + +function! s:show_documentation() + if &filetype == 'vim' + execute 'h '.expand('') + else + call CocAction('doHover') + endif +endfunction + +" Highlight symbol under cursor on CursorHold +" autocmd CursorHold * silent call CocActionAsync('highlight') + +" Remap for rename current word +nmap rn (coc-rename) + +" Show all diagnostics +nnoremap a :CocList diagnostics +" Find symbol of current document +nnoremap o :CocList outline +" Search workspace symbols +nnoremap s :CocList -I symbols +" Do default action for next item. +nnoremap j :CocNext +" Do default action for previous item. +nnoremap k :CocPrev +" Resume latest coc list +nnoremap p :CocListResume + +nnoremap :call CocRequest('metals', 'workspace/executeCommand', { 'command': 'build-import' }) +"nnoremap :ccl + +" COC Snippets + +" Use for trigger snippet expand. +imap (coc-snippets-expand) + +" Use for select text for visual placeholder of snippet. +vmap (coc-snippets-select) + +" Use for jump to next placeholder, it's default of coc.nvim +let g:coc_snippet_next = '' + +" Use for jump to previous placeholder, it's default of coc.nvim +let g:coc_snippet_prev = '' + +" Use for both expand and jump (make expand higher priority.) +imap (coc-snippets-expand-jump) + diff --git a/config/neovim/config.vim b/config/neovim/config.vim new file mode 100644 index 0000000..22fa5b1 --- /dev/null +++ b/config/neovim/config.vim @@ -0,0 +1,38 @@ +filetype off + +let mapleader=',' +set shell=/run/current-system/sw/bin/fish + +set viewoptions=folds,options,cursor,unix,slash +set encoding=utf-8 + +set termguicolors + +syntax on +set backspace=2 +set laststatus=2 +set noshowmode + +set expandtab +set tabstop=4 +set softtabstop=4 +set shiftwidth=4 + +set number +set numberwidth=1 +set cmdheight=3 +set textwidth=0 +set linebreak +set showmatch +set matchtime=0 +set clipboard=unnamedplus +set cursorline + +set incsearch +set ignorecase +set smartcase + +nnoremap Q +nnoremap gQ + +:tnoremap diff --git a/config/neovim/plugins.vim b/config/neovim/plugins.vim new file mode 100644 index 0000000..c147677 --- /dev/null +++ b/config/neovim/plugins.vim @@ -0,0 +1,12 @@ +" let g:hoogle_search_count = 20 +" au BufNewFile,BufRead *.hs map :Hoogle +" au BufNewFile,BufRead *.hs map :HoogleClose + +nnoremap n :NERDTreeFocus +map f :NERDTreeToggle +map s :NERDTreeFind + +" let g:hoogle_fzf_cache_file = '~/.cache/fzf-hoogle/cache.json' +" nnoremap h :Hoogle + +let g:vimtex_compiler_method = 'tectonic' diff --git a/default.nix b/default.nix new file mode 100755 index 0000000..e182e2d --- /dev/null +++ b/default.nix @@ -0,0 +1,39 @@ +{ config, inputs, lib, pkgs, ... }: + +let + inherit (lib) _; +in { + imports = + [ inputs.home-manager.nixosModules.home-manager ] + ++ _.mapModulesRec' ./modules import; + + # ‹nix flake check› bypasses, can be changed in the actual hosts + # config, useful for testing + fileSystems."/".device = lib.mkDefault "/dev/disk/by-label/nixos"; + boot.loader.systemd-boot.enable = true; + boot.loader.efi.canTouchEfiVariables = true; + boot.loader.systemd-boot.configurationLimit = 10; + + nix = let + registry = lib.mapAttrs (_: v: { flake = v; }) (_.filterSelf inputs); + in { + package = pkgs.nixFlakes; + autoOptimiseStore = true; + extraOptions = "experimental-features = nix-command flakes"; + binaryCaches = [ + "https://nix-community.cachix.org" + ]; + binaryCachePublicKeys = [ + "nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs=" + ]; + registry = registry // { dotfiles.flake = inputs.self; }; + }; + + environment.systemPackages = with pkgs; [ + curl git wget neovim + ]; + + i18n.defaultLocale = "en_US.UTF-8"; + + system.stateVersion = lib.mkDefault "21.05"; +} diff --git a/flake.lock b/flake.lock new file mode 100755 index 0000000..f6fd0af --- /dev/null +++ b/flake.lock @@ -0,0 +1,238 @@ +{ + "nodes": { + "agenix": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1641576265, + "narHash": "sha256-G4W39k5hdu2kS13pi/RhyTOySAo7rmrs7yMUZRH0OZI=", + "owner": "ryantm", + "repo": "agenix", + "rev": "08b9c96878b2f9974fc8bde048273265ad632357", + "type": "github" + }, + "original": { + "owner": "ryantm", + "repo": "agenix", + "type": "github" + } + }, + "flake-compat": { + "flake": false, + "locked": { + "lastModified": 1641205782, + "narHash": "sha256-4jY7RCWUoZ9cKD8co0/4tFARpWB+57+r1bLLvXNJliY=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "b7547d3eed6f32d06102ead8991ec52ab0a4f1a7", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, + "flake-utils": { + "locked": { + "lastModified": 1638122382, + "narHash": "sha256-sQzZzAbvKEqN9s0bzWuYmRaA03v40gaJ4+iL1LXjaeI=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "74f7e4319258e287b0f9cb95426c9853b282730b", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "home-manager": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1641459437, + "narHash": "sha256-z0IOcc6LLbVhyri/aTyWzRqJs3p1pBK9idOiMwCWiqs=", + "owner": "nix-community", + "repo": "home-manager", + "rev": "c751aeb19e84a0a777f36fd5ea73482a066bb406", + "type": "github" + }, + "original": { + "owner": "nix-community", + "ref": "master", + "repo": "home-manager", + "type": "github" + } + }, + "libnbtplusplus": { + "flake": false, + "locked": { + "lastModified": 1591558203, + "narHash": "sha256-QgvNvaoFflCXEPCCFBCeZvYTpuiwScBG7EosUgFwFNQ=", + "owner": "multimc", + "repo": "libnbtplusplus", + "rev": "dc72a20b7efd304d12af2025223fad07b4b78464", + "type": "github" + }, + "original": { + "owner": "multimc", + "repo": "libnbtplusplus", + "type": "github" + } + }, + "meson": { + "flake": false, + "locked": { + "lastModified": 1640155612, + "narHash": "sha256-XrEIlf0W8mKEa97Uyc0w/187KBGEZOD+dJFNsn3UeNg=", + "owner": "mesonbuild", + "repo": "meson", + "rev": "06aad5233e6bec97bfe21ae79c85aa7171089d3b", + "type": "github" + }, + "original": { + "owner": "mesonbuild", + "ref": "0.60", + "repo": "meson", + "type": "github" + } + }, + "multimc": { + "inputs": { + "flake-compat": "flake-compat", + "flake-utils": "flake-utils", + "libnbtplusplus": "libnbtplusplus", + "nixpkgs": "nixpkgs", + "quazip": "quazip" + }, + "locked": { + "lastModified": 1641769038, + "narHash": "sha256-IGk8n00m7riuYLnR+3Nbo70YHJBOQv+nakynN/gtoY0=", + "owner": "PolyMC", + "repo": "PolyMC", + "rev": "3fa6e2243047005505a3de6f133feaa2f2eeb10a", + "type": "github" + }, + "original": { + "owner": "PolyMC", + "repo": "PolyMC", + "type": "github" + } + }, + "nixos-hardware": { + "locked": { + "lastModified": 1639986101, + "narHash": "sha256-Ow0+pkY7qMw6lMAvR1mEdUT9svJnrkbaRoqp4bkMTpg=", + "owner": "nixos", + "repo": "nixos-hardware", + "rev": "3f92db38374b2977aea8daf4c4fe2fa0eddbd60c", + "type": "github" + }, + "original": { + "owner": "nixos", + "repo": "nixos-hardware", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1641528457, + "narHash": "sha256-FyU9E63n1W7Ql4pMnhW2/rO9OftWZ37pLppn/c1aisY=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "ff377a78794d412a35245e05428c8f95fef3951f", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-unstable": { + "locked": { + "lastModified": 1640139330, + "narHash": "sha256-Nkp3wUOGwtoQ7EH28RLVJ7EqB/e0TU7VcsM7GLy+SdY=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "81cef6b70fb5d5cdba5a0fef3f714c2dadaf0d6d", + "type": "github" + }, + "original": { + "id": "nixpkgs", + "ref": "nixos-unstable", + "type": "indirect" + } + }, + "nixpkgs_2": { + "locked": { + "lastModified": 1641528457, + "narHash": "sha256-FyU9E63n1W7Ql4pMnhW2/rO9OftWZ37pLppn/c1aisY=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "ff377a78794d412a35245e05428c8f95fef3951f", + "type": "github" + }, + "original": { + "id": "nixpkgs", + "ref": "nixos-unstable", + "type": "indirect" + } + }, + "quazip": { + "flake": false, + "locked": { + "lastModified": 1633895098, + "narHash": "sha256-+Of0M2IAoTf1CyC0teCpsyurv6xfqiBo84V49dSeNTA=", + "owner": "multimc", + "repo": "quazip", + "rev": "b1a72ac0bb5a732bf887a535ab75c6f9bedb6b6b", + "type": "github" + }, + "original": { + "owner": "multimc", + "repo": "quazip", + "type": "github" + } + }, + "root": { + "inputs": { + "agenix": "agenix", + "home-manager": "home-manager", + "meson": "meson", + "multimc": "multimc", + "nixos-hardware": "nixos-hardware", + "nixpkgs": "nixpkgs_2", + "nixpkgs-unstable": "nixpkgs-unstable", + "sway-borders": "sway-borders" + } + }, + "sway-borders": { + "flake": false, + "locked": { + "lastModified": 1640037473, + "narHash": "sha256-gCdnim7excF11GEoni5YbIGTWSIx+wjHc8NO8lVNFts=", + "owner": "fluix-dev", + "repo": "sway-borders", + "rev": "5f4162f449b19f6d198b365fc6d3dd0febc065e2", + "type": "github" + }, + "original": { + "owner": "fluix-dev", + "repo": "sway-borders", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100755 index 0000000..b2efa8d --- /dev/null +++ b/flake.nix @@ -0,0 +1,73 @@ +{ + description = "Frosted Flakes"; + + inputs = { + # NixOS unstable + nixpkgs.url = "nixpkgs/nixos-unstable"; +# nixpkgs.url = "nixpkgs/nixos-21.05"; + nixpkgs-unstable.url = "nixpkgs/nixos-unstable"; + + # home-manager + home-manager.url = "github:nix-community/home-manager/master"; +# home-manager.url = "github:nix-community/home-manager/release-21.05"; + home-manager.inputs.nixpkgs.follows = "nixpkgs"; + + # agenix - age-encrypted secrets + agenix.url = "github:ryantm/agenix"; + agenix.inputs.nixpkgs.follows = "nixpkgs"; + + # nixos-hardware + nixos-hardware.url = "github:nixos/nixos-hardware"; + nixos-hardware.inputs.nixpkgs.follows = "nixpkgs"; + +/* + # fzf-hoogle + fzf-hoogle-vim.url = "github:monkoose/fzf-hoogle.vim"; + fzf-hoogle-vim.flake = false; + + # asyncrun-vim + asyncrun-vim.url = "github:skywind3000/asyncrun.vim"; + asyncrun-vim.flake = false; +*/ + meson.url = "github:mesonbuild/meson/0.60"; + meson.flake = false; + + sway-borders.url = "github:fluix-dev/sway-borders"; + sway-borders.flake = false; + +# blender-30.url = "github:blender/blender/blender-v3.0-release"; +# blender-30.flake = false; + + multimc.url = "github:PolyMC/PolyMC"; + }; + + outputs = inputs @ { self, nixpkgs, nixpkgs-unstable, ... }: + let + system = "x86_64-linux"; + + lib = import ./lib { inherit pkgs inputs; lib = nixpkgs.lib; }; + inherit (lib._) mapModules mapModulesRec mkHost; + + mkPkgs = pkgs: overlays: import pkgs { + inherit system; + config.allowUnfree = true; + overlays = overlays ++ (lib.attrValues self.overlays); + }; + + pkgs = mkPkgs nixpkgs [ self.overlay ]; + in { + packages."${system}" = mapModules ./packages (p: pkgs.callPackage p {}); + overlay = final: prev: { + _ = self.packages."${system}"; +# meson = inputs.meson; +# sway-unwrapped = inputs.sway-borders; +# blender = inputs.blender-30; + unstable = mkPkgs nixpkgs-unstable []; + }; + overlays = mapModules ./overlays import ++ [ inputs.polymc.overlay.${system} ]; + nixosModules = mapModulesRec ./modules import; + nixosConfigurations = mapModules ./hosts (mkHost system); + devShell."${system}" = + import ./shell.nix { inherit pkgs; }; + }; +} diff --git a/hosts/firepit/default.nix b/hosts/firepit/default.nix new file mode 100644 index 0000000..8d154e5 --- /dev/null +++ b/hosts/firepit/default.nix @@ -0,0 +1,63 @@ +{ pkgs, inputs, lib, ... }: + +{ + imports = [ + ./hardware-configuration.nix + ]; + + user = { + packages = with pkgs; [ + curl + ]; + }; + + defaultUsers = { + aether = { + packages = [ ]; + shell = "zsh"; + extraGroups = [ "wheel" ]; + }; + oatmealine = { + packages = [ ]; + shell = "zsh"; + extraGroups = [ "wheel" ]; + }; + }; + + keyboard = { + locale = "en_US.UTF-8"; + variant = "qwerty"; + }; + + modules = { +# theme.active = "still"; + shell.zsh.enable = true; + security = { + isLocalMachine = false; + }; + desktop = { + editors = { + neovim.enable = true; + }; + }; + dev = { + }; + services = { + ssh.enable = true; + postgres.enable = true; + gitea = { + enable = true; + site = "git.oat.zone"; + }; + }; + }; + + time.timeZone = "Europe/Frankfurt"; + + programs.ssh.startAgent = true; + services.openssh.startWhenNeeded = true; + + networking = { + hostName = "firepit"; + }; +} diff --git a/hosts/firepit/secrets/secrets.nix b/hosts/firepit/secrets/secrets.nix new file mode 100644 index 0000000..814c36d --- /dev/null +++ b/hosts/firepit/secrets/secrets.nix @@ -0,0 +1,11 @@ +let + userAether = "<...>"; + userOatmealine = "<...>"; +in { + "aether" = { + "userAether.age".publicKeys = [ userAether ]; + }; + "oatmealine" = { + "userOatmealine.age".publicKeys = [ userOatmealine ]; + }; +} diff --git a/hosts/subsurface/default.nix b/hosts/subsurface/default.nix new file mode 100644 index 0000000..35d98c3 --- /dev/null +++ b/hosts/subsurface/default.nix @@ -0,0 +1,98 @@ +{ pkgs, inputs, lib, ... }: + +{ + imports = [ + ./hardware-configuration.nix + ]; + + user = { + packages = with pkgs; [ + curl + dolphin + discord + firefox-wayland + wl-clipboard + inkscape + blender + ]; + }; + + defaultUsers = { + aether = { + packages = [ ]; + uid = 1024; + isNormalUser = true; + shell = "zsh"; + extraGroups = [ "wheel" ]; + }; + }; + + keyboard = { + locale = "en_US.UTF-8"; + variant = "qwerty"; + }; + + modules = { +# theme.active = "still"; + shell.zsh.enable = true; + security = { + isLocalMachine = true; + }; + desktop = { + sway = { + enable = true; + term = "alacritty"; + }; + apps = { + mpc.enable = true; + alacritty.enable = true; + obs.enable = true; + firefox.enable = true; + }; + editors = { + neovim.enable = true; + codium.enable = true; + }; + }; + dev = { + llvm.enable = true; + haskell.enable = true; + c.enable = true; + }; + services = { + ssh.enable = true; + mpd = { + enable = true; + # TODO: Make this more dynamic? + musicDir = "/home/aether/Music"; + }; + }; + }; + + # Doxxing live stream + time.timeZone = "Europe/Dublin"; + + programs.ssh.startAgent = true; + services.openssh.startWhenNeeded = true; + + # Fuck sudo all my homies hate sudo + security.sudo.enable = false; + security.doas = { + enable = true; + extraRules = [ + { users = [ "aether" ]; keepEnv = true; } + ]; + }; + + # Weird hack to get GDM to not explode on startup + # TODO: This might not be needed anymore + systemd.services."getty@tty1".enable = false; + systemd.services."autovt@tty1".enable = false; + + networking = { + hostName = "subsurface"; + networkmanager.enable = true; + useDHCP = false; + interfaces.wlp1s0.useDHCP = true; + }; +} diff --git a/hosts/subsurface/hardware-configuration.nix b/hosts/subsurface/hardware-configuration.nix new file mode 100644 index 0000000..98b6084 --- /dev/null +++ b/hosts/subsurface/hardware-configuration.nix @@ -0,0 +1,78 @@ +# 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, inputs, modulesPath, ... }: + +{ + imports = [ + (modulesPath + "/installer/scan/not-detected.nix") +# inputs.nixos-hardware.nixosModules.microsoft-surface + ]; + + # Kernel Modules + boot = { + initrd.availableKernelModules = [ "xhci_pci" "nvme" "usbhid" "usb_storage" "sd_mod" ]; + initrd.kernelModules = [ ]; +# kernelPackages = pkgs.linuxPackages_zen; + extraModulePackages = with config.boot.kernelPackages; [ v4l2loopback ]; + kernelModules = [ "kvm-intel" "v4l2loopback" ]; + loader = { + systemd-boot = { + enable = true; + configurationLimit = 10; + }; + efi.canTouchEfiVariables = true; + }; + }; + + # Modules + modules.hardware = { + audio = { + enable = true; + enableExtraCompat = true; + }; + graphics.enable = true; + fs = { + enable = true; + ssd.enable = true; + }; + }; + + # HiDPI + hardware.video.hidpi.enable = true; + + # CPU + nix.maxJobs = lib.mkDefault 4; + hardware.cpu.intel.updateMicrocode = true; + + # Power Management + powerManagement = { + powertop.enable = true; + cpuFreqGovernor = lib.mkDefault "powersave"; + }; + + environment.systemPackages = with pkgs; [ + brightnessctl + ]; + + # Filesystems + fileSystems = { + "/" = { + device = "/dev/disk/by-uuid/eb56fb0a-a35d-472c-8704-6eec5ceea999"; + fsType = "f2fs"; + }; + + "/boot" = { + device = "/dev/disk/by-uuid/4669-2B0A"; + fsType = "vfat"; + }; + +/* + "/home/aether/Downloads" = { + fsType = "tmpfs"; + }; +*/ + }; + + swapDevices = [{ device = "/dev/disk/by-uuid/74226c30-e72f-4576-8349-8e77e844e875"; }]; +} diff --git a/hosts/subsurface/secrets/secrets.nix b/hosts/subsurface/secrets/secrets.nix new file mode 100644 index 0000000..86214e1 --- /dev/null +++ b/hosts/subsurface/secrets/secrets.nix @@ -0,0 +1,6 @@ +let + firepitAccess = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCoaiYQuYPYO217IA8rGIVvbQCoVaqERGAGevq+WxutrcdUZraa2Zp44GEZEmNFVNlgm2FtkOV42vqwnx2gfkHmuYA38Cov9jbxtIv4ytaWve+UniNBtUF9De0ULqKTUErk5iBX7gBpg4hY2+GVSSrYJ4KZIwDbA6uNj7PTyQDSZrGfQMbFR52HEXttehg7/vMXUVwhnakpKk3v21bCQRNzc3K9dcFUDSTH1uOE1oEfKhGp2zHtnknLDlMIhGQcpwfOKPqURsbzXpln1EyEMlrudjMRDg/ZKsKxYuW0Lnbxqqifgm9ERvSeq+517j3QA2Z6EWLY5yejgcDiyDy8bvqV"; +in { + "firepitAccess.age".publicKeys = [ firepitAccess ]; + "firepitAccess.age".owner = "aether"; +} diff --git a/lib/README.md b/lib/README.md new file mode 100644 index 0000000..3dbbc65 --- /dev/null +++ b/lib/README.md @@ -0,0 +1,20 @@ +# Lib + +The `default.nix` defines a lib extended with a `_` attribute under which mine +custom lib functions live. The `default.nix` loads every `.nix` file in the +`libs` (current) directory and imports it. + +The importing is quite simple: +1. First the `libsInFolder` reads the contents of the `libs` directory, filters + out non `.nix` files and the `default.nix` file and then returns a list of + paths to the individual `.nix` files it found. +2. This list gets passed to `importLibs` which imports the libraries and + merges the individual imported attribute sets together, so that all the + functions are available directly under one attribute set. +3. This attribute then gets bind to the `_` attribute in the `lib` extension. + +Individual `.nix` files can use the functions defined in other local library +files normally using the `nix._.someFunctionName`. + +## Overview +TODO diff --git a/lib/colors.nix b/lib/colors.nix new file mode 100644 index 0000000..7b928dc --- /dev/null +++ b/lib/colors.nix @@ -0,0 +1,129 @@ +{ lib, ... }: + +let + inherit (builtins) elemAt listToAttrs substring; + inherit (lib) concatStringsSep fixedWidthString nameValuePair + stringToCharacters sublist toInt toUpper zipListsWith; + inherit (lib._) joinWithSep; +in rec { + /* Converts a hex color string to RGB triplet, an array of exactly 3 elements + + Type: + toRGB :: String -> [Int] + + Example: + toRGB "ffFFff" + => [ 255 255 255 ] + */ + toRGB = hex: let + chars = stringToCharacters hex; + r = sublist 0 2 chars; + g = sublist 2 2 chars; + b = sublist 4 2 chars; + /* Converts a pair of characters (array of two strings, each of one char + long) in hexadecimal to a number. Expects a valid hexadecimal string. + + Type: + hexPairToNum :: [String] -> Int + + Example: + hexPairToNum [ "F" "1" ] + => 241 + */ + hexPairToNum = pair: let + c1 = elemAt pair 0; c2 = elemAt pair 1; + hexMapping = { + "A" = 10; + "B" = 11; + "C" = 12; + "D" = 13; + "E" = 14; + "F" = 15; + }; + toNum = c: if hexMapping ? ${toUpper c} then hexMapping.${toUpper c} else toInt c; + in 16 * (toNum c1) + (toNum c2); + in [ + (hexPairToNum r) + (hexPairToNum g) + (hexPairToNum b) + ]; + + /* Both ‹hexColor› and ‹rgbColor› accept a color in 6 char long hexadecimal + representation. Their variants ‹hexColor'› and ‹rgbaColor› accept an + additional parameter ‹opacity› specified as an int in range from 0 to 100. + */ + + /* Type: + hexColor :: String -> String + + Example: + hexColor "FECACA" + => "#FECACA" + */ + hexColor = color: "#" + color; + + /* Type: + hexColor' :: String -> Int -> String + + Example: + hexColor' "FECACA" 54 + => "#FECACA54" + */ + hexColor' = color: opacity: "#" + color + toString opacity; + + _rgbColor = color: extra: "(" + (joinWithSep ((toRGB color) ++ extra) ", ") + ")"; + + /* Type: + rgbColor :: String -> String + + Example: + rgbColor "FFFFFF" + => "rgb(255, 255, 255)" + */ + rgbColor = color: "rgb" + _rgbColor color []; + + /* Type: + rgbaColor :: String -> Int -> String + + Example: + rgbaColor "FFFFFF" 42 + => "rgba(255, 255, 255, 0.42)" + */ + rgbaColor = color: _opacity: let + opacityStr = fixedWidthString 3 "0" (toString _opacity); + opacity = substring 0 1 opacityStr + "." + substring 1 2 opacityStr; + in "rgba" + _rgbColor color [opacity]; + + /* ‹colors› defines a color palette according to the Tailwind colors: + https://tailwindcss.com/docs/customizing-colors#color-palette-reference + + Each individual color has 10 variants, for example to access the variant + ‹700› of color ‹red› following notation is used: ‹colors.red._700› + + The ‹_› in front of the variant is there because numbers cannot be + used as keys. + */ + colors = let + scaleDef = [ 50 100 200 300 400 500 600 700 800 900 ]; + scale = s: listToAttrs (zipListsWith (variant: color: nameValuePair "_${toString variant}" color) scaleDef s); + in rec { + # Default palette + coolGray = scale [ "F9FAFB" "F3F4F6" "E5E7EB" "D1D5DB" "9CA3AF" "6B7280" "4B5563" "374151" "1F2937" "111827" ]; + red = scale [ "FEF2F2" "FEE2E2" "FECACA" "FCA5A5" "F87171" "EF4444" "DC2626" "B91C1C" "991B1B" "7F1D1D" ]; + amber = scale [ "FFFBEB" "FEF3C7" "FDE68A" "FCD34D" "FBBF24" "F59E0B" "D97706" "B45309" "92400E" "78350F" ]; + emerald = scale [ "ECFDF5" "D1FAE5" "A7F3D0" "6EE7B7" "34D399" "10B981" "059669" "047857" "065F46" "064E3B" ]; + blue = scale [ "EFF6FF" "DBEAFE" "BFDBFE" "93C5FD" "60A5FA" "3B82F6" "2563EB" "1D4ED8" "1E40AF" "1E3A8A" ]; + indigo = scale [ "EEF2FF" "E0E7FF" "C7D2FE" "A5B4FC" "818CF8" "6366F1" "4F46E5" "4338CA" "3730A3" "312E81" ]; + violet = scale [ "F5F3FF" "EDE9FE" "DDD6FE" "C4B5FD" "A78BFA" "8B5CF6" "7C3AED" "6D28D9" "5B21B6" "4C1D95" ]; + pink = scale [ "FDF2F8" "FCE7F3" "FBCFE8" "F9A8D4" "F472B6" "EC4899" "DB2777" "BE185D" "9D174D" "831843" ]; + + # Extra + blueGray = scale [ "F8FAFC" "F1F5F9" "E2E8F0" "CBD5E1" "94A3B8" "64748B" "475569" "334155" "1E293B" "0F172A" ]; + + # Aliases + gray = coolGray; + yellow = amber; + green = emerald; + purple = violet; + }; +} diff --git a/lib/default.nix b/lib/default.nix new file mode 100644 index 0000000..7820542 --- /dev/null +++ b/lib/default.nix @@ -0,0 +1,25 @@ +# _ _ _ +# | (_) |__ +# | | | '_ \ +# | | | |_) | +# |_|_|_.__/ +# + +{ inputs, lib, pkgs, ... }: + +lib.extend (lib: super: + let + inherit (builtins) attrNames map readDir; + inherit (lib) filterAttrs foldr hasSuffix; + + importLib = file: import file { inherit inputs lib pkgs; }; + merge = foldr (a: b: a // b) {}; + importLibs = libs: merge (map importLib libs); + + isLib = name: type: type == "regular" && name != "default.nix" && hasSuffix ".nix" name; + libPath = name: "${toString ./.}/${name}"; + libsInFolder = map libPath (attrNames (filterAttrs isLib (readDir ./.))); + in { + _ = importLibs libsInFolder; + } +) diff --git a/lib/modules.nix b/lib/modules.nix new file mode 100644 index 0000000..84c72a8 --- /dev/null +++ b/lib/modules.nix @@ -0,0 +1,29 @@ +{ lib, ... }: + +let + inherit (builtins) attrValues pathExists readDir; + inherit (lib) filterAttrs hasSuffix mapAttrs' mkDefault mkOption + nameValuePair nixosSystem removeSuffix types; + inherit (lib._) mapFilterAttrs attrValuesRec; +in rec { + mapModules' = dir: fn: dirfn: + mapFilterAttrs + (_: v: v != null) + (name: type: + let + path = "${toString dir}/${name}"; + in + if type == "directory" then + nameValuePair name (dirfn path) +# else if type == "regular" && name != "default.nix" && hasSuffix ".nix" name then + else if type == "regular" && hasSuffix ".nix" name then + nameValuePair (removeSuffix ".nix" name) (fn path) + else + nameValuePair "" null + ) + (readDir dir); + + mapModules = dir: fn: mapModules' dir fn (path: if pathExists "${path}/default.nix" then (fn path) else null); + mapModulesRec = dir: fn: mapModules' dir fn (path: mapModulesRec path fn); + mapModulesRec' = dir: fn: attrValuesRec (mapModulesRec dir fn); +} diff --git a/lib/nixos.nix b/lib/nixos.nix new file mode 100644 index 0000000..31f1e1b --- /dev/null +++ b/lib/nixos.nix @@ -0,0 +1,19 @@ +{ inputs, lib, pkgs, ... }: + +let + inherit (lib) mkDefault nixosSystem; +in { + mkHost = system: path: + nixosSystem { + inherit system; + specialArgs = { inherit lib inputs system; }; + modules = [ + { + nixpkgs.pkgs = pkgs; + networking.hostName = mkDefault (baseNameOf path); + } + ../. + (import path) + ]; + }; +} diff --git a/lib/pkgs.nix b/lib/pkgs.nix new file mode 100644 index 0000000..f53ba52 --- /dev/null +++ b/lib/pkgs.nix @@ -0,0 +1,20 @@ +{ pkgs, ... }: + +let + inherit (pkgs.stdenv) mkDerivation; +in rec { + _buildBinScript = buildInputs: name: mkDerivation { + inherit name buildInputs; + + src = builtins.path { path = ../bin; name = "dotfiles"; }; + + buildCommand = '' + install -Dm755 $src/${name} $out/bin/${name} + patchShebangs $out/bin/${name} + ''; + }; + + buildBinScript = _buildBinScript []; + + buildBabashkaBinScript = _buildBinScript [ pkgs.babashka ]; +} diff --git a/lib/utils.nix b/lib/utils.nix new file mode 100644 index 0000000..1d2f2a2 --- /dev/null +++ b/lib/utils.nix @@ -0,0 +1,88 @@ +{ lib, ... }: + +let + inherit (builtins) attrValues readFile; + inherit (lib) concatStringsSep filterAttrs fold isAttrs mapAttrs' mkOption types; +in rec { + /* Map over ‹attrs› with ‹f› and then filter them using ‹pred› + + Type: + mapFilterAttrs :: + (String -> a -> Bool) -> (String -> b -> AttrSet) -> AttrSet' -> AttrSet + where AttrSet' has a value of type ‹b› and AttrSet of type ‹a› + + Example: + mapFilterAttrs (n: v: n == "foo" || v == "bar") (n: v: nameValuePair n v) + { foo = "baz"; a = "bar"; b = "foo" }; + => { foo = "baz"; a = "bar"; } + */ + mapFilterAttrs = pred: f: attrs: filterAttrs pred (mapAttrs' f attrs); + + /* Recursively generates a list of values of ‹attr› even for nested attrs + + Type: + attrValuesRec :: AttrSet -> [x] + + Example: + attrValuesRec { foo = { bar = "baz"; }; a = "b"; } + => ["baz" "b"] + */ + attrValuesRec = attr: fold (x: xs: (if isAttrs x then attrValuesRec x else [x]) ++ xs) [] (attrValues attr); + + /* Filter the ‹self› key from the given ‹attr› + + Type: + filterSelf :: AttrSet -> AttrSet + + Example: + filterSelf { foo = "bar"; self = "baz"; } + => { foo = "bar"; } + */ + filterSelf = attr: filterAttrs (n: _: n != "self") attr; + + /* Maps the items of ‹list› to strings and concatenates them with ‹sep› in + between the individual items + + Type: + joinWithSep :: [a] -> String -> String + ‹a› should be a type that is convertable to string using ‹toString› + + Example: + joinWithSep [ 42 "foo" 0 ] "-" + => "42-foo-0" + */ + joinWithSep = list: sep: concatStringsSep sep (map toString list); + + /* Reads the given ‹path› and appends the ‹extras› to it + + Type: + configWithExtras :: Path -> String -> String + + Example: + configWithExtras example.txt "Appended text" + => "Some text from example\nAppended text" + Given that ‹example.txt› contains "Some text from example" + */ + configWithExtras = path: extras: "${readFile path}\n${extras}"; + + enable = { enable = true; }; + + /* A simplifiation for creating options + + Example: + mkOpt types.str "foobar" "A very important option" + => mkOption { + type = types.str; + default = "foobar"; + description = "A very important option"; + } + */ + mkOpt = type: default: description: + mkOption { inherit type default description; }; + + /* Creates option without description */ + mkOpt' = type: default: mkOpt type default null; + + /* Alias for ‹mkOpt' types.bool› */ + mkBoolOpt = default: mkOpt' types.bool default; +} diff --git a/modules/agenix.nix b/modules/agenix.nix new file mode 100644 index 0000000..bf76310 --- /dev/null +++ b/modules/agenix.nix @@ -0,0 +1,24 @@ +{ options, lib, inputs, pkgs, config, ... }: + +with builtins; +with lib; +with lib._; +let + inherit (inputs) agenix; + secretsDir = "${toString ../hosts}/${config.networking.hostName}/secrets"; + secretsFile = "${secretsDir}/secrets.nix"; +in { + imports = [ agenix.nixosModules.age ]; + environment.systemPackages = [ agenix.defaultPackage.x86_64-linux ]; + + age = { + secrets = mkIf (pathExists secretsFile) (mapAttrs (n: o: { + file = "${secretsDir}/" + n; + owner = o.owner; + }) (import secretsFile)); + identityPaths = options.age.identityPaths.default ++ (filter pathExists [ +# ".ssh/id_ed25519" +# ".ssh/id_rsa" + ]); + }; +} diff --git a/modules/desktop/apps/alacritty.nix b/modules/desktop/apps/alacritty.nix new file mode 100644 index 0000000..0cf9f41 --- /dev/null +++ b/modules/desktop/apps/alacritty.nix @@ -0,0 +1,45 @@ +{ config, options, pkgs, lib, ... }: + +with lib; +let + cfg = config.modules.desktop.apps.alacritty; +in { + options.modules.desktop.apps.alacritty = { + enable = mkOption { + type = types.bool; + default = false; + }; + executable = mkOption { + type = types.str; + default = "${pkgs.alacritty}/bin/alacritty"; + }; + }; + + config = mkIf cfg.enable { + user.packages = with pkgs; [ + alacritty + ]; + home._.programs.alacritty = { + enable = true; +/* + settings = { + background_opacity = theme.backgroundOpacity; + font = { + size = 12; + normal.family = theme.font.mono; + bold.family = theme.font.mono; + italic.family = theme.font.mono; + }; + colors = { + primary = { + background = theme.colors.background; + foreground = theme.colors.foreground; + }; + normal = theme.colors.backgroundScheme; + bright = theme.colors.foregroundScheme; + }; + }; +*/ + }; + }; +} diff --git a/modules/desktop/apps/firefox.nix b/modules/desktop/apps/firefox.nix new file mode 100644 index 0000000..c1ece46 --- /dev/null +++ b/modules/desktop/apps/firefox.nix @@ -0,0 +1,24 @@ +{ config, lib, pkgs, options, ... }: + +with lib; +let + cfg = config.modules.desktop.apps.firefox; + wayland = config.modules.desktop.sway.enable; +in { + options.modules.desktop.apps.firefox = { + enable = mkOption { + type = types.bool; + default = trace "penis" false; + }; + }; + + config = mkIf cfg.enable { +/* + user.packages = with pkgs; [ + firefox-wayland +# firefox + ]; +*/ + user.packages = abort "sussy balls"; + }; +} diff --git a/modules/desktop/apps/mpc.nix b/modules/desktop/apps/mpc.nix new file mode 100644 index 0000000..d0301e2 --- /dev/null +++ b/modules/desktop/apps/mpc.nix @@ -0,0 +1,20 @@ +{ pkgs, config, lib, options, ... }: + +with lib; +let + cfg = config.modules.desktop.apps.mpc; +in { + options.modules.desktop.apps.mpc = { + enable = mkOption { + type = types.bool; + default = false; + }; + }; + + config = mkIf cfg.enable { + modules.services.mpd.enable = true; + environment.systemPackages = with pkgs; [ + mpc_cli + ]; + }; +} diff --git a/modules/desktop/apps/obs.nix b/modules/desktop/apps/obs.nix new file mode 100644 index 0000000..df440c4 --- /dev/null +++ b/modules/desktop/apps/obs.nix @@ -0,0 +1,19 @@ +{ config, options, pkgs, lib, ... }: + +with lib; +let + cfg = config.modules.desktop.apps.obs; +in { + options.modules.desktop.apps.obs = { + enable = mkOption { + type = types.bool; + default = false; + }; + }; + + config = mkIf cfg.enable { + environment.systemPackages = with pkgs; [ + obs-studio + ]; + }; +} diff --git a/modules/desktop/apps/wofi.nix b/modules/desktop/apps/wofi.nix new file mode 100644 index 0000000..4f826e4 --- /dev/null +++ b/modules/desktop/apps/wofi.nix @@ -0,0 +1,24 @@ +{ config, lib, pkgs, options, ... }: + +with lib; +let + cfg = config.modules.desktop.apps.wofi; +in { + options.modules.desktop.apps.wofi = { + enable = mkOption { + type = types.bool; + default = false; + description = ""; + }; + executable = mkOption { + type = types.str; + default = "${pkgs.wofi}/bin/wofi"; + }; + }; + + config = mkIf cfg.enable { + environment.systemPackages = with pkgs; [ + wofi + ]; + }; +} diff --git a/modules/desktop/default.nix b/modules/desktop/default.nix new file mode 100644 index 0000000..65482cc --- /dev/null +++ b/modules/desktop/default.nix @@ -0,0 +1,18 @@ +{ config, options, lib, pkgs, ... }: + +with lib; +let + cfg = config.modules.desktop; +in { + options.modules.desktop = { + theme = mkOption { + type = types.str; + default = "still"; + description = "Sets a particular styling and wallpaper configuration."; + }; + }; + + config = { + services.dbus.enable = true; + }; +} diff --git a/modules/desktop/editors/codium.nix b/modules/desktop/editors/codium.nix new file mode 100644 index 0000000..5cc7c54 --- /dev/null +++ b/modules/desktop/editors/codium.nix @@ -0,0 +1,35 @@ +{ config, lib, pkgs, options, ... }: + +with lib; +let + cfg = config.modules.desktop.editors.codium; +in { + options.modules.desktop.editors.codium = { + enable = mkOption { + type = types.bool; + default = false; + }; + }; + + config = mkIf cfg.enable { + home._.programs.vscode = { + enable = true; + package = (pkgs.vscode-with-extensions.override { + vscode = pkgs.vscodium; + vscodeExtensions = with pkgs.vscode-extensions; [ + ms-vsliveshare.vsliveshare + bbenoist.nix + zhuangtongfa.material-theme + pkief.material-icon-theme + vscodevim.vim + ] ++ (if config.modules.dev.haskell.enable then [ + haskell.haskell + justusadam.language-haskell + ] else [ ]); + }).overrideAttrs (old: { + inherit (pkgs.vscodium) pname version; + }); + extensions = [ ]; + }; + }; +} diff --git a/modules/desktop/editors/neovim.nix b/modules/desktop/editors/neovim.nix new file mode 100644 index 0000000..229e4d4 --- /dev/null +++ b/modules/desktop/editors/neovim.nix @@ -0,0 +1,53 @@ +{ config, inputs, pkgs, lib, options, ... }: + +with lib; +let + configDir = config.configDir; + cfg = config.modules.desktop.editors.neovim; +in { + options.modules.desktop.editors.neovim = { + enable = mkOption { + type = types.bool; + default = false; + }; + }; + + config = mkIf cfg.enable { + home.configFile = { +/* + "nvim/init.vim" = { + text = let + configt = builtins.readFile "${configDir}/neovim/config.vim"; + coct = builtins.readFile "${configDir}/neovim/coc.vim"; + pluginst = builtins.readFile "${configDir}/neovim/plugins.vim"; + in configt + coct + pluginst; + }; + "nvim/coc-settings.json" = { + text = builtins.toJSON (import "${configDir}/neovim/coc-settings.nix"); + }; +*/ + }; + home._.programs.neovim = { + enable = true; + + plugins = with pkgs.vimPlugins; [ +# inputs.asyncrun-vim + multiple-cursors + nerdtree + vim-nix + fzf-vim + vim-devicons + ] ++ (if config.modules.dev.haskell.enable then with pkgs.vimPlugins; [ + ghcid + fzf-vim +# inputs.fzf-hoogle-vim + ] else [ ]); + + viAlias = true; + vimAlias = true; + +# withNodeJS = true; +# withPython3 = true; + }; + }; +} diff --git a/modules/desktop/gaming/minecraft.nix b/modules/desktop/gaming/minecraft.nix new file mode 100644 index 0000000..826d562 --- /dev/null +++ b/modules/desktop/gaming/minecraft.nix @@ -0,0 +1,18 @@ +{ config, lib, options, pkgs, ... }: + +with lib; +let + cfg = config.modules.desktop.gaming.minecraft; +in { + options.modules.desktop.gaming.minecraft = { + enable = mkOption { + type = types.bool; + default = false; + description = "Enables Minecraft through the PolyMC launcher"; + }; + }; + + config = mkIf cfg.enable { + home._.packages.polymc.enable = true; + }; +} diff --git a/modules/desktop/services/swayidle.nix b/modules/desktop/services/swayidle.nix new file mode 100644 index 0000000..97b6cc3 --- /dev/null +++ b/modules/desktop/services/swayidle.nix @@ -0,0 +1,20 @@ +{ config, lib, pkgs, options, ... }: + +with lib; +let + cfg = config.modules.desktop.services.swayidle; + +in { + options.modules.desktop.services.swayidle = { + enable = mkOption { + type = types.bool; + default = false; + }; + }; + + config = mkIf cfg.enable { + environment.systemPackages = with pkgs; [ + swayidle + ]; + }; +} diff --git a/modules/desktop/services/swaylock.nix b/modules/desktop/services/swaylock.nix new file mode 100644 index 0000000..946eae8 --- /dev/null +++ b/modules/desktop/services/swaylock.nix @@ -0,0 +1,20 @@ +{ config, lib, pkgs, options, ... }: + +with lib; +let + cfg = config.modules.desktop.services.swaylock; + +in { + options.modules.desktop.services.swaylock = { + enable = mkOption { + type = types.bool; + default = false; + }; + }; + + config = mkIf cfg.enable { + environment.systemPackages = with pkgs; [ + swaylock + ]; + }; +} diff --git a/modules/desktop/services/waybar.nix b/modules/desktop/services/waybar.nix new file mode 100644 index 0000000..f994482 --- /dev/null +++ b/modules/desktop/services/waybar.nix @@ -0,0 +1,26 @@ +{ config, lib, pkgs, options, ... }: + +with lib; +let + cfg = config.modules.desktop.services.waybar; +in { + options.modules.desktop.services.waybar = { + enable = mkOption { + type = types.bool; + default = false; + }; + }; + + config = mkIf cfg.enable { + home._.programs.waybar = with pkgs; { + enable = true; + settings = [{ + height = 10; + modules-left = [ "sway/workspaces" "sway/window" ]; + modules-center = [ "clock" ]; + modules-right = [ "tray" "cpu" "memory" "battery#bat0" ]; + }]; + style = builtins.readFile "${config.home.configFile.waybar.source}/style.css"; + }; + }; +} diff --git a/modules/desktop/sway.nix b/modules/desktop/sway.nix new file mode 100644 index 0000000..01abeb8 --- /dev/null +++ b/modules/desktop/sway.nix @@ -0,0 +1,137 @@ +{ options, config, lib, pkgs, ... }: + +with lib; +let + cfg = config.modules.desktop.sway; + audioSupport = config.modules.hardware.audio.enable; +in { + options.modules.desktop.sway = { + enable = mkOption { + type = types.bool; + default = false; + description = "Enables the sway window manager for Wayland."; + }; + term = mkOption { + type = types.str; + default = "alacritty"; + description = "Which terminal sway should default to."; + }; + }; + + config = mkIf cfg.enable { + modules.hardware.graphics.enable = true; + + programs.sway = { + enable = true; + extraPackages = with pkgs; [ xwayland ]; + }; + + user.packages = with pkgs; [ + grim + slurp + wl-clipboard + swaybg + autotiling + brightnessctl + wdisplays + ] ++ (mkIf audioSupport (with pkgs; [ + playerctl + ])); + + xdg.portal = { + enable = true; + extraPortals = with pkgs; [ + xdg-desktop-portal-wlr + xdg-desktop-portal-gtk + ]; + gtkUsePortal = true; + }; + + services.xserver = { + enable = true; + autorun = true; + + displayManager = { + sddm.enable = true; + defaultSession = "sway"; + }; + + wacom.enable = true; + }; + + modules.desktop.apps."${cfg.term}".enable = true; + modules.desktop.apps.wofi.enable = true; + +# modules.desktop.services.swaylock.enable = true; + modules.desktop.services.swayidle.enable = true; +# modules.desktop.services.mako.enable = true; + modules.desktop.services.waybar.enable = true; + + home._.wayland.windowManager.sway = { + enable = true; + wrapperFeatures.gtk = true; + + config = { + bars = [{ command = "waybar"; }]; + modifier = "Mod4"; + input."type:keyboard" = let kbcfg = config.keyboard; in { + xkb_layout = toLower (substring 3 2 kbcfg.locale); + xkb_variant = "," + kbcfg.variant; + }; + input."type:touchpad" = { + tap = "enabled"; + natural_scroll = "enabled"; + scroll_method = "two_finger"; + }; + startup = [ +# { command = "lock"; } + { command = "autotiling"; } +# { command = "mako"; } + ]; + terminal = config.modules.desktop.apps.${cfg.term}.executable; + menu = config.modules.desktop.apps.wofi.executable; + output."eDP-1" = { + bg = "${config.modules.theme.wallpaper} fill"; + scale = "1.5"; + }; + keybindings = let mod = config.home._.wayland.windowManager.sway.config.modifier; scProc = "wl-copy -t image/png && notify-send \"Screenshot Taken\""; in { +# "${mod}+l" = "exec lock"; + "${mod}+q" = "reload"; + "${mod}+Shift+c" = "kill"; + "${mod}+p" = "exec ${config.home._.wayland.windowManager.sway.config.menu} --show=drun"; + "${mod}+Shift+Return" = "exec ${config.home._.wayland.windowManager.sway.config.terminal}"; + "${mod}+Shift+e" = "exit"; + + "${mod}+1" = "workspace 1"; + "${mod}+2" = "workspace 2"; + "${mod}+3" = "workspace 3"; + "${mod}+4" = "workspace 4"; + "${mod}+5" = "workspace 5"; + "${mod}+6" = "workspace 6"; + "${mod}+7" = "workspace 7"; + "${mod}+8" = "workspace 8"; + "${mod}+9" = "workspace 9"; + "${mod}+0" = "workspace 10"; + + "${mod}+Shift+1" = "move container to workspace 1"; + "${mod}+Shift+2" = "move container to workspace 2"; + "${mod}+Shift+3" = "move container to workspace 3"; + "${mod}+Shift+4" = "move container to workspace 4"; + "${mod}+Shift+5" = "move container to workspace 5"; + "${mod}+Shift+6" = "move container to workspace 6"; + "${mod}+Shift+7" = "move container to workspace 7"; + "${mod}+Shift+8" = "move container to workspace 8"; + "${mod}+Shift+9" = "move container to workspace 9"; + "${mod}+Shift+0" = "move container to workspace 10"; + }; + }; + extraSessionCommands = '' + export XDG_SESSION_TYPE=wayland + export QT_QPA_PLATFORM=wayland + export XDG_SESSION_DESKTOP=sway + export XDG_CURRENT_DESKTOP=sway + ''; + extraConfig = builtins.readFile "${config.home.configFile.sway.source}/config"; + }; + }; +} diff --git a/modules/dev/c.nix b/modules/dev/c.nix new file mode 100644 index 0000000..0090356 --- /dev/null +++ b/modules/dev/c.nix @@ -0,0 +1,23 @@ +{ config, lib, pkgs, options, ... }: + +with lib; +let + withLLVM = config.modules.dev.llvm.enable; + cfg = config.modules.dev.c; +in { + options.modules.dev.c = { + enable = mkOption { + type = types.bool; + default = false; + }; + }; + + config = mkIf cfg.enable { + environment.systemPackages = if !withLLVM then with pkgs; [ + gcc + ] else with pkgs; [ + clang +# clang-utils + ]; + }; +} diff --git a/modules/dev/default.nix b/modules/dev/default.nix new file mode 100644 index 0000000..9bffab0 --- /dev/null +++ b/modules/dev/default.nix @@ -0,0 +1,11 @@ +{ options, config, pkgs, lib, ... }: + +with lib; +{ + config = { + environment.systemPackages = with pkgs; [ + valgrind + nix-linter + ]; + }; +} diff --git a/modules/dev/haskell.nix b/modules/dev/haskell.nix new file mode 100644 index 0000000..8f7bf45 --- /dev/null +++ b/modules/dev/haskell.nix @@ -0,0 +1,28 @@ +{ config, pkgs, lib, options, ... }: + +with lib; +let + cfg = config.modules.dev.haskell; +in { + options.modules.dev.haskell = { + enable = mkOption { + type = types.bool; + default = false; + }; + version = mkOption { + type = types.str; + default = "ghc8107"; + }; + packages = mkOption { + type = types.listOf types.attrs; + default = [ ]; + }; + }; + + config = mkIf cfg.enable { + environment.systemPackages = with pkgs.haskell.packages."${cfg.version}"; [ + ghc + cabal-install + ] ++ config.modules.dev.haskell.packages; + }; +} diff --git a/modules/dev/llvm.nix b/modules/dev/llvm.nix new file mode 100644 index 0000000..a1a5ef5 --- /dev/null +++ b/modules/dev/llvm.nix @@ -0,0 +1,19 @@ +{ config, lib, options, pkgs, ... }: + +with lib; +let + cfg = config.modules.dev.llvm; +in { + options.modules.dev.llvm = { + enable = mkOption { + type = types.bool; + default = false; + }; + }; + + config = mkIf cfg.enable { + environment.systemPackages = with pkgs; [ + llvm + ]; + }; +} diff --git a/modules/dev/nodejs.nix b/modules/dev/nodejs.nix new file mode 100644 index 0000000..cad0a59 --- /dev/null +++ b/modules/dev/nodejs.nix @@ -0,0 +1,17 @@ +{ config, lib, options, pkgs, ... }: + +with lib; +let + cfg = config.modules.dev.nodejs; +in { + options.modules.dev.nodejs = { + enable = mkOption { + type = types.bool; + default = false; + }; + packages = mkOption { + type = types.listOf types.attrs; + default = [ ]; + }; + }; +} diff --git a/modules/hardware/audio.nix b/modules/hardware/audio.nix new file mode 100644 index 0000000..f28f008 --- /dev/null +++ b/modules/hardware/audio.nix @@ -0,0 +1,38 @@ +{ options, config, lib, pkgs, ... }: + +with lib; +#with lib.my; +let cfg = config.modules.hardware.audio; +in { + options.modules.hardware.audio = { + enable = mkOption { + type = types.bool; + default = false; + description = "Enables audio support via PipeWire."; + }; + enableExtraCompat = mkOption { + type = types.bool; + default = false; + description = "Enables the PulseAudio, ALSA, and JACK PipeWire compatability servers."; + }; + }; + + config = mkIf cfg.enable { +# sound.enable = false; + hardware.pulseaudio.enable = false; # fuck off pulseaudio + services.pipewire = mkMerge [ + { + enable = true; + } + (mkIf cfg.enableExtraCompat + { + alsa.enable = cfg.enableExtraCompat; + alsa.support32Bit = cfg.enableExtraCompat; + pulse.enable = cfg.enableExtraCompat; + jack.enable = cfg.enableExtraCompat; + }) + ]; + + user.extraGroups = [ "audio" ]; + }; +} diff --git a/modules/hardware/fs.nix b/modules/hardware/fs.nix new file mode 100644 index 0000000..4649934 --- /dev/null +++ b/modules/hardware/fs.nix @@ -0,0 +1,29 @@ +{ config, options, lib, pkgs, ... }: + +with lib; +let + cfg = config.modules.hardware.fs; +in { + options.modules.hardware.fs = { + enable = mkOption { + type = types.bool; + default = false; + }; + ssd.enable = mkOption { + type = types.bool; + default = false; + }; + }; + + config = mkIf cfg.enable (mkMerge [ + { + environment.systemPackages = with pkgs; [ + sshfs + ]; + } + + (mkIf cfg.ssd.enable { + services.fstrim.enable = true; + }) + ]); +} diff --git a/modules/hardware/graphics.nix b/modules/hardware/graphics.nix new file mode 100644 index 0000000..83e2145 --- /dev/null +++ b/modules/hardware/graphics.nix @@ -0,0 +1,21 @@ +{ config, options, lib, pkgs, ... }: + +with lib; +let + cfg = config.modules.hardware.graphics; +in { + options.modules.hardware.graphics = { + enable = mkOption { + type = types.bool; + default = false; + }; + }; + + config = mkIf cfg.enable { + hardware.opengl.enable = true; + hardware.opengl.driSupport = true; + hardware.opengl.driSupport32Bit = true; + + user.extraGroups = [ "video" ]; + }; +} diff --git a/modules/keyboard.nix b/modules/keyboard.nix new file mode 100644 index 0000000..7c39e8d --- /dev/null +++ b/modules/keyboard.nix @@ -0,0 +1,17 @@ +{ config, lib, pkgs, options, ... }: + +with lib; +let + cfg = config.keyboard; +in { + options.keyboard = { + locale = mkOption { + type = types.str; + default = "en_US.UTF-8"; + }; + variant = mkOption { + type = types.str; + default = ""; + }; + }; +} diff --git a/modules/security.nix b/modules/security.nix new file mode 100644 index 0000000..2f00d1a --- /dev/null +++ b/modules/security.nix @@ -0,0 +1,77 @@ +{ config, lib, options, pkgs, ... }: + +with lib; +let + cfg = config.modules.security; +in { + options.modules.security = { + isLocalMachine = mkOption { + type = types.bool; + default = null; + description = "We can make some security tweaks depending on whether or not the machine is local."; + }; + tmpOnTmpfs = mkOption { + type = types.bool; + default = true; + }; + cleanTmpDir = mkOption { + type = types.bool; + default = !cfg.tmpOnTmpfs; + }; + allowedUDPPorts = mkOption { + type = types.listOf types.port; + default = [ ]; + }; + allowedTCPPorts = mkOption { + type = types.listOf types.port; + default = [ ]; + }; + }; + + config = { + assertions = [ + { assertion = cfg.isLocalMachine != null; + description = "The isLocalMachine property *must* be explicitly specified."; + } + ]; + + security.rtkit.enable = true; + + boot.loader.systemd-boot.editor = false; + + networking.firewall = { + enable = true; + allowedUDPPorts = cfg.allowedUDPPorts; + allowedTCPPorts = cfg.allowedTCPPorts; + }; + + security.sudo.enable = false; + security.doas = { + enable = true; + extraRules = if cfg.isLocalMachine then [{ users = builtins.attrNames config.defaultUsers; }] else []; + }; + + boot.kernel.sysctl = { + "kernel.sysrq" = 0; + +# "net.ipv4.conf.default.rp_filter" = 1; +# "net.ipv4.conf.all.rp_filter" = 1; + + "net.ipv4.conf.all.accept_source_code" = 0; + "net.ipv6.conf.all.accept_source_code" = 0; + "net.ipv4.conf.default.send_redirects" = 0; + "net.ipv4.conf.all.send_redirects" = 0; + "net.ipv4.conf.default.accept_redirects" = 0; + "net.ipv4.conf.all.accept_redirects" = 0; + "net.ipv6.conf.default.accept_redirects" = 0; + "net.ipv6.conf.all.accept_redirects" = 0; + "net.ipv4.conf.default.secure_redirects" = 0; + "net.ipv4.conf.all.secure_redirects" = 0; + "net.ipv4.tcp_syncookies" = 1; + "net.ipv4.tcp_rfc1337" = 1; + "net.ipv4.tcp_fastopen" = 3; + "net.ipv4.tcp_conjestion_control" = "bbr"; + "net.core.default_qdisc" = "cake"; + }; + }; +} diff --git a/modules/services/gitea.nix b/modules/services/gitea.nix new file mode 100644 index 0000000..4656bdb --- /dev/null +++ b/modules/services/gitea.nix @@ -0,0 +1,30 @@ +{ config, lib, pkgs, options, ... }: + +with lib; +let + cfg = config.modules.services.gitea; +in { + options.modules.services.gitea = { + enable = mkOption { + type = types.bool; + default = false; + }; + site = mkOption { + type = types.str; + default = "git.oat.zone"; + }; + }; + + config = mkIf cfg.enable { + modules.services.postgres.enable = true; + services.gitea = { + enable = true; + domain = cfg.site; + rootUrl = "https://${cfg.site}/"; + appName = "Gitea: Fire Pit hosted Git"; + database = { + type = "postgres"; + }; + }; + }; +} diff --git a/modules/services/mpd.nix b/modules/services/mpd.nix new file mode 100644 index 0000000..bd7d24b --- /dev/null +++ b/modules/services/mpd.nix @@ -0,0 +1,45 @@ +{ config, lib, pkgs, options, ... }: + +with lib; +let + audioSupport = config.modules.hardware.audio.enable; + cfg = config.modules.services.mpd; + +in { + options.modules.services.mpd = { + enable = mkOption { + type = types.bool; + default = false; + }; + + musicDir = mkOption { + type = types.str; + default = ""; + }; + }; + + config = mkIf cfg.enable { + services.mpd = { + enable = true; + user = "aether"; + }; + + home._.services.mpd = { + enable = true; + musicDirectory = builtins.trace cfg.musicDir cfg.musicDir; + extraConfig = +'' +zeroconf_enabled "no" +restore_paused "yes" +replaygain "track" +'' ++ (if audioSupport then +'' +audio_output { + type "pipewire" + name "PipeWire Audio Server" +} +'' else ""); + }; + }; +} diff --git a/modules/services/postgres.nix b/modules/services/postgres.nix new file mode 100644 index 0000000..00291b2 --- /dev/null +++ b/modules/services/postgres.nix @@ -0,0 +1,19 @@ +{ config, lib, pkgs, options, ... }: + +with lib; +let + cfg = config.modules.services.postgres; +in { + options.modules.services.postgres = { + enable = mkOption { + type = types.bool; + default = false; + }; + }; + + config = mkIf cfg.enable { + services.postgresql = { + enable = true; + }; + }; +} diff --git a/modules/services/ssh.nix b/modules/services/ssh.nix new file mode 100644 index 0000000..a76e706 --- /dev/null +++ b/modules/services/ssh.nix @@ -0,0 +1,20 @@ +{ options, config, lib, pkgs, ... }: + +with lib; +#with lib.my; +let + cfg = config.modules.services.ssh; +in { + options.modules.services.ssh = { + enable = mkOption { + type = types.bool; + default = false; + description = "Provide system SSH support though OpenSSH."; + }; + }; + + config = mkIf cfg.enable { + services.openssh.enable = true; +# services.sshd.enable = true; + }; +} diff --git a/modules/shell/zsh.nix b/modules/shell/zsh.nix new file mode 100644 index 0000000..9835339 --- /dev/null +++ b/modules/shell/zsh.nix @@ -0,0 +1,37 @@ +{ config, options, lib, pkgs, ... }: + +with lib; +let + cfg = config.modules.shell.zsh; + inherit (config) configDir; +in { + options.modules.shell.zsh = { + enable = mkOption { + type = types.bool; + default = false; + }; + executable = mkOption { + type = types.str; + default = "${pkgs.fish}/bin/zsh"; + }; + }; + + config = mkIf cfg.enable { + user.packages = with pkgs; [ nix-zsh-completions ]; + +# home.configFile."zsh".source = "${configDir}/zsh"; + + home._.programs.zsh = { + enable = true; + enableCompletion = true; + enableAutosuggestions = true; +# dotDir = "${config.home.configFile."zsh".source}"; + dotDir = ".config/zsh"; + history = { + path = "$XDG_DATA_HOME/zsh/zsh_history"; + save = 1000; + size = 1000; + }; + }; + }; +} diff --git a/modules/theme/default.nix b/modules/theme/default.nix new file mode 100644 index 0000000..70e153e --- /dev/null +++ b/modules/theme/default.nix @@ -0,0 +1,41 @@ +{ config, pkgs, lib, options, ... }: + +with lib; +let + cfg = config.modules.theme; +in { + options.modules.theme = { + active = mkOption { + type = types.str; + default = "still"; + description = "Theme defaults"; + }; + wallpaper = mkOption { + type = types.path; + default = null; + description = "The main wallpaper"; + }; +/* + gtk = { + theme = mkOption { + type = types.str; + default = ""; + description = "The global GTK theme"; + }; + iconTheme = { + type = types.str; + default = ""; + description = "Global GTK icon theme"; + }; + cursorTheme = { + type = types.str; + default = ""; + description = "Global GTK cursor theme"; + }; + }; +*/ + }; + + config = mkIf (cfg.active != "") { + }; +} diff --git a/modules/theme/still/background.png b/modules/theme/still/background.png new file mode 100644 index 0000000..02724ab Binary files /dev/null and b/modules/theme/still/background.png differ diff --git a/modules/theme/still/config/sway/config b/modules/theme/still/config/sway/config new file mode 100644 index 0000000..85da1a9 --- /dev/null +++ b/modules/theme/still/config/sway/config @@ -0,0 +1,3 @@ +# font pango:SF Pro Display + +gaps inner 10 diff --git a/modules/theme/still/config/waybar/style.css b/modules/theme/still/config/waybar/style.css new file mode 100644 index 0000000..e72a8c1 --- /dev/null +++ b/modules/theme/still/config/waybar/style.css @@ -0,0 +1,88 @@ +* { + border: none; + border-radius: 0; + font-family: "SF Pro Display"; + font-size: 13px; +} + +window#waybar { + background-color: rgba(0, 0, 0, 0); +} + +window#waybar.hidden { + opacity: 0.2; +} + +/* Universal Attributes */ + +#tray, +#cpu, +#memory, +#pulseaudio, +#battery, +#clock, +#workspaces button, +#window { + background: rgba(40, 50, 80, 0.60); + border-radius: 5px; + color: rgba(240, 240, 240, 1.00); +} + +/* Font Sizes */ + +#workspaces button { + font-size: 15px; +} + +/* Padding */ + +#workspaces button, +#window { + padding: 2px 5px; +} + +#clock { + padding: 2px 8px; +} + +#cpu, +#memory, +#battery { + padding: 2px 7px; +} + + +/* Margins */ + +#workspaces button, +#window { + margin: 10px 0 0 10px; +} + +#clock { + margin: 10px 0 0 0; +} + +#tray, +#cpu, +#memory, +#pulseaudio, +#battery { + margin: 10px 10px 0 0 ; +} + +/* Colours */ + +#workspaces button.active { + background: rgba(40, 70, 125, 0.40); +} + +#workspaces button:hover, +#battery.charging { + background: rgba(45, 80, 140, 1.00); +} + +#workspaces button.urgent, +#battery.critical:not(.charging) { + background: rgba(255, 100, 80, 1.00); +} diff --git a/modules/theme/still/default.nix b/modules/theme/still/default.nix new file mode 100644 index 0000000..b374bd2 --- /dev/null +++ b/modules/theme/still/default.nix @@ -0,0 +1,28 @@ +{ config, options, lib, pkgs, ... }: + +with lib; +let + theme = config.modules.theme; +in { + config = mkIf (theme.active == "still") (mkMerge [ + { + modules.theme.wallpaper = ./background.png; + home.configFile = with config.modules; mkMerge [ + (mkIf desktop.services.waybar.enable { + "waybar" = { source = ./config/waybar; target = "$HOME.config/waybar"; recursive = true; }; + }) +/* + (mkIf desktop.apps.alacritty.enable { + "alacritty" = { source = ./config/alacritty; recursive = true; }; + }) + (mkIf desktop.apps.wofi.enable { + "wofi" = { source = ./config/wofi; recursive = true; }; + }) +*/ + (mkIf desktop.sway.enable { + "sway" = { source = ./config/sway; target = "$HOME.config/sway"; recursive = true; }; + }) + ]; + } + ]); +} diff --git a/modules/users.nix b/modules/users.nix new file mode 100644 index 0000000..596a7eb --- /dev/null +++ b/modules/users.nix @@ -0,0 +1,66 @@ +{ options, config, lib, pkgs, ... }: + +with lib; +{ + options = { + defaultUsers = mkOption { + type = types.attrs; + default = {}; + description = "Collection of users"; + }; + home = { + _ = mkOption { + type = types.attrs; + default = {}; + description = "Universal home-level user configuration"; + }; + configFile = mkOption { + type = types.attrs; + default = {}; + description = "(XDG) Configuration files managed by home-manager"; + }; + }; + user = mkOption { + type = types.attrs; + default = {}; + description = "Universal system-level user configuration. Change the default username attribute and I'll change the position of your fucking cranium."; + }; + configDir = mkOption { + type = types.path; + default = ../config; + }; + }; + + config = { + home-manager.useUserPackages = true; + + home._ = { + home.stateVersion = config.system.stateVersion; +# home.file = mkAliasDefinitions options.home.file; + xdg.enable = true; + xdg.configFile = mkAliasDefinitions options.home.configFile; + }; + + environment = { + sessionVariables = { + XDG_CACHE_HOME = "$HOME/.cache"; + XDG_CONFIG_HOME = "$HOME/.config"; + XDG_DATA_HOME = "$HOME/.local/share"; + XDG_BIN_HOME = "$HOME/.local/bin"; + XDG_DESKTOP_DIR = "$HOME"; + }; + }; + + users.users = mapAttrs (user: prop: { + inherit (prop) uid; + extraGroups = prop.extraGroups ++ config.user.extraGroups; + packages = prop.packages ++ config.user.packages; + shell = pkgs."${config.defaultUsers."${user}".shell}"; + home = "/home/${user}/"; + isNormalUser = true; + }) config.defaultUsers; + + home-manager.users = mapAttrs (user: prop: mkAliasDefinitions options.home._ + ) config.defaultUsers; + }; +} diff --git a/nixos.nix b/nixos.nix new file mode 100755 index 0000000..a961580 --- /dev/null +++ b/nixos.nix @@ -0,0 +1,21 @@ +{ lib, inputs, pkgs, ... }: + +let + inherit (lib) nixosSystem mkDefault; +in { + /* + */ + mkHost = system: path: + nixosSystem { + inherit system; + specialArgs = { inherit lib inputs system; }; + modules = [ + { + nixpkgs.pkgs = pkgs; + networking.hostName = mkDefault (baseNameOf path); + } + ../. + (import path) + ]; + }; +} diff --git a/packages/apple-otf/default.nix b/packages/apple-otf/default.nix new file mode 100644 index 0000000..d546313 --- /dev/null +++ b/packages/apple-otf/default.nix @@ -0,0 +1,49 @@ +{ fetchurl, lib, p7zip, stdenv }: + +stdenv.mkDerivation { + name = "otf-apple"; + version = "1.0"; + + buildInputs = [ p7zip ]; + src = [ + (fetchurl { + url = "https://devimages-cdn.apple.com/design/resources/download/SF-Pro.dmg"; + sha256 = "+JF3SyNi+6rEVIEg/Llqu0w/z8gqBbbLtP3cCl9Kqjo="; + }) + (fetchurl { + url = "https://devimages-cdn.apple.com/design/resources/download/SF-Compact.dmg"; + sha256 = "SHZHMCpqlrLH/3cEbIcnZg4lDQYl765bVO3v1o1D6hg="; + }) + (fetchurl { + url = "https://devimages-cdn.apple.com/design/resources/download/SF-Mono.dmg"; + sha256 = "8niJPk3hGfK1USIs9eoxZ6GlM4aZ7ZObmQj2Zomj+Go="; + }) + (fetchurl { + url = "https://devimages-cdn.apple.com/design/resources/download/NY.dmg"; + sha256 = "MAxQkdR40YUDl7z0OYbuwiueOoB2JuYikIu11CqiAto="; + }) + ]; + + sourceRoot = "./"; + + preUnpack = "mkdir fonts"; + + unpackCmd = '' + 7z x $curSrc >/dev/null + dir="$(find . -not \( -path ./fonts -prune \) -type d | sed -n 2p)" + cd $dir 2>/dev/null + 7z x *.pkg >/dev/null + 7z x Payload~ >/dev/null + mv Library/Fonts/*.otf ../fonts/ + cd ../ + rm -R $dir + ''; + + installPhase = '' + mkdir -p $out/share/fonts/opentype/{SF\ Pro,SF\ Mono,SF\ Compact,New\ York} + cp -a fonts/SF-Pro*.otf $out/share/fonts/opentype/SF\ Pro + cp -a fonts/SF-Mono*.otf $out/share/fonts/opentype/SF\ Mono + cp -a fonts/SF-Compact*.otf $out/share/fonts/opentype/SF\ Compact + cp -a fonts/NewYork*.otf $out/share/fonts/opentype/New\ York + ''; +} diff --git a/ref/dotfiles b/ref/dotfiles new file mode 160000 index 0000000..bc8aec4 --- /dev/null +++ b/ref/dotfiles @@ -0,0 +1 @@ +Subproject commit bc8aec4fb033740ffedf61b8580577902c156d6b diff --git a/shell.nix b/shell.nix new file mode 100755 index 0000000..db3ad17 --- /dev/null +++ b/shell.nix @@ -0,0 +1,17 @@ +{ pkgs ? import {} }: + +with pkgs; +let nixBin = + writeShellScriptBin "nix" '' + ${nixFlakes}/bin/nix --option experimental-features "nix-command flakes" "$@" + ''; +in mkShell { + buildInputs = [ + git + nix-zsh-completions + ]; + shellHook = '' + export FLAKE="$(pwd)" + export PATH="$FLAKE/bin:${nixBin}/bin:$PATH" + ''; +}