diff --git a/.gitignore b/.gitignore index ce548ea9..b2be92b7 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1 @@ -secrets.nix result diff --git a/Makefile b/Makefile deleted file mode 100644 index 3bb18952..00000000 --- a/Makefile +++ /dev/null @@ -1,77 +0,0 @@ -USER := hlissner -HOST := kuro -HOME := /home/$(USER) - -NIXOS_VERSION := 20.03 -NIXOS_PREFIX := $(PREFIX)/etc/nixos -COMMAND := test -FLAGS := -I "config=$$(pwd)/config" \ - -I "modules=$$(pwd)/modules" \ - -I "bin=$$(pwd)/bin" \ - $(FLAGS) - -# The real Labowski -all: channels - @sudo nixos-rebuild $(FLAGS) $(COMMAND) - -install: channels update config move_to_home - @sudo nixos-install --root "$(PREFIX)" $(FLAGS) - -upgrade: update switch - -update: channels - @sudo nix-channel --update - -switch: - @sudo nixos-rebuild $(FLAGS) switch - -build: - @sudo nixos-rebuild $(FLAGS) build - -boot: - @sudo nixos-rebuild $(FLAGS) boot - -rollback: - @sudo nixos-rebuild $(FLAGS) --rollback $(COMMAND) - -dry: - @sudo nixos-rebuild $(FLAGS) dry-build - -gc: - @nix-collect-garbage -d - -vm: - @sudo nixos-rebuild $(FLAGS) build-vm - -clean: - @rm -f result - - -# Parts -config: $(NIXOS_PREFIX)/configuration.nix -move_to_home: $(HOME)/.dotfiles - -channels: - @sudo nix-channel --add "https://nixos.org/channels/nixos-${NIXOS_VERSION}" nixos - @sudo nix-channel --add "https://nixos.org/channels/nixos-unstable" nixos-unstable - @sudo nix-channel --add "https://github.com/rycee/home-manager/archive/release-${NIXOS_VERSION}.tar.gz" home-manager - @sudo nix-channel --add "https://nixos.org/channels/nixpkgs-unstable" nixpkgs-unstable - -$(NIXOS_PREFIX)/configuration.nix: - @sudo nixos-generate-config --root "$(PREFIX)" - @echo "import /etc/dotfiles \"$${HOST:-$$(hostname)}\" \"$$USER\"" | sudo tee "$(NIXOS_PREFIX)/configuration.nix" - @[ -f machines/$(HOST).nix ] || echo "WARNING: hosts/$(HOST)/default.nix does not exist" - -$(HOME)/.dotfiles: - @mkdir -p $(HOME) - @[ -e $(HOME)/.dotfiles ] || sudo mv /etc/dotfiles $(HOME)/.dotfiles - @[ -e /etc/dotfiles ] || sudo ln -s $(HOME)/.dotfiles /etc/dotfiles - @chown $(USER):users $(HOME) $(HOME)/.dotfiles - -# Convenience aliases -i: install -s: switch -up: upgrade - - -.PHONY: config diff --git a/README.md b/README.md index 83504844..88790718 100644 --- a/README.md +++ b/README.md @@ -1,71 +1,85 @@ +
+ [![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) -[![NixOS 20.03](https://img.shields.io/badge/NixOS-v20.03-blue.svg?style=flat-square&logo=NixOS&logoColor=white)](https://nixos.org) +[![NixOS 20.09](https://img.shields.io/badge/NixOS-v20.09-blue.svg?style=flat-square&logo=NixOS&logoColor=white)](https://nixos.org) -![Me looking busy](/../screenshots/fluorescence/fakebusy.png?raw=true) +
+ +**Hey,** you. You're finally awake. You were trying to configure your OS declaratively, right? Walked right into that NixOS ambush, same as us, and those dotfiles over there. + +

- - - + + +

-# My dotfiles +------ -+ **Operating System:** NixOS -+ **Shell:** zsh + zgen -+ **DM:** lightdm + lightdm-mini-greeter -+ **WM:** bspwm + polybar -+ **Editor:** [Doom Emacs][doom-emacs] (and occasionally [vim][vimrc]) -+ **Terminal:** st -+ **Launcher:** rofi -+ **Browser:** firefox -+ **GTK Theme:** [Ant Dracula](https://github.com/EliverLara/Ant-Dracula) -+ **Icon Theme:** [Paper Mono Dark](https://github.com/snwh/paper-icon-theme) +| | | +|-|-| +| **Shell:** | zsh + zgen | +| **DM:** | lightdm + lightdm-mini-greeter | +| **WM:** | bspwm + polybar | +| **Editor:** | [Doom Emacs][doom-emacs] (and occasionally [vim]) | +| **Terminal:** | st | +| **Launcher:** | rofi | +| **Browser:** | firefox | +| **GTK Theme:** | [Ant Dracula](https://github.com/EliverLara/Ant-Dracula) | -*Works on my machine* ¯\\\_(ツ)_/¯ +----- ## Quick start -```sh -# Assumes your partitions are set up and root is mounted on /mnt -git clone https://github.com/hlissner/dotfiles /etc/dotfiles -make -C /etc/dotfiles install -``` +1. Yoink [NixOS 20.09][nixos] (must be newer than Sept 12, 2020 for `nixos-install --flake`). +2. Boot into the installer. +3. Do your partitions and mount your root to `/mnt` +4. `git clone https://github.com/hlissner/dotfiles /etc/nixos` +5. Install NixOS: `nixos-install --root /mnt --flake #XYZ`, where `XYZ` is your + hostname. Use `#generic` for a simple, universal config. +6. OPTIONAL: Create a sub-directory in `hosts/` for your device. See [host/kuro] + as an example. +7. Reboot! -Which is equivalent to: +## Management -```sh -USER=${USER:-hlissner} -HOST=${HOST:-kuro} -NIXOS_VERSION=20.03 -DOTFILES=/home/$USER/.dotfiles +Behold. `bin/hey`. -git clone https://github.com/hlissner/dotfiles /etc/dotfiles -ln -s /etc/dotfiles $DOTFILES -chown -R $USER:users $DOTFILES +| Command | Description | +|----------------------|-----------------------------------------------------------------| +| `hey rebuild` | Rebuild this flake | +| `hey upgrade` | Update flake lockfile and switch to it | +| `hey rollback` | Roll back to previous system generation | +| `hey gc` | Runs `nix-collect-garbage -d`. Use sudo to clean system profile | +| `hey deploy REMOTE` | Deploy these dotfiles to REMOTE (over ssh) | +| `hey check` | Run tests and checks for this flake | +| `hey show` | Show flake outputs of this repo | -# make channels -nix-channel --add "https://nixos.org/channels/nixos-${NIXOS_VERSION}" nixos -nix-channel --add "https://github.com/rycee/home-manager/archive/release-${NIXOS_VERSION}.tar.gz" home-manager -nix-channel --add "https://nixos.org/channels/nixpkgs-unstable" nixpkgs-unstable +## Frequently asked questions -# make /etc/nixos/configuration.nix -nixos-generate-config --root /mnt -echo "import /etc/dotfiles \"$$HOST\" \"$$USER\"" >/mnt/etc/nixos/configuration.nix ++ **How do I change the default username?** -# make install -nixos-install --root /mnt -I "my=/etc/dotfiles" -``` + 1. Set `USER` the first time you run `nixos-install`: `USER=myusername + nixos-install --root /mnt --flake #XYZ` + 2. Or change `"hlissner"` in modules/options.nix. -### Management ++ **How do I "set up my partitions"?** -+ `make` = `nixos-rebuild test` -+ `make switch` = `nixos-rebuild switch` -+ `make upgrade` = `nix-channel --update && nixos-rebuild switch` -+ `make install` = `nixos-generate-config --root $PREFIX && nixos-install --root - $PREFIX` -+ `make gc` = `nix-collect-garbage -d` (use sudo to clear system profile) + My main host [has a README](hosts/kuro/README.org) you can use as a reference. + I set up an EFI+GPT system and partitions with `parted` and `zfs`. + ++ **How 2 flakes?** + + It wouldn't be the NixOS experience if I gave you all the answers in one, + convenient place. + ++ **Why is the script called `hey`?** + + And I say... https://www.youtube.com/watch?v=ZZ5LpwO-An4 [doom-emacs]: https://github.com/hlissner/doom-emacs -[vimrc]: https://github.com/hlissner/.vim +[vim]: https://github.com/hlissner/.vim +[nixos]: https://releases.nixos.org/?prefix=nixos/20.09-small/ +[host/kuro]: https://github.com/hlissner/dotfiles/tree/master/hosts/kuro diff --git a/bin/hey b/bin/hey new file mode 100755 index 00000000..e1d8ff90 --- /dev/null +++ b/bin/hey @@ -0,0 +1,135 @@ +#!/usr/bin/env zsh + +# I don't believe the interface for Nix's utility scripts are very good. Guix's, +# on the other hand, is excellent. Management of your OS is done by a single +# program with simpler, more intuitive commands. This script is a rudimentary +# attempt at giving me that. +# +# dots cd|check -> nix flake check $DOTFILES +# dots sh|show -> nix flake show $DOTFILES +# dots u|update -> nix flake update --recreate-lock-file $DOTFILES +# dots re|rebuild -> nixos-rebuild --flake $DOTFILES#$HOSTNAME ${1:-build} +# dots rollback -> dots rebuild --rollback switch +# dots vm -> dots rebuild vm +# dots up|upgrade -> dots update && dots rebuild switch +# dots gc -> GC user profile, optimise nix store +# sudo dots gc -> GC, optimise nix store, & delete old boot entries +# dots push REMOTE -> push flake to remote (over SSH) and rebuild remotely +# dots gen|generations -> explore, manage, diff across generations (WIP) +# +# dots (with no sub-command) can also be used as an alternative to nix-env: +# +# dots -q +# dots -iA nixos.htop +# dots -e htop + +set -e +REMOTE=${REMOTE:-"~/.config/dotfiles"} +DOTFILES="${0:a:h}/.." + +# +function main { + function _do { [[ $DRYRUN ]] && echo "$@" || "$@" } + + ### Helpers + function _usage { + echo "Usage: dots COMMAND [FLAGS...] [ARGS...]" + echo + echo "Available commands:" + echo " init TODO" + echo " env (e) TODO" + echo " shell (sh) TODO" + echo " build (b) TODO" + echo " upgrade (up) TODO" + echo " rebuild (re) TODO" + echo " rollback TODO" + echo " gc TODO" + echo " vm TODO" + echo " repl TODO" + echo " push Push thie config to a remote NixOS system and rebuild it" + echo " generations (gen) TODO" + } + + function _rebuild { + # Move to $DOTFILES to prevent polluting the system with result links + pushd $DOTFILES >/dev/null + _do sudo nixos-rebuild --flake ".#$HOSTNAME" ${@:-build} + popd >/dev/null + } + + function _update { + echo "Updating NixOS flake" + _do nix flake update --recreate-lock-file "$DOTFILES" + } + + function _gc { + if [[ $EUID == 0 ]]; then + echo "Cleaning up your system..." + _do sudo nix-collect-garbage ${@:--d} + # nix-collect-garbage is a Nix tool, not a NixOS tool. It won't delete old + # boot entries until you do a nixos-rebuild (which means we'll always have + # 2 boot entries at any time). Instead, we properly delete them by + # reloading the current environment. + _do sudo nix-env --delete-generations old --profile /nix/var/nix/profiles/system + _do sudo /nix/var/nix/profiles/system/bin/switch-to-configuration switch + else + echo "Cleaning up your user profile..." + _do nix-collect-garbage ${@:--d} + fi + _do nix-store --optimise + } + + ### + cmd="$1" + [[ $# > 0 ]] && shift + case "$cmd" in + # TODO Repl/shell for nixos+dotfiles + # sh|shell) _do nix-shell "$@" ;; + # repl) _do nix develop "$@" ;; + + ch|check) _do nix flake check "$DOTFILES";; + sh|show) _do nix flake show "$DOTFILES" ;; + + re|rebuild) _rebuild "${@:-switch}" ;; + rollback) _rebuild --rollback switch ;; + vm) _rebuild "$@" vm ;; + + u|update) _update "$@" ;; + up|upgrade) _update && _rebuild switch ;; + + gc) _gc "$@" ;; + push) + rsync -avzh ./ "$1:$REMOTE/" + ssh -t -l "$USERNAME" "$1" "$REMOTE/dots re" "${@[2,-1]}" + ;; + + gen|generations) + profile=/nix/var/nix/profiles/system + case "$1" in + switch) >&2 echo "Targeted rollback not supported yet" ;; # TODO Is this true? + diff) + to=/nix/var/nix/profiles/system-${2}-link + diff \ + <(nix-store -q --references $profile) \ + <(nix-store -q --references $to) + ;; + remove) + shift + _do sudo nix-env --delete-generations --profile $profile $@ + ;; + "") + _do sudo nix-env --list-generations --profile $profile + ;; + esac + ;; + + h|help|-h|--help) _usage ;; + -*) _do nix-env "$cmd" "$@" ;; + "") _usage ;; + *) echo "Couldn't find command: $cmd" 1>&2 + exit 1 + ;; + esac +} + +main "$@" diff --git a/bin/scrcap b/bin/scrcap index c5739e8d..5304ba87 100755 --- a/bin/scrcap +++ b/bin/scrcap @@ -5,8 +5,7 @@ # capture) and stores it in the clipboard. tmp=$(mktemp) -cleanup() { rm -f "$tmp"; } -trap cleanup EXIT +trap "rm -f '$tmp'" EXIT # Delay for long enough that we can refocus the targeted window if maim --delay=${2:-1} -us >"$tmp"; then diff --git a/config/bspwm/bspwmrc b/config/bspwm/bspwmrc index 43e24cd6..1f918b0d 100755 --- a/config/bspwm/bspwmrc +++ b/config/bspwm/bspwmrc @@ -1,5 +1,10 @@ #!/usr/bin/env bash +# case $HOSTNAME in +# kuro) export LAN=eno1 ;; +# shiro) export LAN=wlp3s0 ;; +# esac + export MONITOR=$(xrandr -q | grep primary | cut -d' ' -f1) export MONITORS=( $(xrandr -q | grep ' connected' | cut -d' ' -f1) ) MONITOR=${MONITOR:-${MONITORS[0]}} diff --git a/config/git/aliases.zsh b/config/git/aliases.zsh index 1fe7f9a4..708fedf5 100644 --- a/config/git/aliases.zsh +++ b/config/git/aliases.zsh @@ -1,9 +1,8 @@ #!/usr/bin/env zsh g() { [[ $# = 0 ]] && git status --short . || git $*; } -compdef g=hub -alias git='noglob hub' +alias git='noglob git' alias ga='git add' alias gap='git add --patch' alias gb='git branch' diff --git a/modules/media/ncmpcpp.nix b/config/rofi/snippets/issue-resolved similarity index 100% rename from modules/media/ncmpcpp.nix rename to config/rofi/snippets/issue-resolved diff --git a/modules/themes/aquanaut/README.md b/config/rofi/snippets/pr-merged similarity index 100% rename from modules/themes/aquanaut/README.md rename to config/rofi/snippets/pr-merged diff --git a/config/stumpwm/config b/config/stumpwm/config index fb9cb6e4..ed0213ef 100644 --- a/config/stumpwm/config +++ b/config/stumpwm/config @@ -10,7 +10,7 @@ ;; :port swank::default-server-port) ;;; -(defvar *config-dir* "~/.dotfiles/config/stumpwm") +(defvar *config-dir* "~/.config/dotfiles/config/stumpwm") (defcommand reload-dotfiles () () (load (concat *config-dir* "/config")) diff --git a/config/sxhkd/sxhkdrc b/config/sxhkd/sxhkdrc index 9c4bf036..3a314d25 100644 --- a/config/sxhkd/sxhkdrc +++ b/config/sxhkd/sxhkdrc @@ -25,16 +25,16 @@ super + shift + grave emacsclient -e '(open-scratch-frame)' super + space - ~/.dotfiles/bin/rofi/appmenu + ~/.config/dotfiles/bin/rofi/appmenu super + Tab - ~/.dotfiles/bin/rofi/windowmenu + ~/.config/dotfiles/bin/rofi/windowmenu super + backslash - ~/.dotfiles/bin/rofi/passmenu + ~/.config/dotfiles/bin/rofi/passmenu super + slash - ~/.dotfiles/bin/rofi/filemenu -x + ~/.config/dotfiles/bin/rofi/filemenu -x super + Escape pkill -USR1 -x sxhkd @@ -52,21 +52,21 @@ super + {_,ctrl + }f super + {_,ctrl +}{h,j,k,l} - ~/.dotfiles/bin/bspwm/focus {_,-m }{west,south,north,east} + ~/.config/dotfiles/bin/bspwm/focus {_,-m }{west,south,north,east} super + shift + {_,ctrl +}{h,j,k,l} - ~/.dotfiles/bin/bspwm/swap {_,-m }{west,south,north,east} + ~/.config/dotfiles/bin/bspwm/swap {_,-m }{west,south,north,east} ## Resize by preselection super + alt + {1-9} - ~/.dotfiles/bin/bspwm/presel 0.{1-9} + ~/.config/dotfiles/bin/bspwm/presel 0.{1-9} super + alt + {h,j,k,l} bspc node -p {west,south,north,east} super + alt + Return - ~/.dotfiles/bin/bspwm/subtract-presel + ~/.config/dotfiles/bin/bspwm/subtract-presel super + alt + Delete bspc node -p cancel diff --git a/config/tmux/config b/config/tmux/config index 44e71b55..273bc927 100644 --- a/config/tmux/config +++ b/config/tmux/config @@ -92,7 +92,7 @@ bind - break-pane bind _ join-pane # reload config without killing server -bind r source-file ~/.dotfiles/config/tmux/config \; display-message " Config reloaded..". +bind r source-file ~/.config/dotfiles/config/tmux/config \; display-message " Config reloaded..". bind ^r refresh-client diff --git a/config/zsh/.zshrc b/config/zsh/.zshrc index cb2cdb35..a14a06da 100644 --- a/config/zsh/.zshrc +++ b/config/zsh/.zshrc @@ -1,6 +1,3 @@ -export ZGEN_DIR="$XDG_CACHE_HOME/zgen" -export ZGEN_SOURCE="$ZGEN_DIR/zgen.zsh" - [ -d "$ZGEN_DIR" ] || git clone https://github.com/tarjoilija/zgen "$ZGEN_DIR" source $ZGEN_SOURCE if ! zgen saved; then diff --git a/config/zsh/aliases.zsh b/config/zsh/aliases.zsh index 516b4979..098ffbad 100644 --- a/config/zsh/aliases.zsh +++ b/config/zsh/aliases.zsh @@ -20,6 +20,16 @@ alias gurl='curl --compressed' alias y='xclip -selection clipboard -in' alias p='xclip -selection clipboard -out' +alias sc=systemctl +alias ssc='sudo systemctl' + +if command -v exa >/dev/null; then + alias exa="exa --group-directories-first"; + alias l="exa -1"; + alias ll="exa -lg"; + alias la="LC_COLLATE=C exa -la"; +fi + autoload -U zmv take() { diff --git a/config/zsh/completion.zsh b/config/zsh/completion.zsh index 7f6b0ca2..d3b47639 100644 --- a/config/zsh/completion.zsh +++ b/config/zsh/completion.zsh @@ -1,3 +1,5 @@ +fpath+=( $ZDOTDIR/completions ) + ## Options setopt COMPLETE_IN_WORD # Complete from both ends of a word. setopt PATH_DIRS # Perform path search even on command names with slashes. diff --git a/config/zsh/completions/_dots b/config/zsh/completions/_dots new file mode 100755 index 00000000..6b5fc0f8 --- /dev/null +++ b/config/zsh/completions/_dots @@ -0,0 +1,35 @@ +#compdef nix + +_dots_dispatch () { + local cmd="$@" + local offset=$# + CURRENT=$((CURRENT-$offset)) + words=($cmd "${words[$((2 + offset)),-1]}") + _$cmd +} + +_dots_command_list () { + dots | sed '1,/Available commands:/d' | awk '{ print $1 }' +} + +_dots () { + local -a commands + IFS=$'\n' commands=($(_dots_command_list)) + + if (( CURRENT == 2 )); then + _describe -t commands "dots commands" commands + return + fi + integer ret=1 + case ${words[2]} in + ch|channel) _dots_dispatch nix-channel ;; + b|build) _dots_dispatch nix-build ;; + ch|check) _dots_dispatch nix flake check ;; + sh|show) _dots_dispatch nix flake show ;; + -*) _dots_dispatch nix-env ;; + *) _message "Command not found: ${words[2]}" ;; + esac + return ret +} + +_dots diff --git a/config/zsh/config.zsh b/config/zsh/config.zsh index 06f08452..048e8470 100644 --- a/config/zsh/config.zsh +++ b/config/zsh/config.zsh @@ -32,7 +32,7 @@ unsetopt HUP # Don't kill jobs on shell exit. unsetopt CHECK_JOBS # Don't report on jobs when shell exit. ## History -HISTFILE="$HOME/.cache/zhistory" +HISTFILE="$XDG_CACHE_HOME/zhistory" HISTSIZE=1000 # Max events to store in internal history. SAVEHIST=1000 # Max events to store in history file. diff --git a/default.nix b/default.nix deleted file mode 100644 index 9be56d44..00000000 --- a/default.nix +++ /dev/null @@ -1,76 +0,0 @@ -# default.nix --- the heart of my dotfiles -# -# Author: Henrik Lissner -# URL: https://github.com/hlissner/dotfiles -# License: MIT -# -# This is ground zero, where the absolute essentials go, to be present on all -# systems I use nixos on. Most of which are single user systems (the ones that -# aren't are configured from their hosts/*/default.nix). - -device: username: -{ pkgs, options, lib, config, ... }: -{ - networking.hostName = lib.mkDefault device; - my.username = username; - - imports = [ - ./modules - "${./hosts}/${device}" - ] ++ (if builtins.pathExists(/etc/nixos/cachix.nix) then [ - /etc/nixos/cachix.nix - ] else []); - - ### NixOS - nix.autoOptimiseStore = true; - nix.nixPath = options.nix.nixPath.default ++ [ - # So we can use absolute import paths - "bin=/etc/dotfiles/bin" - "config=/etc/dotfiles/config" - ]; - - # Add custom packages & unstable channel, so they can be accessed via pkgs.* - nixpkgs.overlays = import ./packages; - nixpkgs.config.allowUnfree = true; # forgive me Stallman senpai - - # These are the things I want installed on all my systems - environment.systemPackages = with pkgs; [ - # Just the bear necessities~ - coreutils - git - killall - unzip - vim - wget - sshfs - - gnumake # for our own makefile - my.cached-nix-shell # for instant nix-shell scripts - cachix # less time buildin' mo time nixin' - (writeScriptBin "nix-shell" '' - #!${stdenv.shell} - NIX_PATH="nixpkgs-overlays=/etc/dotfiles/packages/default.nix:$NIX_PATH" ${nix}/bin/nix-shell "$@" - '') - ]; - environment.shellAliases = { - nix-env = "NIXPKGS_ALLOW_UNFREE=1 nix-env"; - nsh = "nix-shell"; - nen = "nix-env"; - dots = "make -C ~/.dotfiles"; - }; - - # Default settings for primary user account. `my` is defined in - # modules/default.nix - my.user = { - isNormalUser = true; - uid = 1000; - extraGroups = [ "wheel" "video" "networkmanager" ]; - shell = pkgs.zsh; - }; - - # This value determines the NixOS release with which your system is to be - # compatible, in order to avoid breaking some software such as database - # servers. You should change this only after NixOS release notes say you - # should. - system.stateVersion = "20.03"; # Did you read the comment? -} diff --git a/flake.lock b/flake.lock new file mode 100644 index 00000000..1386ed9a --- /dev/null +++ b/flake.lock @@ -0,0 +1,96 @@ +{ + "nodes": { + "emacs-overlay": { + "locked": { + "lastModified": 1601770752, + "narHash": "sha256-eZo23q0aWyNgFUCVnxsA16vh9My0yJJME9GMfFeS9jo=", + "owner": "nix-community", + "repo": "emacs-overlay", + "rev": "5ddbef90f92809744275c3ec78b5464a376b6f11", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "emacs-overlay", + "type": "github" + } + }, + "home-manager": { + "inputs": { + "nixpkgs": [ + "nixos-unstable" + ] + }, + "locked": { + "lastModified": 1601584113, + "narHash": "sha256-4gLn43KG5KzJatEul+/TfsiMnj3FK3ZU6VMdXdPpdRY=", + "owner": "rycee", + "repo": "home-manager", + "rev": "9ff2188c5d2c65b20ded3f2e7a759319866313d3", + "type": "github" + }, + "original": { + "owner": "rycee", + "ref": "master", + "repo": "home-manager", + "type": "github" + } + }, + "nixos": { + "locked": { + "lastModified": 1601200199, + "narHash": "sha256-wf5XDJJ8tJw0gZH7S1+r/I/k321bj9jGVzRXEVtbfkQ=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "0cfe5377e8993052f9b0dd56d058f8008af45bd9", + "type": "github" + }, + "original": { + "id": "nixpkgs", + "ref": "nixos-20.09", + "type": "indirect" + } + }, + "nixos-hardware": { + "locked": { + "lastModified": 1600019032, + "narHash": "sha256-o/PxAWx2O85NyQRDuhZ5QbAACA5yyglmA7hN9GSI27g=", + "owner": "nixos", + "repo": "nixos-hardware", + "rev": "684eaddf74109b2bedb8b585a25714eb9ea5c54e", + "type": "github" + }, + "original": { + "owner": "nixos", + "repo": "nixos-hardware", + "type": "github" + } + }, + "nixos-unstable": { + "locked": { + "lastModified": 1601171649, + "narHash": "sha256-G3RUAi2DUq6r3ntASLS+LZC/Eamot55W1+xmBOgEh3M=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "84d74ae9c9cbed73274b8e4e00be14688ffc93fe", + "type": "github" + }, + "original": { + "id": "nixpkgs", + "ref": "nixos-unstable", + "type": "indirect" + } + }, + "root": { + "inputs": { + "emacs-overlay": "emacs-overlay", + "home-manager": "home-manager", + "nixos": "nixos", + "nixos-hardware": "nixos-hardware", + "nixos-unstable": "nixos-unstable" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 00000000..9e31aaea --- /dev/null +++ b/flake.nix @@ -0,0 +1,105 @@ +# flake.nix --- the heart of my dotfiles +# +# Author: Henrik Lissner +# URL: https://github.com/hlissner/dotfiles +# License: MIT +# +# Welcome to ground zero. Where the whole flake gets set up and all its modules +# are loaded. + +{ + description = "A grossly incandescent nixos config."; + + inputs = + { + # Core dependencies + nixos.url = "nixpkgs/nixos-20.09"; + nixos-unstable.url = "nixpkgs/nixos-unstable"; + home-manager.url = "github:rycee/home-manager/master"; + home-manager.inputs.nixpkgs.follows = "nixos-unstable"; + + # Extras + emacs-overlay.url = "github:nix-community/emacs-overlay"; + nixos-hardware.url = "github:nixos/nixos-hardware"; + }; + + outputs = inputs @ { self, nixos, nixos-unstable, home-manager, ... }: + let + inherit (builtins) baseNameOf; + inherit (lib) nixosSystem mkIf removeSuffix attrNames attrValues; + inherit (lib.my) mapModules mapModulesRec mapModulesRec'; + + system = "x86_64-linux"; + + lib = nixos.lib.extend + (self: super: { my = import ./lib { inherit pkgs; lib = self; }; }); + + mkPkgs = pkgs: extraOverlays: import pkgs { + inherit system; + config.allowUnfree = true; # forgive me Stallman senpai + overlays = extraOverlays ++ (attrValues self.overlays); + }; + pkgs = mkPkgs nixos [ self.overlay ]; + unstable = mkPkgs nixos-unstable []; + in { + overlay = + final: prev: { + inherit unstable; + user = self.packages."${system}"; + }; + + overlays = + mapModules (toString ./overlays) import; + + packages."${system}" = + mapModules (toString ./packages) + (p: pkgs.callPackage p {}); + + nixosModules = + mapModulesRec (toString ./modules) import; + + nixosConfigurations = + mapModules (toString ./hosts) + (modulePath: nixosSystem { + inherit system; + specialArgs = { inherit lib inputs; }; + modules = [ + # Common config for all nixos machines; and to ensure the flake + # operates soundly + { + networking.hostName = removeSuffix ".nix" (baseNameOf modulePath); + environment.variables.NIXPKGS_ALLOW_UNFREE = "1"; + nixpkgs.pkgs = pkgs; + nix = { + package = unstable.nixFlakes; + extraOptions = "experimental-features = nix-command flakes"; + nixPath = [ + "nixpkgs=${nixos}" + "nixpkgs-overlays=${toString ./.}/overlays" + ]; + binaryCaches = [ + "https://cache.nixos.org/" + "https://nix-community.cachix.org" + ]; + binaryCachePublicKeys = [ + "nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs=" + ]; + autoOptimiseStore = true; + useSandbox = true; + }; + system.configurationRevision = mkIf (self ? rev) self.rev; + system.stateVersion = "20.09"; + } + + # I use home-manager to deploy files to $HOME; little else + home-manager.nixosModules.home-manager + + # All my personal modules + { imports = mapModulesRec' (toString ./modules) import; } + + ./hosts # config common to all hosts + modulePath # host-specific config + ]; + }); + }; +} diff --git a/hosts/README.org b/hosts/README.org new file mode 100644 index 00000000..f8dbafb9 --- /dev/null +++ b/hosts/README.org @@ -0,0 +1,9 @@ +#+TITLE: Host Configurations + +* Systems ++ kuro ++ shiro ++ ao ++ aka ++ aijiro ++ unlisted: 100+ linodes, 7 VMs diff --git a/hosts/aka/default.nix b/hosts/aka/default.nix deleted file mode 100644 index a8a5672a..00000000 --- a/hosts/aka/default.nix +++ /dev/null @@ -1,24 +0,0 @@ -# My HTPC. Mostly so family can organize their media collection. - -{ config, lib, ... }: -{ - imports = [ - ../personal.nix # common settings - ./hardware-configuration.nix - ]; - - modules = { - shell.zsh.enable = true; - services.calibre.enable = true; - services.jellyfin.enable = true; - services.ssh.enable = true; - services.syncthing.enable = true; - }; - - my.zsh.rc = lib.readFile ; - - networking.networkmanager.enable = true; - time.timeZone = "America/Toronto"; - - services.calibre-server.calibre-server = "/data/books"; -} diff --git a/hosts/aka/hardware-configuration.nix b/hosts/aka/hardware-configuration.nix deleted file mode 100644 index 5762c722..00000000 --- a/hosts/aka/hardware-configuration.nix +++ /dev/null @@ -1,32 +0,0 @@ -{ config, lib, ... }: -{ - imports = [ - - ]; - - boot.initrd.availableKernelModules = [ "ohci_pci" "ehci_pci" "ahci" "firewire_ohci" "usb_storage" "usbhid" "sd_mod" "sr_mod" ]; - boot.initrd.kernelModules = [ ]; - boot.kernelModules = [ "kvm-intel" "wl" ]; - boot.extraModulePackages = [ config.boot.kernelPackages.broadcom_sta ]; - - ## CPU - nix.maxJobs = lib.mkDefault 2; - - ## Networking - networking.useDHCP = false; - networking.interfaces.enp0s10.useDHCP = true; - - ## Harddrives - fileSystems = { - "/" = { - device = "/dev/disk/by-label/nixos"; - fsType = "ext4"; - options = [ "noatime" ]; - }; - "/boot" = { - device = "/dev/disk/by-label/boot"; - fsType = "vfat"; - }; - }; - swapDevices = [{ device = "/dev/disk/by-label/swap"; }]; -} diff --git a/hosts/ao/README.org b/hosts/ao/README.org new file mode 100644 index 00000000..fb1689e7 --- /dev/null +++ b/hosts/ao/README.org @@ -0,0 +1 @@ +#+TITLE: Ao diff --git a/hosts/ao/default.nix b/hosts/ao/default.nix index c13ce683..fee988c2 100644 --- a/hosts/ao/default.nix +++ b/hosts/ao/default.nix @@ -1,40 +1,37 @@ # Ao -- my home development and user-facing server -{ pkgs, config, lib, ... }: -{ - imports = [ - ../personal.nix - ./hardware-configuration.nix - ]; +{ config, lib, ... }: +with lib.my; +{ + imports = [ ./hardware-configuration.nix ]; + + ## Modules modules = { shell.git.enable = true; shell.zsh.enable = true; services.ssh.enable = true; - services.nginx.enable = true; - services.gitea.enable = true; - services.syncthing.enable = true; + # services.nginx.enable = true; + # services.gitea.enable = true; + # services.syncthing.enable = true; + + themes.fluorescence.enable = true; }; - my.zsh.rc = lib.readFile ; + ## Local config + boot.loader.systemd-boot.enable = true; networking.networkmanager.enable = true; - time.timeZone = "America/Toronto"; # nginx hosts services.nginx = { - user = config.my.username; + user = config.user.name; virtualHosts = { "v0.io" = { default = true; enableACME = true; forceSSL = true; - root = "/home/${config.my.username}/www/v0.io"; - }; - "dl.v0.io" = { - enableACME = true; - addSSL = true; - root = "/home/${config.my.username}/www/dl.v0.io"; + root = "${homeDir}/www/v0.io"; locations."~* \.(?:ico|css|js|gif|jpe?g|png|mp4)$".extraConfig = '' expires 30d; add_header Pragma public; @@ -46,55 +43,56 @@ forceSSL = true; locations."/".proxyPass = http://127.0.0.1:3000; }; - "tv.v0.io" = { - http2 = true; # more performant for streaming - enableACME = true; - forceSSL = true; - extraConfig = '' - add_header Content-Security-Policy "default-src https: data: blob:; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline' https://www.gstatic.com/cv/js/sender/v1/cast_sender.js; worker-src 'self' blob:; connect-src 'self'; object-src 'none'; frame-ancestors 'self'"; + # "tv.v0.io" = { + # http2 = true; # more performant for streaming + # enableACME = true; + # forceSSL = true; + # extraConfig = '' + # add_header Content-Security-Policy "default-src https: data: blob:; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline' https://www.gstatic.com/cv/js/sender/v1/cast_sender.js; worker-src 'self' blob:; connect-src 'self'; object-src 'none'; frame-ancestors 'self'"; - # Some players don't reopen a socket and playback stops totally - # instead of resuming after an extended pause - send_timeout 100m; + # # Some players don't reopen a socket and playback stops totally + # # instead of resuming after an extended pause + # send_timeout 100m; - # Intentionally not hardened for security for player support and - # encryption video streams has a lot of overhead with something like - # AES-256-GCM-SHA384. - ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:ECDHE-RSA-DES-CBC3-SHA:ECDHE-ECDSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA'; + # # Intentionally not hardened for security for player support and + # # encryption video streams has a lot of overhead with something like + # # AES-256-GCM-SHA384. + # ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:ECDHE-RSA-DES-CBC3-SHA:ECDHE-ECDSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA'; + # ssl_stapling on; + # ssl_stapling_verify on; - ssl_stapling on; - ssl_stapling_verify on; + # # Forward real ip and host to Plex + # proxy_set_header Referer $server_addr; + # proxy_set_header Origin $server_addr; - # Forward real ip and host to Plex - proxy_set_header Referer $server_addr; - proxy_set_header Origin $server_addr; - - # Security / XSS Mitigation Headers - add_header X-Frame-Options "SAMEORIGIN"; - add_header X-XSS-Protection "1; mode=block"; - add_header X-Content-Type-Options "nosniff"; - ''; - # locations."= /".return = "302 https://tv.v0.io/web/index.html"; - locations."/socket" = { - proxyPass = "http://192.168.1.13:8096"; - proxyHttpVersion = "1.1"; - # Buffering off send to the client as soon as the data is received - # from JellyFin. - proxyBuffering = "off"; - }; - locations."/" = { - proxyWebsockets = true; - proxyPass = "http://192.168.1.13:8096"; - }; - }; + # # Security / XSS Mitigation Headers + # add_header X-Frame-Options "SAMEORIGIN"; + # add_header X-XSS-Protection "1; mode=block"; + # add_header X-Content-Type-Options "nosniff"; + # ''; + # # locations."= /".return = "302 https://tv.v0.io/web/index.html"; + # locations."/socket" = { + # proxyPass = "http://192.168.1.13:8096"; + # proxyHttpVersion = "1.1"; + # # Buffering off send to the client as soon as the data is received + # # from JellyFin. + # proxyBuffering = "off"; + # }; + # locations."/" = { + # proxyWebsockets = true; + # proxyPass = "http://192.168.1.13:8096"; + # }; + # }; }; }; - security.acme.certs = { - "v0.io".email = config.my.email; - "dl.v0.io".email = config.my.email; - "git.v0.io".email = config.my.email; - "tv.v0.io".email = config.my.email; + security.acme = { + acceptTerms = true; + certs = let email = "henrik@lissner.net"; in { + "v0.io".email = email; + "git.v0.io".email = email; + # "tv.v0.io".email = email; + }; }; services.gitea = { diff --git a/hosts/ao/hardware-configuration.nix b/hosts/ao/hardware-configuration.nix index 9286f937..ff5ef36b 100644 --- a/hosts/ao/hardware-configuration.nix +++ b/hosts/ao/hardware-configuration.nix @@ -1,13 +1,13 @@ -{ config, lib, ... }: +{ config, lib, modulesPath, ... }: { - imports = [ - - ]; + imports = [ (modulesPath + "/installer/scan/not-detected.nix") ]; - boot.initrd.availableKernelModules = [ "ohci_pci" "ehci_pci" "ahci" "firewire_ohci" "usb_storage" "usbhid" "sd_mod" "sr_mod" "sdhci_pci" ]; - boot.initrd.kernelModules = [ ]; - boot.kernelModules = [ "kvm-intel" "wl" ]; - boot.extraModulePackages = [ config.boot.kernelPackages.broadcom_sta ]; + boot = { + initrd.availableKernelModules = [ "ohci_pci" "ehci_pci" "ahci" "firewire_ohci" "usb_storage" "usbhid" "sd_mod" "sr_mod" "sdhci_pci" ]; + initrd.kernelModules = [ ]; + kernelModules = [ "kvm-intel" "wl" ]; + extraModulePackages = [ config.boot.kernelPackages.broadcom_sta ]; + }; ## CPU nix.maxJobs = lib.mkDefault 2; diff --git a/hosts/default.nix b/hosts/default.nix new file mode 100644 index 00000000..a3279920 --- /dev/null +++ b/hosts/default.nix @@ -0,0 +1,71 @@ +# hosts/default.nix +# +# Loads config common to all hosts. + +{ config, lib, pkgs, ... }: + +with lib; +with lib.my; +{ + ## Some reasonable, global defaults + # This is here to appease 'nix flake check' for generic hosts with no + # hardware-configuration.nix or fileSystem config. + fileSystems."/".device = "/dev/disk/by-label/nixos"; + + boot.loader = { + efi.canTouchEfiVariables = true; + systemd-boot.configurationLimit = 10; + }; + + # Just the bear necessities... + environment.systemPackages = with pkgs; [ + unstable.cached-nix-shell + coreutils + git + vim + wget + gnumake + ]; + + networking.firewall.enable = true; + networking.hosts = + let hostConfig = { + "192.168.1.2" = [ "ao" ]; + "192.168.1.3" = [ "aka" ]; + "192.168.1.10" = [ "kuro" ]; + "192.168.1.11" = [ "shiro" ]; + "192.168.1.12" = [ "midori" ]; + }; + hosts = flatten (attrValues hostConfig); + hostName = config.networking.hostName; + in mkIf (builtins.elem hostName hosts) hostConfig; + + # Use the latest kernel + boot.kernelPackages = pkgs.linuxPackages_latest; + + + ## Location config -- since Toronto is my 127.0.0.1 + time.timeZone = lib.mkDefault "America/Toronto"; + i18n.defaultLocale = lib.mkDefault "en_US.UTF-8"; + # For redshift, mainly + location = (if config.time.timeZone == "America/Toronto" then { + latitude = 43.70011; + longitude = -79.4163; + } else if config.time.timeZone == "Europe/Copenhagen" then { + latitude = 55.88; + longitude = 12.5; + } else {}); + + + ## System security tweaks + boot.tmpOnTmpfs = true; + security.hideProcessInformation = true; + security.protectKernelImage = true; + # Fix a security hole in place for backwards compatibility. See desc in + # nixpkgs/nixos/modules/system/boot/loader/systemd-boot/systemd-boot.nix + boot.loader.systemd-boot.editor = false; + + # Change me later! + user.initialPassword = "nix"; + users.users.root.initialPassword = "nix"; +} diff --git a/hosts/kuro/README.org b/hosts/kuro/README.org new file mode 100644 index 00000000..e543a4f1 --- /dev/null +++ b/hosts/kuro/README.org @@ -0,0 +1,68 @@ +#+TITLE: Kuro +#+DATE: September 13, 2020 + +* Overview + +* Specs +| CPU | [[https://www.newegg.ca/amd-ryzen-9-3900x/p/N82E16819113103][AMD Ryzen 9 3900X 12-core, 24-thread]] | +| MOBO | [[https://www.newegg.ca/gigabyte-b550-aorus-elite/p/N82E16813145214?Item=N82E16813145214&IsFeedbackTab=true#scrollFullInfo][GIGABYTE B550 AORUS Elite]] | +| COOL | [[https://www.newegg.ca/cooler-master-hyper-212-evo-rr-212e-20pk-r2/p/N82E16835103099][Cooler Master Hyper 212 Evo]] | +| GPU | EVGA GeForce 680 GTX SC | +| RAM | [[https://www.newegg.ca/g-skill-64gb-288-pin-ddr4-sdram/p/N82E16820374003?Description=G.SKILL%20Ripjaws%20V%20Series%2064gb&cm_re=G.SKILL_Ripjaws%20V%20Series%2064gb-_-20-374-003-_-Product][G.SKILL Ripjaws V Series 64GB (2x 32GB)]] | +| HDD | [[https://www.newegg.ca/samsung-970-evo-plus-500gb/p/N82E16820147742?Description=samsung%20970%20evo%20plus&cm_re=samsung_970%20evo%20plus-_-20-147-742-_-Product][Samsung 970 EVO Plus 500GB NVMe M2]] | +| HDD | ST31000340NS 1TB (2x) | +| KBD | ErgoDox-EZ | +| MOUSE | Anker Wireless Vertical Mouse | + +* Installation +** Set up root file system +#+BEGIN_SRC sh +# EVO Plus 500gb +parted /dev/nvme0n1 -- mklabel gpt +parted /dev/nvme0n1 -- mkpart ESP fat32 1MiB 512MiB +parted /dev/nvme0n1 -- mkpart primary 512MiB 200GiB +parted /dev/nvme0n1 -- mkpart primary 200GiB 100% +parted /dev/nvme0n1 -- set 1 boot on +mkfs.fat -F32 -n BOOT /dev/nvme0n1p1 +mkfs.ext4 -L nixos /dev/nvme0n1p2 +mkfs.ext4 -L home /dev/nvme0n1p3 +#+END_SRC + +** Set up VM SSDs +#+BEGIN_SRC shell +# 2x SSDs for VMs +parted /dev/sdc -- mklabel gpt +parted /dev/sde -- mklabel gpt +#+END_SRC + +** Set up backup file system +#+BEGIN_SRC sh +# 2x 1TB mirrored backup +zpool create -R /mnt \ + -O mountpoint=none \ + -O xattr=sa \ + -O atime=off \ + -O compression=lz4 \ + -O recordsize=1M \ + -o ashift=9 \ + usr mirror /dev/sda /dev/sdb + +# aux +zfs create -o mountpoint=legacy usr/media +zfs create -o mountpoint=legacy usr/backup +zfs create -o mountpoint=legacy -o recordsize=128K usr/share +zfs create -o mountpoint=legacy -o recordsize=128K usr/local +#+END_SRC + +** Mount drives +#+BEGIN_SRC sh +mount /dev/nvme0n1p2 /mnt + +mkdir -p /mnt/{home,boot,usr/{backup,media,share}} +mount /dev/nvme0n1p1 /mnt/boot +mount /dev/nvme0n1p3 /mnt/home +mount -t zfs {usr,/mnt/usr}/backup +mount -t zfs {usr,/mnt/usr}/media +mount -t zfs {usr,/mnt/usr}/share +mount -t zfs {usr,/mnt/usr}/local +#+END_SRC diff --git a/hosts/kuro/default.nix b/hosts/kuro/default.nix index 3d7b9a78..d8405243 100644 --- a/hosts/kuro/default.nix +++ b/hosts/kuro/default.nix @@ -1,77 +1,79 @@ -# Kuro -- my desktop - -{ pkgs, options, config, ... }: +{ ... }: { - imports = [ - ../personal.nix # common settings - ./hardware-configuration.nix - ]; + imports = [ ./hardware-configuration.nix ]; + ## Modules modules = { desktop = { bspwm.enable = true; - - apps.rofi.enable = true; - apps.discord.enable = true; - # apps.skype.enable = true; - apps.daw.enable = true; # making music - apps.graphics.enable = true; # raster/vector/sprites - apps.recording.enable = true; # recording screen/audio - apps.vm.enable = true; # virtualbox for testing - - term.default = "xst"; - term.st.enable = true; - - browsers.default = "firefox"; - browsers.firefox.enable = true; - # browsers.qutebrowser.enable = true; - # browsers.vimb.enable = true; - - # gaming.emulators.psx.enable = true; - gaming.steam.enable = true; + apps = { + discord.enable = true; + rofi.enable = true; + # godot.enable = true; + }; + browsers = { + default = "firefox"; + firefox.enable = true; + }; + gaming = { + steam.enable = true; + # emulators.enable = true; + # emulators.psx.enable = true; + }; + media = { + daw.enable = true; + documents.enable = true; + graphics.enable = true; + mpv.enable = true; + recording.enable = true; + spotify.enable = true; + }; + term = { + default = "xst"; + st.enable = true; + }; + vm = { + qemu.enable = true; + }; }; - editors = { - default = "nvim"; + default = "emacs -nw"; emacs.enable = true; vim.enable = true; }; - - dev = { - cc.enable = true; - common-lisp.enable = true; - rust.enable = true; - node.enable = true; - # lua.enable = true; - # lua.love2d.enable = true; + hardware = { + audio.enable = true; + ergodox.enable = true; + fs = { + enable = true; + zfs.enable = true; + ssd.enable = true; + }; + nvidia.enable = true; + sensors.enable = true; }; - - media = { - mpv.enable = true; - spotify.enable = true; - }; - shell = { direnv.enable = true; - git.enable = true; - gnupg.enable = true; - # weechat.enable = true; - pass.enable = true; - tmux.enable = true; - # ranger.enable = true; - zsh.enable = true; + git.enable = true; + gnupg.enable = true; + pass.enable = true; + tmux.enable = true; + zsh.enable = true; }; - services = { - # syncthing.enable = true; - # docker.enable = true; + ssh.enable = true; }; - - # themes.aquanaut.enable = true; themes.fluorescence.enable = true; }; + + ## Local config programs.ssh.startAgent = true; + + boot.loader.systemd-boot.enable = true; networking.networkmanager.enable = true; - time.timeZone = "America/Toronto"; + # The global useDHCP flag is deprecated, therefore explicitly set to false + # here. Per-interface useDHCP will be mandatory in the future, so this + # generated config replicates the default behaviour. + networking.useDHCP = false; } diff --git a/hosts/kuro/hardware-configuration.nix b/hosts/kuro/hardware-configuration.nix index e1b4bd30..0453a360 100644 --- a/hosts/kuro/hardware-configuration.nix +++ b/hosts/kuro/hardware-configuration.nix @@ -1,54 +1,54 @@ -{ config, pkgs, lib, ... }: +{ config, lib, pkgs, modulesPath, ... }: + { - imports = [ - - ]; + imports = [ "${modulesPath}/installer/scan/not-detected.nix" ]; - boot.initrd.availableKernelModules = [ "xhci_pci" "ehci_pci" "ahci" "usbhid" "uas" "usb_storage" "sd_mod" ]; - boot.initrd.kernelModules = [ ]; - boot.kernelModules = [ "kvm-intel" ]; - boot.extraModulePackages = [ ]; + boot = { + initrd.availableKernelModules = [ "nvme" "xhci_pci" "ahci" "usb_storage" "usbhid" "sd_mod" ]; + initrd.kernelModules = []; + extraModulePackages = []; + kernelModules = [ + "kvm-amd" + "asix" # REVIEW Remove me when 5.9 kernel is available + ]; + kernelParams = [ + # HACK Disables fixes for spectre, meltdown, L1TF and a number of CPU + # vulnerabilities. This is not a good idea for mission critical or + # server/headless builds, but on my lonely home system I prioritize + # raw performance over security. The gains are minor. + "mitigations=off" + # Limit ZFS cache to 8gb. Sure, this system has 64gb, but I don't want + # this biting me when I'm running multiple VMs. + "zfs.zfs_arc_max=8589934592" + ]; + }; - ## CPU - nix.maxJobs = lib.mkDefault 8; + # CPU + nix.maxJobs = lib.mkDefault 16; powerManagement.cpuFreqGovernor = "performance"; - hardware.cpu.intel.updateMicrocode = true; + hardware.cpu.amd.updateMicrocode = true; - ## SSDs - services.fstrim.enable = true; + # Displays + services.xserver = { + monitorSection = '' + VendorName "Unknown" + ModelName "DELL U2515H" + HorizSync 30.0 - 113.0 + VertRefresh 56.0 - 86.0 + Option "DPMS" + ''; + screenSection = '' + Option "metamodes" "HDMI-0: nvidia-auto-select +1920+0, DVI-I-1: nvidia-auto-select +0+180, DVI-D-0: nvidia-auto-select +4480+180" + Option "SLI" "Off" + Option "MultiGPU" "Off" + Option "BaseMosaic" "off" + Option "Stereo" "0" + Option "nvidiaXineramaInfoOrder" "DFP-1" + ''; + }; - ## Ergodox - my.packages = [ pkgs.teensy-loader-cli ]; - my.alias.teensyload = "sudo teensy-loader-cli -w -v --mcu=atmega32u4"; - # Make ralt the compose key, so ralt+a+a = å or ralt+o+/ = ø - services.xserver.xkbOptions = "compose:ralt"; - - ## GPU - services.xserver.videoDrivers = [ "nvidia" ]; - hardware.opengl.enable = true; - # Respect XDG conventions, damn it! - environment.systemPackages = with pkgs; [ - (writeScriptBin "nvidia-settings" '' - #!${stdenv.shell} - mkdir -p "$XDG_CONFIG_HOME/nvidia" - exec ${config.boot.kernelPackages.nvidia_x11.settings}/bin/nvidia-settings --config="$XDG_CONFIG_HOME/nvidia/settings" - '') - ]; - - ## Tablet - # For my intuos4 pro. Doesn't work for cintiqs. - services.xserver.wacom.enable = true; - # TODO Move this to udev - # system.userActivationScripts.wacom.text = '' - # # lock tablet to main display - # if xinput list --id-only "Wacom Intuos Pro S Pen stylus" 2>&1 >/dev/null; then - # xinput map-to-output $(xinput list --id-only "Wacom Intuos Pro S Pen stylus") DVI-I-1 - # xinput map-to-output $(xinput list --id-only "Wacom Intuos Pro S Pen eraser") DVI-I-1 - # xinput map-to-output $(xinput list --id-only "Wacom Intuos Pro S Pen cursor") DVI-I-1 - # fi - # ''; - - ### Harddrives + # Storage + networking.hostId = "edd9f26b"; # required by zfs fileSystems = { "/" = { device = "/dev/disk/by-label/nixos"; @@ -59,21 +59,27 @@ device = "/dev/disk/by-label/BOOT"; fsType = "vfat"; }; - "/mnt/projects" = { - device = "/dev/disk/by-label/projects"; + "/home" = { + device = "/dev/disk/by-label/home"; fsType = "ext4"; options = [ "noatime" ]; }; - "/mnt/archive" = { - device = "/dev/disk/by-label/archive"; - fsType = "ext4"; - options = [ "noatime" ]; + "/usr/backup" = { + device = "usr/backup"; + fsType = "zfs"; }; - "/mnt/local" = { - device = "/dev/disk/by-label/local"; - fsType = "ext4"; - options = [ "noatime" ]; + "/usr/media" = { + device = "usr/media"; + fsType = "zfs"; + }; + "/usr/local" = { + device = "usr/local"; + fsType = "zfs"; + }; + "/usr/share" = { + device = "usr/share"; + fsType = "zfs"; }; }; - swapDevices = [ { device = "/dev/disk/by-label/swap"; } ]; + swapDevices = []; } diff --git a/hosts/linode.nix b/hosts/linode.nix index cd7c8f7c..ea609567 100644 --- a/hosts/linode.nix +++ b/hosts/linode.nix @@ -14,10 +14,8 @@ # curl $url | dd of=/dev/sda # # 4. Install these dotfiles with -# git clone https://github.com/hlissner/dotfiles ~/.dotfiles -# ln -s ~/.dotfiles /etc/dotfiles -# cd ~/.dotfiles -# mk install-linode +# git clone https://github.com/hlissner/dotfiles ~/.config/dotfiles +# nixos-install --root "$(PREFIX)" --flake ~/.config/dotfiles#linode # # 4. Create a configuration profile: # - Kernel: GRUB 2 @@ -28,16 +26,27 @@ # 5. Reboot into profile. { config, lib, pkgs, ... }: + +let + inherit (lib) filter pathExists; +in { + imports = filter pathExists ["/etc/nixos/configuration.nix"]; + environment.systemPackages = with pkgs; [ inetutils mtr sysstat git ]; - imports = [ - - - - - ]; + modules = { + # editors = { + # default = "nvim"; + # vim.enable = true; + # }; + shell = { + # git.enable = true; + zsh.enable = true; + }; + services.ssh.enable = true; + }; # GRUB boot = { @@ -58,7 +67,9 @@ }; }; - networking.useDHCP = false; - networking.usePredictableInterfaceNames = false; - networking.interfaces.eth0.useDHCP = true; + networking = { + useDHCP = false; + usePredictableInterfaceNames = false; + interfaces.eth0.useDHCP = true; + }; } diff --git a/hosts/personal.nix b/hosts/personal.nix deleted file mode 100644 index 7d619187..00000000 --- a/hosts/personal.nix +++ /dev/null @@ -1,82 +0,0 @@ -# hosts/personal.nix --- settings common to my personal systems - -{ config, lib, pkgs, ... }: -{ - # Support for more filesystems - environment.systemPackages = with pkgs; [ - exfat - ntfs3g - hfsprogs - ]; - - # Nothing in /tmp should survive a reboot - boot.tmpOnTmpfs = true; - # Use simple bootloader; I prefer the on-demand BIOs boot menu - boot.loader = { - timeout = 1; - efi.canTouchEfiVariables = true; - systemd-boot = { - enable = true; - # Fix a security hole in place for backwards compatibility. See desc in - # nixpkgs/nixos/modules/system/boot/loader/systemd-boot/systemd-boot.nix - editor = false; - # Limit number of generations to display in boot menu - configurationLimit = 10; - }; - }; - - ### Universal defaults - networking.firewall.enable = true; - networking.hosts = { - "192.168.1.2" = [ "ao" ]; - "192.168.1.3" = [ "aka" ]; - "192.168.1.10" = [ "kuro" ]; - "192.168.1.11" = [ "shiro" ]; - "192.168.1.12" = [ "midori" ]; - }; - - - ### A tidy $HOME is a tidy mind - # Obey XDG conventions; - my.home.xdg.enable = true; - environment.variables = { - # These are the defaults, but some applications are buggy when these lack - # explicit values. - XDG_CONFIG_HOME = "$HOME/.config"; - XDG_CACHE_HOME = "$HOME/.cache"; - XDG_DATA_HOME = "$HOME/.local/share"; - XDG_BIN_HOME = "$HOME/.local/bin"; - }; - - # Conform more programs to XDG conventions. The rest are handled by their - # respective modules. - my.env = { - __GL_SHADER_DISK_CACHE_PATH = "$XDG_CACHE_HOME/nv"; - CUDA_CACHE_PATH = "$XDG_CACHE_HOME/nv"; - HISTFILE = "$XDG_DATA_HOME/bash/history"; - INPUTRC = "$XDG_CACHE_HOME/readline/inputrc"; - LESSHISTFILE = "$XDG_CACHE_HOME/lesshst"; - WGETRC = "$XDG_CACHE_HOME/wgetrc"; - }; - - # Prevents ~/.esd_auth files by disabling the esound protocol module for - # pulseaudio, which I likely don't need. Is there a better way? - hardware.pulseaudio.configFile = - let paConfigFile = - with pkgs; runCommand "disablePulseaudioEsoundModule" - { buildInputs = [ pulseaudio ]; } '' - mkdir "$out" - cp ${pulseaudio}/etc/pulse/default.pa "$out/default.pa" - sed -i -e 's|load-module module-esound-protocol-unix|# ...|' "$out/default.pa" - ''; - in lib.mkIf config.hardware.pulseaudio.enable - "${paConfigFile}/default.pa"; - - # Clean up leftovers, as much as we can - system.userActivationScripts.cleanupHome = '' - pushd /home/${config.my.username} - rm -rf .compose-cache .nv .pki .dbus .fehbg - [ -s .xsession-errors ] || rm -f .xsession-errors* - popd - ''; -} diff --git a/hosts/shiro/README.org b/hosts/shiro/README.org new file mode 100644 index 00000000..8b408015 --- /dev/null +++ b/hosts/shiro/README.org @@ -0,0 +1,9 @@ +#+TITLE: Shiro +#+DATE: September 13, 2020 + +* Overview + +* Specs +Dell 13" 9370 + +* Installation diff --git a/hosts/shiro/default.nix b/hosts/shiro/default.nix index e29c0cf1..e825a0db 100644 --- a/hosts/shiro/default.nix +++ b/hosts/shiro/default.nix @@ -1,40 +1,43 @@ # Shiro -- my laptop -{ pkgs, ... }: +{ ... }: { - imports = [ - ../personal.nix # common settings - ./hardware-configuration.nix - ]; + imports = [ ./hardware-configuration.nix ]; + ## Modules modules = { desktop = { bspwm.enable = true; - - apps.rofi.enable = true; - apps.discord.enable = true; - # apps.skype.enable = true; - apps.daw.enable = true; # making music - apps.graphics.enable = true; # raster/vector/sprites - apps.recording.enable = true; # recording screen/audio - # apps.vm.enable = true; # virtualbox for testing - - term.default = "xst"; - term.st.enable = true; - - browsers.default = "firefox"; - browsers.firefox.enable = true; - - # gaming.emulators.psx.enable = true; - # gaming.steam.enable = true; + apps = { + discord.enable = true; + rofi.enable = true; + # skype.enable = true; + }; + browsers = { + default = "firefox"; + firefox.enable = true; + }; + media = { + # daw.enable = true; + documents.enable = true; + graphics.enable = true; + mpv.enable = true; + recording.enable = true; + spotify.enable = true; + }; + term = { + default = "xst"; + st.enable = true; + }; + vm = { + # virtualbox.enable = true; + }; }; - editors = { - default = "nvim"; + default = "emacs -nw"; emacs.enable = true; vim.enable = true; }; - dev = { # cc.enable = true; # common-lisp.enable = true; @@ -42,12 +45,13 @@ # lua.enable = true; # lua.love2d.enable = true; }; - - media = { - mpv.enable = true; - spotify.enable = true; + hardware = { + audio.enable = true; + fs = { + enable = true; + ssd.enable = true; + }; }; - shell = { direnv.enable = true; git.enable = true; @@ -58,25 +62,23 @@ # ranger.enable = true; zsh.enable = true; }; + hardware = { - services = { - syncthing.enable = true; }; - - # themes.aquanaut.enable = true; + services = { + # syncthing.enable = true; + ssh.enable = true; + }; themes.fluorescence.enable = true; }; + + ## Local config programs.ssh.startAgent = true; + + boot.loader.systemd-boot.enable = true; networking.wireless.enable = true; hardware.opengl.enable = true; - time.timeZone = "America/Toronto"; # time.timeZone = "Europe/Copenhagen"; - - # Optimize power use - environment.systemPackages = [ pkgs.acpi ]; - powerManagement.powertop.enable = true; - # Monitor backlight control - programs.light.enable = true; } diff --git a/hosts/shiro/hardware-configuration.nix b/hosts/shiro/hardware-configuration.nix index b854fbe0..3d4fe546 100644 --- a/hosts/shiro/hardware-configuration.nix +++ b/hosts/shiro/hardware-configuration.nix @@ -1,30 +1,37 @@ # Do not modify this file! It was generated by ‘nixos-generate-config’ # and may be overwritten by future invocations. Please make changes # to /etc/nixos/configuration.nix instead. -{ config, lib, pkgs, ... }: +{ config, lib, pkgs, inputs, modulesPath, ... }: { imports = [ - - (let nixos-hardware = - builtins.fetchTarball - https://github.com/NixOS/nixos-hardware/archive/master.tar.gz; - in "${nixos-hardware}/dell/xps/13-9370") + (modulesPath + "/installer/scan/not-detected.nix") + inputs.nixos-hardware.nixosModules.dell-xps-13-9370 ]; - boot.initrd.availableKernelModules = [ "xhci_pci" "nvme" "rtsx_pci_sdmmc" ]; - boot.initrd.kernelModules = [ "dm-snapshot" ]; - boot.kernelModules = [ "kvm-intel" ]; - boot.extraModulePackages = [ ]; + boot = { + initrd.availableKernelModules = [ "xhci_pci" "nvme" "rtsx_pci_sdmmc" ]; + initrd.kernelModules = [ "dm-snapshot" ]; + kernelModules = [ "kvm-intel" ]; + extraModulePackages = [ ]; + # HACK Disables fixes for spectre, meltdown, L1TF and a number of CPU + # vulnerabilities. This is not a good idea for mission critical or + # server/headless builds, but on my lonely home system I prioritize raw + # performance over security. The gains are minor. + kernelParams = [ "mitigations=off" ]; + }; - ## CPU + # CPU nix.maxJobs = lib.mkDefault 8; - powerManagement.cpuFreqGovernor = lib.mkDefault "powersave"; + powerManagement.cpuFreqGovernor = lib.mkDefault "ondemand"; hardware.cpu.intel.updateMicrocode = true; - ## SSDs - # services.fstrim.enable = true; + # Power management + environment.systemPackages = [ pkgs.acpi ]; + powerManagement.powertop.enable = true; + programs.light.enable = true; # Monitor backlight control + # Storage fileSystems = { "/" = { device = "/dev/disk/by-label/nixos"; @@ -42,7 +49,7 @@ }; }; swapDevices = [ { device = "/dev/disk/by-label/swap"; }]; - # Encrypted /home + boot.initrd.luks.devices.home = { device = "/dev/nvme0n1p8"; preLVM = true; diff --git a/lib/attrs.nix b/lib/attrs.nix new file mode 100644 index 00000000..0f8ebd19 --- /dev/null +++ b/lib/attrs.nix @@ -0,0 +1,26 @@ +{ lib, ... }: + +with builtins; +with lib; +rec { + # attrsToList + attrsToList = attrs: + mapAttrsToList (name: value: { inherit name value; }) attrs; + + # mapFilterAttrs :: + # (name -> value -> bool) + # (name -> value -> { name = any; value = any; }) + # attrs + mapFilterAttrs = pred: f: attrs: filterAttrs pred (mapAttrs' f attrs); + + # Generate an attribute set by mapping a function over a list of values. + genAttrs' = values: f: listToAttrs (map f values); + + # anyAttrs :: (name -> value -> bool) attrs + anyAttrs = pred: attrs: + any (attr: pred attr.name attr.value) (attrsToList attrs); + + # countAttrs :: (name -> value -> bool) attrs + countAttrs = pred: attrs: + count (attr: pred attr.name attr.value) (attrsToList attrs); +} diff --git a/lib/default.nix b/lib/default.nix new file mode 100644 index 00000000..d74386d8 --- /dev/null +++ b/lib/default.nix @@ -0,0 +1,18 @@ +{ lib, pkgs, ... }: + +let + inherit (lib) makeExtensible attrValues foldr; + inherit (modules) mapModules; + + modules = import ./modules.nix { + inherit lib; + self.attrs = import ./attrs.nix { inherit lib; self = {}; }; + }; + + mylib = makeExtensible (self: + with self; mapModules (toString ./.) + (file: import file { inherit self lib pkgs; })); +in +mylib.extend + (self: super: + foldr (a: b: a // b) {} (attrValues super)) diff --git a/lib/modules.nix b/lib/modules.nix new file mode 100644 index 00000000..47743f12 --- /dev/null +++ b/lib/modules.nix @@ -0,0 +1,53 @@ +{ self, lib, ... }: + +let + inherit (builtins) attrValues readDir pathExists concatLists; + inherit (lib) id mapAttrsToList filterAttrs hasPrefix hasSuffix nameValuePair removeSuffix; + inherit (self.attrs) mapFilterAttrs; +in +rec { + mapModules = dir: fn: + mapFilterAttrs + (n: v: + v != null && + !(hasPrefix "_" n)) + (n: v: + let path = "${toString dir}/${n}"; in + if v == "directory" && pathExists "${path}/default.nix" + then nameValuePair n (fn path) + else if v == "regular" && + n != "default.nix" && + hasSuffix ".nix" n + then nameValuePair (removeSuffix ".nix" n) (fn path) + else nameValuePair "" null) + (readDir dir); + + mapModules' = dir: fn: + attrValues (mapModules dir fn); + + mapModulesRec = dir: fn: + mapFilterAttrs + (n: v: + v != null && + !(hasPrefix "_" n)) + (n: v: + let path = "${toString dir}/${n}"; in + if v == "directory" + then nameValuePair n (mapModulesRec path fn) + else if v == "regular" && n != "default.nix" && hasSuffix ".nix" n + then nameValuePair (removeSuffix ".nix" n) (fn path) + else nameValuePair "" null) + (readDir dir); + + mapModulesRec' = dir: fn: + let + dirs = + mapAttrsToList + (k: _: "${dir}/${k}") + (filterAttrs + (n: v: v == "directory" && !(hasPrefix "_" n)) + (readDir dir)); + files = attrValues (mapModules dir id); + paths = files ++ concatLists (map (d: mapModulesRec' d id) dirs); + in map fn paths; +} diff --git a/lib/options.nix b/lib/options.nix new file mode 100644 index 00000000..2b9c0810 --- /dev/null +++ b/lib/options.nix @@ -0,0 +1,18 @@ +{ lib, ... }: + +let + inherit (lib) mkOption types; +in +rec { + mkOpt = type: default: + mkOption { inherit type default; }; + + mkOpt' = type: default: description: + mkOption { inherit type default description; }; + + mkBoolOpt = default: mkOption { + inherit default; + type = types.bool; + example = true; + }; +} diff --git a/lib/paths.nix b/lib/paths.nix new file mode 100644 index 00000000..7d7b12c6 --- /dev/null +++ b/lib/paths.nix @@ -0,0 +1,15 @@ +{ self, lib, ... }: + +with builtins; +with lib; +rec { + # ... + dotFiles = toString ../.; + modulesDir = "${dotFiles}/modules"; + configDir = "${dotFiles}/config"; + binDir = "${dotFiles}/bin"; + themeDir = "${modulesDir}/themes"; + homeDir = "/home/${let name = getEnv "USERNAME"; in + if elem name [ "" "root" ] + then "hlissner" else name}"; +} diff --git a/modules/default.nix b/modules/default.nix deleted file mode 100644 index f0938907..00000000 --- a/modules/default.nix +++ /dev/null @@ -1,96 +0,0 @@ -{ config, options, lib, ... }: -with lib; -let mkOptionStr = value: mkOption - { type = types.str; - default = value; }; -in { - imports = [ - - - ./desktop - ./dev - ./editors - ./media - ./services - ./shell - ./themes - ]; - - options = { - my = { - ## Personal details - username = mkOptionStr "hlissner"; - email = mkOptionStr "henrik@lissner.net"; - - ## Convenience aliases - home = mkOption { type = options.home-manager.users.type.functor.wrapped; }; - user = mkOption { type = types.submodule; }; - packages = mkOption { type = with types; listOf package; }; - - ## Environment - env = mkOption { - type = with types; attrsOf (either (either str path) (listOf (either str path))); - apply = mapAttrs - (n: v: if isList v - then concatMapStringsSep ":" (x: toString x) v - else (toString v)); - }; - - alias = mkOption { - type = with types; nullOr (attrsOf (nullOr (either str path))); - }; - zsh = { - rc = mkOption { - type = types.lines; - default = ""; - description = '' - Zsh lines to be written to $XDG_CONFIG_HOME/zsh/extra.zshrc and - sourced by $XDG_CONFIG_HOME/zsh/.zshrc - ''; - }; - env = mkOption { - type = types.lines; - default = ""; - description = '' - Zsh lines to be written to $XDG_CONFIG_HOME/zsh/extra.zshenv and - sourced by $XDG_CONFIG_HOME/zsh/.zshenv - ''; - }; - }; - }; - }; - - config = { - ## Convenience aliases - home-manager.users.${config.my.username} = mkAliasDefinitions options.my.home; - users.users.${config.my.username} = mkAliasDefinitions options.my.user; - my.user.packages = config.my.packages; - - ## PATH should always start with its old value - my.env.PATH = [ "$PATH" ]; - environment.extraInit = - let exportLines = mapAttrsToList (n: v: "export ${n}=\"${v}\"") config.my.env; - in '' - export XAUTHORITY=/tmp/Xauthority - [ -e ~/.Xauthority ] && mv -f ~/.Xauthority "$XAUTHORITY" - - ${concatStringsSep "\n" exportLines} - ''; - - # I avoid programs.zsh.*Init variables because they initialize too soon. My - # zsh config is particular about load order. - my.home.xdg.configFile = { - "zsh/extra.zshrc".text = - let aliasLines = mapAttrsToList (n: v: "alias ${n}=\"${v}\"") config.my.alias; - in '' - # This file is autogenerated, do not edit it! - ${concatStringsSep "\n" aliasLines} - ${config.my.zsh.rc} - ''; - "zsh/extra.zshenv".text = '' - # This file is autogenerated, do not edit it! - ${config.my.zsh.env}; - ''; - }; - }; -} diff --git a/modules/desktop/apps/default.nix b/modules/desktop/apps/default.nix deleted file mode 100644 index f3fdefd3..00000000 --- a/modules/desktop/apps/default.nix +++ /dev/null @@ -1,13 +0,0 @@ -{ config, lib, pkgs, ... }: - -{ - imports = [ - ./daw.nix - ./discord.nix - ./graphics.nix - ./recording.nix - ./rofi.nix - ./skype.nix - ./vm.nix - ]; -} diff --git a/modules/desktop/apps/discord.nix b/modules/desktop/apps/discord.nix index 3c28af29..8bdb9571 100644 --- a/modules/desktop/apps/discord.nix +++ b/modules/desktop/apps/discord.nix @@ -1,17 +1,20 @@ { config, options, lib, pkgs, ... }: + with lib; -{ +with lib.my; +let cfg = config.modules.desktop.apps.discord; +in { options.modules.desktop.apps.discord = { - enable = mkOption { - type = types.bool; - default = false; - }; + enable = mkBoolOpt false; }; - config = mkIf config.modules.desktop.apps.discord.enable { - my.packages = with pkgs; [ - discord - # ripcord + config = mkIf cfg.enable { + user.packages = with pkgs; [ + # If not installed from unstable, Discord will sometimes soft-lock itself + # on a "there's an update for discord" screen. + unstable.discord + + # unstable.ripcord ]; }; } diff --git a/modules/dev/godot.nix b/modules/desktop/apps/godot.nix similarity index 59% rename from modules/dev/godot.nix rename to modules/desktop/apps/godot.nix index d4df97a2..102cf139 100644 --- a/modules/dev/godot.nix +++ b/modules/desktop/apps/godot.nix @@ -4,17 +4,17 @@ # but to prototype (for 3D, mainly) I'll occasionally reach for godot. { config, options, lib, pkgs, ... }: + with lib; -{ - options.modules.dev.godot = { - enable = mkOption { - type = types.bool; - default = false; - }; +with lib.my; +let cfg = config.modules.desktop.apps.godot; +in { + options.modules.desktop.apps.godot = { + enable = mkBoolOpt false; }; - config = mkIf config.modules.dev.godot.enable { - my.packages = with pkgs; [ + config = mkIf cfg.enable { + user.packages = with pkgs; [ godot ]; }; diff --git a/modules/desktop/apps/graphics.nix b/modules/desktop/apps/graphics.nix deleted file mode 100644 index 7ce981dc..00000000 --- a/modules/desktop/apps/graphics.nix +++ /dev/null @@ -1,50 +0,0 @@ -# modules/desktop/apps/graphics.nix -# -# The hardest part about switching to linux? Sacrificing Adobe. It really is -# difficult to replace and its open source alternatives don't *quite* cut it, -# but enough that I can do a fraction of it on Linux. For the rest I have a -# second computer dedicated to design work (and gaming). - -{ config, options, lib, pkgs, ... }: -with lib; -{ - options.modules.desktop.apps.graphics = - let mkBoolDefault = bool: mkOption { - type = types.bool; - default = bool; - }; - in { - enable = mkBoolDefault false; - tools.enable = mkBoolDefault false; - raster.enable = mkBoolDefault false; - vector.enable = mkBoolDefault false; - sprites.enable = mkBoolDefault false; - }; - - config = let gfx = config.modules.desktop.apps.graphics; in { - my.packages = with pkgs; - (if gfx.enable || gfx.tools.enable then [ - font-manager # so many damned fonts... - imagemagick # for image manipulation from the shell - ] else []) ++ - - # replaces illustrator & indesign - (if gfx.enable || gfx.vector.enable then [ - unstable.inkscape - ] else []) ++ - - # Replaces photoshop - (if gfx.enable || gfx.raster.enable then [ - krita - gimp - gimpPlugins.resynthesizer2 # content-aware scaling in gimp - ] else []) ++ - - # Sprite sheets & animation - (if gfx.enable || gfx.sprites.enable then [ aseprite-unfree ] else []); - - my.home.xdg.configFile = mkIf (gfx.enable || gfx.raster.enable) { - "GIMP/2.10" = { source = ; recursive = true; }; - }; - }; -} diff --git a/modules/desktop/apps/recording.nix b/modules/desktop/apps/recording.nix deleted file mode 100644 index 114b249d..00000000 --- a/modules/desktop/apps/recording.nix +++ /dev/null @@ -1,28 +0,0 @@ -# modules/desktop/apps/recording.nix -# -# OBS to capture footage/stream, DaVinci Resolve for editing (on my Windows -# system -- it will run on linux, but it can't be automated on nix, what with -# their devs registration-gating their free download). - -{ config, options, lib, pkgs, ... }: -with lib; -{ - options.modules.desktop.apps.recording = - let mkBoolDefault = bool: mkOption { - type = types.bool; - default = bool; - }; - in { - enable = mkBoolDefault false; - audio.enable = mkBoolDefault false; - video.enable = mkBoolDefault false; - }; - - config = let rc = config.modules.desktop.apps.recording; in { - my.packages = with pkgs; - # for recording and remastering audio - (if rc.enable || rc.audio.enable then [ audacity ] else []) ++ - # for longer term streaming/recording the screen - (if rc.enable || rc.video.enable then [ obs-studio handbrake ] else []); - }; -} diff --git a/modules/desktop/apps/rofi.nix b/modules/desktop/apps/rofi.nix index 04074449..fa29b6fb 100644 --- a/modules/desktop/apps/rofi.nix +++ b/modules/desktop/apps/rofi.nix @@ -1,66 +1,63 @@ { config, options, lib, pkgs, ... }: with lib; -{ +with lib.my; +let cfg = config.modules.desktop.apps.rofi; +in { options.modules.desktop.apps.rofi = { - enable = mkOption { - type = types.bool; - default = false; - }; + enable = mkBoolOpt false; }; - config = mkIf config.modules.desktop.apps.rofi.enable { - my = { - # link recursively so other modules can link files in its folder - # home.xdg.configFile."rofi" = { - # source = ; - # recursive = true; - # }; + config = mkIf cfg.enable { + # link recursively so other modules can link files in its folder + # home.xdg.configFile."rofi" = { + # source = ; + # recursive = true; + # }; - packages = with pkgs; [ - (writeScriptBin "rofi" '' - #!${stdenv.shell} - exec ${rofi}/bin/rofi -terminal xst -m -1 "$@" - '') + user.packages = with pkgs; [ + (writeScriptBin "rofi" '' + #!${stdenv.shell} + exec ${pkgs.rofi}/bin/rofi -terminal xst -m -1 "$@" + '') - # For rapidly test changes to rofi's stylesheets - # (writeScriptBin "rofi-test" '' - # #!${stdenv.shell} - # themefile=$1 - # themename=${modules.theme.name} - # shift - # exec rofi \ - # -theme ~/.dotfiles/modules/themes/$themename/rofi/$themefile \ - # "$@" - # '') + # For rapidly test changes to rofi's stylesheets + # (writeScriptBin "rofi-test" '' + # #!${stdenv.shell} + # themefile=$1 + # themename=${my.theme.name} + # shift + # exec rofi \ + # -theme ${themeDir}/$themename/rofi/$themefile \ + # "$@" + # '') - # Fake rofi dmenu entries - (makeDesktopItem { - name = "rofi-bookmarkmenu"; - desktopName = "Open Bookmark in Browser"; - icon = "bookmark-new-symbolic"; - exec = "${}"; - }) - (makeDesktopItem { - name = "rofi-filemenu"; - desktopName = "Open Directory in Terminal"; - icon = "folder"; - exec = "${}"; - }) - (makeDesktopItem { - name = "rofi-filemenu-scratch"; - desktopName = "Open Directory in Scratch Terminal"; - icon = "folder"; - exec = "${} -x"; - }) + # Fake rofi dmenu entries + (makeDesktopItem { + name = "rofi-bookmarkmenu"; + desktopName = "Open Bookmark in Browser"; + icon = "bookmark-new-symbolic"; + exec = "${binDir}/rofi/bookmarkmenu"; + }) + (makeDesktopItem { + name = "rofi-filemenu"; + desktopName = "Open Directory in Terminal"; + icon = "folder"; + exec = "${binDir}/rofi/filemenu"; + }) + (makeDesktopItem { + name = "rofi-filemenu-scratch"; + desktopName = "Open Directory in Scratch Terminal"; + icon = "folder"; + exec = "${binDir}/rofi/filemenu -x"; + }) - (makeDesktopItem { - name = "lock-display"; - desktopName = "Lock screen"; - icon = "system-lock-screen"; - exec = "${}"; - }) - ]; - }; + (makeDesktopItem { + name = "lock-display"; + desktopName = "Lock screen"; + icon = "system-lock-screen"; + exec = "${binDir}/zzz"; + }) + ]; }; } diff --git a/modules/desktop/apps/skype.nix b/modules/desktop/apps/skype.nix index 89f99b73..f12fbbce 100644 --- a/modules/desktop/apps/skype.nix +++ b/modules/desktop/apps/skype.nix @@ -1,15 +1,15 @@ { config, options, lib, pkgs, ... }: + with lib; -{ +with lib.my; +let cfg = config.modules.desktop.apps.skype; +in { options.modules.desktop.apps.skype = { - enable = mkOption { - type = types.bool; - default = false; - }; + enable = mkEnableOption false; }; - config = mkIf config.modules.desktop.apps.skype.enable { - my.packages = with pkgs; [ + config = mkIf cfg.enable { + user.packages = with pkgs; [ skypeforlinux skype_call_recorder ]; diff --git a/modules/dev/unity3d.nix b/modules/desktop/apps/unity3d.nix similarity index 50% rename from modules/dev/unity3d.nix rename to modules/desktop/apps/unity3d.nix index 0734cbf4..afe1251f 100644 --- a/modules/dev/unity3d.nix +++ b/modules/desktop/apps/unity3d.nix @@ -3,17 +3,17 @@ # I don't use Unity often, but when I do, it's in a team or with students. { config, options, lib, pkgs, ... }: + with lib; -{ - options.modules.dev.unity3d = { - enable = mkOption { - type = types.bool; - default = false; - }; +with lib.my; +let cfg = config.modules.desktop.apps.unity3d; +in { + options.modules.desktop.apps.unity3d = { + enable = mkBoolOpt false; }; - config = mkIf config.modules.dev.unity3d.enable { - my.packages = with pkgs; [ + config = mkIf cfg.enable { + user.packages = with pkgs; [ unity3d ]; }; diff --git a/modules/desktop/apps/vm.nix b/modules/desktop/apps/vm.nix deleted file mode 100644 index a4d3ab77..00000000 --- a/modules/desktop/apps/vm.nix +++ /dev/null @@ -1,26 +0,0 @@ -# modules/desktop/apps/vm.nix -# -# For testing software or building it on other OSes. If I find out how to get -# macOS on qemu/libvirt I'd be happy to leave virtualbox behind. - -{ config, options, lib, pkgs, ... }: -with lib; -{ - options.modules.desktop.apps.vm = { - enable = mkOption { - type = types.bool; - default = false; - }; - }; - - # TODO Figure out macOS guest on libvirt/qemu instead - config = mkIf config.modules.desktop.apps.vm.enable { - virtualisation.virtualbox.host = { - enable = true; - # urg, takes so long to build, but needed for macOS guest - enableExtensionPack = true; - }; - - my.user.extraGroups = [ "vboxusers" ]; - }; -} diff --git a/modules/desktop/browsers/default.nix b/modules/desktop/browsers/default.nix index 737d6a8d..972985ed 100644 --- a/modules/desktop/browsers/default.nix +++ b/modules/desktop/browsers/default.nix @@ -1,21 +1,14 @@ -{ config, lib, pkgs, ... }: -with lib; -{ - imports = [ - ./firefox.nix - ./qutebrowser.nix - ./vimb.nix - ./vivaldi.nix - ]; +{ options, config, lib, pkgs, ... }: +with lib; +with lib.my; +let cfg = config.modules.desktop.browsers; +in { options.modules.desktop.browsers = { - default = mkOption { - type = with types; nullOr str; - default = null; - }; + default = mkOpt (with types; nullOr str) null; }; - config = mkIf (config.modules.desktop.browsers.default != null) { - my.env.BROWSER = config.modules.desktop.browsers.default; + config = mkIf (cfg.default != null) { + env.BROWSER = cfg.default; }; } diff --git a/modules/desktop/browsers/firefox.nix b/modules/desktop/browsers/firefox.nix index 91df917c..40792066 100644 --- a/modules/desktop/browsers/firefox.nix +++ b/modules/desktop/browsers/firefox.nix @@ -3,40 +3,128 @@ # Oh firefox, gateway to the interwebs, devourer of ram. Give onto me your # infinite knowledge and shelter me from ads. -{ config, options, lib, pkgs, ... }: +{ options, config, lib, pkgs, ... }: + with lib; -{ - options.modules.desktop.browsers.firefox = { - enable = mkOption { - type = types.bool; - default = false; - }; - profileName = mkOption { - type = types.str; - default = config.my.username; - }; +with lib.my; +let cfg = config.modules.desktop.browsers.firefox; +in { + options.modules.desktop.browsers.firefox = with types; { + enable = mkBoolOpt false; + profileName = mkOpt types.str config.user.name; + + settings = mkOpt' (attrsOf (oneOf [ bool int str ])) {} '' + Firefox preferences to set in user.js + ''; + extraConfig = mkOpt' lines "" '' + Extra preferences to dd to user.js + ''; + + userChrome = mkOpt' lines "" "CSS Styles for Firefox's interface"; + userContent = mkOpt' lines "" "Global CSS Styles for websites"; }; - config = mkIf config.modules.desktop.browsers.firefox.enable { - my.packages = with pkgs; [ - firefox-bin - (makeDesktopItem { - name = "firefox-private"; - desktopName = "Firefox (Private)"; - genericName = "Open a private Firefox window"; - icon = "firefox"; - exec = "${firefox-bin}/bin/firefox --private-window"; - categories = "Network"; - }) - ]; + config = mkIf cfg.enable (mkMerge [ + { + user.packages = with pkgs; [ + firefox-bin + (makeDesktopItem { + name = "firefox-private"; + desktopName = "Firefox (Private)"; + genericName = "Open a private Firefox window"; + icon = "firefox"; + exec = "${firefox-bin}/bin/firefox --private-window"; + categories = "Network"; + }) + ]; - my.env.XDG_DESKTOP_DIR = "$HOME"; # (try to) prevent ~/Desktop + # Prevent auto-creation of ~/Desktop. The trailing slash is necessary; see + # https://bugzilla.mozilla.org/show_bug.cgi?id=1082717 + env.XDG_DESKTOP_DIR = "$HOME/"; - # Use a stable profile name so we can target it in themes - my.home.home.file = - let cfg = config.modules.desktop.browsers.firefox; in - { - ".mozilla/firefox/profiles.ini".text = '' + modules.desktop.browsers.firefox.settings = { + "devtools.theme" = "dark"; + # Enable userContent.css and userChrome.css for our theme modules + "toolkit.legacyUserProfileCustomizations.stylesheets" = true; + # Stop creating ~/Downloads! + "browser.download.dir" = "${homeDir}/dl"; + # Don't use the built-in password manager; a nixos user is more likely + # using an external one (you are using one, right?). + "signon.rememberSignons" = false; + # Do not check if Firefox is the default browser + "browser.shell.checkDefaultBrowser" = false; + # Disable the "new tab page" feature and show a blank tab instead + # https://wiki.mozilla.org/Privacy/Reviews/New_Tab + # https://support.mozilla.org/en-US/kb/new-tab-page-show-hide-and-customize-top-sites#w_how-do-i-turn-the-new-tab-page-off + "browser.newtabpage.enabled" = false; + "browser.newtab.url" = "about:blank"; + # Disable Activity Stream + # https://wiki.mozilla.org/Firefox/Activity_Stream + "browser.newtabpage.activity-stream.enabled" = false; + # Disable new tab tile ads & preload + # http://www.thewindowsclub.com/disable-remove-ad-tiles-from-firefox + # http://forums.mozillazine.org/viewtopic.php?p=13876331#p13876331 + # https://wiki.mozilla.org/Tiles/Technical_Documentation#Ping + # https://gecko.readthedocs.org/en/latest/browser/browser/DirectoryLinksProvider.html#browser-newtabpage-directory-source + # https://gecko.readthedocs.org/en/latest/browser/browser/DirectoryLinksProvider.html#browser-newtabpage-directory-ping + "browser.newtabpage.enhanced" = false; + "browser.newtab.preload" = false; + "browser.newtabpage.directory.ping" = ""; + "browser.newtabpage.directory.source" = "data:text/plain,{}"; + # Disable some not so useful functionality. + "media.videocontrols.picture-in-picture.video-toggle.enabled" = false; + "extensions.htmlaboutaddons.recommendations.enabled" = false; + "extensions.htmlaboutaddons.discover.enabled" = false; + "extensions.pocket.enabled" = false; + "app.normandy.enabled" = false; + "app.normandy.api_url" = ""; + "extensions.shield-recipe-client.enabled" = false; + "app.shield.optoutstudies.enabled" = false; + # Disable battery API + # https://developer.mozilla.org/en-US/docs/Web/API/BatteryManager + # https://bugzilla.mozilla.org/show_bug.cgi?id=1313580 + "dom.battery.enabled" = false; + # Disable "beacon" asynchronous HTTP transfers (used for analytics) + # https://developer.mozilla.org/en-US/docs/Web/API/navigator.sendBeacon + "beacon.enabled" = false; + # Disable pinging URIs specified in HTML ping= attributes + # http://kb.mozillazine.org/Browser.send_pings + "browser.send_pings" = false; + # Disable gamepad API to prevent USB device enumeration + # https://www.w3.org/TR/gamepad/ + # https://trac.torproject.org/projects/tor/ticket/13023 + "dom.gamepad.enabled" = false; + # Don't try to guess domain names when entering an invalid domain name in URL bar + # http://www-archive.mozilla.org/docs/end-user/domain-guessing.html + "browser.fixup.alternate.enabled" = false; + # Disable telemetry + # https://wiki.mozilla.org/Platform/Features/Telemetry + # https://wiki.mozilla.org/Privacy/Reviews/Telemetry + # https://wiki.mozilla.org/Telemetry + # https://www.mozilla.org/en-US/legal/privacy/firefox.html#telemetry + # https://support.mozilla.org/t5/Firefox-crashes/Mozilla-Crash-Reporter/ta-p/1715 + # https://wiki.mozilla.org/Security/Reviews/Firefox6/ReviewNotes/telemetry + # https://gecko.readthedocs.io/en/latest/browser/experiments/experiments/manifest.html + # https://wiki.mozilla.org/Telemetry/Experiments + # https://support.mozilla.org/en-US/questions/1197144 + # https://firefox-source-docs.mozilla.org/toolkit/components/telemetry/telemetry/internals/preferences.html#id1 + "toolkit.telemetry.enabled" = false; + "toolkit.telemetry.unified" = false; + "toolkit.telemetry.archive.enabled" = false; + "experiments.supported" = false; + "experiments.enabled" = false; + "experiments.manifest.uri" = ""; + # Disable health reports (basically more telemetry) + # https://support.mozilla.org/en-US/kb/firefox-health-report-understand-your-browser-perf + # https://gecko.readthedocs.org/en/latest/toolkit/components/telemetry/telemetry/preferences.html + "datareporting.healthreport.uploadEnabled" = false; + "datareporting.healthreport.service.enabled" = false; + "datareporting.policy.dataSubmissionEnabled" = false; + }; + + # Use a stable profile name so we can target it in themes + home.file = let cfgPath = ".mozilla/firefox"; in { + "${cfgPath}/profiles.ini".text = '' [Profile0] Name=default IsRelative=1 @@ -47,6 +135,27 @@ with lib; StartWithLastProfile=1 Version=2 ''; + + "${cfgPath}/${cfg.profileName}.default/user.js" = + mkIf (cfg.settings != {} || cfg.extraConfig != "") { + text = '' + ${concatStrings (mapAttrsToList (name: value: '' + user_pref("${name}", ${builtins.toJSON value}); + '') cfg.settings)} + ${cfg.extraConfig} + ''; + }; + + "${cfgPath}/${cfg.profileName}.default/chrome/userChrome.css" = + mkIf (cfg.userChrome != "") { + text = cfg.userChrome; + }; + + "${cfgPath}/${cfg.profileName}.default/chrome/userContent.css" = + mkIf (cfg.userContent != "") { + text = cfg.userContent; + }; }; - }; + } + ]); } diff --git a/modules/desktop/browsers/qutebrowser.nix b/modules/desktop/browsers/qutebrowser.nix index 125d2386..1e382cee 100644 --- a/modules/desktop/browsers/qutebrowser.nix +++ b/modules/desktop/browsers/qutebrowser.nix @@ -3,18 +3,19 @@ # Qutebrowser is cute because it's not enough of a browser to be handsome. # Still, we can all tell he'll grow up to be one hell of a lady-killer. -{ config, options, lib, pkgs, ... }: +{ options, config, lib, pkgs, ... }: + with lib; -{ +with lib.my; +let cfg = config.modules.desktop.browsers.qutebrowser; +in { options.modules.desktop.browsers.qutebrowser = { - enable = mkOption { - type = types.bool; - default = false; - }; + enable = mkBoolOpt false; + userStyles = mkOpt types.lines ""; }; - config = mkIf config.modules.desktop.browsers.qutebrowser.enable { - my.packages = with pkgs; [ + config = mkIf cfg.enable { + user.packages = with pkgs; [ qutebrowser (makeDesktopItem { name = "qutebrowser-private"; @@ -25,9 +26,13 @@ with lib; categories = "Network"; }) ]; - my.home.xdg.configFile."qutebrowser" = { - source = ; - recursive = true; + + home = { + configFile."qutebrowser" = { + source = "${configDir}/qutebrowser"; + recursive = true; + }; + dataFile."qutebrowser/userstyles.css".text = userStyles; }; }; } diff --git a/modules/desktop/browsers/vimb.nix b/modules/desktop/browsers/vimb.nix deleted file mode 100644 index 875232b5..00000000 --- a/modules/desktop/browsers/vimb.nix +++ /dev/null @@ -1,28 +0,0 @@ -# NOTE pkgs.vimb is unmaintained and broken on nixos. This module doesn't work, -# and only exists for posterity. Don't use it! - -{ config, options, lib, pkgs, ... }: -with lib; -{ - options.modules.desktop.browsers.vimb = { - enable = mkOption { - type = types.bool; - default = false; - }; - }; - - config = mkIf config.modules.desktop.browsers.vimb.enable { - my.packages = with pkgs; [ - vimb - tabbed - (makeDesktopItem { - name = "vimb-private"; - desktopName = "Vimb (Private)"; - genericName = "Open an incognito Vimb window"; - icon = "vim"; - exec = "${firefox-bin}/bin/vimb --incognito"; - categories = "Network"; - }) - ]; - }; -} diff --git a/modules/desktop/browsers/vivaldi.nix b/modules/desktop/browsers/vivaldi.nix deleted file mode 100644 index 82fdddeb..00000000 --- a/modules/desktop/browsers/vivaldi.nix +++ /dev/null @@ -1,27 +0,0 @@ -# modules/browser/vivaldi.nix --- ... - -{ config, options, lib, pkgs, ... }: -with lib; -{ - options.modules.desktop.browsers.vivaldi = { - enable = mkOption { - type = types.bool; - default = false; - }; - }; - - config = mkIf config.modules.desktop.browsers.vivaldi.enable { - my.packages = with pkgs; [ - vivaldi - vivaldi-widevine - (makeDesktopItem { - name = "vivaldi-private"; - desktopName = "Vivaldi (Incognito)"; - genericName = "Open an incognito Vivaldi window"; - icon = "vivaldi"; - exec = "${vivaldi}/bin/vivaldi --incognito"; - categories = "Network"; - }) - ]; - }; -} diff --git a/modules/desktop/bspwm.nix b/modules/desktop/bspwm.nix index b0f53eac..612b2bed 100644 --- a/modules/desktop/bspwm.nix +++ b/modules/desktop/bspwm.nix @@ -1,15 +1,14 @@ -{ config, options, lib, pkgs, ... }: -with lib; -{ - imports = [ - ./common.nix - ]; +{ options, config, lib, pkgs, ... }: +with lib; +with lib.my; +let cfg = config.modules.desktop.bspwm; +in { options.modules.desktop.bspwm = { - enable = mkOption { type = types.bool; default = false; }; + enable = mkBoolOpt false; }; - config = mkIf config.modules.desktop.bspwm.enable { + config = mkIf cfg.enable { environment.systemPackages = with pkgs; [ lightdm dunst @@ -25,18 +24,29 @@ with lib; redshift.enable = true; xserver = { enable = true; - displayManager.defaultSession = "none+bspwm"; - displayManager.lightdm.enable = true; - displayManager.lightdm.greeters.mini.enable = true; + displayManager = { + defaultSession = "none+bspwm"; + lightdm.enable = true; + lightdm.greeters.mini.enable = true; + }; windowManager.bspwm.enable = true; }; }; + systemd.user.services."dunst" = { + enable = true; + description = ""; + wantedBy = [ "default.target" ]; + serviceConfig.Restart = "always"; + serviceConfig.RestartSec = 2; + serviceConfig.ExecStart = "${pkgs.dunst}/bin/dunst"; + }; + # link recursively so other modules can link files in their folders - my.home.xdg.configFile = { - "sxhkd".source = ; + home.configFile = { + "sxhkd".source = "${configDir}/sxhkd"; "bspwm" = { - source = ; + source = "${configDir}/bspwm"; recursive = true; }; }; diff --git a/modules/desktop/common.nix b/modules/desktop/common.nix deleted file mode 100644 index 1334d518..00000000 --- a/modules/desktop/common.nix +++ /dev/null @@ -1,103 +0,0 @@ -{ config, lib, pkgs, ... }: -{ - my.packages = with pkgs; [ - # I often need a thumbnail browser to show off, peruse or organize photos, - # design work, or digital art. - xfce.thunar - xfce.tumbler # for thumbnails - - calibre # managing my ebooks - evince # pdf reader - feh # image viewer - mpv # video player - xclip - xdotool - libqalculate # calculator cli w/ currency conversion - (makeDesktopItem { - name = "scratch-calc"; - desktopName = "Calculator"; - icon = "calc"; - exec = "scratch '${tmux}/bin/tmux new-session -s calc -n calc qalc'"; - categories = "Development"; - }) - ]; - - ## Sound - sound.enable = true; - hardware.pulseaudio.enable = true; - - ## Fonts - fonts = { - enableFontDir = true; - enableGhostscriptFonts = true; - fonts = with pkgs; [ - ubuntu_font_family - dejavu_fonts - fira-code - fira-code-symbols - symbola - noto-fonts - noto-fonts-cjk - font-awesome-ttf - siji - ]; - fontconfig.defaultFonts = { - sansSerif = ["Ubuntu"]; - monospace = ["Fira Code"]; - }; - }; - - ## Apps/Services - # For redshift - location = (if config.time.timeZone == "America/Toronto" then { - latitude = 43.70011; - longitude = -79.4163; - } else if config.time.timeZone == "Europe/Copenhagen" then { - latitude = 55.88; - longitude = 12.5; - } else {}); - - services.xserver = { - displayManager.lightdm.greeters.mini.user = config.my.username; - }; - - services.picom = { - backend = "glx"; - vSync = true; - opacityRules = [ - # "100:class_g = 'Firefox'" - # "100:class_g = 'Vivaldi-stable'" - "100:class_g = 'VirtualBox Machine'" - # Art/image programs where we need fidelity - "100:class_g = 'Gimp'" - "100:class_g = 'Inkscape'" - "100:class_g = 'aseprite'" - "100:class_g = 'krita'" - "100:class_g = 'feh'" - "100:class_g = 'mpv'" - "100:class_g = 'Rofi'" - "100:class_g = 'Peek'" - "99:_NET_WM_STATE@:32a = '_NET_WM_STATE_FULLSCREEN'" - ]; - shadowExclude = [ - # Put shadows on notifications, the scratch popup and rofi only - "! name~='(rofi|scratch|Dunst)$'" - ]; - settings.blur-background-exclude = [ - "window_type = 'dock'" - "window_type = 'desktop'" - "class_g = 'Rofi'" - "_GTK_FRAME_EXTENTS@:c" - ]; - }; - - # Try really hard to get QT to respect my GTK theme. - my.env.GTK_DATA_PREFIX = [ "${config.system.path}" ]; - my.env.QT_QPA_PLATFORMTHEME = "gtk2"; - qt5 = { style = "gtk2"; platformTheme = "gtk2"; }; - services.xserver.displayManager.sessionCommands = '' - export GTK2_RC_FILES="$XDG_CONFIG_HOME/gtk-2.0/gtkrc" - source "$XDG_CONFIG_HOME"/xsession/*.sh - xrdb -merge "$XDG_CONFIG_HOME"/xtheme/* - ''; -} diff --git a/modules/desktop/default.nix b/modules/desktop/default.nix index f6b2cbbb..8d98794a 100644 --- a/modules/desktop/default.nix +++ b/modules/desktop/default.nix @@ -1,13 +1,140 @@ -{ config, lib, pkgs, ... }: +{ config, options, lib, pkgs, ... }: -{ - imports = [ - ./bspwm.nix - # ./stumpwm.nix +with lib; +with lib.my; +let cfg = config.modules.desktop; +in { + config = mkIf config.services.xserver.enable { + assertions = [ + { + assertion = (countAttrs (n: v: n == "enable" && value) cfg) < 2; + message = "Can't have more than one desktop environment enabled at a time"; + } + { + assertion = + let srv = config.services; + in srv.xserver.enable || + srv.sway.enable || + !(anyAttrs + (n: v: isAttrs v && + anyAttrs (n: v: isAttrs v && v.enable)) + cfg); + message = "Can't enable a desktop app without a desktop environment"; + } + ]; - ./apps - ./term - ./browsers - ./gaming - ]; + user.packages = with pkgs; [ + feh # image viewer + xclip + xdotool + + libqalculate # calculator cli w/ currency conversion + (makeDesktopItem { + name = "scratch-calc"; + desktopName = "Calculator"; + icon = "calc"; + exec = ''scratch "${tmux}/bin/tmux new-session -s calc -n calc qalc"''; + categories = "Development"; + }) + ]; + + fonts = { + enableFontDir = true; + enableGhostscriptFonts = true; + fonts = with pkgs; [ + ubuntu_font_family + dejavu_fonts + fira-code + fira-code-symbols + symbola + noto-fonts + noto-fonts-cjk + font-awesome-ttf + siji + ]; + fontconfig.defaultFonts = { + sansSerif = ["Fira Sans"]; + monospace = ["Fira Code"]; + }; + }; + + ## Apps/Services + services.xserver.displayManager.lightdm.greeters.mini.user = config.user.name; + + services.picom = { + backend = "glx"; + vSync = true; + opacityRules = [ + # "100:class_g = 'Firefox'" + # "100:class_g = 'Vivaldi-stable'" + "100:class_g = 'VirtualBox Machine'" + # Art/image programs where we need fidelity + "100:class_g = 'Gimp'" + "100:class_g = 'Inkscape'" + "100:class_g = 'aseprite'" + "100:class_g = 'krita'" + "100:class_g = 'feh'" + "100:class_g = 'mpv'" + "100:class_g = 'Rofi'" + "100:class_g = 'Peek'" + "99:_NET_WM_STATE@:32a = '_NET_WM_STATE_FULLSCREEN'" + ]; + shadowExclude = [ + # Put shadows on notifications, the scratch popup and rofi only + "! name~='(rofi|scratch|Dunst)$'" + ]; + settings = { + blur-background-exclude = [ + "window_type = 'dock'" + "window_type = 'desktop'" + "class_g = 'Rofi'" + "_GTK_FRAME_EXTENTS@:c" + ]; + + # Unredirect all windows if a full-screen opaque window is detected, to + # maximize performance for full-screen windows. Known to cause + # flickering when redirecting/unredirecting windows. + unredir-if-possible = true; + + # GLX backend: Avoid using stencil buffer, useful if you don't have a + # stencil buffer. Might cause incorrect opacity when rendering + # transparent content (but never practically happened) and may not work + # with blur-background. My tests show a 15% performance boost. + # Recommended. + glx-no-stencil = true; + + # Use X Sync fence to sync clients' draw calls, to make sure all draw + # calls are finished before picom starts drawing. Needed on + # nvidia-drivers with GLX backend for some users. + xrender-sync-fence = true; + }; + }; + + # Try really hard to get QT to respect my GTK theme. + env.GTK_DATA_PREFIX = [ "${config.system.path}" ]; + env.QT_QPA_PLATFORMTHEME = "gtk2"; + qt5 = { style = "gtk2"; platformTheme = "gtk2"; }; + # Also, read xresources files in ~/.config/xtheme/* and init scripts in + # ~/.config/xsessions/*, so I can centralize my theme config files. + services.xserver.displayManager.sessionCommands = + let cfg = config.services.xserver.desktopManager.wallpaper; in '' + export GTK2_RC_FILES="$XDG_CONFIG_HOME/gtk-2.0/gtkrc" + source "$XDG_CONFIG_HOME"/xsession/*.sh + xrdb -merge "$XDG_CONFIG_HOME"/xtheme/* + if [ -e "$XDG_DATA_HOME/wallpaper" ]; then + ${pkgs.feh}/bin/feh --bg-${cfg.mode} \ + ${optionalString cfg.combineScreens "--no-xinerama"} \ + --no-fehbg \ + $XDG_DATA_HOME/wallpaper + fi + ''; + + # Clean up leftovers, as much as we can + system.userActivationScripts.cleanupHome = '' + pushd "${homeDir}" + rm -rf .compose-cache .nv .pki .dbus .fehbg + [ -s .xsession-errors ] || rm -f .xsession-errors* + popd + ''; + }; } diff --git a/modules/desktop/gaming/default.nix b/modules/desktop/gaming/default.nix deleted file mode 100644 index ce1ec763..00000000 --- a/modules/desktop/gaming/default.nix +++ /dev/null @@ -1,9 +0,0 @@ -{ config, lib, pkgs, ... }: - -{ - imports = [ - ./emulators.nix - ./factorio.nix - ./steam.nix - ]; -} diff --git a/modules/desktop/gaming/emulators.nix b/modules/desktop/gaming/emulators.nix index 03e6d64d..cc1f7b91 100644 --- a/modules/desktop/gaming/emulators.nix +++ b/modules/desktop/gaming/emulators.nix @@ -1,27 +1,25 @@ -{ config, options, lib, pkgs, ... }: +{ options, config, lib, pkgs, ... }: with lib; -{ - options.modules.desktop.gaming.emulators = - let mkBoolDefault = bool: mkOption { - type = types.bool; - default = bool; - }; - in { - psx.enable = mkBoolDefault false; # Playstation - ds.enable = mkBoolDefault false; # Nintendo DS - gb.enable = mkBoolDefault false; # GameBoy + GameBoy Color - gba.enable = mkBoolDefault false; # GameBoy Advance - snes.enable = mkBoolDefault false; # Super Nintendo - }; +with lib.my; +let cfg = config.modules.desktop.gaming.emulators; +in { + options.modules.desktop.gaming.emulators = { + psx.enable = mkBoolOpt false; # Playstation + ds.enable = mkBoolOpt false; # Nintendo DS + gb.enable = mkBoolOpt false; # GameBoy + GameBoy Color + gba.enable = mkBoolOpt false; # GameBoy Advance + snes.enable = mkBoolOpt false; # Super Nintendo + }; - config = let emu = config.modules.desktop.gaming.emulators; in { - my.packages = with pkgs; - (if emu.psx.enable then [ epsxe ] else []) ++ - (if emu.ds.enable then [ desume ] else []) ++ - (if (emu.gba.enable || - emu.gb.enable || - emu.snes.enable) - then [ higan ] else []); + config = { + user.packages = with pkgs; [ + (mkIf cfg.psx.enable epsxe) + (mkIf cfg.ds.enable desmume) + (mkIf (cfg.gba.enable || + cfg.gb.enable || + cfg.snes.enable) + higan) + ]; }; } diff --git a/modules/desktop/gaming/steam.nix b/modules/desktop/gaming/steam.nix index 43a7d705..56cd1c35 100644 --- a/modules/desktop/gaming/steam.nix +++ b/modules/desktop/gaming/steam.nix @@ -1,30 +1,53 @@ -{ config, options, lib, pkgs, ... }: +{ options, config, lib, pkgs, ... }: with lib; -{ - options.modules.desktop.gaming.steam = { - enable = mkOption { - type = types.bool; - default = false; - }; +with lib.my; +let cfg = config.modules.desktop.gaming.steam; +in { + options.modules.desktop.gaming.steam = with types; { + enable = mkBoolOpt false; + hardware.enable = mkBoolOpt false; + libDir = mkOpt str "$XDG_DATA_HOME/steamlib"; }; - config = mkIf config.modules.desktop.gaming.steam.enable { - my.packages = with pkgs; [ - # Get steam to keep its garbage out of $HOME - (writeScriptBin "steam" '' - #!${stdenv.shell} - HOME="$XDG_DATA_HOME/steamlib" exec ${steam}/bin/steam "$@" - '') - # for GOG and humblebundle games - (writeScriptBin "steam-run" '' - #!${stdenv.shell} - HOME="$XDG_DATA_HOME/steamlib" exec ${steam-run-native}/bin/steam-run "$@" - '') - xboxdrv # driver for 360 controller - ]; + config = mkIf cfg.enable (mkMerge [ + { + # I avoid programs.steam.enable because it installs another steam binary, + # which the xdesktop package invokes, instead of my steam shims below. + hardware.opengl.enable = true; + hardware.opengl.driSupport32Bit = true; + hardware.pulseaudio.support32Bit = config.hardware.pulseaudio.enable; - hardware.opengl.driSupport32Bit = true; - hardware.pulseaudio.support32Bit = true; - }; + user.packages = with pkgs; [ + # Get steam to keep its garbage out of $HOME + (writeScriptBin "steam" '' + #!${stdenv.shell} + HOME="${cfg.libDir}" exec ${steam}/bin/steam "$@" + '') + # for running GOG and humble bundle games + (writeScriptBin "steam-run" '' + #!${stdenv.shell} + HOME="${cfg.libDir}" exec ${steam-run-native}/bin/steam-run "$@" + '') + # So a rofi entry exists + (makeDesktopItem { + name = "steam"; + desktopName = "Steam"; + icon = "steam"; + exec = "steam"; + terminal = "false"; + mimeType = "x-scheme-handler/steam"; + categories = "Network;FileTransfer;Game"; + }) + ]; + system.userActivationScripts.setupSteamDir = ''mkdir -p "${cfg.libDir}"''; + + # better for steam proton games + systemd.extraConfig = "DefaultLimitNOFILE=1048576"; + } + + (mkIf cfg.hardware.enable { + hardware.steam-hardware.enable = true; + }) + ]); } diff --git a/modules/desktop/apps/daw.nix b/modules/desktop/media/daw.nix similarity index 72% rename from modules/desktop/apps/daw.nix rename to modules/desktop/media/daw.nix index fd45e834..923a22c5 100644 --- a/modules/desktop/apps/daw.nix +++ b/modules/desktop/media/daw.nix @@ -1,4 +1,4 @@ -# modules/desktop/apps/daw.nix +# modules/desktop/media/daw.nix # # I make music for my games. LMMS is my DAW; or will be, once I've weened myself # off of Fruityloops. When I'm in the mood for a quicky I fire up sunvox @@ -6,17 +6,17 @@ # ever need to. { config, options, lib, pkgs, ... }: + with lib; -{ - options.modules.desktop.apps.daw = { - enable = mkOption { - type = types.bool; - default = false; - }; +with lib.my; +let cfg = config.modules.desktop.media.daw; +in { + options.modules.desktop.media.daw = { + enable = mkBoolOpt false; }; - config = mkIf config.modules.desktop.apps.daw.enable { - my.packages = with pkgs; [ + config = mkIf cfg.enable { + user.packages = with pkgs; [ # lmms on stable is broken due to 'Could not find the Qt platform plugin # "xcb" in ""' error: https://github.com/NixOS/nixpkgs/issues/76074 unstable.lmms # for making music diff --git a/modules/desktop/media/documents.nix b/modules/desktop/media/documents.nix new file mode 100644 index 00000000..4bc87e70 --- /dev/null +++ b/modules/desktop/media/documents.nix @@ -0,0 +1,24 @@ +# modules/desktop/media/docs.nix + +{ options, config, lib, pkgs, ... }: + +with lib; +with lib.my; +let cfg = config.modules.desktop.media.documents; +in { + options.modules.desktop.media.documents = { + enable = mkBoolOpt false; + pdf.enable = mkBoolOpt false; + ebook.enable = mkBoolOpt false; + }; + + config = mkIf cfg.enable { + user.packages = with pkgs; [ + (mkIf cfg.ebook.enable calibre) + (mkIf cfg.pdf.enable evince) + # zathura + ]; + + # TODO calibre/evince/zathura dotfiles + }; +} diff --git a/modules/desktop/media/graphics.nix b/modules/desktop/media/graphics.nix new file mode 100644 index 00000000..95f532b8 --- /dev/null +++ b/modules/desktop/media/graphics.nix @@ -0,0 +1,50 @@ +# modules/desktop/media/graphics.nix +# +# The hardest part about switching to linux? Sacrificing Adobe. It really is +# difficult to replace and its open source alternatives don't *quite* cut it, +# but enough that I can do a fraction of it on Linux. For the rest I have a +# second computer dedicated to design work (and gaming). + +{ config, options, lib, pkgs, ... }: + +with lib; +with lib.my; +let cfg = config.modules.desktop.media.graphics; +in { + options.modules.desktop.media.graphics = { + enable = mkBoolOpt false; + tools.enable = mkBoolOpt true; + raster.enable = mkBoolOpt true; + vector.enable = mkBoolOpt true; + sprites.enable = mkBoolOpt true; + }; + + config = mkIf cfg.enable { + user.packages = with pkgs; + (if cfg.tools.enable then [ + font-manager # so many damned fonts... + imagemagick # for image manipulation from the shell + ] else []) ++ + + # replaces illustrator & indesign + (if cfg.vector.enable then [ + unstable.inkscape + ] else []) ++ + + # Replaces photoshop + (if cfg.raster.enable then [ + krita + gimp + gimpPlugins.resynthesizer2 # content-aware scaling in gimp + ] else []) ++ + + # Sprite sheets & animation + (if cfg.sprites.enable then [ + aseprite-unfree + ] else []); + + home.configFile = mkIf cfg.raster.enable { + "GIMP/2.10" = { source = "${configDir}/gimp"; recursive = true; }; + }; + }; +} diff --git a/modules/media/mpv.nix b/modules/desktop/media/mpv.nix similarity index 52% rename from modules/media/mpv.nix rename to modules/desktop/media/mpv.nix index 25255b8b..ab51b638 100644 --- a/modules/media/mpv.nix +++ b/modules/desktop/media/mpv.nix @@ -1,15 +1,15 @@ { config, options, lib, pkgs, ... }: + with lib; -{ - options.modules.media.mpv = { - enable = mkOption { - type = types.bool; - default = false; - }; +with lib.my; +let cfg = config.modules.desktop.media.mpv; +in { + options.modules.desktop.media.mpv = { + enable = mkBoolOpt false; }; - config = mkIf config.modules.media.mpv.enable { - my.packages = with pkgs; [ + config = mkIf cfg.enable { + user.packages = with pkgs; [ mpv-with-scripts mpvc # CLI controller for mpv (mkIf config.services.xserver.enable diff --git a/modules/desktop/media/ncmpcpp.nix b/modules/desktop/media/ncmpcpp.nix new file mode 100644 index 00000000..d65b05d4 --- /dev/null +++ b/modules/desktop/media/ncmpcpp.nix @@ -0,0 +1,26 @@ +{ config, options, lib, pkgs, ... }: + +with lib; +with lib.my; +let cfg = config.modules.desktop.media.ncmpcpp; +in { + options.modules.desktop.media.ncmpcpp = { + enable = mkBoolOpt false; + # modipy.enable = mkBoolOpt false; + }; + + config = mkIf cfg.enable { + user.packages = with pkgs; [ + (ncmpcpp.override { visualizerSupport = true; }) + ]; + + env.NCMPCPP_HOME = "$XDG_CONFIG_HOME/ncmpcpp"; + + # Symlink these one at a time because ncmpcpp writes other files to + # ~/.config/ncmpcpp, so it needs to be writeable. + home.configFile = { + "ncmpcpp/config".source = "${configDir}/ncmpcpp/config"; + "ncmpcpp/bindings".source = "${configDir}/ncmpcpp/bindings"; + }; + }; +} diff --git a/modules/desktop/media/recording.nix b/modules/desktop/media/recording.nix new file mode 100644 index 00000000..2a141d26 --- /dev/null +++ b/modules/desktop/media/recording.nix @@ -0,0 +1,26 @@ +# modules/desktop/media/recording.nix +# +# OBS to capture footage/stream, audacity for audio, handbrake to encode it all. +# This, paired with DaVinci Resolve for video editing (on my Windows system) and +# I have what I need for youtube videos and streaming. + +{ config, options, lib, pkgs, ... }: + +with lib; +with lib.my; +let cfg = config.modules.desktop.media.recording; +in { + options.modules.desktop.media.recording = { + enable = mkBoolOpt false; + audio.enable = mkBoolOpt true; + video.enable = mkBoolOpt true; + }; + + config = mkIf cfg.enable { + user.packages = with pkgs; + # for recording and remastering audio + (if cfg.audio.enable then [ audacity ] else []) ++ + # for longer term streaming/recording the screen + (if cfg.video.enable then [ obs-studio handbrake ] else []); + }; +} diff --git a/modules/media/spotify.nix b/modules/desktop/media/spotify.nix similarity index 91% rename from modules/media/spotify.nix rename to modules/desktop/media/spotify.nix index 44b297f8..3587cfa0 100644 --- a/modules/media/spotify.nix +++ b/modules/desktop/media/spotify.nix @@ -2,38 +2,39 @@ # local music; most of which I haven't heard or don't even like. { config, options, lib, pkgs, ... }: + with lib; -{ - options.modules.media.spotify = { - enable = mkOption { - type = types.bool; - default = false; - }; +with lib.my; +let cfg = config.modules.desktop.media.spotify; +in { + options.modules.desktop.media.spotify = { + enable = mkBoolOpt false; + tui.enable = mkBoolOpt false; # TODO }; - config = mkIf config.modules.media.spotify.enable { - my.packages = with pkgs; [ + config = mkIf cfg.enable { + user.packages = with pkgs; [ + # spotify-tui is fine for selecting and playing music, but incomplete. We + # still occasionally need the official client for more sophisticated + # search and the "made for you" playlists. + spotify + # # services.spotifyd doesn't work so we'll have to roll our own spotifyd + # # spotify-tui solution. The dbus interface doesn't work, though, so we # # have to wait for spotify-tui to implement CLI command for controlling # # spotify playback. See # # https://github.com/Rigellute/spotify-tui/issues/147 or for spotifyd to # # get fixed. - # unstable.spotifyd + # master.spotifyd # (writeScriptBin "spt" '' # #!${stdenv.shell} # if ! systemctl --user is-active spotifyd >/dev/null; then # systemctl --user start spotifyd # fi # echo $TMUX >/tmp/spt.tmux - # exec ${unstable.spotify-tui}/bin/spt + # exec ${master.spotify-tui}/bin/spt # '') - # spotify-tui is fine for selecting and playing music, but incomplete. We - # still occasionally need the official client for more sophisticated - # search and the "made for you" playlists. - spotify - # # Since dbus doesn't work with Nix's spotifyd/spotify-tui, and I always # # use tmux for my terminal, may as well exploit tmux to control spotify. # playerctl @@ -84,11 +85,11 @@ with lib; # password_cmd = ${pkgs.pass}/bin/pass www/spotify.com | head -n1 # backend = pulseaudio # on_song_change_hook = spt-send-notify - # cache_path = /home/${config.my.username}/.cache/spotifyd + # cache_path = ${config.my.home}/.cache/spotifyd # ''; # in { # ExecStart = '' - # ${pkgs.unstable.spotifyd}/bin/spotifyd --no-daemon \ + # ${pkgs.master.spotifyd}/bin/spotifyd --no-daemon \ # --cache-path /tmp/spotifyd \ # --config-path ${spotifydConf} # ''; diff --git a/modules/desktop/stumpwm.nix b/modules/desktop/stumpwm.nix index c2cfa07e..1f0472e3 100644 --- a/modules/desktop/stumpwm.nix +++ b/modules/desktop/stumpwm.nix @@ -1,31 +1,36 @@ -{ config, lib, pkgs, ... }: +{ options, config, lib, pkgs, ... }: -{ - imports = [ - ./common.nix - ]; +with lib; +with lib.my; +let cfg = config.modules.desktop.stumpwm; +in { + options.modules.desktop.stumpwm = { + enable = mkBoolOpt false; + }; - environment.systemPackages = with pkgs; [ - lightdm - dunst - libnotify - ]; + config = mkIf cfg.enable { + environment.systemPackages = with pkgs; [ + lightdm + dunst + libnotify + ]; - # unstable.services.picom.enable = true; - services = { - redshift.enable = true; - xserver = { - enable = true; - windowManager.default = "stumpwm"; - windowManager.stumpwm.enable = true; - displayManager.lightdm.enable = true; - displayManager.lightdm.greeters.mini.enable = true; + # master.services.picom.enable = true; + services = { + redshift.enable = true; + xserver = { + enable = true; + windowManager.default = "stumpwm"; + windowManager.stumpwm.enable = true; + displayManager.lightdm.enable = true; + displayManager.lightdm.greeters.mini.enable = true; + }; + }; + + # link recursively so other modules can link files in their folders + home.configFile."stumpwm" = { + source = "${configDir}/stumpwm"; + recursive = true; }; }; - - # link recursively so other modules can link files in their folders - my.home.xdg.configFile."stumpwm" = { - source = ; - recursive = true; - }; } diff --git a/modules/desktop/term/default.nix b/modules/desktop/term/default.nix index 18ef58b5..79528254 100644 --- a/modules/desktop/term/default.nix +++ b/modules/desktop/term/default.nix @@ -1,23 +1,16 @@ -{ config, options, lib, pkgs, ... }: -with lib; -{ - imports = [ - # ./alacritty.nix - ./st.nix - # ./urxvt.nix - ]; +{ options, config, lib, pkgs, ... }: +with lib; +with lib.my; +let cfg = config.modules.desktop.term; +in { options.modules.desktop.term = { - default = mkOption { - type = types.str; - default = "xterm"; - }; + default = mkOpt types.str "xterm"; }; config = { - services.xserver.desktopManager.xterm.enable = - config.modules.desktop.term.default == "xterm"; + services.xserver.desktopManager.xterm.enable = mkDefault (cfg.default == "xterm"); - my.env.TERMINAL = config.modules.editors.default; + env.TERMINAL = cfg.default; }; } diff --git a/modules/desktop/term/st.nix b/modules/desktop/term/st.nix index 2067a16b..f95e2e2a 100644 --- a/modules/desktop/term/st.nix +++ b/modules/desktop/term/st.nix @@ -1,19 +1,25 @@ -{ config, lib, pkgs, ... }: +# modules/desktop/term/st.nix +# +# I like (x)st. This appears to be a controversial opinion; don't tell anyone, +# mkay? + +{ options, config, lib, pkgs, ... }: with lib; -{ +with lib.my; +let cfg = config.modules.desktop.term.st; +in { options.modules.desktop.term.st = { - enable = mkOption { - type = types.bool; - default = false; - }; + enable = mkBoolOpt false; }; - config = mkIf config.modules.desktop.term.st.enable { + config = mkIf cfg.enable { # xst-256color isn't supported over ssh, so revert to a known one - my.zsh.rc = ''[ "$TERM" = xst-256color ] && export TERM=xterm-256color''; + modules.shell.zsh.rcInit = '' + [ "$TERM" = xst-256color ] && export TERM=xterm-256color + ''; - my.packages = with pkgs; [ + user.packages = with pkgs; [ xst # st + nice-to-have extensions (makeDesktopItem { name = "xst"; diff --git a/modules/desktop/vm/lxd.nix b/modules/desktop/vm/lxd.nix new file mode 100644 index 00000000..44b74d12 --- /dev/null +++ b/modules/desktop/vm/lxd.nix @@ -0,0 +1,32 @@ +# Inspired by https://www.srid.ca/2012301.html + +{ options, config, lib, pkgs, ... }: + +with lib; +with lib.my; +let cfg = config.modules.desktop.vm.lxd; +in { + options.modules.desktop.vm.lxd = { + enable = mkBoolOpt false; + }; + + config = mkIf cfg.enable { + virtualisation.lxd.enable = true; + + user.packages = [ + (pkgs.writeScriptBin "lxc-build-nixos-image" '' + #!/usr/bin/env nix-shell + #!nix-shell -i bash -p nixos-generators + set -xe + config=$1 + metaimg=`nixos-generate -f lxc-metadata \ + | xargs -r cat \ + | awk '{print $3}'` + img=`nixos-generate -c $config -f lxc \ + | xargs -r cat \ + | awk '{print $3}'` + lxc image import --alias nixos $metaimg $img + '') + ]; + }; +} diff --git a/modules/desktop/vm/qemu.nix b/modules/desktop/vm/qemu.nix new file mode 100644 index 00000000..2dd8967a --- /dev/null +++ b/modules/desktop/vm/qemu.nix @@ -0,0 +1,21 @@ +{ options, config, lib, pkgs, ... }: + +with lib; +with lib.my; +let cfg = config.modules.desktop.vm.qemu; +in { + options.modules.desktop.vm.qemu = { + enable = mkBoolOpt false; + }; + + config = mkIf cfg.enable { + environment.systemPackages = with pkgs; [ + qemu + ]; + }; +} + +# Creating an image: +# qemu-img create -f qcow2 disk.img +# Creating a snapshot (don't tamper with disk.img): +# qemu-img create -f qcow2 -b disk.img snapshot.img diff --git a/modules/desktop/vm/virtualbox.nix b/modules/desktop/vm/virtualbox.nix new file mode 100644 index 00000000..018b314a --- /dev/null +++ b/modules/desktop/vm/virtualbox.nix @@ -0,0 +1,25 @@ +# modules/desktop/vm/virtualbox.nix +# +# For testing or building software on other OSes. If I find out how to get macOS +# on qemu/libvirt I'd be happy to leave virtualbox behind. + +{ options, config, lib, pkgs, ... }: + +with lib; +with lib.my; +let cfg = config.modules.desktop.vm.virtualbox; +in { + options.modules.desktop.vm.virtualbox = { + enable = mkBoolOpt false; + }; + + config = mkIf cfg.enable { + virtualisation.virtualbox.host = { + enable = true; + # urg, takes so long to build, but needed for macOS guest + # enableExtensionPack = true; + }; + + user.extraGroups = [ "vboxusers" ]; + }; +} diff --git a/modules/dev/cc.nix b/modules/dev/cc.nix index 577506d2..61291196 100644 --- a/modules/dev/cc.nix +++ b/modules/dev/cc.nix @@ -5,17 +5,17 @@ # tell anyone pls. { config, options, lib, pkgs, ... }: + with lib; -{ +with lib.my; +let cfg = config.modules.dev.cc; +in { options.modules.dev.cc = { - enable = mkOption { - type = types.bool; - default = false; - }; + enable = mkBoolOpt false; }; - config = mkIf config.modules.dev.cc.enable { - my.packages = with pkgs; [ + config = mkIf cfg.enable { + user.packages = with pkgs; [ clang gcc bear diff --git a/modules/dev/clojure.nix b/modules/dev/clojure.nix index b91dd38d..23f267d5 100644 --- a/modules/dev/clojure.nix +++ b/modules/dev/clojure.nix @@ -2,18 +2,18 @@ # # I don't use clojure. Perhaps one day... -{ config, options, lib, pkgs, ... }: +{ config, options, lib, pkgs, my, ... }: + with lib; -{ +with lib.my; +let cfg = config.modules.dev.clojure; +in { options.modules.dev.clojure = { - enable = mkOption { - type = types.bool; - default = false; - }; + enable = mkBoolOpt false; }; - config = mkIf config.modules.dev.clojure.enable { - my.packages = with pkgs; [ + config = mkIf cfg.enable { + user.packages = with pkgs; [ clojure joker leiningen diff --git a/modules/dev/common-lisp.nix b/modules/dev/common-lisp.nix index c1dfb130..71fc25bd 100644 --- a/modules/dev/common-lisp.nix +++ b/modules/dev/common-lisp.nix @@ -3,17 +3,17 @@ # Mostly for my stumpwm config, and the occasional dip into lisp gamedev. { config, options, lib, pkgs, ... }: + with lib; -{ +with lib.my; +let cfg = config.modules.dev.common-lisp; +in { options.modules.dev.common-lisp = { - enable = mkOption { - type = types.bool; - default = false; - }; + enable = mkBoolOpt false; }; - config = mkIf config.modules.dev.common-lisp.enable { - my.packages = with pkgs; [ + config = mkIf cfg.enable { + user.packages = with pkgs; [ sbcl lispPackages.quicklisp ]; diff --git a/modules/dev/default.nix b/modules/dev/default.nix deleted file mode 100644 index 14be7685..00000000 --- a/modules/dev/default.nix +++ /dev/null @@ -1,23 +0,0 @@ -# modules/dev --- common settings for dev modules - -{ pkgs, ... }: -{ - imports = [ - ./cc.nix - ./clojure.nix - ./common-lisp.nix - ./godot.nix - # ./haskell.nix - # ./latex.nix - ./lua.nix - ./node.nix - ./python.nix - ./rust.nix - ./scala.nix - ./unity3d.nix - ./zsh.nix - ]; - - options = {}; - config = {}; -} diff --git a/modules/dev/lua.nix b/modules/dev/lua.nix index 8aa9fce2..d1fbd93e 100644 --- a/modules/dev/lua.nix +++ b/modules/dev/lua.nix @@ -6,24 +6,21 @@ # on a per-project basis. { config, options, lib, pkgs, ... }: + with lib; -{ +with lib.my; +let cfg = config.modules.dev.lua; +in { options.modules.dev.lua = { - enable = mkOption { - type = types.bool; - default = false; - }; + enable = mkBoolOpt false; + love2D.enable = mkBoolOpt false; }; - config = mkIf config.modules.dev.lua.enable { - my = { - packages = with pkgs; [ - lua - luaPackages.moonscript - luarocks - ]; - - zsh.rc = ''eval "$(luarocks path --bin)"''; - }; + config = mkIf cfg.enable { + user.packages = with pkgs; [ + lua + luaPackages.moonscript + (mkIf cfg.love2D.enable love2d) + ]; }; } diff --git a/modules/dev/node.nix b/modules/dev/node.nix index 281a78ff..bfedb55f 100644 --- a/modules/dev/node.nix +++ b/modules/dev/node.nix @@ -4,37 +4,37 @@ # disaster" languages. { config, options, lib, pkgs, ... }: + with lib; -{ +with lib.my; +let cfg = config.modules.dev.node; +in { options.modules.dev.node = { - enable = mkOption { - type = types.bool; - default = false; - }; + enable = mkBoolOpt false; }; - config = mkIf config.modules.dev.node.enable { - my = { - packages = with pkgs; [ - nodejs - yarn - ]; + config = mkIf cfg.enable { + user.packages = with pkgs; [ + nodejs + yarn + ]; - env.NPM_CONFIG_USERCONFIG = "$XDG_CONFIG_HOME/npm/config"; - env.NPM_CONFIG_CACHE = "$XDG_CACHE_HOME/npm"; - env.NPM_CONFIG_TMP = "$XDG_RUNTIME_DIR/npm"; - env.NPM_CONFIG_PREFIX = "$XDG_CACHE_HOME/npm"; - env.NODE_REPL_HISTORY = "$XDG_CACHE_HOME/node/repl_history"; - env.PATH = [ "$(yarn global bin)" ]; + env.NPM_CONFIG_USERCONFIG = "$XDG_CONFIG_HOME/npm/config"; + env.NPM_CONFIG_CACHE = "$XDG_CACHE_HOME/npm"; + env.NPM_CONFIG_TMP = "$XDG_RUNTIME_DIR/npm"; + env.NPM_CONFIG_PREFIX = "$XDG_CACHE_HOME/npm"; + env.NODE_REPL_HISTORY = "$XDG_CACHE_HOME/node/repl_history"; + env.PATH = [ "$(yarn global bin)" ]; - # Run locally installed bin-script, e.g. n coffee file.coffee - alias.n = "PATH=\"$(npm bin):$PATH\""; - alias.ya = "yarn"; - - home.xdg.configFile."npm/config".text = '' - cache=$XDG_CACHE_HOME/npm - prefix=$XDG_DATA_HOME/npm - ''; + # Run locally installed bin-script, e.g. n coffee file.coffee + environment.shellAliases = { + n = "PATH=\"$(npm bin):$PATH\""; + ya = "yarn"; }; + + home.configFile."npm/config".text = '' + cache=$XDG_CACHE_HOME/npm + prefix=$XDG_DATA_HOME/npm + ''; }; } diff --git a/modules/dev/python.nix b/modules/dev/python.nix index aee24ac2..86395baa 100644 --- a/modules/dev/python.nix +++ b/modules/dev/python.nix @@ -4,45 +4,43 @@ # me. The Py2->3 transition make trainwrecks jealous. But SciPy, NumPy, iPython # and Jupyter can have my babies. Every single one. -{ config, options, lib, pkgs, ... }: +{ config, options, lib, pkgs, my, ... }: + with lib; -{ +with lib.my; +let cfg = config.modules.dev.python; +in { options.modules.dev.python = { - enable = mkOption { - type = types.bool; - default = false; - }; + enable = mkBoolOpt false; }; - config = mkIf config.modules.dev.python.enable { - my = { - packages = with pkgs; [ - python37 - python37Packages.pip - python37Packages.ipython - python37Packages.black - python37Packages.setuptools - python37Packages.pylint - python37Packages.poetry - ]; + config = mkIf cfg.enable { + user.packages = with pkgs; [ + python37 + python37Packages.pip + python37Packages.ipython + python37Packages.black + python37Packages.setuptools + python37Packages.pylint + python37Packages.poetry + ]; - env.IPYTHONDIR = "$XDG_CONFIG_HOME/ipython"; - env.PIP_CONFIG_FILE = "$XDG_CONFIG_HOME/pip/pip.conf"; - env.PIP_LOG_FILE = "$XDG_DATA_HOME/pip/log"; - env.PYLINTHOME = "$XDG_DATA_HOME/pylint"; - env.PYLINTRC = "$XDG_CONFIG_HOME/pylint/pylintrc"; - env.PYTHONSTARTUP = "$XDG_CONFIG_HOME/python/pythonrc"; - env.PYTHON_EGG_CACHE = "$XDG_CACHE_HOME/python-eggs"; - env.JUPYTER_CONFIG_DIR = "$XDG_CONFIG_HOME/jupyter"; + env.IPYTHONDIR = "$XDG_CONFIG_HOME/ipython"; + env.PIP_CONFIG_FILE = "$XDG_CONFIG_HOME/pip/pip.conf"; + env.PIP_LOG_FILE = "$XDG_DATA_HOME/pip/log"; + env.PYLINTHOME = "$XDG_DATA_HOME/pylint"; + env.PYLINTRC = "$XDG_CONFIG_HOME/pylint/pylintrc"; + env.PYTHONSTARTUP = "$XDG_CONFIG_HOME/python/pythonrc"; + env.PYTHON_EGG_CACHE = "$XDG_CACHE_HOME/python-eggs"; + env.JUPYTER_CONFIG_DIR = "$XDG_CONFIG_HOME/jupyter"; - zsh.rc = lib.readFile ; - - alias.py = "python"; - alias.py2 = "python2"; - alias.py3 = "python3"; - alias.po = "poetry"; - alias.ipy = "ipython --no-banner"; - alias.ipylab = "ipython --pylab=qt5 --no-banner"; + environment.shellAliases = { + py = "python"; + py2 = "python2"; + py3 = "python3"; + po = "poetry"; + ipy = "ipython --no-banner"; + ipylab = "ipython --pylab=qt5 --no-banner"; }; }; } diff --git a/modules/dev/rust.nix b/modules/dev/rust.nix index d1e91203..3823d2cc 100644 --- a/modules/dev/rust.nix +++ b/modules/dev/rust.nix @@ -8,28 +8,28 @@ # all the world's problems to be wonderful? { config, options, lib, pkgs, ... }: + with lib; -{ +with lib.my; +let cfg = config.modules.dev.rust; +in { options.modules.dev.rust = { - enable = mkOption { - type = types.bool; - default = false; - }; + enable = mkBoolOpt false; }; - config = mkIf config.modules.dev.rust.enable { - my = { - packages = with pkgs; [ - rustup - ]; + config = mkIf cfg.enable { + user.packages = with pkgs; [ + rustup + ]; - env.RUSTUP_HOME = "$XDG_DATA_HOME/rustup"; - env.CARGO_HOME = "$XDG_DATA_HOME/cargo"; - env.PATH = [ "$CARGO_HOME/bin" ]; + env.RUSTUP_HOME = "$XDG_DATA_HOME/rustup"; + env.CARGO_HOME = "$XDG_DATA_HOME/cargo"; + env.PATH = [ "$CARGO_HOME/bin" ]; - alias.rs = "rustc"; - alias.rsp = "rustup"; - alias.ca = "cargo"; + environment.shellAliases = { + rs = "rustc"; + rsp = "rustup"; + ca = "cargo"; }; }; } diff --git a/modules/dev/scala.nix b/modules/dev/scala.nix index b893e487..90106062 100644 --- a/modules/dev/scala.nix +++ b/modules/dev/scala.nix @@ -1,16 +1,15 @@ +{ config, options, lib, pkgs, my, ... }: -{ config, options, lib, pkgs, ... }: with lib; -{ +with lib.my; +let cfg = config.modules.dev.scala; +in { options.modules.dev.scala = { - enable = mkOption { - type = types.bool; - default = false; - }; + enable = mkBoolOpt false; }; - config = mkIf config.modules.dev.scala.enable { - my.packages = with pkgs; [ + config = mkIf cfg.enable { + user.packages = with pkgs; [ scala jdk sbt diff --git a/modules/dev/zsh.nix b/modules/dev/shell.nix similarity index 51% rename from modules/dev/zsh.nix rename to modules/dev/shell.nix index 8137216a..4e4e539f 100644 --- a/modules/dev/zsh.nix +++ b/modules/dev/shell.nix @@ -1,24 +1,23 @@ -# modules/dev/zsh.nix --- http://zsh.sourceforge.net/ +# modules/dev/shell.nix --- http://zsh.sourceforge.net/ # # Shell script programmers are strange beasts. Writing programs in a language # that wasn't intended as a programming language. Alas, it is not for us mere # mortals to question the will of the ancient ones. If they want shell programs, # they get shell programs. -{ config, options, lib, pkgs, ... }: +{ config, options, lib, pkgs, my, ... }: + with lib; -{ - options.modules.dev.zsh = { - enable = mkOption { - type = types.bool; - default = false; - }; +with lib.my; +let cfg = config.modules.dev.shell; +in { + options.modules.dev.shell = { + enable = mkBoolOpt false; }; - config = mkIf config.modules.dev.zsh.enable { - my.packages = with pkgs; [ + config = mkIf cfg.enable { + user.packages = with pkgs; [ shellcheck - my.zunit ]; }; } diff --git a/modules/editors/default.nix b/modules/editors/default.nix index 7f99e0fd..590df572 100644 --- a/modules/editors/default.nix +++ b/modules/editors/default.nix @@ -1,19 +1,14 @@ { config, options, lib, pkgs, ... }: -with lib; -{ - imports = [ - ./emacs.nix - ./vim.nix - ]; +with lib; +with lib.my; +let cfg = config.modules.editors; +in { options.modules.editors = { - default = mkOption { - type = types.str; - default = "vi"; - }; + default = mkOpt types.str "vim"; }; - config = mkIf (config.modules.editors.default != null) { - my.env.EDITOR = config.modules.editors.default; + config = mkIf (cfg.default != null) { + env.EDITOR = cfg.default; }; } diff --git a/modules/editors/emacs.nix b/modules/editors/emacs.nix index 902d3069..25b3eb49 100644 --- a/modules/editors/emacs.nix +++ b/modules/editors/emacs.nix @@ -2,65 +2,76 @@ # https://github.com/hlissner/doom-emacs. This module sets it up to meet my # particular Doomy needs. -{ config, options, lib, pkgs, ... }: +{ config, options, lib, pkgs, inputs, ... }: + with lib; -{ +with lib.my; +let cfg = config.modules.editors.emacs; +in { options.modules.editors.emacs = { - enable = mkOption { - type = types.bool; - default = false; - }; - pkg = mkOption { - type = types.package; - default = pkgs.emacsUnstable; + enable = mkBoolOpt false; + doom = { + enable = mkBoolOpt true; + fromSSH = mkBoolOpt false; }; }; - config = mkIf config.modules.editors.emacs.enable { - my = { - packages = with pkgs; [ - ## Doom dependencies - config.modules.editors.emacs.pkg - git - (ripgrep.override {withPCRE2 = true;}) - gnutls # for TLS connectivity + config = mkIf cfg.enable { + nixpkgs.overlays = [ inputs.emacs-overlay.overlay ]; - ## Optional dependencies - fd # faster projectile indexing - imagemagick # for image-dired - (lib.mkIf (config.programs.gnupg.agent.enable) - pinentry_emacs) # in-emacs gnupg prompts - zstd # for undo-fu-session/undo-tree compression + user.packages = with pkgs; [ + ## Doom dependencies + emacsUnstable # 27.1 + git + (ripgrep.override {withPCRE2 = true;}) + gnutls # for TLS connectivity - ## Module dependencies - # :checkers spell - aspell - aspellDicts.en - aspellDicts.en-computers - aspellDicts.en-science - # :checkers grammar - languagetool - # :tools editorconfig - editorconfig-core-c # per-project style config - # :tools lookup & :lang org +roam - sqlite - # :lang cc - ccls - # :lang javascript - nodePackages.javascript-typescript-langserver - # :lang latex & :lang org (latex previews) - texlive.combined.scheme-medium - # :lang rust - rustfmt - rls - ]; + ## Optional dependencies + fd # faster projectile indexing + imagemagick # for image-dired + (mkIf (config.programs.gnupg.agent.enable) + pinentry_emacs) # in-emacs gnupg prompts + zstd # for undo-fu-session/undo-tree compression - env.PATH = [ "$XDG_CONFIG_HOME/emacs/bin" ]; - zsh.rc = lib.readFile ; - }; - - fonts.fonts = [ - pkgs.emacs-all-the-icons-fonts + ## Module dependencies + # :checkers spell + (aspellWithDicts (ds: with ds; [ + en en-computers en-science + ])) + # :checkers grammar + languagetool + # :tools editorconfig + editorconfig-core-c # per-project style config + # :tools lookup & :lang org +roam + sqlite + # :lang cc + ccls + # :lang javascript + nodePackages.javascript-typescript-langserver + # :lang latex & :lang org (latex previews) + texlive.combined.scheme-medium + # :lang rust + rustfmt + unstable.rust-analyzer ]; + + env.PATH = [ "$XDG_CONFIG_HOME/emacs/bin" ]; + + modules.shell.zsh.rcFiles = [ "${configDir}/emacs/aliases.zsh" ]; + + fonts.fonts = [ pkgs.emacs-all-the-icons-fonts ]; + + # init.doomEmacs = mkIf cfg.doom.enable '' + # if [ -d $HOME/.config/emacs ]; then + # ${optionalString cfg.doom.fromSSH '' + # git clone git@github.com:hlissner/doom-emacs.git $HOME/.config/emacs + # git clone git@github.com:hlissner/doom-emacs-private.git $HOME/.config/doom + # ''} + # ${optionalString (cfg.doom.fromSSH == false) '' + # git clone https://github.com/hlissner/doom-emacs $HOME/.config/emacs + # git clone https://github.com/hlissner/doom-emacs-private $HOME/.config/doom + # ''} + # fi + # ''; }; } diff --git a/modules/editors/vim.nix b/modules/editors/vim.nix index 536f26e5..8c99d8b4 100644 --- a/modules/editors/vim.nix +++ b/modules/editors/vim.nix @@ -2,25 +2,26 @@ # go-to. I am a vimmer at heart, after all. { config, options, lib, pkgs, ... }: + with lib; -{ +with lib.my; +let cfg = config.modules.editors.vim; +in { options.modules.editors.vim = { - enable = mkOption { - type = types.bool; - default = false; - }; + enable = mkBoolOpt false; }; - config = mkIf config.modules.editors.vim.enable { - my = { - packages = with pkgs; [ - editorconfig-core-c - neovim - ]; + config = mkIf cfg.enable { + user.packages = with pkgs; [ + editorconfig-core-c + neovim + ]; - env.VIMINIT = "let \\$MYVIMRC='\\$XDG_CONFIG_HOME/nvim/init.vim' | source \\$MYVIMRC"; - alias.vim = "nvim"; - alias.v = "nvim"; + # env.VIMINIT = "let \\$MYVIMRC='\\$XDG_CONFIG_HOME/nvim/init.vim' | source \\$MYVIMRC"; + + environment.shellAliases = { + vim = "nvim"; + v = "nvim"; }; }; } diff --git a/modules/hardware/audio.nix b/modules/hardware/audio.nix new file mode 100644 index 00000000..9508b3d4 --- /dev/null +++ b/modules/hardware/audio.nix @@ -0,0 +1,31 @@ +{ options, config, lib, pkgs, ... }: + +with lib; +with lib.my; +let cfg = config.modules.hardware.audio; +in { + options.modules.hardware.audio = { + enable = mkBoolOpt false; + }; + + config = mkIf cfg.enable { + sound.enable = true; + hardware.pulseaudio.enable = true; + + # HACK Prevents ~/.esd_auth files by disabling the esound protocol module + # for pulseaudio, which I likely don't need. Is there a better way? + hardware.pulseaudio.configFile = + let inherit (pkgs) runCommand pulseaudio; + paConfigFile = + runCommand "disablePulseaudioEsoundModule" + { buildInputs = [ pulseaudio ]; } '' + mkdir "$out" + cp ${pulseaudio}/etc/pulse/default.pa "$out/default.pa" + sed -i -e 's|load-module module-esound-protocol-unix|# ...|' "$out/default.pa" + ''; + in mkIf config.hardware.pulseaudio.enable + "${paConfigFile}/default.pa"; + + user.extraGroups = [ "audio" ]; + }; +} diff --git a/modules/hardware/bluetooth.nix b/modules/hardware/bluetooth.nix new file mode 100644 index 00000000..34d08741 --- /dev/null +++ b/modules/hardware/bluetooth.nix @@ -0,0 +1,32 @@ +{ options, config, lib, pkgs, ... }: + +with lib; +with lib.my; +let hwCfg = config.modules.hardware; + cfg = hwCfg.bluetooth; +in { + options.modules.hardware.bluetooth = { + enable = mkBoolOpt false; + audio.enable = mkBoolOpt false; + }; + + config = mkIf cfg.enable (mkMerge [ + { hardware.bluetooth.enable = true; } + + (mkIf cfg.audio.enable { + hardware.pulseaudio = { + # NixOS allows either a lightweight build (default) or full build of + # PulseAudio to be installed. Only the full build has Bluetooth + # support, so it must be selected here. + package = pkgs.pulseaudioFull; + # Enable additional codecs + extraModules = [ pkgs.pulseaudio-modules-bt ]; + }; + + hardware.bluetooth.extraConfig = '' + [General] + Enable=Source,Sink,Media,Socket + ''; + }) + ]); +} diff --git a/modules/hardware/ergodox.nix b/modules/hardware/ergodox.nix new file mode 100644 index 00000000..1da1a5e3 --- /dev/null +++ b/modules/hardware/ergodox.nix @@ -0,0 +1,19 @@ +{ options, config, lib, pkgs, ... }: + +with lib; +with lib.my; +let cfg = config.modules.hardware.ergodox; +in { + options.modules.hardware.ergodox = { + enable = mkBoolOpt false; + }; + + config = mkIf cfg.enable { + user.packages = [ pkgs.teensy-loader-cli ]; + # 'teensyload FILE' to load a new config into the ergodox + environment.shellAliases.teensyload = + "sudo teensy-loader-cli -w -v --mcu=atmega32u4"; + # Make right-alt the compose key, so ralt+a+a = å or ralt+o+/ = ø + services.xserver.xkbOptions = "compose:ralt"; + }; +} diff --git a/modules/hardware/fs.nix b/modules/hardware/fs.nix new file mode 100644 index 00000000..2a79cdfb --- /dev/null +++ b/modules/hardware/fs.nix @@ -0,0 +1,46 @@ +{ config, options, lib, pkgs, ... }: + +with lib; +with lib.my; +let cfg = config.modules.hardware.fs; +in { + options.modules.hardware.fs = { + enable = mkBoolOpt false; + zfs.enable = mkBoolOpt false; + ssd.enable = mkBoolOpt false; + # TODO automount.enable = mkBoolOpt false; + }; + + config = mkIf cfg.enable (mkMerge [ + { + programs.udevil.enable = true; + + # Support for more filesystems, mostly to support external drives + environment.systemPackages = with pkgs; [ + sshfs + exfat + ntfs3g + hfsprogs + ]; + } + + (mkIf (!cfg.zfs.enable && cfg.ssd.enable) { + services.fstrim.enable = true; + }) + + (mkIf cfg.zfs.enable (mkMerge [ + { + boot.loader.grub.copyKernels = true; + boot.supportedFilesystems = [ "zfs" ]; + boot.zfs.devNodes = "/dev/disk/by-partuuid"; + services.zfs.autoScrub.enable = true; + } + + (mkIf cfg.ssd.enable { + # Will only TRIM SSDs; skips over HDDs + services.fstrim.enable = false; + services.zfs.trim.enable = true; + }) + ])) + ]); +} diff --git a/modules/hardware/nvidia.nix b/modules/hardware/nvidia.nix new file mode 100644 index 00000000..4073118d --- /dev/null +++ b/modules/hardware/nvidia.nix @@ -0,0 +1,25 @@ +{ options, config, lib, pkgs, ... }: + +with lib; +with lib.my; +let cfg = config.modules.hardware.nvidia; +in { + options.modules.hardware.nvidia = { + enable = mkBoolOpt false; + }; + + config = mkIf cfg.enable { + hardware.opengl.enable = true; + + services.xserver.videoDrivers = [ "nvidia" ]; + + environment.systemPackages = with pkgs; [ + # Respect XDG conventions, damn it! + (writeScriptBin "nvidia-settings" '' + #!${stdenv.shell} + mkdir -p "$XDG_CONFIG_HOME/nvidia" + exec ${config.boot.kernelPackages.nvidia_x11.settings}/bin/nvidia-settings --config="$XDG_CONFIG_HOME/nvidia/settings" + '') + ]; + }; +} diff --git a/modules/hardware/razer.nix b/modules/hardware/razer.nix new file mode 100644 index 00000000..48e2a13f --- /dev/null +++ b/modules/hardware/razer.nix @@ -0,0 +1,22 @@ +# modules/hardware/razer.nix --- support for razer devices + +{ options, config, lib, pkgs, ... }: + +with lib; +with lib.my; +let cfg = config.modules.hardware.razer; +in { + options.modules.hardware.razer = { + enable = mkBoolOpt false; + }; + + config = mkIf cfg.enable { + hardware.openrazer.enable = true; + + user.extraGroups = [ "plugdev" ]; + + environment.systemPackages = with pkgs; [ + # TODO Install polychromatic + ]; + }; +} diff --git a/modules/hardware/sensors.nix b/modules/hardware/sensors.nix new file mode 100644 index 00000000..42739013 --- /dev/null +++ b/modules/hardware/sensors.nix @@ -0,0 +1,14 @@ +{ options, config, lib, pkgs, ... }: + +with lib; +with lib.my; +let cfg = config.modules.hardware.sensors; +in { + options.modules.hardware.sensors = { + enable = mkBoolOpt false; + }; + + config = mkIf cfg.enable { + user.packages = [ pkgs.lm_sensors ]; + }; +} diff --git a/modules/hardware/wacom.nix b/modules/hardware/wacom.nix new file mode 100644 index 00000000..b93bccf6 --- /dev/null +++ b/modules/hardware/wacom.nix @@ -0,0 +1,25 @@ +{ options, config, lib, pkgs, ... }: + +with lib; +with lib.my; +let cfg = config.modules.hardware.wacom; +in +{ + options.modules.hardware.wacom = { + enable = mkBoolOpt false; + }; + + config = mkIf cfg.enable { + # For my intuos4 pro. Doesn't work for cintiqs. + services.xserver.wacom.enable = true; + # TODO Move this to udev + system.userActivationScripts.wacom = '' + # lock tablet to main display + if xinput list --id-only "Wacom Intuos Pro S Pen stylus" 2>&1 >/dev/null; then + xinput map-to-output $(xinput list --id-only "Wacom Intuos Pro S Pen stylus") DVI-I-1 + xinput map-to-output $(xinput list --id-only "Wacom Intuos Pro S Pen eraser") DVI-I-1 + xinput map-to-output $(xinput list --id-only "Wacom Intuos Pro S Pen cursor") DVI-I-1 + fi + ''; + }; +} diff --git a/modules/media/default.nix b/modules/media/default.nix deleted file mode 100644 index d73b739c..00000000 --- a/modules/media/default.nix +++ /dev/null @@ -1,9 +0,0 @@ -{ config, lib, pkgs, ... }: - -{ - imports = [ - ./mpv.nix - # ./ncmpcpp.nix - ./spotify.nix - ]; -} diff --git a/modules/options.nix b/modules/options.nix new file mode 100644 index 00000000..b2ac6a2f --- /dev/null +++ b/modules/options.nix @@ -0,0 +1,79 @@ +{ config, options, lib, home-manager, ... }: + +with lib; +with lib.my; +{ + options = { + user = mkOpt types.attrs {}; + + home = with types; { + file = mkOpt' attrs {} "Files to place directly in $HOME"; + configFile = mkOpt' attrs {} "Files to place in $XDG_CONFIG_HOME"; + dataFile = mkOpt' attrs {} "Files to place in $XDG_DATA_HOME"; + }; + + env = mkOption { + type = with types; attrsOf (oneOf [ str path (listOf (either str path)) ]); + apply = mapAttrs + (n: v: if isList v + then concatMapStringsSep ":" (x: toString x) v + else (toString v)); + default = {}; + description = "TODO"; + }; + }; + + config = { + user = { + description = "The primary user account"; + extraGroups = [ "wheel" ]; + isNormalUser = true; + name = let name = builtins.getEnv "USER"; in + if elem name [ "" "root" ] + then "hlissner" else name; + uid = 1000; + }; + + # Install user packages to /etc/profiles instead. Necessary for + # nixos-rebuild build-vm to work. + home-manager = { + useUserPackages = true; + + # I only need a subset of home-manager's capabilities. That is, access to + # its home.file, home.xdg.configFile and home.xdg.dataFile so I can deploy + # files easily to my $HOME, but 'home-manager.users.hlissner.home.file.*' + # is much too long and harder to maintain, so I've made aliases in: + # + # home.file -> home-manager.users.hlissner.home.file + # home.configFile -> home-manager.users.hlissner.home.xdg.configFile + # home.dataFile -> home-manager.users.hlissner.home.xdg.dataFile + users.${config.user.name} = { + home = { + file = mkAliasDefinitions options.home.file; + # Necessary for home-manager to work with flakes, otherwise it will + # look for a nixpkgs channel. + stateVersion = config.system.stateVersion; + }; + xdg = { + configFile = mkAliasDefinitions options.home.configFile; + dataFile = mkAliasDefinitions options.home.dataFile; + }; + }; + }; + + users.users.${config.user.name} = mkAliasDefinitions options.user; + + nix = let users = [ "root" config.user.name ]; in { + trustedUsers = users; + allowedUsers = users; + }; + + # must already begin with pre-existing PATH. Also, can't use binDir here, + # because it contains a nix store path. + env.PATH = [ "$XDG_CONFIG_HOME/dotfiles/bin" "$PATH" ]; + + environment.extraInit = + concatStringsSep "\n" + (mapAttrsToList (n: v: "export ${n}=\"${v}\"") config.env); + }; +} diff --git a/modules/services/calibre.nix b/modules/services/calibre.nix index 9db47028..22c28347 100644 --- a/modules/services/calibre.nix +++ b/modules/services/calibre.nix @@ -1,15 +1,16 @@ -{ config, options, pkgs, lib, ... }: +{ options, config, lib, pkgs, ... }: + with lib; -{ +with lib.my; +let cfg = config.modules.services.calibre; +in { options.modules.services.calibre = { - enable = mkOption { - type = types.bool; - default = false; - }; + enable = mkBoolOpt false; }; - config = mkIf config.modules.services.calibre.enable { + config = mkIf cfg.enable { services.calibre-server.enable = true; + networking.firewall.allowedTCPPorts = [ 8080 ]; }; } diff --git a/modules/services/default.nix b/modules/services/default.nix deleted file mode 100644 index e16514d1..00000000 --- a/modules/services/default.nix +++ /dev/null @@ -1,17 +0,0 @@ -{ config, lib, pkgs, ... }: - -{ - imports = [ - # ./calibre-server.nix - ./docker.nix - # ./gitea.nix - # ./jellyfin.nix - # ./keybase.nix - # ./mpd.nix - # ./nginx.nix - # ./plex.nix - # ./ssh.nix - ./syncthing.nix - # ./transmission.nix - ]; -} diff --git a/modules/services/docker.nix b/modules/services/docker.nix index a38caac4..5e854576 100644 --- a/modules/services/docker.nix +++ b/modules/services/docker.nix @@ -1,23 +1,25 @@ -{ config, options, pkgs, lib, ... }: +{ options, config, lib, pkgs, ... }: + with lib; -{ +with lib.my; +let cfg = config.modules.services.docker; +in { options.modules.services.docker = { - enable = mkOption { - type = types.bool; - default = false; - }; + enable = mkBoolOpt false; }; - config = mkIf config.modules.services.docker.enable { - my = { - packages = with pkgs; [ docker docker-compose ]; + config = mkIf cfg.enable { + user.packages = with pkgs; [ + docker + docker-compose + ]; - env.DOCKER_CONFIG = "$XDG_CONFIG_HOME/docker"; - env.MACHINE_STORAGE_PATH = "$XDG_DATA_HOME/docker/machine"; + env.DOCKER_CONFIG = "$XDG_CONFIG_HOME/docker"; + env.MACHINE_STORAGE_PATH = "$XDG_DATA_HOME/docker/machine"; - user.extraGroups = [ "docker" ]; - zsh.rc = lib.readFile ; - }; + user.extraGroups = [ "docker" ]; + + modules.shell.zsh.rcFiles = [ "${configDir}/docker/aliases.zsh" ]; virtualisation = { docker = { diff --git a/modules/services/gitea.nix b/modules/services/gitea.nix index d952f22c..1c60df08 100644 --- a/modules/services/gitea.nix +++ b/modules/services/gitea.nix @@ -1,14 +1,14 @@ -{ config, options, pkgs, lib, ... }: +{ options, config, lib, pkgs, ... }: + with lib; -{ +with lib.my; +let cfg = config.modules.services.gitea; +in { options.modules.services.gitea = { - enable = mkOption { - type = types.bool; - default = false; - }; + enable = mkBoolOpt false; }; - config = mkIf config.modules.services.gitea.enable { + config = mkIf cfg.enable { # I prefer git@... ssh addresses over gitea@... users.users.git = { useDefaultShell = true; diff --git a/modules/services/jellyfin.nix b/modules/services/jellyfin.nix index e1f3460c..ecb6914f 100644 --- a/modules/services/jellyfin.nix +++ b/modules/services/jellyfin.nix @@ -1,16 +1,16 @@ # Finally, a decent open alternative to Plex! -{ config, options, pkgs, lib, ... }: +{ options, config, lib, pkgs, ... }: + with lib; -{ +with lib.my; +let cfg = config.modules.services.jellyfin; +in { options.modules.services.jellyfin = { - enable = mkOption { - type = types.bool; - default = false; - }; + enable = mkBoolOpt false; }; - config = mkIf config.modules.services.jellyfin.enable { + config = mkIf cfg.enable { services.jellyfin.enable = true; networking.firewall = { @@ -18,6 +18,6 @@ with lib; allowedUDPPorts = [ 8096 ]; }; - my.user.extraGroups = [ "jellyfin" ]; + user.extraGroups = [ "jellyfin" ]; }; } diff --git a/modules/services/keybase.nix b/modules/services/keybase.nix deleted file mode 100644 index 0d3c2c57..00000000 --- a/modules/services/keybase.nix +++ /dev/null @@ -1,14 +0,0 @@ -{ config, lib, pkgs, ... }: - -{ - services.kbfs = { - enable = true; - mountPoint = "%t/kbfs"; - extraFlags = [ "-label %u" ]; - }; - - systemd.user.services.kbfs = { - environment = { KEYBASE_RUN_MODE = "prod"; }; - serviceConfig.Slice = "keybase.slice"; - }; -} diff --git a/modules/services/mpd.nix b/modules/services/mpd.nix deleted file mode 100644 index b91115c0..00000000 --- a/modules/services/mpd.nix +++ /dev/null @@ -1,30 +0,0 @@ -{ config, lib, pkgs, ... }: - -{ - environment.systemPackages = with pkgs; [ - mpc_cli - ]; - - my.env.MPD_HOME = "$XDG_CONFIG_HOME/mpd"; - - services.mpd = { - enable = true; - musicDirectory = "/home/hlissner/music"; - startWhenNeeded = true; - extraConfig = '' - input { - plugin "curl" - } - audio_output { - type "pulse" - name "pulse audio" - } - audio_output { - type "fifo" - name "mpd_fifo" - path "/tmp/mpd.fifo" - format "44100:16:2" - } - ''; - }; -} diff --git a/modules/services/nginx.nix b/modules/services/nginx.nix index 2615232d..c3850819 100644 --- a/modules/services/nginx.nix +++ b/modules/services/nginx.nix @@ -1,14 +1,14 @@ -{ config, options, pkgs, lib, ... }: +{ config, options, lib, pkgs, ... }: + with lib; -{ +with lib.my; +let cfg = config.modules.services.nginx; +in { options.modules.services.nginx = { - enable = mkOption { - type = types.bool; - default = false; - }; + enable = mkBoolOpt false; }; - config = mkIf config.modules.services.nginx.enable { + config = mkIf cfg.enable { networking.firewall.allowedTCPPorts = [ 80 443 ]; services.nginx = { diff --git a/modules/services/plex.nix b/modules/services/plex.nix deleted file mode 100644 index 8e7cdce3..00000000 --- a/modules/services/plex.nix +++ /dev/null @@ -1,14 +0,0 @@ -{ config, pkgs, ... }: - -{ - services.plex = { - enable = true; - openFirewall = true; - }; - - services.transmission = { - enable = true; - settings.rpc-whitelist = "127.0.0.1,192.168.*.*"; - }; - networking.firewall.allowedTCPPorts = [ 9091 51413 ]; -} diff --git a/modules/services/ssh.nix b/modules/services/ssh.nix index 87bfa790..ea00a5b7 100644 --- a/modules/services/ssh.nix +++ b/modules/services/ssh.nix @@ -1,30 +1,21 @@ -{ config, pkgs, ... }: +{ options, config, lib, ... }: -{ config, options, pkgs, lib, ... }: with lib; -{ +with lib.my; +let cfg = config.modules.services.ssh; +in { options.modules.services.ssh = { - enable = mkOption { - type = types.bool; - default = false; - }; + enable = mkBoolOpt false; }; - config = mkIf config.modules.services.ssh.enable { + config = mkIf cfg.enable { services.openssh = { enable = true; - forwardX11 = true; - permitRootLogin = "no"; + challengeResponseAuthentication = false; passwordAuthentication = false; - - # Allow local LAN to connect with passwords - extraConfig = '' - Match address 192.168.0.0/24 - PasswordAuthentication yes - ''; }; - users.users.hlissner.openssh.authorizedKeys.keys = [ + user.openssh.authorizedKeys.keys = [ "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC8Tl2pj6CPBV3V72cohPhn+k0a/Na3cOrbmUtFC7rR7icWocSs1S1cSrP3sPLwUqRh3+zfIuLXTrTv3gj8Xvg8WELOspzsiYeAtbcHrnWnx/a7xzYvFyT9/8hkiGM/F6w7IuKEk+AZW34vARSgRPJ1FdH8NbPKJ8ay9zW9XB9YJGnbzIRmsVVpQ8l6Fh8ZqRjZfC1ea7hns8+HgjPrIHFb+S3qZZiwU4Gc8aWJy9ziwwkllEsSchv3aigYA3eOeW0FUQFiKsLGxbX2b2b3d6jFO4Pu+dMSen0h5IzBo0nh7UADSfJPdwbZaMuJzviKe2y6zg6jaM9XRIhLBT6bftDr henrik@lissner.net" ]; }; diff --git a/modules/services/syncthing.nix b/modules/services/syncthing.nix deleted file mode 100644 index 5c24f709..00000000 --- a/modules/services/syncthing.nix +++ /dev/null @@ -1,69 +0,0 @@ -{ config, options, pkgs, lib, ... }: -with lib; -{ - options.modules.services.syncthing = { - enable = mkOption { - type = types.bool; - default = false; - }; - }; - - config = mkIf config.modules.services.syncthing.enable { - services.syncthing = { - enable = true; - openDefaultPorts = true; - user = config.my.username; - configDir = "/home/${config.my.username}/.config/syncthing"; - dataDir = "/home/${config.my.username}/.local/share/syncthing"; - declarative = { - devices = { - kuro.id = "4UJSUBN-V7LCISG-6ZE7SBN-YPXM5FQ-CE7CD2U-W4KZC7O-4HUZZSW-6DXAGQQ"; - shiro.id = "G4DUO25-AMQQIWS-SRZE5TJ-43CCQZJ-5ULEZBS-P2LMZZU-V5JA5CS-6X7RLQK"; - aka.id = "IZQ2GAC-I3QBTRT-TXBIG7Z-NT6S66Y-H64WOCO-T3AMKYZ-VGWTNCY-CTQOLQN"; - ao.id = "NBMLUKD-PJRXCTM-GQ2WFLE-NN4IGSN-6WSC6JL-M6XN7PE-HCBTOKV-7VER2QE"; - # Windows machine; set up the other end yourself! - midori.id = "BOFH5JP-A3MPTJA-EGIZVWV-URHUTSJ-2ZXCAA2-XMZPPSR-GLMOQFL-ZX7DGQP"; - }; - folders = - let deviceEnabled = devices: lib.elem config.networking.hostName devices; - deviceType = devices: - if deviceEnabled devices - then "sendreceive" - else "receiveonly"; - in { - archive = rec { - devices = [ "kuro" "ao" "midori" ]; - path = "/home/${config.my.username}/archive"; - watch = false; - rescanInterval = 3600 * 6; - type = deviceType ["kuro"]; - enable = deviceEnabled devices; - }; - share = rec { - devices = [ "kuro" "shiro" "ao" "aka" "midori" ]; - path = "/home/${config.my.username}/share"; - watch = true; - rescanInterval = 3600 * 6; - enable = deviceEnabled devices; - }; - projects = rec { - devices = [ "kuro" "shiro" "ao" "midori" ]; - path = "/home/${config.my.username}/projects"; - watch = false; - rescanInterval = 3600 * 2; - type = deviceType ["kuro" "shiro"]; - enable = deviceEnabled devices; - }; - secrets = rec { - devices = [ "kuro" "shiro" "ao" "aka" ]; - path = "/home/${config.my.username}/.secrets"; - watch = true; - rescanInterval = 3600; - type = deviceType ["kuro" "shiro"]; - enable = deviceEnabled devices; - }; - }; - }; - }; - }; -} diff --git a/modules/services/transmission.nix b/modules/services/transmission.nix index d1e51555..83724971 100644 --- a/modules/services/transmission.nix +++ b/modules/services/transmission.nix @@ -1,23 +1,32 @@ -{ config, lib, pkgs, ... }: +{ config, options, pkgs, lib, my, ... }: -{ - services.transmission = { - enable = true; - home = "/data/media/torrents"; - settings = { - incomplete-dir-enabled = true; - rpc-whitelist = "127.0.0.1,192.168.*.*"; - rpc-host-whitelist = "*"; - rpc-host-whitelist-enabled = true; - ratio-limit = 0; - ratio-limit-enabled = true; +with lib; +with lib.my; +let cfg = config.modules.services.transmission; +in { + options.modules.services.transmission = { + enable = mkBoolOpt false; + }; + + config = mkIf cfg.enable { + services.transmission = { + enable = true; + home = "${homeDir}/torrents"; + settings = { + incomplete-dir-enabled = true; + rpc-whitelist = "127.0.0.1,192.168.*.*"; + rpc-host-whitelist = "*"; + rpc-host-whitelist-enabled = true; + ratio-limit = 0; + ratio-limit-enabled = true; + }; }; - }; - networking.firewall = { - allowedTCPPorts = [ 51413 ]; - allowedUDPPorts = [ 51413 ]; - }; + networking.firewall = { + allowedTCPPorts = [ 51413 ]; + allowedUDPPorts = [ 51413 ]; + }; - my.user.extraGroups = [ "transmission" ]; + user.extraGroups = [ "transmission" ]; + }; } diff --git a/modules/shell/default.nix b/modules/shell/default.nix deleted file mode 100644 index 59778272..00000000 --- a/modules/shell/default.nix +++ /dev/null @@ -1,15 +0,0 @@ -{ config, lib, pkgs, ... }: - -{ - imports = [ - ./direnv.nix - ./git.nix - ./gnupg.nix - ./ncmpcpp.nix - ./pass.nix - ./ranger.nix - ./tmux.nix - ./weechat.nix - ./zsh.nix - ]; -} diff --git a/modules/shell/direnv.nix b/modules/shell/direnv.nix index 254ac28c..60609c64 100644 --- a/modules/shell/direnv.nix +++ b/modules/shell/direnv.nix @@ -1,17 +1,15 @@ { config, options, lib, pkgs, ... }: with lib; -{ +with lib.my; +let cfg = config.modules.shell.direnv; +in { options.modules.shell.direnv = { - enable = mkOption { type = types.bool; default = false; }; + enable = mkBoolOpt false; }; - config = mkIf config.modules.shell.direnv.enable { - my = { - packages = [ pkgs.direnv ]; - zsh.rc = ''eval "$(direnv hook zsh)"''; - }; - - services.lorri.enable = true; + config = mkIf cfg.enable { + user.packages = [ pkgs.direnv ]; + modules.shell.zsh.rcInit = ''eval "$(direnv hook zsh)"''; }; } diff --git a/modules/shell/git.nix b/modules/shell/git.nix index 68c9ae85..419d5edb 100644 --- a/modules/shell/git.nix +++ b/modules/shell/git.nix @@ -1,26 +1,26 @@ -{ config, lib, pkgs, ... }: +{ config, options, lib, pkgs, ... }: with lib; -{ +with lib.my; +let cfg = config.modules.shell.git; +in { options.modules.shell.git = { - enable = mkOption { - type = types.bool; - default = false; - }; + enable = mkBoolOpt false; }; - config = mkIf config.modules.shell.git.enable { - my = { - packages = with pkgs; [ - gitAndTools.hub - gitAndTools.diff-so-fancy - ]; - zsh.rc = lib.readFile ; - # Do recursively, in case git stores files in this folder - home.xdg.configFile = { - "git/config".source = ; - "git/ignore".source = ; - }; + config = mkIf cfg.enable { + user.packages = with pkgs; [ + gitAndTools.gh + gitAndTools.diff-so-fancy + (mkIf config.modules.shell.gnupg.enable + gitAndTools.git-crypt) + ]; + + home.configFile = { + "git/config".source = "${configDir}/git/config"; + "git/ignore".source = "${configDir}/git/ignore"; }; + + modules.shell.zsh.rcFiles = [ "${configDir}/git/aliases.zsh" ]; }; } diff --git a/modules/shell/gnupg.nix b/modules/shell/gnupg.nix index c5c4912e..1eaf05ab 100644 --- a/modules/shell/gnupg.nix +++ b/modules/shell/gnupg.nix @@ -1,30 +1,29 @@ { config, options, lib, pkgs, ... }: with lib; -let cfg = config.modules; - gnupgCfg = cfg.shell.gnupg; - homedir = "$XDG_CONFIG_HOME/gnupg"; +with lib.my; +let cfg = config.modules.shell.gnupg; in { - options.modules.shell.gnupg = { - enable = mkOption { type = types.bool; default = false; }; - cacheTTL = mkOption { type = types.int; default = 1800; }; + options.modules.shell.gnupg = with types; { + enable = mkBoolOpt false; + cacheTTL = mkOpt int 3600; # 1hr }; - config = mkIf gnupgCfg.enable { - my = { - env.GNUPGHOME = homedir; - - # HACK Without this config file you get "No pinentry program" on 20.03. - # program.gnupg.agent.pinentryFlavor doesn't appear to work, and this - # is cleaner than overriding the systemd unit. - home.xdg.configFile."gnupg/gpg-agent.conf" = { - text = '' - default-cache-ttl ${toString gnupgCfg.cacheTTL} - pinentry-program ${pkgs.pinentry.gtk2}/bin/pinentry - ''; - }; - }; + config = mkIf cfg.enable { + environment.variables.GNUPGHOME = "$XDG_CONFIG_HOME/gnupg"; programs.gnupg.agent.enable = true; + + user.packages = [ pkgs.tomb ]; + + # HACK Without this config file you get "No pinentry program" on 20.03. + # programs.gnupg.agent.pinentryFlavor doesn't appear to work, and this + # is cleaner than overriding the systemd unit. + home.configFile."gnupg/gpg-agent.conf" = { + text = '' + default-cache-ttl ${toString cfg.cacheTTL} + pinentry-program ${pkgs.pinentry.gtk2}/bin/pinentry + ''; + }; }; } diff --git a/modules/shell/ncmpcpp.nix b/modules/shell/ncmpcpp.nix deleted file mode 100644 index bf514bba..00000000 --- a/modules/shell/ncmpcpp.nix +++ /dev/null @@ -1,29 +0,0 @@ -{ config, options, lib, pkgs, ... }: -with lib; -{ - options.modules.shell.ncmpcpp = { - enable = mkOption { - type = types.bool; - default = false; - }; - }; - - config = mkIf config.modules.shell.ncmpcpp.enable { - my.packages = with pkgs; [ - (ncmpcpp.override { visualizerSupport = true; }) - ]; - - my.alias.rate = "mpd-rate"; - my.alias.mpcs = "mpc search any"; - my.alias.mpcsp = "mpc searchplay any"; - - my.env.NCMPCPP_HOME = "$XDG_CONFIG_HOME/ncmpcpp"; - - # Symlink these one at a time because ncmpcpp writes other files to - # ~/.config/ncmpcpp, so it needs to be writeable. - my.home.xdg.configFile = { - "ncmpcpp/config".source = ; - "ncmpcpp/bindings".source = ; - }; - }; -} diff --git a/modules/shell/pass.nix b/modules/shell/pass.nix index 80b4128a..f5382f08 100644 --- a/modules/shell/pass.nix +++ b/modules/shell/pass.nix @@ -1,22 +1,22 @@ { config, options, pkgs, lib, ... }: + with lib; -{ +with lib.my; +let cfg = config.modules.shell.pass; +in { options.modules.shell.pass = { - enable = mkOption { - type = types.bool; - default = false; - }; + enable = mkBoolOpt false; }; - config = mkIf config.modules.shell.pass.enable { - my = { - packages = with pkgs; [ - (pass.withExtensions (exts: [ - exts.pass-otp - exts.pass-genphrase - ])) - ]; - env.PASSWORD_STORE_DIR = "$HOME/.secrets/password-store"; - }; + config = mkIf cfg.enable { + user.packages = with pkgs; [ + (pass.withExtensions (exts: [ + exts.pass-otp + exts.pass-genphrase + ] ++ (if config.modules.shell.gnupg.enable + then [ exts.pass-tomb ] + else []))) + ]; + env.PASSWORD_STORE_DIR = "$HOME/.secrets/password-store"; }; } diff --git a/modules/shell/ranger.nix b/modules/shell/ranger.nix deleted file mode 100644 index 25f27133..00000000 --- a/modules/shell/ranger.nix +++ /dev/null @@ -1,18 +0,0 @@ -{ config, options, pkgs, lib, ... }: -with lib; -{ - options.modules.shell.ranger = { - enable = mkOption { - type = types.bool; - default = false; - }; - }; - - config = mkIf config.modules.shell.ranger.enable { - my.packages = with pkgs; [ - ranger - # For image previews - (lib.mkIf config.services.xserver.enable w3m) - ]; - }; -} diff --git a/modules/shell/tmux.nix b/modules/shell/tmux.nix index 42afc838..39f982c7 100644 --- a/modules/shell/tmux.nix +++ b/modules/shell/tmux.nix @@ -1,41 +1,43 @@ { config, options, pkgs, lib, ... }: + with lib; -{ +with lib.my; +let cfg = config.modules.shell.tmux; +in { options.modules.shell.tmux = { - enable = mkOption { - type = types.bool; - default = false; - }; + enable = mkBoolOpt false; }; - config = mkIf config.modules.shell.tmux.enable { - my = { - packages = with pkgs; [ - # The developer of tmux chooses not to add XDG support for religious - # reasons (see tmux/tmux#142). Fortunately, nix makes this easy: - (writeScriptBin "tmux" '' - #!${stdenv.shell} - exec ${tmux}/bin/tmux -f "$TMUX_HOME/config" "$@" - '') - ]; + config = mkIf cfg.enable { + user.packages = with pkgs; [ + # Despite tmux/tmux#142, tmux will support XDG in 3.2. Sadly, only 3.0 is + # available on nixpkgs, and 3.1b on master (tmux/tmux@15d7e56), so I + # implement it myself: + (writeScriptBin "tmux" '' + #!${stdenv.shell} + exec ${tmux}/bin/tmux -f "$TMUX_HOME/config" "$@" + '') + ]; - env.TMUX_HOME = "$XDG_CONFIG_HOME/tmux"; - env.TMUXIFIER = "$XDG_DATA_HOME/tmuxifier"; - env.TMUXIFIER_LAYOUT_PATH = "$XDG_DATA_HOME/tmuxifier"; - env.PATH = [ "$TMUXIFIER/bin" ]; + modules.shell.zsh = { + rcInit = "_cache tmuxifier init -"; + rcFiles = [ "${configDir}/tmux/aliases.zsh" ]; + }; - zsh.rc = '' - _cache tmuxifier init - - ${lib.readFile } + home.configFile = { + "tmux" = { source = "${configDir}/tmux"; recursive = true; }; + "tmux/plugins".text = '' + run-shell ${pkgs.tmuxPlugins.copycat}/share/tmux-plugins/copycat/copycat.tmux + run-shell ${pkgs.tmuxPlugins.prefix-highlight}/share/tmux-plugins/prefix-highlight/prefix_highlight.tmux + run-shell ${pkgs.tmuxPlugins.yank}/share/tmux-plugins/yank/yank.tmux ''; - home.xdg.configFile = { - "tmux" = { source = ; recursive = true; }; - "tmux/plugins".text = '' - run-shell ${pkgs.tmuxPlugins.copycat}/share/tmux-plugins/copycat/copycat.tmux - run-shell ${pkgs.tmuxPlugins.prefix-highlight}/share/tmux-plugins/prefix-highlight/prefix_highlight.tmux - run-shell ${pkgs.tmuxPlugins.yank}/share/tmux-plugins/yank/yank.tmux - ''; - }; + }; + + env = { + PATH = [ "$TMUXIFIER/bin" ]; + TMUX_HOME = "$XDG_CONFIG_HOME/tmux"; + TMUXIFIER = "$XDG_DATA_HOME/tmuxifier"; + TMUXIFIER_LAYOUT_PATH = "$XDG_DATA_HOME/tmuxifier"; }; }; } diff --git a/modules/shell/weechat.nix b/modules/shell/weechat.nix deleted file mode 100644 index 016b6226..00000000 --- a/modules/shell/weechat.nix +++ /dev/null @@ -1,17 +0,0 @@ -{ config, options, lib, pkgs, ... }: - -with lib; -{ - options.modules.shell.weechat = { - enable = mkOption { - type = types.bool; - default = false; - }; - }; - - config = mkIf config.modules.shell.weechat.enable { - my.packages = with pkgs; [ - weechat - ]; - }; -} diff --git a/modules/shell/zsh.nix b/modules/shell/zsh.nix index 2961d8ca..f5a61ae8 100644 --- a/modules/shell/zsh.nix +++ b/modules/shell/zsh.nix @@ -1,56 +1,82 @@ -# modules/shell/zsh.nix --- ... - { config, options, pkgs, lib, ... }: + with lib; -{ - options.modules.shell.zsh = { - enable = mkOption { - type = types.bool; - default = false; - }; +with lib.my; +let cfg = config.modules.shell.zsh; +in { + options.modules.shell.zsh = with types; { + enable = mkBoolOpt false; + + aliases = mkOpt (attrsOf (either str path)) {}; + + rcInit = mkOpt' lines "" '' + Zsh lines to be written to $XDG_CONFIG_HOME/zsh/extra.zshrc and sourced by + $XDG_CONFIG_HOME/zsh/.zshrc + ''; + envInit = mkOpt' lines "" '' + Zsh lines to be written to $XDG_CONFIG_HOME/zsh/extra.zshenv and sourced + by $XDG_CONFIG_HOME/zsh/.zshenv + ''; + + rcFiles = mkOpt (listOf (either str path)) []; + envFiles = mkOpt (listOf (either str path)) []; }; - config = mkIf config.modules.shell.zsh.enable { - my = { - packages = with pkgs; [ - zsh - nix-zsh-completions - bat - exa - fasd - fd - fzf - htop - tldr - tree - ]; - env.ZDOTDIR = "$XDG_CONFIG_HOME/zsh"; - env.ZSH_CACHE = "$XDG_CACHE_HOME/zsh"; - - alias.exa = "exa --group-directories-first"; - alias.l = "exa -1"; - alias.ll = "exa -lg"; - alias.la = "LC_COLLATE=C exa -la"; - alias.sc = "systemctl"; - alias.ssc = "sudo systemctl"; - - # Write it recursively so other modules can write files to it - home.xdg.configFile."zsh" = { - source = ; - recursive = true; - }; - }; + config = mkIf cfg.enable { + users.defaultUserShell = pkgs.zsh; programs.zsh = { enable = true; enableCompletion = true; - # I init completion myself, because enableGlobalCompInit initializes it too - # soon, which means commands initialized later in my config won't get + # I init completion myself, because enableGlobalCompInit initializes it + # too soon, which means commands initialized later in my config won't get # completion, and running compinit twice is slow. enableGlobalCompInit = false; promptInit = ""; }; + user.packages = with pkgs; [ + zsh + nix-zsh-completions + bat + exa + fasd + fd + fzf + tldr + ]; + + env = { + ZDOTDIR = "$XDG_CONFIG_HOME/zsh"; + ZSH_CACHE = "$XDG_CACHE_HOME/zsh"; + ZGEN_DIR = "$XDG_DATA_HOME/zsh"; + ZGEN_SOURCE = "$ZGEN_DIR/zgen.zsh"; + }; + + home.configFile = { + # Write it recursively so other modules can write files to it + "zsh" = { source = "${configDir}/zsh"; recursive = true; }; + + # Why am I creating extra.zsh{rc,env} when I could be using extraInit? + # Because extraInit generates those files in /etc/profile, and mine just + # write the files to ~/.config/zsh; where it's easier to edit and tweak + # them in case of issues or when experimenting. + "zsh/extra.zshrc".text = + let aliasLines = mapAttrsToList (n: v: "alias ${n}=\"${v}\"") cfg.aliases; + in '' + # This file was autogenerated, do not edit it! + ${concatStringsSep "\n" aliasLines} + ${concatMapStrings (path: "source '${path}'\n") cfg.rcFiles} + ${cfg.rcInit} + ''; + + "zsh/extra.zshenv".text = '' + # This file is autogenerated, do not edit it! + ${concatMapStrings (path: "source '${path}'\n") cfg.envFiles} + ${cfg.envInit} + ''; + }; + system.userActivationScripts.cleanupZgen = "rm -fv $XDG_CACHE_HOME/zsh/*"; }; } diff --git a/modules/themes/aquanaut/Xresources b/modules/themes/aquanaut/Xresources deleted file mode 100644 index 985fee6c..00000000 --- a/modules/themes/aquanaut/Xresources +++ /dev/null @@ -1,81 +0,0 @@ -!! Colors -#define blk #101216 -#define bblk #969896 -#define red #cc6666 -#define bred #de935f -#define grn #8BD49C -#define bgrn #757d28 -#define ylw #f0c674 -#define bylw #f9a03f -#define blu #5EC4FF -#define bblu #2a8fed -#define mag #E27E8D -#define bmag #bc77a8 -#define cyn #8abeb7 -#define bcyn #a3685a -#define wht #bbc2cf -#define bwht #ffffff -#define bg blk -#define fg wht - -*.foreground: fg -*.background: bg -*.cursorColor: mag - -*.color0: blk -*.color8: bblk -*.color1: red -*.color9: bred -*.color2: grn -*.color10: bgrn -*.color3: ylw -*.color11: bylw -*.color4: blu -*.color12: bblu -*.color5: mag -*.color13: bmag -*.color6: cyn -*.color14: bcyn -*.color7: wht -*.color15: bwht - -! greys -*.color234: #1d2021 -*.color235: #282828 -*.color236: #32302f -*.color237: #3c3836 -*.color239: #504945 -*.color240: #544c49 -*.color241: #665c54 - - -!! general -scratch.font: Fira Code:pixelsize=16 - - -!! xst -st.opacity: 200 -st.font: Fira Code:pixelsize=12 - - -!! urxvt -URxvt*depth: 32 -URxvt*.background: [80]#101216 -! URxvt*.termName: xterm-256color -URxvt*.borderless: 1 -URxvt*.buffered: true -URxvt*.cursorBlink: true -URxvt*.font: xft:Fira Code:pixelsize=12 -URxvt*.internalBorder: 10 -URxvt*.letterSpace: 0 -URxvt*.lineSpace: 0 -URxvt*.loginShell: false -URxvt*.matcher.button: 1 -URxvt*.matcher.rend.0: Uline Bold fg5 -URxvt*.saveLines: 5000 -URxvt*.scrollBar: false -URxvt*.underlineColor: grey -URxvt.clipboard.autocopy: true -URxvt.iso14755: false -URxvt.iso14755_52: false -URxvt.perl-ext-common: default,matcher diff --git a/modules/themes/aquanaut/bspwmrc b/modules/themes/aquanaut/bspwmrc deleted file mode 100755 index f2ddb064..00000000 --- a/modules/themes/aquanaut/bspwmrc +++ /dev/null @@ -1,15 +0,0 @@ -#!/usr/bin/env sh - -bspc config borderless_monocle true -bspc config gapless_monocle true - -bspc config border_width 1 -bspc config window_gap 12 - -bspc config normal_border_color "#11141b" -bspc config active_border_color "#21242b" -bspc config focused_border_color "#798cb3" - -# Extra padding for polybar -bspc config -m $MONITOR window_gap 12 -bspc config -m $MONITOR bottom_padding 28 diff --git a/modules/themes/aquanaut/default.nix b/modules/themes/aquanaut/default.nix deleted file mode 100644 index 9196e36b..00000000 --- a/modules/themes/aquanaut/default.nix +++ /dev/null @@ -1,80 +0,0 @@ -# themes/aquanaut/default.nix --- a sea-blue linux theme - -{ config, options, lib, pkgs, ... }: -with lib; -{ - options.modules.themes.aquanaut = { - enable = mkOption { - type = types.bool; - default = false; - }; - }; - - config = mkIf config.modules.themes.aquanaut.enable { - modules.theme = { - name = "Aquanaut"; - version = "0.1"; - path = ./.; - }; - - services.picom = { - activeOpacity = "0.96"; - inactiveOpacity = "0.75"; - settings = { - blur-background = true; - blur-background-frame = true; - blur-background-fixed = true; - blur-kern = "7x7box"; - blur-strength = 340; - }; - }; - - services.xserver.displayManager.lightdm = { - greeters.mini.extraConfig = '' - text-color = "#bbc2cf" - password-background-color = "#29323d" - window-color = "#0b1117" - border-color = "#0b1117" - ''; - }; - - fonts.fonts = [ pkgs.nerdfonts ]; - my.packages = with pkgs; [ - nordic - paper-icon-theme # for rofi - ]; - my.zsh.rc = lib.readFile ./zsh/prompt.zsh; - my.home.xdg.configFile = { - "bspwm/rc.d/polybar".source = ./polybar/run.sh; - "bspwm/rc.d/theme".source = ./bspwmrc; - "dunst/dunstrc".source = ./dunstrc; - "polybar" = { source = ./polybar; recursive = true; }; - "rofi/theme" = { source = ./rofi; recursive = true; }; - "tmux/theme".source = ./tmux.conf; - "xtheme/90-theme".source = ./Xresources; - # GTK - "gtk-3.0/settings.ini".text = '' - [Settings] - gtk-theme-name=Nordic-blue - gtk-icon-theme-name=Paper - gtk-fallback-icon-theme=gnome - gtk-application-prefer-dark-theme=true - gtk-cursor-theme-name=Paper - gtk-xft-hinting=1 - gtk-xft-hintstyle=hintfull - gtk-xft-rgba=none - ''; - # GTK2 global theme (widget and icon theme) - "gtk-2.0/gtkrc".text = '' - gtk-theme-name="Nordic-blue" - gtk-icon-theme-name="Paper-Mono-Dark" - gtk-font-name="Sans 10" - ''; - # QT4/5 global theme - "Trolltech.conf".text = '' - [Qt] - style=Nordic-blue - ''; - }; - }; -} diff --git a/modules/themes/aquanaut/dunstrc b/modules/themes/aquanaut/dunstrc deleted file mode 100644 index 497485c9..00000000 --- a/modules/themes/aquanaut/dunstrc +++ /dev/null @@ -1,49 +0,0 @@ -[global] -alignment = left -bounce_freq = 0 -browser = firefox -new-tab -corner_radius = 3 -dmenu = rofi -dmenu -p dunst: -follow = none -font = Fira Code 10 -format = "%s\n%b" -frame_color = "#101216" -frame_width = 0 -# geometry [{width}]x{height}][+/-{x}+/-{y}] -geometry = "375x15-18+18" -history_length = 20 -horizontal_padding = 16 -icon_position = right -idle_threshold = 120 -ignore_newline = no -indicate_hidden = yes -line_height = 0 -markup = full -max_icon_size = 64 -monitor = 0 -padding = 14 -separator_color = auto -separator_height = 4 -show_age_threshold = 60 -show_indicators = yes -shrink = no -sort = yes -startup_notification = false -sticky_history = yes -transparency = 10 -word_wrap = yes - -[urgency_low] -background = "#101216" -foreground = "#5EC4FF" -timeout = 8 - -[urgency_normal] -background = "#5EC4FF" -foreground = "#101216" -timeout = 14 - -[urgency_critical] -background = "#f0c674" -foreground = "#101216" -timeout = 0 diff --git a/modules/themes/aquanaut/polybar/config b/modules/themes/aquanaut/polybar/config deleted file mode 100644 index c5abb933..00000000 --- a/modules/themes/aquanaut/polybar/config +++ /dev/null @@ -1,320 +0,0 @@ -[colors] -bg = ${xrdb:background} -fg = ${xrdb:color4} -black = ${xrdb:color0} -bblack = ${xrdb:color8} -red = ${xrdb:color1} -bred = ${xrdb:color9} -green = ${xrdb:color2} -bgreen = ${xrdb:color10} -yellow = ${xrdb:color3} -byellow = ${xrdb:color11} -blue = ${xrdb:color4} -bblue = ${xrdb:color12} -magenta = ${xrdb:color5} -bmagenta = ${xrdb:color13} -cyan = ${xrdb:color6} -bcyan = ${xrdb:color14} -white = ${xrdb:color7} -bwhite = ${xrdb:color15} - -bg-alt = #0F1013 -fg-alt = #25283a -icons = #555856 -alert = ${colors.red} - -[global/wm] -margin-top = 0 -margin-bottom = 24 - -[bar/main] -monitor = ${env:MONITOR} -monitor-strict = true -enable-ipc = true -wm-restack = bspwm -# REQUIRED to move the window with hideit.sh -override-redirect = true - -background = -foreground = ${colors.fg} - -width = 100% -height = 24 -offset-x = 0 -offset-y = 8 -bottom = 1 - -overline-size = 0 -overline-color = #f00 -underline-size = 0 -underline-color = #00f - -border-bottom-size = 0 - -padding-left = 2 -padding-right = 2 -module-margin-left = 0 -module-margin-right = 0 - -font-0 = "Fira Code:pixelsize=9;2" -font-1 = "Wuncon Siji:pixelsize=12;2" -font-2 = "Siji:pixelsize=10;2" - -; modules-left = volume pad cpu memory pad pkg mail -modules-left = volume pad cpu memory -modules-center = bspwm -modules-right = battery wlan syncthing redshift pad date - -;tray-position = center -;tray-padding = 2 -;tray-transparent = true -;tray-background = #0063ff - -[module/bspwm] -type = internal/bspwm -pin-workspaces = true -enable-click = true - -ws-icon-0 = 1; -ws-icon-1 = 2; -ws-icon-2 = 3; -ws-icon-3 = 4; -ws-icon-4 = 5; -ws-icon-default = x - -format = -label-padding = 1 - -label-focused = %icon% -label-focused-background = #44000000 -label-focused-foreground = ${colors.blue} -; label-focused-underline = ${colors.magenta} -; label-focused-foreground = ${xrdb:color2} -label-focused-padding = 1 - -label-occupied = %icon% -label-occupied-foreground = ${colors.icons} -label-occupied-padding = 1 - -; label-urgent = %icon% -label-urgent-foreground = ${colors.red} -; label-urgent-background = ${colors.alert} -label-urgent-padding = 1 - -label-empty = %icon% -label-empty-foreground = ${colors.fg-alt} -label-empty-padding = 1 - -[module/date] -type = internal/date -interval = 5 - -label = %date% %time% -date = %A, %h %d -date-alt = %Y-%m-%d -time = %I:%M %p -time-alt = %H:%M:%S -format-prefix = "" -format-prefix-padding = 1 -; format-prefix-background = ${colors.bg-alt} -format-prefix-foreground = ${colors.icons} -; format-underline = ${xrdb:color4} - -[module/xwindow] -type = internal/xwindow -label = %title:0:80:...% -label-padding-left = 2 - -; [module/mpd] -; type = internal/mpd -; host = /home/hlissner/.config/mpd/mpd.sock -; -; format-online = -; format-padding = 5 -; -; label-song-maxlen = 45 -; label-song-ellipsis = true -; -; icon-prev =  -; icon-seekb =  -; icon-stop =  -; icon-play =  -; icon-pause =  -; icon-next =  -; icon-seekf =  -; -; icon-random =  -; icon-repeat =  -; -; toggle-on-foreground = ${colors.fg} -; toggle-off-foreground = #66 - -[module/cpu] -type = internal/cpu -interval = 2 -format = -format-prefix = "" -format-foreground = ${colors.icons} -; format-underline = #f90000 -; label = %percentage%% -format-padding = 1 - -bar-load-indicator = -bar-load-width = 6 -bar-load-foreground-0 = ${colors.green} -bar-load-foreground-1 = ${colors.green} -bar-load-foreground-2 = ${colors.yellow} -bar-load-foreground-3 = ${colors.red} -bar-load-foreground-4 = ${colors.red} -bar-load-fill = | -bar-load-empty = ¦ -bar-load-empty-foreground = ${colors.fg-alt} - -[module/memory] -type = internal/memory -interval = 3 -format = -format-prefix = "" -format-prefix-foreground = ${colors.icons} -; format-underline = #4bffdc -; label = %percentage_used%% -format-padding-left = 1 - -; Only applies if is used -bar-used-indicator = -bar-used-width = 6 -bar-used-foreground-0 = ${colors.green} -bar-used-foreground-1 = ${colors.green} -bar-used-foreground-2 = ${colors.yellow} -bar-used-foreground-3 = ${colors.red} -bar-used-foreground-4 = ${colors.red} -bar-used-fill = | -bar-used-empty = ¦ -bar-used-empty-foreground = ${colors.fg-alt} - -[module/wlan] -type = internal/network -interface = ${env:WLP:wlp3s0} -interval = 3.0 - -format-connected = -format-disconnected = ! -format-disconnected-foreground = ${colors.red} - -; label-connected = -; label-disconnected = ! -; label-disconnected-foreground = ${colors.red} - -ramp-signal-0 =  -ramp-signal-0-foreground = ${colors.yellow} -ramp-signal-1 =  -ramp-signal-1-foreground = ${colors.yellow} -ramp-signal-2 =  -ramp-signal-2-foreground = ${colors.yellow} -ramp-signal-3 =  -ramp-signal-3-foreground = ${colors.icons} -ramp-signal-4 =  -ramp-signal-4-foreground = ${colors.icons} - -; [module/eth] -; type = internal/network -; interface = ${env:ETH:enp2s0} -; interval = 4.0 -; -; ; format-connected-underline = #55aa55 -; ; format-connected-prefix = " " -; format-connected-foreground-foreground = ${colors.fg-alt} -; label-connected = %local_ip% -; -; format-disconnected-underline = ${self.format-connected-underline} -; label-disconnected = %ifname% disconnected -; label-disconnected-foreground = ${colors.fg-alt} - -[module/volume] -type = internal/volume - -; format-volume = -format-volume = -; label-volume = " " -label-volume-foreground = ${colors.fg} - -; format-muted-prefix = " " -format-muted-foreground = ${colors.red} -label-muted =  - -bar-volume-width = 8 -bar-volume-foreground-0 = ${colors.blue} -bar-volume-foreground-1 = ${colors.blue} -bar-volume-foreground-2 = ${colors.blue} -bar-volume-foreground-3 = ${colors.blue} -bar-volume-foreground-4 = ${colors.blue} -bar-volume-foreground-5 = ${colors.blue} -bar-volume-foreground-6 = ${colors.blue} -bar-volume-gradient = false -bar-volume-indicator = | -bar-volume-indicator-font = 2 -bar-volume-indicator-foreground = #ff -bar-volume-fill = ─ -bar-volume-fill-font = 2 -bar-volume-empty = ─ -bar-volume-empty-font = 2 -bar-volume-empty-foreground = ${colors.fg-alt} - -; Only applies if is used -ramp-volume-0 =  -ramp-volume-1 =  -ramp-volume-2 =  - -[module/battery] -type = internal/battery -battery = BAT0 -adapter = ADP1 -full-at = 98 - -format-charging = -format-charging-underline = #ffb52a - -format-discharging = -format-discharging-underline = ${self.format-charging-underline} - -format-full-prefix = " " -format-full-prefix-foreground = ${colors.fg-alt} -format-full-underline = ${self.format-charging-underline} - -ramp-capacity-0 =  -ramp-capacity-1 =  -ramp-capacity-2 =  -ramp-capacity-foreground = ${colors.fg-alt} - -animation-charging-0 =  -animation-charging-1 =  -animation-charging-2 =  -animation-charging-foreground = ${colors.fg-alt} -animation-charging-framerate = 750 - - -;===================================================== -; Custom scripts -;===================================================== - -[module/pad] -type = custom/text -content = " " -content-foreground = ${colors.fg-alt} - -[module/redshift] -type = custom/script -exec = ~/.config/polybar/modules/redshift -exec-if = pgrep -x redshift -interval = 60 -format-padding = 1 - -[module/syncthing] -type = custom/script -exec = echo 1 -exec-if = systemctl is-active syncthing -format = "" -format-foreground = ${colors.icons} -interval = 30 - -; vim:ft=dosini diff --git a/modules/themes/aquanaut/polybar/modules/redshift b/modules/themes/aquanaut/polybar/modules/redshift deleted file mode 100755 index 7733a7fc..00000000 --- a/modules/themes/aquanaut/polybar/modules/redshift +++ /dev/null @@ -1,21 +0,0 @@ -#!/usr/bin/env bash - -# Specifying the icon(s) in the script -# This allows us to change its appearance conditionally -pgrep -x redshift &> /dev/null -if [[ $? -eq 0 ]]; then - temp=$(redshift -p 2>/dev/null | grep temp | cut -d' ' -f3) - temp=${temp//K/} -fi - -# OPTIONAL: Append ' ${temp}K' after $icon -if [[ -z $temp ]]; then - echo "%{F#65737E}$icon" # Greyed out (not running) -elif [[ $temp -ge 5000 ]]; then - echo "%{F#8FA1B3}$icon" # Blue -elif [[ $temp -ge 4000 ]]; then - echo "%{F#EBCB8B}$icon" # Yellow -else - echo "%{F#D08770}$icon" # Orange -fi - diff --git a/modules/themes/aquanaut/polybar/run.sh b/modules/themes/aquanaut/polybar/run.sh deleted file mode 100755 index 528a069a..00000000 --- a/modules/themes/aquanaut/polybar/run.sh +++ /dev/null @@ -1,7 +0,0 @@ -#!/usr/bin/env bash - -killall -q polybar -while pgrep -u $UID -x polybar >/dev/null; do sleep 1; done - -polybar main >>$XDG_DATA_HOME/polybar.log 2>&1 & -echo 'Polybar launched...' \ No newline at end of file diff --git a/modules/themes/aquanaut/rofi/appmenu.rasi b/modules/themes/aquanaut/rofi/appmenu.rasi deleted file mode 100644 index a5d35d21..00000000 --- a/modules/themes/aquanaut/rofi/appmenu.rasi +++ /dev/null @@ -1,48 +0,0 @@ -/** -*- mode: css; -*- - * This theme is intended for a 8x2 items list menu with a headerbar. - */ -@import "config.rasi" -* { - background-color: @background; - text-color: @foreground-list; - font: @text-font; -} -#window { - padding: @list-8-window-padding; -} -inputbar, -prompt, -textbox-prompt-colon, -entry { - background-color: @background-light; -} -#inputbar { - children: [ prompt, textbox-prompt-colon, entry ]; - margin: @inputbar-margin; -} -#prompt { - padding: @prompt-padding; - background-color: @accent; - text-color: @background; -} -#textbox-prompt-colon { - expand: false; - str: " : : "; - padding: @apps-textbox-prompt-colon-padding; -} -#entry { - text-color: @accent; - padding: @entry-padding; -} -#element { - padding: @list-element-padding; - margin: @list-element-margin; - border: @list-element-border; - background-color: @background-light; - border-color: @background-light; -} -#element.selected { - background-color: @background-focus; - text-color: @accent; - border-color: @accent; -} diff --git a/modules/themes/aquanaut/rofi/browsermenu.rasi b/modules/themes/aquanaut/rofi/browsermenu.rasi deleted file mode 100644 index 50c33b8c..00000000 --- a/modules/themes/aquanaut/rofi/browsermenu.rasi +++ /dev/null @@ -1,16 +0,0 @@ -/* -*- mode: css; -*- */ - -@import "appmenu.rasi" - -#prompt { - background-color: #a9a1e1; -} - -#entry { - text-color: #a9a1e1; -} - -#element.selected { - text-color: #a9a1e1; - border-color: #a9a1e1; -} diff --git a/modules/themes/aquanaut/rofi/config.rasi b/modules/themes/aquanaut/rofi/config.rasi deleted file mode 100644 index 2941b86c..00000000 --- a/modules/themes/aquanaut/rofi/config.rasi +++ /dev/null @@ -1,46 +0,0 @@ -/* -*- mode: css; -*- */ -configuration { - icon-theme: "Paper"; - cycle: true; - hide-scrollbar: true; - disable-history: false; - monitor: -4; - columns: 2; -} - -* { - accent: #51afef; - background: #101216; - background-light: #1f1f1f; - background-focus: #282828; - foreground: #888888; - foreground-list: #bbbbbb; - on: #98be65; - off: #ff6c6b; - - text-font: "Fira Sans 16"; - text-font-mono: "Fira Mono 16"; - icon-font: "Hurmit Nerd Font Mono 60"; - icon-font-small: "Hurmit Nerd Font Mono 24"; - - /* General */ - inputbar-margin: 4px 4px; - prompt-padding: 14px 18px; - entry-padding: 16px 14px 14px 0px; - /* list menus: appsmenu, networkmenu and nmvpnmenu */ - list-element-padding: 20px; - list-element-margin: @inputbar-margin; - list-element-border: 0px 0px 0px 8px; - list-8-window-padding: 240px 18%; - /* appsmenu */ - apps-textbox-prompt-colon-padding: 16px; - /* networkmenu */ - network-textbox-prompt-colon-padding: 14px 10px 10px 10px; - /* nmvpnmenu */ - nmvpn-textbox-prompt-colon-padding: @network-textbox-prompt-colon-padding; -} - -#window { - width: 100%; - height: 100%; -} diff --git a/modules/themes/aquanaut/rofi/filemenu.rasi b/modules/themes/aquanaut/rofi/filemenu.rasi deleted file mode 100644 index 129e8262..00000000 --- a/modules/themes/aquanaut/rofi/filemenu.rasi +++ /dev/null @@ -1,3 +0,0 @@ -/* -*- mode: css; -*- */ - -@import "appmenu.rasi" diff --git a/modules/themes/aquanaut/rofi/passmenu.rasi b/modules/themes/aquanaut/rofi/passmenu.rasi deleted file mode 100644 index bbf9378d..00000000 --- a/modules/themes/aquanaut/rofi/passmenu.rasi +++ /dev/null @@ -1,16 +0,0 @@ -/* -*- mode: css; -*- */ - -@import "appmenu.rasi" - -#prompt { - background-color: #c678dd; -} - -#entry { - text-color: #c678dd; -} - -#element.selected { - text-color: #c678dd; - border-color: #c678dd; -} diff --git a/modules/themes/aquanaut/rofi/powermenu.rasi b/modules/themes/aquanaut/rofi/powermenu.rasi deleted file mode 100644 index 697904e4..00000000 --- a/modules/themes/aquanaut/rofi/powermenu.rasi +++ /dev/null @@ -1,28 +0,0 @@ -/** -*- mode: css; -*- - * This theme is intended for a 5 items wide menu on a 1920x1080 pixels resolution. - * You may have to tweak values such as the window padding if you have a different resolution. - */ -@import "appmenu.rasi" - -#element { - padding: 30px; - background-color: @background-light; -} -#element.selected { - background-color: @accent; - text-color: @background; -} -#window { - /* padding: @option-5-window-padding; */ -} -#listview { - /* spacing: @option-5-listview-spacing; */ - /* lines: 5; */ - columns: 1; -} -#window { - children: [ horibox ]; -} -#horibox { - children: [ listview ]; -} diff --git a/modules/themes/aquanaut/rofi/windowmenu.rasi b/modules/themes/aquanaut/rofi/windowmenu.rasi deleted file mode 100644 index 9cefdc79..00000000 --- a/modules/themes/aquanaut/rofi/windowmenu.rasi +++ /dev/null @@ -1,16 +0,0 @@ -/* -*- mode: css; -*- */ - -@import "appmenu.rasi" - -#prompt { - background-color: #bbc2cf; -} - -#entry { - text-color: #bbc2cf; -} - -#element.selected { - text-color: #bbc2cf; - border-color: #bbc2cf; -} diff --git a/modules/themes/aquanaut/tmux.conf b/modules/themes/aquanaut/tmux.conf deleted file mode 100644 index 7a184696..00000000 --- a/modules/themes/aquanaut/tmux.conf +++ /dev/null @@ -1,68 +0,0 @@ -# -- THEME ------------------------------- - -# The statusbar -set -g status-position bottom -set -g status-justify centre -set -g status-bg default -set -g status-fg colour15 -set -g status-interval 10 -# set -g status-attr dim -# set -g status-left '#[fg=colour236]_________________________' -set -g status-left '#{prefix_highlight}#[fg=colour236]|―――――――――――――――――――|' -# set -g status-left "#[fg=colour236]#{prefix_highlight} #[fg=colour5] #S #[fg=colour236]──" -# set -g status-right '#[fg=colour236]_________________________' -set -g status-right '#[fg=colour236]|―――――――――――――――――――――――――|' -set -g status-right-length 30 -set -g status-left-length 30 - -# The messages -# set -g message-fg colour4 -# set -g message-bg colour237 -# set -g message-command-fg blue -# set -g message-command-bg black - -# loud or quiet? -set-option -g visual-activity off -set-option -g visual-bell off -set-option -g visual-silence off -set-window-option -g monitor-activity on -set-option -g bell-action none - -# The modes -setw -g clock-mode-colour colour135 -# setw -g mode-attr bold -# setw -g mode-fg colour196 -# setw -g mode-bg colour238 - -# The panes -# set -g pane-border-fg colour235 -# set -g pane-border-bg default -# set -g pane-active-border-fg colour5 -# set -g pane-active-border-bg default - -# setw -g window-status-current-fg colour2 -# setw -g window-status-current-bg default -# setw -g window-status-current-attr none -# setw -g window-status-current-format ' #W ' - -# setw -g window-status-fg colour236 -# setw -g window-status-bg default -# setw -g window-status-attr none -# setw -g window-status-format '#[fg=colour8] #I #[fg=default]#W ' -setw -g window-status-format ' #W ' - -# setw -g window-status-activity-bg default -# setw -g window-status-activity-fg colour240 -# setw -g window-status-activity-attr none - -# setw -g window-status-bell-attr bold -# setw -g window-status-bell-fg colour255 -# setw -g window-status-bell-bg colour1 - - -# -- PLUGINS ----------------------------- - -# tmux-prefix-highlight -set -g @prefix_highlight_empty_prompt '-----' -set -g @prefix_highlight_prefix_prompt ' C^c #[bg=colour8]' -set -g @prefix_highlight_show_copy_mode 'on' diff --git a/modules/themes/aquanaut/wallpaper.jpg b/modules/themes/aquanaut/wallpaper.jpg deleted file mode 100644 index 626fcbde..00000000 Binary files a/modules/themes/aquanaut/wallpaper.jpg and /dev/null differ diff --git a/modules/themes/aquanaut/zsh/prompt.zsh b/modules/themes/aquanaut/zsh/prompt.zsh deleted file mode 100644 index 1d83100c..00000000 --- a/modules/themes/aquanaut/zsh/prompt.zsh +++ /dev/null @@ -1,71 +0,0 @@ -# Loosely based off Pure - -_strlen() { echo ${#${(S%%)1//$~%([BSUbfksu]|([FB]|){*})/}}; } - -# fastest possible way to check if repo is dirty -prompt_git_dirty() { - command -v git >/dev/null || return - - # check if we're in a git repo - [[ "$(command git rev-parse --is-inside-work-tree 2>/dev/null)" == "true" ]] || return - # check if it's dirty - command test -n "$(git status --porcelain --ignore-submodules -unormal)" || return - - local r=$(command git rev-list --right-only --count HEAD...@'{u}' 2>/dev/null) - local l=$(command git rev-list --left-only --count HEAD...@'{u}' 2>/dev/null) - - (( ${r:-0} > 0 )) && echo -n " %F{red}${r}-" - (( ${l:-0} > 0 )) && echo -n " %F{green}${l}+" - echo -n '%f' -} - -## Hooks ############################### -prompt_hook_precmd() { - vcs_info # get git info - # Newline before prompt, except on init - [[ -n $PROMPT_DONE ]] && print ""; PROMPT_DONE=1 -} - -## Initialization ###################### -prompt_init() { - # prevent percentage showing up - # if output doesn't end with a newline - export PROMPT_EOL_MARK= - - # prompt_opts=(cr subst percent) - setopt promptsubst - autoload -Uz add-zsh-hook - autoload -Uz vcs_info - - add-zsh-hook precmd prompt_hook_precmd - # Updates cursor shape and prompt symbol based on vim mode - zle-keymap-select() { - case $KEYMAP in - vicmd) PROMPT_SYMBOL="%F{magenta}« " ;; - main|viins) PROMPT_SYMBOL="%(?.%F{blue}.%F{red})λ " ;; - esac - zle reset-prompt - zle -R - } - zle -N zle-keymap-select - zle -A zle-keymap-select zle-line-init - - zstyle ':vcs_info:*' enable git - zstyle ':vcs_info:*' use-simple true - zstyle ':vcs_info:*' max-exports 2 - zstyle ':vcs_info:git*' formats ' %b' - zstyle ':vcs_info:git*' actionformats ' %b (%a)' - - # show username@host if logged in through SSH - if [[ -n $SSH_CONNECTION ]]; then - prompt_username='%m ' - if [[ $(whoami) != hlissner ]]; then - prompt_username="%n.$prompt_username" - fi - fi - - RPROMPT='%F{blue}%~%F{magenta}${vcs_info_msg_0_}$(prompt_git_dirty)%f' - PROMPT='%F{green}${prompt_username}%f${PROMPT_SYMBOL:-$ }' -} - -prompt_init "$@" diff --git a/modules/themes/default.nix b/modules/themes/default.nix index a20e6f36..6d5861e8 100644 --- a/modules/themes/default.nix +++ b/modules/themes/default.nix @@ -1,56 +1,15 @@ -{ config, options, lib, pkgs, ... }: +# Theme modules are a special beast. They're the only modules that are deeply +# intertwined with others, and are solely responsible for aesthetics. Disabling +# a theme module should never leave a system non-functional. + +{ config, lib, ... }: with lib; -{ - imports = [ - # aquanaut = callPackage (import ./aquanaut {}); - ./fluorescence - ]; - - options.modules.theme = { - name = mkOption { type = with types; nullOr str; default = null; }; - version = mkOption { type = with types; nullOr str; default = null; }; - path = mkOption { - type = with types; nullOr path; - default = null; - }; - - wallpaper = { - path = mkOption { - type = with types; nullOr str; - default = if config.modules.theme.path != null - then "${config.modules.theme.path}/wallpaper.png" - else null; - }; - - filter = { - enable = mkOption { - type = types.bool; - default = true; - }; - options = mkOption { - type = types.str; - default = "-gaussian-blur 0x2 -modulate 70 -level 5%"; - }; - }; - }; - }; - - config = mkIf (config.modules.theme.wallpaper.path != null && - builtins.pathExists config.modules.theme.wallpaper.path) { - my.home.home.file.".background-image".source = - config.modules.theme.wallpaper.path; - - services.xserver.displayManager.lightdm.background = - mkIf config.modules.theme.wallpaper.filter.enable - (let filteredPath = "wallpaper.filtered.png"; - filteredWallpaper = - with pkgs; runCommand "filterWallpaper" - { buildInputs = [ imagemagick ]; } '' - mkdir "$out" - convert ${config.modules.theme.wallpaper.filter.options} \ - ${config.modules.theme.wallpaper.path} $out/${filteredPath} - ''; - in "${filteredWallpaper}/${filteredPath}"); - }; +with lib.my; +let cfg = config.modules.themes; +in { + assertions = [{ + assertion = countAttrs (_: x: x.enable) cfg < 2; + message = "Can't have more than one theme enabled at a time"; + }]; } diff --git a/modules/themes/fluorescence/README.md b/modules/themes/fluorescence/README.org similarity index 65% rename from modules/themes/fluorescence/README.md rename to modules/themes/fluorescence/README.org index 1c85945c..33ca9ea3 100644 --- a/modules/themes/fluorescence/README.md +++ b/modules/themes/fluorescence/README.org @@ -1,5 +1,13 @@ -# Fluorescence +#+TITLE: Fluorescence +#+AUTHOR: Henrik Lissner +#+DATE: October 1, 2019 +A regal dracula-inspired theme. + +* Wallpaper +![Fluorescence wallpaper](config/wallpaper.jpg) + +* Screenshots ![My desktop, pretending to look busy, with gaps](/../screenshots/fluorescence/fakebusy.png?raw=true) ![My desktop, unfettered by windows](/../screenshots/fluorescence/desktop.png?raw=true) ![My app launcher, rofi](/../screenshots/fluorescence/rofi.png?raw=true) diff --git a/modules/themes/fluorescence/Xresources b/modules/themes/fluorescence/config/Xresources similarity index 100% rename from modules/themes/fluorescence/Xresources rename to modules/themes/fluorescence/config/Xresources diff --git a/modules/themes/fluorescence/bspwmrc b/modules/themes/fluorescence/config/bspwmrc similarity index 100% rename from modules/themes/fluorescence/bspwmrc rename to modules/themes/fluorescence/config/bspwmrc diff --git a/modules/themes/fluorescence/dunstrc b/modules/themes/fluorescence/config/dunstrc similarity index 100% rename from modules/themes/fluorescence/dunstrc rename to modules/themes/fluorescence/config/dunstrc diff --git a/modules/themes/fluorescence/firefox/userChrome.css b/modules/themes/fluorescence/config/firefox/userChrome.css similarity index 100% rename from modules/themes/fluorescence/firefox/userChrome.css rename to modules/themes/fluorescence/config/firefox/userChrome.css diff --git a/modules/themes/fluorescence/config/inkscape/default-template.svg b/modules/themes/fluorescence/config/inkscape/default-template.svg new file mode 100644 index 00000000..ff14f948 --- /dev/null +++ b/modules/themes/fluorescence/config/inkscape/default-template.svg @@ -0,0 +1,75 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + Default template + 2020-08-05 + + diff --git a/modules/themes/fluorescence/polybar/config b/modules/themes/fluorescence/config/polybar/config similarity index 100% rename from modules/themes/fluorescence/polybar/config rename to modules/themes/fluorescence/config/polybar/config diff --git a/modules/themes/fluorescence/polybar/modules/redshift b/modules/themes/fluorescence/config/polybar/modules/redshift similarity index 100% rename from modules/themes/fluorescence/polybar/modules/redshift rename to modules/themes/fluorescence/config/polybar/modules/redshift diff --git a/modules/themes/fluorescence/polybar/run.sh b/modules/themes/fluorescence/config/polybar/run.sh similarity index 100% rename from modules/themes/fluorescence/polybar/run.sh rename to modules/themes/fluorescence/config/polybar/run.sh diff --git a/modules/themes/fluorescence/rofi/appmenu.rasi b/modules/themes/fluorescence/config/rofi/appmenu.rasi similarity index 100% rename from modules/themes/fluorescence/rofi/appmenu.rasi rename to modules/themes/fluorescence/config/rofi/appmenu.rasi diff --git a/modules/themes/fluorescence/rofi/base.cyclemenu.rasi b/modules/themes/fluorescence/config/rofi/base.cyclemenu.rasi similarity index 100% rename from modules/themes/fluorescence/rofi/base.cyclemenu.rasi rename to modules/themes/fluorescence/config/rofi/base.cyclemenu.rasi diff --git a/modules/themes/fluorescence/rofi/bookmarkmenu.rasi b/modules/themes/fluorescence/config/rofi/bookmarkmenu.rasi similarity index 100% rename from modules/themes/fluorescence/rofi/bookmarkmenu.rasi rename to modules/themes/fluorescence/config/rofi/bookmarkmenu.rasi diff --git a/modules/themes/fluorescence/rofi/config.rasi b/modules/themes/fluorescence/config/rofi/config.rasi similarity index 100% rename from modules/themes/fluorescence/rofi/config.rasi rename to modules/themes/fluorescence/config/rofi/config.rasi diff --git a/modules/themes/fluorescence/rofi/filemenu.rasi b/modules/themes/fluorescence/config/rofi/filemenu.rasi similarity index 100% rename from modules/themes/fluorescence/rofi/filemenu.rasi rename to modules/themes/fluorescence/config/rofi/filemenu.rasi diff --git a/modules/themes/fluorescence/rofi/passmenu.rasi b/modules/themes/fluorescence/config/rofi/passmenu.rasi similarity index 100% rename from modules/themes/fluorescence/rofi/passmenu.rasi rename to modules/themes/fluorescence/config/rofi/passmenu.rasi diff --git a/modules/themes/fluorescence/rofi/powermenu.rasi b/modules/themes/fluorescence/config/rofi/powermenu.rasi similarity index 100% rename from modules/themes/fluorescence/rofi/powermenu.rasi rename to modules/themes/fluorescence/config/rofi/powermenu.rasi diff --git a/modules/themes/fluorescence/rofi/windowmenu.rasi b/modules/themes/fluorescence/config/rofi/windowmenu.rasi similarity index 100% rename from modules/themes/fluorescence/rofi/windowmenu.rasi rename to modules/themes/fluorescence/config/rofi/windowmenu.rasi diff --git a/modules/themes/fluorescence/tmux.conf b/modules/themes/fluorescence/config/tmux.conf similarity index 100% rename from modules/themes/fluorescence/tmux.conf rename to modules/themes/fluorescence/config/tmux.conf diff --git a/modules/themes/fluorescence/userstyles/firefox/stylus-2020-02-11.json b/modules/themes/fluorescence/config/userstyles/firefox/stylus-2020-02-11.json similarity index 100% rename from modules/themes/fluorescence/userstyles/firefox/stylus-2020-02-11.json rename to modules/themes/fluorescence/config/userstyles/firefox/stylus-2020-02-11.json diff --git a/modules/themes/fluorescence/userstyles/qutebrowser/github.scss b/modules/themes/fluorescence/config/userstyles/qutebrowser/github.scss similarity index 100% rename from modules/themes/fluorescence/userstyles/qutebrowser/github.scss rename to modules/themes/fluorescence/config/userstyles/qutebrowser/github.scss diff --git a/modules/themes/fluorescence/userstyles/qutebrowser/monospace-textareas.scss b/modules/themes/fluorescence/config/userstyles/qutebrowser/monospace-textareas.scss similarity index 100% rename from modules/themes/fluorescence/userstyles/qutebrowser/monospace-textareas.scss rename to modules/themes/fluorescence/config/userstyles/qutebrowser/monospace-textareas.scss diff --git a/modules/themes/fluorescence/userstyles/qutebrowser/quora.scss b/modules/themes/fluorescence/config/userstyles/qutebrowser/quora.scss similarity index 100% rename from modules/themes/fluorescence/userstyles/qutebrowser/quora.scss rename to modules/themes/fluorescence/config/userstyles/qutebrowser/quora.scss diff --git a/modules/themes/fluorescence/userstyles/qutebrowser/stackoverflow.scss b/modules/themes/fluorescence/config/userstyles/qutebrowser/stackoverflow.scss similarity index 100% rename from modules/themes/fluorescence/userstyles/qutebrowser/stackoverflow.scss rename to modules/themes/fluorescence/config/userstyles/qutebrowser/stackoverflow.scss diff --git a/modules/themes/fluorescence/userstyles/qutebrowser/xkcd.scss b/modules/themes/fluorescence/config/userstyles/qutebrowser/xkcd.scss similarity index 100% rename from modules/themes/fluorescence/userstyles/qutebrowser/xkcd.scss rename to modules/themes/fluorescence/config/userstyles/qutebrowser/xkcd.scss diff --git a/modules/themes/fluorescence/userstyles/qutebrowser/youtube.scss b/modules/themes/fluorescence/config/userstyles/qutebrowser/youtube.scss similarity index 100% rename from modules/themes/fluorescence/userstyles/qutebrowser/youtube.scss rename to modules/themes/fluorescence/config/userstyles/qutebrowser/youtube.scss diff --git a/modules/themes/fluorescence/wallpaper.png b/modules/themes/fluorescence/config/wallpaper.png similarity index 100% rename from modules/themes/fluorescence/wallpaper.png rename to modules/themes/fluorescence/config/wallpaper.png diff --git a/modules/themes/fluorescence/zsh/prompt.zsh b/modules/themes/fluorescence/config/zsh/prompt.zsh similarity index 100% rename from modules/themes/fluorescence/zsh/prompt.zsh rename to modules/themes/fluorescence/config/zsh/prompt.zsh diff --git a/modules/themes/fluorescence/default.nix b/modules/themes/fluorescence/default.nix index 61c8145d..f096489a 100644 --- a/modules/themes/fluorescence/default.nix +++ b/modules/themes/fluorescence/default.nix @@ -1,133 +1,177 @@ -# themes/fluorescence/default.nix --- a regal dracula-inspired theme +# modules/themes/fluorescence/default.nix --- a regal dracula-inspired theme + +{ options, config, lib, pkgs, ... }: -{ config, options, lib, pkgs, ... }: with lib; -let cfg = config.modules; in -{ - options.modules.themes.fluorescence = { - enable = mkOption { - type = types.bool; - default = false; +with lib.my; +let m = config.modules; + cfg = m.themes.fluorescence; +in { + options.modules.themes.fluorescence = with types; { + enable = mkBoolOpt false; + wallpaper = { + path = mkOpt path ./config/wallpaper.png; + filter = { + enable = mkBoolOpt true; + options = mkOpt str "-gaussian-blur 0x2 -modulate 70 -level 5%"; + }; }; }; - config = mkIf cfg.themes.fluorescence.enable { - modules.theme = { - name = "fluorescence"; - version = "0.0.1"; - path = ./.; - - wallpaper = { - filter.options = "-gaussian-blur 0x2 -modulate 70 -level 5%"; + config = mkIf cfg.enable (mkMerge [ + # Desktop-agnostic configuration + { + home.configFile = mkIf m.shell.tmux.enable { + "tmux/theme".source = ./config/tmux.conf; }; - }; + modules.shell.zsh.rcFiles = [ ./config/zsh/prompt.zsh ]; + } - services.picom = { - fade = true; - fadeDelta = 1; - fadeSteps = [ "0.01" "0.012" ]; - shadow = true; - shadowOffsets = [ (-10) (-10) ]; - shadowOpacity = "0.22"; - # activeOpacity = "1.00"; - # inactiveOpacity = "0.92"; - settings = { - shadow-radius = 12; - # blur-background = true; - # blur-background-frame = true; - # blur-background-fixed = true; - blur-kern = "7x7box"; - blur-strength = 320; + # Use a blurred+dimmed version of my wallpaper for the login screen + (mkIf (pathExists cfg.wallpaper.path) { + services.xserver.displayManager.lightdm.background = + if cfg.wallpaper.filter.enable + then cfg.wallpaper.path + else (let options = cfg.wallpaper.filter.options; + wallpaperPath = cfg.wallpaper.path; + filteredPath = "wallpaper.filtered.png"; + filteredWallpaper = + pkgs.runCommand "filterWallpaper" + { buildInputs = [ pkgs.imagemagick ]; } '' + mkdir "$out" + convert ${options} ${wallpaperPath} $out/${filteredPath} + ''; + in "${filteredWallpaper}/${filteredPath}"); + }) + + # Desktop (X11) theming + (mkIf config.services.xserver.enable { + user.packages = with pkgs; [ + unstable.ant-dracula-theme + paper-icon-theme # for rofi + ]; + + fonts.fonts = [ pkgs.jetbrains-mono ]; + + # Compositor + services.picom = { + fade = true; + fadeDelta = 1; + fadeSteps = [ 0.01 0.012 ]; + shadow = true; + shadowOffsets = [ (-10) (-10) ]; + shadowOpacity = 0.22; + # activeOpacity = "1.00"; + # inactiveOpacity = "0.92"; + settings = { + shadow-radius = 12; + # blur-background = true; + # blur-background-frame = true; + # blur-background-fixed = true; + blur-kern = "7x7box"; + blur-strength = 320; + }; }; - }; - services.xserver.displayManager.lightdm = { - greeters.mini.extraConfig = '' - text-color = "#ff79c6" - password-background-color = "#1E2029" - window-color = "#181a23" - border-color = "#181a23" - ''; - }; + services.xserver.displayManager.lightdm = mkMerge [ + # Login screen theme + { + greeters.mini.extraConfig = '' + text-color = "#ff79c6" + password-background-color = "#1E2029" + window-color = "#181a23" + border-color = "#181a23" + ''; + } - fonts.fonts = [ pkgs.nerdfonts ]; - my.packages = with pkgs; [ - my.ant-dracula - paper-icon-theme # for rofi - ]; - my.zsh.rc = lib.readFile ./zsh/prompt.zsh; + # Use a blurred+dimmed version of my wallpaper for the login screen + (mkIf (pathExists cfg.wallpaper.path) { + background = + if cfg.wallpaper.filter.enable + then cfg.wallpaper.path + else (let options = cfg.wallpaper.filter.options; + wallpaperPath = cfg.wallpaper.path; + filteredPath = "wallpaper.filtered.png"; + filteredWallpaper = + pkgs.runCommand "filterWallpaper" + { buildInputs = [ pkgs.imagemagick ]; } '' + mkdir "$out" + convert ${options} ${wallpaperPath} $out/${filteredPath} + ''; + in "${filteredWallpaper}/${filteredPath}"); - my.home = { - home.file = mkMerge [ - (mkIf cfg.desktop.browsers.firefox.enable { - ".mozilla/firefox/${cfg.desktop.browsers.firefox.profileName}.default/chrome/userChrome.css" = { - source = ./firefox/userChrome.css; - }; }) ]; - xdg.configFile = mkMerge [ - (mkIf config.services.xserver.enable { - "xtheme/90-theme".source = ./Xresources; - # GTK - "gtk-3.0/settings.ini".text = '' - [Settings] - gtk-theme-name=Ant-Dracula - gtk-icon-theme-name=Paper - gtk-fallback-icon-theme=gnome - gtk-application-prefer-dark-theme=true - gtk-cursor-theme-name=Paper - gtk-xft-hinting=1 - gtk-xft-hintstyle=hintfull - gtk-xft-rgba=none - ''; - # GTK2 global theme (widget and icon theme) - "gtk-2.0/gtkrc".text = '' - gtk-theme-name="Ant-Dracula" - gtk-icon-theme-name="Paper-Mono-Dark" - gtk-font-name="Sans 10" - ''; - # QT4/5 global theme - "Trolltech.conf".text = '' - [Qt] - style=Ant-Dracula - ''; - }) - (mkIf cfg.desktop.bspwm.enable { - "bspwm/rc.d/polybar".source = ./polybar/run.sh; - "bspwm/rc.d/theme".source = ./bspwmrc; - }) - (mkIf cfg.desktop.apps.rofi.enable { - "rofi/theme" = { source = ./rofi; recursive = true; }; - }) - (mkIf (cfg.desktop.bspwm.enable || cfg.desktop.stumpwm.enable) { - "polybar" = { source = ./polybar; recursive = true; }; - "dunst/dunstrc".source = ./dunstrc; - }) - (mkIf cfg.shell.tmux.enable { - "tmux/theme".source = ./tmux.conf; - }) - ]; + modules.desktop.browsers = { + firefox.userChrome = + readFile ./config/firefox/userChrome.css; + qutebrowser.userStyles = + with pkgs; + let compiledStyles = + runCommand "compileUserStyles" + { buildInputs = [ sass ]; } '' + mkdir "$out" + for file in "${./config/userstyles/qutebrowser}"/*.scss; do + scss --sourcemap=none \ + --no-cache \ + --style compressed \ + --default-encoding utf-8 \ + "$file" \ + >>"$out/userstyles.css" + done + ''; + in readFile "${compiledStyles}/userstyles.css"; + }; - xdg.dataFile = mkMerge [ - (mkIf cfg.desktop.browsers.qutebrowser.enable { - "qutebrowser/userstyles.css".source = - let compiledStyles = - with pkgs; runCommand "compileUserStyles" - { buildInputs = [ sass ]; } '' - mkdir "$out" - for file in ${./userstyles/qutebrowser}/*.scss; do - scss --sourcemap=none \ - --no-cache \ - --style compressed \ - --default-encoding utf-8 \ - "$file" \ - >>"$out/userstyles.css" - done - ''; - in "${compiledStyles}/userstyles.css"; - }) - ]; - }; - }; + home = { + configFile = mkMerge [ + { + "xtheme/90-theme".source = ./config/Xresources; + # GTK + "gtk-3.0/settings.ini".text = '' + [Settings] + gtk-theme-name=Ant-Dracula + gtk-icon-theme-name=Paper + gtk-fallback-icon-theme=gnome + gtk-application-prefer-dark-theme=true + gtk-cursor-theme-name=Paper + gtk-xft-hinting=1 + gtk-xft-hintstyle=hintfull + gtk-xft-rgba=none + ''; + # GTK2 global theme (widget and icon theme) + "gtk-2.0/gtkrc".text = '' + gtk-theme-name="Ant-Dracula" + gtk-icon-theme-name="Paper-Mono-Dark" + gtk-font-name="Sans 10" + ''; + # QT4/5 global theme + "Trolltech.conf".text = '' + [Qt] + style=Ant-Dracula + ''; + } + (mkIf m.desktop.bspwm.enable { + "bspwm/rc.d/polybar".source = ./config/polybar/run.sh; + "bspwm/rc.d/theme".source = ./config/bspwmrc; + }) + (mkIf m.desktop.apps.rofi.enable { + "rofi/theme" = { source = ./config/rofi; recursive = true; }; + }) + (mkIf (m.desktop.bspwm.enable || m.desktop.stumpwm.enable) { + "polybar" = { source = ./config/polybar; recursive = true; }; + "dunst/dunstrc".source = ./config/dunstrc; + }) + (mkIf m.desktop.media.graphics.vector.enable { + "inkscape/templates/default.svg".source = ./config/inkscape/default-template.svg; + }) + ]; + + dataFile = mkIf (pathExists cfg.wallpaper.path) { + "wallpaper".source = cfg.wallpaper.path; + }; + }; + }) + ]); } diff --git a/modules/xdg.nix b/modules/xdg.nix new file mode 100644 index 00000000..649922e6 --- /dev/null +++ b/modules/xdg.nix @@ -0,0 +1,43 @@ +# xdg.nix +# +# Set up and enforce XDG compliance. Other modules will take care of their own, +# but this takes care of the general case. + +{ config, home-manager, ... }: +{ + ### A tidy $HOME is a tidy mind + home-manager.users.${config.user.name}.xdg.enable = true; + + environment = { + sessionVariables = { + # These are the defaults, and xdg.enable does set them, but due to load + # order, they're not set before environment.variables are set, which could + # cause race conditions. + XDG_CACHE_HOME = "$HOME/.cache"; + XDG_CONFIG_HOME = "$HOME/.config"; + XDG_DATA_HOME = "$HOME/.local/share"; + XDG_BIN_HOME = "$HOME/.local/bin"; + }; + variables = { + # Conform more programs to XDG conventions. The rest are handled by their + # respective modules. + __GL_SHADER_DISK_CACHE_PATH = "$XDG_CACHE_HOME/nv"; + ASPELL_CONF = '' + per-conf $XDG_CONFIG_HOME/aspell/aspell.conf; + personal $XDG_CONFIG_HOME/aspell/en_US.pws; + repl $XDG_CONFIG_HOME/aspell/en.prepl; + ''; + CUDA_CACHE_PATH = "$XDG_CACHE_HOME/nv"; + HISTFILE = "$XDG_DATA_HOME/bash/history"; + INPUTRC = "$XDG_CACHE_HOME/readline/inputrc"; + LESSHISTFILE = "$XDG_CACHE_HOME/lesshst"; + WGETRC = "$XDG_CACHE_HOME/wgetrc"; + }; + + # Move ~/.Xauthority out of $HOME + extraInit = '' + export XAUTHORITY=/tmp/Xauthority + [ -e ~/.Xauthority ] && mv -f ~/.Xauthority "$XAUTHORITY" + ''; + }; +} diff --git a/overlays/.git-keep b/overlays/.git-keep new file mode 100644 index 00000000..e69de29b diff --git a/packages/.git-keep b/packages/.git-keep new file mode 100644 index 00000000..e69de29b diff --git a/packages/ant-dracula.nix b/packages/ant-dracula.nix deleted file mode 100644 index 8dd7d0f5..00000000 --- a/packages/ant-dracula.nix +++ /dev/null @@ -1,39 +0,0 @@ -{ stdenv, fetchurl, gtk-engine-murrine }: - -stdenv.mkDerivation rec { - pname = "ant-dracula-theme"; - version = "1.3.0"; - - src = fetchurl { - url = "https://github.com/EliverLara/Ant-Dracula/releases/download/v${version}/Ant-Dracula.tar"; - sha256 = "00b8w69xapqy8kc7zqwlfz1xpld6hibbh35djvhcnd905gzzymkd"; - }; - - propagatedUserEnvPkgs = [ - gtk-engine-murrine - ]; - - dontBuild = true; - - installPhase = '' - runHook preInstall - mkdir -p $out/share/themes/Ant-Dracula - cp -a * $out/share/themes/Ant-Dracula - rm -r $out/share/themes/Ant-Dracula/{Art,LICENSE,README.md,gtk-2.0/render-assets.sh} - runHook postInstall - ''; - - outputHashAlgo = "sha256"; - outputHashMode = "recursive"; - outputHash = "1ns00y1haxm20jak26gjv53yisaw9vsr2dbsgj10zz65rglr1h18"; - - meta = with stdenv.lib; { - description = "A flat and light theme with a modern look"; - homepage = https://github.com/EliverLara/Ant-Dracula; - license = licenses.gpl3; - platforms = platforms.all; - maintainers = [ - maintainers.pbogdan - ]; - }; -} diff --git a/packages/default.nix b/packages/default.nix deleted file mode 100644 index 61f95f0d..00000000 --- a/packages/default.nix +++ /dev/null @@ -1,25 +0,0 @@ -[ - (self: super: with super; { - my = { - ant-dracula = (callPackage ./ant-dracula.nix {}); - cached-nix-shell = - (callPackage - (builtins.fetchTarball - https://github.com/xzfc/cached-nix-shell/archive/master.tar.gz) {}); - linode-cli = (callPackage ./linode-cli.nix {}); - ripcord = (callPackage ./ripcord.nix {}); - zunit = (callPackage ./zunit.nix {}); - }; - - nur = import (builtins.fetchTarball "https://github.com/nix-community/NUR/archive/master.tar.gz") { - inherit super; - }; - - # Occasionally, "stable" packages are broken or incomplete, so access to the - # bleeding edge is necessary, as a last resort. - unstable = import { inherit config; }; - }) - - # emacsGit - (import (builtins.fetchTarball https://github.com/nix-community/emacs-overlay/archive/master.tar.gz)) -] diff --git a/packages/linode-cli.nix b/packages/linode-cli.nix deleted file mode 100644 index 0e3113a7..00000000 --- a/packages/linode-cli.nix +++ /dev/null @@ -1,23 +0,0 @@ -{ lib, pkgs, python2 }: - -with python2.pkgs; -buildPythonPackage rec { - pname = "linode-cli"; - version = "2.12.0"; - format = "wheel"; - - src = fetchPypi { - inherit version format; - pname = "linode_cli"; - sha256 = "d5a91327c7ce41ac63fe4436d6a2469f50ddada217d45724f1de16dc8e1e8191"; - }; - - propagatedBuildInputs = [ terminaltables requests wheel setuptools enum34 colorclass pyaml ]; - - meta = with lib; { - homepage = "https://github.com/linode/linode-cli"; - description = "The Linode CLI"; - license = licenses.bsd3; - maintainers = [ maintainers.hlissner ]; - }; -} diff --git a/packages/ripcord.nix b/packages/ripcord.nix deleted file mode 100644 index 8f34fa19..00000000 --- a/packages/ripcord.nix +++ /dev/null @@ -1,44 +0,0 @@ -{ appimageTools, fetchurl, lib, gsettings-desktop-schemas, gtk3, makeDesktopItem }: - -let pname = "ripcord"; - version = "0.4.21"; - desktopItem = makeDesktopItem { - name = pname; - desktopName = "Ripcord"; - comment = "Desktop chat client for Slack (and Discord)"; - icon = "discord"; - terminal = "false"; - exec = pname; - categories = "Network;InstantMessaging;"; - }; -in appimageTools.wrapType2 rec { - name = "${pname}-${version}"; - src = fetchurl { - url = "https://cancel.fm/dl/Ripcord-${version}-x86_64.AppImage"; - sha256 = "63a16a1369bc9c6d7b24c12044e3d2e341264f65ac38bd16bf01576f6cceb3df"; - }; - - profile = '' - export LC_ALL=C.UTF-8 - export XDG_DATA_DIRS=${gsettings-desktop-schemas}/share/gsettings-schemas/${gsettings-desktop-schemas.name}:${gtk3}/share/gsettings-schemas/${gtk3.name}:$XDG_DATA_DIRS - ''; - - multiPkgs = null; # no 32bit needed - extraPkgs = p: (appimageTools.defaultFhsEnvArgs.multiPkgs p); - - extraInstallCommands = '' - mv $out/bin/{${name},${pname}} - chmod +x $out/bin/${pname} - mkdir -p "$out/share/applications/" - cp "${desktopItem}"/share/applications/* "$out/share/applications/" - substituteInPlace $out/share/applications/*.desktop --subst-var out - ''; - - meta = with lib; { - description = "Desktop chat client for Slack (and Discord)"; - homepage = https://cancel.fm/ripcord; - license = licenses.isc; - platforms = [ "x86_64-linux" ]; - maintainers = with maintainers; [ hlissner ]; - }; -}