Rewrite to use flakes

This puts a hard dependency on 20.09, but that's to be expected.
This commit is contained in:
Henrik Lissner 2020-10-01 18:46:04 -04:00
parent 744cf032c3
commit a75c64d04a
No known key found for this signature in database
GPG key ID: 5F6C0EA160557395
172 changed files with 2833 additions and 3141 deletions

1
.gitignore vendored
View file

@ -1,2 +1 @@
secrets.nix
result result

View file

@ -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

114
README.md
View file

@ -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) <div align="center">
[![NixOS 20.03](https://img.shields.io/badge/NixOS-v20.03-blue.svg?style=flat-square&logo=NixOS&logoColor=white)](https://nixos.org)
![Me looking busy](/../screenshots/fluorescence/fakebusy.png?raw=true) [![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.09](https://img.shields.io/badge/NixOS-v20.09-blue.svg?style=flat-square&logo=NixOS&logoColor=white)](https://nixos.org)
</div>
**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.
<img src="https://raw.githubusercontent.com/hlissner/dotfiles/screenshots/fluorescence/fakebusy.png" width="100%" />
<p align="center"> <p align="center">
<span><img src="/../screenshots/fluorescence/desktop.png?raw=true" height="188" /></span> <span><img src="/../screenshots/fluorescence/desktop.png" height="187" /></span>
<span><img src="/../screenshots/fluorescence/rofi.png?raw=true" height="188" /></span> <span><img src="/../screenshots/fluorescence/rofi.png" height="187" /></span>
<span><img src="/../screenshots/fluorescence/tiling.png?raw=true" height="188" /></span> <span><img src="/../screenshots/fluorescence/tiling.png" height="187" /></span>
</p> </p>
# My dotfiles ------
+ **Operating System:** NixOS | | |
+ **Shell:** zsh + zgen |-|-|
+ **DM:** lightdm + lightdm-mini-greeter | **Shell:** | zsh + zgen |
+ **WM:** bspwm + polybar | **DM:** | lightdm + lightdm-mini-greeter |
+ **Editor:** [Doom Emacs][doom-emacs] (and occasionally [vim][vimrc]) | **WM:** | bspwm + polybar |
+ **Terminal:** st | **Editor:** | [Doom Emacs][doom-emacs] (and occasionally [vim]) |
+ **Launcher:** rofi | **Terminal:** | st |
+ **Browser:** firefox | **Launcher:** | rofi |
+ **GTK Theme:** [Ant Dracula](https://github.com/EliverLara/Ant-Dracula) | **Browser:** | firefox |
+ **Icon Theme:** [Paper Mono Dark](https://github.com/snwh/paper-icon-theme) | **GTK Theme:** | [Ant Dracula](https://github.com/EliverLara/Ant-Dracula) |
*Works on my machine* ¯\\\_(ツ)_/¯ -----
## Quick start ## Quick start
```sh 1. Yoink [NixOS 20.09][nixos] (must be newer than Sept 12, 2020 for `nixos-install --flake`).
# Assumes your partitions are set up and root is mounted on /mnt 2. Boot into the installer.
git clone https://github.com/hlissner/dotfiles /etc/dotfiles 3. Do your partitions and mount your root to `/mnt`
make -C /etc/dotfiles install 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 Behold. `bin/hey`.
USER=${USER:-hlissner}
HOST=${HOST:-kuro}
NIXOS_VERSION=20.03
DOTFILES=/home/$USER/.dotfiles
git clone https://github.com/hlissner/dotfiles /etc/dotfiles | Command | Description |
ln -s /etc/dotfiles $DOTFILES |----------------------|-----------------------------------------------------------------|
chown -R $USER:users $DOTFILES | `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 ## Frequently asked questions
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
# make /etc/nixos/configuration.nix + **How do I change the default username?**
nixos-generate-config --root /mnt
echo "import /etc/dotfiles \"$$HOST\" \"$$USER\"" >/mnt/etc/nixos/configuration.nix
# make install 1. Set `USER` the first time you run `nixos-install`: `USER=myusername
nixos-install --root /mnt -I "my=/etc/dotfiles" 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` My main host [has a README](hosts/kuro/README.org) you can use as a reference.
+ `make switch` = `nixos-rebuild switch` I set up an EFI+GPT system and partitions with `parted` and `zfs`.
+ `make upgrade` = `nix-channel --update && nixos-rebuild switch`
+ `make install` = `nixos-generate-config --root $PREFIX && nixos-install --root + **How 2 flakes?**
$PREFIX`
+ `make gc` = `nix-collect-garbage -d` (use sudo to clear system profile) 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 [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

135
bin/hey Executable file
View file

@ -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 "$@"

View file

@ -5,8 +5,7 @@
# capture) and stores it in the clipboard. # capture) and stores it in the clipboard.
tmp=$(mktemp) tmp=$(mktemp)
cleanup() { rm -f "$tmp"; } trap "rm -f '$tmp'" EXIT
trap cleanup EXIT
# Delay for long enough that we can refocus the targeted window # Delay for long enough that we can refocus the targeted window
if maim --delay=${2:-1} -us >"$tmp"; then if maim --delay=${2:-1} -us >"$tmp"; then

View file

@ -1,5 +1,10 @@
#!/usr/bin/env bash #!/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 MONITOR=$(xrandr -q | grep primary | cut -d' ' -f1)
export MONITORS=( $(xrandr -q | grep ' connected' | cut -d' ' -f1) ) export MONITORS=( $(xrandr -q | grep ' connected' | cut -d' ' -f1) )
MONITOR=${MONITOR:-${MONITORS[0]}} MONITOR=${MONITOR:-${MONITORS[0]}}

View file

@ -1,9 +1,8 @@
#!/usr/bin/env zsh #!/usr/bin/env zsh
g() { [[ $# = 0 ]] && git status --short . || git $*; } g() { [[ $# = 0 ]] && git status --short . || git $*; }
compdef g=hub
alias git='noglob hub' alias git='noglob git'
alias ga='git add' alias ga='git add'
alias gap='git add --patch' alias gap='git add --patch'
alias gb='git branch' alias gb='git branch'

View file

@ -10,7 +10,7 @@
;; :port swank::default-server-port) ;; :port swank::default-server-port)
;;; ;;;
(defvar *config-dir* "~/.dotfiles/config/stumpwm") (defvar *config-dir* "~/.config/dotfiles/config/stumpwm")
(defcommand reload-dotfiles () () (defcommand reload-dotfiles () ()
(load (concat *config-dir* "/config")) (load (concat *config-dir* "/config"))

View file

@ -25,16 +25,16 @@ super + shift + grave
emacsclient -e '(open-scratch-frame)' emacsclient -e '(open-scratch-frame)'
super + space super + space
~/.dotfiles/bin/rofi/appmenu ~/.config/dotfiles/bin/rofi/appmenu
super + Tab super + Tab
~/.dotfiles/bin/rofi/windowmenu ~/.config/dotfiles/bin/rofi/windowmenu
super + backslash super + backslash
~/.dotfiles/bin/rofi/passmenu ~/.config/dotfiles/bin/rofi/passmenu
super + slash super + slash
~/.dotfiles/bin/rofi/filemenu -x ~/.config/dotfiles/bin/rofi/filemenu -x
super + Escape super + Escape
pkill -USR1 -x sxhkd pkill -USR1 -x sxhkd
@ -52,21 +52,21 @@ super + {_,ctrl + }f
super + {_,ctrl +}{h,j,k,l} 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} 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 ## Resize by preselection
super + alt + {1-9} 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} super + alt + {h,j,k,l}
bspc node -p {west,south,north,east} bspc node -p {west,south,north,east}
super + alt + Return super + alt + Return
~/.dotfiles/bin/bspwm/subtract-presel ~/.config/dotfiles/bin/bspwm/subtract-presel
super + alt + Delete super + alt + Delete
bspc node -p cancel bspc node -p cancel

View file

@ -92,7 +92,7 @@ bind - break-pane
bind _ join-pane bind _ join-pane
# reload config without killing server # 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 bind ^r refresh-client

View file

@ -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" [ -d "$ZGEN_DIR" ] || git clone https://github.com/tarjoilija/zgen "$ZGEN_DIR"
source $ZGEN_SOURCE source $ZGEN_SOURCE
if ! zgen saved; then if ! zgen saved; then

View file

@ -20,6 +20,16 @@ alias gurl='curl --compressed'
alias y='xclip -selection clipboard -in' alias y='xclip -selection clipboard -in'
alias p='xclip -selection clipboard -out' 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 autoload -U zmv
take() { take() {

View file

@ -1,3 +1,5 @@
fpath+=( $ZDOTDIR/completions )
## Options ## Options
setopt COMPLETE_IN_WORD # Complete from both ends of a word. setopt COMPLETE_IN_WORD # Complete from both ends of a word.
setopt PATH_DIRS # Perform path search even on command names with slashes. setopt PATH_DIRS # Perform path search even on command names with slashes.

35
config/zsh/completions/_dots Executable file
View file

@ -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

View file

@ -32,7 +32,7 @@ unsetopt HUP # Don't kill jobs on shell exit.
unsetopt CHECK_JOBS # Don't report on jobs when shell exit. unsetopt CHECK_JOBS # Don't report on jobs when shell exit.
## History ## History
HISTFILE="$HOME/.cache/zhistory" HISTFILE="$XDG_CACHE_HOME/zhistory"
HISTSIZE=1000 # Max events to store in internal history. HISTSIZE=1000 # Max events to store in internal history.
SAVEHIST=1000 # Max events to store in history file. SAVEHIST=1000 # Max events to store in history file.

View file

@ -1,76 +0,0 @@
# default.nix --- the heart of my dotfiles
#
# Author: Henrik Lissner <henrik@lissner.net>
# 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?
}

96
flake.lock Normal file
View file

@ -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
}

105
flake.nix Normal file
View file

@ -0,0 +1,105 @@
# flake.nix --- the heart of my dotfiles
#
# Author: Henrik Lissner <henrik@lissner.net>
# 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
];
});
};
}

9
hosts/README.org Normal file
View file

@ -0,0 +1,9 @@
#+TITLE: Host Configurations
* Systems
+ kuro
+ shiro
+ ao
+ aka
+ aijiro
+ unlisted: 100+ linodes, 7 VMs

View file

@ -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 <modules/themes/aquanaut/zsh/prompt.zsh>;
networking.networkmanager.enable = true;
time.timeZone = "America/Toronto";
services.calibre-server.calibre-server = "/data/books";
}

View file

@ -1,32 +0,0 @@
{ config, lib, ... }:
{
imports = [
<nixpkgs/nixos/modules/installer/scan/not-detected.nix>
];
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"; }];
}

1
hosts/ao/README.org Normal file
View file

@ -0,0 +1 @@
#+TITLE: Ao

View file

@ -1,40 +1,37 @@
# Ao -- my home development and user-facing server # Ao -- my home development and user-facing server
{ pkgs, config, lib, ... }: { config, lib, ... }:
{
imports = [
../personal.nix
./hardware-configuration.nix
];
with lib.my;
{
imports = [ ./hardware-configuration.nix ];
## Modules
modules = { modules = {
shell.git.enable = true; shell.git.enable = true;
shell.zsh.enable = true; shell.zsh.enable = true;
services.ssh.enable = true; services.ssh.enable = true;
services.nginx.enable = true; # services.nginx.enable = true;
services.gitea.enable = true; # services.gitea.enable = true;
services.syncthing.enable = true; # services.syncthing.enable = true;
themes.fluorescence.enable = true;
}; };
my.zsh.rc = lib.readFile <modules/themes/aquanaut/zsh/prompt.zsh>;
## Local config
boot.loader.systemd-boot.enable = true;
networking.networkmanager.enable = true; networking.networkmanager.enable = true;
time.timeZone = "America/Toronto";
# nginx hosts # nginx hosts
services.nginx = { services.nginx = {
user = config.my.username; user = config.user.name;
virtualHosts = { virtualHosts = {
"v0.io" = { "v0.io" = {
default = true; default = true;
enableACME = true; enableACME = true;
forceSSL = true; forceSSL = true;
root = "/home/${config.my.username}/www/v0.io"; root = "${homeDir}/www/v0.io";
};
"dl.v0.io" = {
enableACME = true;
addSSL = true;
root = "/home/${config.my.username}/www/dl.v0.io";
locations."~* \.(?:ico|css|js|gif|jpe?g|png|mp4)$".extraConfig = '' locations."~* \.(?:ico|css|js|gif|jpe?g|png|mp4)$".extraConfig = ''
expires 30d; expires 30d;
add_header Pragma public; add_header Pragma public;
@ -46,55 +43,56 @@
forceSSL = true; forceSSL = true;
locations."/".proxyPass = http://127.0.0.1:3000; locations."/".proxyPass = http://127.0.0.1:3000;
}; };
"tv.v0.io" = { # "tv.v0.io" = {
http2 = true; # more performant for streaming # http2 = true; # more performant for streaming
enableACME = true; # enableACME = true;
forceSSL = true; # forceSSL = true;
extraConfig = '' # 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'"; # 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 # # Some players don't reopen a socket and playback stops totally
# instead of resuming after an extended pause # # instead of resuming after an extended pause
send_timeout 100m; # send_timeout 100m;
# Intentionally not hardened for security for player support and # # Intentionally not hardened for security for player support and
# encryption video streams has a lot of overhead with something like # # encryption video streams has a lot of overhead with something like
# AES-256-GCM-SHA384. # # 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_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; # # Forward real ip and host to Plex
ssl_stapling_verify on; # proxy_set_header Referer $server_addr;
# proxy_set_header Origin $server_addr;
# Forward real ip and host to Plex # # Security / XSS Mitigation Headers
proxy_set_header Referer $server_addr; # add_header X-Frame-Options "SAMEORIGIN";
proxy_set_header Origin $server_addr; # add_header X-XSS-Protection "1; mode=block";
# add_header X-Content-Type-Options "nosniff";
# Security / XSS Mitigation Headers # '';
add_header X-Frame-Options "SAMEORIGIN"; # # locations."= /".return = "302 https://tv.v0.io/web/index.html";
add_header X-XSS-Protection "1; mode=block"; # locations."/socket" = {
add_header X-Content-Type-Options "nosniff"; # proxyPass = "http://192.168.1.13:8096";
''; # proxyHttpVersion = "1.1";
# locations."= /".return = "302 https://tv.v0.io/web/index.html"; # # Buffering off send to the client as soon as the data is received
locations."/socket" = { # # from JellyFin.
proxyPass = "http://192.168.1.13:8096"; # proxyBuffering = "off";
proxyHttpVersion = "1.1"; # };
# Buffering off send to the client as soon as the data is received # locations."/" = {
# from JellyFin. # proxyWebsockets = true;
proxyBuffering = "off"; # proxyPass = "http://192.168.1.13:8096";
}; # };
locations."/" = { # };
proxyWebsockets = true;
proxyPass = "http://192.168.1.13:8096";
};
};
}; };
}; };
security.acme.certs = { security.acme = {
"v0.io".email = config.my.email; acceptTerms = true;
"dl.v0.io".email = config.my.email; certs = let email = "henrik@lissner.net"; in {
"git.v0.io".email = config.my.email; "v0.io".email = email;
"tv.v0.io".email = config.my.email; "git.v0.io".email = email;
# "tv.v0.io".email = email;
};
}; };
services.gitea = { services.gitea = {

View file

@ -1,13 +1,13 @@
{ config, lib, ... }: { config, lib, modulesPath, ... }:
{ {
imports = [ imports = [ (modulesPath + "/installer/scan/not-detected.nix") ];
<nixpkgs/nixos/modules/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 = {
boot.initrd.kernelModules = [ ]; initrd.availableKernelModules = [ "ohci_pci" "ehci_pci" "ahci" "firewire_ohci" "usb_storage" "usbhid" "sd_mod" "sr_mod" "sdhci_pci" ];
boot.kernelModules = [ "kvm-intel" "wl" ]; initrd.kernelModules = [ ];
boot.extraModulePackages = [ config.boot.kernelPackages.broadcom_sta ]; kernelModules = [ "kvm-intel" "wl" ];
extraModulePackages = [ config.boot.kernelPackages.broadcom_sta ];
};
## CPU ## CPU
nix.maxJobs = lib.mkDefault 2; nix.maxJobs = lib.mkDefault 2;

71
hosts/default.nix Normal file
View file

@ -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";
}

68
hosts/kuro/README.org Normal file
View file

@ -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

View file

@ -1,77 +1,79 @@
# Kuro -- my desktop { ... }:
{ pkgs, options, config, ... }:
{ {
imports = [ imports = [ ./hardware-configuration.nix ];
../personal.nix # common settings
./hardware-configuration.nix
];
## Modules
modules = { modules = {
desktop = { desktop = {
bspwm.enable = true; bspwm.enable = true;
apps = {
apps.rofi.enable = true; discord.enable = true;
apps.discord.enable = true; rofi.enable = true;
# apps.skype.enable = true; # godot.enable = true;
apps.daw.enable = true; # making music };
apps.graphics.enable = true; # raster/vector/sprites browsers = {
apps.recording.enable = true; # recording screen/audio default = "firefox";
apps.vm.enable = true; # virtualbox for testing firefox.enable = true;
};
term.default = "xst"; gaming = {
term.st.enable = true; steam.enable = true;
# emulators.enable = true;
browsers.default = "firefox"; # emulators.psx.enable = true;
browsers.firefox.enable = true; };
# browsers.qutebrowser.enable = true; media = {
# browsers.vimb.enable = true; daw.enable = true;
documents.enable = true;
# gaming.emulators.psx.enable = true; graphics.enable = true;
gaming.steam.enable = true; mpv.enable = true;
recording.enable = true;
spotify.enable = true;
};
term = {
default = "xst";
st.enable = true;
};
vm = {
qemu.enable = true;
};
}; };
editors = { editors = {
default = "nvim"; default = "emacs -nw";
emacs.enable = true; emacs.enable = true;
vim.enable = true; vim.enable = true;
}; };
hardware = {
dev = { audio.enable = true;
cc.enable = true; ergodox.enable = true;
common-lisp.enable = true; fs = {
rust.enable = true; enable = true;
node.enable = true; zfs.enable = true;
# lua.enable = true; ssd.enable = true;
# lua.love2d.enable = true;
}; };
nvidia.enable = true;
media = { sensors.enable = true;
mpv.enable = true;
spotify.enable = true;
}; };
shell = { shell = {
direnv.enable = true; direnv.enable = true;
git.enable = true; git.enable = true;
gnupg.enable = true; gnupg.enable = true;
# weechat.enable = true;
pass.enable = true; pass.enable = true;
tmux.enable = true; tmux.enable = true;
# ranger.enable = true;
zsh.enable = true; zsh.enable = true;
}; };
services = { services = {
# syncthing.enable = true; ssh.enable = true;
# docker.enable = true;
}; };
# themes.aquanaut.enable = true;
themes.fluorescence.enable = true; themes.fluorescence.enable = true;
}; };
## Local config
programs.ssh.startAgent = true; programs.ssh.startAgent = true;
boot.loader.systemd-boot.enable = true;
networking.networkmanager.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;
} }

View file

@ -1,54 +1,54 @@
{ config, pkgs, lib, ... }: { config, lib, pkgs, modulesPath, ... }:
{ {
imports = [ imports = [ "${modulesPath}/installer/scan/not-detected.nix" ];
<nixpkgs/nixos/modules/installer/scan/not-detected.nix>
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"
];
};
boot.initrd.availableKernelModules = [ "xhci_pci" "ehci_pci" "ahci" "usbhid" "uas" "usb_storage" "sd_mod" ]; # CPU
boot.initrd.kernelModules = [ ]; nix.maxJobs = lib.mkDefault 16;
boot.kernelModules = [ "kvm-intel" ];
boot.extraModulePackages = [ ];
## CPU
nix.maxJobs = lib.mkDefault 8;
powerManagement.cpuFreqGovernor = "performance"; powerManagement.cpuFreqGovernor = "performance";
hardware.cpu.intel.updateMicrocode = true; hardware.cpu.amd.updateMicrocode = true;
## SSDs # Displays
services.fstrim.enable = true; 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 # Storage
my.packages = [ pkgs.teensy-loader-cli ]; networking.hostId = "edd9f26b"; # required by zfs
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
fileSystems = { fileSystems = {
"/" = { "/" = {
device = "/dev/disk/by-label/nixos"; device = "/dev/disk/by-label/nixos";
@ -59,21 +59,27 @@
device = "/dev/disk/by-label/BOOT"; device = "/dev/disk/by-label/BOOT";
fsType = "vfat"; fsType = "vfat";
}; };
"/mnt/projects" = { "/home" = {
device = "/dev/disk/by-label/projects"; device = "/dev/disk/by-label/home";
fsType = "ext4"; fsType = "ext4";
options = [ "noatime" ]; options = [ "noatime" ];
}; };
"/mnt/archive" = { "/usr/backup" = {
device = "/dev/disk/by-label/archive"; device = "usr/backup";
fsType = "ext4"; fsType = "zfs";
options = [ "noatime" ];
}; };
"/mnt/local" = { "/usr/media" = {
device = "/dev/disk/by-label/local"; device = "usr/media";
fsType = "ext4"; fsType = "zfs";
options = [ "noatime" ]; };
"/usr/local" = {
device = "usr/local";
fsType = "zfs";
};
"/usr/share" = {
device = "usr/share";
fsType = "zfs";
}; };
}; };
swapDevices = [ { device = "/dev/disk/by-label/swap"; } ]; swapDevices = [];
} }

View file

@ -14,10 +14,8 @@
# curl $url | dd of=/dev/sda # curl $url | dd of=/dev/sda
# #
# 4. Install these dotfiles with # 4. Install these dotfiles with
# git clone https://github.com/hlissner/dotfiles ~/.dotfiles # git clone https://github.com/hlissner/dotfiles ~/.config/dotfiles
# ln -s ~/.dotfiles /etc/dotfiles # nixos-install --root "$(PREFIX)" --flake ~/.config/dotfiles#linode
# cd ~/.dotfiles
# mk install-linode
# #
# 4. Create a configuration profile: # 4. Create a configuration profile:
# - Kernel: GRUB 2 # - Kernel: GRUB 2
@ -28,16 +26,27 @@
# 5. Reboot into profile. # 5. Reboot into profile.
{ config, lib, pkgs, ... }: { config, lib, pkgs, ... }:
let
inherit (lib) filter pathExists;
in
{ {
imports = filter pathExists ["/etc/nixos/configuration.nix"];
environment.systemPackages = environment.systemPackages =
with pkgs; [ inetutils mtr sysstat git ]; with pkgs; [ inetutils mtr sysstat git ];
imports = [ modules = {
<modules/editors/vim.nix> # editors = {
<modules/shell/git.nix> # default = "nvim";
<modules/shell/zsh.nix> # vim.enable = true;
<modules/services/ssh.nix> # };
]; shell = {
# git.enable = true;
zsh.enable = true;
};
services.ssh.enable = true;
};
# GRUB # GRUB
boot = { boot = {
@ -58,7 +67,9 @@
}; };
}; };
networking.useDHCP = false; networking = {
networking.usePredictableInterfaceNames = false; useDHCP = false;
networking.interfaces.eth0.useDHCP = true; usePredictableInterfaceNames = false;
interfaces.eth0.useDHCP = true;
};
} }

View file

@ -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
'';
}

9
hosts/shiro/README.org Normal file
View file

@ -0,0 +1,9 @@
#+TITLE: Shiro
#+DATE: September 13, 2020
* Overview
* Specs
Dell 13" 9370
* Installation

View file

@ -1,40 +1,43 @@
# Shiro -- my laptop # Shiro -- my laptop
{ pkgs, ... }: { ... }:
{ {
imports = [ imports = [ ./hardware-configuration.nix ];
../personal.nix # common settings
./hardware-configuration.nix
];
## Modules
modules = { modules = {
desktop = { desktop = {
bspwm.enable = true; bspwm.enable = true;
apps = {
apps.rofi.enable = true; discord.enable = true;
apps.discord.enable = true; rofi.enable = true;
# apps.skype.enable = true; # skype.enable = true;
apps.daw.enable = true; # making music };
apps.graphics.enable = true; # raster/vector/sprites browsers = {
apps.recording.enable = true; # recording screen/audio default = "firefox";
# apps.vm.enable = true; # virtualbox for testing firefox.enable = true;
};
term.default = "xst"; media = {
term.st.enable = true; # daw.enable = true;
documents.enable = true;
browsers.default = "firefox"; graphics.enable = true;
browsers.firefox.enable = true; mpv.enable = true;
recording.enable = true;
# gaming.emulators.psx.enable = true; spotify.enable = true;
# gaming.steam.enable = true; };
term = {
default = "xst";
st.enable = true;
};
vm = {
# virtualbox.enable = true;
};
}; };
editors = { editors = {
default = "nvim"; default = "emacs -nw";
emacs.enable = true; emacs.enable = true;
vim.enable = true; vim.enable = true;
}; };
dev = { dev = {
# cc.enable = true; # cc.enable = true;
# common-lisp.enable = true; # common-lisp.enable = true;
@ -42,12 +45,13 @@
# lua.enable = true; # lua.enable = true;
# lua.love2d.enable = true; # lua.love2d.enable = true;
}; };
hardware = {
media = { audio.enable = true;
mpv.enable = true; fs = {
spotify.enable = true; enable = true;
ssd.enable = true;
};
}; };
shell = { shell = {
direnv.enable = true; direnv.enable = true;
git.enable = true; git.enable = true;
@ -58,25 +62,23 @@
# ranger.enable = true; # ranger.enable = true;
zsh.enable = true; zsh.enable = true;
}; };
hardware = {
services = {
syncthing.enable = true;
}; };
services = {
# themes.aquanaut.enable = true; # syncthing.enable = true;
ssh.enable = true;
};
themes.fluorescence.enable = true; themes.fluorescence.enable = true;
}; };
## Local config
programs.ssh.startAgent = true; programs.ssh.startAgent = true;
boot.loader.systemd-boot.enable = true;
networking.wireless.enable = true; networking.wireless.enable = true;
hardware.opengl.enable = true; hardware.opengl.enable = true;
time.timeZone = "America/Toronto";
# time.timeZone = "Europe/Copenhagen"; # time.timeZone = "Europe/Copenhagen";
# Optimize power use
environment.systemPackages = [ pkgs.acpi ];
powerManagement.powertop.enable = true;
# Monitor backlight control
programs.light.enable = true;
} }

View file

@ -1,30 +1,37 @@
# Do not modify this file! It was generated by nixos-generate-config # Do not modify this file! It was generated by nixos-generate-config
# and may be overwritten by future invocations. Please make changes # and may be overwritten by future invocations. Please make changes
# to /etc/nixos/configuration.nix instead. # to /etc/nixos/configuration.nix instead.
{ config, lib, pkgs, ... }: { config, lib, pkgs, inputs, modulesPath, ... }:
{ {
imports = [ imports = [
<nixpkgs/nixos/modules/installer/scan/not-detected.nix> (modulesPath + "/installer/scan/not-detected.nix")
(let nixos-hardware = inputs.nixos-hardware.nixosModules.dell-xps-13-9370
builtins.fetchTarball
https://github.com/NixOS/nixos-hardware/archive/master.tar.gz;
in "${nixos-hardware}/dell/xps/13-9370")
]; ];
boot.initrd.availableKernelModules = [ "xhci_pci" "nvme" "rtsx_pci_sdmmc" ]; boot = {
boot.initrd.kernelModules = [ "dm-snapshot" ]; initrd.availableKernelModules = [ "xhci_pci" "nvme" "rtsx_pci_sdmmc" ];
boot.kernelModules = [ "kvm-intel" ]; initrd.kernelModules = [ "dm-snapshot" ];
boot.extraModulePackages = [ ]; 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; nix.maxJobs = lib.mkDefault 8;
powerManagement.cpuFreqGovernor = lib.mkDefault "powersave"; powerManagement.cpuFreqGovernor = lib.mkDefault "ondemand";
hardware.cpu.intel.updateMicrocode = true; hardware.cpu.intel.updateMicrocode = true;
## SSDs # Power management
# services.fstrim.enable = true; environment.systemPackages = [ pkgs.acpi ];
powerManagement.powertop.enable = true;
programs.light.enable = true; # Monitor backlight control
# Storage
fileSystems = { fileSystems = {
"/" = { "/" = {
device = "/dev/disk/by-label/nixos"; device = "/dev/disk/by-label/nixos";
@ -42,7 +49,7 @@
}; };
}; };
swapDevices = [ { device = "/dev/disk/by-label/swap"; }]; swapDevices = [ { device = "/dev/disk/by-label/swap"; }];
# Encrypted /home
boot.initrd.luks.devices.home = { boot.initrd.luks.devices.home = {
device = "/dev/nvme0n1p8"; device = "/dev/nvme0n1p8";
preLVM = true; preLVM = true;

26
lib/attrs.nix Normal file
View file

@ -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);
}

18
lib/default.nix Normal file
View file

@ -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))

53
lib/modules.nix Normal file
View file

@ -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;
}

18
lib/options.nix Normal file
View file

@ -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;
};
}

15
lib/paths.nix Normal file
View file

@ -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}";
}

View file

@ -1,96 +0,0 @@
{ config, options, lib, ... }:
with lib;
let mkOptionStr = value: mkOption
{ type = types.str;
default = value; };
in {
imports = [
<home-manager/nixos>
./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 = [ <bin> "$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};
'';
};
};
}

View file

@ -1,13 +0,0 @@
{ config, lib, pkgs, ... }:
{
imports = [
./daw.nix
./discord.nix
./graphics.nix
./recording.nix
./rofi.nix
./skype.nix
./vm.nix
];
}

View file

@ -1,17 +1,20 @@
{ config, options, lib, pkgs, ... }: { config, options, lib, pkgs, ... }:
with lib; with lib;
{ with lib.my;
let cfg = config.modules.desktop.apps.discord;
in {
options.modules.desktop.apps.discord = { options.modules.desktop.apps.discord = {
enable = mkOption { enable = mkBoolOpt false;
type = types.bool;
default = false;
};
}; };
config = mkIf config.modules.desktop.apps.discord.enable { config = mkIf cfg.enable {
my.packages = with pkgs; [ user.packages = with pkgs; [
discord # If not installed from unstable, Discord will sometimes soft-lock itself
# ripcord # on a "there's an update for discord" screen.
unstable.discord
# unstable.ripcord
]; ];
}; };
} }

View file

@ -4,17 +4,17 @@
# but to prototype (for 3D, mainly) I'll occasionally reach for godot. # but to prototype (for 3D, mainly) I'll occasionally reach for godot.
{ config, options, lib, pkgs, ... }: { config, options, lib, pkgs, ... }:
with lib; with lib;
{ with lib.my;
options.modules.dev.godot = { let cfg = config.modules.desktop.apps.godot;
enable = mkOption { in {
type = types.bool; options.modules.desktop.apps.godot = {
default = false; enable = mkBoolOpt false;
};
}; };
config = mkIf config.modules.dev.godot.enable { config = mkIf cfg.enable {
my.packages = with pkgs; [ user.packages = with pkgs; [
godot godot
]; ];
}; };

View file

@ -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 = <config/gimp>; recursive = true; };
};
};
}

View file

@ -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 []);
};
}

View file

@ -1,36 +1,34 @@
{ config, options, lib, pkgs, ... }: { config, options, lib, pkgs, ... }:
with lib; with lib;
{ with lib.my;
let cfg = config.modules.desktop.apps.rofi;
in {
options.modules.desktop.apps.rofi = { options.modules.desktop.apps.rofi = {
enable = mkOption { enable = mkBoolOpt false;
type = types.bool;
default = false;
};
}; };
config = mkIf config.modules.desktop.apps.rofi.enable { config = mkIf cfg.enable {
my = {
# link recursively so other modules can link files in its folder # link recursively so other modules can link files in its folder
# home.xdg.configFile."rofi" = { # home.xdg.configFile."rofi" = {
# source = <config/rofi>; # source = <config/rofi>;
# recursive = true; # recursive = true;
# }; # };
packages = with pkgs; [ user.packages = with pkgs; [
(writeScriptBin "rofi" '' (writeScriptBin "rofi" ''
#!${stdenv.shell} #!${stdenv.shell}
exec ${rofi}/bin/rofi -terminal xst -m -1 "$@" exec ${pkgs.rofi}/bin/rofi -terminal xst -m -1 "$@"
'') '')
# For rapidly test changes to rofi's stylesheets # For rapidly test changes to rofi's stylesheets
# (writeScriptBin "rofi-test" '' # (writeScriptBin "rofi-test" ''
# #!${stdenv.shell} # #!${stdenv.shell}
# themefile=$1 # themefile=$1
# themename=${modules.theme.name} # themename=${my.theme.name}
# shift # shift
# exec rofi \ # exec rofi \
# -theme ~/.dotfiles/modules/themes/$themename/rofi/$themefile \ # -theme ${themeDir}/$themename/rofi/$themefile \
# "$@" # "$@"
# '') # '')
@ -39,28 +37,27 @@ with lib;
name = "rofi-bookmarkmenu"; name = "rofi-bookmarkmenu";
desktopName = "Open Bookmark in Browser"; desktopName = "Open Bookmark in Browser";
icon = "bookmark-new-symbolic"; icon = "bookmark-new-symbolic";
exec = "${<bin/rofi/bookmarkmenu>}"; exec = "${binDir}/rofi/bookmarkmenu";
}) })
(makeDesktopItem { (makeDesktopItem {
name = "rofi-filemenu"; name = "rofi-filemenu";
desktopName = "Open Directory in Terminal"; desktopName = "Open Directory in Terminal";
icon = "folder"; icon = "folder";
exec = "${<bin/rofi/filemenu>}"; exec = "${binDir}/rofi/filemenu";
}) })
(makeDesktopItem { (makeDesktopItem {
name = "rofi-filemenu-scratch"; name = "rofi-filemenu-scratch";
desktopName = "Open Directory in Scratch Terminal"; desktopName = "Open Directory in Scratch Terminal";
icon = "folder"; icon = "folder";
exec = "${<bin/rofi/filemenu>} -x"; exec = "${binDir}/rofi/filemenu -x";
}) })
(makeDesktopItem { (makeDesktopItem {
name = "lock-display"; name = "lock-display";
desktopName = "Lock screen"; desktopName = "Lock screen";
icon = "system-lock-screen"; icon = "system-lock-screen";
exec = "${<bin/zzz>}"; exec = "${binDir}/zzz";
}) })
]; ];
}; };
};
} }

View file

@ -1,15 +1,15 @@
{ config, options, lib, pkgs, ... }: { config, options, lib, pkgs, ... }:
with lib; with lib;
{ with lib.my;
let cfg = config.modules.desktop.apps.skype;
in {
options.modules.desktop.apps.skype = { options.modules.desktop.apps.skype = {
enable = mkOption { enable = mkEnableOption false;
type = types.bool;
default = false;
};
}; };
config = mkIf config.modules.desktop.apps.skype.enable { config = mkIf cfg.enable {
my.packages = with pkgs; [ user.packages = with pkgs; [
skypeforlinux skypeforlinux
skype_call_recorder skype_call_recorder
]; ];

View file

@ -3,17 +3,17 @@
# I don't use Unity often, but when I do, it's in a team or with students. # I don't use Unity often, but when I do, it's in a team or with students.
{ config, options, lib, pkgs, ... }: { config, options, lib, pkgs, ... }:
with lib; with lib;
{ with lib.my;
options.modules.dev.unity3d = { let cfg = config.modules.desktop.apps.unity3d;
enable = mkOption { in {
type = types.bool; options.modules.desktop.apps.unity3d = {
default = false; enable = mkBoolOpt false;
};
}; };
config = mkIf config.modules.dev.unity3d.enable { config = mkIf cfg.enable {
my.packages = with pkgs; [ user.packages = with pkgs; [
unity3d unity3d
]; ];
}; };

View file

@ -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" ];
};
}

View file

@ -1,21 +1,14 @@
{ config, lib, pkgs, ... }: { options, config, lib, pkgs, ... }:
with lib; with lib;
{ with lib.my;
imports = [ let cfg = config.modules.desktop.browsers;
./firefox.nix in {
./qutebrowser.nix
./vimb.nix
./vivaldi.nix
];
options.modules.desktop.browsers = { options.modules.desktop.browsers = {
default = mkOption { default = mkOpt (with types; nullOr str) null;
type = with types; nullOr str;
default = null;
};
}; };
config = mkIf (config.modules.desktop.browsers.default != null) { config = mkIf (cfg.default != null) {
my.env.BROWSER = config.modules.desktop.browsers.default; env.BROWSER = cfg.default;
}; };
} }

View file

@ -3,22 +3,30 @@
# Oh firefox, gateway to the interwebs, devourer of ram. Give onto me your # Oh firefox, gateway to the interwebs, devourer of ram. Give onto me your
# infinite knowledge and shelter me from ads. # infinite knowledge and shelter me from ads.
{ config, options, lib, pkgs, ... }: { options, config, lib, pkgs, ... }:
with lib; with lib;
{ with lib.my;
options.modules.desktop.browsers.firefox = { let cfg = config.modules.desktop.browsers.firefox;
enable = mkOption { in {
type = types.bool; options.modules.desktop.browsers.firefox = with types; {
default = false; enable = mkBoolOpt false;
}; profileName = mkOpt types.str config.user.name;
profileName = mkOption {
type = types.str; settings = mkOpt' (attrsOf (oneOf [ bool int str ])) {} ''
default = config.my.username; Firefox preferences to set in <filename>user.js</filename>
}; '';
extraConfig = mkOpt' lines "" ''
Extra preferences to dd to <filename>user.js</filename>
'';
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 { config = mkIf cfg.enable (mkMerge [
my.packages = with pkgs; [ {
user.packages = with pkgs; [
firefox-bin firefox-bin
(makeDesktopItem { (makeDesktopItem {
name = "firefox-private"; name = "firefox-private";
@ -30,13 +38,93 @@ with lib;
}) })
]; ];
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/";
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 <a> 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 # Use a stable profile name so we can target it in themes
my.home.home.file = home.file = let cfgPath = ".mozilla/firefox"; in {
let cfg = config.modules.desktop.browsers.firefox; in "${cfgPath}/profiles.ini".text = ''
{
".mozilla/firefox/profiles.ini".text = ''
[Profile0] [Profile0]
Name=default Name=default
IsRelative=1 IsRelative=1
@ -47,6 +135,27 @@ with lib;
StartWithLastProfile=1 StartWithLastProfile=1
Version=2 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;
}; };
}; };
}
]);
} }

View file

@ -3,18 +3,19 @@
# Qutebrowser is cute because it's not enough of a browser to be handsome. # 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. # 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;
{ with lib.my;
let cfg = config.modules.desktop.browsers.qutebrowser;
in {
options.modules.desktop.browsers.qutebrowser = { options.modules.desktop.browsers.qutebrowser = {
enable = mkOption { enable = mkBoolOpt false;
type = types.bool; userStyles = mkOpt types.lines "";
default = false;
};
}; };
config = mkIf config.modules.desktop.browsers.qutebrowser.enable { config = mkIf cfg.enable {
my.packages = with pkgs; [ user.packages = with pkgs; [
qutebrowser qutebrowser
(makeDesktopItem { (makeDesktopItem {
name = "qutebrowser-private"; name = "qutebrowser-private";
@ -25,9 +26,13 @@ with lib;
categories = "Network"; categories = "Network";
}) })
]; ];
my.home.xdg.configFile."qutebrowser" = {
source = <config/qutebrowser>; home = {
configFile."qutebrowser" = {
source = "${configDir}/qutebrowser";
recursive = true; recursive = true;
}; };
dataFile."qutebrowser/userstyles.css".text = userStyles;
};
}; };
} }

View file

@ -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";
})
];
};
}

View file

@ -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";
})
];
};
}

View file

@ -1,15 +1,14 @@
{ config, options, lib, pkgs, ... }: { options, config, lib, pkgs, ... }:
with lib;
{
imports = [
./common.nix
];
with lib;
with lib.my;
let cfg = config.modules.desktop.bspwm;
in {
options.modules.desktop.bspwm = { 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; [ environment.systemPackages = with pkgs; [
lightdm lightdm
dunst dunst
@ -25,18 +24,29 @@ with lib;
redshift.enable = true; redshift.enable = true;
xserver = { xserver = {
enable = true; enable = true;
displayManager.defaultSession = "none+bspwm"; displayManager = {
displayManager.lightdm.enable = true; defaultSession = "none+bspwm";
displayManager.lightdm.greeters.mini.enable = true; lightdm.enable = true;
lightdm.greeters.mini.enable = true;
};
windowManager.bspwm.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 # link recursively so other modules can link files in their folders
my.home.xdg.configFile = { home.configFile = {
"sxhkd".source = <config/sxhkd>; "sxhkd".source = "${configDir}/sxhkd";
"bspwm" = { "bspwm" = {
source = <config/bspwm>; source = "${configDir}/bspwm";
recursive = true; recursive = true;
}; };
}; };

View file

@ -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/*
'';
}

View file

@ -1,13 +1,140 @@
{ config, lib, pkgs, ... }: { config, options, lib, pkgs, ... }:
{ with lib;
imports = [ with lib.my;
./bspwm.nix let cfg = config.modules.desktop;
# ./stumpwm.nix in {
config = mkIf config.services.xserver.enable {
./apps assertions = [
./term {
./browsers assertion = (countAttrs (n: v: n == "enable" && value) cfg) < 2;
./gaming 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";
}
]; ];
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
'';
};
} }

View file

@ -1,9 +0,0 @@
{ config, lib, pkgs, ... }:
{
imports = [
./emulators.nix
./factorio.nix
./steam.nix
];
}

View file

@ -1,27 +1,25 @@
{ config, options, lib, pkgs, ... }: { options, config, lib, pkgs, ... }:
with lib; with lib;
{ with lib.my;
options.modules.desktop.gaming.emulators = let cfg = config.modules.desktop.gaming.emulators;
let mkBoolDefault = bool: mkOption { in {
type = types.bool; options.modules.desktop.gaming.emulators = {
default = bool; psx.enable = mkBoolOpt false; # Playstation
}; ds.enable = mkBoolOpt false; # Nintendo DS
in { gb.enable = mkBoolOpt false; # GameBoy + GameBoy Color
psx.enable = mkBoolDefault false; # Playstation gba.enable = mkBoolOpt false; # GameBoy Advance
ds.enable = mkBoolDefault false; # Nintendo DS snes.enable = mkBoolOpt false; # Super Nintendo
gb.enable = mkBoolDefault false; # GameBoy + GameBoy Color
gba.enable = mkBoolDefault false; # GameBoy Advance
snes.enable = mkBoolDefault false; # Super Nintendo
}; };
config = let emu = config.modules.desktop.gaming.emulators; in { config = {
my.packages = with pkgs; user.packages = with pkgs; [
(if emu.psx.enable then [ epsxe ] else []) ++ (mkIf cfg.psx.enable epsxe)
(if emu.ds.enable then [ desume ] else []) ++ (mkIf cfg.ds.enable desmume)
(if (emu.gba.enable || (mkIf (cfg.gba.enable ||
emu.gb.enable || cfg.gb.enable ||
emu.snes.enable) cfg.snes.enable)
then [ higan ] else []); higan)
];
}; };
} }

View file

@ -1,30 +1,53 @@
{ config, options, lib, pkgs, ... }: { options, config, lib, pkgs, ... }:
with lib; with lib;
{ with lib.my;
options.modules.desktop.gaming.steam = { let cfg = config.modules.desktop.gaming.steam;
enable = mkOption { in {
type = types.bool; options.modules.desktop.gaming.steam = with types; {
default = false; enable = mkBoolOpt false;
}; hardware.enable = mkBoolOpt false;
libDir = mkOpt str "$XDG_DATA_HOME/steamlib";
}; };
config = mkIf config.modules.desktop.gaming.steam.enable { config = mkIf cfg.enable (mkMerge [
my.packages = with pkgs; [ {
# 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;
user.packages = with pkgs; [
# Get steam to keep its garbage out of $HOME # Get steam to keep its garbage out of $HOME
(writeScriptBin "steam" '' (writeScriptBin "steam" ''
#!${stdenv.shell} #!${stdenv.shell}
HOME="$XDG_DATA_HOME/steamlib" exec ${steam}/bin/steam "$@" HOME="${cfg.libDir}" exec ${steam}/bin/steam "$@"
'') '')
# for GOG and humblebundle games # for running GOG and humble bundle games
(writeScriptBin "steam-run" '' (writeScriptBin "steam-run" ''
#!${stdenv.shell} #!${stdenv.shell}
HOME="$XDG_DATA_HOME/steamlib" exec ${steam-run-native}/bin/steam-run "$@" HOME="${cfg.libDir}" exec ${steam-run-native}/bin/steam-run "$@"
'') '')
xboxdrv # driver for 360 controller # 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}"'';
hardware.opengl.driSupport32Bit = true; # better for steam proton games
hardware.pulseaudio.support32Bit = true; systemd.extraConfig = "DefaultLimitNOFILE=1048576";
}; }
(mkIf cfg.hardware.enable {
hardware.steam-hardware.enable = true;
})
]);
} }

View file

@ -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 # 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 # off of Fruityloops. When I'm in the mood for a quicky I fire up sunvox
@ -6,17 +6,17 @@
# ever need to. # ever need to.
{ config, options, lib, pkgs, ... }: { config, options, lib, pkgs, ... }:
with lib; with lib;
{ with lib.my;
options.modules.desktop.apps.daw = { let cfg = config.modules.desktop.media.daw;
enable = mkOption { in {
type = types.bool; options.modules.desktop.media.daw = {
default = false; enable = mkBoolOpt false;
};
}; };
config = mkIf config.modules.desktop.apps.daw.enable { config = mkIf cfg.enable {
my.packages = with pkgs; [ user.packages = with pkgs; [
# lmms on stable is broken due to 'Could not find the Qt platform plugin # lmms on stable is broken due to 'Could not find the Qt platform plugin
# "xcb" in ""' error: https://github.com/NixOS/nixpkgs/issues/76074 # "xcb" in ""' error: https://github.com/NixOS/nixpkgs/issues/76074
unstable.lmms # for making music unstable.lmms # for making music

View file

@ -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
};
}

View file

@ -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; };
};
};
}

View file

@ -1,15 +1,15 @@
{ config, options, lib, pkgs, ... }: { config, options, lib, pkgs, ... }:
with lib; with lib;
{ with lib.my;
options.modules.media.mpv = { let cfg = config.modules.desktop.media.mpv;
enable = mkOption { in {
type = types.bool; options.modules.desktop.media.mpv = {
default = false; enable = mkBoolOpt false;
};
}; };
config = mkIf config.modules.media.mpv.enable { config = mkIf cfg.enable {
my.packages = with pkgs; [ user.packages = with pkgs; [
mpv-with-scripts mpv-with-scripts
mpvc # CLI controller for mpv mpvc # CLI controller for mpv
(mkIf config.services.xserver.enable (mkIf config.services.xserver.enable

View file

@ -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";
};
};
}

View file

@ -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 []);
};
}

View file

@ -2,38 +2,39 @@
# local music; most of which I haven't heard or don't even like. # local music; most of which I haven't heard or don't even like.
{ config, options, lib, pkgs, ... }: { config, options, lib, pkgs, ... }:
with lib; with lib;
{ with lib.my;
options.modules.media.spotify = { let cfg = config.modules.desktop.media.spotify;
enable = mkOption { in {
type = types.bool; options.modules.desktop.media.spotify = {
default = false; enable = mkBoolOpt false;
}; tui.enable = mkBoolOpt false; # TODO
}; };
config = mkIf config.modules.media.spotify.enable { config = mkIf cfg.enable {
my.packages = with pkgs; [ 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 + # # 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 # # spotify-tui solution. The dbus interface doesn't work, though, so we
# # have to wait for spotify-tui to implement CLI command for controlling # # have to wait for spotify-tui to implement CLI command for controlling
# # spotify playback. See # # spotify playback. See
# # https://github.com/Rigellute/spotify-tui/issues/147 or for spotifyd to # # https://github.com/Rigellute/spotify-tui/issues/147 or for spotifyd to
# # get fixed. # # get fixed.
# unstable.spotifyd # master.spotifyd
# (writeScriptBin "spt" '' # (writeScriptBin "spt" ''
# #!${stdenv.shell} # #!${stdenv.shell}
# if ! systemctl --user is-active spotifyd >/dev/null; then # if ! systemctl --user is-active spotifyd >/dev/null; then
# systemctl --user start spotifyd # systemctl --user start spotifyd
# fi # fi
# echo $TMUX >/tmp/spt.tmux # 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 # # 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. # # use tmux for my terminal, may as well exploit tmux to control spotify.
# playerctl # playerctl
@ -84,11 +85,11 @@ with lib;
# password_cmd = ${pkgs.pass}/bin/pass www/spotify.com | head -n1 # password_cmd = ${pkgs.pass}/bin/pass www/spotify.com | head -n1
# backend = pulseaudio # backend = pulseaudio
# on_song_change_hook = spt-send-notify # on_song_change_hook = spt-send-notify
# cache_path = /home/${config.my.username}/.cache/spotifyd # cache_path = ${config.my.home}/.cache/spotifyd
# ''; # '';
# in { # in {
# ExecStart = '' # ExecStart = ''
# ${pkgs.unstable.spotifyd}/bin/spotifyd --no-daemon \ # ${pkgs.master.spotifyd}/bin/spotifyd --no-daemon \
# --cache-path /tmp/spotifyd \ # --cache-path /tmp/spotifyd \
# --config-path ${spotifydConf} # --config-path ${spotifydConf}
# ''; # '';

View file

@ -1,17 +1,21 @@
{ config, lib, pkgs, ... }: { options, config, lib, pkgs, ... }:
{ with lib;
imports = [ with lib.my;
./common.nix let cfg = config.modules.desktop.stumpwm;
]; in {
options.modules.desktop.stumpwm = {
enable = mkBoolOpt false;
};
config = mkIf cfg.enable {
environment.systemPackages = with pkgs; [ environment.systemPackages = with pkgs; [
lightdm lightdm
dunst dunst
libnotify libnotify
]; ];
# unstable.services.picom.enable = true; # master.services.picom.enable = true;
services = { services = {
redshift.enable = true; redshift.enable = true;
xserver = { xserver = {
@ -24,8 +28,9 @@
}; };
# link recursively so other modules can link files in their folders # link recursively so other modules can link files in their folders
my.home.xdg.configFile."stumpwm" = { home.configFile."stumpwm" = {
source = <config/stumpwm>; source = "${configDir}/stumpwm";
recursive = true; recursive = true;
}; };
};
} }

View file

@ -1,23 +1,16 @@
{ config, options, lib, pkgs, ... }: { options, config, lib, pkgs, ... }:
with lib;
{
imports = [
# ./alacritty.nix
./st.nix
# ./urxvt.nix
];
with lib;
with lib.my;
let cfg = config.modules.desktop.term;
in {
options.modules.desktop.term = { options.modules.desktop.term = {
default = mkOption { default = mkOpt types.str "xterm";
type = types.str;
default = "xterm";
};
}; };
config = { config = {
services.xserver.desktopManager.xterm.enable = services.xserver.desktopManager.xterm.enable = mkDefault (cfg.default == "xterm");
config.modules.desktop.term.default == "xterm";
my.env.TERMINAL = config.modules.editors.default; env.TERMINAL = cfg.default;
}; };
} }

View file

@ -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;
{ with lib.my;
let cfg = config.modules.desktop.term.st;
in {
options.modules.desktop.term.st = { options.modules.desktop.term.st = {
enable = mkOption { enable = mkBoolOpt false;
type = types.bool;
default = 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 # 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 xst # st + nice-to-have extensions
(makeDesktopItem { (makeDesktopItem {
name = "xst"; name = "xst";

View file

@ -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
'')
];
};
}

View file

@ -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

View file

@ -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" ];
};
}

View file

@ -5,17 +5,17 @@
# tell anyone pls. # tell anyone pls.
{ config, options, lib, pkgs, ... }: { config, options, lib, pkgs, ... }:
with lib; with lib;
{ with lib.my;
let cfg = config.modules.dev.cc;
in {
options.modules.dev.cc = { options.modules.dev.cc = {
enable = mkOption { enable = mkBoolOpt false;
type = types.bool;
default = false;
};
}; };
config = mkIf config.modules.dev.cc.enable { config = mkIf cfg.enable {
my.packages = with pkgs; [ user.packages = with pkgs; [
clang clang
gcc gcc
bear bear

View file

@ -2,18 +2,18 @@
# #
# I don't use clojure. Perhaps one day... # I don't use clojure. Perhaps one day...
{ config, options, lib, pkgs, ... }: { config, options, lib, pkgs, my, ... }:
with lib; with lib;
{ with lib.my;
let cfg = config.modules.dev.clojure;
in {
options.modules.dev.clojure = { options.modules.dev.clojure = {
enable = mkOption { enable = mkBoolOpt false;
type = types.bool;
default = false;
};
}; };
config = mkIf config.modules.dev.clojure.enable { config = mkIf cfg.enable {
my.packages = with pkgs; [ user.packages = with pkgs; [
clojure clojure
joker joker
leiningen leiningen

View file

@ -3,17 +3,17 @@
# Mostly for my stumpwm config, and the occasional dip into lisp gamedev. # Mostly for my stumpwm config, and the occasional dip into lisp gamedev.
{ config, options, lib, pkgs, ... }: { config, options, lib, pkgs, ... }:
with lib; with lib;
{ with lib.my;
let cfg = config.modules.dev.common-lisp;
in {
options.modules.dev.common-lisp = { options.modules.dev.common-lisp = {
enable = mkOption { enable = mkBoolOpt false;
type = types.bool;
default = false;
};
}; };
config = mkIf config.modules.dev.common-lisp.enable { config = mkIf cfg.enable {
my.packages = with pkgs; [ user.packages = with pkgs; [
sbcl sbcl
lispPackages.quicklisp lispPackages.quicklisp
]; ];

View file

@ -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 = {};
}

View file

@ -6,24 +6,21 @@
# on a per-project basis. # on a per-project basis.
{ config, options, lib, pkgs, ... }: { config, options, lib, pkgs, ... }:
with lib; with lib;
{ with lib.my;
let cfg = config.modules.dev.lua;
in {
options.modules.dev.lua = { options.modules.dev.lua = {
enable = mkOption { enable = mkBoolOpt false;
type = types.bool; love2D.enable = mkBoolOpt false;
default = false;
};
}; };
config = mkIf config.modules.dev.lua.enable { config = mkIf cfg.enable {
my = { user.packages = with pkgs; [
packages = with pkgs; [
lua lua
luaPackages.moonscript luaPackages.moonscript
luarocks (mkIf cfg.love2D.enable love2d)
]; ];
zsh.rc = ''eval "$(luarocks path --bin)"'';
};
}; };
} }

View file

@ -4,18 +4,17 @@
# disaster" languages. # disaster" languages.
{ config, options, lib, pkgs, ... }: { config, options, lib, pkgs, ... }:
with lib; with lib;
{ with lib.my;
let cfg = config.modules.dev.node;
in {
options.modules.dev.node = { options.modules.dev.node = {
enable = mkOption { enable = mkBoolOpt false;
type = types.bool;
default = false;
};
}; };
config = mkIf config.modules.dev.node.enable { config = mkIf cfg.enable {
my = { user.packages = with pkgs; [
packages = with pkgs; [
nodejs nodejs
yarn yarn
]; ];
@ -28,13 +27,14 @@ with lib;
env.PATH = [ "$(yarn global bin)" ]; env.PATH = [ "$(yarn global bin)" ];
# Run locally installed bin-script, e.g. n coffee file.coffee # Run locally installed bin-script, e.g. n coffee file.coffee
alias.n = "PATH=\"$(npm bin):$PATH\""; environment.shellAliases = {
alias.ya = "yarn"; n = "PATH=\"$(npm bin):$PATH\"";
ya = "yarn";
};
home.xdg.configFile."npm/config".text = '' home.configFile."npm/config".text = ''
cache=$XDG_CACHE_HOME/npm cache=$XDG_CACHE_HOME/npm
prefix=$XDG_DATA_HOME/npm prefix=$XDG_DATA_HOME/npm
''; '';
}; };
};
} }

View file

@ -4,19 +4,18 @@
# me. The Py2->3 transition make trainwrecks jealous. But SciPy, NumPy, iPython # me. The Py2->3 transition make trainwrecks jealous. But SciPy, NumPy, iPython
# and Jupyter can have my babies. Every single one. # and Jupyter can have my babies. Every single one.
{ config, options, lib, pkgs, ... }: { config, options, lib, pkgs, my, ... }:
with lib; with lib;
{ with lib.my;
let cfg = config.modules.dev.python;
in {
options.modules.dev.python = { options.modules.dev.python = {
enable = mkOption { enable = mkBoolOpt false;
type = types.bool;
default = false;
};
}; };
config = mkIf config.modules.dev.python.enable { config = mkIf cfg.enable {
my = { user.packages = with pkgs; [
packages = with pkgs; [
python37 python37
python37Packages.pip python37Packages.pip
python37Packages.ipython python37Packages.ipython
@ -35,14 +34,13 @@ with lib;
env.PYTHON_EGG_CACHE = "$XDG_CACHE_HOME/python-eggs"; env.PYTHON_EGG_CACHE = "$XDG_CACHE_HOME/python-eggs";
env.JUPYTER_CONFIG_DIR = "$XDG_CONFIG_HOME/jupyter"; env.JUPYTER_CONFIG_DIR = "$XDG_CONFIG_HOME/jupyter";
zsh.rc = lib.readFile <config/python/aliases.zsh>; environment.shellAliases = {
py = "python";
alias.py = "python"; py2 = "python2";
alias.py2 = "python2"; py3 = "python3";
alias.py3 = "python3"; po = "poetry";
alias.po = "poetry"; ipy = "ipython --no-banner";
alias.ipy = "ipython --no-banner"; ipylab = "ipython --pylab=qt5 --no-banner";
alias.ipylab = "ipython --pylab=qt5 --no-banner";
}; };
}; };
} }

View file

@ -8,18 +8,17 @@
# all the world's problems to be wonderful? # all the world's problems to be wonderful?
{ config, options, lib, pkgs, ... }: { config, options, lib, pkgs, ... }:
with lib; with lib;
{ with lib.my;
let cfg = config.modules.dev.rust;
in {
options.modules.dev.rust = { options.modules.dev.rust = {
enable = mkOption { enable = mkBoolOpt false;
type = types.bool;
default = false;
};
}; };
config = mkIf config.modules.dev.rust.enable { config = mkIf cfg.enable {
my = { user.packages = with pkgs; [
packages = with pkgs; [
rustup rustup
]; ];
@ -27,9 +26,10 @@ with lib;
env.CARGO_HOME = "$XDG_DATA_HOME/cargo"; env.CARGO_HOME = "$XDG_DATA_HOME/cargo";
env.PATH = [ "$CARGO_HOME/bin" ]; env.PATH = [ "$CARGO_HOME/bin" ];
alias.rs = "rustc"; environment.shellAliases = {
alias.rsp = "rustup"; rs = "rustc";
alias.ca = "cargo"; rsp = "rustup";
ca = "cargo";
}; };
}; };
} }

View file

@ -1,16 +1,15 @@
{ config, options, lib, pkgs, my, ... }:
{ config, options, lib, pkgs, ... }:
with lib; with lib;
{ with lib.my;
let cfg = config.modules.dev.scala;
in {
options.modules.dev.scala = { options.modules.dev.scala = {
enable = mkOption { enable = mkBoolOpt false;
type = types.bool;
default = false;
};
}; };
config = mkIf config.modules.dev.scala.enable { config = mkIf cfg.enable {
my.packages = with pkgs; [ user.packages = with pkgs; [
scala scala
jdk jdk
sbt sbt

View file

@ -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 # 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 # 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, # mortals to question the will of the ancient ones. If they want shell programs,
# they get shell programs. # they get shell programs.
{ config, options, lib, pkgs, ... }: { config, options, lib, pkgs, my, ... }:
with lib; with lib;
{ with lib.my;
options.modules.dev.zsh = { let cfg = config.modules.dev.shell;
enable = mkOption { in {
type = types.bool; options.modules.dev.shell = {
default = false; enable = mkBoolOpt false;
};
}; };
config = mkIf config.modules.dev.zsh.enable { config = mkIf cfg.enable {
my.packages = with pkgs; [ user.packages = with pkgs; [
shellcheck shellcheck
my.zunit
]; ];
}; };
} }

View file

@ -1,19 +1,14 @@
{ config, options, lib, pkgs, ... }: { config, options, lib, pkgs, ... }:
with lib; with lib;
{ with lib.my;
imports = [ let cfg = config.modules.editors;
./emacs.nix in {
./vim.nix
];
options.modules.editors = { options.modules.editors = {
default = mkOption { default = mkOpt types.str "vim";
type = types.str;
default = "vi";
};
}; };
config = mkIf (config.modules.editors.default != null) { config = mkIf (cfg.default != null) {
my.env.EDITOR = config.modules.editors.default; env.EDITOR = cfg.default;
}; };
} }

View file

@ -2,25 +2,26 @@
# https://github.com/hlissner/doom-emacs. This module sets it up to meet my # https://github.com/hlissner/doom-emacs. This module sets it up to meet my
# particular Doomy needs. # particular Doomy needs.
{ config, options, lib, pkgs, ... }: { config, options, lib, pkgs, inputs, ... }:
with lib; with lib;
{ with lib.my;
let cfg = config.modules.editors.emacs;
in {
options.modules.editors.emacs = { options.modules.editors.emacs = {
enable = mkOption { enable = mkBoolOpt false;
type = types.bool; doom = {
default = false; enable = mkBoolOpt true;
}; fromSSH = mkBoolOpt false;
pkg = mkOption {
type = types.package;
default = pkgs.emacsUnstable;
}; };
}; };
config = mkIf config.modules.editors.emacs.enable { config = mkIf cfg.enable {
my = { nixpkgs.overlays = [ inputs.emacs-overlay.overlay ];
packages = with pkgs; [
user.packages = with pkgs; [
## Doom dependencies ## Doom dependencies
config.modules.editors.emacs.pkg emacsUnstable # 27.1
git git
(ripgrep.override {withPCRE2 = true;}) (ripgrep.override {withPCRE2 = true;})
gnutls # for TLS connectivity gnutls # for TLS connectivity
@ -28,16 +29,15 @@ with lib;
## Optional dependencies ## Optional dependencies
fd # faster projectile indexing fd # faster projectile indexing
imagemagick # for image-dired imagemagick # for image-dired
(lib.mkIf (config.programs.gnupg.agent.enable) (mkIf (config.programs.gnupg.agent.enable)
pinentry_emacs) # in-emacs gnupg prompts pinentry_emacs) # in-emacs gnupg prompts
zstd # for undo-fu-session/undo-tree compression zstd # for undo-fu-session/undo-tree compression
## Module dependencies ## Module dependencies
# :checkers spell # :checkers spell
aspell (aspellWithDicts (ds: with ds; [
aspellDicts.en en en-computers en-science
aspellDicts.en-computers ]))
aspellDicts.en-science
# :checkers grammar # :checkers grammar
languagetool languagetool
# :tools editorconfig # :tools editorconfig
@ -52,15 +52,26 @@ with lib;
texlive.combined.scheme-medium texlive.combined.scheme-medium
# :lang rust # :lang rust
rustfmt rustfmt
rls unstable.rust-analyzer
]; ];
env.PATH = [ "$XDG_CONFIG_HOME/emacs/bin" ]; env.PATH = [ "$XDG_CONFIG_HOME/emacs/bin" ];
zsh.rc = lib.readFile <config/emacs/aliases.zsh>;
};
fonts.fonts = [ modules.shell.zsh.rcFiles = [ "${configDir}/emacs/aliases.zsh" ];
pkgs.emacs-all-the-icons-fonts
]; 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
# '';
}; };
} }

View file

@ -2,25 +2,26 @@
# go-to. I am a vimmer at heart, after all. # go-to. I am a vimmer at heart, after all.
{ config, options, lib, pkgs, ... }: { config, options, lib, pkgs, ... }:
with lib; with lib;
{ with lib.my;
let cfg = config.modules.editors.vim;
in {
options.modules.editors.vim = { options.modules.editors.vim = {
enable = mkOption { enable = mkBoolOpt false;
type = types.bool;
default = false;
};
}; };
config = mkIf config.modules.editors.vim.enable { config = mkIf cfg.enable {
my = { user.packages = with pkgs; [
packages = with pkgs; [
editorconfig-core-c editorconfig-core-c
neovim neovim
]; ];
env.VIMINIT = "let \\$MYVIMRC='\\$XDG_CONFIG_HOME/nvim/init.vim' | source \\$MYVIMRC"; # env.VIMINIT = "let \\$MYVIMRC='\\$XDG_CONFIG_HOME/nvim/init.vim' | source \\$MYVIMRC";
alias.vim = "nvim";
alias.v = "nvim"; environment.shellAliases = {
vim = "nvim";
v = "nvim";
}; };
}; };
} }

View file

@ -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" ];
};
}

View file

@ -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
'';
})
]);
}

View file

@ -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";
};
}

46
modules/hardware/fs.nix Normal file
View file

@ -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;
})
]))
]);
}

View file

@ -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"
'')
];
};
}

View file

@ -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
];
};
}

View file

@ -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 ];
};
}

View file

@ -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
'';
};
}

View file

@ -1,9 +0,0 @@
{ config, lib, pkgs, ... }:
{
imports = [
./mpv.nix
# ./ncmpcpp.nix
./spotify.nix
];
}

79
modules/options.nix Normal file
View file

@ -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);
};
}

View file

@ -1,15 +1,16 @@
{ config, options, pkgs, lib, ... }: { options, config, lib, pkgs, ... }:
with lib; with lib;
{ with lib.my;
let cfg = config.modules.services.calibre;
in {
options.modules.services.calibre = { options.modules.services.calibre = {
enable = mkOption { enable = mkBoolOpt false;
type = types.bool;
default = false;
};
}; };
config = mkIf config.modules.services.calibre.enable { config = mkIf cfg.enable {
services.calibre-server.enable = true; services.calibre-server.enable = true;
networking.firewall.allowedTCPPorts = [ 8080 ]; networking.firewall.allowedTCPPorts = [ 8080 ];
}; };
} }

View file

@ -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
];
}

View file

@ -1,23 +1,25 @@
{ config, options, pkgs, lib, ... }: { options, config, lib, pkgs, ... }:
with lib; with lib;
{ with lib.my;
let cfg = config.modules.services.docker;
in {
options.modules.services.docker = { options.modules.services.docker = {
enable = mkOption { enable = mkBoolOpt false;
type = types.bool;
default = false;
};
}; };
config = mkIf config.modules.services.docker.enable { config = mkIf cfg.enable {
my = { user.packages = with pkgs; [
packages = with pkgs; [ docker docker-compose ]; docker
docker-compose
];
env.DOCKER_CONFIG = "$XDG_CONFIG_HOME/docker"; env.DOCKER_CONFIG = "$XDG_CONFIG_HOME/docker";
env.MACHINE_STORAGE_PATH = "$XDG_DATA_HOME/docker/machine"; env.MACHINE_STORAGE_PATH = "$XDG_DATA_HOME/docker/machine";
user.extraGroups = [ "docker" ]; user.extraGroups = [ "docker" ];
zsh.rc = lib.readFile <config/docker/aliases.zsh>;
}; modules.shell.zsh.rcFiles = [ "${configDir}/docker/aliases.zsh" ];
virtualisation = { virtualisation = {
docker = { docker = {

Some files were not shown because too many files have changed in this diff Show more