├── .envrc ├── .git-crypt ├── .gitattributes └── keys │ └── default │ └── 0 │ └── 0D34C387EDA03AD69B856664AFF8C0623B1CE493.gpg ├── .gitattributes ├── .gitignore ├── LICENSE ├── README.md ├── bin ├── colorid ├── get-vscode-extension-hash ├── hey ├── hot ├── incfilewatchers ├── loc ├── max_perf_pct ├── mouse ├── mouseon ├── myip ├── rgt ├── rm-submodule ├── search ├── snow ├── spawn ├── unmount ├── weather ├── webcam ├── wifi └── wl ├── config ├── alacritty │ └── alacritty.toml ├── direnv │ └── direnvrc ├── firefox │ └── userChrome.css ├── foot │ └── foot.ini ├── gh │ └── config.yml ├── gimp │ └── menurc ├── git │ ├── config │ └── ignore ├── inkscape │ └── default-template.svg ├── joshuto │ ├── joshuto.toml │ ├── mimetype.toml │ └── preview_file.sh ├── kanshi │ └── config ├── mailcap ├── ncmpcpp │ ├── bindings │ └── config ├── newsboat │ └── config ├── nushell │ ├── config.nu │ ├── env.nu │ └── login.nu ├── starship │ └── starship.toml ├── sway │ └── config ├── tmux │ ├── config │ ├── swap-pane.sh │ └── tmux.conf ├── tree-sitter │ └── config.json ├── vscode │ ├── settings.json │ └── tasks.json ├── waybar │ ├── config │ └── style.css ├── wayfire │ └── config └── xdg │ └── user-dirs.dirs ├── default.nix ├── etc └── test-screencast.py ├── flake.lock ├── flake.nix ├── hosts ├── README.org ├── iso-install │ └── default.nix ├── personal.nix ├── vultr │ ├── default.nix │ └── hardware-configuration.nix ├── work │ ├── default.nix │ └── hardware-configuration.nix └── xps │ ├── default.nix │ └── hardware-configuration.nix ├── keys └── jake.asc ├── lib ├── attrs.nix ├── default.nix ├── generators.nix ├── makeSimpleWebApp.nix ├── modules.nix ├── nixos.nix ├── options.nix ├── paths.nix └── secrets.nix ├── modules ├── browsers │ ├── brave.nix │ ├── chrome.nix │ ├── chromium-help.nix │ ├── default.nix │ ├── firefox.nix │ └── netsurf.nix ├── desktop │ ├── README.org │ ├── default.nix │ ├── gnome.nix │ ├── sway.nix │ └── wayfire.nix ├── dev │ ├── android.nix │ ├── cc.nix │ ├── clojure.nix │ ├── lua.nix │ ├── node.nix │ ├── python.nix │ └── rust.nix ├── editors │ ├── default.nix │ ├── emacs.nix │ ├── tree-sitter.nix │ ├── vim.nix │ └── vscode.nix ├── gaming │ └── emulators.nix ├── hardware │ ├── audio.nix │ ├── bluetooth.nix │ ├── extraHosts.nix │ ├── fs.nix │ ├── printer.nix │ ├── remarkable.nix │ └── scanner.nix ├── media │ ├── daw.nix │ ├── documents.nix │ ├── graphics.nix │ ├── mpv.nix │ ├── ncmpcpp.nix │ ├── recording.nix │ └── spotify.nix ├── messengers │ ├── deltachat.nix │ ├── discord.nix │ ├── email.nix │ ├── matrix.nix │ ├── rss.nix │ ├── signal.nix │ ├── slack.nix │ └── weechat.nix ├── options.nix ├── security.nix ├── services │ ├── acme.nix │ ├── avahi.nix │ ├── backup.nix │ ├── bitwarden.nix │ ├── cal.nix │ ├── calibre.nix │ ├── dnsmasq.nix │ ├── docker.nix │ ├── gitea.nix │ ├── jellyfin.nix │ ├── jitsi.nix │ ├── mailserver.nix │ ├── matrix.nix │ ├── nginx.nix │ ├── ssh.nix │ ├── syncthing.nix │ ├── teamviewer.nix │ └── transmission.nix ├── shell │ ├── bitwarden.nix │ ├── direnv.nix │ ├── file.nix │ ├── fish.nix │ ├── git.nix │ ├── gnupg.nix │ ├── nushell.nix │ └── tmux.nix ├── term │ ├── alacritty.nix │ ├── default.nix │ └── foot.nix ├── themes │ ├── default.nix │ └── stilla │ │ └── default.nix ├── vm │ ├── lxd.nix │ ├── qemu.nix │ └── virtualbox.nix ├── wayland │ ├── default.nix │ ├── kanshi.nix │ ├── mako.nix │ ├── swaylock.nix │ ├── waybar.nix │ └── wofi.nix └── xdg.nix ├── overlays └── x-clipboard.nix ├── packages └── .git-keep ├── shell.nix └── templates └── flake ├── .envrc ├── flake.nix └── shell.nix /.envrc: -------------------------------------------------------------------------------- 1 | if has nix; then 2 | use nix 3 | fi 4 | -------------------------------------------------------------------------------- /.git-crypt/.gitattributes: -------------------------------------------------------------------------------- 1 | # Do not edit this file. To specify the files to encrypt, create your own 2 | # .gitattributes file in the directory where your files are. 3 | * !filter !diff 4 | *.gpg binary 5 | -------------------------------------------------------------------------------- /.git-crypt/keys/default/0/0D34C387EDA03AD69B856664AFF8C0623B1CE493.gpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jakeisnt/nixcfg/e9230d4f90a855a290882a6e7862c593a114cf5e/.git-crypt/keys/default/0/0D34C387EDA03AD69B856664AFF8C0623B1CE493.gpg -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | lib/secrets.nix filter=git-crypt diff=git-crypt 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | result 2 | 3 | .direnv/* 4 | !.direnv/.git-keep 5 | # lib/secrets.nix 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016-2020 Henrik Lissner. 4 | Copyright (c) 2020-2021 Jacob Chvatal. 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining 7 | a copy of this software and associated documentation files (the 8 | "Software"), to deal in the Software without restriction, including 9 | without limitation the rights to use, copy, modify, merge, publish, 10 | distribute, sublicense, and/or sell copies of the Software, and to 11 | permit persons to whom the Software is furnished to do so, subject to 12 | the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be 15 | included in all copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 21 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 22 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 23 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Made with Doom Emacs](https://img.shields.io/badge/Made_with-Doom_Emacs-blueviolet.svg?style=flat-square&logo=GNU%20Emacs&logoColor=white)](https://github.com/hlissner/doom-emacs) 2 | [![NixOS 20.09](https://img.shields.io/badge/NixOS-v20.09-blue.svg?style=flat-square&logo=NixOS&logoColor=white)](https://nixos.org) 3 | 4 | Started as a fork of [hlissner's dotfiles](https://github.com/hlissner/dotfiles), but different design decisions have been made to differentiate the two since. 5 | 6 | ## Screenshots 7 | ### Full Configuration 8 | 9 | 10 | 11 | 12 | ### Minimal Configuration 13 | 14 | 15 | 16 | Feel free to poke around. Contact me if you have any questions! 17 | 18 | ## Installation 19 | 20 | First, snag a copy of the newest version of NixOS by building it off of a previous machine from source. 21 | 22 | This configuration offers `usb`, a CLI-based live USB configuration with some nice utilities for getting started. 23 | 24 | If you'd like to use that system, load the ISO onto a USB with the following commands from an existing Nix system with Nix Flakes enabled: 25 | 26 | ``` sh 27 | nix build .#nixosConfigurations.iso-install.config.system.build.isoImage --impure 28 | sudo cp /path/to/iso/in/nix/store /dev/sda-usb-device-name 29 | sudo sync 30 | ``` 31 | 32 | It's often the case that older version of Linux don't have support for utilities you want, 33 | and it's nice to have access to a graphical installer for most of the process - which none of the nightly NixOS ISOs support. 34 | 35 | Move that ISO to a flash drive (`mv path/to/firmware.iso drive-address`) and make sure to `sync` afterwards. 36 | 37 | After following the default NixOS install instructions off of that flash drive: 38 | 39 | 1. Enter a shell with the necessary dependencies. 40 | 41 | ``` sh 42 | nix-shell -p git nixFlakes 43 | ``` 44 | 45 | 2. Clone this repository into the configuration folder. 46 | 47 | ``` sh 48 | chown -R nixos /mnt/boot/nixos 49 | git clone https://github.com/jakeisnt/nixcfg /mnt/boot/nixos 50 | ``` 51 | 3. Generate a configuration for this machine (ensure that you've mounted swap space) 52 | 53 | ``` sh 54 | nixos-generate-config --root /mnt 55 | mv configuration.nix hosts/$HOSTNAME/default.nix 56 | mv hardware-configuration.nix hosts/$HOSTNAME/ 57 | ``` 58 | 59 | 4. Reference previous configurations when rewriting `default.nix` to use the desired format. 60 | Do not mess this up; make sure you give yourself things like a window manager and internet access. remember to import `../personal.nix` from `default.nix` in addition to the hardware configuration. 61 | 62 | 5. Install the configuration. 63 | ``` sh 64 | 65 | nixos-install --root /mnt --impure --flake .#$HOSTNAME 66 | ``` 67 | 68 | You should be set! Reboot into the machine you've just configured. 69 | Make sure to commit to this repository with that machine's configuration. 70 | -------------------------------------------------------------------------------- /bin/colorid: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env nix-shell 2 | #!nix-shell -i bash -p grim slurp 3 | 4 | # identify a color on ur screen by clicking on it (i think this works?) 5 | # Requires 'slurp' and 'grim' executables 6 | 7 | grim -g "$(slurp -p)" -t ppm - | convert - -format '%[pixel:p{0:0}]' txt:- 8 | -------------------------------------------------------------------------------- /bin/get-vscode-extension-hash: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # format: 4 | # first argument is publisher 5 | # second argument is name 6 | # third argument is version 7 | 8 | wget "https://$1.gallery.vsassets.io/_apis/public/gallery/publisher/$1/extension/$2/$3/assetbyname/Microsoft.VisualStudio.Services.VSIXPackage" 9 | 10 | mv ./Microsoft.VisualStudio.Services.VSIXPackage "./$1-$2.zip" 11 | 12 | nix-hash --flat --base32 --type sha256 "./$1-$2.zip" 13 | rm "./$1-$2.zip" 14 | -------------------------------------------------------------------------------- /bin/hey: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env nu 2 | 3 | # Collect garbage from the nix store 4 | def "main gc" [] { 5 | nix-collect-garbage -d 6 | } 7 | 8 | # Rebuild the NixOS system 9 | def "main rebuild" [] { 10 | sudo nixos-rebuild switch --flake /etc/nixos --option pure-eval no 11 | } 12 | 13 | # find a package with the given name. currently slow 14 | def "main find" [ 15 | package_name: string # the name of the package to locate 16 | ] { 17 | nix search nixos $package_name 18 | } 19 | 20 | # TODO: support updating a flake input: https://github.com/NixOS/nix/issues/5110 21 | 22 | # Upgrade the system's NixOS flake 23 | def "main upgrade" [] { 24 | nix flake update /etc/nixos --impure 25 | main rebuild 26 | } 27 | 28 | # Look into bou.ke shell magic and `nix run` 29 | 30 | # Rebuild for and deploy to a remote server. Not sure if this works 31 | def "main deploy" [] { 32 | nix run nixpkgs#nixos-reubild -- --fast --target-host jake@isnt.online --build-host jake@isnt.online .#vultr --use-remote-sudo switch 33 | } 34 | 35 | # A cli program for interacting with the nix store 36 | def main [] { 37 | help main 38 | } 39 | -------------------------------------------------------------------------------- /bin/hot: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # "Hot reload": Invoke a command whenenver specified file(s) change 4 | # inspired by https://stackoverflow.com/questions/42049983/bash-based-hot-reload-implementation 5 | 6 | function hot { 7 | if (( $# < 2 )); then 8 | echo 'USAGE: hot [ ... ]' 9 | echo ' will be run once when any of the files listed is changed (i.e. ls -l has its output changed)' 10 | else 11 | script=$1 12 | shift 13 | a=''; 14 | while true; do 15 | b=`ls -l $*` 16 | [[ $a != $b ]] && a=$b && eval $script; 17 | sleep .5; 18 | done 19 | fi 20 | } 21 | 22 | hot $@ 23 | -------------------------------------------------------------------------------- /bin/incfilewatchers: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf && sudo sysctl -p 3 | -------------------------------------------------------------------------------- /bin/loc: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env nu 2 | 3 | # Geolocate yourself 4 | def main [ 5 | --json (-j): bool # display the data in json format (default: nushell table) 6 | ] { 7 | let curIp = (curl --silent https://ipinfo.io/ip) 8 | let locationJson = (curl --silent $'https://ipinfo.io/($curIp)') 9 | if $json { 10 | $locationJson 11 | } else { 12 | $locationJson | from json 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /bin/max_perf_pct: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Manipulate Intel P-state "max_perf_pct" sysfs parameter at runtime! 3 | # 4 | # Author: Bjørn Forsman 5 | # Source: https://github.com/bjornfor/nixos-config/blob/master/pkgs/max_perf_pct/max_perf_pct 6 | 7 | usage() 8 | { 9 | cat << EOF 10 | Manipulate Intel P-state "max_perf_pct" sysfs parameter. 11 | Usage: $progname [ num_0_to_100 | + | - ] 12 | Examples: 13 | $progname # print current value 14 | $progname num_0_to_100 # set given value 15 | $progname + # increment by $increment and print new value 16 | $progname - # decrement by $increment and print new value 17 | To reduce fan noise (and performance, of course), try "$progname 70". 18 | EOF 19 | } 20 | 21 | if [ "$UID" -eq 0 ]; then 22 | maybe_sudo= 23 | else 24 | maybe_sudo=sudo 25 | fi 26 | 27 | # Since kernel X.Y(?) we have to use powersave governor to be able to change 28 | # max_perf_pct. (Otherwise, the default governor ("performance") simply ignores 29 | # our writes to max_perf_pct.) 30 | setup() 31 | { 32 | echo powersave | $maybe_sudo tee /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor >/dev/null 33 | } 34 | 35 | set_val() 36 | { 37 | val="$1" 38 | test "$val" -lt 0 && val=0 39 | test "$val" -gt 100 && val=100 40 | setup 41 | echo "$val" | $maybe_sudo tee "$max_perf_pct" >/dev/null 42 | } 43 | 44 | print_val() 45 | { 46 | cat "$max_perf_pct" 47 | } 48 | 49 | max_perf_pct=/sys/devices/system/cpu/intel_pstate/max_perf_pct 50 | increment=5 51 | progname="$(basename "$0")" 52 | 53 | for arg in "$@"; do 54 | case "$arg" in 55 | -h|--help) usage; exit 0;; 56 | "") usage; exit 1;; 57 | esac 58 | done 59 | 60 | arg="$1" 61 | cur_val=$(cat "$max_perf_pct") 62 | 63 | case "$arg" in 64 | +) set_val $(($cur_val + $increment)); print_val;; 65 | -) set_val $(($cur_val - $increment)); print_val;; 66 | "") print_val;; 67 | *) set_val "$arg";; 68 | esac 69 | -------------------------------------------------------------------------------- /bin/mouse: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # disable mouse 4 | swaymsg input 2362:628:PIXA3854:00_093A:0274_Mouse events disabled 5 | swaymsg input 2362:628:PIXA3854:00_093A:0274_Touchpad events disabled 6 | -------------------------------------------------------------------------------- /bin/mouseon: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # enable mouse 4 | swaymsg input 2362:628:PIXA3854:00_093A:0274_Mouse events enabled 5 | swaymsg input 2362:628:PIXA3854:00_093A:0274_Touchpad events enabled 6 | -------------------------------------------------------------------------------- /bin/myip: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Echos your local or WAN IP 3 | 4 | if [[ $1 == -w ]]; then 5 | wan=1 6 | shift 7 | fi 8 | 9 | if [[ -n $wan ]]; then 10 | dig +short myip.opendns.com @resolver1.opendns.com 11 | else 12 | IF=$(netstat -rn | awk '/^0.0.0.0/ {thif=substr($0,74,10); print thif;} /^default.*UG/ {thif=substr($0,65,10); print thif;}') 13 | if command -v ifconfig >/dev/null; then 14 | ifconfig ${NET_IF} | grep -Eo 'inet (addr:)?([0-9]*\.){3}[0-9]*' | grep -Eo '([0-9]*\.){3}[0-9]*' | grep -v '127.0.0.1' 15 | elif command -v ip >/dev/null; then 16 | ip addr | grep 'state UP' -A2 | tail -n1 | awk '{print $2}' | cut -f1 -d'/' 17 | else 18 | >&2 echo "No easy way to grab your IP" 19 | exit 1 20 | fi 21 | fi 22 | -------------------------------------------------------------------------------- /bin/rgt: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env nix-shell 2 | #! nix-shell -p babashka -i "bb -i" 3 | 4 | ;; ripgrep for variable names! 5 | 6 | ;; if the term matches one of these patterns: 7 | ;; replicate it as the others and make lots of ripgrep requests for them 8 | 9 | ;; patterns: 10 | ;; UpperCamelCase 11 | ;; camelCaseRegular 12 | ;; kebab-case-i-think 13 | ;; snake_case_apparently 14 | ;; SCREAMING_SNAKE_CASE 15 | 16 | ;; TODO: 17 | ;; - fix recognition of some of these terms in some patterns 18 | ;; - figure out why `cmd` is hanging in all cases 19 | 20 | (ns rgt 21 | (:require [clojure.tools.cli :refer [parse-opts]] 22 | [babashka.process :as p] 23 | [clojure.core.match :refer [match]] 24 | [clojure.string :as str] 25 | [clojure.java.io :as io])) 26 | 27 | ;; --- utils --- 28 | (defn cmd 29 | "Run a command with a custom printer and sane defaults provided to the process" 30 | [args & [settings]] 31 | (let 32 | [proc (p/process args (merge {:out :inherit :err :inherit :shutdown p/destroy-tree} (or settings nil)))] 33 | (with-open [rdr (io/reader (:out proc))] 34 | (binding [*in* rdr] @proc nil)))) 35 | 36 | 37 | ;; --- recognizers --- 38 | (def camel-regex #"[a-z0-9]+[A-Z0-9][a-z0-9]+") 39 | (def upper-camel-regex #"[A-Z0-9][a-z0-9]+") 40 | (def kebab-regex #"[a-z0-9][a-z0-9-]+[a-z0-9]") 41 | (def snake-regex #"[a-z0-9][a-z0-9_]+[a-z0-9]") 42 | (def screaming-snake-regex #"[A-Z0-9][A-Z0-9_]+[A-Z0-9]") 43 | 44 | ;; --- split-on patterns --- 45 | (def camel-split #"(?=[A-Z])") 46 | (def kebab-split #"-") 47 | (def snake-split #"_") 48 | 49 | ;; --- make cases --- 50 | ;; a 'term' is a seq of lowercase strings 51 | (defn make-camel [term] 52 | (str/join (cons (first term) (map str/capitalize (rest term))))) 53 | 54 | (defn make-upper-camel [term] 55 | (str/join (map str/capitalize term))) 56 | 57 | (defn make-kebab [term] 58 | (str/join "-" term)) 59 | 60 | (defn make-snake [term] 61 | (str/join "_" term)) 62 | 63 | (defn make-screaming-snake [term] 64 | (str/join "_" (map str/upper-case term))) 65 | 66 | ;; --- case map --- 67 | (def cases {:camel-case {:regex camel-regex :gen make-camel} 68 | :upper-camel-case {:regex upper-camel-regex :gen make-upper-camel} 69 | :kebab-case {:regex kebab-regex :gen make-kebab} 70 | :snake-case {:regex snake-regex :gen make-snake} 71 | :screaming-snake-case {:regex screaming-snake-regex :gen make-screaming-snake}}) 72 | 73 | (defn str->term 74 | "Convert a variable name string into a seq of lowercase strings" 75 | [arg term-type] 76 | (map str/lower-case 77 | (str/split 78 | arg 79 | (match term-type 80 | (:or :snake-case :screaming-snake-case) snake-split 81 | (:or :camel-case :upper-camel-case) camel-split 82 | :kebab-case kebab-split)))) 83 | 84 | (defn permute-term 85 | "Permute term into forms aside from the one provided to exclude" 86 | [term to-exclude] 87 | (let 88 | [rem-map (dissoc cases to-exclude) 89 | case-keys (keys rem-map)] 90 | (map 91 | (fn [case-key] ((:gen (case-key rem-map)) term)) 92 | case-keys))) 93 | 94 | (defn rg 95 | "Invoke `ripgrep` with the provided argument" 96 | [arg] 97 | (println "`rg` " arg) 98 | (cmd ["rg" arg])) 99 | 100 | (defn search-all-but 101 | "Search all terms but the term configured to be excluded." 102 | [arg term-type] 103 | (let 104 | [term-str (str->term arg term-type) 105 | permuted-term (permute-term term-str term-type)] 106 | (println "Invoking rg for the terms " permuted-term) 107 | (map rg permuted-term))) 108 | 109 | (defn main [args] 110 | (let 111 | [arg (str/join #" " args)] 112 | (cond 113 | (re-matches camel-regex arg) (search-all-but arg :camel-case) 114 | (re-matches upper-camel-regex arg) (search-all-but arg :upper-camel-case) 115 | (re-matches kebab-regex arg) (search-all-but arg :kebab-case) 116 | (re-matches snake-regex arg) (search-all-but arg :snake-case) 117 | (re-matches screaming-snake-regex arg) (search-all-but arg :screaming-snake-case) 118 | ;; fall back to a trivial ripgrep search with everything to search for 119 | :else (do 120 | (println "Term not recognized; falling back to trivial ripgrep search") 121 | (rg arg))))) 122 | 123 | (main *command-line-args*) 124 | 125 | ;; vi: ft=clojure 126 | -------------------------------------------------------------------------------- /bin/rm-submodule: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # assume running from home directory and submodule name is $1 4 | # also assume that git is installed 5 | 6 | # i hope you don't have anything named "active =" in your .git/config..." 7 | 8 | # remove the submodule from gitmodules 9 | sed -i '/'$1'/d' .gitmodules 10 | 11 | git add .gitmodules 12 | 13 | # remove from .git/config 14 | sed -i '/'$1'/d' .git/config 15 | # this could be dangerous!!!! be careful. 16 | sed -i '/active = /d' .git/config 17 | 18 | # remove from cached 19 | git rm --cached $1/ 20 | 21 | echo "Committing removal of submodule "$1 22 | git commit -m "Removed submodule "$1 23 | 24 | rm -rf $1/ 25 | -------------------------------------------------------------------------------- /bin/search: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # If a query is provided, search duckduckgo for that query. 4 | # If not, visit the duckduckgo website. 5 | 6 | # In the future support more options for searches; 7 | # passing the flag '-p' followed with the platform name or an abbreviation 8 | # (arguments 1 and 2) should make the third argument come up with the search. 9 | 10 | set -e 11 | 12 | firefox https://duckduckgo.com/$1 13 | -------------------------------------------------------------------------------- /bin/snow: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # https://gist.github.com/sontek/1505483 4 | LINES=$(tput lines) 5 | COLUMNS=$(tput cols) 6 | 7 | declare -A snowflakes 8 | declare -A lastflakes 9 | 10 | clear 11 | 12 | function move_flake() { 13 | i="$1" 14 | 15 | if [ "${snowflakes[$i]}" = "" ] || [ "${snowflakes[$i]}" = "$LINES" ]; then 16 | snowflakes[$i]=0 17 | else 18 | if [ "${lastflakes[$i]}" != "" ]; then 19 | printf "\033[%s;%sH \033[1;1H " ${lastflakes[$i]} $i 20 | fi 21 | fi 22 | 23 | printf "\033[%s;%sH\u274$[($RANDOM%6)+3]\033[1;1H" ${snowflakes[$i]} $i 24 | 25 | lastflakes[$i]=${snowflakes[$i]} 26 | snowflakes[$i]=$((${snowflakes[$i]}+1)) 27 | } 28 | 29 | while : 30 | do 31 | i=$(($RANDOM % $COLUMNS)) 32 | 33 | move_flake $i 34 | 35 | for x in "${!lastflakes[@]}" 36 | do 37 | move_flake "$x" 38 | done 39 | 40 | sleep 0.1 41 | done 42 | -------------------------------------------------------------------------------- /bin/spawn: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # TODO: support working directory flag 3 | # TODO: run command to make sure it's valid? then run in another terminal? 4 | alacritty --hold -e bash -c "$@" & disown 5 | -------------------------------------------------------------------------------- /bin/unmount: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # unmount sd card, assuming it's mounted at this point 4 | umount /run/media/jake/disk 5 | -------------------------------------------------------------------------------- /bin/weather: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env nu 2 | 3 | def "main commit" [] { 4 | echo $"*\n\n(weather)\n\ntemperature:(weather --simple)" | git commit -F - 5 | } 6 | 7 | def main [ 8 | -l --location: string # the location to search for 9 | -s --simple: bool # just the temperature 10 | ] { 11 | if ($location != '') { 12 | if ($simple) { 13 | (curl -s $"wttr.in/($location)?format=1") 14 | } else { 15 | (curl -s $"wttr.in/($location)") | head -7 | tail -7 16 | } 17 | } else { 18 | if ($simple) { 19 | (curl -s "wttr.in/?format=1") 20 | } else { 21 | 22 | (curl -s "wttr.in") | head -7 | tail -7 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /bin/webcam: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env nix-shell 2 | #!nix-shell -i bash -p gphoto2 ffmpeg 3 | 4 | # use a DSLR as a webcam via USB 5 | gphoto2 --stdout --capture-movie | ffmpeg -i - -vf format=yuv420p -f v4l2 /dev/video8 6 | # -threads 0 7 | # make sure the camera is plugged into your device and has a consistent power source (the USB bus may not be enough) 8 | 9 | # if having issues: 10 | # - make sure that the camera has adequete power - USB bus power might not be enough 11 | # run gphoto2 --auto-detect to make sure that your camera can be seen. can retrieve logs with another gphoto2 tag as well 12 | # 13 | # streaming setup: 14 | # - obs studio 15 | # - install ffplay with ffmpeg-full package 16 | # - start this script 17 | # - start ffplay at /dev/video8 to pick up rawvideo off fuji and have separate window 18 | # 19 | # join twitch chat with irc: 20 | # - open weechat window, /connect twitch, /join #jakeissnt 21 | -------------------------------------------------------------------------------- /bin/wifi: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env nix-shell 2 | #! nix-shell -p ruby rubyPackages.thor captive-browser -i "ruby" 3 | 4 | # TODO: better integrate nushell tables with fzf: https://github.com/nushell/nushell/issues/5785 5 | # really i want a command where i can say 6 | # x list | x parse | fzf | x action 7 | # for any x program that can both list options and select one of them. 8 | # the `wl` script does this pretty well in the meantime! 9 | 10 | # Easy-to-use wrapper CLI script for wifi. 11 | # Ideally this uses a nushell-compatible interface : ) 12 | # TODO: `captive-browser` doesn't work, and either needs to be configured or re-coded. 13 | 14 | require 'bundler/inline' 15 | 16 | gemfile do 17 | source 'https://rubygems.org' 18 | gem 'cli-ui' 19 | end 20 | 21 | require 'cli/ui' 22 | 23 | # Redirect STDOUT to /dev/null to run the command. 24 | def quiet 25 | old_stdout = $stdout.dup 26 | $stdout = File.new( '/dev/null', 'w' ) 27 | yield 28 | ensure 29 | $stdout = STDOUT 30 | end 31 | 32 | # Attempt to establish a wifi connection with the provided network 33 | def connect_to_wifi(network) 34 | puts `nmcli device wifi connect #{network} --ask` 35 | 36 | # TODO: Check if the network has a captive portal with `captive-browser`. 37 | quiet { `captive-browser` } 38 | if $?.exitstatus != 0 39 | puts "No captive portal detected. You should be good." 40 | else 41 | puts "Captive portal detected. Browser should have opened." 42 | end 43 | end 44 | 45 | 46 | require 'thor' 47 | 48 | class WifiCLI < Thor 49 | class_option :verbose, :type => :boolean, :aliases => "-v" 50 | 51 | # TODO: Display an interactive list of networks to connect to. 52 | # Update the list as more networks become available. 53 | # Pressing 'enter' on a network should connect to it, effectively running `connect ...`. 54 | desc "pick", "Pick and connect to a wifi network" 55 | def list 56 | networks = `nmcli device wifi list`.split("\n")[1..].map { |line| # remove current networks 57 | v = line.split(" ").filter { |x| x != "Mbit/s" } 58 | if v[0] == "*" 59 | v = v[1..] 60 | end 61 | 62 | Hash[[:bssid, :ssid, :mode, :chan, :rate, :signal, :bars, :security].zip(v)] 63 | }.filter { |v| v[:ssid] != "--" } # ensure there are no blank networks 64 | 65 | 66 | if networks.length > 0 67 | CLI::UI.ask('Pick a network to connect to') do |handler| 68 | networks.each do |network| 69 | handler.option([network[:ssid], network[:rate] + " Mbit/s", network[:signal], network[:bars]].join(" ")) { connect_to_wifi(network[1]) } 70 | end 71 | end 72 | else 73 | puts 'No wifi networks available. Sorry!' 74 | end 75 | end 76 | 77 | # Connect to a wifi network, prompting for a password if necessary. 78 | # If a wifi network has a portal, this should open the portal in a browser. 79 | desc "connect NETWORK", "Connect to the specified network" 80 | def connect(network) 81 | connect_to_wifi(network) 82 | end 83 | 84 | # Restart the wifi system. Not sure if this is the best way to approach it or solve slow wifi issues. 85 | desc "reset", "Reset the wifi connection" 86 | def reset 87 | puts `systemctl restart NetworkManager` 88 | end 89 | 90 | # List all of the currently connected wifi devices. 91 | desc "devices", "List all available wifi devices" 92 | def devices 93 | puts `nmcli device` 94 | end 95 | 96 | # List all of the currently connected wifi devices. 97 | desc "hotspot", "Create a wifi hotspot connection" 98 | def devices 99 | puts `nmcli device wifi hotspot` 100 | end 101 | 102 | no_commands { 103 | def exit_on_failure? 104 | true 105 | end 106 | } 107 | end 108 | 109 | WifiCLI.start(ARGV) 110 | 111 | # NOTE: `nmcli device wifi list | lines | str replace 'Mbit\/s' '' | str trim -r | str replace -a '\s+' ',' | split column "," | headers` 112 | # ^ is the command in nushell to get the wifi list as a table. Not sure how to make it interactive! 113 | # 114 | # IDEA: nushell wifi list -> 115 | 116 | # vi: ft=ruby 117 | -------------------------------------------------------------------------------- /bin/wl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | nmcli device wifi rescan > /dev/null 4 | ssid=$(nmcli device wifi list | tail -n +2 | grep -v '^ *\B--\B' | fzf -m | sed 's/^ *\*//' | awk '{print $1}') 5 | 6 | if [ "x$ssid" != "x" ]; then 7 | # check if the SSID has already a connection setup 8 | conn=$(nmcli con | grep "$ssid" | awk '{print $1}' | uniq) 9 | if [ "x$conn" = "x$ssid" ]; then 10 | echo "Please wait while switching to known network $ssid…" 11 | # if yes, bring up that connection 12 | nmcli con up id "$conn" 13 | else 14 | echo "Please wait while connecting to new network $ssid…" 15 | # if not connect to it and ask for the password 16 | nmcli device wifi connect "$ssid" 17 | fi 18 | fi 19 | -------------------------------------------------------------------------------- /config/alacritty/alacritty.toml: -------------------------------------------------------------------------------- 1 | [colors] 2 | draw_bold_text_with_bright_colors = false 3 | 4 | [colors.bright] 5 | black = "#4C566A" 6 | blue = "#ADB2BA" 7 | cyan = "#8FBCBB" 8 | green = "#A19C9A" 9 | magenta = "#CD96B3" 10 | red = "#BA8082" 11 | white = "#FAF5EF" 12 | yellow = "#E9B872" 13 | 14 | [colors.cursor] 15 | cursor = "#F2F2F2" 16 | text = "#0D0D0D" 17 | 18 | [colors.dim] 19 | black = "#373e4d" 20 | blue = "#68809a" 21 | cyan = "#6d96a5" 22 | green = "#809575" 23 | magenta = "#8c738c" 24 | red = "#94545d" 25 | white = "#aeb3bb" 26 | yellow = "#b29e75" 27 | 28 | [colors.normal] 29 | black = "#121414" 30 | blue = "#ADB2BA" 31 | cyan = "#88B6D0" 32 | green = "#A19C9A" 33 | magenta = "#CD96B3" 34 | red = "#BA8082" 35 | white = "#FAFAFA" 36 | yellow = "#E9B872" 37 | 38 | [colors.primary] 39 | background = "#0D0D0D" 40 | dim_foreground = "#4C566A" 41 | foreground = "#F2F2F2" 42 | 43 | [colors.search.matches] 44 | background = "#88B6D0" 45 | foreground = "CellBackground" 46 | 47 | [colors.selection] 48 | background = "#4C566A" 49 | text = "CellForeground" 50 | 51 | [colors.vi_mode_cursor] 52 | cursor = "#F2F2F2" 53 | text = "#0D0D0D" 54 | 55 | [cursor] 56 | style = "Block" 57 | unfocused_hollow = true 58 | 59 | [scrolling] 60 | history = 100000 61 | multiplier = 3 62 | 63 | [selection] 64 | save_to_clipboard = false 65 | semantic_escape_chars = ",│`|:\"' ()[]{}<>\t" 66 | 67 | [window] 68 | decorations = "full" 69 | dynamic_padding = false 70 | opacity = 1 71 | title = "Alacritty" 72 | 73 | [window.dimensions] 74 | columns = 0 75 | lines = 0 76 | 77 | [window.padding] 78 | x = 11 79 | y = 10 80 | -------------------------------------------------------------------------------- /config/direnv/direnvrc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jakeisnt/nixcfg/e9230d4f90a855a290882a6e7862c593a114cf5e/config/direnv/direnvrc -------------------------------------------------------------------------------- /config/firefox/userChrome.css: -------------------------------------------------------------------------------- 1 | /* @namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"); */ 2 | 3 | @-moz-document url(chrome://browser/content/browser.xul), 4 | url(chrome://browser/content/browser.xhtml) 5 | { 6 | /*** TAB BAR ***/ 7 | /* Ensure tab doesn't show through auto-completion popup */ 8 | .tabbrowser-tab { z-index: 0 !important; } 9 | /* Ensure tab "spacers" don't show through the completion window */ 10 | #tabbrowser-arrowscrollbox > spacer { z-index: -1 !important; } 11 | #mainPopupSet { z-index: 9999 !important; } 12 | 13 | /* Hide tabbar if only one tab */ 14 | @import url(./css/tabs-hide-if-only-one.css); 15 | 16 | /* Remove the colored overline on the focused tab */ 17 | .tabbrowser-tab .tab-line { background: none !important; } 18 | 19 | /* Replace favicon on tabs with close button on mouse hover */ 20 | .tabbrowser-tab:not(:hover) .tab-close-button, 21 | .tabbrowser-tab:not([pinned]):hover .tab-icon-image { display: none !important; } 22 | .tabbrowser-tab:not([pinned]):hover .tab-close-button { display:block !important; } 23 | 24 | .tabbrowser-tab:hover .tab-throbber, 25 | .tabbrowser-tab:hover .tab-icon-image, 26 | .tabbrowser-tab:hover .tab-sharing-icon-overlay, 27 | .tabbrowser-tab:hover .tab-icon-overlay, 28 | .tabbrowser-tab:hover .tab-label-container, 29 | .tabbrowser-tab:hover .tab-icon-sound { 30 | -moz-box-ordinal-group: 2 !important; 31 | } 32 | 33 | .tabbrowser-tab .tab-close-button { 34 | margin-left: -2px !important; 35 | margin-right: 4px !important; 36 | } 37 | 38 | .tab-close-button:hover { 39 | fill-opacity: 0 !important; 40 | } 41 | 42 | .tabbrowser-tab::after, 43 | .tabbrowser-tab::before { 44 | border-left: none !important; 45 | border-right: none !important; 46 | } 47 | 48 | .scrollbutton-up[orient="horizontal"]~spacer { border-width: 0px; opacity: 0 } 49 | 50 | scrollbar { 51 | -moz-appearance: none !important; 52 | display: none !important; 53 | } 54 | 55 | /*** NAV BAR ***/ 56 | /* Hide urlbar */ 57 | #nav-bar { 58 | position: relative !important; 59 | z-index: 2 !important; 60 | height: 2px !important; 61 | min-height: 2px !important; 62 | margin-bottom: -2px !important; 63 | opacity: 0 !important; 64 | border: none !important; 65 | } 66 | 67 | /* But unfocus it when we invoke it with ctrl+L */ 68 | #nav-bar:focus-within { 69 | height: auto !important; 70 | margin-bottom: 0px !important; 71 | opacity: 1 !important; 72 | overflow: show !important; 73 | } 74 | 75 | #urlbar-container { 76 | min-height: 0 !important; 77 | } 78 | 79 | #urlbar { 80 | top: 0 !important; 81 | } 82 | 83 | #urlbar-input-container { 84 | height: 28px !important; 85 | } 86 | 87 | .tab-background { 88 | border-radius: 0px !important; 89 | margin-block: 1px 0 !important; 90 | } 91 | 92 | /*** Load local overrides ***/ 93 | @import url(./userChrome.local.css); 94 | } 95 | -------------------------------------------------------------------------------- /config/foot/foot.ini: -------------------------------------------------------------------------------- 1 | # -*- conf -*- 2 | 3 | # shell=$SHELL (if set, otherwise user's default shell from /etc/passwd) 4 | # term=foot (or xterm-256color if built with -Dterminfo=disabled) 5 | # login-shell=no 6 | 7 | # app-id=foot # globally set wayland app-id. Default values are "foot" and "footclient" for desktop and server mode 8 | # title=foot 9 | # locked-title=no 10 | 11 | font=Berkeley Mono:size=11 12 | # font-bold= 13 | # font-italic= 14 | # font-bold-italic= 15 | # font-size-adjustment=0.5 16 | # line-height= 17 | # letter-spacing=0 18 | # horizontal-letter-offset=0 19 | # vertical-letter-offset=0 20 | # underline-offset= 21 | # underline-thickness= 22 | # box-drawings-uses-font-glyphs=no 23 | # dpi-aware=auto 24 | 25 | # initial-window-size-pixels=700x500 # Or, 26 | # initial-window-size-chars= 27 | # initial-window-mode=windowed 28 | pad=10x10 # optionally append 'center' 29 | # resize-delay-ms=100 30 | 31 | # notify=notify-send -a ${app-id} -i ${app-id} ${title} ${body} 32 | 33 | # bold-text-in-bright=no 34 | # word-delimiters=,│`|:"'()[]{}<> 35 | # selection-target=primary 36 | # workers= 37 | # utmp-helper=/usr/lib/utempter/utempter # When utmp backend is ‘libutempter’ (Linux) 38 | # utmp-helper=/usr/libexec/ulog-helper # When utmp backend is ‘ulog’ (FreeBSD) 39 | 40 | [environment] 41 | # name=value 42 | 43 | [bell] 44 | # urgent=no 45 | # notify=no 46 | # command= 47 | # command-focused=no 48 | 49 | [scrollback] 50 | # lines=1000 51 | # multiplier=3.0 52 | # indicator-position=relative 53 | # indicator-format="" 54 | 55 | [url] 56 | # launch=xdg-open ${url} 57 | # label-letters=sadfjklewcmpgh 58 | # osc8-underline=url-mode 59 | # protocols=http, https, ftp, ftps, file, gemini, gopher 60 | # uri-characters=abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.,~:;/?#@!$&%*+="'()[] 61 | 62 | [cursor] 63 | # style=block 64 | # color= 65 | # blink=no 66 | # beam-thickness=1.5 67 | # underline-thickness= 68 | 69 | [mouse] 70 | # hide-when-typing=no 71 | # alternate-scroll-mode=yes 72 | 73 | [csd] 74 | # preferred=server 75 | # size=26 76 | # font= 77 | # color= 78 | # hide-when-typing=no 79 | # border-width=0 80 | # border-color= 81 | # button-width=26 82 | # button-color= 83 | # button-minimize-color= 84 | # button-maximize-color= 85 | # button-close-color= 86 | 87 | [key-bindings] 88 | # scrollback-up-page=Shift+Page_Up 89 | # scrollback-up-half-page=none 90 | # scrollback-up-line=none 91 | # scrollback-down-page=Shift+Page_Down 92 | # scrollback-down-half-page=none 93 | # scrollback-down-line=none 94 | # clipboard-copy=Control+Shift+c XF86Copy 95 | # clipboard-paste=Control+Shift+v XF86Paste 96 | # primary-paste=Shift+Insert 97 | # search-start=Control+Shift+r 98 | # font-increase=Control+plus Control+equal Control+KP_Add 99 | # font-decrease=Control+minus Control+KP_Subtract 100 | # font-reset=Control+0 Control+KP_0 101 | # spawn-terminal=Control+Shift+n 102 | # minimize=none 103 | # maximize=none 104 | # fullscreen=none 105 | # pipe-visible=[sh -c "xurls | fuzzel | xargs -r firefox"] none 106 | # pipe-scrollback=[sh -c "xurls | fuzzel | xargs -r firefox"] none 107 | # pipe-selected=[xargs -r firefox] none 108 | # show-urls-launch=Control+Shift+u 109 | # show-urls-copy=none 110 | # show-urls-persistent=none 111 | # prompt-prev=Control+Shift+z 112 | # prompt-next=Control+Shift+x 113 | # unicode-input=none 114 | # noop=none 115 | 116 | [search-bindings] 117 | # cancel=Control+g Control+c Escape 118 | # commit=Return 119 | # find-prev=Control+r 120 | # find-next=Control+s 121 | # cursor-left=Left Control+b 122 | # cursor-left-word=Control+Left Mod1+b 123 | # cursor-right=Right Control+f 124 | # cursor-right-word=Control+Right Mod1+f 125 | # cursor-home=Home Control+a 126 | # cursor-end=End Control+e 127 | # delete-prev=BackSpace 128 | # delete-prev-word=Mod1+BackSpace Control+BackSpace 129 | # delete-next=Delete 130 | # delete-next-word=Mod1+d Control+Delete 131 | # extend-to-word-boundary=Control+w 132 | # extend-to-next-whitespace=Control+Shift+w 133 | # clipboard-paste=Control+v Control+Shift+v Control+y XF86Paste 134 | # primary-paste=Shift+Insert 135 | # unicode-input=none 136 | 137 | [url-bindings] 138 | # cancel=Control+g Control+c Control+d Escape 139 | # toggle-url-visible=t 140 | 141 | [text-bindings] 142 | # \x03=Mod4+c # Map Super+c -> Ctrl+c 143 | 144 | [mouse-bindings] 145 | # selection-override-modifiers=Shift 146 | # primary-paste=BTN_MIDDLE 147 | # select-begin=BTN_LEFT 148 | # select-begin-block=Control+BTN_LEFT 149 | # select-extend=BTN_RIGHT 150 | # select-extend-character-wise=Control+BTN_RIGHT 151 | # select-word=BTN_LEFT-2 152 | # select-word-whitespace=Control+BTN_LEFT-2 153 | # select-row=BTN_LEFT-3 154 | 155 | # vim: ft=dosini 156 | -------------------------------------------------------------------------------- /config/gh/config.yml: -------------------------------------------------------------------------------- 1 | # What protocol to use when performing git operations. Supported values: ssh, https 2 | git_protocol: https 3 | # What editor gh should run when creating issues, pull requests, etc. If blank, will refer to environment. 4 | editor: 5 | # When to interactively prompt. This is a global config that cannot be overridden by hostname. Supported values: enabled, disabled 6 | prompt: enabled 7 | # A pager program to send command output to, e.g. "less". Set the value to "cat" to disable the pager. 8 | pager: 9 | # Aliases allow you to create nicknames for gh commands 10 | aliases: 11 | co: pr checkout 12 | -------------------------------------------------------------------------------- /config/git/config: -------------------------------------------------------------------------------- 1 | [user] 2 | name = Jacob Chvatal 3 | email = jake@isnt.online 4 | signingkey = 1EB278CFEE0A2F49 5 | [gpg] 6 | program = gpg2 7 | [commit] 8 | gpgsign = true 9 | [init] 10 | defaultBranch = main 11 | [core] 12 | whitespace = trailing-space 13 | pager = delta 14 | [pager] 15 | difftool = true 16 | [interactive] 17 | diffFilter = delta --color-only 18 | [delta] 19 | features = side-by-side line-numbers 20 | hunk-header-style = omit 21 | whitespace-error-style = blue purple 22 | [github] 23 | user = jakeisnt 24 | [gitlab] 25 | user = jakeisnt 26 | [rebase] 27 | autosquash = true 28 | [pull] 29 | rebase = true 30 | [push] 31 | default = current 32 | [alias] 33 | amend = commit --amend 34 | exec = "!exec " 35 | lg = log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit -- 36 | ls = ls-files 37 | orphan = checkout --orphan 38 | unadd = reset HEAD 39 | undo-commit = reset --soft "HEAD^" 40 | rm-submodule = rm-submodule # this should really be git only 41 | # data analysis 42 | ranked-authors = !git authors | sort | uniq -c | sort -n 43 | emails = !git log --format="%aE" | sort -u 44 | email-domains = !git log --format="%aE" | awk -F'@' '{print $2}' | sort -u 45 | count-lines = !git ls-files | xargs wc -l 46 | # fzf-based rebase 47 | # frbi = "!f() { git rebase -i $(git log --pretty=oneline --color=always) | fzf --ansi | cut -d ' ' -f1; }; f" 48 | [diff] 49 | tool = difftastic 50 | colorMoved = default 51 | 52 | [difftool] 53 | prompt = false 54 | [difftool "difftastic"] 55 | cmd = difft "$LOCAL" "$REMOTE" 56 | 57 | [filter "lfs"] 58 | required = true 59 | smudge = git-lfs smudge -- %f 60 | process = git-lfs filter-process 61 | clean = git-lfs clean -- %f 62 | [sendemail] 63 | smtpserver = mail.isnt.online 64 | smtpencryption = tls 65 | smtpserverport= 587 66 | smtpuser = jake@isnt.online 67 | [transfer] 68 | fsckObjects = true 69 | [fetch] 70 | fsckObjects = true 71 | [receive] 72 | fsckObjects = true 73 | [url "https://github.com/"] 74 | insteadOf = gh: 75 | [url "git@github.com:jakeisnt/"] 76 | insteadOf = gh:/ 77 | [url "https://gitlab.com/"] 78 | insteadOf = gl: 79 | [url "https://gist.github.com/"] 80 | insteadOf = gist: 81 | [url "https://bitbucket.org/"] 82 | insteadOf = bb: 83 | [url "https://git.v0.com"] 84 | insteadOf = v0: 85 | -------------------------------------------------------------------------------- /config/git/ignore: -------------------------------------------------------------------------------- 1 | # For emacs: 2 | *~ 3 | *.*~ 4 | \#* 5 | .\#* 6 | 7 | # For vim: 8 | *.swp 9 | .*.sw[a-z] 10 | *.un~ 11 | Session.vim 12 | .netrwhist 13 | 14 | # Ignore tags (from etags and ctags) 15 | TAGS 16 | !TAGS/ 17 | tags 18 | !tags/ 19 | 20 | # Logs and databases # 21 | ###################### 22 | *.log 23 | *.cache 24 | 25 | # OS generated files # 26 | ###################### 27 | .DS_Store? 28 | .DS_Store 29 | .CFUserTextEncoding 30 | .Trash 31 | .Xauthority 32 | thumbs.db 33 | Icon? 34 | Thumbs.db 35 | .cache 36 | .pid 37 | .sock 38 | 39 | # Code stuffs # 40 | ############### 41 | .svn 42 | .git 43 | .swp 44 | .idea 45 | .*.swp 46 | *~ 47 | .tags 48 | tags 49 | .sass-cache 50 | tmp 51 | .codekit-cache 52 | config.codekit 53 | 54 | # Compiled thangs # 55 | ################### 56 | *.class 57 | *.exe 58 | *.o 59 | *.so 60 | *.dll 61 | *.pyc 62 | -------------------------------------------------------------------------------- /config/inkscape/default-template.svg: -------------------------------------------------------------------------------- 1 | 2 | 16 | 18 | 41 | 43 | 44 | 46 | image/svg+xml 47 | 49 | 50 | 51 | 52 | 53 | 58 | 66 | 67 | 71 | 72 | Default template 73 | 2020-08-05 74 | 75 | 76 | -------------------------------------------------------------------------------- /config/joshuto/joshuto.toml: -------------------------------------------------------------------------------- 1 | numbered_command = false 2 | 3 | use_trash = true 4 | watch_files = true 5 | xdg_open = false 6 | xdg_open_fork = false 7 | 8 | 9 | [display] 10 | # default, hsplit 11 | mode = "default" 12 | 13 | automatically_count_files = false 14 | collapse_preview = true 15 | # ratios for parent view (optional), current view and preview 16 | column_ratio = [1, 4, 4] 17 | scroll_offset = 6 18 | show_borders = true 19 | show_hidden = false 20 | show_icons = true 21 | tilde_in_titlebar = true 22 | # none, absolute, relative 23 | line_number_style = "none" 24 | 25 | [display.sort] 26 | # lexical, mtime, natural 27 | method = "natural" 28 | case_sensitive = false 29 | directories_first = true 30 | reverse = false 31 | 32 | [preview] 33 | max_preview_size = 2097152 # 2MB 34 | preview_script = "~/.config/joshuto/preview_file.sh" 35 | 36 | [tab] 37 | # inherit, home, root 38 | home_page = "home" 39 | -------------------------------------------------------------------------------- /config/joshuto/preview_file.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | test -z "$joshuto_wrap_id" && exit 1; 4 | 5 | path="$1" # Full path of the previewed file 6 | x="$2" # x coordinate of upper left cell of preview area 7 | # y="$3" # y coordinate of upper left cell of preview area 8 | width="$4" # Width of the preview pane (number of fitting characters) 9 | height="$5" # Height of the preview pane (number of fitting characters) 10 | let y="$height"/5 11 | 12 | # Find out mimetype and extension 13 | mimetype=$(file --mime-type -Lb "$path") 14 | extension=$(/bin/echo "${path##*.}" | awk '{print tolower($0)}') 15 | 16 | case "$mimetype" in 17 | image/png | image/jpeg) 18 | show_image "$path" $x $y $width $height 19 | ;; 20 | video/*) 21 | ffmpegthumbnailer -i "$path" -f -m -c png -s 0 -o /tmp/vid.png 2>/dev/null 22 | show_image /tmp/vid.png $x $y $width $height 23 | sleep 5 && rm -f /tmp/vid.png 24 | ;; 25 | *) 26 | remove_image 27 | esac 28 | -------------------------------------------------------------------------------- /config/kanshi/config: -------------------------------------------------------------------------------- 1 | profile workdesk { 2 | output eDP-1 enable scale 2 mode 3840x2160 position 0,0 3 | output DP-2 enable scale 1.5 4 | } 5 | 6 | profile laptop { 7 | output eDP-1 enable mode 3840x2160 position 0,0 8 | } 9 | -------------------------------------------------------------------------------- /config/mailcap: -------------------------------------------------------------------------------- 1 | application/pdf;gv '%s'; test=test -n "$DISPLAY" 2 | application/pdf;pdfcat '%s'; copiousoutput 3 | text/html; firefox '%s'; edit=emacs -c '%s'; test=test -n "$DISPLAY" 4 | text/html; w3m -T text/html '%s'; needsterminal 5 | text/html; w3m -T text/html -dump '%s'; copiousoutput 6 | 7 | 8 | -------------------------------------------------------------------------------- /config/ncmpcpp/config: -------------------------------------------------------------------------------- 1 | ncmpcpp_directory = ~/.config/ncmpcpp 2 | mpd_host = localhost 3 | mpd_port = 6600 4 | mpd_crossfade_time = 2 5 | song_list_format = "{{%a - %t}|{%f}}{$R%l}" 6 | song_status_format = "{{%a{ $2//$9 %b{, %y}} $2//$9 }{%t$/b}}|{$b%f$/b}" 7 | song_library_format = {{%a - %t} (%b)}|{%f} 8 | #alternative_header_first_line_format = $b$1$aqqu$/a$9 {%t}|{%f} $1$atqq$/a$9$/b 9 | #alternative_header_second_line_format = {{$4$b%a$/b$9}{ - $7%b$9}{ ($4%y$9)}}|{%D} 10 | now_playing_prefix = "$b$5" 11 | now_playing_suffix = "$/b$9" 12 | #browser_playlist_prefix = "$2playlist$9 " 13 | #selected_item_prefix = $6 14 | #selected_item_suffix = $9 15 | #modified_item_prefix = $3> $9 16 | #song_window_title_format = {%a - }{%t}|{%f} 17 | #browser_sort_mode = name 18 | #browser_sort_format = {%a - }{%t}|{%f} {(%l)} 19 | #song_columns_list_format = (20)[]{a} (6f)[green]{NE} (50)[white]{t|f:Title} (20)[red]{b} (7f)[magenta]{l} 20 | #playlist_show_mpd_host = no 21 | #playlist_show_remaining_time = no 22 | #playlist_shorten_total_times = no 23 | #playlist_separate_albums = no 24 | playlist_display_mode = classic 25 | #browser_display_mode = classic 26 | #search_engine_display_mode = classic 27 | #playlist_editor_display_mode = classic 28 | #discard_colors_if_item_is_selected = yes 29 | #incremental_seeking = yes 30 | #seek_time = 1 31 | #volume_change_step = 2 32 | autocenter_mode = yes 33 | #centered_cursor = no 34 | progressbar_look = "──" 35 | #progressbar_boldness = yes 36 | #default_place_to_search_in = database 37 | #user_interface = classic 38 | #data_fetching_delay = yes 39 | #media_library_primary_tag = artist 40 | #default_find_mode = wrapped 41 | #default_tag_editor_pattern = %n - %t 42 | header_visibility = no 43 | statusbar_visibility = no 44 | titles_visibility = no 45 | #header_text_scrolling = yes 46 | #cyclic_scrolling = no 47 | #lines_scrolled = 2 48 | follow_now_playing_lyrics = no 49 | #fetch_lyrics_for_current_song_in_background = no 50 | #store_lyrics_in_song_dir = no 51 | #generate_win32_compatible_filenames = yes 52 | #allow_for_physical_item_deletion = no 53 | #lastfm_preferred_language = en 54 | #show_hidden_files_in_local_browser = no 55 | #screen_switcher_mode = playlist, browser 56 | startup_screen = playlist 57 | #startup_slave_screen = "" 58 | #startup_slave_screen_focus = no 59 | #locked_screen_width_part = 50 60 | #ask_for_locked_screen_width_part = yes 61 | jump_to_now_playing_song_at_start = yes 62 | #ask_before_clearing_playlists = yes 63 | #clock_display_seconds = no 64 | #display_volume_level = yes 65 | #display_bitrate = no 66 | #display_remaining_time = no 67 | #regular_expressions = perl 68 | #block_search_constraints_change_if_items_found = yes 69 | #mouse_support = yes 70 | #mouse_list_scroll_whole_page = yes 71 | #empty_tag_marker = 72 | #tags_separator = " | " 73 | #tag_editor_extended_numeration = no 74 | #media_library_sort_by_mtime = no 75 | # enable_window_title = no 76 | external_editor = nvim 77 | colors_enabled = yes 78 | empty_tag_color = red 79 | header_window_color = yellow 80 | volume_color = yellow 81 | state_line_color = red 82 | state_flags_color = yellow 83 | main_window_color = default 84 | color1 = red 85 | color2 = red 86 | progressbar_color = black 87 | progressbar_elapsed_color = red 88 | statusbar_color = default 89 | alternative_ui_separator_color = magenta 90 | window_border_color = yellow 91 | 92 | ## you have dunst? use this 93 | # execute_on_song_change = $XDG_CONFIG_DIR/ncmpcpp/art-dark.sh && notify-send "Now Playing ♫" "$(mpc current)" 94 | 95 | ## you don't have dunst? maybe another notification daemon would work. doesn't work? use this to disable sending notification attemps 96 | # execute_on_song_change = ~/.config/ncmpcpp/art-dark.sh 97 | -------------------------------------------------------------------------------- /config/newsboat/config: -------------------------------------------------------------------------------- 1 | # By default, old articles are cached and have to be fetched manually with R 2 | # This configures newsboat to download feeds automatically 3 | auto-reload yes 4 | refresh-on-startup yes 5 | show-read-articles yes 6 | cleanup-on-quit yes 7 | 8 | # Vim bindings 9 | unbind-key h 10 | unbind-key j 11 | unbind-key k 12 | unbind-key l 13 | 14 | bind-key h quit 15 | bind-key j next 16 | bind-key k prev 17 | bind-key l open 18 | 19 | unbind-key J 20 | unbind-key K 21 | 22 | bind-key J next-feed 23 | bind-key K prev-feed 24 | 25 | unbind-key d 26 | unbind-key u 27 | bind-key d pagedown 28 | bind-key u pageup 29 | 30 | unbind-key n 31 | unbind-key N 32 | bind-key n next-unread 33 | bind-key N prev-unread 34 | 35 | unbind-key r 36 | unbind-key x 37 | bind-key r toggle-article-read 38 | bind-key x pb-delete 39 | 40 | browser linkhandler 41 | macro v set browser "setsid -f mpv"; open-in-browser ; set browser linkhandler 42 | macro p set browser "setsid -f feh"; open-in-browser ; set browser linkhandler 43 | macro c set browser "xsel -b <<<"; open-in-browser ; set browser linkhandler 44 | 45 | # color scheme and format 46 | articlelist-format "%4i %f %D %?T?|%-17T| ?%t" 47 | 48 | highlight article "(^Feed:.*|^Title:.*|^Author:.*)" red default 49 | highlight article "(^Link:.*|^Date:.*)" white default 50 | highlight article "^Podcast Download URL:.*" cyan default 51 | highlight article "^Links:" magenta black underline 52 | highlight article "https?://[^ ]+" green default 53 | highlight article "^(Title):.*$" blue default 54 | highlight article "\\[[0-9][0-9]*\\]" magenta default bold 55 | highlight article "\\[image\\ [0-9]+\\]" green default bold 56 | highlight article "\\[embedded flash: [0-9][0-9]*\\]" green default bold 57 | highlight article ":.*\\(link\\)$" cyan default 58 | highlight article ":.*\\(image\\)$" blue default 59 | highlight article ":.*\\(embedded flash\\)$" magenta default 60 | 61 | color background default default 62 | color listnormal default default 63 | color listfocus magenta default 64 | color info blue black 65 | color article default default 66 | color listnormal_unread white default 67 | color listfocus_unread color255 red 68 | 69 | # urls-source "ttrss" 70 | # ttrss-url "https://rss.chvatal.com/" 71 | # ttrss-login "jake" 72 | # ttrss-passwordfile "~/.newsboat/password" 73 | 74 | # ttrss-flag-star "s" 75 | # ttrss-flag-publish "p" 76 | -------------------------------------------------------------------------------- /config/nushell/config.nu: -------------------------------------------------------------------------------- 1 | $env.config = { 2 | show_banner: false 3 | table: { 4 | mode: none 5 | } 6 | hooks: { 7 | pre_prompt: [{ 8 | let direnv = (direnv export json | from json | default {}) 9 | if ($direnv | is-empty) { 10 | return 11 | } 12 | $direnv 13 | | items {|key, value| 14 | { 15 | key: $key 16 | value: (if $key in $env.ENV_CONVERSIONS { 17 | do ($env.ENV_CONVERSIONS | get $key | get from_string) $value 18 | } else { 19 | $value 20 | }) 21 | } 22 | } | transpose -ird | load-env 23 | }] 24 | } 25 | } 26 | 27 | source ~/.cache/starship/init.nu 28 | -------------------------------------------------------------------------------- /config/nushell/env.nu: -------------------------------------------------------------------------------- 1 | # Specifies how environment variables are: 2 | # - converted from a string to a value on Nushell startup (from_string) 3 | # - converted from a value back to a string when running external commands (to_string) 4 | # Note: The conversions happen *after* config.nu is loaded 5 | 6 | # gnupghome is only defined in bash? redefine it 7 | $env.GNUPGHOME = $'($env.XDG_CONFIG_HOME)/gnupg' 8 | 9 | $env.ENV_CONVERSIONS = { 10 | "PATH": { 11 | from_string: { |s| $s | split row (char esep) } 12 | to_string: { |v| $v | str join (char esep) } 13 | } 14 | "Path": { 15 | from_string: { |s| $s | split row (char esep) } 16 | to_string: { |v| $v | str join (char esep) } 17 | } 18 | } 19 | 20 | # Directories to search for scripts when calling source or use 21 | # By default, /scripts is added 22 | $env.NU_LIB_DIRS = [ 23 | ($nu.config-path | path dirname | path join 'scripts') 24 | ] 25 | 26 | # Directories to search for plugin binaries when calling register 27 | # By default, /plugins is added 28 | $env.NU_PLUGIN_DIRS = [ 29 | ($nu.config-path | path dirname | path join 'plugins') 30 | ] 31 | 32 | # Add /bin to path 33 | $env.PATH = ($env.PATH | split row (char esep) | prepend '/etc/nixos/bin') 34 | $env.PATH = ($env.PATH | split row (char esep) | prepend $'($env.HOME)/.emacs.d/bin') 35 | 36 | # TODO: incorporate this throughout 37 | $env.EDITOR = 'emacsclient -c'; 38 | 39 | $env.GDK_BACKEND = 'wayland'; 40 | 41 | alias js = joshuto 42 | alias cat = bat 43 | alias e = emacsclient -c 44 | # TODO: is there a better wifi testing tool? 45 | alias ct = ping google.com 46 | 47 | alias v = nvim -u ~/.config/nvim/init.lua 48 | alias vi = nvim -u ~/.config/nvim/init.lua 49 | alias vim = nvim -u ~/.config/nvim/init.lua 50 | alias nvim = nvim -u ~/.config/nvim/init.lua 51 | 52 | # TODO: Remove once shell aliases are ported to nushell 53 | 54 | alias gbc = git checkout (git branch --all | fzf | str replace '(\*)' '' | str trim); 55 | alias gop = git open 56 | alias ga = git add 57 | alias gc = git commit 58 | alias gcm = git commit -m 59 | alias gcl = git clone 60 | 61 | alias gap = git add --patch 62 | # need to pass this the commit after `resolve` ... 63 | alias gre = git revert --strategy resolve 64 | alias gb = git branch -av 65 | alias gbl = git blame 66 | alias gca = git commit --amend 67 | alias gcf = git commit --fixup 68 | alias gf = git fetch 69 | alias gi = git init 70 | alias gl = git log --graph --pretty="format:%C(yellow)%h%Creset %C(red)%G?%Creset%C(green)%d%Creset %s %Cblue(%cr) %C(bold blue)<%aN>%Creset" 71 | alias gll = git log --pretty="format:%C(yellow)%h%Creset %C(red)%G?%Creset%C(green)%d%Creset %s %Cblue(%cr) %C(bold blue)<%aN>%Creset" 72 | alias gL = gl --stat 73 | alias gp = git push 74 | alias gpl = git pull --rebase --autostash 75 | alias gs = git status --short . 76 | alias gss = git status 77 | alias gst = git stash 78 | alias gr = git reset HEAD 79 | alias grv = git rev-parse 80 | 81 | mkdir ~/.cache/starship 82 | starship init nu | save -f ~/.cache/starship/init.nu 83 | -------------------------------------------------------------------------------- /config/nushell/login.nu: -------------------------------------------------------------------------------- 1 | if (echo (tty)) == /dev/tty1 { 2 | exec sway 3 | } 4 | -------------------------------------------------------------------------------- /config/starship/starship.toml: -------------------------------------------------------------------------------- 1 | format = """$character""" 2 | right_format = """$all""" 3 | add_newline = false 4 | 5 | [nix_shell] 6 | format = 'via [$symbol$name]($style) ' 7 | -------------------------------------------------------------------------------- /config/tmux/config: -------------------------------------------------------------------------------- 1 | # tmux.conf 2 | # By Henrik Lissner 3 | # https://github.com/hlissner/dotfiles 4 | ######################################## 5 | 6 | set -g default-terminal "xterm-256color" 7 | 8 | new-session # spawn session if attaching when none are running 9 | 10 | setw -g automatic-rename on # rename window after current program 11 | set -g renumber-windows on # renumber windows when one is closed 12 | # Zero-based indexing is fine in programming languages, but not so much in a 13 | # multiplexer when zero is on the other side of the keyboard. 14 | set -g base-index 1 15 | setw -g pane-base-index 1 16 | # display tmux messages longer 17 | set -g display-time 1500 18 | set -g display-panes-time 800 19 | # Address vim-mode switching delay (http://superuser.com/a/252717/65504) 20 | set -s escape-time 0 21 | set -sg repeat-time 600 22 | set -g history-limit 10000 23 | # Rather than constraining window size to the maximum size of any client 24 | # connected to the *session*, constrain window size to the maximum size of any 25 | # client connected to *that window*. Much more reasonable. 26 | setw -g aggressive-resize off 27 | # For terminals that support them, propagate these events to programs that 28 | # understand them. 29 | set -s focus-events on 30 | # Enable mouse + mouse wheel 31 | set -g mouse on 32 | 33 | ######################################## 34 | # Keybinds # 35 | ######################################## 36 | 37 | # Rebind prefix to C-c. Press twice to send literal C-c. 38 | unbind C-b 39 | set -g prefix C-c 40 | bind C-c send-prefix 41 | 42 | # Vi-style keybinds 43 | set -g status-keys vi 44 | set -g mode-keys vi 45 | 46 | bind c new-window -c "#{pane_current_path}" 47 | bind v split-window -h -c "#{pane_current_path}" 48 | bind s split-window -v -c "#{pane_current_path}" 49 | 50 | bind h select-pane -L 51 | bind j select-pane -D 52 | bind k select-pane -U 53 | bind l select-pane -R 54 | bind H run '$TMUX_HOME/swap-pane.sh left' 55 | bind J run '$TMUX_HOME/swap-pane.sh down' 56 | bind K run '$TMUX_HOME/swap-pane.sh up' 57 | bind L run '$TMUX_HOME/swap-pane.sh right' 58 | bind M run '$TMUX_HOME/swap-pane.sh master' 59 | 60 | bind o resize-pane -Z 61 | bind S choose-session 62 | bind W choose-window 63 | bind / choose-session 64 | bind . choose-window 65 | 66 | # bind = select-layout tiled 67 | bind | select-layout even-horizontal 68 | bind _ select-layout even-vertical 69 | 70 | # Disable confirmation 71 | bind x kill-pane 72 | bind X kill-window 73 | bind q kill-session 74 | bind Q kill-server 75 | 76 | # Smart pane switching with awareness of vim splits 77 | # See: https://github.com/christoomey/vim-tmux-navigator 78 | is_vim='echo "#{pane_current_command}" | grep -iqE "(^|\/)g?(view|n?vim?x?)(diff)?$"' 79 | bind -n C-h if-shell "$is_vim" "send-keys C-h" "select-pane -L" 80 | bind -n C-j if-shell "$is_vim" "send-keys C-j" "select-pane -D" 81 | bind -n C-k if-shell "$is_vim" "send-keys C-k" "select-pane -U" 82 | bind -n C-l if-shell "$is_vim" "send-keys C-l" "select-pane -R" 83 | bind -n C-\\ if-shell "$is_vim" "send-keys C-\\" "select-pane -l" 84 | bind C-w last-pane 85 | bind C-n next-window 86 | bind C-p previous-window 87 | 88 | # break pane into a window 89 | bind = select-layout even-vertical 90 | bind + select-layout even-horizontal 91 | bind - break-pane 92 | bind _ join-pane 93 | 94 | # reload config without killing server 95 | bind r source-file $DOTFILES/config/tmux/config \; display-message " Config reloaded..". 96 | bind ^r refresh-client 97 | 98 | 99 | ######################################## 100 | # Copy mode # 101 | ######################################## 102 | 103 | bind Enter copy-mode # enter copy mode 104 | bind b list-buffers # list paster buffers 105 | bind B choose-buffer # choose which buffer to paste from 106 | bind p paste-buffer # paste from the top paste buffer 107 | bind P run "xclip -selection clipboard -o | tmux load-buffer - ; tmux paste-buffer" 108 | 109 | bind -T copy-mode-vi v send-keys -X begin-selection 110 | bind -T copy-mode-vi C-v send-keys -X rectangle-toggle 111 | bind -T copy-mode-vi Escape send-keys -X cancel 112 | bind -T copy-mode-vi C-g send-keys -X cancel 113 | bind -T copy-mode-vi H send-keys -X start-of-line 114 | bind -T copy-mode-vi L send-keys -X end-of-line 115 | 116 | 117 | ######################################## 118 | # Local config # 119 | ######################################## 120 | set -g @open-editor 'C-e' 121 | set -g @open-S 'https://www.duckduckgo.com/' 122 | 123 | source $TMUX_HOME/extraInit 124 | if '[ -f ~/.tmux.conf ]' 'source ~/.tmux.conf' 125 | -------------------------------------------------------------------------------- /config/tmux/swap-pane.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | CONF="$TMUX_PLUGINS_PATH/lastpane" 3 | swap() { tmux swap-pane -s"$1" -t"$2"; } 4 | 5 | target= 6 | case $1 in 7 | up) target="U" ;; 8 | down) target="D" ;; 9 | left) target="L" ;; 10 | right) target="R" ;; 11 | master) target="M" ;; 12 | *) exit 1 ;; 13 | esac 14 | 15 | src_pane=$(tmux display-message -p "#P") 16 | tmux select-pane -${target} 17 | 18 | dst_pane=$(tmux display-message -p "#P") 19 | tmux select-pane -${src_pane} 20 | 21 | [[ "$target" == M ]] && dst_pane=0 22 | swap "$src_pane" "$dst_pane" 23 | tmux select-pane -t"$dst_pane" 24 | -------------------------------------------------------------------------------- /config/tmux/tmux.conf: -------------------------------------------------------------------------------- 1 | # -- THEME ------------------------------- 2 | 3 | # The statusbar 4 | set -g status-position bottom 5 | set -g status-justify centre 6 | set -g status-bg default 7 | set -g status-fg colour15 8 | set -g status-interval 10 9 | # set -g status-attr dim 10 | # set -g status-left '#[fg=colour236]_________________________' 11 | set -g status-left '#{prefix_highlight}#[fg=colour236]|―――――――――――――――――――|' 12 | # set -g status-left "#[fg=colour236]#{prefix_highlight} #[fg=colour5] #S #[fg=colour236]──" 13 | # set -g status-right '#[fg=colour236]_________________________' 14 | set -g status-right '#[fg=colour236]|―――――――――――――――――――――――――|' 15 | set -g status-right-length 30 16 | set -g status-left-length 30 17 | 18 | # The messages 19 | set -g message-style fg=magenta,bg=colour236 20 | set -g message-command-style fg=blue,bg=black 21 | 22 | # loud or quiet? 23 | set-option -g visual-activity off 24 | set-option -g visual-bell off 25 | set-option -g visual-silence off 26 | set-window-option -g monitor-activity on 27 | set-option -g bell-action none 28 | 29 | # The modes 30 | setw -g clock-mode-colour colour135 31 | # setw -g mode-attr bold 32 | # setw -g mode-fg colour196 33 | # setw -g mode-bg colour238 34 | 35 | # The panes 36 | set -g pane-border-style fg=colour235 37 | set -g pane-active-border-style fg=colour5 38 | 39 | # setw -g window-status-current-fg colour2 40 | # setw -g window-status-current-bg default 41 | # setw -g window-status-current-attr none 42 | # setw -g window-status-current-format ' #W ' 43 | 44 | # setw -g window-status-fg colour236 45 | # setw -g window-status-bg default 46 | # setw -g window-status-attr none 47 | # setw -g window-status-format '#[fg=colour8] #I #[fg=default]#W ' 48 | setw -g window-status-format ' #W ' 49 | 50 | # setw -g window-status-activity-bg default 51 | # setw -g window-status-activity-fg colour240 52 | # setw -g window-status-activity-attr none 53 | 54 | # setw -g window-status-bell-attr bold 55 | # setw -g window-status-bell-fg colour255 56 | # setw -g window-status-bell-bg colour1 57 | 58 | 59 | # -- PLUGINS ----------------------------- 60 | 61 | # tmux-prefix-highlight 62 | set -g @prefix_highlight_empty_prompt '-----' 63 | set -g @prefix_highlight_prefix_prompt ' C^c #[bg=colour8]' 64 | set -g @prefix_highlight_show_copy_mode 'on' 65 | -------------------------------------------------------------------------------- /config/tree-sitter/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "parser-directories": [ 3 | "/home/jake/.tree-sitter" 4 | ], 5 | "theme": { 6 | "function": 26, 7 | "string": 28, 8 | "constant": 94, 9 | "punctuation.bracket": 239, 10 | "constant.builtin": { 11 | "color": 94, 12 | "bold": true 13 | }, 14 | "punctuation.delimiter": 239, 15 | "property": 124, 16 | "number": { 17 | "color": 94, 18 | "bold": true 19 | }, 20 | "string.special": 30, 21 | "operator": { 22 | "bold": true, 23 | "color": 239 24 | }, 25 | "type": 23, 26 | "comment": { 27 | "color": 245, 28 | "italic": true 29 | }, 30 | "constructor": 136, 31 | "type.builtin": { 32 | "color": 23, 33 | "bold": true 34 | }, 35 | "variable.parameter": { 36 | "underline": true 37 | }, 38 | "keyword": 56, 39 | "embedded": null, 40 | "attribute": { 41 | "italic": true, 42 | "color": 124 43 | }, 44 | "function.builtin": { 45 | "bold": true, 46 | "color": 26 47 | }, 48 | "variable.builtin": { 49 | "bold": true 50 | }, 51 | "module": 136, 52 | "tag": 18 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /config/vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "window.menuBarVisibility": "hidden", 3 | "keyboard.dispatch": "keyCode", 4 | "editor.lineNumbers": "relative" , 5 | "editor.minimap.enable": false, 6 | "update.mode": "none", 7 | "editor.scrollbar.horizontal": "hidden", 8 | "editor.scrollbar.vertical": "hidden", 9 | "workbench.colorTheme": "Nord", 10 | "workbench.startupEditor": "newUntitledFile" 11 | 12 | "editor.tabSize": 4, 13 | "editor.formatOnSave": true, 14 | "editor.autoIndent": "full", 15 | "editor.quickSuggestions": true, 16 | "editor.mouseWheelZoom": true, 17 | "editor.semanticHighlighting.enabled": true, 18 | "editor.fontLigatures": true, 19 | "editor.wordBasedSuggestions": true, 20 | "editor.suggest.localityBonus": true, 21 | "editor.snippetSuggestions": "bottom", 22 | "editor.quickSuggestionsDelay": 0, 23 | "files.exclude": { 24 | "**/.git": true, 25 | "**/.DS_Store": true 26 | }, 27 | "editor.rulers": [ 28 | { "column": 80, "color": "#ffffff10" }, 29 | { "column": 120, "color": "#6666668e" } 30 | ], 31 | "editor.codeActionsOnSave": { 32 | "source.fixAll": true 33 | }, 34 | "prettier.tabWidth": 4, 35 | "prettier.useTabs": true 36 | } 37 | -------------------------------------------------------------------------------- /config/vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | // See https://go.microsoft.com/fwlink/? LinkId=733558 3 | // for the documentation about the tasks.json format 4 | "version": "2.0.0", 5 | "tasks": [] 6 | } 7 | -------------------------------------------------------------------------------- /config/waybar/config: -------------------------------------------------------------------------------- 1 | { 2 | "layer": "top", 3 | "output": ["eDP-1"], 4 | "modules-left": ["sway/workspaces", "sway/mode"], 5 | "modules-center": ["network"], 6 | "modules-right": ["pulseaudio", "battery", "clock"], 7 | "sway/workspaces": { 8 | "disable-scroll": true 9 | }, 10 | "mpd": { 11 | "tooltip": false, 12 | "format": "{stateIcon} {artist} - {album} - {title} ({elapsedTime:%M:%S}/{totalTime:%M:%S})", 13 | "format-disconnected": "ﳌ", 14 | "format-stopped": "", 15 | "state-icons": { 16 | "playing": "", 17 | "paused": "" 18 | } 19 | }, 20 | "pulseaudio": { 21 | "tooltip": false, 22 | "scroll-step": 5, 23 | "format": "{icon} {format_source} {volume}%", 24 | "format-bluetooth": "{icon} {format_source} {volume}% ", 25 | "format-bluetooth-muted": "{icon}  {format_source}", 26 | "format-muted": "🔇{format_source}", 27 | "format-source": " {volume}%", 28 | "format-source-muted": "", 29 | "format-icons": { 30 | "headphones": "", 31 | "handsfree": "", 32 | "headset": "", 33 | "phone": "", 34 | "portable": "", 35 | "car": "", 36 | "default": ["奄", "奔", "墳"] 37 | } 38 | }, 39 | "network": { 40 | "tooltip": false, 41 | "format-wifi": " {essid} {ipaddr}", 42 | "format-ethernet": " {ipaddr}" 43 | }, 44 | "cpu": { 45 | "tooltip": false, 46 | "format": " {}%" 47 | }, 48 | "memory": { 49 | "tooltip": false, 50 | "format": " {}%" 51 | }, 52 | "battery": { 53 | "states": { 54 | "warning": 30, 55 | "critical": 15 56 | }, 57 | "format": "{icon} {capacity}%", 58 | "format-icons": ["", "", "", "", ""], 59 | "max-length": 25 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /config/waybar/style.css: -------------------------------------------------------------------------------- 1 | * { 2 | font-family: monospace; 3 | font-size: 12px; 4 | min-height: 16px; 5 | } 6 | 7 | window#waybar { 8 | border-bottom: 2px solid @bgalt; 9 | background-color: @background; 10 | } 11 | 12 | window#waybar.hidden { 13 | opacity: 0.2; 14 | } 15 | 16 | #workspaces, #mode, #window, #mpd, #network, #pulseaudio, #temperature, #cpu, #memory, #battery, #clock { 17 | margin: 4px 3px; 18 | margin-top: 0; 19 | margin-bottom: 2px; 20 | padding: 0 8px; 21 | padding-top: 0; 22 | transition: none; 23 | color: @fgalt; 24 | } 25 | 26 | #window { 27 | color: transparent; 28 | background: transparent; 29 | } 30 | 31 | #workspaces { 32 | /* as the leftmost element, this needs extra padding */ 33 | padding: 0; 34 | } 35 | 36 | #workspaces button { 37 | transition: none; 38 | color: @foreground; 39 | margin: 0 4px; 40 | padding: 0 6px; 41 | background: transparent; 42 | font-size: 16px; 43 | } 44 | 45 | #workspaces button.focused { 46 | color: @blue; 47 | } 48 | 49 | #workspaces button:hover { 50 | transition: none; 51 | box-shadow: inherit; 52 | text-shadow: inherit; 53 | color: @buttonhover; 54 | } 55 | 56 | #clock { 57 | /* As the last element, this needs right margin */ 58 | padding-right: 16px; 59 | } 60 | -------------------------------------------------------------------------------- /config/xdg/user-dirs.dirs: -------------------------------------------------------------------------------- 1 | # This file is written by xdg-user-dirs-update 2 | # If you want to change or add directories, just edit the line you're 3 | # interested in. All local changes will be retained on the next run. 4 | # Format is XDG_xxx_DIR="$HOME/yyy", where yyy is a shell-escaped 5 | # homedir-relative path, or XDG_xxx_DIR="/yyy", where /yyy is an 6 | # absolute path. No other format is supported. 7 | # 8 | 9 | XDG_DESKTOP_DIR="$HOME/" 10 | XDG_DOWNLOAD_DIR="$HOME/" 11 | XDG_TEMPLATES_DIR="$HOME/" 12 | XDG_PUBLICSHARE_DIR="$HOME/" 13 | XDG_DOCUMENTS_DIR="$HOME/" 14 | XDG_MUSIC_DIR="$HOME/" 15 | XDG_PICTURES_DIR="$HOME/pics/" 16 | XDG_VIDEOS_DIR="$HOME/" 17 | -------------------------------------------------------------------------------- /default.nix: -------------------------------------------------------------------------------- 1 | { inputs, config, lib, pkgs, ... }: 2 | 3 | with lib; 4 | with lib.my; 5 | with inputs; { 6 | imports = 7 | [ 8 | home-manager.nixosModules.home-manager 9 | simple-nixos-mailserver.nixosModules.mailserver 10 | ] 11 | ++ (mapModulesRec' (toString ./modules) import); 12 | 13 | # Common config for all nixos machines to ensure the flake operates soundly 14 | environment.variables = { 15 | DOTFILES = dotFilesDir; 16 | NIXPKGS_ALLOW_UNFREE = "1"; 17 | }; 18 | 19 | nix = { 20 | package = pkgs.nixFlakes; 21 | extraOptions = '' 22 | experimental-features = nix-command flakes 23 | ''; 24 | 25 | nixPath = (mapAttrsToList (n: v: "${n}=${v}") inputs) ++ [ 26 | "nixpkgs-overlays=${dotFilesDir}/overlays" 27 | "dotfiles=${dotFilesDir}" 28 | ]; 29 | 30 | settings.substituters = [ 31 | "https://cache.nixos.org/" 32 | "https://nix-community.cachix.org" 33 | ]; 34 | 35 | settings.trusted-public-keys = [ 36 | "nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs=" 37 | ]; 38 | 39 | # TODO: I had conflicting values here, 40 | # so had to update. Makes sense -- but what do each of these do? 41 | registry = { 42 | nixos.flake = nixpkgs; 43 | nixpkgs.flake = nixpkgs; # nixpkgs-unstable; 44 | }; 45 | 46 | settings.sandbox = true; 47 | settings.trusted-users = [ username ]; 48 | gc.automatic = false; # never automatically garbage collect 49 | }; 50 | system.configurationRevision = mkIf (self ? rev) self.rev; 51 | system.stateVersion = "20.09"; 52 | 53 | # allow users to store fonts easily 54 | fonts.fontDir.enable = true; 55 | 56 | ## Some reasonable, global defaults 57 | # This is here to appease 'nix flake check' for generic hosts with no 58 | # hardware-configuration.nix or fileSystem config. 59 | fileSystems."/".device = mkDefault "/dev/disk/by-label/nixos"; 60 | 61 | # Use the latest kernel 62 | # boot.kernelPackages = pkgs.linuxPackages_latest; 63 | 64 | boot.loader = { 65 | efi.canTouchEfiVariables = true; 66 | systemd-boot.configurationLimit = 10; 67 | systemd-boot.enable = mkDefault true; 68 | }; 69 | 70 | environment.systemPackages = with pkgs; [ 71 | coreutils 72 | wget 73 | unzip 74 | ]; 75 | } 76 | -------------------------------------------------------------------------------- /etc/test-screencast.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Test screensharing with Linux + Wayland + PipeWire 4 | # https://gitlab.gnome.org/-/snippets/19 5 | 6 | import re 7 | import signal 8 | import dbus 9 | from gi.repository import GLib 10 | from dbus.mainloop.glib import DBusGMainLoop 11 | 12 | import gi 13 | gi.require_version('Gst', '1.0') 14 | from gi.repository import GObject, Gst 15 | 16 | DBusGMainLoop(set_as_default=True) 17 | Gst.init(None) 18 | 19 | loop = GLib.MainLoop() 20 | 21 | bus = dbus.SessionBus() 22 | request_iface = 'org.freedesktop.portal.Request' 23 | screen_cast_iface = 'org.freedesktop.portal.ScreenCast' 24 | 25 | pipeline = None 26 | 27 | def terminate(): 28 | if pipeline is not None: 29 | self.player.set_state(Gst.State.NULL) 30 | loop.quit() 31 | 32 | request_token_counter = 0 33 | session_token_counter = 0 34 | sender_name = re.sub(r'\.', r'_', bus.get_unique_name()[1:]) 35 | 36 | def new_request_path(): 37 | global request_token_counter 38 | request_token_counter = request_token_counter + 1 39 | token = 'u%d'%request_token_counter 40 | path = '/org/freedesktop/portal/desktop/request/%s/%s'%(sender_name, token) 41 | return (path, token) 42 | 43 | def new_session_path(): 44 | global session_token_counter 45 | session_token_counter = session_token_counter + 1 46 | token = 'u%d'%session_token_counter 47 | path = '/org/freedesktop/portal/desktop/session/%s/%s'%(sender_name, token) 48 | return (path, token) 49 | 50 | def screen_cast_call(method, callback, *args, options={}): 51 | (request_path, request_token) = new_request_path() 52 | bus.add_signal_receiver(callback, 53 | 'Response', 54 | request_iface, 55 | 'org.freedesktop.portal.Desktop', 56 | request_path) 57 | options['handle_token'] = request_token 58 | method(*(args + (options, )), 59 | dbus_interface=screen_cast_iface) 60 | 61 | def on_gst_message(bus, message): 62 | type = message.type 63 | if type == Gst.MessageType.EOS or type == Gst.MessageType.ERROR: 64 | terminate() 65 | 66 | def play_pipewire_stream(node_id): 67 | empty_dict = dbus.Dictionary(signature="sv") 68 | fd_object = portal.OpenPipeWireRemote(session, empty_dict, 69 | dbus_interface=screen_cast_iface) 70 | fd = fd_object.take() 71 | pipeline = Gst.parse_launch('pipewiresrc fd=%d path=%u ! videoconvert ! xvimagesink'%(fd, node_id)) 72 | pipeline.set_state(Gst.State.PLAYING) 73 | pipeline.get_bus().connect('message', on_gst_message) 74 | 75 | def on_start_response(response, results): 76 | if response != 0: 77 | print("Failed to start: %s"%response) 78 | terminate() 79 | return 80 | 81 | print("streams:") 82 | for (node_id, stream_properties) in results['streams']: 83 | print("stream {}".format(node_id)) 84 | play_pipewire_stream(node_id) 85 | 86 | def on_select_sources_response(response, results): 87 | if response != 0: 88 | print("Failed to select sources: %d"%response) 89 | terminate() 90 | return 91 | 92 | print("sources selected") 93 | global session 94 | screen_cast_call(portal.Start, on_start_response, 95 | session, '') 96 | 97 | def on_create_session_response(response, results): 98 | if response != 0: 99 | print("Failed to create session: %d"%response) 100 | terminate() 101 | return 102 | 103 | global session 104 | session = results['session_handle'] 105 | print("session %s created"%session) 106 | 107 | screen_cast_call(portal.SelectSources, on_select_sources_response, 108 | session, 109 | options={ 'multiple': False, 110 | 'types': dbus.UInt32(1|2) }) 111 | 112 | portal = bus.get_object('org.freedesktop.portal.Desktop', 113 | '/org/freedesktop/portal/desktop') 114 | 115 | (session_path, session_token) = new_session_path() 116 | screen_cast_call(portal.CreateSession, on_create_session_response, 117 | options={ 'session_handle_token': session_token }) 118 | 119 | try: 120 | loop.run() 121 | except KeyboardInterrupt: 122 | terminate() 123 | -------------------------------------------------------------------------------- /flake.nix: -------------------------------------------------------------------------------- 1 | # flake.nix --- the heart of my dotfiles # 2 | # Author: Henrik Lissner ++ Jake Chvatal 3 | # URL: https://github.com/jakeisnt/nixcfg 4 | # License: MIT 5 | 6 | { 7 | description = "jakeisnt's nix configuration"; 8 | 9 | inputs = { 10 | # Two inputs so I can track them separately at different rates. 11 | nixpkgs.url = "nixpkgs/nixos-24.05"; 12 | nixpkgs-unstable.url = "nixpkgs/master"; 13 | 14 | home-manager = { 15 | url = "github:nix-community/home-manager/release-24.05"; 16 | inputs.nixpkgs.follows = "nixpkgs"; 17 | }; 18 | 19 | nur = { 20 | url = "github:nix-community/NUR/master"; 21 | # inputs.nixpkgs.follows = "nixpkgs"; 22 | }; 23 | 24 | emacs-overlay = { 25 | url = "github:nix-community/emacs-overlay"; 26 | inputs.nixpkgs.follows = "nixpkgs"; 27 | }; 28 | 29 | nixos-hardware = { 30 | url = "github:nixos/nixos-hardware"; 31 | # inputs.nixpkgs.follows = "nixpkgs"; 32 | }; 33 | 34 | simple-nixos-mailserver = { 35 | url = "gitlab:simple-nixos-mailserver/nixos-mailserver"; 36 | inputs.nixpkgs.follows = "nixpkgs"; 37 | }; 38 | 39 | spicetify-nix = { 40 | url = "github:jakeisnt/spicetify-nix"; 41 | inputs.nixpkgs.follows = "nixpkgs"; 42 | }; 43 | 44 | nix-remarkable = { 45 | url = "github:siraben/nix-remarkable"; 46 | inputs.nixpkgs.follows = "nixpkgs"; 47 | }; 48 | 49 | # Pin Doom Emacs version 50 | doom-emacs = { 51 | url = "github:doomemacs/doomemacs/master"; 52 | flake = false; 53 | # inputs.nixpkgs.follows = "nixpkgs"; 54 | }; 55 | 56 | # Used for compatible `nix build` commands if the system doesn't yet have flakes enabled` 57 | flake-compat = { 58 | url = github:edolstra/flake-compat; 59 | flake = false; 60 | # inputs.nixpkgs.follows = "nixpkgs"; 61 | }; 62 | }; 63 | 64 | outputs = inputs@{ self, nixpkgs, nixpkgs-unstable, spicetify-nix, doom-emacs, ... }: 65 | let 66 | inherit (lib) attrValues; 67 | inherit (lib.my) mapModules mapModulesRec mapHosts; 68 | 69 | system = "x86_64-linux"; 70 | 71 | mkPkgs = pkgs: extraOverlays: 72 | import pkgs { 73 | inherit system; 74 | config = { 75 | android_sdk.accept_license = true; 76 | allowUnfree = true; 77 | }; 78 | overlays = extraOverlays ++ (attrValues self.overlays); 79 | }; 80 | 81 | uPkgs = mkPkgs nixpkgs-unstable [ 82 | self.overlay 83 | (self: super: { doomEmacsRevision = doom-emacs.rev; }) 84 | ]; 85 | 86 | pkgs = mkPkgs nixpkgs [ 87 | self.overlay 88 | (self: super: { 89 | doomEmacsRevision = doom-emacs.rev; 90 | unstable = uPkgs; 91 | }) 92 | ]; 93 | 94 | 95 | lib = nixpkgs.lib.extend ( 96 | self: super: { 97 | my = 98 | import ./lib { 99 | inherit pkgs inputs; 100 | lib = self; 101 | }; 102 | } 103 | ); 104 | in 105 | { 106 | overlay = final: prev: { 107 | unstable = uPkgs; 108 | my = self.packages."${system}"; 109 | extras = { inherit spicetify-nix; }; 110 | }; 111 | 112 | overlays = mapModules ./overlays import; 113 | 114 | packages."${system}" = mapModules ./packages (p: pkgs.callPackage p {}); 115 | 116 | nixosModules = { 117 | dotfiles = import ./.; 118 | } // mapModulesRec ./modules import; 119 | 120 | nixosConfigurations = mapHosts ./hosts { inherit system; }; 121 | 122 | devShell."${system}" = pkgs.mkShell { 123 | name = "nixos-config"; 124 | }; 125 | 126 | templates = { 127 | full = { 128 | path = ./.; 129 | description = "A grossly incandescent nixos config"; 130 | }; 131 | flake = { 132 | path = ./templates/flake; 133 | description = "A simple Nix flake starter project."; 134 | }; 135 | }; 136 | 137 | defaultTemplate = self.templates.flake; 138 | 139 | defaultApp."${system}" = { 140 | type = "app"; 141 | program = ./bin/hey; 142 | }; 143 | }; 144 | } 145 | -------------------------------------------------------------------------------- /hosts/README.org: -------------------------------------------------------------------------------- 1 | #+TITLE: Host Configurations 2 | 3 | * Systems 4 | + kuro 5 | + shiro 6 | + ao 7 | + aka 8 | + aijiro 9 | + unlisted: 100+ linodes, 7 VMs 10 | -------------------------------------------------------------------------------- /hosts/iso-install/default.nix: -------------------------------------------------------------------------------- 1 | # Minimal config built to run off of a live USB. 2 | # Provides a TUI with configured emacs, git and fish. 3 | # Used for bootstrapping other configurations! 4 | 5 | { config, lib, pkgs, ... }: 6 | let hostname = "usb"; 7 | in 8 | 9 | { 10 | imports = [ 11 | ../personal.nix 12 | 13 | ]; 14 | 15 | isoImage = { 16 | # if i don't want this to be an install disk: 17 | # makeEfiBootable = true; 18 | # makeUsbBootable = true; 19 | volumeID = lib.mkForce hostname; 20 | isoName = lib.mkForce "${hostname}.iso"; 21 | }; 22 | 23 | networking = { 24 | networkmanager.enable = true; 25 | wireless.enable = lib.mkForce false; 26 | }; 27 | 28 | security.polkit.extraConfig = '' 29 | polkit.addRule(function(action, subject) { 30 | if (subject.isInGroup("wheel")) { 31 | return polkit.Result.YES; 32 | } 33 | }); 34 | ''; 35 | 36 | modules = { 37 | editors = { 38 | default = "emacs"; 39 | emacs.enable = true; 40 | }; 41 | shell = { 42 | git.enable = true; 43 | file.enable = true; 44 | fish.enable = true; 45 | }; 46 | }; 47 | } 48 | -------------------------------------------------------------------------------- /hosts/personal.nix: -------------------------------------------------------------------------------- 1 | { config, lib, pkgs, inputs, ... }: 2 | 3 | with lib; 4 | with lib.my; 5 | { 6 | time.timeZone = mkDefault "America/New_York"; 7 | i18n.defaultLocale = mkDefault "en_US.UTF-8"; 8 | 9 | console = { 10 | earlySetup = true; 11 | keyMap = "us"; 12 | }; 13 | 14 | # Only allow user creation through Nix 15 | users.mutableUsers = false; 16 | 17 | users.users.root.password = "jake"; 18 | users.users.${username}.password = "jake"; 19 | 20 | user.extraGroups = [ 21 | "networkmanager" 22 | ]; 23 | 24 | location = (if config.time.timeZone == "America/Los_Angeles" then { 25 | latitude = 43.70011; 26 | longitude = -79.4163; 27 | } else if config.time.timeZone == "Europe/Stockholm" then { 28 | latitude = 55.88; 29 | longitude = 12.5; 30 | } else 31 | { }); 32 | } 33 | -------------------------------------------------------------------------------- /hosts/vultr/default.nix: -------------------------------------------------------------------------------- 1 | { config, pkgs, lib, ... }: 2 | 3 | # Deprecated: 4 | # This was a custom managed Vultr server. 5 | # It's no longer operating - I've moved to trusting cloud providers and other hosted services. 6 | # I might revisit this in the future when I have a permanent home and physical server infrastructure. 7 | 8 | with lib.my; { 9 | imports = [ ./hardware-configuration.nix ../personal.nix ]; 10 | 11 | networking.hostName = "vultr"; 12 | 13 | modules = { 14 | # just use nano 15 | # editors = { 16 | # default = "nvim"; 17 | # vim.enable = true; 18 | # }; 19 | shell = { 20 | git.enable = true; 21 | file.enable = true; 22 | fish.enable = true; # TODO need a simple shell to use without rust things, but not zsh - too heavy 23 | gnupg.enable = true; 24 | direnv.enable = true; 25 | }; 26 | services = { 27 | acme.enable = true; 28 | mailserver.enable = false; 29 | ssh.enable = true; 30 | matrix = { 31 | enable = false; 32 | registration = false; 33 | element = false; 34 | }; 35 | bitwarden = { 36 | enable = false; 37 | registration = false; 38 | mail = false; 39 | }; 40 | cal.enable = false; 41 | nginx.enable = true; 42 | }; 43 | }; 44 | 45 | boot.loader.systemd-boot.enable = false; 46 | 47 | boot.loader.grub = { 48 | enable = true; 49 | version = 2; 50 | device = "/dev/vda"; 51 | }; 52 | 53 | networking = { 54 | domain = "isnt.online"; 55 | # The ports are configured in their respective services, 56 | # but the system should individually decide whether to enable the firewall 57 | firewall.enable = true; 58 | 59 | # Enable the OpenSSH daemon. 60 | useDHCP = false; 61 | interfaces.ens3.useDHCP = true; 62 | }; 63 | 64 | # isntweb-home.enable = true; 65 | services.nginx.virtualHosts = { 66 | "isnt.online" = { 67 | forceSSL = true; 68 | enableACME = true; 69 | locations = { 70 | "/" = { 71 | proxyPass = "http://127.0.0.1:6200/"; 72 | proxyWebsockets = true; 73 | }; 74 | }; 75 | }; 76 | }; 77 | } 78 | -------------------------------------------------------------------------------- /hosts/vultr/hardware-configuration.nix: -------------------------------------------------------------------------------- 1 | { config, lib, pkgs, modulesPath, ... }: 2 | 3 | { 4 | imports = 5 | [ (modulesPath + "/profiles/qemu-guest.nix") 6 | ]; 7 | 8 | boot.initrd.availableKernelModules = [ "ata_piix" "uhci_hcd" "virtio_pci" "sr_mod" "virtio_blk" ]; 9 | boot.initrd.kernelModules = [ ]; 10 | boot.kernelModules = [ ]; 11 | boot.extraModulePackages = [ ]; 12 | 13 | fileSystems."/" = 14 | { device = "/dev/disk/by-label/nixos"; 15 | fsType = "btrfs"; 16 | }; 17 | 18 | swapDevices = [ ]; 19 | } 20 | -------------------------------------------------------------------------------- /hosts/work/default.nix: -------------------------------------------------------------------------------- 1 | # Framework laptop! 2 | { config, pkgs, inputs, lib, ... }: 3 | 4 | { 5 | imports = [./hardware-configuration.nix ../personal.nix]; 6 | 7 | networking.hostName = "work"; 8 | services.getty.autologinUser = "jake"; 9 | 10 | boot.loader = { 11 | systemd-boot.enable = true; 12 | efi.canTouchEfiVariables = true; 13 | }; 14 | 15 | time.timeZone = "Europe/Stockholm"; 16 | 17 | user.packages = with pkgs; [ 18 | ripgrep 19 | fzf 20 | nil 21 | ]; 22 | 23 | # automount storage devices 24 | services.devmon.enable = true; 25 | user.extraGroups = [ 26 | # unprivileged access to storage devices 27 | "storage" 28 | # for scanner 29 | "scanner" 30 | ]; 31 | 32 | networking = { 33 | extraHosts = lib.my.secrets.aliasDomains; 34 | useDHCP = false; 35 | interfaces.wlp170s0.useDHCP = true; 36 | networkmanager = { 37 | enable = true; 38 | wifi = { 39 | powersave = false; # no wifi lag 40 | }; 41 | }; 42 | }; 43 | 44 | services.libinput.enable = true; 45 | services.openssh.startWhenNeeded = true; 46 | services.gnome.gnome-keyring.enable = true; 47 | 48 | programs.ssh = { 49 | startAgent = true; 50 | forwardX11 = true; 51 | }; 52 | 53 | modules = { 54 | desktop.sway = { 55 | enable = true; 56 | fancy = true; 57 | scale = 1.0; 58 | }; 59 | browsers = { 60 | default = "firefox"; 61 | firefox.enable = true; 62 | # chrome.enable = true; 63 | }; 64 | term = { 65 | default = "alacritty"; 66 | alacritty.enable = true; 67 | foot.enable = true; 68 | }; 69 | editors = { 70 | default = "emacsclient -c"; 71 | vim.enable = true; 72 | emacs = { 73 | enable = false; 74 | }; 75 | }; 76 | hardware = { 77 | audio.enable = true; 78 | # bluetooth.enable = true; 79 | }; 80 | # messengers.email.enable = true; 81 | media = { 82 | ncmpcpp.enable = true; 83 | recording.enable = true; 84 | # TODO: These options require python2. 85 | # graphics.enable = true; 86 | # graphics.photo.enable = true; 87 | }; 88 | shell = { 89 | git.enable = true; 90 | file.enable = true; 91 | nushell.enable = true; 92 | gnupg = { 93 | enable = true; 94 | gui = true; 95 | cacheTTL = 60480000; 96 | }; 97 | direnv = { 98 | enable = true; 99 | preventGC = true; 100 | }; 101 | }; 102 | }; 103 | } 104 | -------------------------------------------------------------------------------- /hosts/work/hardware-configuration.nix: -------------------------------------------------------------------------------- 1 | # Do not modify this file! It was generated by ‘nixos-generate-config’ 2 | # and may be overwritten by future invocations. Please make changes 3 | # to /etc/nixos/configuration.nix instead. 4 | { config, lib, pkgs, modulesPath, ... }: 5 | 6 | { 7 | imports = 8 | [ (modulesPath + "/installer/scan/not-detected.nix") 9 | ]; 10 | 11 | # used to fix bluetooth 12 | # TODO: remove this when we figure out bluetooth 13 | # boot.kernelPackages = pkgs.linuxPackagesFor (pkgs.linux_latest.override { 14 | # argsOverride = rec { 15 | # src = pkgs.fetchurl { 16 | # url = "mirror://kernel/linux/kernel/v5.x/linux-${version}.tar.xz"; 17 | # sha256 = "1j0lnrsj5y2bsmmym8pjc5wk4wb11y336zr9gad1nmxcr0rwvz9j"; 18 | # }; 19 | # version = "5.15.1"; 20 | # modDirVersion = "5.15.1"; 21 | # }; 22 | # }); 23 | 24 | boot.kernelPackages = pkgs.linuxPackages_latest; 25 | 26 | hardware.bluetooth.enable = true; 27 | networking.networkmanager.enable = true; 28 | security.rtkit.enable = true; 29 | 30 | boot = { 31 | initrd = { 32 | availableKernelModules = [ "xhci_pci" "btusb" "thunderbolt" "nvme" "usb_storage" "sd_mod" ]; 33 | kernelModules = [ ]; 34 | }; 35 | 36 | kernelModules = [ "kvm-intel" ]; 37 | extraModulePackages = [ ]; 38 | 39 | kernelParams = [ 40 | # fix crashing on sleep behavior< save battery 41 | "mem_sleep_default=deep" 42 | ]; 43 | }; 44 | 45 | fileSystems."/" = 46 | { device = "/dev/disk/by-label/nixos"; 47 | fsType = "ext4"; 48 | }; 49 | 50 | fileSystems."/boot" = 51 | { device = "/dev/disk/by-label/boot"; 52 | fsType = "vfat"; 53 | }; 54 | 55 | swapDevices = 56 | [ { device = "/dev/disk/by-label/swap"; } 57 | ]; 58 | 59 | powerManagement.cpuFreqGovernor = lib.mkDefault "powersave"; 60 | hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; 61 | } 62 | -------------------------------------------------------------------------------- /hosts/xps/default.nix: -------------------------------------------------------------------------------- 1 | # My Dell XPS 9370: 4K monitor, malfunctioning screen and trackpad 2 | { config, pkgs, lib, ... }: 3 | 4 | with lib; 5 | with lib.my; 6 | { 7 | imports = [ ./hardware-configuration.nix ../personal.nix ]; 8 | 9 | networking.hostName = "xps"; 10 | 11 | users.users.jake.packages = with pkgs; [ thunderbird openssl ]; 12 | services.fwupd.enable = true; 13 | services.xserver.libinput.enable = true; 14 | 15 | programs.ssh = { 16 | startAgent = true; 17 | forwardX11 = true; 18 | }; 19 | 20 | services.openssh.startWhenNeeded = true; 21 | services.getty.autologinUser = "jake"; 22 | 23 | networking = { 24 | networkmanager = { 25 | enable = true; 26 | wifi = { 27 | powersave = false; # wifi beast mode 28 | }; 29 | }; 30 | }; 31 | 32 | modules = { 33 | theme.active = "stilla"; 34 | desktop.sway = { 35 | enable = true; 36 | fancy = true; 37 | disable-touch = true; 38 | scale = 2.0; 39 | }; 40 | browsers = { 41 | default = "firefox"; 42 | firefox.enable = true; 43 | }; 44 | media = { 45 | documents.enable = true; 46 | graphics = { 47 | vector.enable = false; 48 | sprites.enable = false; 49 | enable = true; 50 | }; 51 | recording.enable = true; 52 | spotify.enable = true; 53 | }; 54 | term = { 55 | default = "alacritty"; 56 | alacritty.enable = true; 57 | }; 58 | media = { 59 | mpv.enable = true; 60 | # ncmpcpp.enable = true; needs fixing, not used 61 | }; 62 | messengers = { 63 | rss.enable = true; 64 | matrix.enable = true; 65 | signal.enable = true; 66 | # email.enable = true; 67 | weechat.enable = true; 68 | }; 69 | editors = { 70 | default = "emacsclient -c"; 71 | emacs = { 72 | enable = true; 73 | daemon = true; 74 | }; 75 | vim.enable = false; 76 | vscode.enable = true; 77 | }; 78 | 79 | # TODO consider deleting 80 | dev = { 81 | node.enable = true; 82 | cc.enable = false; 83 | rust.enable = false; # should be project local 84 | }; 85 | 86 | hardware = { 87 | remarkable.enable = true; 88 | extraHosts = { 89 | enable = true; 90 | allowSocial = true; 91 | }; 92 | audio.enable = true; 93 | bluetooth.enable = true; 94 | scanner.enable = true; 95 | printer.enable = true; 96 | fs = { 97 | enable = true; 98 | ssd.enable = true; 99 | }; 100 | }; 101 | shell = { 102 | git.enable = true; 103 | gnupg = { 104 | enable = true; 105 | gui = true; 106 | cacheTTL = 60480000; 107 | }; 108 | direnv = { 109 | enable = true; 110 | preventGC = true; 111 | }; 112 | file.enable = true; 113 | fish.enable = true; 114 | }; 115 | services = { 116 | docker.enable = true; 117 | syncthing.enable = true; 118 | ssh.enable = true; 119 | backup.enable = true; 120 | dnsmasq.enable = true; 121 | }; 122 | }; 123 | } 124 | -------------------------------------------------------------------------------- /hosts/xps/hardware-configuration.nix: -------------------------------------------------------------------------------- 1 | { config, lib, pkgs, inputs, modulesPath, ... }: 2 | 3 | { 4 | imports = [ (modulesPath + "/installer/scan/not-detected.nix") ]; 5 | # https://github.com/yegortimoshenko/yegortimoshenko-flake/blob/master/profiles/hardware/dell-xps/9380/default.nix 6 | boot = { 7 | consoleLogLevel = 1; 8 | initrd = { 9 | availableKernelModules = 10 | [ "xhci_pci" "nvme" "rtsx_pci_sdmmc" "usb_storage" ]; 11 | kernelModules = [ "dm-snapshot" "i915" ]; 12 | checkJournalingFS = true; 13 | }; 14 | 15 | kernelModules = [ 16 | "kvm-intel" 17 | "dm-snapshot" 18 | "i915" 19 | "xboxdrv" 20 | "vboxnetadp" 21 | "vboxnetflt" 22 | 23 | # enable v4l2loopback to stream from camera 24 | "dslr-webcam" 25 | "v4l2loopback" 26 | ]; 27 | kernel.sysctl = { 28 | # enable ipv6 privacy extensions and prefer using temp addresses 29 | "net.ipv6.conf.all.use_tempaddr" = 2; 30 | "fs.inotify.max_user_instances" = 8192; 31 | "fs.inotify.max_user_watches" = 16834; 32 | }; 33 | kernelParams = [ 34 | # disable spectre and meltdown fixes 35 | "mitigations=off" 36 | # 4k video config 37 | "video=eDP-1:3840x2160@60" 38 | # fast quiet boot 39 | "quiet" 40 | "splash" 41 | "vga=current" 42 | "i915.fastboot=1" 43 | "loglevel=3" 44 | "systemd.show_status=auto" 45 | "udev.log_priority=3" 46 | # force power savings when possible 47 | "iwlwifi.power_save=Y" 48 | "pcie_aspm=force" 49 | # Optimize xps battery; causes framebuffer issues on some devices 50 | "i915.semaphores=1" 51 | "i915.enable_fbc=1" 52 | "i915.enable_psr=2" 53 | "i915.enable_rc6=7" 54 | "i915.lvds_downclock=1" 55 | "dev.i915.perf_stream_paranoid=0" 56 | 57 | # significant amount of usb issues without this 58 | "usbcore.autosuspend=-1" 59 | 60 | # v4l2lopback settings 61 | # "vl42loopback.exclusive_caps=1" 62 | # "v4l2loopback.card_label=GPhoto2Webcam" 63 | ]; 64 | 65 | extraModulePackages = [ 66 | pkgs.linuxKernel.packages.linux_5_10.virtualbox 67 | # Allows for the creation of virtual video devices generated by other applications 68 | # that act like real video devices 69 | (config.boot.kernelPackages.v4l2loopback.overrideAttrs ({ ... }: { 70 | src = pkgs.fetchFromGitHub { 71 | owner = "umlaeute"; 72 | repo = "v4l2loopback"; 73 | rev = "10b1c7e6bda4255fdfaa187ce2b3be13433416d2"; 74 | sha256 = "0xsn4yzj7lwdg0n7q3rnqpz07i9i011k2pwn06hasd45313zf8j2"; 75 | }; 76 | })) 77 | ]; 78 | 79 | # create video device 80 | extraModprobeConfig = '' 81 | alias dslr-webcam v4l2loopback 82 | options v4l2loopback exclusive_caps=1 card_label=\"GPhoto2 Webcam\" max_buffers=2 video_nr=8,9 83 | ''; 84 | }; 85 | 86 | # scanning 87 | hardware = { 88 | sane.enable = true; 89 | keyboard.zsa.enable = true; 90 | opengl = { 91 | enable = true; 92 | extraPackages = with pkgs; [ vaapiIntel vaapiVdpau libvdpau-va-gl ]; 93 | }; 94 | # enable machine check exception error logs 95 | # mcelog.enable = true; 96 | }; 97 | 98 | # CPU 99 | nix.maxJobs = lib.mkDefault 8; 100 | # "powersave" for the obvious 101 | powerManagement.cpuFreqGovernor = lib.mkDefault "performance"; 102 | hardware.cpu.intel.updateMicrocode = true; 103 | 104 | # Power management 105 | environment.systemPackages = [ pkgs.acpi ]; 106 | powerManagement.powertop.enable = true; 107 | # Monitor backlight control 108 | user.extraGroups = [ 109 | # ZSA keyboard support without root 110 | "plugdev" 111 | ]; 112 | 113 | fileSystems."/" = { 114 | device = "/dev/disk/by-label/nixos"; 115 | fsType = "ext4"; 116 | # keep file system from recording on file visit 117 | options = [ "noatime" ]; 118 | }; 119 | 120 | fileSystems."/home" = { 121 | device = "/dev/disk/by-label/home"; 122 | fsType = "ext4"; 123 | options = [ "noatime" ]; 124 | }; 125 | 126 | fileSystems."/boot" = { 127 | device = "/dev/disk/by-label/BOOT"; 128 | fsType = "vfat"; 129 | }; 130 | 131 | swapDevices = 132 | [{ device = "/dev/disk/by-uuid/786f7e92-74b5-4327-873a-89905a173f86"; }]; 133 | 134 | # Undervolt 135 | 136 | # Note that this is incredibly device specific. 137 | # If you're copying this config, there is no guarantee 138 | # that you'll be able to get away with these values. 139 | services.undervolt = { 140 | enable = true; 141 | coreOffset = -80; 142 | gpuOffset = -80; 143 | uncoreOffset = -80; 144 | }; 145 | 146 | services = { 147 | # https://github.com/NixOS/nixos-hardware/pull/127 148 | throttled.enable = lib.mkDefault true; 149 | # https://wiki.archlinux.org/index.php/Dell_XPS_13_(9370)#Thermal_Throttling 150 | thermald.enable = lib.mkDefault true; 151 | }; 152 | } 153 | -------------------------------------------------------------------------------- /keys/jake.asc: -------------------------------------------------------------------------------- 1 | -----BEGIN PGP PUBLIC KEY BLOCK----- 2 | 3 | xsFNBAAAAAABEACtB3BbMTx18grI1xxJ+mvjO8jzYoUIWh6l230DiXmQ7w7+3ZJp 4 | PEh21UphqZvm/k5FwsPU5Tb+vuwofEjPZfvx0ERL1XNvrFg/2rQmGl2ccsupclMz 5 | 2uxwP47APW5amJzhVRUejTOhv9Xo7kaZGqeh3L5hbyNSfC3Ci2LpZpV1nwuOgqmC 6 | m58d68G05YrW/LIM7zPVpWRa7/1Jyplu2AYViCB5z3jt1q1s7UP2oXAh5bH5QQ5v 7 | lqdsU9GEpn0HSF0CjQdGx7PDfyeocDoI0Dy0coUCWsMDrPqURnZWzQL0eARKkaYd 8 | LHcJ2N8I3dwU1z8I/8VJ+jxm9jmOxhuwlIluXdz6VUbh+eNOmEczVwjAtTdpiyBG 9 | 2ku0labQ4TMN0G0GdV3USxC4sEfBYfzF1m2NERRAm9ySkjxbLqQ5b/85mvLUtuJ4 10 | q5hMla6gGDRRKUAWGrDlVe8G3NACARqqDIQOE36Je/u/f3HjOFtczEf5pfAUW4Ky 11 | 7tyOJYzaxErPK/zc1g2qRdVtDclgdI1IHuSFywQPeAkz0l0vTqe60+RUZT0kyQXN 12 | zvZeEZ9U8ia8kO07HfxGAu3cdW7AJI/5eZv1LXI6Xa0GYN+9BSARz6RKHjNIM9wY 13 | AqGrDExgo56UOLrHqiDRRt6ZaqBPXzBdIp6D6HHuh7oggexINXoRvHaMWwARAQAB 14 | zSlyb290IChJbXBvcnRlZCBmcm9tIFNTSCkgPHJvb3RAbG9jYWxob3N0PsLBYgQT 15 | AQgAFgUCAAAAAAkQ3FAML6jGwAsCGw8CGQEAAEGWEAAodNwAx+N2CpzdHSo9nOQl 16 | O/bf3chrqukWc26e8Q/0TtlOhO6YzkWM+h5sBfmYrH7qCzjN9h8flryzewCJ9Utu 17 | rgTrt3MVoe6cM5Rw9GiTTTVXEc2z4ieVcvCdqr5XlPAfDqyN7x4naj9W/MzM3On9 18 | LnSXt5/PJxYsqVnUCDcVkN3UwgZBuI9qNZltC7Iii2YGU2j8S9dobWTvnhdc1A4S 19 | L5j04OCDT/biVeMZUAzLqLFotsjx0VHkzsZbczXnlW/qNX/SR0ltzGbOrwFp9tlG 20 | RZ6H+i7BTL/kT82xiypJftgiI97pj7sH5kzRajK9IoexVZ/ICzXFYuQ2K0+W1uGV 21 | vbk/CbzTf4a7vB2V3cAxj5B2vVhQ9M6lEt50QhOCV9KH/9aP2H1vEa5VzxX3XoKz 22 | 0OU/uecCYSudTLUX5d23ScGokLNJ0kLSz3AOiFIbYuCYyedIW6iu0OmZIW2EQLjv 23 | XxBDnlPJZ/jLzUNRN9bKXDWXWIBKWLFb48cBpkK+jDXJRDcpLe/1AbnZiFhl9KL+ 24 | 11C6r8ahLQUMHlbDGW6Tlm36QeOOrQn4WT5X5MwWL/X5z0ejux/L2uK6QDi+x5R5 25 | Y/645q/4gwsXa7hggYAX6wNY5WflNuOZcmmrIG36URAxx+iT/Csg4ATwvmzsVK2R 26 | 5XYg3Q7a/7mlpcSgH43xOQ== 27 | =snLB 28 | -----END PGP PUBLIC KEY BLOCK----- -------------------------------------------------------------------------------- /lib/attrs.nix: -------------------------------------------------------------------------------- 1 | { lib, ... }: 2 | 3 | with builtins; 4 | with lib; 5 | 6 | rec { 7 | # attrsToList 8 | attrsToList = attrs: 9 | mapAttrsToList (name: value: { inherit name value; }) attrs; 10 | 11 | # mapFilterAttrs :: 12 | # (name -> value -> bool) 13 | # (name -> value -> { name = any; value = any; }) 14 | # attrs 15 | mapFilterAttrs = pred: f: attrs: filterAttrs pred (mapAttrs' f attrs); 16 | 17 | # Generate an attribute set by mapping a function over a list of values. 18 | genAttrs' = values: f: listToAttrs (map f values); 19 | 20 | # anyAttrs :: (name -> value -> bool) attrs 21 | anyAttrs = pred: attrs: 22 | any (attr: pred attr.name attr.value) (attrsToList attrs); 23 | 24 | # countAttrs :: (name -> value -> bool) attrs 25 | countAttrs = pred: attrs: 26 | count (attr: pred attr.name attr.value) (attrsToList attrs); 27 | } 28 | -------------------------------------------------------------------------------- /lib/default.nix: -------------------------------------------------------------------------------- 1 | { inputs, lib, pkgs, ... }: 2 | 3 | let 4 | inherit (lib) makeExtensible attrValues foldr; 5 | inherit (modules) mapModules; 6 | 7 | modules = import ./modules.nix { 8 | inherit lib; 9 | self.attrs = import ./attrs.nix { inherit lib; self = {}; }; 10 | }; 11 | 12 | mylib = makeExtensible (self: 13 | with self; (mapModules ./. 14 | (file: import file { inherit self lib pkgs inputs modules; }))); 15 | 16 | in 17 | mylib.extend 18 | (self: super: 19 | foldr (a: b: a // b) {} (attrValues super)) 20 | -------------------------------------------------------------------------------- /lib/generators.nix: -------------------------------------------------------------------------------- 1 | { lib, pkgs, ... }: 2 | 3 | with builtins; 4 | with lib; 5 | { 6 | toCSSFile = file: 7 | let fileName = baseNameOf file; 8 | compiledStyles = 9 | pkgs.runCommand "compileScssFile" 10 | { buildInputs = [ sass ]; } '' 11 | mkdir "$out" 12 | scss --sourcekkmap=none \ 13 | --no-cache \ 14 | --style compressed \ 15 | --default-encoding utf-8 \ 16 | "${file}" \ 17 | >>"$out/${fileName}.css" 18 | ''; 19 | in "${compiledStyles}/${fileName}"; 20 | 21 | toFilteredImage = imageFile: options: 22 | let result = "result.png"; 23 | filteredImage = 24 | pkgs.runCommand "filterWallpaper" 25 | { buildInputs = [ pkgs.imagemagick ]; } '' 26 | mkdir "$out" 27 | convert ${options} ${imageFile} $out/${result} 28 | ''; 29 | in "${filteredImage}/${result}"; 30 | } 31 | -------------------------------------------------------------------------------- /lib/makeSimpleWebApp.nix: -------------------------------------------------------------------------------- 1 | { pkgs, ... }: 2 | 3 | # Source: https://github.com/bjornfor/nixos-config/blob/master/lib/default.nix 4 | 5 | { 6 | makeSimpleWebApp = { server, icon ? null, comment ? null 7 | , desktopName ? comment, categories ? null, browser ? "chromium-browser" }: 8 | pkgs.makeDesktopItem ({ 9 | name = server; 10 | exec = "${browser} --app=https://${server}/"; 11 | extraEntries = '' 12 | StartupWMClass=${server} 13 | ''; 14 | } // (if icon != null then { inherit icon; } else { }) 15 | // (if comment != null then { inherit comment; } else { }) 16 | // (if desktopName != null then { inherit desktopName; } else { }) 17 | // (if categories != null then { inherit categories; } else { })); 18 | } 19 | -------------------------------------------------------------------------------- /lib/modules.nix: -------------------------------------------------------------------------------- 1 | { self, lib, ... }: 2 | 3 | let 4 | inherit (builtins) attrValues readDir pathExists concatLists; 5 | inherit (lib) id mapAttrsToList filterAttrs hasPrefix hasSuffix nameValuePair removeSuffix; 6 | inherit (self.attrs) mapFilterAttrs; 7 | in 8 | rec { 9 | mapModules = dir: fn: 10 | mapFilterAttrs 11 | (n: v: 12 | v != null && 13 | !(hasPrefix "_" n)) 14 | (n: v: 15 | let path = "${toString dir}/${n}"; in 16 | if v == "directory" && pathExists "${path}/default.nix" 17 | then nameValuePair n (fn path) 18 | else if v == "regular" && 19 | n != "default.nix" && 20 | hasSuffix ".nix" n 21 | then nameValuePair (removeSuffix ".nix" n) (fn path) 22 | else nameValuePair "" null) 23 | (readDir dir); 24 | 25 | mapModules' = dir: fn: 26 | attrValues (mapModules dir fn); 27 | 28 | mapModulesRec = dir: fn: 29 | mapFilterAttrs 30 | (n: v: 31 | v != null && 32 | !(hasPrefix "_" n)) 33 | (n: v: 34 | let path = "${toString dir}/${n}"; in 35 | if v == "directory" 36 | then nameValuePair n (mapModulesRec path fn) 37 | else if v == "regular" && n != "default.nix" && hasSuffix ".nix" n 38 | then nameValuePair (removeSuffix ".nix" n) (fn path) 39 | else nameValuePair "" null) 40 | (readDir dir); 41 | 42 | mapModulesRec' = dir: fn: 43 | let 44 | dirs = 45 | mapAttrsToList 46 | (k: _: "${dir}/${k}") 47 | (filterAttrs 48 | (n: v: v == "directory" && !(hasPrefix "_" n)) 49 | (readDir dir)); 50 | files = attrValues (mapModules dir id); 51 | paths = files ++ concatLists (map (d: mapModulesRec' d id) dirs); 52 | in map fn paths; 53 | } 54 | -------------------------------------------------------------------------------- /lib/nixos.nix: -------------------------------------------------------------------------------- 1 | { inputs, lib, pkgs, ... }: 2 | 3 | with lib; 4 | with lib.my; 5 | let system = "x86_64-linux"; 6 | in { 7 | mkHost = path: attrs @ { system ? system, ... }: 8 | let hostname = (removeSuffix ".nix" (baseNameOf path)); in 9 | nixosSystem { 10 | inherit system; 11 | specialArgs = { inherit lib inputs; }; 12 | modules = [ 13 | { 14 | nixpkgs.pkgs = pkgs; 15 | networking.hostName = mkDefault hostname; 16 | } 17 | (filterAttrs (n: v: !elem n [ "system" ]) attrs) 18 | ../. 19 | (import path) 20 | ]; 21 | }; 22 | 23 | mapHosts = dir: attrs @ { system ? system, ... }: 24 | mapModules dir 25 | (hostPath: mkHost hostPath attrs); 26 | } 27 | -------------------------------------------------------------------------------- /lib/options.nix: -------------------------------------------------------------------------------- 1 | { lib, ... }: 2 | 3 | let 4 | inherit (lib) mkOption types; 5 | in 6 | rec { 7 | mkOpt = type: default: 8 | mkOption { inherit type default; }; 9 | 10 | mkOpt' = type: default: description: 11 | mkOption { inherit type default description; }; 12 | 13 | mkBoolOpt = default: mkOption { 14 | inherit default; 15 | type = types.bool; 16 | example = true; 17 | }; 18 | } 19 | -------------------------------------------------------------------------------- /lib/paths.nix: -------------------------------------------------------------------------------- 1 | { self, lib, modules, ... }: 2 | 3 | with builtins; 4 | with lib; rec { 5 | # ... 6 | dotFilesDir = toString ../.; 7 | modulesDir = "${dotFilesDir}/modules"; 8 | configDir = "${dotFilesDir}/config"; 9 | binDir = "${dotFilesDir}/bin"; 10 | themesDir = "${modulesDir}/themes"; 11 | username = "jake"; 12 | homeDir = "/home/${ 13 | let 14 | name = getEnv "USERNAME"; 15 | in 16 | if elem name [ username "root" ] then username 17 | else 18 | name 19 | }"; 20 | 21 | secrets = import ./secrets.nix { inherit lib; }; 22 | } 23 | -------------------------------------------------------------------------------- /lib/secrets.nix: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jakeisnt/nixcfg/e9230d4f90a855a290882a6e7862c593a114cf5e/lib/secrets.nix -------------------------------------------------------------------------------- /modules/browsers/brave.nix: -------------------------------------------------------------------------------- 1 | { options, config, lib, pkgs, ... }: 2 | 3 | with lib; 4 | with lib.my; 5 | let cfg = config.modules.browsers.brave; 6 | in { 7 | options.modules.browsers.brave = { enable = mkBoolOpt false; }; 8 | config = mkIf cfg.enable { 9 | modules.browsers.chromium-help.enable = true; 10 | user.packages = with pkgs; [ brave ]; 11 | }; 12 | } 13 | -------------------------------------------------------------------------------- /modules/browsers/chrome.nix: -------------------------------------------------------------------------------- 1 | { options, config, lib, pkgs, ... }: 2 | 3 | with lib; 4 | with lib.my; 5 | let cfg = config.modules.browsers.chrome; 6 | chrome = pkgs.google-chrome; 7 | chrome-improvin = pkgs.writeShellScriptBin "chrome-improvin" '' 8 | exec ${chrome}/bin/google-chrome-unstable --profile-directory="Profile 2" & 9 | ''; 10 | chrome-default = pkgs.writeShellScriptBin "chrome-default" '' 11 | exec ${chrome}/bin/google-chrome-unstable --profile-directory="Default" & 12 | ''; 13 | in { 14 | options.modules.browsers.chrome = { enable = mkBoolOpt false; }; 15 | config = mkIf cfg.enable { 16 | modules.browsers.chromium-help.enable = true; 17 | # The profiles here correspond to profiles created dynamically when opening Chrome and signing in. 18 | user.packages = with pkgs; [ 19 | chrome 20 | chrome-improvin 21 | chrome-default 22 | (makeDesktopItem { 23 | name = "chrome-improvin"; 24 | desktopName = "Chrome (Improvin)"; 25 | genericName = "Open a Chrome window to the Improvin workspace"; 26 | icon = "google-chrome-unstable"; 27 | exec = "${chrome-improvin}/bin/chrome-improvin"; 28 | categories = ["Network"]; 29 | }) 30 | (makeDesktopItem { 31 | name = "chrome-default"; 32 | desktopName = "Chrome (Default)"; 33 | genericName = "Open a Chrome window to the default workspace"; 34 | icon = "google-chrome-unstable"; 35 | exec = "${chrome-default}/bin/chrome-default"; 36 | categories = ["Network"]; 37 | }) 38 | ]; 39 | }; 40 | } 41 | -------------------------------------------------------------------------------- /modules/browsers/chromium-help.nix: -------------------------------------------------------------------------------- 1 | { config, lib, pkgs, ... }: 2 | 3 | # settings for all chromium browsers. 4 | 5 | with lib; 6 | with lib.my; 7 | let cfg = config.modules.browsers.chromium-help; 8 | in { 9 | options.modules.browsers.chromium-help = { 10 | enable = mkBoolOpt false; 11 | }; 12 | 13 | config = mkIf cfg.enable { 14 | # TODO: Enable wayland for chromium. Currently this is a saved browser setting, but it might not carry over. 15 | programs.chromium = { 16 | enable = true; 17 | # TODO: change to something more secure than google 18 | defaultSearchProviderSearchURL = 19 | "https://encrypted.google.com/search?q={searchTerms}&{google:RLZ}{google:originalQueryForSuggestion}{google:assistedQueryStats}{google:searchFieldtrialParameter}{google:searchClient}{google:sourceId}{google:instantExtendedEnabledParameter}ie={inputEncoding}"; 20 | defaultSearchProviderSuggestURL = 21 | "https://encrypted.google.com/complete/search?output=chrome&q={searchTerms}"; 22 | homepageLocation = "https://github.com"; 23 | extensions = [ 24 | "cjpalhdlnbpafiamejdnhcphjbkeiagm" # ublock origin 25 | "kkkjlfejijcjgjllecmnejhogpbcigdc" # org-capture 26 | "dbepggeogbaibhgnhhndojpepiihcmeb" # vimium 27 | "ddehdnnhjimbggeeenghijehnpakijod" # remove scrollbar 28 | # "ikdgincnppajmpmnhfheflannaiapmlm" # ampie: social interaction with webpages 29 | # ^ cool, but it always gets in the way! 30 | # custom css; 31 | # ::-webkit-scrollbar { 32 | # display: none; 33 | # } 34 | # must be added to Rescroller extension 35 | # also sign into lastfm scrobbler 36 | ]; 37 | 38 | extraOpts = { 39 | # I like having my information synced across browser sessions, 40 | # and I'm okay with surrendering some information to Google to do so. 41 | # The other settings may not work without managed browser control, though. 42 | 43 | # "BrowserSignin" = 0; 44 | # "SyncDisabled" = true; 45 | 46 | # Definitely want to turn off these though. 47 | "PasswordManagerEnabled" = false; 48 | "CloudReportingEnabled" = false; 49 | "SafeBrowsingEnabled" = false; 50 | "ReportSafeBrowsingData" = false; 51 | "AllowDinosaurEasterEgg" = false; # : ( 52 | "AllowOutdatedPlugins" = true; 53 | "DefaultBrowserSettingEnabled" = false; 54 | 55 | # voice assistant 56 | "VoiceInteractionContextEnabled" = false; 57 | "VoiceInteractionHotwordEnabled" = false; 58 | "VoiceInteractionQuickAnswersEnabled" = false; 59 | }; 60 | }; 61 | }; 62 | } 63 | -------------------------------------------------------------------------------- /modules/browsers/default.nix: -------------------------------------------------------------------------------- 1 | { options, config, lib, pkgs, ... }: 2 | 3 | with lib; 4 | with lib.my; 5 | let cfg = config.modules.browsers; 6 | in { 7 | options.modules.browsers = { 8 | default = mkOpt (with types; nullOr str) null; 9 | }; 10 | 11 | config = mkIf (cfg.default != null) { 12 | env.BROWSER = cfg.default; 13 | }; 14 | } 15 | -------------------------------------------------------------------------------- /modules/browsers/netsurf.nix: -------------------------------------------------------------------------------- 1 | { options, config, lib, pkgs, ... }: 2 | 3 | # a JavaScript-free web browser. 4 | with lib; 5 | with lib.my; 6 | let cfg = config.modules.browsers.netsurf; 7 | in { 8 | options.modules.browsers.netsurf = { enable = mkBoolOpt false; }; 9 | config = mkIf cfg.enable { user.packages = with pkgs; [ netsurf-browser ]; }; 10 | } 11 | -------------------------------------------------------------------------------- /modules/desktop/README.org: -------------------------------------------------------------------------------- 1 | #+TITLE: Desktop 2 | 3 | Utilities only relevant to the desktop (only usable as a GUI). 4 | -------------------------------------------------------------------------------- /modules/desktop/default.nix: -------------------------------------------------------------------------------- 1 | { config, options, lib, pkgs, ... }: 2 | 3 | with lib; 4 | with lib.my; 5 | let cfg = config.modules.desktop; 6 | in { 7 | config = mkIf config.modules.desktop.sway.enable { 8 | user.packages = with pkgs; [ feh ]; 9 | 10 | fonts = { 11 | fontDir.enable = true; 12 | enableGhostscriptFonts = true; 13 | packages = with pkgs; [ nerdfonts noto-fonts ]; 14 | }; 15 | 16 | ## Apps/Services 17 | # Try really hard to get QT to respect my GTK theme. 18 | env.GTK_DATA_PREFIX = [ "${config.system.path}" ]; 19 | env.QT_QPA_PLATFORMTHEME = "gtk2"; 20 | qt = { 21 | style = "gtk2"; 22 | platformTheme = "gtk2"; 23 | }; 24 | 25 | services.xserver.displayManager.sessionCommands = '' 26 | # GTK2_RC_FILES must be available to the display manager. 27 | export GTK2_RC_FILES="$XDG_CONFIG_HOME/gtk-2.0/gtkrc" 28 | ''; 29 | 30 | # set user dirs 31 | home.configFile = { 32 | "user-dirs.dirs".source = "${configDir}/xdg/user-dirs.dirs"; 33 | }; 34 | }; 35 | } 36 | -------------------------------------------------------------------------------- /modules/desktop/gnome.nix: -------------------------------------------------------------------------------- 1 | { options, config, lib, pkgs, ... }: 2 | 3 | with lib; 4 | with lib.my; 5 | let 6 | cfg = config.modules.desktop.gnome; 7 | colors = config.modules.theme.color; 8 | in { 9 | options.modules.desktop.gnome = { enable = mkBoolOpt false; }; 10 | 11 | config = mkIf cfg.enable { 12 | # security.pam.services.gdm.enableGnomeKeyring = true; 13 | # security.pam.services = with pkgs.gnome3; [{ 14 | # name = "gnome_keyring"; 15 | # text = '' 16 | # auth optional ${gnome_keyring}/lib/security/pam_gnome_keyring.so 17 | # session optional ${gnome_keyring}/lib/security/pam_gnome_keyring.so auto_start 18 | # password optional ${gnome_keyring}/lib/security/pam_gnome_keyring.so 19 | # ''; 20 | # }]; 21 | services = { 22 | # gnome keyring is not available anymore? 23 | # gnome3.gnome-keyring.enable = true; 24 | xserver = { 25 | enable = true; 26 | xkbOptions = "caps:swapescape"; 27 | displayManager.gdm.enable = true; 28 | # desktopManager.gnome3.enable = true; 29 | 30 | # todo: device-specific 31 | # monitorSection = '' 32 | # DisplaySize 508 285 33 | # ''; 34 | }; 35 | }; 36 | }; 37 | } 38 | -------------------------------------------------------------------------------- /modules/desktop/wayfire.nix: -------------------------------------------------------------------------------- 1 | { options, config, lib, pkgs, ... }: 2 | 3 | with lib; 4 | with lib.my; 5 | let 6 | cfg = config.modules.desktop.wayfire; 7 | colors = config.modules.theme.color; 8 | startwf = (pkgs.writeTextFile { 9 | name = "startwf"; 10 | destination = "/bin/startwf"; 11 | executable = true; 12 | text = '' 13 | #! ${pkgs.bash}/bin/bash 14 | 15 | # first import environment variables from the login manager 16 | systemctl --user import-environment 17 | # then start the service 18 | exec systemctl --user start wf.service 19 | ''; 20 | }); 21 | in { 22 | options.modules.desktop.wayfire = { enable = mkBoolOpt false; }; 23 | 24 | config = mkIf cfg.enable { 25 | modules.wayland.enable = true; 26 | modules.wayland.mako.enable = true; 27 | modules.wayland.swaylock.enable = true; 28 | modules.wayland.waybar.enable = true; 29 | modules.wayland.kanshi.enable = true; 30 | 31 | user.packages = with pkgs; [ wayfire ]; 32 | 33 | env.XDG_CURRENT_DESKTOP = "wayfire"; 34 | 35 | systemd.user.targets.wayfire-session = { 36 | enable = true; 37 | description = "Wayfire compositor session"; 38 | documentation = [ "man:systemd.special(7)" ]; 39 | 40 | bindsTo = [ "graphical-session.target" ]; 41 | wants = [ "graphical-session-pre.target" ]; 42 | after = [ "graphical-session-pre.target" ]; 43 | requiredBy = 44 | [ "graphical-session.target" "graphical-session-pre.target" ]; 45 | }; 46 | 47 | systemd.user.services.wf = { 48 | enable = true; 49 | description = "Wayfire - Wayland window manager"; 50 | bindsTo = [ "graphical-session.target" ]; 51 | wants = [ "graphical-session-pre.target" ]; 52 | after = [ "graphical-session-pre.target" ]; 53 | # We explicitly unset PATH here, as we want it to be set by 54 | # systemctl --user import-environment in startsway 55 | environment.PATH = lib.mkForce null; 56 | serviceConfig = { 57 | Type = "simple"; 58 | ExecStart = 59 | "${pkgs.dbus}/bin/dbus-run-session ${pkgs.wayfire}/bin/wayfire"; 60 | Restart = "on-failure"; 61 | RestartSec = 1; 62 | TimeoutStopSec = 10; 63 | }; 64 | }; 65 | 66 | modules.shell.fish.loginInit = '' 67 | if status is-login 68 | if test -z "$DISPLAY" -a "$XDG_VTNR" = 1 69 | sway 70 | end 71 | end 72 | ''; 73 | 74 | home.configFile = { 75 | "wayfire/config" = { source = "${configDir}/wayfire/config"; }; 76 | }; 77 | }; 78 | } 79 | -------------------------------------------------------------------------------- /modules/dev/android.nix: -------------------------------------------------------------------------------- 1 | { config, options, lib, pkgs, ... }: 2 | # https://nixos.wiki/wiki/Android 3 | with lib; 4 | with lib.my; 5 | let 6 | cfg = config.modules.dev.android; 7 | androidSdk = pkgs.androidenv.androidPkgs_9_0.androidsdk; 8 | platformTools = pkgs.androidenv.androidPkgs_9_0.platform-tools; 9 | in { 10 | options.modules.dev.android = { enable = mkBoolOpt false; }; 11 | 12 | config = mkIf cfg.enable { 13 | user.packages = with pkgs; [ 14 | # use the development version of android-studio (needed for StreetComplete) 15 | androidStudioPackages.dev 16 | androidSdk 17 | platformTools 18 | glibc 19 | openjdk8 20 | ]; 21 | programs.adb.enable = true; 22 | user.extraGroups = [ "adbusers" ]; 23 | services.udev.packages = [ pkgs.android-udev-rules ]; 24 | 25 | environment.variables = { 26 | ANDROID_JAVA_HOME = "${pkgs.openjdk8.home}"; 27 | ANDROID_SDK_ROOT = "${androidSdk}"; 28 | GRADLE_OPTS = "-Dorg.gradle.project.android.aapt2FromMavenOverride=${androidSdk}/libexec/android-sdk/build-tools/28.0.3/aapt2"; 29 | # Increase max memory sizes for gradle builds 30 | JAVA_OPTIONS = "-Xms1024m -Xmx4096m"; 31 | # https://github.com/swaywm/sway/issues/595 32 | _JAVA_AWT_WM_NONREPARENTING = "1"; 33 | }; 34 | 35 | # TODO: Redundant? 36 | env = { 37 | ANDROID_JAVA_HOME = "${pkgs.openjdk8.home}"; 38 | ANDROID_SDK_ROOT = "${androidSdk}"; 39 | 40 | # override the aapt2 that gradle uses with the nix-shipped version 41 | GRADLE_OPTS = 42 | "-Dorg.gradle.project.android.aapt2FromMavenOverride=${androidSdk}/libexec/android-sdk/build-tools/28.0.3/aapt2"; 43 | }; 44 | }; 45 | } 46 | -------------------------------------------------------------------------------- /modules/dev/cc.nix: -------------------------------------------------------------------------------- 1 | # modules/dev/cc.nix --- C & C++ 2 | # 3 | # I love C. I tolerate C++. I adore C with a few choice C++ features tacked on. 4 | # Liking C/C++ seems to be an unpopular opinion. It's my guilty secret, so don't 5 | # tell anyone pls. 6 | 7 | { config, options, lib, pkgs, ... }: 8 | 9 | with lib; 10 | with lib.my; 11 | let cfg = config.modules.dev.cc; 12 | in { 13 | options.modules.dev.cc = { enable = mkBoolOpt false; }; 14 | 15 | config = mkIf cfg.enable { 16 | user.packages = with pkgs; [ 17 | clang 18 | gcc 19 | bear 20 | gdb 21 | cmake 22 | llvmPackages.libcxx 23 | 24 | # :lang cc 25 | ccls 26 | ]; 27 | }; 28 | } 29 | -------------------------------------------------------------------------------- /modules/dev/clojure.nix: -------------------------------------------------------------------------------- 1 | # modules/dev/clojure.nix --- https://clojure.org/ 2 | # 3 | # I use clojure now > : ) 4 | 5 | { config, options, lib, pkgs, my, ... }: 6 | 7 | with lib; 8 | with lib.my; 9 | let cfg = config.modules.dev.clojure; 10 | in { 11 | options.modules.dev.clojure = { enable = mkBoolOpt false; }; 12 | 13 | config = mkIf cfg.enable { 14 | user.packages = with pkgs; [ jdk17 clojure-lsp clojure joker leiningen ]; 15 | }; 16 | } 17 | -------------------------------------------------------------------------------- /modules/dev/lua.nix: -------------------------------------------------------------------------------- 1 | # modules/dev/lua.nix --- https://www.lua.org/ 2 | # 3 | # I use lua for modding, awesomewm or Love2D for rapid gamedev prototyping (when 4 | # godot is overkill and I have the luxury of avoiding JS). I write my Love games 5 | # in moonscript to get around lua's idiosynchrosies. That said, I install love2d 6 | # on a per-project basis. 7 | 8 | { config, options, lib, pkgs, ... }: 9 | 10 | with lib; 11 | with lib.my; 12 | let 13 | cfg = config.modules.dev.lua; 14 | in 15 | { 16 | options.modules.dev.lua = { 17 | enable = mkBoolOpt false; 18 | love2D.enable = mkBoolOpt false; 19 | }; 20 | 21 | config = mkIf cfg.enable { 22 | user.packages = with pkgs; [ 23 | lua 24 | luaPackages.moonscript 25 | (mkIf cfg.love2D.enable love2d) 26 | ]; 27 | }; 28 | } 29 | -------------------------------------------------------------------------------- /modules/dev/node.nix: -------------------------------------------------------------------------------- 1 | # modules/dev/node.nix --- https://nodejs.org/en/ 2 | # 3 | # JS is one of those "when it's good, it's alright, when it's bad, it's a 4 | # disaster" languages. 5 | 6 | { config, options, lib, pkgs, ... }: 7 | 8 | with lib; 9 | with lib.my; 10 | let cfg = config.modules.dev.node; 11 | in { 12 | options.modules.dev.node = { enable = mkBoolOpt false; }; 13 | 14 | config = mkIf cfg.enable { 15 | user.packages = with pkgs; [ 16 | nodejs 17 | yarn 18 | 19 | # :lang javascript 20 | nodePackages.typescript-language-server 21 | ]; 22 | 23 | env.NPM_CONFIG_USERCONFIG = "$XDG_CONFIG_HOME/npm/config"; 24 | env.NPM_CONFIG_CACHE = "$XDG_CACHE_HOME/npm"; 25 | env.NPM_CONFIG_TMP = "$XDG_RUNTIME_DIR/npm"; 26 | env.NPM_CONFIG_PREFIX = "$XDG_CACHE_HOME/npm"; 27 | env.NODE_REPL_HISTORY = "$XDG_CACHE_HOME/node/repl_history"; 28 | env.PATH = [ "$(yarn global bin)" ]; 29 | 30 | # Run locally installed bin-script, e.g. n coffee file.coffee 31 | environment.shellAliases = { 32 | n = ''PATH="$(npm bin):$PATH"''; 33 | ya = "yarn"; 34 | }; 35 | 36 | home.configFile."npm/config".text = '' 37 | cache=$XDG_CACHE_HOME/npm 38 | prefix=$XDG_DATA_HOME/npm 39 | ''; 40 | }; 41 | } 42 | -------------------------------------------------------------------------------- /modules/dev/python.nix: -------------------------------------------------------------------------------- 1 | # modules/dev/python.nix --- https://godotengine.org/ 2 | # 3 | # Python's ecosystem repulses me. The list of environment "managers" exhausts 4 | # me. The Py2->3 transition make trainwrecks jealous. But SciPy, NumPy, iPython 5 | # and Jupyter can have my babies. Every single one. 6 | 7 | { config, options, lib, pkgs, my, ... }: 8 | 9 | with lib; 10 | with lib.my; 11 | let cfg = config.modules.dev.python; 12 | in { 13 | options.modules.dev.python = { 14 | enable = mkBoolOpt false; 15 | }; 16 | 17 | config = mkIf cfg.enable { 18 | user.packages = with pkgs; [ 19 | python37 20 | python37Packages.pip 21 | python37Packages.ipython 22 | python37Packages.black 23 | python37Packages.setuptools 24 | python37Packages.pylint 25 | python37Packages.poetry 26 | ]; 27 | 28 | env.IPYTHONDIR = "$XDG_CONFIG_HOME/ipython"; 29 | env.PIP_CONFIG_FILE = "$XDG_CONFIG_HOME/pip/pip.conf"; 30 | env.PIP_LOG_FILE = "$XDG_DATA_HOME/pip/log"; 31 | env.PYLINTHOME = "$XDG_DATA_HOME/pylint"; 32 | env.PYLINTRC = "$XDG_CONFIG_HOME/pylint/pylintrc"; 33 | env.PYTHONSTARTUP = "$XDG_CONFIG_HOME/python/pythonrc"; 34 | env.PYTHON_EGG_CACHE = "$XDG_CACHE_HOME/python-eggs"; 35 | env.JUPYTER_CONFIG_DIR = "$XDG_CONFIG_HOME/jupyter"; 36 | 37 | environment.shellAliases = { 38 | py = "python"; 39 | py3 = "python3"; 40 | po = "poetry"; 41 | ipy = "ipython --no-banner"; 42 | ipylab = "ipython --pylab=qt5 --no-banner"; 43 | }; 44 | }; 45 | } 46 | -------------------------------------------------------------------------------- /modules/dev/rust.nix: -------------------------------------------------------------------------------- 1 | # modules/dev/rust.nix --- https://rust-lang.org 2 | # 3 | # Oh Rust. The light of my life, fire of my loins. Years of C++ has conditioned 4 | # me to believe there was no hope left, but the gods have heard us. Sure, you're 5 | # not going to replace C/C++. Sure, your starlight popularity has been 6 | # overblown. Sure, macros aren't namespaced, cargo bypasses crates.io, and there 7 | # is no formal proof of your claims for safety, but who said you have to solve 8 | # all the world's problems to be wonderful? 9 | 10 | { config, options, lib, pkgs, ... }: 11 | 12 | with lib; 13 | with lib.my; 14 | let cfg = config.modules.dev.rust; 15 | in { 16 | options.modules.dev.rust = { enable = mkBoolOpt false; }; 17 | 18 | config = mkIf cfg.enable { 19 | user.packages = with pkgs; [ rustup rustfmt unstable.rust-analyzer ]; 20 | 21 | env.RUSTUP_HOME = "$XDG_DATA_HOME/rustup"; 22 | env.CARGO_HOME = "$XDG_DATA_HOME/cargo"; 23 | env.PATH = [ "$CARGO_HOME/bin" ]; 24 | 25 | environment.shellAliases = { 26 | rs = "rustc"; 27 | rsp = "rustup"; 28 | ca = "cargo"; 29 | }; 30 | }; 31 | } 32 | -------------------------------------------------------------------------------- /modules/editors/default.nix: -------------------------------------------------------------------------------- 1 | { config, options, lib, pkgs, ... }: 2 | 3 | with lib; 4 | with lib.my; 5 | let cfg = config.modules.editors; 6 | secrets = lib.my.secrets; 7 | in { 8 | options.modules.editors = { default = mkOpt types.str "emacsclient -c"; }; 9 | 10 | config = { 11 | env.EDITOR = cfg.default; 12 | user.packages = with pkgs; [wakatime]; 13 | 14 | environment.shellAliases = { 15 | wakatime-cli = 16 | "${pkgs.wakatime}/bin/wakatime-cli --key ${secrets.wakatime.apiKey}"; 17 | wakatime = 18 | "${pkgs.wakatime}/bin/wakatime-cli --key ${secrets.wakatime.apiKey}"; 19 | }; 20 | }; 21 | } 22 | -------------------------------------------------------------------------------- /modules/editors/emacs.nix: -------------------------------------------------------------------------------- 1 | { config, lib, pkgs, inputs, ... }: 2 | 3 | with lib; 4 | with lib.my; 5 | # emacs (~pgtk~) + native-comp 6 | # this was `29.2`, but the emacs interface keeps changing in backwards-incompatible ways 7 | let 8 | myemacs0 = pkgs.emacs29-pgtk; 9 | emacsWPkgs = (pkgs.emacsPackagesFor myemacs0).emacsWithPackages; 10 | myemacs = emacsWPkgs (epkgs: (with epkgs; [ vterm pdf-tools org-pdftools ])); 11 | 12 | cfg = config.modules.editors.emacs; 13 | # Install Doom Emacs if not already configured, placing the correct things in the system path. 14 | daemonScript = pkgs.writeScriptBin "emacs" '' 15 | #!${pkgs.bash}/bin/bash -l 16 | export PATH=$PATH:${lib.makeBinPath [ pkgs.git pkgs.sqlite pkgs.unzip ]} 17 | export SHELL=${pkgs.bash}/bin/bash 18 | if [ ! -d $HOME/.emacs.d/.git ]; then 19 | mkdir -p $HOME/.emacs.d 20 | git -C $HOME/.emacs.d init 21 | fi 22 | if [ ! -d $HOME/.config/doom ]; then 23 | git clone git@github.com:jakeisnt/doom.d.git $HOME/.config/doom 24 | fi 25 | if [ $(git -C $HOME/.emacs.d rev-parse HEAD) != ${pkgs.doomEmacsRevision} ]; then 26 | git -C $HOME/.emacs.d fetch https://github.com/hlissner/doom-emacs.git || true 27 | git -C $HOME/.emacs.d checkout ${pkgs.doomEmacsRevision} || true 28 | $HOME/.emacs.d/bin/doom sync || true 29 | YES=1 FORCE=1 $HOME/.emacs.d/bin/doom sync -u & 30 | fi 31 | 32 | exec ${myemacs}/bin/emacs --daemon 33 | ''; 34 | 35 | in { 36 | options.modules.editors.emacs = { 37 | enable = mkBoolOpt false; 38 | daemon = mkBoolOpt false; 39 | doom = { 40 | enable = mkBoolOpt true; 41 | fromSSH = mkBoolOpt false; 42 | }; 43 | }; 44 | 45 | config = mkIf cfg.enable { 46 | nixpkgs.overlays = [ 47 | inputs.emacs-overlay.overlay 48 | inputs.nur.overlay 49 | ]; 50 | 51 | # enable tree sitter grammars 52 | modules.editors.tree-sitter.enable = true; 53 | 54 | services.emacs = mkIf cfg.daemon { 55 | enable = true; 56 | install = false; 57 | package = daemonScript; 58 | defaultEditor = true; 59 | }; 60 | 61 | user.packages = with pkgs; [ 62 | binutils # native-comp needs 'as', provided by this 63 | myemacs 64 | daemonScript 65 | direnv # required for nix dev envintegration 66 | 67 | ## Doom dependencies 68 | git 69 | (ripgrep.override { withPCRE2 = true; }) 70 | gnutls # for TLS connectivity 71 | 72 | ## Optional dependencies 73 | fd # faster projectile indexing 74 | imagemagick # for image-dired 75 | (mkIf (config.programs.gnupg.agent.enable) 76 | pinentry-emacs) # in-emacs gnupg prompts 77 | zstd # for undo-fu-session/undo-tree compression 78 | 79 | ## Module dependencies 80 | # :checkers spell 81 | (aspellWithDicts (ds: with ds; [ en en-computers en-science ])) 82 | # :checkers grammar 83 | languagetool 84 | # :tools editorconfig 85 | editorconfig-core-c # per-project style config 86 | # :tools lookup & :lang org +roam 87 | sqlite 88 | # :lang latex & :lang org (latex previews) 89 | texlive.combined.scheme-medium 90 | # :lang rust 91 | # org +gnuplot 92 | gnuplot 93 | # org +pandoc 94 | pandoc 95 | # graphviz 96 | graphviz 97 | 98 | # for vterm 99 | libvterm 100 | libtool 101 | 102 | # for org-roam graph 103 | graphviz 104 | 105 | # presumably to build emacs 106 | gcc 107 | 108 | # copilot 109 | nodejs 110 | 111 | # other project searching 112 | fzf 113 | ]; 114 | 115 | env.PATH = [ "$XDG_CONFIG_HOME/emacs/bin" ]; 116 | fonts.packages = [ pkgs.emacs-all-the-icons-fonts ]; 117 | }; 118 | } 119 | -------------------------------------------------------------------------------- /modules/editors/tree-sitter.nix: -------------------------------------------------------------------------------- 1 | { config, lib, pkgs, inputs, ... }: 2 | 3 | # Fetch and compile tree-sitter grammars ahead of time rather than with a stateful configuration. 4 | # Inspired by https://github.com/Mic92/dotfiles. 5 | 6 | with lib; 7 | with lib.my; 8 | 9 | let 10 | treeSitterGrammars = pkgs.runCommandLocal "grammars" {} '' 11 | mkdir -p $out/bin 12 | ${lib.concatStringsSep "\n" 13 | (lib.mapAttrsToList (name: src: "ln -s ${src}/parser $out/bin/${name}.so") pkgs.tree-sitter.builtGrammars)} 14 | ''; 15 | langs = [ 16 | "bash" 17 | "c" 18 | "c-sharp" 19 | "css" 20 | "go" 21 | "html" 22 | "java" 23 | "javascript" 24 | "jsdoc" 25 | "json" 26 | "ocaml" 27 | "python" 28 | "ruby" 29 | "rust" 30 | "scala" 31 | "typescript" 32 | "org-nvim" 33 | "clojure" 34 | "commonlisp" 35 | ]; 36 | 37 | grammars = lib.getAttrs (map (lang: "tree-sitter-${lang}") langs) pkgs.tree-sitter.builtGrammars; 38 | cfg = config.modules.editors.tree-sitter; 39 | 40 | in { 41 | options.modules.editors.tree-sitter = { 42 | enable = mkBoolOpt false; 43 | }; 44 | 45 | config = mkIf cfg.enable { 46 | user.packages = with pkgs; [ tree-sitter ]; 47 | home.file.".tree-sitter".source = treeSitterGrammars; 48 | home.configFile."tree-sitter" = { 49 | source = "${configDir}/tree-sitter"; 50 | recursive = true; # include all utils, config files, etc... 51 | }; 52 | }; 53 | } 54 | -------------------------------------------------------------------------------- /modules/editors/vim.nix: -------------------------------------------------------------------------------- 1 | { config, options, lib, pkgs, uPkgs, inputs, ... }: 2 | 3 | with lib; 4 | with lib.my; 5 | let 6 | cfg = config.modules.editors.vim; 7 | launchNvim = "nvim -u ~/.config/nvim/init.lua"; 8 | in 9 | { 10 | options.modules.editors.vim = { enable = mkBoolOpt false; }; 11 | 12 | config = mkIf cfg.enable { 13 | programs.neovim = { 14 | package = pkgs.unstable.neovim-unwrapped; # switch from (neovim-nightly) 15 | enable = true; 16 | defaultEditor = false; # this is configured by me elsewhere 17 | }; 18 | 19 | user.packages = with pkgs; [ 20 | sqlite # for coq nvim completion 21 | universal-ctags # for coq nvim completion 22 | python310 # for coq setup 23 | python310Packages.virtualenv 24 | # lua lsp for vim config 25 | sumneko-lua-language-server 26 | # for nvim 27 | gcc 28 | # for copilot (and others?) 29 | nodejs 30 | ]; 31 | 32 | modules.editors.tree-sitter.enable = true; 33 | 34 | # env.VIMINIT = "let \\$MYVIMRC='\\$XDG_CONFIG_HOME/nvim/init.lua' | source \\$MYVIMRC"; 35 | 36 | environment.shellAliases = { 37 | nvim = launchNvim; 38 | vim = launchNvim; 39 | vi = launchNvim; 40 | v = launchNvim; 41 | }; 42 | }; 43 | } 44 | -------------------------------------------------------------------------------- /modules/editors/vscode.nix: -------------------------------------------------------------------------------- 1 | # I don't actively use VSCode, but it's good to have a configuration handy 2 | # because it's become the industry standard for text editors. 3 | # 4 | # It was a pain to get these hashes working. 5 | # I retrieved the real URL from https://github.com/NixOS/nixpkgs/blob/master/pkgs/misc/vscode-extensions/mktplcExtRefToFetchArgs.nix 6 | # and wrote a quick bash script to fetch the hash provided the url - go check it out in the bin/ folder 7 | 8 | { config, options, lib, pkgs, ... }: 9 | 10 | with lib; 11 | with lib.my; 12 | let 13 | cfg = config.modules.editors.vscode; 14 | extensions = with pkgs.vscode-extensions; 15 | ( 16 | [ bbenoist.nix vscodevim.vim eugleo.magic-racket ] 17 | ++ pkgs.vscode-utils.extensionsFromVscodeMarketplace [ 18 | { 19 | name = "vscode-wakatime"; 20 | publisher = "WakaTime"; 21 | version = "5.0.1"; 22 | sha256 = "0wahh7kmrdzcrcp2lj71qxsxbmgdq97k60aw2jxxqlmdfy407nnh"; 23 | } 24 | { 25 | name = "stilla"; 26 | publisher = "jakeisnt"; 27 | version = "0.0.1"; 28 | sha256 = "1hwmv2545qmdx7s6mf3ba0qf6217xssws1w2018s6s75sbcxmga4"; 29 | } 30 | { 31 | name = "vscode-direnv"; 32 | publisher = "Rubymaniac"; 33 | version = "0.0.2"; 34 | sha256 = "1gml41bc77qlydnvk1rkaiv95rwprzqgj895kxllqy4ps8ly6nsd"; 35 | } 36 | { 37 | name = "leadermode"; 38 | publisher = "michaelgriscom"; 39 | version = "0.2.0"; 40 | sha256 = "184b8g0rgfasippvfvr6bslaxfm34bqa2mgzr0y0dphj26fyw2wn"; 41 | } 42 | ] ++ ( 43 | if config.modules.dev.node.enable then 44 | pkgs.vscode-utils.extensionsFromVscodeMarketplace [ 45 | { 46 | name = "vscode-eslint"; 47 | publisher = "dbaeumer"; 48 | version = "2.1.14"; 49 | sha256 = "113w2iis4zi4z3sqc3vd2apyrh52hbh2gvmxjr5yvjpmrsksclbd"; 50 | } 51 | ] 52 | else 53 | [] 54 | ) ++ ( 55 | if config.modules.dev.cc.enable then [ 56 | xaver.clang-format 57 | ms-vscode.cpptools 58 | ] else 59 | [] 60 | ) ++ ( 61 | if config.modules.dev.rust.enable then 62 | [ matklad.rust-analyzer ] 63 | else 64 | [] 65 | ) 66 | ) ++ pkgs.vscode-utils.extensionsFromVscodeMarketplace [ 67 | { 68 | name = "remote-ssh-edit"; 69 | publisher = "ms-vscode-remote"; 70 | version = "0.47.2"; 71 | sha256 = "1hp6gjh4xp2m1xlm1jsdzxw9d8frkiidhph6nvl24d0h8z34w49g"; 72 | } 73 | ]; 74 | vscodium-with-extensions = pkgs.vscode-with-extensions.override { 75 | vscode = pkgs.vscodium; 76 | vscodeExtensions = extensions; 77 | }; 78 | in 79 | { 80 | options.modules.editors.vscode = { enable = mkBoolOpt false; }; 81 | 82 | config = mkIf cfg.enable { 83 | user.packages = with pkgs; [ vscodium-with-extensions ]; 84 | home.configFile = { 85 | "VSCodium/User" = { 86 | source = "${configDir}/vscode"; 87 | recursive = true; 88 | }; 89 | }; 90 | }; 91 | } 92 | -------------------------------------------------------------------------------- /modules/gaming/emulators.nix: -------------------------------------------------------------------------------- 1 | { options, config, lib, pkgs, ... }: 2 | 3 | with lib; 4 | with lib.my; 5 | let cfg = config.modules.gaming.emulators; 6 | in { 7 | options.modules.gaming.emulators = { 8 | psx.enable = mkBoolOpt false; # Playstation 9 | ds.enable = mkBoolOpt false; # Nintendo DS 10 | gb.enable = mkBoolOpt false; # GameBoy + GameBoy Color 11 | gba.enable = mkBoolOpt false; # GameBoy Advance 12 | snes.enable = mkBoolOpt false; # Super Nintendo 13 | }; 14 | 15 | config = { 16 | user.packages = with pkgs; [ 17 | # (mkIf cfg.psx.enable epsxe) 18 | # (mkIf cfg.ds.enable desmume) 19 | # (mkIf (cfg.gba.enable || cfg.gb.enable || cfg.snes.enable) higan) 20 | ]; 21 | }; 22 | } 23 | -------------------------------------------------------------------------------- /modules/hardware/audio.nix: -------------------------------------------------------------------------------- 1 | { options, config, lib, pkgs, ... }: 2 | 3 | with lib; 4 | with lib.my; 5 | let cfg = config.modules.hardware.audio; 6 | in { 7 | options.modules.hardware.audio = { enable = mkBoolOpt false; }; 8 | 9 | config = mkIf cfg.enable { 10 | # DEPRECATED: Can be removed! 11 | # sound.enable = true; 12 | xdg.portal = mkIf config.modules.desktop.sway.enable { 13 | enable = true; 14 | extraPortals = with pkgs; [ 15 | xdg-desktop-portal-wlr 16 | xdg-desktop-portal-gtk 17 | ]; 18 | }; 19 | 20 | # control audio utilities 21 | user.extraGroups = [ 22 | "audio" 23 | ]; 24 | 25 | hardware.pulseaudio.enable = mkForce false; 26 | 27 | services.pipewire = { 28 | enable = true; 29 | alsa.enable = true; 30 | pulse.enable = true; 31 | jack.enable = true; 32 | }; 33 | 34 | user.packages = with pkgs; [ 35 | # communicate with pipewire via `pactl` 36 | pulseaudio 37 | # dynamically linked to; supports camera connection 38 | libcamera 39 | ]; 40 | }; 41 | } 42 | -------------------------------------------------------------------------------- /modules/hardware/bluetooth.nix: -------------------------------------------------------------------------------- 1 | { options, config, lib, pkgs, ... }: 2 | 3 | with lib; 4 | with lib.my; 5 | let 6 | hwCfg = config.modules.hardware; 7 | cfg = hwCfg.bluetooth; 8 | in { 9 | options.modules.hardware.bluetooth = { 10 | enable = mkBoolOpt false; 11 | audio.enable = mkBoolOpt false; 12 | }; 13 | 14 | 15 | config = mkIf cfg.enable (mkMerge [ 16 | { 17 | hardware.bluetooth = { 18 | enable = true; 19 | package = pkgs.bluezFull; 20 | }; 21 | services.blueman.enable = true; 22 | user.extraGroups = [ "bluetooth" "lp"]; 23 | } 24 | (mkIf cfg.audio.enable { 25 | systemd.user.services.mpris-proxy = { 26 | Unit.Description = "Mpris proxy"; 27 | Unit.After = [ "network.target" "sound.target" ]; 28 | Service.ExecStart = "${pkgs.bluez}/bin/mpris-proxy"; 29 | Install.WantedBy = [ "default.target" ]; 30 | }; 31 | 32 | hardware.bluetooth.settings = { 33 | General = { 34 | Enable = "Source,Sink,Media,Socket"; 35 | # ControllerMode = "bredr"; # disable Bluetooth LE 36 | }; 37 | }; 38 | }) 39 | ]); 40 | } 41 | -------------------------------------------------------------------------------- /modules/hardware/extraHosts.nix: -------------------------------------------------------------------------------- 1 | { options, config, lib, pkgs, ... }: 2 | 3 | with lib; 4 | with lib.my; 5 | let 6 | cfg = config.modules.hardware.extraHosts; 7 | src = builtins.fetchTarball { 8 | url = "https://github.com/StevenBlack/hosts/archive/3.3.4.tar.gz"; 9 | sha256 = "15474wjzwldfrbacvnwii7wjil83lh1wykq0h1sf59fq4fv75inj"; 10 | }; 11 | blockAllButSocial = "${src}/alternates/fakenews-gambling-porn/hosts"; 12 | blockAll = "${src}/alternates/fakenews-gambling-porn-social/hosts"; 13 | in { 14 | options.modules.hardware.extraHosts = { 15 | enable = mkBoolOpt false; 16 | allowSocial = mkBoolOpt true; 17 | }; 18 | 19 | config = mkIf cfg.enable { 20 | networking.extraHosts = 21 | readFile (if cfg.allowSocial then blockAllButSocial else blockAll); 22 | }; 23 | } 24 | -------------------------------------------------------------------------------- /modules/hardware/fs.nix: -------------------------------------------------------------------------------- 1 | { config, options, lib, pkgs, ... }: 2 | 3 | with lib; 4 | with lib.my; 5 | let cfg = config.modules.hardware.fs; 6 | in { 7 | options.modules.hardware.fs = { 8 | enable = mkBoolOpt false; 9 | zfs.enable = mkBoolOpt false; 10 | ssd.enable = mkBoolOpt false; 11 | }; 12 | 13 | config = mkIf cfg.enable (mkMerge [ 14 | { 15 | programs.udevil.enable = true; 16 | 17 | # Support for more filesystems, mostly to support external drives 18 | environment.systemPackages = with pkgs; [ 19 | sshfs 20 | exfat # Windows drives 21 | ntfs3g # Windows drives 22 | hfsprogs # MacOS drives 23 | ]; 24 | } 25 | 26 | (mkIf (!cfg.zfs.enable && cfg.ssd.enable) { 27 | services.fstrim = { 28 | enable = true; 29 | interval = "daily"; 30 | }; 31 | }) 32 | 33 | (mkIf cfg.zfs.enable (mkMerge [ 34 | { 35 | boot.loader.grub.copyKernels = true; 36 | boot.supportedFilesystems = [ "zfs" ]; 37 | boot.zfs.devNodes = "/dev/disk/by-partuuid"; 38 | services.zfs.autoScrub.enable = true; 39 | } 40 | 41 | (mkIf cfg.ssd.enable { 42 | # Will only TRIM SSDs; skips over HDDs 43 | services.fstrim.enable = false; 44 | services.zfs.trim.enable = true; 45 | }) 46 | ])) 47 | ]); 48 | } 49 | -------------------------------------------------------------------------------- /modules/hardware/printer.nix: -------------------------------------------------------------------------------- 1 | { options, config, lib, pkgs, ... }: 2 | 3 | with lib; 4 | with lib.my; 5 | let cfg = config.modules.hardware.printer; 6 | in { 7 | options.modules.hardware.printer = { enable = mkBoolOpt false; }; 8 | 9 | config = mkIf cfg.enable { 10 | services.printing = { 11 | enable = true; 12 | drivers = [ ]; 13 | }; 14 | 15 | modules.services.avahi.enable = true; 16 | 17 | user.extraGroups = [ "scanner" "lp" ]; 18 | }; 19 | } 20 | -------------------------------------------------------------------------------- /modules/hardware/remarkable.nix: -------------------------------------------------------------------------------- 1 | { options, config, lib, pkgs, ... }: 2 | 3 | with lib; 4 | with lib.my; 5 | let cfg = config.modules.hardware.remarkable; 6 | in { 7 | options.modules.hardware.remarkable = { enable = mkBoolOpt false; }; 8 | config = mkIf cfg.enable { 9 | user.packages = with pkgs; [ rmapi ]; 10 | 11 | 12 | programs.ssh.knownHosts = { 13 | # alias for ReMarkable IP! 14 | "remarkable" = { 15 | hostNames = ["10.110.139.108"]; 16 | publicKey = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCY05XsAsq0wgBJvVQcT9MOh+U/rTlk0s7MHDZkFEwQiGuiGme3+96D8IrNGbtYwwWKDLZafxy9aAGLrTiT/UMTRC/7rO1aRRRCnpBbLfLiKX0JqWWL0ZzHdNNI3tPgIWUNw502GzcELbHjvw2SSgxvUF/Prqv6/CUrEN3tWG2ch/jjmXGlLkOcev/hHp6HR3J8OcSTTVlc9MZhYkrrfifi3nCtNOtbWWQfEx1KnAQ2L4t4LLfeATBqzVkNsmk3p8IZ97tZJdWFajEb44jROBpvei0JG+VTSW6CcolwluYx4vkk2mVOt+e520T7gjNQQnFjxeXJOy/5FxJfq9OFn7/T root@reMarkable"; 17 | }; 18 | }; 19 | 20 | }; 21 | } 22 | -------------------------------------------------------------------------------- /modules/hardware/scanner.nix: -------------------------------------------------------------------------------- 1 | { options, config, lib, pkgs, ... }: 2 | 3 | with lib; 4 | with lib.my; 5 | let cfg = config.modules.hardware.scanner; 6 | in { 7 | options.modules.hardware.scanner = { enable = mkBoolOpt false; }; 8 | 9 | config = mkIf cfg.enable { 10 | hardware.sane = { 11 | enable = true; 12 | # needed to support epson 13 | extraBackends = with pkgs; [ epkowa ]; 14 | }; 15 | user.extraGroups = [ "scanner" "lp" ]; 16 | }; 17 | } 18 | -------------------------------------------------------------------------------- /modules/media/daw.nix: -------------------------------------------------------------------------------- 1 | # modules/desktop/media/daw.nix 2 | 3 | # off of Fruityloops. When I'm in the mood for a quicky I fire up sunvox 4 | # instead. It runs absolutely anywhere, even on my ipad and phone. As if I'd 5 | # ever need to. 6 | 7 | { config, options, lib, pkgs, ... }: 8 | 9 | with lib; 10 | with lib.my; 11 | let 12 | cfg = config.modules.media.daw; 13 | in 14 | { 15 | options.modules.media.daw = { enable = mkBoolOpt false; }; 16 | 17 | config = mkIf cfg.enable { 18 | user.packages = with pkgs; [ 19 | ardour 20 | # audacity # for recording and remastering audio 21 | calf # nice open source audio plugins and synths!! 22 | vcv-rack # rack simulation thing (start it by running Rack!) 23 | # sunvox # chill synth for making music (where LMMS is overkill) 24 | # orca-c # powers sunvox 25 | ]; 26 | }; 27 | } 28 | -------------------------------------------------------------------------------- /modules/media/documents.nix: -------------------------------------------------------------------------------- 1 | # modules/desktop/media/docs.nix 2 | 3 | { options, config, lib, pkgs, ... }: 4 | 5 | with lib; 6 | with lib.my; 7 | let cfg = config.modules.media.documents; 8 | in { 9 | options.modules.media.documents = { 10 | enable = mkBoolOpt false; 11 | pdf.enable = mkBoolOpt false; 12 | ebook.enable = mkBoolOpt false; 13 | }; 14 | 15 | config = mkIf cfg.enable { 16 | user.packages = with pkgs; [ 17 | (mkIf cfg.ebook.enable calibre) 18 | (mkIf cfg.pdf.enable evince) 19 | zathura 20 | ]; 21 | }; 22 | } 23 | -------------------------------------------------------------------------------- /modules/media/graphics.nix: -------------------------------------------------------------------------------- 1 | # modules/desktop/media/graphics.nix 2 | # 3 | # No Adobe allowed. 4 | 5 | { config, options, lib, pkgs, ... }: 6 | 7 | with builtins; 8 | with lib; 9 | with lib.my; 10 | let 11 | cfg = config.modules.media.graphics; 12 | # username = let name = getEnv "username"; 13 | # in if elem name [ "" "root" ] then username else name; 14 | in { 15 | options.modules.media.graphics = { 16 | enable = mkBoolOpt false; 17 | tools.enable = mkBoolOpt true; 18 | raster.enable = mkBoolOpt true; 19 | vector.enable = mkBoolOpt true; 20 | sprites.enable = mkBoolOpt true; 21 | photo.enable = mkBoolOpt true; 22 | }; 23 | 24 | config = mkIf cfg.enable { 25 | user.packages = with pkgs; 26 | [ vlc ] ++ (if cfg.tools.enable then [ 27 | font-manager # so many damned fonts... 28 | imagemagick # for image manipulation from the shell 29 | ] else 30 | [ ]) ++ 31 | 32 | # replaces illustrator & indesign 33 | (if cfg.vector.enable then [ inkscape ] else [ ]) ++ 34 | 35 | # Replaces photoshop 36 | (if cfg.raster.enable then [ 37 | # krita 38 | gimp 39 | # gimpPlugins.resynthesizer2 # content-aware scaling in gimp 40 | ] else 41 | [ ]) ++ 42 | 43 | # replaces lightroom 44 | (if cfg.photo.enable then [ darktable ] else [ ]) ++ 45 | 46 | # Sprite sheets & animation 47 | (if cfg.sprites.enable then [ aseprite-unfree ] else [ ]); 48 | 49 | home.configFile = mkMerge [ 50 | (mkIf cfg.raster.enable { 51 | "GIMP/2.10" = { 52 | source = "${configDir}/gimp"; 53 | recursive = true; 54 | }; 55 | }) 56 | (mkIf cfg.vector.enable { 57 | "inkscape/templates/default.svg".source = "${configDir}/inkscape/default-template.svg"; 58 | }) 59 | ]; 60 | 61 | environment.variables.PICTURES_FOLDER = "/home/${username}/pics"; 62 | }; 63 | 64 | } 65 | -------------------------------------------------------------------------------- /modules/media/mpv.nix: -------------------------------------------------------------------------------- 1 | { config, options, lib, pkgs, ... }: 2 | 3 | with lib; 4 | with lib.my; 5 | let cfg = config.modules.media.mpv; 6 | in { 7 | options.modules.media.mpv = { enable = mkBoolOpt false; }; 8 | 9 | config = mkIf cfg.enable { 10 | user.packages = with pkgs; [ 11 | # image viewer 12 | imv 13 | mpv-with-scripts 14 | mpvc # CLI controller for mpv 15 | (mkIf config.programs.sway.enable celluloid) # nice GTK GUI for mpv 16 | ]; 17 | }; 18 | } 19 | -------------------------------------------------------------------------------- /modules/media/recording.nix: -------------------------------------------------------------------------------- 1 | # modules/desktop/media/recording.nix 2 | # 3 | # OBS to capture footage/stream, audacity for audio, handbrake to encode it all. 4 | # This, paired with DaVinci Resolve for video editing (on my Windows system) and 5 | # I have what I need for youtube videos and streaming. 6 | 7 | { config, options, lib, pkgs, ... }: 8 | 9 | with lib; 10 | with lib.my; 11 | let 12 | cfg = config.modules.media.recording; 13 | in 14 | { 15 | options.modules.media.recording = { 16 | enable = mkBoolOpt false; 17 | audio.enable = mkBoolOpt true; 18 | video.enable = mkBoolOpt true; 19 | }; 20 | 21 | config = mkIf cfg.enable { 22 | user.packages = with pkgs; 23 | # for recording and remastering audio 24 | ( 25 | if cfg.audio.enable then [ 26 | # audacity 27 | ] else [] 28 | ) ++ # for longer term streaming/recording the screen 29 | (if cfg.video.enable then [(wrapOBS { 30 | plugins = with obs-studio-plugins; [ 31 | wlrobs 32 | ]; 33 | }) handbrake ] else []); 34 | }; 35 | } 36 | -------------------------------------------------------------------------------- /modules/messengers/deltachat.nix: -------------------------------------------------------------------------------- 1 | { config, options, lib, pkgs, ... }: 2 | 3 | with lib; 4 | with lib.my; 5 | let cfg = config.modules.messengers.deltachat; 6 | in { 7 | options.modules.messengers.deltachat = { enable = mkBoolOpt false; }; 8 | 9 | config = mkIf cfg.enable { 10 | user.packages = with pkgs; 11 | (if config.programs.sway.enable then [ deltachat-electron ] else [ ]); 12 | }; 13 | } 14 | -------------------------------------------------------------------------------- /modules/messengers/discord.nix: -------------------------------------------------------------------------------- 1 | { config, options, lib, pkgs, ... }: 2 | 3 | with lib; 4 | with lib.my; 5 | let cfg = config.modules.messengers.discord; 6 | in { 7 | options.modules.messengers.discord = { enable = mkBoolOpt false; }; 8 | 9 | config = mkIf cfg.enable { 10 | user.packages = with pkgs; 11 | [ 12 | # If not installed from the bleeding edge, Discord will sometimes 13 | # soft-lock itself on a "there's an update for discord" screen. 14 | ] ++ (if config.programs.sway.enable then 15 | [ unstable.discord ] 16 | else 17 | [ cordless ]); 18 | }; 19 | } 20 | -------------------------------------------------------------------------------- /modules/messengers/matrix.nix: -------------------------------------------------------------------------------- 1 | { config, lib, pkgs, ... }: 2 | 3 | with lib; 4 | with lib.my; 5 | let cfg = config.modules.messengers.matrix; 6 | in { 7 | options.modules.messengers.matrix = { enable = mkBoolOpt false; }; 8 | 9 | config = mkIf cfg.enable { user.packages = with pkgs; [ gomuks ]; }; 10 | } 11 | -------------------------------------------------------------------------------- /modules/messengers/rss.nix: -------------------------------------------------------------------------------- 1 | { config, options, lib, pkgs, ... }: 2 | 3 | with lib; 4 | with lib.my; 5 | let cfg = config.modules.messengers.rss; 6 | in { 7 | options.modules.messengers.rss = { enable = mkBoolOpt false; }; 8 | config = mkIf cfg.enable { 9 | # 'liferea' provides a nice GUI for RSS if I need images and html at some point 10 | user.packages = with pkgs; [ newsboat ]; 11 | # TODO: consider tt-rss server (or mimic the protocol with another service?) 12 | # we want to be able to tweak .config/newsboat/urls without rebuild, so it's not included here. 13 | home.configFile = { 14 | "newsboat/config".source = "${configDir}/newsboat/config"; 15 | }; 16 | }; 17 | } 18 | -------------------------------------------------------------------------------- /modules/messengers/signal.nix: -------------------------------------------------------------------------------- 1 | { config, lib, pkgs, ... }: 2 | 3 | with lib; 4 | with lib.my; 5 | let cfg = config.modules.messengers.signal; 6 | in { 7 | options.modules.messengers.signal = { enable = mkBoolOpt false; }; 8 | 9 | config = mkIf cfg.enable { 10 | user.packages = with pkgs; 11 | [ ] ++ (if config.programs.sway.enable then 12 | [ signal-desktop ] 13 | else 14 | [ signal-cli ]); 15 | }; 16 | } 17 | -------------------------------------------------------------------------------- /modules/messengers/slack.nix: -------------------------------------------------------------------------------- 1 | { config, lib, pkgs, ... }: 2 | 3 | with lib; 4 | with lib.my; 5 | let cfg = config.modules.messengers.slack; 6 | in { 7 | options.modules.messengers.slack = { enable = mkBoolOpt false; }; 8 | 9 | config = mkIf cfg.enable { 10 | user.packages = with pkgs; 11 | [ ] 12 | ++ (if config.programs.sway.enable then [ slack ] else [ slack-term ]); 13 | }; 14 | } 15 | -------------------------------------------------------------------------------- /modules/messengers/weechat.nix: -------------------------------------------------------------------------------- 1 | { config, options, lib, pkgs, ... }: 2 | 3 | with lib; 4 | with lib.my; 5 | let cfg = config.modules.messengers.weechat; 6 | in { 7 | options.modules.messengers.weechat = { enable = mkBoolOpt false; }; 8 | 9 | config = mkIf cfg.enable { 10 | user.packages = with pkgs; [ weechat ]; 11 | }; 12 | } 13 | -------------------------------------------------------------------------------- /modules/security.nix: -------------------------------------------------------------------------------- 1 | { ... }: 2 | 3 | { 4 | ## System security tweaks 5 | boot.tmp.useTmpfs = true; 6 | boot.tmp.tmpfsSize = "16G"; 7 | boot.tmp.cleanOnBoot = true; 8 | 9 | security.protectKernelImage = true; 10 | 11 | # Fix a security hole in place for backwards compatibility. See desc in 12 | # nixpkgs/nixos/modules/system/boot/loader/systemd-boot/systemd-boot.nix 13 | boot.loader.systemd-boot.editor = false; 14 | } 15 | -------------------------------------------------------------------------------- /modules/services/acme.nix: -------------------------------------------------------------------------------- 1 | { config, options, lib, pkgs, ... }: 2 | 3 | with lib; 4 | with lib.my; 5 | let cfg = config.modules.services.acme; 6 | in { 7 | options.modules.services.acme = { 8 | enable = mkBoolOpt false; 9 | }; 10 | 11 | config = mkIf cfg.enable { 12 | security.acme = { 13 | defaults.email = "${secrets.gmail.user}"; 14 | email = "${secrets.gmail.user}"; 15 | acceptTerms = true; 16 | }; 17 | }; 18 | } 19 | -------------------------------------------------------------------------------- /modules/services/avahi.nix: -------------------------------------------------------------------------------- 1 | { options, config, lib, pkgs, ... }: 2 | 3 | # Make systems discoverable to one another over local networks. 4 | 5 | with lib; 6 | with lib.my; 7 | let cfg = config.modules.services.avahi; 8 | in { 9 | options.modules.services.avahi = { enable = mkBoolOpt false; }; 10 | 11 | config = mkIf cfg.enable { 12 | services.avahi = { 13 | enable = true; 14 | nssmdns = true; 15 | publish.enable = true; 16 | publish.addresses = true; 17 | publish.workstation = true; 18 | }; 19 | }; 20 | } 21 | -------------------------------------------------------------------------------- /modules/services/backup.nix: -------------------------------------------------------------------------------- 1 | { config, lib, pkgs, ... }: 2 | 3 | # This service backs up to the cloud and to a physical device, somehow. 4 | with lib; 5 | with lib.my; 6 | let 7 | cfg = config.modules.services.backup; 8 | domain = config.networking.domain; 9 | in { 10 | options.modules.services.backup = { 11 | enable = mkBoolOpt false; 12 | registration = mkBoolOpt false; 13 | mail = mkBoolOpt false; 14 | yubikey = mkBoolOpt false; 15 | }; 16 | 17 | 18 | config = mkIf cfg.enable { 19 | users.users.duplicati.isNormalUser = true; 20 | services.duplicati = { 21 | enable = true; 22 | user = "jake"; 23 | }; 24 | }; 25 | } 26 | -------------------------------------------------------------------------------- /modules/services/bitwarden.nix: -------------------------------------------------------------------------------- 1 | { options, config, lib, pkgs, ... }: 2 | 3 | with lib; 4 | with lib.my; 5 | let 6 | cfg = config.modules.services.bitwarden; 7 | domain = config.networking.domain; 8 | in { 9 | options.modules.services.bitwarden = { 10 | enable = mkBoolOpt false; 11 | registration = mkBoolOpt false; 12 | mail = mkBoolOpt false; 13 | }; 14 | 15 | config = mkIf cfg.enable { 16 | modules.services.acme.enable = true; 17 | modules.services.nginx.enable = true; 18 | 19 | services = { 20 | vaultwarden = { 21 | enable = true; 22 | config = mkMerge [ 23 | { 24 | signupsAllowed = cfg.registration; 25 | invitationsAllowed = cfg.registration; 26 | domain = "https://bitwarden.${domain}"; 27 | logFile = "/var/log/bitwarden"; 28 | websocketEnabled = true; 29 | websocketAddress = "0.0.0.0"; 30 | websocketPort = 3012; 31 | signupsVerify = true; 32 | adminToken = secrets.bitwarden.adminToken; 33 | rocketPort = 8812; 34 | } 35 | (mkIf cfg.mail { 36 | smtpHost = "localhost"; 37 | smtpFrom = "admin@${domain}"; 38 | smtpFromName = "Admin"; 39 | smtpPort = 587; 40 | smtpSsl = true; 41 | smtpUsername = "admin@${domain}"; 42 | smtpPassword = secrets.email.hashedPassword; 43 | smtpTimeout = 15; 44 | }) 45 | ]; 46 | }; 47 | 48 | nginx = { 49 | virtualHosts."bitwarden.${domain}" = { 50 | forceSSL = true; 51 | enableACME = true; 52 | root = "/srv/www/bitwarden.${domain}"; 53 | locations = { 54 | "/".proxyPass = 55 | "http://localhost:8812"; # changed the default rocket port due to some conflict 56 | "/notifications/hub".proxyWebsockets = true; 57 | "/notifications/hub/negotiate".proxyWebsockets = true; 58 | }; 59 | }; 60 | }; 61 | }; 62 | 63 | user.extraGroups = [ "vaultwarden" ]; 64 | }; 65 | } 66 | -------------------------------------------------------------------------------- /modules/services/cal.nix: -------------------------------------------------------------------------------- 1 | { config, lib, pkgs, ... }: 2 | 3 | # Calendar and contacts sync server 4 | # Largely from https://nixos-mailserver.readthedocs.io/en/latest/howto-add-radicale.html 5 | with lib; 6 | with lib.my; 7 | let 8 | cfg = config.modules.services.cal; 9 | domain = config.networking.domain; 10 | mailAccounts = config.mailserver.loginAccounts; 11 | htpasswd = pkgs.writeText "radicale.users" (concatStrings 12 | (flip mapAttrsToList mailAccounts 13 | (mail: user: mail + ":" + secrets.email.hashedPassword + "\n"))); 14 | in { 15 | options.modules.services.cal = { enable = mkBoolOpt false; }; 16 | 17 | config = mkIf cfg.enable { 18 | services.radicale = { 19 | enable = true; 20 | settings = { 21 | auth = { 22 | type = "htpasswd"; 23 | htpasswd_filename = "${htpasswd}"; 24 | htpasswd_encryption = "bcrypt"; 25 | }; 26 | }; 27 | }; 28 | 29 | services.nginx = { 30 | enable = true; 31 | virtualHosts = { 32 | "cal.${domain}" = { 33 | forceSSL = true; 34 | enableACME = true; 35 | root = "/srv/www/cal.${domain}"; 36 | locations."/" = { 37 | proxyPass = "http://localhost:5232/"; 38 | extraConfig = '' 39 | proxy_set_header X-Script-Name /; 40 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 41 | proxy_pass_header Authorization; 42 | ''; 43 | }; 44 | }; 45 | }; 46 | }; 47 | }; 48 | } 49 | -------------------------------------------------------------------------------- /modules/services/calibre.nix: -------------------------------------------------------------------------------- 1 | { options, config, lib, pkgs, ... }: 2 | 3 | with lib; 4 | with lib.my; 5 | let cfg = config.modules.services.calibre; 6 | in { 7 | options.modules.services.calibre = { 8 | enable = mkBoolOpt false; 9 | }; 10 | 11 | config = mkIf cfg.enable { 12 | services.calibre-server.enable = true; 13 | 14 | networking.firewall.allowedTCPPorts = [ 8080 ]; 15 | }; 16 | } 17 | -------------------------------------------------------------------------------- /modules/services/dnsmasq.nix: -------------------------------------------------------------------------------- 1 | { config, options, lib, pkgs, ... }: 2 | 3 | with lib; 4 | with lib.my; 5 | let cfg = config.modules.services.dnsmasq; 6 | in { 7 | options.modules.services.dnsmasq = { enable = mkBoolOpt false; }; 8 | 9 | config = mkIf cfg.enable { 10 | # use dnsmasq to cache dns 11 | services.dnsmasq = { 12 | enable = true; 13 | servers = [ "8.8.8.8" "8.8.4.4" ]; 14 | 15 | extraConfig = '' 16 | interface=lo 17 | bind-interfaces 18 | listen-address=127.0.0.1 19 | cache-size=1000 20 | no-negcache 21 | ''; 22 | }; 23 | }; 24 | } 25 | -------------------------------------------------------------------------------- /modules/services/docker.nix: -------------------------------------------------------------------------------- 1 | { options, config, lib, pkgs, ... }: 2 | 3 | with lib; 4 | with lib.my; 5 | let cfg = config.modules.services.docker; 6 | in { 7 | options.modules.services.docker = { 8 | enable = mkBoolOpt false; 9 | podman = mkBoolOpt false; 10 | kubernetes = mkBoolOpt false; 11 | }; 12 | 13 | config = mkIf cfg.enable { 14 | user.packages = with pkgs; ([ 15 | docker-client 16 | docker-compose 17 | ] ++ (if cfg.kubernetes then [ kubectl k3s ] else [])); 18 | 19 | env.DOCKER_CONFIG = "$XDG_CONFIG_HOME/docker"; 20 | env.MACHINE_STORAGE_PATH = "$XDG_DATA_HOME/docker/machine"; 21 | 22 | user.extraGroups = [ "docker" ]; 23 | 24 | environment.shellAliases = { 25 | "dk" = "docker"; 26 | "dkc" = "docker-compose"; 27 | "dkl" = "dk logs"; 28 | "dkcl" = "dkc logs"; 29 | "dkclr" = "dk stop (docker ps -a -q) && dk rm (docker ps -a -q)"; 30 | }; 31 | 32 | # a nixos kubernetes service running in userspace (I hope 33 | # TODO: This doesn't work. 34 | # services.kubernetes = mkIf cfg.kubernetes { 35 | # roles = ["master" "node"]; 36 | # masterAddress = "localhost"; 37 | # apiserver.enable = true; 38 | # controllerManager.enable = true; 39 | # scheduler.enable = true; 40 | # addonManager.enable = true; 41 | # proxy.enable = true; 42 | # flannel.enable = true; 43 | # }; 44 | 45 | virtualisation = { 46 | podman = { 47 | enable = cfg.podman; 48 | dockerCompat = true; 49 | dockerSocket.enable = true; 50 | }; 51 | docker = { 52 | enable = !cfg.podman; 53 | # autoPrune.enable = true; 54 | enableOnBoot = true; 55 | # listenOptions = []; 56 | }; 57 | }; 58 | users.users.jake.extraGroups = [ "podman" ]; 59 | }; 60 | } 61 | -------------------------------------------------------------------------------- /modules/services/gitea.nix: -------------------------------------------------------------------------------- 1 | { options, config, lib, pkgs, ... }: 2 | 3 | with lib; 4 | with lib.my; 5 | let 6 | cfg = config.modules.services.gitea; 7 | domain = config.networking.domain; 8 | in { 9 | options.modules.services.gitea = { 10 | enable = mkBoolOpt false; 11 | registration = mkBoolOpt false; 12 | mail = mkBoolOpt false; 13 | }; 14 | 15 | config = mkIf cfg.enable { 16 | modules.services.nginx.enable = true; 17 | 18 | # I prefer git@... ssh addresses over gitea@... 19 | users.users.git = { 20 | useDefaultShell = true; 21 | home = "/var/lib/gitea"; 22 | group = "gitea"; 23 | }; 24 | 25 | services = { 26 | gitea = { 27 | enable = true; 28 | domain = "git.${domain}"; 29 | appName = "git.${domain}"; 30 | 31 | user = "git"; 32 | database = { 33 | user = "git"; 34 | type = "postgres"; 35 | createDatabase = true; 36 | }; 37 | 38 | ssh = { 39 | enable = true; 40 | clonePort = 2222; 41 | }; 42 | 43 | dump.enable = true; 44 | disableRegistration = cfg.registration; 45 | httpPort = 3000; 46 | 47 | # We're assuming SSL-only connectivity 48 | cookieSecure = true; 49 | 50 | log.level = "Error"; 51 | settings.server.DISABLE_ROUTER_LOG = true; 52 | settings.mailer = mkIf cfg.mail { 53 | ENABLED = true; 54 | FROM = "admin@${domain}"; 55 | MAILER_TYPE = "smtp"; 56 | HOST = "localhost:587"; 57 | IS_TLS_ENABLED = true; 58 | USER = "admin@${domain}"; 59 | PASSWD = secrets.email.hashedPassword; 60 | }; 61 | }; 62 | 63 | nginx = { 64 | virtualHosts = { 65 | "git.${domain}" = { 66 | forceSSL = true; 67 | enableACME = true; 68 | root = "/srv/www/git.${domain}"; 69 | locations."/" = { proxyPass = "http://127.0.0.1:3000"; }; 70 | }; 71 | }; 72 | }; 73 | }; 74 | 75 | user.extraGroups = [ "gitea" ]; 76 | }; 77 | } 78 | -------------------------------------------------------------------------------- /modules/services/jellyfin.nix: -------------------------------------------------------------------------------- 1 | # Finally, a decent open alternative to Plex! 2 | 3 | { options, config, lib, pkgs, ... }: 4 | 5 | with lib; 6 | with lib.my; 7 | let cfg = config.modules.services.jellyfin; 8 | in { 9 | options.modules.services.jellyfin = { 10 | enable = mkBoolOpt false; 11 | }; 12 | 13 | config = mkIf cfg.enable { 14 | services.jellyfin.enable = true; 15 | 16 | networking.firewall = { 17 | allowedTCPPorts = [ 8096 ]; 18 | allowedUDPPorts = [ 8096 ]; 19 | }; 20 | 21 | user.extraGroups = [ "jellyfin" ]; 22 | }; 23 | } 24 | -------------------------------------------------------------------------------- /modules/services/jitsi.nix: -------------------------------------------------------------------------------- 1 | # Finally, a decent open alternative to Plex! 2 | 3 | { options, config, lib, pkgs, ... }: 4 | 5 | with lib; 6 | with lib.my; 7 | let 8 | cfg = config.modules.services.jitsi; 9 | domain = config.networking.domain; 10 | in { 11 | options.modules.services.jitsi = { enable = mkBoolOpt false; }; 12 | 13 | config = mkIf cfg.enable { 14 | services = { 15 | jitsi-meet = { 16 | enable = true; 17 | hostName = "jitsi.${domain}"; 18 | config = { 19 | enableWelcomePage = false; 20 | prejoinPageEnabled = true; 21 | }; 22 | interfaceConfig = { 23 | SHOW_JITSI_WATERMARK = false; 24 | SHOW_WATERMARK_FOR_GUESTS = false; 25 | }; 26 | }; 27 | 28 | jitsi-videobridge.openFirewall = true; 29 | }; 30 | 31 | networking.firewall = { 32 | allowedTCPPorts = [ 5349 5350 ]; 33 | allowedUDPPorts = [ 80 443 3478 3479 ]; 34 | }; 35 | }; 36 | } 37 | -------------------------------------------------------------------------------- /modules/services/mailserver.nix: -------------------------------------------------------------------------------- 1 | { lib, config, pkgs, ... }: 2 | 3 | with lib; 4 | with lib.my; 5 | let 6 | cfg = config.modules.services.mailserver; 7 | domain = config.networking.domain; 8 | in { 9 | options.modules.services.mailserver = { enable = mkBoolOpt false; }; 10 | 11 | config = mkIf cfg.enable { 12 | modules.services.acme.enable = true; 13 | networking.firewall.allowedTCPPorts = [ 14 | # Email 15 | 25 # SMTP 16 | 465 # Submission TLS 17 | 587 # Submission StartTLS 18 | 993 # IMAP with TLS 19 | 995 # POP3 with TLS 20 | 143 # IMAP with StartTLS 21 | 110 # POP3 with StartTLS 22 | 23 | # roundcube 24 | 80 25 | 443 26 | ]; 27 | 28 | services.nginx.enable = true; 29 | 30 | services.roundcube = { 31 | enable = true; 32 | hostName = "mail.${domain}"; 33 | extraConfig = '' 34 | # starttls needed for authentication, so the fqdn required to match 35 | # the certificate 36 | $config['smtp_server'] = "tls://${config.mailserver.fqdn}"; 37 | $config['smtp_user'] = "%u"; 38 | $config['smtp_pass'] = "%p"; 39 | ''; 40 | }; 41 | 42 | mailserver = { 43 | enable = true; 44 | fqdn = "mail.${domain}"; 45 | domains = [ domain ]; 46 | 47 | loginAccounts = { 48 | "jake@${domain}" = { 49 | hashedPassword = secrets.email.hashedPassword; 50 | # aliases = [ ]; 51 | catchAll = [ domain ]; 52 | }; 53 | 54 | "tommy@${domain}" = { 55 | hashedPassword = secrets.email.hashedPasswordT; 56 | # aliases = [ ]; 57 | catchAll = [ domain ]; 58 | }; 59 | 60 | "admin@${domain}" = { 61 | hashedPassword = secrets.email.hashedPassword; 62 | # aliases = [ ]; 63 | }; 64 | "phoebe@${domain}" = { 65 | hashedPassword = secrets.email.hashedPasswordP; 66 | aliases = [ "pheebs" ]; 67 | }; 68 | }; 69 | 70 | # Use Let's Encrypt certificates. Note that this needs to set up a stripped 71 | # down nginx and opens port 80. 72 | certificateScheme = 3; 73 | 74 | # Enable IMAP and POP3 75 | enableImap = true; enablePop3 = true; enableImapSsl = true; 76 | enablePop3Ssl = true; 77 | 78 | # Enable the ManageSieve protocol 79 | enableManageSieve = true; 80 | 81 | # whether to scan inbound emails for viruses (note that this requires at least 82 | # 1 Gb RAM for the server. Without virus scanning 256 MB RAM should be plenty) 83 | virusScanning = false; 84 | }; 85 | }; 86 | } 87 | -------------------------------------------------------------------------------- /modules/services/matrix.nix: -------------------------------------------------------------------------------- 1 | { options, config, lib, pkgs, ... }: 2 | 3 | with lib; 4 | with lib.my; 5 | let 6 | cfg = config.modules.services.matrix; 7 | domain = config.networking.domain; 8 | in { 9 | options.modules.services.matrix = { 10 | enable = mkBoolOpt false; 11 | registration = mkBoolOpt false; 12 | element = mkBoolOpt false; 13 | }; 14 | 15 | config = mkIf cfg.enable { 16 | modules.services.acme.enable = true; 17 | modules.services.nginx.enable = true; 18 | 19 | networking.firewall.allowedTCPPorts = [ 20 | 8448 # Matrix federation 21 | ]; 22 | 23 | services = mkMerge [ 24 | (mkIf cfg.element { 25 | nginx.virtualHosts."element.${domain}" = { 26 | enableACME = true; 27 | forceSSL = true; 28 | root = pkgs.element-web.override { 29 | conf = { 30 | default_server_config."m.homeserver" = { 31 | "base_url" = "https://matrix.${domain}"; 32 | "server_name" = "${domain}"; 33 | }; 34 | 35 | jitsi.preferredDomain = 36 | mkIf config.modules.services.jitsi.enable "jitsi.${domain}"; 37 | }; 38 | }; 39 | }; 40 | }) 41 | { 42 | matrix-synapse = { 43 | enable = true; 44 | server_name = domain; 45 | enable_registration = cfg.registration; 46 | registration_shared_secret = secrets.matrix.password; 47 | 48 | public_baseurl = "https://matrix.${domain}"; 49 | # tls_certificate_path = "/var/lib/acme/matrix.isnt.online/fullchain.pem"; 50 | # tls_private_key_path = "/var/lib/acme/matrix.isnt.online/key.pem"; 51 | 52 | database_type = "psycopg2"; 53 | database_args = { database = "matrix-synapse"; }; 54 | 55 | listeners = [{ # federation 56 | bind_address = "::1"; 57 | port = 8008; 58 | resources = [{ 59 | compress = true; 60 | names = [ "client" "federation" ]; 61 | }]; 62 | 63 | tls = false; 64 | type = "http"; 65 | x_forwarded = false; 66 | }]; 67 | 68 | extraConfig = '' 69 | max_upload_size: "100M" 70 | ''; 71 | }; 72 | 73 | postgresql = { 74 | enable = true; 75 | initialScript = pkgs.writeText "synapse-init.sql" '' 76 | CREATE USER "matrix-synapse"; 77 | 78 | CREATE DATABASE "matrix-synapse" 79 | ENCODING 'UTF8' 80 | LC_COLLATE='C' 81 | LC_CTYPE='C' 82 | template=template0 83 | OWNER "matrix-synapse"; 84 | ''; 85 | }; 86 | 87 | nginx = { 88 | virtualHosts = { 89 | "${domain}" = { 90 | locations."= /.well-known/matrix/server".extraConfig = let 91 | # use 443 instead of the default 8448 port 92 | server = { "m.server" = "matrix.${domain}:443"; }; 93 | in '' 94 | add_header Content-Type application/json; 95 | return 200 '${builtins.toJSON server}'; 96 | ''; 97 | locations."= /.well-known/matrix/client".extraConfig = let 98 | client = { 99 | "m.homeserver" = { "base_url" = "https://matrix.${domain}"; }; 100 | "m.identity_server" = { "base_url" = "https://vector.im"; }; 101 | }; 102 | in '' 103 | add_header Content-Type application/json; 104 | add_header Access-Control-Allow-Origin *; 105 | return 200 '${builtins.toJSON client}'; 106 | ''; 107 | }; 108 | 109 | "matrix.${domain}" = { 110 | enableACME = true; 111 | forceSSL = true; 112 | 113 | locations."/".extraConfig = '' 114 | return 404; 115 | ''; 116 | 117 | locations."/_matrix" = { proxyPass = "http://[::1]:8008"; }; 118 | }; 119 | }; 120 | }; 121 | 122 | } 123 | ]; 124 | }; 125 | } 126 | -------------------------------------------------------------------------------- /modules/services/nginx.nix: -------------------------------------------------------------------------------- 1 | { config, options, lib, pkgs, ... }: 2 | 3 | with lib; 4 | with lib.my; 5 | let cfg = config.modules.services.nginx; 6 | in { 7 | options.modules.services.nginx = { enable = mkBoolOpt false; }; 8 | 9 | config = mkIf cfg.enable { 10 | networking.firewall.allowedTCPPorts = [ 80 443 ]; 11 | 12 | services.nginx = { 13 | enable = true; 14 | 15 | # Use recommended settings 16 | recommendedGzipSettings = true; 17 | recommendedOptimisation = true; 18 | recommendedProxySettings = true; 19 | recommendedTlsSettings = true; 20 | }; 21 | }; 22 | } 23 | -------------------------------------------------------------------------------- /modules/services/ssh.nix: -------------------------------------------------------------------------------- 1 | { options, config, lib, pkgs, ... }: 2 | 3 | with lib; 4 | with lib.my; 5 | let 6 | cfg = config.modules.services.ssh; 7 | add = "/run/current-system/sw/bin/ssh-add"; 8 | keygen = "/run/current-system/sw/bin/ssh-keygen"; 9 | ssh-agent = "/run/current-system/sw/bin/ssh-agent"; 10 | xpsKey = 11 | "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQCtB3BbMTx18grI1xxJ+mvjO8jzYoUIWh6l230DiXmQ7w7+3ZJpPEh21UphqZvm/k5FwsPU5Tb+vuwofEjPZfvx0ERL1XNvrFg/2rQmGl2ccsupclMz2uxwP47APW5amJzhVRUejTOhv9Xo7kaZGqeh3L5hbyNSfC3Ci2LpZpV1nwuOgqmCm58d68G05YrW/LIM7zPVpWRa7/1Jyplu2AYViCB5z3jt1q1s7UP2oXAh5bH5QQ5vlqdsU9GEpn0HSF0CjQdGx7PDfyeocDoI0Dy0coUCWsMDrPqURnZWzQL0eARKkaYdLHcJ2N8I3dwU1z8I/8VJ+jxm9jmOxhuwlIluXdz6VUbh+eNOmEczVwjAtTdpiyBG2ku0labQ4TMN0G0GdV3USxC4sEfBYfzF1m2NERRAm9ySkjxbLqQ5b/85mvLUtuJ4q5hMla6gGDRRKUAWGrDlVe8G3NACARqqDIQOE36Je/u/f3HjOFtczEf5pfAUW4Ky7tyOJYzaxErPK/zc1g2qRdVtDclgdI1IHuSFywQPeAkz0l0vTqe60+RUZT0kyQXNzvZeEZ9U8ia8kO07HfxGAu3cdW7AJI/5eZv1LXI6Xa0GYN+9BSARz6RKHjNIM9wYAqGrDExgo56UOLrHqiDRRt6ZaqBPXzBdIp6D6HHuh7oggexINXoRvHaMWw== jake@isnt.online"; 12 | in { 13 | options.modules.services.ssh = { enable = mkBoolOpt false; }; 14 | 15 | config = mkIf cfg.enable { 16 | services.openssh = { 17 | enable = true; 18 | forwardX11 = true; 19 | kbdInteractiveAuthentication = false; 20 | passwordAuthentication = false; 21 | }; 22 | 23 | # Allow SSHing through firewall 24 | networking.firewall.allowedTCPPorts = [ 22 ]; 25 | user.openssh.authorizedKeys.keys = [ xpsKey ]; 26 | 27 | # user.packages = with pkgs; 28 | # TODO restore 29 | # [ 30 | # (writeScriptBin "ssh-key" '' 31 | # #!${stdenv.shell} 32 | # # Create SSH key 33 | # ${keygen} -t rsa -b 4096 -C "${username}@${secrets.domain}" 34 | # eval $(${ssh-agent} -s) 35 | # ${add} $HOME/.ssh/id_rsa 36 | # '') 37 | # ]; 38 | }; 39 | } 40 | -------------------------------------------------------------------------------- /modules/services/syncthing.nix: -------------------------------------------------------------------------------- 1 | { config, options, pkgs, lib, ... }: 2 | with builtins; 3 | with lib; 4 | with lib.my; 5 | let 6 | cfg = config.modules.services.syncthing; 7 | username = let name = getEnv "username"; 8 | in if elem name [ "" "root" ] then "jake" else name; 9 | 10 | domain = config.networking.domain; 11 | in { 12 | options.modules.services.syncthing = { 13 | enable = mkBoolOpt false; 14 | server = mkBoolOpt false; 15 | }; 16 | 17 | config = mkIf cfg.enable { 18 | modules.services = mkIf cfg.server { 19 | acme.enable = true; 20 | nginx.enable = true; 21 | }; 22 | 23 | services.nginx = mkIf cfg.server { 24 | virtualHosts = { 25 | "syncthing.${domain}" = { 26 | forceSSL = true; 27 | enableACME = true; 28 | root = "/srv/www/syncthing.${domain}"; 29 | locations."/" = { 30 | proxyPass = "http://localhost:8384"; 31 | proxyWebsockets = true; 32 | }; 33 | }; 34 | }; 35 | }; 36 | 37 | services.syncthing = { 38 | enable = true; 39 | guiAddress = mkIf cfg.server "syncthing.${domain}"; 40 | user = username; 41 | openDefaultPorts = true; 42 | configDir = "/home/${username}/.config/syncthing"; 43 | dataDir = "/home/${username}/.local/share/syncthing"; 44 | 45 | folders = let 46 | deviceEnabled = devices: lib.elem config.networking.hostName devices; 47 | deviceType = devices: 48 | if deviceEnabled devices then "sendreceive" else "receiveonly"; 49 | in { 50 | work = rec { 51 | devices = [ "phone" "xps" "vultr" ]; 52 | path = "/home/${username}/work"; 53 | watch = true; 54 | rescanInterval = 3600 * 6; 55 | type = deviceType [ "xps" ]; 56 | enable = deviceEnabled devices; 57 | }; 58 | pics = rec { 59 | devices = [ "phone" "xps" "vultr" ]; 60 | path = "/home/${username}/pics"; 61 | watch = true; 62 | rescanInterval = 3600 * 6; 63 | type = deviceType [ "xps" ]; 64 | enable = deviceEnabled devices; 65 | }; 66 | }; 67 | 68 | devices = { 69 | xps.id = 70 | "M4GBTEM-N55HKKV-KLP4G5H-JFMMPUD-REYTNI6-EE4L2WS-S7KJES6-TK6Y4Q5"; 71 | phone.id = 72 | "KYKZF7Z-TD62SOX-5A6LEWA-URNMNF7-CSNWD2E-ALNXGIC-P4PXDSI-4N6EHAV"; 73 | vultr.id = 74 | "JRGIZAD-VHMLCCH-PFONWDZ-JEHKFAS-QG2ODRM-L7CWZBZ-SYD3LJF-DXZC3QI"; 75 | }; 76 | }; 77 | }; 78 | } 79 | -------------------------------------------------------------------------------- /modules/services/teamviewer.nix: -------------------------------------------------------------------------------- 1 | { options, config, lib, pkgs, ... }: 2 | 3 | with lib; 4 | with lib.my; 5 | let cfg = config.modules.services.teamviewer; 6 | in { 7 | options.modules.services.teamviewer = { 8 | enable = mkBoolOpt false; 9 | }; 10 | 11 | config = mkIf cfg.enable { 12 | services.teamviewer.enable = true; 13 | }; 14 | } 15 | -------------------------------------------------------------------------------- /modules/services/transmission.nix: -------------------------------------------------------------------------------- 1 | { config, options, pkgs, lib, my, ... }: 2 | 3 | with lib; 4 | with lib.my; 5 | let cfg = config.modules.services.transmission; 6 | in { 7 | options.modules.services.transmission = { 8 | enable = mkBoolOpt false; 9 | }; 10 | 11 | config = mkIf cfg.enable { 12 | services.transmission = { 13 | enable = true; 14 | home = "${homeDir}/torrents"; 15 | settings = { 16 | incomplete-dir-enabled = true; 17 | rpc-whitelist = "127.0.0.1,192.168.*.*"; 18 | rpc-host-whitelist = "*"; 19 | rpc-host-whitelist-enabled = true; 20 | ratio-limit = 0; 21 | ratio-limit-enabled = true; 22 | }; 23 | }; 24 | 25 | networking.firewall = { 26 | allowedTCPPorts = [ 51413 ]; 27 | allowedUDPPorts = [ 51413 ]; 28 | }; 29 | 30 | user.extraGroups = [ "transmission" ]; 31 | }; 32 | } 33 | -------------------------------------------------------------------------------- /modules/shell/bitwarden.nix: -------------------------------------------------------------------------------- 1 | { config, options, pkgs, lib, ... }: 2 | 3 | with lib; 4 | with lib.my; 5 | let cfg = config.modules.shell.bitwarden; 6 | in { 7 | options.modules.shell.bitwarden = with types; { 8 | enable = mkBoolOpt false; 9 | config = mkOpt attrs { }; 10 | }; 11 | 12 | config = mkIf cfg.enable { 13 | user.packages = with pkgs; [ bitwarden-cli ]; 14 | 15 | system.userActivationScripts = mkIf (cfg.config != { }) { 16 | initBitwarden = '' 17 | ${concatStringsSep "\n" 18 | (mapAttrsToList (n: v: "bw config ${n} ${v}") cfg.config)} 19 | ''; 20 | }; 21 | }; 22 | } 23 | -------------------------------------------------------------------------------- /modules/shell/direnv.nix: -------------------------------------------------------------------------------- 1 | { config, options, lib, pkgs, ... }: 2 | 3 | with lib; 4 | with lib.my; 5 | let cfg = config.modules.shell.direnv; 6 | in { 7 | options.modules.shell.direnv = { 8 | enable = mkBoolOpt false; 9 | preventGC = mkBoolOpt false; 10 | }; 11 | 12 | config = mkIf cfg.enable { 13 | user.packages = with pkgs; [ direnv nix-direnv ]; 14 | nix.extraOptions = mkIf cfg.preventGC '' 15 | keep-outputs = true 16 | keep-derivations = true 17 | ''; 18 | 19 | environment.pathsToLink = [ "/share/nix-direnv" ]; 20 | home.configFile = { 21 | "direnv/config".text = 22 | "source /run/current-system/sw/share/nix-direnv/direnvrc"; 23 | }; 24 | 25 | modules.shell.fish.rcInit = ''direnv hook fish | source''; 26 | 27 | home.configFile = { 28 | "direnv" = { 29 | source = "${configDir}/direnv"; 30 | recursive = true; 31 | }; 32 | }; 33 | }; 34 | } 35 | -------------------------------------------------------------------------------- /modules/shell/file.nix: -------------------------------------------------------------------------------- 1 | # fast terminal browsing 2 | { config, options, lib, pkgs, ... }: 3 | 4 | with lib; 5 | with lib.my; 6 | let cfg = config.modules.shell.file; 7 | 8 | # convenient interaction and support for lots of different types of files 9 | in { 10 | options.modules.shell.file = { enable = mkBoolOpt false; }; 11 | 12 | config = mkIf cfg.enable { 13 | user.packages = with pkgs; [ 14 | joshuto # tui file browser 15 | poppler_utils # pdf preview 16 | ffmpegthumbnailer # video thumbnails 17 | xdg_utils # xdg-open is used a lot 18 | feh # image viewer 19 | zathura # pdf viewer 20 | bat # text file viewer 21 | mediainfo # image and video metadata viewer 22 | mpv # video and audio player 23 | ]; 24 | 25 | home.configFile = { 26 | "joshuto" = { 27 | source = "${configDir}/joshuto"; 28 | recursive = true; # include all utils, config files, etc... 29 | }; 30 | }; 31 | }; 32 | } 33 | -------------------------------------------------------------------------------- /modules/shell/fish.nix: -------------------------------------------------------------------------------- 1 | { config, options, pkgs, lib, ... }: 2 | 3 | with lib; 4 | with lib.my; 5 | let cfg = config.modules.shell.fish; 6 | loginInit = config.modules.shell.loginInit; 7 | in { 8 | options.modules.shell.fish = with types; { 9 | enable = mkBoolOpt false; 10 | 11 | aliases = mkOpt (attrsOf (either str path)) { }; 12 | 13 | rcInit = mkOpt' lines "" '' 14 | Fish commands to be run when fish starts up. 15 | ''; 16 | loginInit = mkOpt' lines "" '' 17 | Other fish commands to be run before fish starts up. It's worth noting that these run before 'rcInit' commands. 18 | ''; 19 | 20 | rcFiles = mkOpt (listOf (either str path)) [ ]; 21 | envFiles = mkOpt (listOf (either str path)) [ ]; 22 | }; 23 | 24 | config = mkIf cfg.enable { 25 | users.defaultUserShell = pkgs.fish; 26 | 27 | programs.fish = { 28 | enable = true; 29 | promptInit = with pkgs; '' 30 | set fish_greeting 31 | function fish_mode_prompt; end 32 | function fish_prompt; end 33 | 34 | function postexec_test --on-event fish_postexec 35 | echo 36 | end 37 | 38 | fish_add_path /etc/nixos/bin 39 | ${starship}/bin/starship init fish | source 40 | ${zoxide}/bin/zoxide init fish | source 41 | ${cfg.loginInit} 42 | ${cfg.rcInit} 43 | ''; 44 | 45 | loginShellInit = loginInit; 46 | 47 | shellAliases = with pkgs; { 48 | # use the souped-up rust stuff! 49 | "ls" = "${exa}/bin/exa"; 50 | "cat" = "${bat}/bin/bat"; 51 | "find" = "${fd}/bin/fd"; 52 | "ps" = "${procs}/bin/procs"; 53 | "grep" = "${ripgrep}/bin/rg"; 54 | 55 | # other sane shell reconfigurations 56 | "q" = "exit"; 57 | "cp" = "cp -i"; 58 | "mv" = "mv -i"; 59 | "rm" = "rm -i"; 60 | "mkdir" = "mkdir -p"; 61 | "sc" = "systemctl"; 62 | "ssc" = "sudo systemctl"; 63 | 64 | # cool idea: remind me later! 65 | # r() { 66 | # local time=$1; shift 67 | # sched "$time" "notify-send --urgency=critical 'Reminder' '$@'; ding"; 68 | # }; compdef r=sched 69 | }; 70 | }; 71 | 72 | user.packages = with pkgs; [ 73 | starship 74 | bat 75 | exa 76 | fd 77 | procs 78 | ripgrep 79 | tokei 80 | tealdeer # tldr 81 | fzf 82 | zoxide 83 | ]; 84 | 85 | home.configFile = { 86 | "starship.toml".text = (concatMapStringsSep "\n" readFile [ "${configDir}/starship/starship.toml" ]); 87 | }; 88 | }; 89 | } 90 | -------------------------------------------------------------------------------- /modules/shell/git.nix: -------------------------------------------------------------------------------- 1 | { config, options, lib, pkgs, ... }: 2 | 3 | with lib; 4 | with lib.my; 5 | let cfg = config.modules.shell.git; 6 | in { 7 | options.modules.shell.git = { enable = mkBoolOpt false; }; 8 | 9 | config = mkIf cfg.enable { 10 | user.packages = with pkgs; [ 11 | git 12 | gitflow 13 | gitAndTools.gh 14 | gitAndTools.git-open 15 | gitAndTools.diff-so-fancy 16 | gitAndTools.git-absorb 17 | (mkIf config.modules.shell.gnupg.enable gitAndTools.git-crypt) 18 | # semantic diff! 19 | difftastic 20 | # good diff page viewer 21 | delta 22 | ]; 23 | 24 | environment.shellAliases = with pkgs; { 25 | "ga" = "${git}/bin/git add"; 26 | "gap" = "${git}/bin/git add --patch"; 27 | "gb" = "${git}/bin/git branch -av"; 28 | "gop" = "${git}/bin/git open"; 29 | "gbl"="${git}/bin/git blame"; 30 | "gc"="${git}/bin/git commit"; 31 | "gcm"="${git}/bin/git commit -m"; 32 | "gca"="${git}/bin/git commit --amend"; 33 | "gcf"="${git}/bin/git commit --fixup"; 34 | "gcl"="${git}/bin/git clone"; 35 | "gco"="${git}/bin/git checkout"; 36 | "gcoo"="${git}/bin/git checkout --"; 37 | "gf"="${git}/bin/git fetch"; 38 | "gi"="${git}/bin/git init"; 39 | "gl"="${git}/bin/git log --graph --pretty=\"format:%C(yellow)%h%Creset %C(red)%G?%Creset%C(green)%d%Creset %s %Cblue(%cr) %C(bold blue)<%aN>%Creset\""; 40 | "gll"="${git}/bin/git log --pretty=\"format:%C(yellow)%h%Creset %C(red)%G?%Creset%C(green)%d%Creset %s %Cblue(%cr) %C(bold blue)<%aN>%Creset\""; 41 | "gL"="gl --stat"; 42 | "gp"="${git}/bin/git push"; 43 | "gpl"="${git}/bin/git pull --rebase --autostash"; 44 | "gs"="${git}/bin/git status --short ."; 45 | "gss"="${git}/bin/git status"; 46 | "gst"="${git}/bin/git stash"; 47 | "gr"="${git}/bin/git reset HEAD"; 48 | "grv"="${git}/bin/git rev-parse"; 49 | }; 50 | 51 | home.configFile = { 52 | "git/config".source = "${configDir}/git/config"; 53 | "git/ignore".source = "${configDir}/git/ignore"; 54 | "gh/config.yml".source = "${configDir}/gh/config.yml"; 55 | }; 56 | }; 57 | } 58 | -------------------------------------------------------------------------------- /modules/shell/gnupg.nix: -------------------------------------------------------------------------------- 1 | { config, options, lib, pkgs, ... }: 2 | 3 | with lib; 4 | with lib.my; 5 | let cfg = config.modules.shell.gnupg; 6 | in { 7 | options.modules.shell.gnupg = with types; { 8 | enable = mkBoolOpt false; 9 | gui = mkBoolOpt false; 10 | cacheTTL = mkOpt int 3600; # 1hr 11 | }; 12 | 13 | config = mkIf cfg.enable { 14 | environment.variables.GNUPGHOME = "$XDG_CONFIG_HOME/gnupg"; 15 | programs.gnupg.agent.enable = true; 16 | user.packages = with pkgs; [ 17 | tomb 18 | # all three are necessary for some reason 19 | pinentry.curses 20 | # pinentry-gnome 21 | pinentry-emacs 22 | ]; 23 | 24 | # HACK Without this config file you get "No pinentry program" on 20.03. 25 | # programs.gnupg.agent.pinentryFlavor doesn't appear to work, and this 26 | # is cleaner than overriding the systemd unit. 27 | # pinentry-program ${pkgs.pinentry.curses}/bin/pinentry 28 | # TODO: this may not line up with emacs 29 | programs.gnupg.agent.pinentryPackage = pkgs.emacs; 30 | home.configFile."gnupg/gpg.conf" = { 31 | text = '' 32 | pinentry-mode loopback 33 | ''; 34 | }; 35 | home.configFile."gnupg/gpg-agent.conf" = { 36 | text = '' 37 | allow-emacs-pinentry 38 | allow-loopback-pinentry 39 | enable-ssh-support 40 | pinentry-program ${if true then pkgs.pinentry-emacs else (if cfg.gui then pkgs.pinentry-gnome else pkgs.pinentry-curses)}/bin/pinentry 41 | default-cache-ttl ${toString cfg.cacheTTL} 42 | max-cache-ttl ${toString cfg.cacheTTL} 43 | ''; 44 | }; 45 | }; 46 | } 47 | -------------------------------------------------------------------------------- /modules/shell/nushell.nix: -------------------------------------------------------------------------------- 1 | { config, options, pkgs, lib, ... }: 2 | 3 | with lib; 4 | with lib.my; 5 | let cfg = config.modules.shell.nushell; 6 | loginInit = config.modules.shell.loginInit; 7 | in { 8 | options.modules.shell.loginInit = with types; mkOpt' lines "" '' 9 | Shell commands to be run before the shell starts up. Assume POSIX-compatibility here. 10 | ''; 11 | 12 | options.modules.shell.nushell = with types; { 13 | enable = mkBoolOpt false; 14 | }; 15 | 16 | config = mkIf cfg.enable { 17 | users.defaultUserShell = pkgs.nushell; 18 | 19 | user.packages = with pkgs; [ 20 | nushell 21 | starship 22 | bat 23 | ]; 24 | 25 | environment.variables.ANTHROPIC_API_KEY = secrets.llm.ANTHROPIC_API_KEY; 26 | 27 | home.configFile = { 28 | "starship.toml".text = (concatMapStringsSep "\n" readFile [ "${configDir}/starship/starship.toml" ]); 29 | "nushell/config.nu".text = (concatMapStringsSep "\n" readFile [ "${configDir}/nushell/config.nu" ]); 30 | "nushell/login.nu".text = (concatMapStringsSep "\n" readFile [ "${configDir}/nushell/login.nu" ]); 31 | "nushell/env.nu".text = (concatMapStringsSep "\n" readFile [ "${configDir}/nushell/env.nu" ]); 32 | }; 33 | }; 34 | } 35 | -------------------------------------------------------------------------------- /modules/shell/tmux.nix: -------------------------------------------------------------------------------- 1 | { config, options, pkgs, lib, stdenv, ... }: 2 | 3 | 4 | # if you're using tmux again, 5 | # revisit all of the former zsh aliases to find some useful commands 6 | # that might be worth revisiting! 7 | 8 | with lib; 9 | with lib.my; 10 | let 11 | cfg = config.modules.shell.tmux; 12 | # Despite tmux/tmux#142, tmux will support XDG in 3.2. Sadly, only 3.0 is 13 | # available on nixpkgs, and 3.1b on master (tmux/tmux@15d7e56), so I 14 | # implement it myself: 15 | tmux = (pkgs.writeScriptBin "tmux" '' 16 | #!${pkgs.stdenv.shell} 17 | exec ${pkgs.tmux}/bin/tmux -f "$TMUX_HOME/config" "$@" 18 | ''); 19 | in { 20 | options.modules.shell.tmux = with types; { 21 | enable = mkBoolOpt false; 22 | rcFiles = mkOpt (listOf (either str path)) [ ]; 23 | }; 24 | 25 | config = mkIf cfg.enable { 26 | user.packages = [ tmux ]; 27 | 28 | modules.theme.onReload.tmux = 29 | "${tmux}/bin/tmux source-file $XDG_CONFIG_HOME/tmux/extraInit"; 30 | 31 | home.configFile = { 32 | "tmux" = { 33 | source = "${configDir}/tmux"; 34 | recursive = true; 35 | }; 36 | "tmux/extraInit".text = '' 37 | # This file is auto-generated by nixos, don't edit by hand! 38 | run-shell ${pkgs.tmuxPlugins.copycat}/share/tmux-plugins/copycat/copycat.tmux 39 | run-shell ${pkgs.tmuxPlugins.prefix-highlight}/share/tmux-plugins/prefix-highlight/prefix_highlight.tmux 40 | run-shell ${pkgs.tmuxPlugins.yank}/share/tmux-plugins/yank/yank.tmux 41 | # run-shell ${pkgs.tmuxPlugins.nord}/share/tmux-plugins/nord-tmux/nord.tmux 42 | 43 | ${concatMapStrings (path: '' 44 | source '${path}' 45 | '') cfg.rcFiles} 46 | ''; 47 | }; 48 | 49 | env = { 50 | PATH = [ "$TMUXIFIER/bin" ]; 51 | TMUX_HOME = "$XDG_CONFIG_HOME/tmux"; 52 | TMUXIFIER = "$XDG_DATA_HOME/tmuxifier"; 53 | TMUXIFIER_LAYOUT_PATH = "$XDG_DATA_HOME/tmuxifier"; 54 | }; 55 | }; 56 | } 57 | -------------------------------------------------------------------------------- /modules/term/alacritty.nix: -------------------------------------------------------------------------------- 1 | { options, config, lib, pkgs, ... }: 2 | 3 | with lib; 4 | with lib.my; 5 | let 6 | cfg = config.modules.term.alacritty; 7 | colors = config.modules.theme.color; 8 | in { 9 | options.modules.term.alacritty = { enable = mkBoolOpt false; }; 10 | config = mkIf cfg.enable { 11 | user.packages = with pkgs; [ alacritty ]; 12 | home.configFile = { 13 | "alacritty/alacritty.toml".text = with colors; 14 | concatStrings [ 15 | (concatMapStringsSep "\n" readFile 16 | [ "${configDir}/alacritty/alacritty.toml" ]) 17 | ]; 18 | }; 19 | }; 20 | } 21 | -------------------------------------------------------------------------------- /modules/term/default.nix: -------------------------------------------------------------------------------- 1 | { options, config, lib, pkgs, ... }: 2 | 3 | with lib; 4 | with lib.my; 5 | let cfg = config.modules.term; 6 | in { 7 | options.modules.term = { 8 | default = mkOpt types.str "xterm"; 9 | }; 10 | 11 | config = { 12 | services.xserver.desktopManager.xterm.enable = mkDefault (cfg.default == "xterm"); 13 | 14 | env.TERMINAL = cfg.default; 15 | }; 16 | } 17 | -------------------------------------------------------------------------------- /modules/term/foot.nix: -------------------------------------------------------------------------------- 1 | { options, config, lib, pkgs, ... }: 2 | 3 | with lib; 4 | with lib.my; 5 | let 6 | cfg = config.modules.term.foot; 7 | colors = config.modules.theme.color; 8 | in { 9 | options.modules.term.foot = { enable = mkBoolOpt false; }; 10 | config = mkIf cfg.enable { 11 | user.packages = with pkgs; [ foot ]; 12 | home.configFile = { 13 | "foot/foot.ini".text = with colors; 14 | concatStrings [ 15 | (concatMapStringsSep "\n" readFile 16 | [ "${configDir}/foot/foot.ini" ]) 17 | ('' 18 | [colors] 19 | alpha=1.0 20 | background=${background} 21 | foreground=${foreground} 22 | 23 | ## Normal/regular colors (color palette 0-7) 24 | regular0=${color0} # black 25 | regular1=${color1} # red 26 | regular2=${color2} # green 27 | regular3=${color3} # yellow 28 | regular4=${color4} # blue 29 | regular5=${color5} # magenta 30 | regular6=${color6} # cyan 31 | regular7=${color7} # white 32 | 33 | ## Bright colors (color palette 8-15) 34 | bright0=${color8} # bright black 35 | bright1=${color9} # bright red 36 | bright2=${color10} # bright green 37 | bright3=${color11} # bright yellow 38 | bright4=${color12} # bright blue 39 | bright5=${color13} # bright magenta 40 | bright6=${color14} # bright cyan 41 | bright7=${color15} # bright white 42 | 43 | ## dimmed colors (see foot.ini(5) man page) 44 | dim0=${dim.black} 45 | dim1=${dim.red} 46 | dim2=${dim.green} 47 | dim3=${dim.yellow} 48 | dim4=${dim.blue} 49 | dim5=${dim.magenta} 50 | dim6=${dim.cyan} 51 | dim7=${dim.white} 52 | 53 | ## The remaining 256-color palette 54 | # 16 = <256-color palette #16> 55 | # ... 56 | # 255 = <256-color palette #255> 57 | 58 | ## Misc colors 59 | # selection-foreground= 60 | # selection-background= 61 | # jump-labels= # black-on-yellow 62 | # scrollback-indicator= # black-on-bright-blue 63 | # search-box-no-match= # black-on-red 64 | # search-box-match= # black-on-yellow 65 | # urls= 66 | '') 67 | ]; 68 | }; 69 | }; 70 | } 71 | -------------------------------------------------------------------------------- /modules/themes/stilla/default.nix: -------------------------------------------------------------------------------- 1 | { options, config, lib, pkgs, ... }: 2 | 3 | with lib; 4 | with lib.my; 5 | let 6 | cfg = config.modules.theme; 7 | colorscheme = { 8 | stilla0 = "0D0D0D"; 9 | stilla1 = "121414"; 10 | stilla2 = "1A1C1C"; 11 | stilla3 = "4C566A"; 12 | stilla4 = "F2F2F2"; 13 | stilla5 = "FAFAFA"; 14 | stilla6 = "FAF5EF"; 15 | stilla7 = "8FBCBB"; 16 | stilla8 = "88B6D0"; 17 | stilla9 = "ADB2BA"; 18 | stilla10 = "5E81AC"; 19 | stilla11 = "BA8082"; 20 | stilla12 = "d99962"; 21 | stilla13 = "E9B872"; 22 | stilla14 = "A19C9A"; 23 | stilla15 = "CD96B3"; 24 | }; 25 | in { 26 | config = mkIf (cfg.active == "stilla") (mkMerge [ 27 | # Desktop-agnostic configuration 28 | { 29 | modules = { 30 | theme = { 31 | gtk = { 32 | theme = "Yaru"; 33 | iconTheme = "Zafiro-icons"; 34 | cursorTheme = "openzone-cursors"; 35 | }; 36 | color = with colorscheme; { 37 | foreground = stilla4; 38 | background = stilla0; 39 | fadeColor = stilla3; 40 | fgAlt = stilla6; 41 | bgAlt = stilla1; 42 | bgAlt2 = stilla2; 43 | color0 = stilla1; 44 | color1 = stilla11; 45 | color2 = stilla14; 46 | color3 = stilla13; 47 | color4 = stilla9; 48 | color5 = stilla15; 49 | color6 = stilla8; 50 | color7 = stilla5; 51 | color8 = stilla3; 52 | color9 = stilla11; 53 | color10 = stilla14; 54 | color11 = stilla13; 55 | color12 = stilla9; 56 | color13 = stilla15; 57 | color14 = stilla7; 58 | color15 = stilla6; 59 | normal = { 60 | black = stilla1; 61 | red = stilla11; 62 | green = stilla14; 63 | yellow = stilla13; 64 | blue = stilla9; 65 | magenta = stilla15; 66 | cyan = stilla8; 67 | white = stilla5; 68 | }; 69 | alt = { 70 | black = stilla3; 71 | red = stilla11; 72 | green = stilla14; 73 | yellow = stilla13; 74 | blue = stilla9; 75 | magenta = stilla15; 76 | cyan = stilla7; 77 | white = stilla6; 78 | }; 79 | dim = { 80 | black = "373e4d"; 81 | red = "94545d"; 82 | green = "809575"; 83 | yellow = "b29e75"; 84 | blue = "68809a"; 85 | magenta = "8c738c"; 86 | cyan = "6d96a5"; 87 | white = "aeb3bb"; 88 | }; 89 | urgent = "FF5555"; 90 | }; 91 | }; 92 | shell.tmux.rcFiles = [ ./config/tmux.conf ]; 93 | browsers = { 94 | firefox.userChrome = concatMapStringsSep "\n" readFile 95 | [ ./config/firefox/userChrome.css ]; 96 | }; 97 | }; 98 | } 99 | 100 | # Desktop theming 101 | { 102 | user.packages = with pkgs; 103 | [ yaru-theme zafiro-icons openzone-cursors ]; 104 | # ++ (if config.modules.media.spotify.enable then 105 | # [ extras.spicetify-nix.packages.x86_64-linux.stilla ] 106 | # else 107 | # [ ]); 108 | fonts = { 109 | packages = with pkgs; [ 110 | fira-code 111 | fira-code-symbols 112 | jetbrains-mono 113 | siji 114 | font-awesome 115 | roboto-mono 116 | ibm-plex 117 | ]; 118 | fontconfig.defaultFonts = { 119 | sansSerif = [ "Fira Sans" ]; 120 | monospace = [ "Berkeley Mono" ]; # was fira code 121 | }; 122 | }; 123 | 124 | home.configFile = mkIf config.modules.editors.vim.enable { 125 | "nvim/theme.vim" = { text = "colorscheme stilla"; }; 126 | }; 127 | } 128 | ]); 129 | } 130 | -------------------------------------------------------------------------------- /modules/vm/lxd.nix: -------------------------------------------------------------------------------- 1 | # Inspired by https://www.srid.ca/2012301.html 2 | 3 | { options, config, lib, pkgs, ... }: 4 | 5 | with lib; 6 | with lib.my; 7 | let cfg = config.modules.vm.lxd; 8 | in { 9 | options.modules.vm.lxd = { 10 | enable = mkBoolOpt false; 11 | }; 12 | 13 | config = mkIf cfg.enable { 14 | virtualisation.lxd.enable = true; 15 | 16 | user.packages = [ 17 | (pkgs.writeScriptBin "lxc-build-nixos-image" '' 18 | #!/usr/bin/env nix-shell 19 | #!nix-shell -i bash -p nixos-generators 20 | set -xe 21 | config=$1 22 | metaimg=`nixos-generate -f lxc-metadata \ 23 | | xargs -r cat \ 24 | | awk '{print $3}'` 25 | img=`nixos-generate -c $config -f lxc \ 26 | | xargs -r cat \ 27 | | awk '{print $3}'` 28 | lxc image import --alias nixos $metaimg $img 29 | '') 30 | ]; 31 | }; 32 | } 33 | -------------------------------------------------------------------------------- /modules/vm/qemu.nix: -------------------------------------------------------------------------------- 1 | { options, config, lib, pkgs, ... }: 2 | 3 | with lib; 4 | with lib.my; 5 | let cfg = config.modules.vm.qemu; 6 | in { 7 | options.modules.vm.qemu = { 8 | enable = mkBoolOpt false; 9 | }; 10 | 11 | config = mkIf cfg.enable { 12 | environment.systemPackages = with pkgs; [ 13 | qemu 14 | ]; 15 | }; 16 | } 17 | 18 | # Creating an image: 19 | # qemu-img create -f qcow2 disk.img 20 | # Creating a snapshot (don't tamper with disk.img): 21 | # qemu-img create -f qcow2 -b disk.img snapshot.img 22 | -------------------------------------------------------------------------------- /modules/vm/virtualbox.nix: -------------------------------------------------------------------------------- 1 | # modules/desktop/vm/virtualbox.nix 2 | # 3 | # For testing or building software on other OSes. If I find out how to get macOS 4 | # on qemu/libvirt I'd be happy to leave virtualbox behind. 5 | 6 | { options, config, lib, pkgs, ... }: 7 | 8 | with lib; 9 | with lib.my; 10 | let cfg = config.modules.vm.virtualbox; 11 | in { 12 | options.modules.vm.virtualbox = { 13 | enable = mkBoolOpt false; 14 | }; 15 | 16 | config = mkIf cfg.enable { 17 | virtualisation.virtualbox.host = { 18 | enable = true; 19 | # urg, takes so long to build, but needed for macOS guest 20 | enableExtensionPack = true; 21 | }; 22 | 23 | users.extraGroups.vboxusers.members = [ "jake" ]; 24 | user.extraGroups = [ "vboxusers" ]; 25 | }; 26 | } 27 | -------------------------------------------------------------------------------- /modules/wayland/default.nix: -------------------------------------------------------------------------------- 1 | # Nice-to-haves for all Wayland compositors. 2 | 3 | { config, lib, pkgs, ... }: 4 | 5 | with lib; 6 | with lib.my; 7 | let cfg = config.modules.wayland; 8 | in { 9 | 10 | options.modules.wayland = { enable = mkBoolOpt false; }; 11 | config = mkIf cfg.enable { 12 | env.XDG_SESSION_TYPE = "wayland"; 13 | 14 | modules.wayland.wofi.enable = true; 15 | 16 | user.extraGroups = [ 17 | # control video utilities 18 | "video" 19 | ]; 20 | 21 | programs.light.enable = true; 22 | 23 | user.packages = with pkgs; [ 24 | xwayland 25 | qt5.qtwayland 26 | wl-clipboard 27 | sway-contrib.grimshot 28 | wf-recorder 29 | # due to overlay these are now wayland clipboard interoperable 30 | xclip 31 | xsel 32 | # versatile audio control 33 | playerctl 34 | ]; 35 | }; 36 | } 37 | -------------------------------------------------------------------------------- /modules/wayland/kanshi.nix: -------------------------------------------------------------------------------- 1 | { config, lib, pkgs, ... }: 2 | # notifications for wayland 3 | 4 | with lib; 5 | with lib.my; 6 | let 7 | colors = config.modules.theme.color; 8 | cfg = config.modules.wayland.kanshi; 9 | in { 10 | options.modules.wayland.kanshi = { enable = mkBoolOpt false; }; 11 | 12 | config = mkIf cfg.enable { 13 | user.packages = with pkgs; [ kanshi ]; 14 | systemd.user.services.kanshi = { 15 | description = "Kanshi output autoconfig "; 16 | wantedBy = [ "graphical-session.target" ]; 17 | partOf = [ "graphical-session.target" ]; 18 | serviceConfig = { 19 | # kanshi doesn't have an option to specifiy config file yet, so it looks 20 | # at .config/kanshi/config 21 | ExecStart = '' 22 | ${pkgs.kanshi}/bin/kanshi 23 | ''; 24 | RestartSec = 5; 25 | Restart = "always"; 26 | }; 27 | }; 28 | home.configFile = { 29 | "kanshi/config" = { source = "${configDir}/kanshi/config"; }; 30 | }; 31 | }; 32 | } 33 | -------------------------------------------------------------------------------- /modules/wayland/mako.nix: -------------------------------------------------------------------------------- 1 | { config, lib, pkgs, ... }: 2 | # notifications for wayland 3 | 4 | with lib; 5 | with lib.my; 6 | let 7 | colors = config.modules.theme.color; 8 | cfg = config.modules.wayland.mako; 9 | in { 10 | options.modules.wayland.mako = { enable = mkBoolOpt false; }; 11 | 12 | config = mkIf cfg.enable { 13 | user.packages = with pkgs; [ mako ]; 14 | home.configFile = { 15 | "mako/config".text = with colors; '' 16 | sort=-time 17 | layer=overlay 18 | max-visible=-1 19 | background-color=#${background} 20 | border-color=#${color0} 21 | text-color=#${foreground} 22 | width=300 23 | height=110 24 | border-size=1 25 | default-timeout=5000 26 | ignore-timeout=1 27 | margin=10,12 28 | 29 | [urgency=low] 30 | background-color=#${background} 31 | border-color=#${color0} 32 | 33 | [urgency=normal] 34 | background-color=#${background} 35 | border-color=#${color0} 36 | 37 | [urgency=high] 38 | background-color=#${urgent} 39 | border-color=#${urgent} 40 | default-timeout=0 41 | 42 | [category=mpd] 43 | default-timeout=2000 44 | group-by=category 45 | 46 | [category=spotify] 47 | default-timeout=2000 48 | group-by=category 49 | ''; 50 | }; 51 | }; 52 | } 53 | -------------------------------------------------------------------------------- /modules/wayland/swaylock.nix: -------------------------------------------------------------------------------- 1 | { config, lib, pkgs, ... }: 2 | # lock for wayland 3 | 4 | with lib; 5 | with lib.my; 6 | let 7 | colors = config.modules.theme.color; 8 | cfg = config.modules.wayland.swaylock; 9 | lock = with pkgs; (writeScriptBin "lock" '' 10 | #!${stdenv.shell} 11 | ${playerctl}/bin/playerctl pause & 12 | ${swaylock-effects}/bin/swaylock 13 | ''); 14 | screenOff = with pkgs; (writeScriptBin "screenOff" '' 15 | #!${stdenv.shell} 16 | swaymsg "output * dpms off" 17 | ''); 18 | screenOn = with pkgs; (writeScriptBin "screenOn" '' 19 | #!${stdenv.shell} 20 | swaymsg "output * dpms off" 21 | ''); 22 | in { 23 | options.modules.wayland.swaylock = { 24 | enable = mkBoolOpt false; 25 | }; 26 | 27 | config = mkIf cfg.enable { 28 | systemd.user.services.swayidle = { 29 | enable = true; 30 | description = "Idle Manager for Wayland"; 31 | documentation = [ "man:swayidle(1)" ]; 32 | wantedBy = [ "sway-session.target" ]; 33 | partOf = [ "graphical-session.target" ]; 34 | serviceConfig = { 35 | ExecStart = '' 36 | ${pkgs.swayidle}/bin/swayidle \ 37 | timeout 300 '${lock}/bin/lock' \ 38 | timeout 600 '${screenOff}/bin/screenOff' \ 39 | resume '${screenOn}/bin/screenOn' \ 40 | before-sleep '${lock}/bin/lock' 41 | ''; 42 | }; 43 | }; 44 | 45 | user.packages = with pkgs; [ lock swayidle screenOff screenOn ]; 46 | home.configFile = { 47 | "swaylock/config".text = (with colors; '' 48 | line-color=${colors.background} 49 | inside-color=${colors.background} 50 | ring-color=${background} 51 | separator-color=${colors.foreground} 52 | key-hl-color=${colors.foreground} 53 | 54 | line-wrong-color=${colors.background} 55 | inside-wrong-color=${colors.urgent} 56 | ring-wrong-color=${colors.urgent} 57 | 58 | line-ver-color=${colors.background} 59 | inside-ver-color=${colors.background} 60 | ring-ver-color=${colors.background} 61 | 62 | grace=30 63 | screenshots 64 | fade-in=0.15 65 | effect-pixelate=20 66 | indicator-radius=50 67 | ''); 68 | }; 69 | }; 70 | } 71 | -------------------------------------------------------------------------------- /modules/wayland/waybar.nix: -------------------------------------------------------------------------------- 1 | { config, lib, pkgs, ... }: 2 | # notifications for wayland 3 | 4 | with lib; 5 | with lib.my; 6 | let 7 | colors = config.modules.theme.color; 8 | cfg = config.modules.wayland.waybar; 9 | in { 10 | options.modules.wayland.waybar = { enable = mkBoolOpt false; }; 11 | 12 | config = mkIf cfg.enable { 13 | user.packages = with pkgs; 14 | [ 15 | (if config.modules.hardware.audio.enable then 16 | waybar.override { pulseSupport = true; } 17 | else 18 | waybar) 19 | ]; 20 | home.configFile = { 21 | "waybar/config" = { source = "${configDir}/waybar/config"; }; 22 | 23 | # waybar inspiration credit goes to github.com/jakehamilton! 24 | "waybar/style.css".text = (with colors; 25 | concatStrings [ 26 | '' 27 | @define-color foreground #${fgAlt}; 28 | @define-color background #${background}; 29 | @define-color buttonhover #${urgent}; 30 | @define-color fgalt #${fgAlt}; 31 | @define-color bgalt #${bgAlt2}; 32 | @define-color cyan #${normal.cyan}; 33 | @define-color green #${normal.green}; 34 | @define-color yellow #${normal.yellow}; 35 | @define-color blue #${normal.blue}; 36 | @define-color purple #${normal.magenta}; 37 | @define-color cyanalt #${dim.cyan}; 38 | @define-color greenalt #${dim.green}; 39 | @define-color yellowalt #${dim.yellow}; 40 | @define-color bluealt #${dim.blue}; 41 | @define-color purplealt #${dim.magenta}; 42 | '' 43 | (concatMapStringsSep "\n" readFile 44 | [ "${configDir}/waybar/style.css" ]) 45 | ]); 46 | }; 47 | }; 48 | } 49 | -------------------------------------------------------------------------------- /modules/wayland/wofi.nix: -------------------------------------------------------------------------------- 1 | { options, config, lib, pkgs, ... }: 2 | 3 | with lib; 4 | with lib.my; 5 | let 6 | cfg = config.modules.wayland.wofi; 7 | colors = config.modules.theme.color; 8 | in { 9 | options.modules.wayland.wofi = { enable = mkBoolOpt false; }; 10 | 11 | config = mkIf cfg.enable { 12 | user.packages = with pkgs; [ 13 | wofi 14 | (writeScriptBin "launch" '' 15 | #!${stdenv.shell} 16 | exec ${wofi}/bin/wofi --show drun 17 | '') 18 | ]; 19 | 20 | home.configFile = { 21 | "wofi/config".text = '' 22 | width=15% 23 | lines=5 24 | allow_images=false 25 | insensitive=true 26 | mode=drun 27 | ''; 28 | "wofi/style.css".text = with colors; '' 29 | window { 30 | margin: 0px; 31 | border-width: 0px; 32 | border-radius: 0px; 33 | } 34 | 35 | #input { 36 | color: #${color4}; 37 | padding: 8px; 38 | background-color: #${background}; 39 | border-width: 1px 1px 1px 1px; 40 | border-color: #${color10}; 41 | } 42 | 43 | #inner-box { 44 | border-color: #${color10}; 45 | border-width: 0px 1px 1px 1px; 46 | background-color: #${background}; 47 | } 48 | 49 | #outer-box { 50 | border-width: 0px 1px 1px 1px; 51 | background-color: #${background}; 52 | } 53 | 54 | #scroll { 55 | margin: 0px; 56 | border: none; 57 | } 58 | 59 | #text { 60 | color: #${color4}; 61 | padding: 5px; 62 | border: none; 63 | } 64 | 65 | button { 66 | padding: 6px; 67 | color: #${foreground}; 68 | border-width: 2px 0px 2px 2px; 69 | border-color: #${foreground}; 70 | } 71 | 72 | button selected normal { 73 | border-width: 0; 74 | } 75 | ''; 76 | }; 77 | }; 78 | } 79 | -------------------------------------------------------------------------------- /modules/xdg.nix: -------------------------------------------------------------------------------- 1 | # xdg.nix 2 | # 3 | # Set up and enforce XDG compliance. Other modules will take care of their own, 4 | # but this takes care of the general cases. 5 | { config, home-manager, ... }: { 6 | ### A tidy $HOME is a tidy mind 7 | home-manager.users.${config.user.name}.xdg.enable = true; 8 | 9 | environment = { 10 | sessionVariables = { 11 | # These are the defaults, and xdg.enable does set them, but due to load 12 | # order, they're not set before environment.variables are set, which could 13 | # cause race conditions. 14 | XDG_CACHE_HOME = "$HOME/.cache"; 15 | XDG_CONFIG_HOME = "$HOME/.config"; 16 | XDG_DATA_HOME = "$HOME/.local/share"; 17 | XDG_BIN_HOME = "$HOME/.local/bin"; 18 | 19 | # Prevent auto-creation of ~/Desktop. The trailing slash is necessary; see 20 | # https://bugzilla.mozilla.org/show_bug.cgi?id=1082717 21 | XDG_DESKTOP_DIR = "$HOME/"; 22 | XDG_DOWNLOAD_DIR = "$HOME/"; 23 | XDG_DOWNLOADS_DIR = "$HOME/"; 24 | XDG_PICTURES_DIR = "$HOME/pics/"; 25 | XDG_MUSIC_DIR = "$HOME/music/"; 26 | }; 27 | variables = { 28 | # Conform more programs to XDG conventions. The rest are handled by their 29 | # respective modules. 30 | __GL_SHADER_DISK_CACHE_PATH = "$XDG_CACHE_HOME/nv"; 31 | ASPELL_CONF = '' 32 | per-conf $XDG_CONFIG_HOME/aspell/aspell.conf; 33 | personal $XDG_CONFIG_HOME/aspell/en_US.pws; 34 | repl $XDG_CONFIG_HOME/aspell/en.prepl; 35 | ''; 36 | CUDA_CACHE_PATH = "$XDG_CACHE_HOME/nv"; 37 | HISTFILE = "$XDG_DATA_HOME/bash/history"; 38 | INPUTRC = "$XDG_CONFIG_HOME/readline/inputrc"; 39 | LESSHISTFILE = "$XDG_CACHE_HOME/lesshst"; 40 | # WGETRC = "$XDG_CONFIG_HOME/wgetrc"; -- I don't use this 41 | 42 | # Tools I don't use 43 | # SUBVERSION_HOME = "$XDG_CONFIG_HOME/subversion"; 44 | # BZRPATH = "$XDG_CONFIG_HOME/bazaar"; 45 | # BZR_PLUGIN_PATH = "$XDG_DATA_HOME/bazaar"; 46 | # BZR_HOME = "$XDG_CACHE_HOME/bazaar"; 47 | # ICEAUTHORITY = "$XDG_CACHE_HOME/ICEauthority"; 48 | }; 49 | 50 | # Move ~/.Xauthority out of $HOME (setting XAUTHORITY early isn't enough) 51 | extraInit = '' 52 | export XAUTHORITY=/tmp/Xauthority 53 | [ -e ~/.Xauthority ] && mv -f ~/.Xauthority "$XAUTHORITY" 54 | ''; 55 | 56 | }; 57 | } 58 | -------------------------------------------------------------------------------- /overlays/x-clipboard.nix: -------------------------------------------------------------------------------- 1 | final: prev: { 2 | wl-clipboard-x11 = prev.stdenv.mkDerivation rec { 3 | pname = "wl-clipboard-x11"; 4 | version = "5"; 5 | 6 | src = prev.fetchFromGitHub { 7 | owner = "brunelli"; 8 | repo = "wl-clipboard-x11"; 9 | rev = "v${version}"; 10 | sha256 = "1y7jv7rps0sdzmm859wn2l8q4pg2x35smcrm7mbfxn5vrga0bslb"; 11 | }; 12 | 13 | dontBuild = true; 14 | dontConfigure = true; 15 | propagatedBuildInputs = [ prev.wl-clipboard ]; 16 | makeFlags = [ "PREFIX=$(out)" ]; 17 | }; 18 | 19 | xsel = final.wl-clipboard-x11; 20 | xclip = final.wl-clipboard-x11; 21 | } 22 | -------------------------------------------------------------------------------- /packages/.git-keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jakeisnt/nixcfg/e9230d4f90a855a290882a6e7862c593a114cf5e/packages/.git-keep -------------------------------------------------------------------------------- /shell.nix: -------------------------------------------------------------------------------- 1 | (import 2 | ( 3 | let 4 | flake-compat = (builtins.fromJSON (builtins.readFile ./flake.lock)).nodes.flake-compat; 5 | in 6 | fetchTarball { 7 | url = "https://github.com/edolstra/flake-compat/archive/${flake-compat.locked.rev}.tar.gz"; 8 | sha256 = flake-compat.locked.narHash; 9 | } 10 | ) 11 | {src = ./.;}) 12 | .shellNix 13 | -------------------------------------------------------------------------------- /templates/flake/.envrc: -------------------------------------------------------------------------------- 1 | if has nix; then 2 | use nix 3 | fi 4 | -------------------------------------------------------------------------------- /templates/flake/flake.nix: -------------------------------------------------------------------------------- 1 | { 2 | description = "An empty project"; 3 | 4 | inputs = { 5 | nixpkgs.url = "github:nixos/nixpkgs/release-24.05"; 6 | flake-utils.url = "github:numtide/flake-utils"; 7 | zig.url = "github:mitchellh/zig-overlay"; 8 | 9 | # Used for shell.nix 10 | flake-compat = { 11 | url = github:edolstra/flake-compat; 12 | flake = false; 13 | }; 14 | }; 15 | 16 | outputs = { 17 | self, 18 | nixpkgs, 19 | flake-utils, 20 | ... 21 | } @ inputs: let 22 | overlays = [ ]; 23 | in 24 | flake-utils.lib.eachDefaultSystem ( 25 | system: let 26 | pkgs = import nixpkgs {inherit overlays system;}; 27 | in rec { 28 | devShells.default = pkgs.mkShell { 29 | nativeBuildInputs = with pkgs; [ 30 | ]; 31 | }; 32 | 33 | # For compatibility with older versions of the `nix` binary 34 | devShell = self.devShells.${system}.default; 35 | } 36 | ); 37 | } 38 | -------------------------------------------------------------------------------- /templates/flake/shell.nix: -------------------------------------------------------------------------------- 1 | (import 2 | ( 3 | let 4 | flake-compat = (builtins.fromJSON (builtins.readFile ./flake.lock)).nodes.flake-compat; 5 | in 6 | fetchTarball { 7 | url = "https://github.com/edolstra/flake-compat/archive/${flake-compat.locked.rev}.tar.gz"; 8 | sha256 = flake-compat.locked.narHash; 9 | } 10 | ) 11 | {src = ./.;}) 12 | .shellNix 13 | --------------------------------------------------------------------------------