Modularize config

This commit is contained in:
Henrik Lissner 2020-03-29 01:48:43 -04:00
parent 67da3cf844
commit 592ee79a83
No known key found for this signature in database
GPG key ID: 5F6C0EA160557395
92 changed files with 2138 additions and 1141 deletions

View file

@ -6,7 +6,7 @@ device:
networking.hostName = lib.mkDefault device; networking.hostName = lib.mkDefault device;
imports = [ imports = [
./options.nix ./modules
"${./hosts}/${device}" "${./hosts}/${device}"
]; ];
@ -16,15 +16,15 @@ device:
# So we can use absolute import paths # So we can use absolute import paths
"bin=/etc/dotfiles/bin" "bin=/etc/dotfiles/bin"
"config=/etc/dotfiles/config" "config=/etc/dotfiles/config"
"modules=/etc/dotfiles/modules"
]; ];
# ...but we still need to set nixpkgs.overlays to make them visible to the # Add custom packages & unstable channel, so they can be accessed via pkgs.*
# rebuild process, however...
nixpkgs.overlays = import ./overlays.nix; nixpkgs.overlays = import ./overlays.nix;
nixpkgs.config.allowUnfree = true; # forgive me Stallman senpai nixpkgs.config.allowUnfree = true; # forgive me Stallman senpai
# For instant nix-shell scripts environment.systemPackages = with pkgs; [
environment.systemPackages = [ pkgs.my.cached-nix-shell ]; gnumake # for our own makefile
my.cached-nix-shell # for instant nix-shell scripts
];
environment.shellAliases = { environment.shellAliases = {
nix-env = "NIXPKGS_ALLOW_UNFREE=1 nix-env"; nix-env = "NIXPKGS_ALLOW_UNFREE=1 nix-env";
nix-shell = ''NIX_PATH="nixpkgs-overlays=/etc/dotfiles/overlays.nix:$NIX_PATH" nix-shell''; nix-shell = ''NIX_PATH="nixpkgs-overlays=/etc/dotfiles/overlays.nix:$NIX_PATH" nix-shell'';

View file

@ -5,16 +5,16 @@
imports = [ imports = [
../personal.nix # common settings ../personal.nix # common settings
./hardware-configuration.nix ./hardware-configuration.nix
## Apps
<modules/shell/zsh.nix>
## Services
<modules/services/ssh.nix>
# <modules/services/plex.nix>
<modules/services/jellyfin.nix>
<modules/services/syncthing.nix>
<modules/services/calibre-server.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>; my.zsh.rc = lib.readFile <modules/themes/aquanaut/zsh/prompt.zsh>;
networking.networkmanager.enable = true; networking.networkmanager.enable = true;

View file

@ -5,16 +5,17 @@
imports = [ imports = [
../personal.nix ../personal.nix
./hardware-configuration.nix ./hardware-configuration.nix
## Apps
<modules/shell/git.nix>
<modules/shell/zsh.nix>
## Services
<modules/services/ssh.nix>
<modules/services/nginx.nix>
<modules/services/gitea.nix>
<modules/services/syncthing.nix>
]; ];
modules = {
shell.git.enable = true;
shell.zsh.enable = true;
services.ssh.enable = true;
services.nginx.enable = true;
services.gitea.enable = true;
services.syncthing.enable = true;
};
my.zsh.rc = lib.readFile <modules/themes/aquanaut/zsh/prompt.zsh>; my.zsh.rc = lib.readFile <modules/themes/aquanaut/zsh/prompt.zsh>;
networking.networkmanager.enable = true; networking.networkmanager.enable = true;

View file

@ -1,4 +1,4 @@
# hosts/default.nix --- settings common to all my systems # hosts/common.nix --- settings common to all my systems
{ pkgs, ... }: { pkgs, ... }:
{ {
@ -13,7 +13,6 @@
sshfs sshfs
]; ];
### My user settings ### My user settings
my.username = "hlissner"; my.username = "hlissner";
my.user = { my.user = {

View file

@ -1,41 +1,73 @@
# Kuro -- my desktop # Kuro -- my desktop
{ pkgs, ... }: { pkgs, options, config, ... }:
{ {
imports = [ imports = [
../personal.nix # common settings ../personal.nix # common settings
./hardware-configuration.nix ./hardware-configuration.nix
## Desktop/shell environment
<modules/desktop/bspwm.nix>
# <modules/desktop/stumpwm.nix>
## Apps
<modules/browser/firefox.nix>
<modules/dev/cc.nix>
<modules/dev/rust.nix>
# <modules/dev/common-lisp.nix>
<modules/editors/emacs.nix>
<modules/editors/vim.nix>
<modules/gaming/steam.nix>
<modules/shell/direnv.nix>
<modules/shell/git.nix>
<modules/shell/gnupg.nix>
<modules/shell/pass.nix>
<modules/shell/tmux.nix>
<modules/shell/ranger.nix>
<modules/shell/zsh.nix>
## Project-based
<modules/chat.nix> # discord, mainly
<modules/recording.nix> # recording video & audio
<modules/daw.nix> # making music
<modules/music.nix> # playing music
<modules/graphics.nix> # art & design
<modules/vm.nix> # virtualbox for testing
## Services
<modules/services/syncthing.nix>
## Theme
<modules/themes/fluorescence>
]; ];
modules = {
desktop = {
bspwm.enable = true;
apps.rofi.enable = true;
apps.discord.enable = true;
# apps.skype.enable = true;
apps.daw.enable = true; # making music
apps.graphics.enable = true; # raster/vector/sprites
apps.recording.enable = true; # recording screen/audio
apps.vm.enable = true; # virtualbox for testing
term.default = "xst";
term.st.enable = true;
browsers.default = "firefox";
browsers.firefox.enable = true;
# browsers.qutebrowser.enable = true;
# gaming.emulators.psx.enable = true;
# gaming.steam.enable = true;
# gaming.factorio.enable = true;
};
editors = {
default = "nvim";
emacs.enable = true;
vim.enable = true;
};
dev = {
cc.enable = true;
common-lisp.enable = true;
rust.enable = true;
scala.enable = true;
};
media = {
mpv.enable = true;
spotify.enable = true;
};
shell = {
direnv.enable = true;
git.enable = true;
gnupg.enable = true;
# weechat.enable = true;
pass.enable = true;
tmux.enable = true;
ranger.enable = true;
zsh.enable = true;
};
services = {
syncthing.enable = true;
};
# themes.aquanaut.enable = true;
themes.fluorescence.enable = true;
};
networking.networkmanager.enable = true; networking.networkmanager.enable = true;
time.timeZone = "America/Toronto"; time.timeZone = "America/Toronto";
} }

View file

@ -33,7 +33,7 @@
with pkgs; [ inetutils mtr sysstat git ]; with pkgs; [ inetutils mtr sysstat git ];
imports = [ imports = [
./. ./common.nix
<modules/editors/vim.nix> <modules/editors/vim.nix>
<modules/shell/git.nix> <modules/shell/git.nix>
<modules/shell/zsh.nix> <modules/shell/zsh.nix>

View file

@ -2,7 +2,7 @@
{ config, lib, pkgs, ... }: { config, lib, pkgs, ... }:
{ {
imports = [ ./. ]; imports = [ ./common.nix ];
# Support for more filesystems # Support for more filesystems
environment.systemPackages = with pkgs; [ environment.systemPackages = with pkgs; [

View file

@ -5,32 +5,68 @@
imports = [ imports = [
../personal.nix # common settings ../personal.nix # common settings
./hardware-configuration.nix ./hardware-configuration.nix
## Dekstop environment
<modules/desktop/bspwm.nix>
## Apps
<modules/browser/firefox.nix>
<modules/dev>
<modules/editors/emacs.nix>
<modules/editors/vim.nix>
<modules/shell/direnv.nix>
<modules/shell/git.nix>
<modules/shell/gnupg.nix>
<modules/shell/pass.nix>
<modules/shell/tmux.nix>
<modules/shell/zsh.nix>
## Project-based
<modules/chat.nix> # discord, mainly
<modules/recording.nix> # recording video & audio
<modules/daw.nix> # making music
<modules/music.nix> # playing music
<modules/graphics.nix> # art & design
# <modules/vm.nix> # virtualbox for testing
## Services
<modules/services/syncthing.nix>
## Theme
<modules/themes/aquanaut>
]; ];
modules = {
desktop = {
bspwm.enable = true;
apps.rofi.enable = true;
apps.discord.enable = true;
# apps.skype.enable = true;
apps.daw.enable = true; # making music
apps.graphics.enable = true; # raster/vector/sprites
apps.recording.enable = true; # recording screen/audio
# apps.vm.enable = true; # virtualbox for testing
term.default = "xst";
term.st.enable = true;
browsers.default = "firefox";
browsers.firefox.enable = true;
# browsers.qutebrowser.enable = true;
# gaming.emulators.psx.enable = true;
# gaming.steam.enable = true;
# gaming.factorio.enable = true;
};
editors = {
default = "nvim";
emacs.enable = true;
vim.enable = true;
};
# dev = {
# cc.enable = true;
# # common-lisp.enable = true;
# rust.enable = true;
# };
media = {
mpv.enable = true;
spotify.enable = true;
};
shell = {
direnv.enable = true;
git.enable = true;
gnupg.enable = true;
# weechat.enable = true;
pass.enable = true;
tmux.enable = true;
ranger.enable = true;
zsh.enable = true;
};
services = {
syncthing.enable = true;
};
# themes.aquanaut.enable = true;
themes.fluorescence.enable = true;
};
networking.wireless.enable = true; networking.wireless.enable = true;
hardware.opengl.enable = true; hardware.opengl.enable = true;

View file

@ -1,26 +0,0 @@
# modules/browser/firefox.nix --- https://www.mozilla.org/en-US/firefox
#
# Oh firefox, gateway to the interwebs, devourer of ram. Give onto me your
# infinite knowledge and shelter me from ads.
{ config, lib, pkgs, ... }:
{
my.packages = with pkgs; [
firefox-bin
(pkgs.writeScriptBin "firefox-private" ''
#!${stdenv.shell}
${firefox}/bin/firefox --private-window "$@"
'')
(makeDesktopItem {
name = "firefox-private";
desktopName = "Firefox (Private)";
genericName = "Open a private Firefox window";
icon = "firefox";
exec = "${firefox-bin}/bin/firefox --private-window";
categories = "Network";
})
];
my.env.BROWSER = "firefox";
my.env.XDG_DESKTOP_DIR = "$HOME"; # prevent firefox creating ~/Desktop
}

View file

@ -1,51 +0,0 @@
# modules/browser/qutebrowser.nix --- https://github.com/qutebrowser/qutebrowser
#
# Qutebrowser is cute because it's not enough of a browser to be handsome.
# Still, we can all tell he'll grow up to be one hell of a lady-killer.
{ config, lib, pkgs, ... }:
{
my.packages = with pkgs; [
qutebrowser
(pkgs.writeScriptBin "qutebrowser-private" ''
#!${stdenv.shell}
${qutebrowser}/bin/qutebrowser ":open -p $@"
'')
(makeDesktopItem {
name = "qutebrowser-private";
desktopName = "Qutebrowser (Private)";
genericName = "Open a private Qutebrowser window";
icon = "qutebrowser";
exec = "${qutebrowser}/bin/qutebrowser ':open -p'";
categories = "Network";
})
];
my.env.BROWSER = "qutebrowser";
my.home.xdg = {
configFile."qutebrowser" = {
source = <config/qutebrowser>;
recursive = true;
};
dataFile = {
"qutebrowser/greasemonkey" = {
source = <config/qutebrowser/greasemonkey>;
recursive = true;
};
"qutebrowser/userstyles.css".source =
let compiledStyles =
with pkgs; runCommand "compileUserStyles"
{ buildInputs = [ sass ]; } ''
mkdir "$out"
for file in ${<config/qutebrowser/styles>}/*.scss; do
scss --sourcemap=none \
--no-cache \
--style compressed \
--default-encoding utf-8 \
"$file" \
>>"$out/userstyles.css"
done
'';
in "${compiledStyles}/userstyles.css";
};
};
}

View file

@ -1,21 +0,0 @@
{ config, lib, pkgs, ... }:
{
my.packages = with pkgs; [
vivaldi
vivaldi-widevine
(pkgs.writeScriptBin "vivaldi-private" ''
#!${stdenv.shell}
${vivaldi}/bin/vivaldi --incognito "$@"
'')
(makeDesktopItem {
name = "vivaldi-private";
desktopName = "Vivaldi (Incognito)";
genericName = "Open an incognito Vivaldi window";
icon = "vivaldi";
exec = "${vivaldi}/bin/vivaldi --incognito";
categories = "Network";
})
];
my.env.BROWSER = "vivaldi";
}

View file

@ -1,12 +0,0 @@
# modules/chat.nix
#
# Even neckbeards have a social life. Not that I have one. A neckbeard, I mean.
# But when I do have either, then discord and weechat are my go-to.
{ pkgs, ... }:
{
my.packages = with pkgs; [
# weechat # TODO For the real neckbeards
discord # For everyone else
];
}

View file

@ -1,18 +0,0 @@
# modules/music.nix
#
# I make music for my games. LMMS is my DAW; or will be, once I've weened myself
# off of Fruityloops. When I'm in the mood for a quicky I fire up sunvox
# instead. It runs absolutely anywhere, even on my ipad and phone. As if I'd
# ever need to.
{ config, lib, pkgs, ... }:
{
my.packages = with pkgs; [
audacity # for recording and remastering audio
sunvox # for making music (where LMMS is overkill)
# lmms on stable is broken due to 'Could not find the Qt platform plugin
# "xcb" in ""' error: https://github.com/NixOS/nixpkgs/issues/76074
unstable.lmms # for making music
];
}

101
modules/default.nix Normal file
View file

@ -0,0 +1,101 @@
{ 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));
};
init = mkOption {
type = types.lines;
description = ''
An init script that runs after the environment has been rebuilt or
booted. Anything done here should be idempotent and inexpensive.
'';
};
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 ''
${concatStringsSep "\n" exportLines}
${config.my.init}
'';
# 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

@ -0,0 +1,28 @@
# modules/desktop/apps/daw.nix
#
# I make music for my games. LMMS is my DAW; or will be, once I've weened myself
# off of Fruityloops. When I'm in the mood for a quicky I fire up sunvox
# instead. It runs absolutely anywhere, even on my ipad and phone. As if I'd
# ever need to.
{ config, options, lib, pkgs, ... }:
with lib;
{
options.modules.desktop.apps.daw = {
enable = mkOption {
type = types.bool;
default = false;
};
};
config = mkIf config.modules.desktop.apps.daw.enable {
my.packages = with pkgs; [
# lmms on stable is broken due to 'Could not find the Qt platform plugin
# "xcb" in ""' error: https://github.com/NixOS/nixpkgs/issues/76074
unstable.lmms # for making music
audacity # for recording and remastering audio
# sunvox # for making music (where LMMS is overkill)
];
};
}

View file

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

View file

@ -0,0 +1,17 @@
{ config, options, lib, pkgs, ... }:
with lib;
{
options.modules.desktop.apps.discord = {
enable = mkOption {
type = types.bool;
default = false;
};
};
config = mkIf config.modules.desktop.apps.discord.enable {
my.packages = with pkgs; [
discord
# ripcord
];
};
}

View file

@ -0,0 +1,50 @@
# 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 [
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

@ -0,0 +1,28 @@
# 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,15 +0,0 @@
# modules/desktop/apps/redshift.nix
{ config, lib, pkgs, ... }:
{
services.redshift.enable = true;
# 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 {});
}

View file

@ -1,63 +1,84 @@
{ config, lib, pkgs, ... }: { config, options, lib, pkgs, ... }:
with lib;
{ {
my = { options.modules.desktop.apps.rofi = {
# link recursively so other modules can link files in its folder enable = mkOption {
home.xdg.configFile."rofi" = { type = types.bool;
source = <config/rofi>; default = false;
recursive = true;
}; };
};
packages = with pkgs; [ config = mkIf config.modules.desktop.apps.rofi.enable {
(writeScriptBin "rofi" '' my = {
#!${stdenv.shell} # link recursively so other modules can link files in its folder
exec ${rofi}/bin/rofi -terminal xst -m -1 "$@" home.xdg.configFile."rofi" = {
'') source = <config/rofi>;
recursive = true;
};
# Fake rofi dmenu entries packages = with pkgs; [
(makeDesktopItem { (writeScriptBin "rofi" ''
name = "rofi-bookmarkmenu"; #!${stdenv.shell}
desktopName = "Open Bookmark in Browser"; exec ${rofi}/bin/rofi -terminal xst -m -1 "$@"
icon = "bookmark-new-symbolic"; '')
exec = "${<bin/rofi/bookmarkmenu>}";
})
(makeDesktopItem {
name = "rofi-filemenu";
desktopName = "Open Directory in Terminal";
icon = "folder";
exec = "${<bin/rofi/filemenu>}";
})
(makeDesktopItem {
name = "rofi-filemenu-scratch";
desktopName = "Open Directory in Scratch Terminal";
icon = "folder";
exec = "${<bin/rofi/filemenu>} -x";
})
(makeDesktopItem { # For rapidly test changes to rofi's stylesheets
name = "reboot"; # (writeScriptBin "rofi-test" ''
desktopName = "System: Reboot"; # #!${stdenv.shell}
icon = "system-reboot"; # themefile=$1
exec = "systemctl reboot"; # themename=${modules.theme.name}
}) # shift
(makeDesktopItem { # exec rofi \
name = "shutdown"; # -theme ~/.dotfiles/modules/themes/$themename/rofi/$themefile \
desktopName = "System: Shut Down"; # "$@"
icon = "system-shutdown"; # '')
exec = "systemctl shutdown";
}) # Fake rofi dmenu entries
(makeDesktopItem { (makeDesktopItem {
name = "sleep"; name = "rofi-bookmarkmenu";
desktopName = "System: Sleep"; desktopName = "Open Bookmark in Browser";
icon = "system-suspend"; icon = "bookmark-new-symbolic";
exec = "zzz -f"; exec = "${<bin/rofi/bookmarkmenu>}";
}) })
(makeDesktopItem { (makeDesktopItem {
name = "lock-display"; name = "rofi-filemenu";
desktopName = "Lock screen"; desktopName = "Open Directory in Terminal";
icon = "system-lock-screen"; icon = "folder";
exec = "zzz"; exec = "${<bin/rofi/filemenu>}";
}) })
]; (makeDesktopItem {
name = "rofi-filemenu-scratch";
desktopName = "Open Directory in Scratch Terminal";
icon = "folder";
exec = "${<bin/rofi/filemenu>} -x";
})
(makeDesktopItem {
name = "reboot";
desktopName = "System: Reboot";
icon = "system-reboot";
exec = "systemctl reboot";
})
(makeDesktopItem {
name = "shutdown";
desktopName = "System: Shut Down";
icon = "system-shutdown";
exec = "systemctl shutdown";
})
(makeDesktopItem {
name = "sleep";
desktopName = "System: Sleep";
icon = "system-suspend";
exec = "${<bin/zzz>} -f";
})
(makeDesktopItem {
name = "lock-display";
desktopName = "Lock screen";
icon = "system-lock-screen";
exec = "${<bin/zzz>}";
})
];
};
}; };
} }

View file

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

View file

@ -1,18 +0,0 @@
{ config, lib, pkgs, ... }:
{
# xst-256color isn't supported over ssh, so revert to a known one
my.zsh.rc = ''[ "$TERM" = xst-256color ] && export TERM=xterm-256color'';
my.packages = with pkgs; [
xst # st + nice-to-have extensions
(makeDesktopItem {
name = "xst";
desktopName = "Suckless Terminal";
genericName = "Default terminal";
icon = "utilities-terminal";
exec = "${xst}/bin/xst";
categories = "Development;System;Utility";
})
];
}

View file

@ -1,8 +0,0 @@
{ config, lib, pkgs, ... }:
{
my.packages = with pkgs; [
xfce.thunar
xfce.tumbler # for thumbnails
];
}

View file

@ -1,7 +0,0 @@
{ config, lib, pkgs, ... }:
{
my.packages = with pkgs; [
rxvt_unicode
];
}

View file

@ -0,0 +1,25 @@
# 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;
enableExtensionPack = true; # urg, takes so long to build
};
my.user.extraGroups = [ "vboxusers" ];
};
}

View file

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

View file

@ -0,0 +1,30 @@
# modules/browser/firefox.nix --- https://www.mozilla.org/en-US/firefox
#
# Oh firefox, gateway to the interwebs, devourer of ram. Give onto me your
# infinite knowledge and shelter me from ads.
{ config, options, lib, pkgs, ... }:
with lib;
{
options.modules.desktop.browsers.firefox = {
enable = mkOption {
type = types.bool;
default = false;
};
};
config = mkIf config.modules.desktop.browsers.firefox.enable {
my.packages = with pkgs; [
firefox-bin
(makeDesktopItem {
name = "firefox-private";
desktopName = "Firefox (Private)";
genericName = "Open a private Firefox window";
icon = "firefox";
exec = "${firefox-bin}/bin/firefox --private-window";
categories = "Network";
})
];
my.env.XDG_DESKTOP_DIR = "$HOME"; # (try to) prevent ~/Desktop
};
}

View file

@ -0,0 +1,33 @@
# modules/browser/qutebrowser.nix --- https://github.com/qutebrowser/qutebrowser
#
# Qutebrowser is cute because it's not enough of a browser to be handsome.
# Still, we can all tell he'll grow up to be one hell of a lady-killer.
{ config, options, lib, pkgs, ... }:
with lib;
{
options.modules.desktop.browsers.qutebrowser = {
enable = mkOption {
type = types.bool;
default = false;
};
};
config = mkIf config.modules.desktop.browsers.qutebrowser.enable {
my.packages = with pkgs; [
qutebrowser
(makeDesktopItem {
name = "qutebrowser-private";
desktopName = "Qutebrowser (Private)";
genericName = "Open a private Qutebrowser window";
icon = "qutebrowser";
exec = "${qutebrowser}/bin/qutebrowser ':open -p'";
categories = "Network";
})
];
my.home.xdg.configFile."qutebrowser" = {
source = <config/qutebrowser>;
recursive = true;
};
};
}

View file

@ -0,0 +1,27 @@
# 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,34 +1,43 @@
{ config, lib, pkgs, ... }: { config, options, lib, pkgs, ... }:
with lib;
{ {
imports = [ imports = [
./. # common settings ./common.nix
]; ];
environment.systemPackages = with pkgs; [ options.modules.desktop.bspwm = {
lightdm enable = mkOption { type = types.bool; default = false; };
dunst
libnotify
(polybar.override {
pulseSupport = true;
nlSupport = true;
})
];
services = {
compton.enable = true;
xserver = {
windowManager.default = "bspwm";
windowManager.bspwm.enable = true;
displayManager.lightdm.enable = true;
displayManager.lightdm.greeters.mini.enable = true;
};
}; };
my.home.xdg.configFile = { config = mkIf config.modules.desktop.bspwm.enable {
"sxhkd".source = <config/sxhkd>; environment.systemPackages = with pkgs; [
lightdm
dunst
libnotify
(polybar.override {
pulseSupport = true;
nlSupport = true;
})
];
services = {
compton.enable = true;
redshift.enable = true;
xserver = {
enable = true;
windowManager.default = "bspwm";
windowManager.bspwm = {
enable = true;
configFile = <config/bspwm/bspwmrc>;
sxhkd.configFile = <config/sxhkd/sxhkdrc>;
};
displayManager.lightdm.enable = true;
displayManager.lightdm.greeters.mini.enable = true;
};
};
# link recursively so other modules can link files in their folders # link recursively so other modules can link files in their folders
"bspwm" = { my.home.xdg.configFile."bspwm" = {
source = <config/bspwm>; source = <config/bspwm>;
recursive = true; recursive = true;
}; };

103
modules/desktop/common.nix Normal file
View file

@ -0,0 +1,103 @@
{ 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.compton = {
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

@ -2,96 +2,12 @@
{ {
imports = [ imports = [
## Desktop apps ./bspwm.nix
./apps/redshift.nix # ./stumpwm.nix
./apps/rofi.nix # My launcher
# I often need a thumbnail browser to show off, peruse or organize photos, ./apps
# design work, or digital art. ./term
# ./apps/nautilus.nix ./browsers
./apps/thunar.nix ./gaming
## Terminal
# ./apps/alacritty.nix
./apps/st.nix
# ./apps/urxvt.nix
]; ];
services.xserver = {
enable = true;
desktopManager.xterm.enable = lib.mkDefault false;
displayManager.lightdm.greeters.mini.user = config.my.username;
};
my.packages = with pkgs; [
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"];
};
};
services.compton = {
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~='(scratch|Dunst)$'"
];
settings.blur-background-exclude = [
"window_type = 'dock'"
"window_type = 'desktop'"
"class_g = 'Rofi'"
"_GTK_FRAME_EXTENTS@:c"
];
};
} }

View file

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

View file

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

View file

@ -0,0 +1,17 @@
{ config, options, lib, pkgs, ... }:
with lib;
{
options.modules.desktop.gaming.factorio = {
enable = mkOption {
type = types.bool;
default = false;
};
};
config = mkIf config.modules.desktop.gaming.factorio.enable {
my.packages = with pkgs; [
unstable.factorio-experimental
];
};
}

View file

@ -0,0 +1,30 @@
{ config, options, lib, pkgs, ... }:
with lib;
{
options.modules.desktop.gaming.steam = {
enable = mkOption {
type = types.bool;
default = false;
};
};
config = mkIf config.modules.desktop.gaming.steam.enable {
my.packages = with pkgs; [
# Get steam to keep its garbage out of $HOME
(writeScriptBin "steam" ''
#!${stdenv.shell}
HOME="$XDG_DATA_HOME/steamlib" exec ${steam}/bin/steam "$@"
'')
# for GOG and humblebundle games
(writeScriptBin "steam-run" ''
#!${stdenv.shell}
HOME="$XDG_DATA_HOME/steamlib" exec ${steam-run-native}/bin/steam-run "$@"
'')
xboxdrv # driver for 360 controller
];
hardware.opengl.driSupport32Bit = true;
hardware.pulseaudio.support32Bit = true;
};
}

View file

@ -1,10 +1,8 @@
{ config, lib, pkgs, ... }: { config, lib, pkgs, ... }:
# let unstable = import <nixos-unstable> {};
# in
{ {
imports = [ imports = [
./. # common settings ./common.nix
]; ];
environment.systemPackages = with pkgs; [ environment.systemPackages = with pkgs; [
@ -15,7 +13,9 @@
# unstable.services.picom.enable = true; # unstable.services.picom.enable = true;
services = { services = {
redshift.enable = true;
xserver = { xserver = {
enable = true;
windowManager.default = "stumpwm"; windowManager.default = "stumpwm";
windowManager.stumpwm.enable = true; windowManager.stumpwm.enable = true;
displayManager.lightdm.enable = true; displayManager.lightdm.enable = true;

View file

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

View file

@ -0,0 +1,28 @@
{ config, lib, pkgs, ... }:
with lib;
{
options.modules.desktop.term.st = {
enable = mkOption {
type = types.bool;
default = false;
};
};
config = mkIf config.modules.desktop.term.st.enable {
# xst-256color isn't supported over ssh, so revert to a known one
my.zsh.rc = ''[ "$TERM" = xst-256color ] && export TERM=xterm-256color'';
my.packages = with pkgs; [
xst # st + nice-to-have extensions
(makeDesktopItem {
name = "xst";
desktopName = "Suckless Terminal";
genericName = "Default terminal";
icon = "utilities-terminal";
exec = "${xst}/bin/xst";
categories = "Development;System;Utility";
})
];
};
}

View file

@ -4,16 +4,24 @@
# Liking C/C++ seems to be an unpopular opinion. It's my guilty secret, so don't # Liking C/C++ seems to be an unpopular opinion. It's my guilty secret, so don't
# tell anyone pls. # tell anyone pls.
{ pkgs, ... }: { config, options, lib, pkgs, ... }:
with lib;
{ {
imports = [ ./. ]; options.modules.dev.cc = {
enable = mkOption {
type = types.bool;
default = false;
};
};
my.packages = with pkgs; [ config = mkIf config.modules.dev.cc.enable {
clang my.packages = with pkgs; [
gcc clang
bear gcc
gdb bear
cmake gdb
llvmPackages.libcxx cmake
]; llvmPackages.libcxx
];
};
} }

View file

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

View file

@ -2,10 +2,20 @@
# #
# 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, lib, pkgs, ... }: { config, options, lib, pkgs, ... }:
with lib;
{ {
my.packages = with pkgs; [ options.modules.dev.common-lisp = {
sbcl enable = mkOption {
lispPackages.quicklisp type = types.bool;
]; default = false;
};
};
config = mkIf config.modules.dev.common-lisp.enable {
my.packages = with pkgs; [
sbcl
lispPackages.quicklisp
];
};
} }

View file

@ -2,7 +2,22 @@
{ pkgs, ... }: { pkgs, ... }:
{ {
my.packages = with pkgs; [ imports = [
gnumake ./cc.nix
./clojure.nix
./common-lisp.nix
# ./godot.nix
# ./haskell.nix
# ./latex.nix
# ./love2d.nix
# ./node.nix
# ./python.nix
./rust.nix
./scala.nix
# ./unity3d.nix
# ./zsh.nix
]; ];
options = {};
config = {};
} }

View file

@ -3,9 +3,19 @@
# Gamedev is my hobby. C++ or Rust are my main drivers (and occasionally Lua), # Gamedev is my hobby. C++ or Rust are my main drivers (and occasionally Lua),
# but to prototype (for 3D, mainly) I'll occasionally reach for godot. # but to prototype (for 3D, mainly) I'll occasionally reach for godot.
{ pkgs, ... }: { config, options, lib, pkgs, ... }:
with lib;
{ {
my.packages = with pkgs; [ options.modules.dev.godot = {
godot enable = mkOption {
]; type = types.bool;
default = false;
};
};
config = mkIf config.modules.dev.godot.enable {
my.packages = with pkgs; [
godot
];
};
} }

View file

@ -7,19 +7,29 @@
# is no formal proof of your claims for safety, but who said you have to solve # is no formal proof of your claims for safety, but who said you have to solve
# all the world's problems to be wonderful? # all the world's problems to be wonderful?
{ lib, pkgs, ... }: { config, options, lib, pkgs, ... }:
with lib;
{ {
my = { options.modules.dev.rust = {
packages = with pkgs; [ enable = mkOption {
rustup type = types.bool;
]; default = false;
};
};
env.RUSTUP_HOME = "$XDG_DATA_HOME/rustup"; config = mkIf config.modules.dev.rust.enable {
env.CARGO_HOME = "$XDG_DATA_HOME/cargo"; my = {
env.PATH = [ "$CARGO_HOME/bin" ]; packages = with pkgs; [
rustup
];
alias.rs = "rustc"; env.RUSTUP_HOME = "$XDG_DATA_HOME/rustup";
alias.rsp = "rustup"; env.CARGO_HOME = "$XDG_DATA_HOME/cargo";
alias.ca = "cargo"; env.PATH = [ "$CARGO_HOME/bin" ];
alias.rs = "rustc";
alias.rsp = "rustup";
alias.ca = "cargo";
};
}; };
} }

19
modules/dev/scala.nix Normal file
View file

@ -0,0 +1,19 @@
{ config, options, lib, pkgs, ... }:
with lib;
{
options.modules.dev.scala = {
enable = mkOption {
type = types.bool;
default = false;
};
};
config = mkIf config.modules.dev.scala.enable {
my.packages = with pkgs; [
scala
jdk
sbt
];
};
}

View file

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

View file

@ -2,50 +2,60 @@
# 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, lib, pkgs, ... }: { config, options, lib, pkgs, ... }:
with lib;
{ {
my = { options.modules.editors.emacs = {
packages = with pkgs; [ enable = mkOption {
## Doom dependencies type = types.bool;
my.emacs27 default = false;
git };
(ripgrep.override {withPCRE2 = true;})
## Optional dependencies
editorconfig-core-c # per-project style config
fd # faster projectile indexing
gnutls # for TLS connectivity
imagemagick # for image-dired
(lib.mkIf (config.programs.gnupg.agent.enable)
pinentry_emacs) # in-emacs gnupg prompts
zstd # for undo-tree compression
## Module dependencies
# :checkers spell
aspell
aspellDicts.en
aspellDicts.en-computers
aspellDicts.en-science
# :checkers grammar
languagetool
# :tools lookup
sqlite
# :lang cc
ccls
# :lang javascript
nodePackages.javascript-typescript-langserver
# :lang latex & :lang org (latex previews)
texlive.combined.scheme-medium
# :lang rust
rustfmt
rls
];
env.PATH = [ "$HOME/.emacs.d/bin" ];
zsh.rc = lib.readFile <config/emacs/aliases.zsh>;
}; };
fonts.fonts = [ config = mkIf config.modules.editors.emacs.enable {
pkgs.emacs-all-the-icons-fonts my = {
]; packages = with pkgs; [
## Doom dependencies
my.emacs27
git
(ripgrep.override {withPCRE2 = true;})
## Optional dependencies
editorconfig-core-c # per-project style config
fd # faster projectile indexing
gnutls # for TLS connectivity
imagemagick # for image-dired
(lib.mkIf (config.programs.gnupg.agent.enable)
pinentry_emacs) # in-emacs gnupg prompts
zstd # for undo-tree compression
## Module dependencies
# :checkers spell
aspell
aspellDicts.en
aspellDicts.en-computers
aspellDicts.en-science
# :checkers grammar
languagetool
# :tools lookup
sqlite
# :lang cc
ccls
# :lang javascript
nodePackages.javascript-typescript-langserver
# :lang latex & :lang org (latex previews)
texlive.combined.scheme-medium
# :lang rust
rustfmt
rls
];
env.PATH = [ "$HOME/.emacs.d/bin" ];
zsh.rc = lib.readFile <config/emacs/aliases.zsh>;
};
fonts.fonts = [
pkgs.emacs-all-the-icons-fonts
];
};
} }

View file

@ -1,17 +1,26 @@
# When I'm stuck in the terminal or don't have access to Emacs, (neo)vim is my # When I'm stuck in the terminal or don't have access to Emacs, (neo)vim is my
# go-to. I am a vimmer at heart, after all. # go-to. I am a vimmer at heart, after all.
{ config, lib, pkgs, ... }: { config, options, lib, pkgs, ... }:
with lib;
{ {
my = { options.modules.editors.vim = {
packages = with pkgs; [ enable = mkOption {
editorconfig-core-c type = types.bool;
neovim default = false;
]; };
};
env.EDITOR = "nvim"; config = mkIf config.modules.editors.vim.enable {
env.VIMINIT = "let \\$MYVIMRC='\\$XDG_CONFIG_HOME/nvim/init.vim' | source \\$MYVIMRC"; my = {
packages = with pkgs; [
editorconfig-core-c
neovim
];
alias.v = "nvim"; env.VIMINIT = "let \\$MYVIMRC='\\$XDG_CONFIG_HOME/nvim/init.vim' | source \\$MYVIMRC";
alias.vim = "nvim";
alias.v = "nvim";
};
}; };
} }

View file

@ -1,8 +0,0 @@
{ config, lib, pkgs, ... }:
{
environment.systemPackages = with pkgs; [
epsxe # PSX
desmume # DS
];
}

View file

@ -1,20 +0,0 @@
{ config, lib, pkgs, ... }:
{
my.packages = with pkgs; [
# Get steam to keep its garbage out of $HOME
(writeScriptBin "steam" ''
#!${stdenv.shell}
HOME="$XDG_DATA_HOME/steamlib" exec ${steam}/bin/steam "$@"
'')
# for GOG and humblebundle games
(writeScriptBin "steam-run" ''
#!${stdenv.shell}
HOME="$XDG_DATA_HOME/steamlib" exec ${steam-run-native}/bin/steam-run "$@"
'')
xboxdrv # driver for 360 controller
];
hardware.opengl.driSupport32Bit = true;
hardware.pulseaudio.support32Bit = true;
}

View file

@ -1,26 +0,0 @@
# modules/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, lib, pkgs, ... }:
{
my = {
packages = with pkgs; [
font-manager # so many damned fonts...
imagemagick # for image manipulation from the shell
aseprite-unfree # pixel art
inkscape # illustrator & indesign
krita # replaces photoshop
gimp # replaces photoshop
gimpPlugins.resynthesizer2 # content-aware scaling in gimp
];
home.xdg.configFile = {
"GIMP/2.10" = { source = <config/gimp>; recursive = true; };
};
};
}

View file

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

19
modules/media/mpv.nix Normal file
View file

@ -0,0 +1,19 @@
{ config, options, lib, pkgs, ... }:
with lib;
{
options.modules.media.mpv = {
enable = mkOption {
type = types.bool;
default = false;
};
};
config = mkIf config.modules.media.mpv.enable {
my.packages = with pkgs; [
mpv-with-scripts
mpvc # CLI controller for mpv
(mkIf config.services.xserver.enable
celluloid) # nice GTK GUI for mpv
];
};
}

View file

67
modules/media/spotify.nix Normal file
View file

@ -0,0 +1,67 @@
# I use spotify for my music needs. Gone are the days where I'd manage 200gb+ of
# local music; most of which I haven't heard or don't even like.
{ config, options, lib, pkgs, ... }:
with lib;
{
options.modules.media.spotify = {
enable = mkOption {
type = types.bool;
default = false;
};
};
config = mkIf config.modules.media.spotify.enable {
# services.spotifyd doesn't work so we'll have to roll our own spotifyd +
# spotify-tui solution. The dbus interface doesn't work, though, so we have to
# wait for spotify-tui to implement CLI command for controlling spotify
# playback. See https://github.com/Rigellute/spotify-tui/issues/147 or for
# spotifyd to get fixed.
my.packages = with pkgs; [
# unstable.spotifyd
# (writeScriptBin "spt" ''
# #!${stdenv.shell}
# if ! systemctl --user is-active spotifyd >/dev/null; then
# systemctl --user start spotifyd
# fi
# echo $TMUX >$XDG_DATA_HOME/spt.tmux
# exec ${unstable.spotify-tui}/bin/spt
# '')
# spotify-tui is fine for selecting and playing music, but incomplete. We
# occasionally still need the official client for more sophisticated search
# and the "made for you" playlists.
spotify
# Since dbus doesn't work with spotifyd/spotify-tui, and I always use tmux
# for my terminal, may as well exploit tmux to control spotify.
# (writeScriptBin "spt-send" ''
# #!${stdenv.shell}
# dbus_cmd='dbus-send --print-reply --dest=org.mpris.MediaPlayer2.spotify /org/mpris/MediaPlayer2 org.mpris.MediaPlayer2.Player'
# tmux_cmd="tmux send-keys -t $(cat $XDG_DATA_HOME/spt.tmux | cut -d, -f3)"
# case "$1" in
# toggle) $dbus_cmd.PlayPause 2>/dev/null || $tmux_cmd " " ;;
# next) $dbus_cmd.Next 2>/dev/null || $tmux_cmd n ;;
# prev) $dbus_cmd.Previous 2>/dev/null || $tmux_cmd p ;;
# esac
# '')
];
# systemd.user.services.spotifyd.serviceConfig =
# let spotifydConf = pkgs.writeText "spotifyd.conf" ''
# [global]
# username = g2qwjcs6334oacg1zg9wrihnn
# password_cmd = ${pkgs.pass}/bin/pass www/spotify.com | head -n1
# backend = pulseaudio
# '';
# in {
# ExecStart = ''
# ${pkgs.unstable.spotifyd}/bin/spotifyd --no-daemon \
# --cache-path /tmp/spotifyd \
# --config-path ${spotifydConf}
# '';
# Restart = "always";
# RestartSec = 6;
# };
};
}

View file

@ -1,39 +0,0 @@
# I use spotify for my music needs. Gone are the days where I'd manage 200gb+ of
# local music; most of which I haven't heard or don't even like.
{ config, lib, pkgs, ... }:
{
# services.spotifyd doesn't work so we'll have to roll our own spotifyd +
# spotify-tui solution. The dbus interface doesn't work, though, so we have to
# wait for spotify-tui to implement CLI command for controlling spotify
# playback. See https://github.com/Rigellute/spotify-tui/issues/147 or for
# spotifyd to get fixed.
my.packages = with pkgs; [
unstable.spotifyd
(writeScriptBin "spt" ''
#!${stdenv.shell}
if ! systemctl --user is-active spotifyd >/dev/null; then
systemctl --user start spotifyd
fi
${unstable.spotify-tui}/bin/spt
'')
# spotify-tui is fine for selecting and playing music, but incomplete. We
# occasionally still need the official client for more sophisticated search
# and the "made for you" playlists.
spotify
];
systemd.user.services.spotifyd.serviceConfig =
let spotifydConf = pkgs.writeText "spotifyd.conf" ''
[global]
username = g2qwjcs6334oacg1zg9wrihnn
password_cmd = ${pkgs.pass}/bin/pass www/spotify.com | head -n1
backend = pulseaudio
'';
in {
ExecStart = "${pkgs.unstable.spotifyd}/bin/spotifyd --no-daemon --cache-path /tmp/spotifyd --config-path ${spotifydConf}";
Restart = "always";
RestartSec = 6;
};
}

View file

@ -1,14 +0,0 @@
# modules/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, lib, pkgs, ... }:
{
my.packages = with pkgs; [
audacity # for recording and remastering audio
obs-studio # for streaming to twitch/recording for youtube
handbrake # for encoding footage
];
}

View file

@ -1,6 +0,0 @@
{ config, lib, pkgs, ... }:
{
services.calibre-server.enable = true;
networking.firewall.allowedTCPPorts = [ 8080 ];
}

View file

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

View file

@ -0,0 +1,16 @@
{ config, lib, pkgs, ... }:
{
imports = [
# ./calibre-server.nix
# ./gitea.nix
# ./jellyfin.nix
# ./keybase.nix
# ./mpd.nix
# ./nginx.nix
# ./plex.nix
# ./ssh.nix
./syncthing.nix
# ./transmission.nix
];
}

View file

@ -1,26 +1,35 @@
{ config, lib, pkgs, ... }: { config, options, pkgs, lib, ... }:
with lib;
{ {
# I prefer git@... ssh addresses over gitea@... options.modules.services.gitea = {
users.users.git = { enable = mkOption {
useDefaultShell = true; type = types.bool;
home = "/var/lib/gitea"; default = false;
group = "gitea"; };
}; };
services.gitea = { config = mkIf config.modules.services.gitea.enable {
enable = true; # I prefer git@... ssh addresses over gitea@...
log.level = "Info"; users.users.git = {
useDefaultShell = true;
user = "git"; home = "/var/lib/gitea";
database = { group = "gitea";
user = "git";
type = "postgres";
}; };
useWizard = false;
disableRegistration = true;
# We're assuming SSL-only connectivity services.gitea = {
cookieSecure = true; enable = true;
log.level = "Info";
user = "git";
database = {
user = "git";
type = "postgres";
};
useWizard = false;
disableRegistration = true;
# We're assuming SSL-only connectivity
cookieSecure = true;
};
}; };
} }

View file

@ -1,14 +1,23 @@
# Finally, a decent open alternative to Plex! # Finally, a decent open alternative to Plex!
{ config, lib, pkgs, ... }: { config, options, pkgs, lib, ... }:
with lib;
{ {
services.jellyfin.enable = true; options.modules.services.jellyfin = {
enable = mkOption {
networking.firewall = { type = types.bool;
allowedTCPPorts = [ 8096 ]; default = false;
allowedUDPPorts = [ 8096 ]; };
}; };
my.user.extraGroups = [ "jellyfin" ]; config = mkIf config.modules.services.jellyfin.enable {
services.jellyfin.enable = true;
networking.firewall = {
allowedTCPPorts = [ 8096 ];
allowedUDPPorts = [ 8096 ];
};
my.user.extraGroups = [ "jellyfin" ];
};
} }

View file

@ -0,0 +1,14 @@
{ config, lib, pkgs, ... }:
{
services.kbfs = {
enable = true;
mountPoint = "%t/kbfs";
extraFlags = [ "-label %u" ];
};
systemd.user.services.kbfs = {
environment = { KEYBASE_RUN_MODE = "prod"; };
serviceConfig.Slice = "keybase.slice";
};
}

View file

@ -5,6 +5,8 @@
mpc_cli mpc_cli
]; ];
my.env.MPD_HOME = "$XDG_CONFIG_HOME/mpd";
services.mpd = { services.mpd = {
enable = true; enable = true;
musicDirectory = "/home/hlissner/music"; musicDirectory = "/home/hlissner/music";

View file

@ -1,15 +1,24 @@
{ config, lib, pkgs, ... }: { config, options, pkgs, lib, ... }:
with lib;
{ {
networking.firewall.allowedTCPPorts = [ 80 443 ]; options.modules.services.nginx = {
enable = mkOption {
type = types.bool;
default = false;
};
};
services.nginx = { config = mkIf config.modules.services.nginx.enable {
enable = true; networking.firewall.allowedTCPPorts = [ 80 443 ];
# Use recommended settings services.nginx = {
recommendedGzipSettings = true; enable = true;
recommendedOptimisation = true;
recommendedProxySettings = true; # Use recommended settings
recommendedTlsSettings = true; recommendedGzipSettings = true;
recommendedOptimisation = true;
recommendedProxySettings = true;
recommendedTlsSettings = true;
};
}; };
} }

View file

@ -1,20 +1,31 @@
{ config, pkgs, ... }: { config, pkgs, ... }:
{ config, options, pkgs, lib, ... }:
with lib;
{ {
services.openssh = { options.modules.services.ssh = {
enable = true; enable = mkOption {
forwardX11 = true; type = types.bool;
permitRootLogin = "no"; default = false;
passwordAuthentication = false; };
# Allow local LAN to connect with passwords
extraConfig = ''
Match address 192.168.0.0/24
PasswordAuthentication yes
'';
}; };
users.users.hlissner.openssh.authorizedKeys.keys = [ config = mkIf config.modules.services.ssh.enable {
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC8Tl2pj6CPBV3V72cohPhn+k0a/Na3cOrbmUtFC7rR7icWocSs1S1cSrP3sPLwUqRh3+zfIuLXTrTv3gj8Xvg8WELOspzsiYeAtbcHrnWnx/a7xzYvFyT9/8hkiGM/F6w7IuKEk+AZW34vARSgRPJ1FdH8NbPKJ8ay9zW9XB9YJGnbzIRmsVVpQ8l6Fh8ZqRjZfC1ea7hns8+HgjPrIHFb+S3qZZiwU4Gc8aWJy9ziwwkllEsSchv3aigYA3eOeW0FUQFiKsLGxbX2b2b3d6jFO4Pu+dMSen0h5IzBo0nh7UADSfJPdwbZaMuJzviKe2y6zg6jaM9XRIhLBT6bftDr henrik@lissner.net" services.openssh = {
]; enable = true;
forwardX11 = true;
permitRootLogin = "no";
passwordAuthentication = false;
# Allow local LAN to connect with passwords
extraConfig = ''
Match address 192.168.0.0/24
PasswordAuthentication yes
'';
};
users.users.hlissner.openssh.authorizedKeys.keys = [
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC8Tl2pj6CPBV3V72cohPhn+k0a/Na3cOrbmUtFC7rR7icWocSs1S1cSrP3sPLwUqRh3+zfIuLXTrTv3gj8Xvg8WELOspzsiYeAtbcHrnWnx/a7xzYvFyT9/8hkiGM/F6w7IuKEk+AZW34vARSgRPJ1FdH8NbPKJ8ay9zW9XB9YJGnbzIRmsVVpQ8l6Fh8ZqRjZfC1ea7hns8+HgjPrIHFb+S3qZZiwU4Gc8aWJy9ziwwkllEsSchv3aigYA3eOeW0FUQFiKsLGxbX2b2b3d6jFO4Pu+dMSen0h5IzBo0nh7UADSfJPdwbZaMuJzviKe2y6zg6jaM9XRIhLBT6bftDr henrik@lissner.net"
];
};
} }

View file

@ -1,60 +1,69 @@
{ config, lib, pkgs, ... }: { config, options, pkgs, lib, ... }:
with lib;
{ {
services.syncthing = { options.modules.services.syncthing = {
enable = true; enable = mkOption {
openDefaultPorts = true; type = types.bool;
user = config.my.username; default = false;
configDir = "/home/${config.my.username}/.config/syncthing"; };
dataDir = "/home/${config.my.username}/.local/share/syncthing"; };
declarative = {
devices = { config = mkIf config.modules.services.syncthing.enable {
kuro.id = "4UJSUBN-V7LCISG-6ZE7SBN-YPXM5FQ-CE7CD2U-W4KZC7O-4HUZZSW-6DXAGQQ"; services.syncthing = {
shiro.id = "G4DUO25-AMQQIWS-SRZE5TJ-43CCQZJ-5ULEZBS-P2LMZZU-V5JA5CS-6X7RLQK"; enable = true;
aka.id = "IZQ2GAC-I3QBTRT-TXBIG7Z-NT6S66Y-H64WOCO-T3AMKYZ-VGWTNCY-CTQOLQN"; openDefaultPorts = true;
ao.id = "NBMLUKD-PJRXCTM-GQ2WFLE-NN4IGSN-6WSC6JL-M6XN7PE-HCBTOKV-7VER2QE"; user = config.my.username;
# Windows machine; set up the other end yourself! configDir = "/home/${config.my.username}/.config/syncthing";
midori.id = "BOFH5JP-A3MPTJA-EGIZVWV-URHUTSJ-2ZXCAA2-XMZPPSR-GLMOQFL-ZX7DGQP"; dataDir = "/home/${config.my.username}/.local/share/syncthing";
}; declarative = {
folders = devices = {
let deviceEnabled = devices: lib.elem config.networking.hostName devices; kuro.id = "4UJSUBN-V7LCISG-6ZE7SBN-YPXM5FQ-CE7CD2U-W4KZC7O-4HUZZSW-6DXAGQQ";
deviceType = devices: shiro.id = "G4DUO25-AMQQIWS-SRZE5TJ-43CCQZJ-5ULEZBS-P2LMZZU-V5JA5CS-6X7RLQK";
if deviceEnabled devices aka.id = "IZQ2GAC-I3QBTRT-TXBIG7Z-NT6S66Y-H64WOCO-T3AMKYZ-VGWTNCY-CTQOLQN";
then "sendreceive" ao.id = "NBMLUKD-PJRXCTM-GQ2WFLE-NN4IGSN-6WSC6JL-M6XN7PE-HCBTOKV-7VER2QE";
else "receiveonly"; # Windows machine; set up the other end yourself!
in { midori.id = "BOFH5JP-A3MPTJA-EGIZVWV-URHUTSJ-2ZXCAA2-XMZPPSR-GLMOQFL-ZX7DGQP";
archive = rec {
devices = [ "kuro" "ao" "midori" ];
path = "/home/${config.my.username}/archive";
watch = false;
rescanInterval = 3600 * 6;
type = deviceType ["kuro"];
enable = deviceEnabled devices;
};
share = rec {
devices = [ "kuro" "shiro" "ao" "aka" "midori" ];
path = "/home/${config.my.username}/share";
watch = true;
rescanInterval = 3600 * 6;
enable = deviceEnabled devices;
};
projects = rec {
devices = [ "kuro" "shiro" "ao" "midori" ];
path = "/home/${config.my.username}/projects";
watch = false;
rescanInterval = 3600 * 2;
type = deviceType ["kuro" "shiro"];
enable = deviceEnabled devices;
};
secrets = rec {
devices = [ "kuro" "shiro" "ao" "aka" ];
path = "/home/${config.my.username}/.secrets";
watch = true;
rescanInterval = 3600;
type = deviceType ["kuro" "shiro"];
enable = deviceEnabled devices;
};
}; };
folders =
let deviceEnabled = devices: lib.elem config.networking.hostName devices;
deviceType = devices:
if deviceEnabled devices
then "sendreceive"
else "receiveonly";
in {
archive = rec {
devices = [ "kuro" "ao" "midori" ];
path = "/home/${config.my.username}/archive";
watch = false;
rescanInterval = 3600 * 6;
type = deviceType ["kuro"];
enable = deviceEnabled devices;
};
share = rec {
devices = [ "kuro" "shiro" "ao" "aka" "midori" ];
path = "/home/${config.my.username}/share";
watch = true;
rescanInterval = 3600 * 6;
enable = deviceEnabled devices;
};
projects = rec {
devices = [ "kuro" "shiro" "ao" "midori" ];
path = "/home/${config.my.username}/projects";
watch = false;
rescanInterval = 3600 * 2;
type = deviceType ["kuro" "shiro"];
enable = deviceEnabled devices;
};
secrets = rec {
devices = [ "kuro" "shiro" "ao" "aka" ];
path = "/home/${config.my.username}/.secrets";
watch = true;
rescanInterval = 3600;
type = deviceType ["kuro" "shiro"];
enable = deviceEnabled devices;
};
};
};
}; };
}; };
} }

15
modules/shell/default.nix Normal file
View file

@ -0,0 +1,15 @@
{ config, lib, pkgs, ... }:
{
imports = [
./direnv.nix
./git.nix
./gnupg.nix
./ncmpcpp.nix
./pass.nix
./ranger.nix
./tmux.nix
./weechat.nix
./zsh.nix
];
}

View file

@ -1,10 +1,17 @@
{ config, lib, pkgs, ... }: { config, options, lib, pkgs, ... }:
with lib;
{ {
services.lorri.enable = true; options.modules.shell.direnv = {
enable = mkOption { type = types.bool; default = false; };
};
my = { config = mkIf config.modules.shell.direnv.enable {
packages = [ pkgs.direnv ]; my = {
zsh.rc = "_cache direnv hook zsh"; packages = [ pkgs.direnv ];
zsh.rc = "_cache direnv hook zsh";
};
services.lorri.enable = true;
}; };
} }

View file

@ -1,16 +1,26 @@
{ config, lib, pkgs, ... }: { config, lib, pkgs, ... }:
with lib;
{ {
my = { options.modules.shell.git = {
packages = with pkgs; [ enable = mkOption {
gitAndTools.hub type = types.bool;
gitAndTools.diff-so-fancy default = false;
]; };
zsh.rc = lib.readFile <config/git/aliases.zsh>; };
# Do recursively, in case git stores files in this folder
home.xdg.configFile = { config = mkIf config.modules.shell.git.enable {
"git/config".source = <config/git/config>; my = {
"git/ignore".source = <config/git/ignore>; packages = with pkgs; [
gitAndTools.hub
gitAndTools.diff-so-fancy
];
zsh.rc = lib.readFile <config/git/aliases.zsh>;
# Do recursively, in case git stores files in this folder
home.xdg.configFile = {
"git/config".source = <config/git/config>;
"git/ignore".source = <config/git/ignore>;
};
}; };
}; };
} }

View file

@ -1,27 +1,37 @@
{ config, lib, pkgs, ... }: { config, options, lib, pkgs, ... }:
{ with lib;
my = { let cfg = config.modules;
packages = with pkgs; [ gnupgCfg = cfg.shell.gnupg;
gnupg in {
pinentry options.modules.shell.gnupg = {
enable = mkOption { type = types.bool; default = false; };
cacheTTL = mkOption { type = types.int; default = 1800; };
};
config = mkIf gnupgCfg.enable {
my = {
packages = with pkgs; [
gnupg
pinentry
];
env.GNUPGHOME = "$XDG_CONFIG_HOME/gnupg";
init = "mkdir -p \"$GNUPGHOME\" -m 700";
};
programs.gnupg.agent = {
enable = true;
enableSSHSupport = true;
};
systemd.user.services.gpg-agent.serviceConfig.ExecStart = [
"" ''
${pkgs.gnupg}/bin/gpg-agent \
--supervised \
--allow-emacs-pinentry \
--default-cache-ttl ${toString gnupgCfg.cacheTTL} \
--pinentry-program ${pkgs.pinentry}/bin/pinentry-gtk-2
''
]; ];
env.GNUPGHOME = "$XDG_CONFIG_HOME/gnupg";
init = "mkdir -p \"$GNUPGHOME\" -m 700";
}; };
programs.gnupg.agent = {
enable = true;
enableSSHSupport = true;
};
systemd.user.services.gpg-agent.serviceConfig.ExecStart = [
"" ''
${pkgs.gnupg}/bin/gpg-agent \
--supervised \
--allow-emacs-pinentry \
--default-cache-ttl 1800 \
--pinentry-program ${pkgs.pinentry}/bin/pinentry-gtk-2
''
];
} }

View file

@ -1,21 +1,29 @@
{ config, lib, pkgs, ... }: { config, options, lib, pkgs, ... }:
with lib;
{ {
my.packages = with pkgs; [ options.modules.shell.ncmpcpp = {
(ncmpcpp.override { visualizerSupport = true; }) enable = mkOption {
]; type = types.bool;
default = false;
};
};
my.env.MPD_HOME = "$XDG_CONFIG_HOME/mpd"; config = mkIf config.modules.shell.ncmpcpp.enable {
my.env.NCMPCPP_HOME = "$XDG_CONFIG_HOME/ncmpcpp"; my.packages = with pkgs; [
(ncmpcpp.override { visualizerSupport = true; })
];
my.alias.rate = "mpd-rate"; my.alias.rate = "mpd-rate";
my.alias.mpcs = "mpc search any"; my.alias.mpcs = "mpc search any";
my.alias.mpcsp = "mpc searchplay any"; my.alias.mpcsp = "mpc searchplay any";
# Symlink these one at a time because ncmpcpp writes other files to my.env.NCMPCPP_HOME = "$XDG_CONFIG_HOME/ncmpcpp";
# ~/.config/ncmpcpp, so it needs to be writeable.
my.home.xdg.configFile = { # Symlink these one at a time because ncmpcpp writes other files to
"ncmpcpp/config".source = <config/ncmpcpp/config>; # ~/.config/ncmpcpp, so it needs to be writeable.
"ncmpcpp/bindings".source = <config/ncmpcpp/bindings>; my.home.xdg.configFile = {
"ncmpcpp/config".source = <config/ncmpcpp/config>;
"ncmpcpp/bindings".source = <config/ncmpcpp/bindings>;
};
}; };
} }

View file

@ -1,13 +1,22 @@
{ config, pkgs, lib, ... }: { config, options, pkgs, lib, ... }:
with lib;
{ {
my = { options.modules.shell.pass = {
packages = with pkgs; [ enable = mkOption {
(pass.withExtensions (exts: [ type = types.bool;
exts.pass-otp default = false;
exts.pass-genphrase };
])) };
];
env.PASSWORD_STORE_DIR = "$HOME/.secrets/password-store"; config = mkIf config.modules.shell.pass.enable {
my = {
packages = with pkgs; [
(pass.withExtensions (exts: [
exts.pass-otp
exts.pass-genphrase
]))
];
env.PASSWORD_STORE_DIR = "$HOME/.secrets/password-store";
};
}; };
} }

View file

@ -1,9 +1,18 @@
{ config, lib, pkgs, ... }: { config, options, pkgs, lib, ... }:
with lib;
{ {
my.packages = with pkgs; [ options.modules.shell.ranger = {
ranger enable = mkOption {
(lib.mkIf config.services.xserver.enable type = types.bool;
w3m) default = false;
]; };
};
config = mkIf config.modules.shell.ranger.enable {
my.packages = with pkgs; [
ranger
# For image previews
(lib.mkIf config.services.xserver.enable w3m)
];
};
} }

View file

@ -1,32 +1,41 @@
{ config, lib, pkgs, ... }: { config, options, pkgs, lib, ... }:
with lib;
{ {
my = { options.modules.shell.tmux = {
packages = with pkgs; [ enable = mkOption {
# The developer of tmux chooses not to add XDG support for religious type = types.bool;
# reasons (see tmux/tmux#142). Fortunately, nix makes this easy: default = false;
(writeScriptBin "tmux" '' };
#!${stdenv.shell} };
exec ${tmux}/bin/tmux -f "$TMUX_HOME/config" "$@"
'')
];
env.TMUX_HOME = "$XDG_CONFIG_HOME/tmux"; config = mkIf config.modules.shell.tmux.enable {
env.TMUXIFIER = "$XDG_DATA_HOME/tmuxifier"; my = {
env.TMUXIFIER_LAYOUT_PATH = "$XDG_DATA_HOME/tmuxifier"; packages = with pkgs; [
env.PATH = [ "$TMUXIFIER/bin" ]; # The developer of tmux chooses not to add XDG support for religious
# reasons (see tmux/tmux#142). Fortunately, nix makes this easy:
(writeScriptBin "tmux" ''
#!${stdenv.shell}
exec ${tmux}/bin/tmux -f "$TMUX_HOME/config" "$@"
'')
];
zsh.rc = '' env.TMUX_HOME = "$XDG_CONFIG_HOME/tmux";
_cache tmuxifier init - env.TMUXIFIER = "$XDG_DATA_HOME/tmuxifier";
${lib.readFile <config/tmux/aliases.zsh>} env.TMUXIFIER_LAYOUT_PATH = "$XDG_DATA_HOME/tmuxifier";
''; env.PATH = [ "$TMUXIFIER/bin" ];
home.xdg.configFile = {
"tmux" = { source = <config/tmux>; recursive = true; }; zsh.rc = ''
"tmux/plugins".text = '' _cache tmuxifier init -
run-shell ${pkgs.tmuxPlugins.copycat}/share/tmux-plugins/copycat/copycat.tmux ${lib.readFile <config/tmux/aliases.zsh>}
run-shell ${pkgs.tmuxPlugins.prefix-highlight}/share/tmux-plugins/prefix-highlight/prefix_highlight.tmux
run-shell ${pkgs.tmuxPlugins.yank}/share/tmux-plugins/yank/yank.tmux
''; '';
home.xdg.configFile = {
"tmux" = { source = <config/tmux>; recursive = true; };
"tmux/plugins".text = ''
run-shell ${pkgs.tmuxPlugins.copycat}/share/tmux-plugins/copycat/copycat.tmux
run-shell ${pkgs.tmuxPlugins.prefix-highlight}/share/tmux-plugins/prefix-highlight/prefix_highlight.tmux
run-shell ${pkgs.tmuxPlugins.yank}/share/tmux-plugins/yank/yank.tmux
'';
};
}; };
}; };
} }

17
modules/shell/weechat.nix Normal file
View file

@ -0,0 +1,17 @@
{ config, options, lib, pkgs, ... }:
with lib;
{
options.modules.shell.weechat = {
enable = mkOption {
type = types.bool;
default = false;
};
};
config = mkIf config.modules.shell.weechat.enable {
my.packages = with pkgs; [
weechat
];
};
}

View file

@ -1,48 +1,58 @@
# modules/shell/zsh.nix --- ... # modules/shell/zsh.nix --- ...
{ pkgs, libs, ... }: { config, options, pkgs, lib, ... }:
with lib;
{ {
my = { options.modules.shell.zsh = {
packages = with pkgs; [ enable = mkOption {
zsh type = types.bool;
nix-zsh-completions default = false;
bat
exa
fasd
fd
fzf
htop
tldr
tree
];
env.ZDOTDIR = "$XDG_CONFIG_HOME/zsh";
env.ZSH_CACHE = "$XDG_CACHE_HOME/zsh";
alias.exa = "exa --group-directories-first";
alias.l = "exa -1";
alias.ll = "exa -lg";
alias.la = "LC_COLLATE=C exa -la";
alias.sc = "systemctl";
alias.ssc = "sudo systemctl";
# Write it recursively so other modules can write files to it
home.xdg.configFile."zsh" = {
source = <config/zsh>;
recursive = true;
}; };
}; };
programs.zsh = { config = mkIf config.modules.shell.zsh.enable {
enable = true; my = {
enableCompletion = true; packages = with pkgs; [
# I init completion myself, because enableGlobalCompInit initializes it too zsh
# soon, which means commands initialized later in my config won't get nix-zsh-completions
# completion, and running compinit twice is slow. bat
enableGlobalCompInit = false; exa
promptInit = ""; fasd
}; fd
fzf
htop
tldr
tree
];
env.ZDOTDIR = "$XDG_CONFIG_HOME/zsh";
env.ZSH_CACHE = "$XDG_CACHE_HOME/zsh";
system.userActivationScripts.cleanupZgen = '' alias.exa = "exa --group-directories-first";
rm -fv $XDG_CACHE_HOME/zsh/* alias.l = "exa -1";
''; alias.ll = "exa -lg";
alias.la = "LC_COLLATE=C exa -la";
alias.sc = "systemctl";
alias.ssc = "sudo systemctl";
# Write it recursively so other modules can write files to it
home.xdg.configFile."zsh" = {
source = <config/zsh>;
recursive = true;
};
};
programs.zsh = {
enable = true;
enableCompletion = true;
# I init completion myself, because enableGlobalCompInit initializes it too
# soon, which means commands initialized later in my config won't get
# completion, and running compinit twice is slow.
enableGlobalCompInit = false;
promptInit = "";
};
system.userActivationScripts.cleanupZgen = ''
rm -fv $XDG_CACHE_HOME/zsh/*
'';
};
} }

View file

@ -1,68 +1,80 @@
# modules/themes/aquanaut/default.nix --- a sea-blue linux theme # themes/aquanaut/default.nix --- a sea-blue linux theme
{ config, lib, pkgs, ... }: { config, options, lib, pkgs, ... }:
with lib;
{ {
imports = [ ../. ]; # Load framework for themes options.modules.themes.aquanaut = {
enable = mkOption {
theme.wallpaper = ./wallpaper.jpg; type = types.bool;
default = false;
services.compton = {
activeOpacity = "0.96";
inactiveOpacity = "0.75";
settings = {
blur-background = true;
blur-background-frame = true;
blur-background-fixed = true;
blur-kern = "7x7box";
blur-strength = 340;
}; };
}; };
services.xserver.displayManager.lightdm = { config = mkIf config.modules.themes.aquanaut.enable {
greeters.mini.extraConfig = '' modules.theme = {
text-color = "#bbc2cf" name = "Aquanaut";
password-background-color = "#29323d" version = "0.1";
window-color = "#0b1117" path = ./.;
border-color = "#0b1117" };
'';
};
fonts.fonts = [ pkgs.nerdfonts ]; services.compton = {
my.packages = with pkgs; [ activeOpacity = "0.96";
nordic inactiveOpacity = "0.75";
paper-icon-theme # for rofi settings = {
]; blur-background = true;
my.zsh.rc = lib.readFile ./zsh/prompt.zsh; blur-background-frame = true;
my.home.xdg.configFile = { blur-background-fixed = true;
"bspwm/rc.d/polybar".source = ./polybar/run.sh; blur-kern = "7x7box";
"bspwm/rc.d/theme".source = ./bspwmrc; blur-strength = 340;
"dunst/dunstrc".source = ./dunstrc; };
"polybar" = { source = ./polybar; recursive = true; }; };
"rofi/theme" = { source = ./rofi; recursive = true; };
"tmux/theme".source = ./tmux.conf; services.xserver.displayManager.lightdm = {
"xtheme/90-theme".source = ./Xresources; greeters.mini.extraConfig = ''
# GTK text-color = "#bbc2cf"
"gtk-3.0/settings.ini".text = '' password-background-color = "#29323d"
[Settings] window-color = "#0b1117"
gtk-theme-name=Nordic-blue border-color = "#0b1117"
gtk-icon-theme-name=Paper '';
gtk-fallback-icon-theme=gnome };
gtk-application-prefer-dark-theme=true
gtk-cursor-theme-name=Paper fonts.fonts = [ pkgs.nerdfonts ];
gtk-xft-hinting=1 my.packages = with pkgs; [
gtk-xft-hintstyle=hintfull nordic
gtk-xft-rgba=none paper-icon-theme # for rofi
''; ];
# GTK2 global theme (widget and icon theme) my.zsh.rc = lib.readFile ./zsh/prompt.zsh;
"gtk-2.0/gtkrc".text = '' my.home.xdg.configFile = {
gtk-theme-name="Nordic-blue" "bspwm/rc.d/polybar".source = ./polybar/run.sh;
gtk-icon-theme-name="Paper-Mono-Dark" "bspwm/rc.d/theme".source = ./bspwmrc;
gtk-font-name="Sans 10" "dunst/dunstrc".source = ./dunstrc;
''; "polybar" = { source = ./polybar; recursive = true; };
# QT4/5 global theme "rofi/theme" = { source = ./rofi; recursive = true; };
"Trolltech.conf".text = '' "tmux/theme".source = ./tmux.conf;
[Qt] "xtheme/90-theme".source = ./Xresources;
style=Nordic-blue # GTK
''; "gtk-3.0/settings.ini".text = ''
[Settings]
gtk-theme-name=Nordic-blue
gtk-icon-theme-name=Paper
gtk-fallback-icon-theme=gnome
gtk-application-prefer-dark-theme=true
gtk-cursor-theme-name=Paper
gtk-xft-hinting=1
gtk-xft-hintstyle=hintfull
gtk-xft-rgba=none
'';
# GTK2 global theme (widget and icon theme)
"gtk-2.0/gtkrc".text = ''
gtk-theme-name="Nordic-blue"
gtk-icon-theme-name="Paper-Mono-Dark"
gtk-font-name="Sans 10"
'';
# QT4/5 global theme
"Trolltech.conf".text = ''
[Qt]
style=Nordic-blue
'';
};
}; };
} }

View file

@ -1,16 +1,56 @@
# modules/themes/default.nix { config, options, lib, pkgs, ... }:
{ config, ... }: with lib;
{ {
imports = [ ./options.nix ]; imports = [
# aquanaut = callPackage (import ./aquanaut {});
./fluorescence
];
# Try really hard to get QT to respect my GTK theme. options.modules.theme = {
my.env.GTK_DATA_PREFIX = [ "${config.system.path}" ]; name = mkOption { type = with types; nullOr str; default = null; };
my.env.QT_QPA_PLATFORMTHEME = "gtk2"; version = mkOption { type = with types; nullOr str; default = null; };
qt5 = { style = "gtk2"; platformTheme = "gtk2"; }; path = mkOption {
services.xserver.displayManager.sessionCommands = '' type = with types; nullOr path;
export GTK2_RC_FILES="$XDG_CONFIG_HOME/gtk-2.0/gtkrc" default = null;
source "$XDG_CONFIG_HOME"/xsession/*.sh };
xrdb -merge "$XDG_CONFIG_HOME"/xtheme/*
''; wallpaper = {
path = mkOption {
type = with types; nullOr str;
default = if config.modules.theme.path != null
then "${config.modules.theme.path}/wallpaper.png"
else null;
};
filter = {
enable = mkOption {
type = types.bool;
default = true;
};
options = mkOption {
type = types.str;
default = "-gaussian-blur 0x2 -modulate 70 -level 5%";
};
};
};
};
config = mkIf (config.modules.theme.wallpaper.path != null &&
builtins.pathExists config.modules.theme.wallpaper.path) {
my.home.home.file.".background-image".source =
config.modules.theme.wallpaper.path;
services.xserver.displayManager.lightdm.background =
mkIf config.modules.theme.wallpaper.filter.enable
(let filteredPath = "wallpaper.filtered.png";
filteredWallpaper =
with pkgs; runCommand "filterWallpaper"
{ buildInputs = [ imagemagick ]; } ''
mkdir "$out"
convert ${config.modules.theme.wallpaper.filter.options} \
${config.modules.theme.wallpaper.path} $out/${filteredPath}
'';
in "${filteredWallpaper}/${filteredPath}");
};
} }

View file

@ -1,75 +1,111 @@
# modules/themes/aquanaut/default.nix --- a sea-blue linux theme # themes/fluorescence/default.nix --- a regal dracula-inspired theme
{ config, lib, pkgs, ... }: { config, options, lib, pkgs, ... }:
with lib;
{ {
imports = [ ../. ]; # Load framework for themes options.modules.themes.fluorescence = {
enable = mkOption {
theme.wallpaper = ./wallpaper.png; type = types.bool;
default = false;
services.compton = {
fade = true;
fadeDelta = 1;
fadeSteps = [ "0.01" "0.012" ];
shadow = true;
shadowOffsets = [ (-10) (-10) ];
shadowOpacity = "0.22";
# activeOpacity = "1.00";
# inactiveOpacity = "0.92";
settings = {
shadow-radius = 12;
# blur-background = true;
# blur-background-frame = true;
# blur-background-fixed = true;
blur-kern = "7x7box";
blur-strength = 320;
}; };
}; };
services.xserver.displayManager.lightdm = { config = mkIf config.modules.themes.fluorescence.enable {
greeters.mini.extraConfig = '' modules.theme = {
text-color = "#ff79c6" name = "fluorescence";
password-background-color = "#1E2029" version = "0.0.1";
window-color = "#181a23" path = ./.;
border-color = "#181a23"
'';
};
fonts.fonts = [ pkgs.nerdfonts ]; wallpaper = {
my.packages = with pkgs; [ filter.options = "-gaussian-blur 0x2 -modulate 70 -level 5%";
my.ant-dracula };
paper-icon-theme # for rofi };
];
my.zsh.rc = lib.readFile ./zsh/prompt.zsh; services.compton = {
my.home.xdg.configFile = { fade = true;
"bspwm/rc.d/polybar".source = ./polybar/run.sh; fadeDelta = 1;
"bspwm/rc.d/theme".source = ./bspwmrc; fadeSteps = [ "0.01" "0.012" ];
"dunst/dunstrc".source = ./dunstrc; shadow = true;
"polybar" = { source = ./polybar; recursive = true; }; shadowOffsets = [ (-10) (-10) ];
"rofi/theme" = { source = ./rofi; recursive = true; }; shadowOpacity = "0.22";
"tmux/theme".source = ./tmux.conf; # activeOpacity = "1.00";
"xtheme/90-theme".source = ./Xresources; # inactiveOpacity = "0.92";
# GTK settings = {
"gtk-3.0/settings.ini".text = '' shadow-radius = 12;
[Settings] # blur-background = true;
gtk-theme-name=Ant-Dracula # blur-background-frame = true;
gtk-icon-theme-name=Paper # blur-background-fixed = true;
gtk-fallback-icon-theme=gnome blur-kern = "7x7box";
gtk-application-prefer-dark-theme=true blur-strength = 320;
gtk-cursor-theme-name=Paper };
gtk-xft-hinting=1 };
gtk-xft-hintstyle=hintfull
gtk-xft-rgba=none services.xserver.displayManager.lightdm = {
''; greeters.mini.extraConfig = ''
# GTK2 global theme (widget and icon theme) text-color = "#ff79c6"
"gtk-2.0/gtkrc".text = '' password-background-color = "#1E2029"
gtk-theme-name="Ant-Dracula" window-color = "#181a23"
gtk-icon-theme-name="Paper-Mono-Dark" border-color = "#181a23"
gtk-font-name="Sans 10" '';
''; };
# QT4/5 global theme
"Trolltech.conf".text = '' fonts.fonts = [ pkgs.nerdfonts ];
[Qt] my.packages = with pkgs; [
style=Ant-Dracula my.ant-dracula
''; paper-icon-theme # for rofi
];
my.zsh.rc = lib.readFile ./zsh/prompt.zsh;
my.home.xdg = {
configFile = {
"bspwm/rc.d/polybar".source = ./polybar/run.sh;
"bspwm/rc.d/theme".source = ./bspwmrc;
"dunst/dunstrc".source = ./dunstrc;
"polybar" = { source = ./polybar; recursive = true; };
"rofi/theme" = { source = ./rofi; recursive = true; };
"tmux/theme".source = ./tmux.conf;
"xtheme/90-theme".source = ./Xresources;
# GTK
"gtk-3.0/settings.ini".text = ''
[Settings]
gtk-theme-name=Ant-Dracula
gtk-icon-theme-name=Paper
gtk-fallback-icon-theme=gnome
gtk-application-prefer-dark-theme=true
gtk-cursor-theme-name=Paper
gtk-xft-hinting=1
gtk-xft-hintstyle=hintfull
gtk-xft-rgba=none
'';
# GTK2 global theme (widget and icon theme)
"gtk-2.0/gtkrc".text = ''
gtk-theme-name="Ant-Dracula"
gtk-icon-theme-name="Paper-Mono-Dark"
gtk-font-name="Sans 10"
'';
# QT4/5 global theme
"Trolltech.conf".text = ''
[Qt]
style=Ant-Dracula
'';
};
dataFile = mkIf config.modules.desktop.browsers.qutebrowser.enable {
"qutebrowser/userstyles.css".source =
let compiledStyles =
with pkgs; runCommand "compileUserStyles"
{ buildInputs = [ sass ]; } ''
mkdir "$out"
for file in ${./userstyles/qutebrowser}/*.scss; do
scss --sourcemap=none \
--no-cache \
--style compressed \
--default-encoding utf-8 \
"$file" \
>>"$out/userstyles.css"
done
'';
in "${compiledStyles}/userstyles.css";
};
};
}; };
} }

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,3 @@
textarea {
font-family: monospace;
}

View file

@ -1,27 +0,0 @@
# modules/themes/options.nix
{ options, config, lib, pkgs, ... }:
with lib;
{
options.theme = {
wallpaper = mkOption {
type = with types; nullOr (either str path);
};
# TODO Colors?
};
config = {
my.home.home.file.".background-image".source = config.theme.wallpaper;
services.xserver.displayManager.lightdm.background =
let blurredWallpaper =
with pkgs; runCommand "blurWallpaper"
{ buildInputs = [ imagemagick ]; } ''
mkdir "$out"
convert -gaussian-blur 0x2 -modulate 70 -level 5% \
${config.theme.wallpaper} $out/wallpaper.blurred.png
'';
in mkIf (config.theme.wallpaper != null)
"${blurredWallpaper}/wallpaper.blurred.png";
};
}

View file

@ -1,14 +0,0 @@
# modules/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, lib, pkgs, ... }:
{
virtualisation.virtualbox.host = {
enable = true;
enableExtensionPack = true; # urg, takes so long to build
};
my.user.extraGroups = [ "vboxusers" ];
}

View file

@ -1,89 +0,0 @@
{ config, options, lib, ... }:
with lib;
let mkOptionStr = value: mkOption
{ type = types.str;
default = value; };
in
{
imports = [ <home-manager/nixos> ];
## Personal settings
options.my.username = mkOptionStr "hlissner";
options.my.email = mkOptionStr "henrik@lissner.net";
## Convenience aliases
options.my.home = mkOption
{ type = options.home-manager.users.type.functor.wrapped; };
config.home-manager.users.${config.my.username} = mkAliasDefinitions options.my.home;
options.my.user = mkOption { type = types.submodule; };
config.users.users.${config.my.username} = mkAliasDefinitions options.my.user;
options.my.packages = mkOption
{ type = types.listOf types.package;
description = "The set of packages to appear in the user environment."; };
config.my.user.packages = config.my.packages;
## Shell/Environment
options.my.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));
};
options.my.init = mkOption {
type = types.lines;
description = ''
An init script that runs after the environment has been rebuilt or
booted. Anything done here should be idempotent and inexpensive.
'';
};
## PATH should always start with its old value
config.my.env.PATH = [ ./bin "$PATH" ];
config.environment.extraInit =
let exportLines = mapAttrsToList (n: v: "export ${n}=\"${v}\"") config.my.env;
in ''
${concatStringsSep "\n" exportLines}
${config.my.init}
'';
options.my.alias = mkOption
{ type = with types; nullOr (attrsOf (nullOr (either str path))); };
options.my.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
'';
};
};
# I avoid programs.zsh.*Init variables because they initialize too soon. My
# zsh config is particular about load order.
config.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}
'';
config.my.home.xdg.configFile."zsh/extra.zshenv".text = ''
# This file is autogenerated, do not edit it!
${config.my.zsh.env};
'';
}