This commit is contained in:
chayleaf 2023-01-24 02:24:40 +07:00
commit 7d7450ebbc
16 changed files with 1233 additions and 0 deletions

2
.gitignore vendored Normal file
View file

@ -0,0 +1,2 @@
flake.lock
private.nix

33
home/common/firefox.nix Normal file
View file

@ -0,0 +1,33 @@
{ config, pkgs, ... }:
{
imports = [ ./gui.nix ];
programs.firefox = {
enable = true;
package = pkgs.librewolf;
extensions = with config.nur.repos.rycee.firefox-addons; [
youtube-shorts-block
vimium-c
search-by-image
unpaywall
ublock-origin
steam-database
sponsorblock
rust-search-extension
return-youtube-dislikes
protondb-for-steam
privacy-redirect
privacy-pass
noscript
localcdn
keepassxc-browser
i-dont-care-about-cookies
greasemonkey
don-t-fuck-with-paste
cookies-txt
# also yomichan, maybe i should package it
];
profiles = {
chayleaf = {};
};
};
}

60
home/common/general.nix Normal file
View file

@ -0,0 +1,60 @@
{ config, pkgs, ... }:
{
imports = [ ./options.nix ];
manual.json.enable = true;
services.gpg-agent = {
enable = true;
enableSshSupport = true;
maxCacheTtl = 72000;
maxCacheTtlSsh = 72000;
};
programs = {
neomutt = {
enable = true;
sidebar.enable = true;
vimKeys = true;
};
home-manager.enable = true;
bash = {
enable = true;
};
fish = {
enable = true;
interactiveShellInit = ''
${pkgs.gnupg}/bin/gpg-connect-agent --quiet updatestartuptty /bye > /dev/null
'';
shellInit = ''
set PATH ~/bin/:$PATH
'';
shellAbbrs = {
};
};
git = {
enable = true;
package = pkgs.gitAndTools.gitFull;
delta.enable = true;
};
ssh = {
enable = true;
compression = true;
};
tmux = {
enable = true;
clock24 = true;
customPaneNavigationAndResize = true;
keyMode = "vi";
};
gpg = {
enable = true;
homedir = "${config.xdg.dataHome}/gnupg";
mutableKeys = true;
mutableTrust = true;
};
nix-index.enable = true;
};
home.packages = with pkgs; [
rclone fuse jq appimage-run python3Full
];
}

115
home/common/gui.nix Normal file
View file

@ -0,0 +1,115 @@
{ config, pkgs, lib, ... }:
{
# TODO sort out this mess with colors
programs.mpv = {
enable = true;
defaultProfiles = [ "main" ];
profiles.main = {
vo = "vdpau";
alang = "jpn,en,ru";
slang = "jpn,en,ru";
vlang = "jpn,en,ru";
};
scripts = [ ];
};
i18n.inputMethod = let fcitx5-qt = pkgs.libsForQt5.fcitx5-qt; in {
enabled = "fcitx5";
fcitx5.addons = with pkgs; [ fcitx5-lua fcitx5-gtk fcitx5-mozc fcitx5-configtool fcitx5-qt ];
};
xresources.properties = {
# special colors
"*.foreground" = "#ebdadd";
"*.background" = "[75]#24101a";
"*.cursorColor" = "#ebdadd";
# black
"*.color0" = "#523b3f"; # "#3b4252";
"*.color8" = "#6b4d52"; # "#4c566a";
# red
"*.color1" = "#e66e6e";
"*.color9" = "#e66e6e";
# green
"*.color2" = "#8cbf73";
"*.color10" = "#8cbf73";
# yellow
"*.color3" = "#ebbe5f";
"*.color11" = "#ebbe5f";
# blue
"*.color4" = "#5968b3";
"*.color12" = "#5968b3";
# magenta
"*.color5" = "#a64999";
"*.color13" = "#a64999";
# cyan
"*.color6" = "#77c7c2";
"*.color14" = "#77c7c2";
# white
"*.color7" = "#f0e4e6";
"*.color15" = "#f7f0f1";
"*antialias" = true;
"*autohint" = true;
# "*fading" = 0;
# "*fadeColor" = "#6b4d52";
};
services.gammastep.enable = true;
services.kdeconnect.enable = true;
fonts.fontconfig.enable = true;
gtk = {
enable = true;
font.name = "Noto Sans";
font.size = 10;
iconTheme = {
package = pkgs.papirus-icon-theme;
name = "Papirus-Dark";
};
theme = {
package = pkgs.breeze-gtk;
name = "Breeze-Dark";
};
};
programs.fzf = {
enable = true;
};
systemd.user.services = {
fcitx5-daemon = {
Unit.After = "graphical-session-pre.target";
Service = {
Restart = "on-failure";
RestartSec = 3;
};
};
};
# i run this manually instead
#services.nextcloud-client = {
# enable = true;
# startInBackground = true;
#};
# and this too
#programs.nheko = {
# enable = true;
# settings = {
# };
#};
# some packages require a pointer theme
home.pointerCursor.gtk.enable = true;
home.pointerCursor.package = pkgs.vanilla-dmz;
home.pointerCursor.name = "Vanilla-DMZ";
programs.yt-dlp.enable = true;
home.packages = with pkgs; [
# wayland
grim slurp
# gui compat stuff
qt5ct qgnomeplatform
# various programs i use
keepassxc nheko qbittorrent anki mumble
nextcloud-client gnome.zenity
# cli tools
imagemagick ffmpeg
# fonts
noto-fonts noto-fonts-cjk noto-fonts-emoji
(nerdfonts.override { fonts = [ "NerdFontsSymbolsOnly" ]; })
# might check out some day (tm)
# nyxt qutebrowser
];
}

37
home/common/helix.nix Normal file
View file

@ -0,0 +1,37 @@
{ config, pkgs, lib, ... }:
let
wrapHelix = { extraPackages ? [] , withPython3 ? true, extraPython3Packages ? (_: []) }:
pkgs.symlinkJoin {
postBuild = ''
rm $out/bin/hx
makeWrapper ${lib.escapeShellArgs (
[ "${pkgs.helix}/bin/hx" "${placeholder "out"}/bin/hx" ]
++ [ "--suffix" "PATH" ":" (lib.makeBinPath (extraPackages ++ [(pkgs.python3.withPackages extraPython3Packages)])) ]
)}
'';
buildInputs = [ pkgs.makeWrapper ]; preferLocalBuild = true;
name = "helix${pkgs.helix.version}"; paths = [ pkgs.helix ];
passthru.unwrapped = pkgs.helix; meta = pkgs.helix.meta; version = pkgs.helix.version;
};
in {
programs.helix = {
enable = true;
package = wrapHelix {
extraPackages = with pkgs; [
rust-analyzer
nodePackages.bash-language-server shellcheck
nodePackages.typescript-language-server
clang-tools
nodePackages.vscode-langservers-extracted
nil
marksman
taplo
];
extraPython3Packages = (pypkgs: with pypkgs; [ python-lsp-server ]);
};
languages = [];
settings = {
theme = "base16_terminal";
};
};
}

259
home/common/i3-sway.nix Normal file
View file

@ -0,0 +1,259 @@
{ options, config, pkgs, lib, ... }:
let
modifier = "Mod4";
commonConfig = {
modifier = modifier;
bars = [{
mode = "dock";
hiddenState = "hide";
position = "bottom";
workspaceButtons = true;
workspaceNumbers = true;
statusCommand = "${pkgs.i3status}/bin/i3status";
fonts = {
names = [ "Noto Sans Mono" ];
size = 16.0;
};
trayOutput = "*";
colors = {
background = "#24101a";
statusline = "#ebdadd";
separator = "#6b4d52";
focusedWorkspace = {
border = "#782a2a";
background = "#782a2a";
text = "#ebdadd";
};
activeWorkspace = {
border = "#913131";
background = "#913131";
text = "#ebdadd";
};
inactiveWorkspace = {
border = "#472222";
background = "#4d2525";
text = "#8c8284";
};
urgentWorkspace = {
border = "#734545";
background = "#993d3d";
text = "#ebdadd";
};
bindingMode = {
border = "#734545";
background = "#993d3d";
text = "#ebdadd";
};
};
}];
startup = [
{ command = "~/scripts/initwm.sh"; }
];
colors = {
focused = {
background = "#913131";
border = "#913131";
childBorder = "#b35656";
indicator = "#b35656";
text = "#ebdadd";
};
focusedInactive = {
background = "#782a2a";
border = "#782a2a";
childBorder = "#b32d2d";
indicator = "#b32d2d";
text = "#ebdadd";
};
placeholder = {
background = "#24101a";
border = "#24101a";
childBorder = "#24101a";
indicator = "#000000";
text = "#ebdadd";
};
unfocused = {
background = "#4d2525";
border = "#472222";
childBorder = "#4d2525";
indicator = "#661a1a";
text = "#8c8284";
};
urgent = {
background = "#993d3d";
border = "#734545";
childBorder = "#993d3d";
indicator = "#993d3d";
text = "#ebdadd";
};
};
floating.titlebar = true;
fonts = {
names = [ "Noto Sans" "Noto Emoji" "FontAwesome5Free" ];
size = 16.0;
};
gaps = {
smartBorders = "on";
smartGaps = true;
inner = 10;
};
menu = "${pkgs.bemenu}/bin/bemenu-run --no-overlap --prompt '>' --tb '#24101a' --tf '#ebbe5f' --fb '#24101a' --nb '#24101a70' --ab '#24101a70' --nf '#ebdadd' --af '#ebdadd' --hb '#394893' --hf '#e66e6e' --list 30 --prefix '*' --scrollbar autohide --fn 'Noto Sans Mono' --line-height 23 --sb '#394893' --sf '#ebdadd' --scb '#6b4d52' --scf '#e66e6e'";
terminal = if config.useAlacritty then "${pkgs.alacritty}/bin/alacritty" else "${pkgs.urxvt}/bin/urxvt";
window = {
hideEdgeBorders = "smart";
};
workspaceAutoBackAndForth = true;
floating.criteria = [
{ title = "Steam - Update News"; }
];
};
genKeybindings = (default_options: kb:
kb // {
"${modifier}+Shift+g" = "floating toggle";
"${modifier}+g" = "focus mode_toggle";
}
// (lib.attrsets.filterAttrs
(k: v:
!(builtins.elem
k
["${modifier}+space" "${modifier}+Shift+space"]))
(lib.lists.head
(lib.lists.head
default_options.config.type.getSubModules)
.imports)
.options.keybindings.default)
);
in
{
imports = [ ./options.nix ./gui.nix ];
programs.mako = {
enable = lib.mkDefault config.wayland.windowManager.sway.enable;
# ms
defaultTimeout = 7500;
font = "Noto Sans Mono 12";
};
# TODO merge with colors in gui.nix
programs.alacritty = {
enable = lib.mkDefault config.useAlacritty;
settings = {
window.opacity = 0.75;
font.normal.family = "Noto Sans Mono";
font.size = 16;
colors.primary.background = "#24101a";
colors.primary.foreground = "#ebdadd";
colors.normal = {
black = "#523b3f";
red = "#e66e6e";
green = "#8cbf73";
yellow = "#ebbe5f";
blue = "#5968b3";
magenta = "#a64999";
cyan = "#77c7c2";
white = "#f0e4e6";
};
colors.bright = {
black = "#6b4d52";
red = "#e66e6e";
green = "#8cbf73";
yellow = "#ebbe5f";
blue = "#5968b3";
magenta = "#a64999";
cyan = "#77c7c2";
white = "#f7f0f1";
};
};
};
# i use this instead of alacritty on old laptops
programs.urxvt = {
enable = lib.mkDefault (!config.useAlacritty);
keybindings = {
"Control-Alt-C" = "builtin-string:";
"Control-Alt-V" = "builtin-string:";
};
extraConfig = {
depth = 32;
inheritPixmap = true;
};
scroll.bar.enable = false;
fonts = [ "xft:Noto Sans Mono:pixelsize=16" "xft:Symbols Nerd Font Mono:pixelsize=16" ];
};
xsession.windowManager.i3 = {
config = {
keybindings = genKeybindings options.xsession.windowManager.i3 {};
} // commonConfig;
};
home.file.".xinitrc".text = ''
if test -z "$DBUS_SESSION_BUS_ADDRESS"; then
eval $(dbus-launch --exit-with-session --sh-syntax)
fi
systemctl --user import-environment DISPLAY XAUTHORITY
if command -v dbus-update-activation-environment >/dev/null 2>&1; then
dbus-update-activation-environment DISPLAY XAUTHORITY
fi
exec i3
'';
xsession.initExtra = ''
export BEMENU_OPTS="--no-overlap --prompt '>' --tb '#24101a' --tf '#ebbe5f' --fb '#24101a' --nb '#24101a70' --ab '#24101a70' --nf '#ebdadd' --af '#ebdadd' --hb '#394893' --hf '#e66e6e' --list 30 --prefix '*' --scrollbar autohide --fn 'Noto Sans Mono' --line-height 23 --sb '#394893' --sf '#ebdadd' --scb '#6b4d52' --scf '#e66e6e'"
export _JAVA_AWT_WM_NONREPARENTING=1
export GTK_IM_MODULE=fcitx
export QT_IM_MODULE=fcitx
export XMODIFIERS=@im=fcitx
export SDL_IM_MODULE=fcitx
export XIM_SERVERS=fcitx
export INPUT_METHOD=fcitx
setxkbmap -layout jp,ru -option caps:swapescape,compose:menu,grp:win_space_toggle
'';
home.packages = with pkgs; if config.wayland.windowManager.sway.enable then [
wl-clipboard
] else [];
wayland.windowManager.sway = {
wrapperFeatures.gtk = true;
config = {
assigns = {
"3" = [{ app_id = "org.keepassxc.KeePassXC"; }];
};
keybindings = genKeybindings options.wayland.windowManager.sway (with pkgs.sway-contrib; {
"${modifier}+Print" = "exec ${grimshot}/bin/grimshot copy area";
"${modifier}+Mod1+Print" = "exec ${grimshot}/bin/grimshot copy window";
});
startup = [
{
command = "~/scripts/initwm.sh";
}
{
always = true;
command = "${pkgs.wl-clipboard}/bin/wl-paste -t text --watch ${pkgs.clipman}/bin/clipman store --no-persist";
}
];
output = {
"*" = {
bg = "~/var/wallpaper.jpg fill";
# improved screen latency, apparently
max_render_time = "2";
};
};
input = {
"*" = {
xkb_layout = "jp,ru";
xkb_options = "caps:swapescape,compose:menu,grp:win_space_toggle";
};
};
} // commonConfig;
extraSessionCommands = ''
export BEMENU_OPTS="--no-overlap --prompt '>' --tb '#24101a' --tf '#ebbe5f' --fb '#24101a' --nb '#24101a70' --ab '#24101a70' --nf '#ebdadd' --af '#ebdadd' --hb '#394893' --hf '#e66e6e' --list 30 --prefix '*' --scrollbar autohide --fn 'Noto Sans Mono' --line-height 23 --sb '#394893' --sf '#ebdadd' --scb '#6b4d52' --scf '#e66e6e'"
export _JAVA_AWT_WM_NONREPARENTING=1
export GTK_IM_MODULE=fcitx
export QT_IM_MODULE=fcitx
export XMODIFIERS=@im=fcitx
export SDL_IM_MODULE=fcitx
export XIM_SERVERS=fcitx
export INPUT_METHOD=fcitx
export BEMENU_BACKEND=wayland
export SDL_VIDEODRIVER=wayland
export QT_QPA_PLATFORM=wayland
export QT_WAYLAND_DISABLE_WINDOWDECORATION=1
export QT_QPA_PLATFORMTHEME=gnome
export MOZ_ENABLE_WAYLAND=1
'';
};
}

66
home/common/kakoune.nix Normal file
View file

@ -0,0 +1,66 @@
{ config, pkgs, lib, ... }:
let
wrapKakoune = { extraPackages ? [] , withPython3 ? true, extraPython3Packages ? (_: []) }:
pkgs.symlinkJoin {
postBuild = ''
rm $out/bin/kak
makeWrapper ${lib.escapeShellArgs (
[ "${pkgs.kakoune-unwrapped}/bin/kak" "${placeholder "out"}/bin/kak" ]
++ [ "--suffix" "PATH" ":" (lib.makeBinPath (extraPackages ++ [(pkgs.python3.withPackages extraPython3Packages)])) ]
)}
'';
buildInputs = [ pkgs.makeWrapper ]; preferLocalBuild = true;
name = "kakoune${pkgs.kakoune-unwrapped.version}"; paths = [ pkgs.kakoune-unwrapped ];
passthru.unwrapped = pkgs.kakoune-unwrapped; meta = pkgs.kakoune-unwrapped.meta; version = pkgs.kakoune-unwrapped.version;
};
in {
programs.kakoune = {
enable = true;
package = wrapKakoune {
extraPackages = with pkgs; [
rust-analyzer
nodePackages.bash-language-server shellcheck
nodePackages.typescript-language-server
clang-tools
nodePackages.vscode-langservers-extracted
nil
marksman
taplo
];
extraPython3Packages = (pypkgs: with pypkgs; [ python-lsp-server ]);
};
config = {
# colorScheme
ui.changeColors = false;
};
extraConfig = ''
eval %sh{kak-lsp --kakoune -s $kak_session}
lsp-enable
'';
plugins = with pkgs.kakounePlugins; [ kak-lsp sleuth-kak tabs-kak ];
};
home.file."${config.xdg.configHome}/kak-lsp/kak-lsp.toml".text = ''
# bash, clangd, json, html, css, python work out of the box
[language.rust]
filetypes = ["rust"]
roots = ["rust-toolchain.toml", "rust-toolchain", "Cargo.toml"]
command = "rust-analyzer"
[language.typescript]
filetypes = ["typescript"]
roots = ["package.json"]
command = "typescript-language-server"
args = ["--stdio"]
[language.nix]
filetypes = ["nix"]
roots = ["flake.nix"]
command = "nil"
[language.markdown]
filetypes = ["markdown"]
roots = []
command = "marksman"
[language.toml]
filetypes = ["toml"]
roots = []
command = "taplo"
'';
}

8
home/common/options.nix Normal file
View file

@ -0,0 +1,8 @@
{ lib, ... }:
{
options.useAlacritty = lib.mkOption {
type = with lib.types; uniq bool;
description = "Use Alacritty";
default = true;
};
}

189
home/common/vim.nix Normal file
View file

@ -0,0 +1,189 @@
{ config, pkgs, ... }:
{
programs.neovim = {
enable = true;
defaultEditor = true;
package = pkgs.neovim-unwrapped;
extraPackages = with pkgs; [
rust-analyzer
nodePackages.bash-language-server shellcheck
nodePackages.typescript-language-server
clang-tools
nodePackages.vscode-langservers-extracted
nil
marksman
taplo
];
extraPython3Packages = pyPkgs: with pyPkgs; [ python-lsp-server ];
extraConfig = ''
autocmd BufReadPost * if @% !~# '\.git[\/\\]COMMIT_EDITMSG$' && line("'\"") > 1 && line("'\"") <= line("$") | exe "normal! g`\"" | endif
syntax on
lua << EOF
EOF
'';
viAlias = true;
vimAlias = true;
vimdiffAlias = true;
plugins =
# TODO make pure
let lua = (s: ''
lua << EOF
${s}
EOF
'');
in with pkgs.vimPlugins; [
# TODO remove on next nvim update (0.8.3/0.9)
vim-nix
{ plugin = nvim-web-devicons;
config = lua ''
require'nvim-web-devicons'.setup {
}
''; }
{ plugin = nvim-tree-lua;
config = lua ''
vim.g.loaded_netrw = 1
vim.g.loaded_netrwPlugin = 1
vim.opt.termguicolors = true
require("nvim-tree").setup({
-- :help nvim-tree-setup
})
''; }
vim-sleuth
luasnip
{ plugin = nvim-cmp;
config = lua ''
local cmp = require('cmp')
cmp.setup {
snippet = {
expand = function(args)
require('luasnip').lsp_expand(args.body)
end,
},
mapping = {
['<C-p>'] = cmp.mapping.select_prev_item(),
['<C-n>'] = cmp.mapping.select_next_item(),
['<C-space>'] = cmp.mapping.complete(),
['<C-e>'] = cmp.mapping.close(),
['<tab>'] = cmp.mapping.confirm { select = true },
},
sources = cmp.config.sources({
{ name = 'nvim_lsp' },
{ name = 'luasnip' },
}),
}
''; }
cmp_luasnip
cmp-nvim-lsp
{ plugin = nvim-lspconfig;
config = lua ''
-- Mappings.
-- See `:help vim.diagnostic.*` for documentation on any of the below functions
local opts = { noremap=true, silent=true }
vim.keymap.set('n', '<space>e', vim.diagnostic.open_float, opts)
vim.keymap.set('n', '[d', vim.diagnostic.goto_prev, opts)
vim.keymap.set('n', ']d', vim.diagnostic.goto_next, opts)
vim.keymap.set('n', '<space>q', vim.diagnostic.setloclist, opts)
-- Use an on_attach function to only map the following keys
-- after the language server attaches to the current buffer
local on_attach = function(client, bufnr)
-- Enable completion triggered by <c-x><c-o>
vim.api.nvim_buf_set_option(bufnr, 'omnifunc', 'v:lua.vim.lsp.omnifunc')
-- Mappings.
-- See `:help vim.lsp.*` for documentation on any of the below functions
local bufopts = { noremap=true, silent=true, buffer=bufnr }
vim.keymap.set('n', 'gD', vim.lsp.buf.declaration, bufopts)
vim.keymap.set('n', 'gd', vim.lsp.buf.definition, bufopts)
vim.keymap.set('n', 'K', vim.lsp.buf.hover, bufopts)
vim.keymap.set('n', 'gi', vim.lsp.buf.implementation, bufopts)
vim.keymap.set('n', '<C-k>', vim.lsp.buf.signature_help, bufopts)
vim.keymap.set('n', '<space>wa', vim.lsp.buf.add_workspace_folder, bufopts)
vim.keymap.set('n', '<space>wr', vim.lsp.buf.remove_workspace_folder, bufopts)
vim.keymap.set('n', '<space>wl', function()
print(vim.inspect(vim.lsp.buf.list_workspace_folders()))
end, bufopts)
vim.keymap.set('n', '<space>D', vim.lsp.buf.type_definition, bufopts)
vim.keymap.set('n', '<space>rn', vim.lsp.buf.rename, bufopts)
vim.keymap.set('n', '<space>ca', vim.lsp.buf.code_action, bufopts)
vim.keymap.set('n', 'gr', vim.lsp.buf.references, bufopts)
vim.keymap.set('n', '<space>f', function() vim.lsp.buf.format { async = true } end, bufopts)
end
local lsp_flags = {
-- This is the default in Nvim 0.7+
debounce_text_changes = 150,
}
local capabilities = vim.tbl_extend(
'keep',
vim.lsp.protocol.make_client_capabilities(),
require('cmp_nvim_lsp').default_capabilities()
);
-- see https://github.com/neovim/nvim-lspconfig/blob/master/doc/server_configurations.md
require'lspconfig'.bashls.setup{
on_attach = on_attach,
flags = lsp_flags,
capabilities = capabilities,
}
require'lspconfig'.clangd.setup{
-- usually requires compile_flags.json
on_attach = on_attach,
flags = lsp_flags,
capabilities = capabilities,
}
require'lspconfig'.pylsp.setup{
-- https://github.com/python-lsp/python-lsp-server/blob/develop/CONFIGURATION.md
on_attach = on_attach,
flags = lsp_flags,
capabilities = capabilities,
}
-- todo completion
require'lspconfig'.html.setup{
on_attach = on_attach,
flags = lsp_flags,
capabilities = capabilities,
}
require'lspconfig'.cssls.setup{
on_attach = on_attach,
flags = lsp_flags,
capabilities = capabilities,
}
require'lspconfig'.tsserver.setup{
on_attach = on_attach,
flags = lsp_flags,
capabilities = capabilities,
}
require'lspconfig'.jsonls.setup{
on_attach = on_attach,
flags = lsp_flags,
capabilities = capabilities,
}
require'lspconfig'.nil_ls.setup{
on_attach = on_attach,
flags = lsp_flags,
capabilities = capabilities,
}
require'lspconfig'.taplo.setup{
on_attach = on_attach,
flags = lsp_flags,
capabilities = capabilities,
}
require'lspconfig'.marksman.setup{
on_attach = on_attach,
flags = lsp_flags,
capabilities = capabilities,
}
require'lspconfig'.rust_analyzer.setup{
on_attach = on_attach,
flags = lsp_flags,
capabilities = capabilities,
-- Server-specific settings...
settings = {
["rust-analyzer"] = {}
}
}
'';
}
];
};
}

30
home/flake.nix Normal file
View file

@ -0,0 +1,30 @@
{
description = "Home Manager configuration of chayleaf";
inputs = {
#nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
#instead take it from system config
nur.url = "github:nix-community/NUR";
home-manager = {
url = "github:nix-community/home-manager";
inputs.nixpkgs.follows = "nixpkgs";
};
};
outputs = inputs@{ self, nixpkgs, home-manager, nur }:
let
priv = import ./private.nix inputs;
in {
homeConfigurations = {
"user@nixmsi" = home-manager.lib.homeManagerConfiguration {
pkgs = nixpkgs.legacyPackages."x86_64-linux";
modules = [
nur.nixosModules.nur
./hosts/nixmsi.nix
# IRL-related private config
priv.nixmsi
];
};
};
};
}

68
home/hosts/nixmsi.nix Normal file
View file

@ -0,0 +1,68 @@
{ config, pkgs, lib, ... }:
{
imports = [
../common/general.nix
../common/firefox.nix
../common/i3-sway.nix
../common/vim.nix
../common/helix.nix
../common/kakoune.nix
];
home.stateVersion = "22.11";
home.username = "user";
home.homeDirectory = "/home/user";
xsession.windowManager.i3.enable = true;
wayland.windowManager.sway.enable = true;
nixpkgs.config.allowUnfreePredicate = pkg: builtins.elem (lib.getName pkg) [
"steam-run"
"steam"
"steam-original"
"steam-runtime"
"steamcmd"
];
home.packages = with pkgs; [
steam-run steam
easyeffects
wineWowPackages.waylandFull
winetricks
protontricks proton-caller
bottles
gimp krita blender
# waiting until the PR gets merged
(looking-glass-client.overrideAttrs (old: {
version = "B6";
src = fetchFromGitHub {
owner = "gnif";
repo = "LookingGlass";
rev = "B6";
sha256 = "sha256-6vYbNmNJBCoU23nVculac24tHqH7F4AZVftIjL93WJU=";
fetchSubmodules = true;
};
buildInputs = old.buildInputs ++ (with pkgs; [ pipewire libsamplerate ]);
cmakeFlags = old.cmakeFlags ++ [ "-DENABLE_PULSEAUDIO=no" ];
}))
];
home.file."${config.xdg.configHome}/looking-glass/client.ini".text = ''
[app]
shmFile=/dev/kvmfr0
capture=dxgi
[dxgi]
copyBackend=d3d12
d3d12CopySleep=5
disableDamage=false
[input]
rawMouse=yes
escapeKey=KEY_INSERT
[egl]
vsync=yes
[opengl]
vsync=yes
[win]
jitRender=yes
'';
}

6
home/private.nix Normal file
View file

@ -0,0 +1,6 @@
{ ... }:
{
nixmsi = {
# insert config here
};
}

141
system/common/vfio.nix Normal file
View file

@ -0,0 +1,141 @@
{ config, lib, pkgs, ... }:
{
options.vfio = with lib; mkOption {
type = types.submodule {
options = {
enable = mkOption {
type = types.bool;
default = false;
description = "Enable AMD GPU passthrough config (no intel/nvidia support since I can't test it)";
};
libvirtdGroup = mkOption {
type = with types; listOf str;
default = ["user"];
description = "Users to add to libvirtd group";
};
intelCpu = mkOption {
type = types.bool;
default = false;
description = "Whether the CPU is Intel (untested)";
};
passGpuAtBoot = mkOption {
type = types.bool;
default = false;
description = "Whether to pass the GPU at boot (can be more stable)";
};
pciIDs = mkOption {
type = with types; listOf str;
default = [];
description = "PCI passthrough IDs";
};
lookingGlass = mkOption {
type = types.submodule {
options = {
enable = mkOption {
type = types.bool;
default = true;
description = "Enable Looking Glass integration";
};
ivshmem = mkOption {
type = with types; listOf (submodule {
options = {
size = mkOption {
type = types.int;
default = 32;
description = "IVSHMEM size in MB: https://looking-glass.io/docs/B6/install/#determining-memory";
};
owner = mkOption {
type = types.str;
description = "IVSHMEM device owner";
};
};
});
default = [];
example = [{ size = 32; owner = "user"; }];
description = "IVSHMEM/kvmfr config (multiple devices can be created: /dev/kvmfr0, /dev/kvmfr1, and so on)";
};
};
};
default = {};
description = "Looking glass config";
};
};
};
default = {};
description = "VFIO settings";
};
config = lib.mkIf config.vfio.enable
(let
cfg = config.vfio;
gpuIDs = lib.concatStringsSep "," cfg.pciIDs;
enableIvshmem = config.vfio.lookingGlass.enable && (builtins.length config.vfio.lookingGlass.ivshmem) > 0;
in {
boot = {
initrd.kernelModules = [
(if cfg.intelCpu then "kvm-intel" else "kvm-amd")
] ++ (if cfg.passGpuAtBoot then [
"vfio"
"vfio_iommu_type1"
"vfio_pci"
"vfio_virqfd"
] else []);
extraModulePackages =
with config.boot.kernelPackages;
lib.mkIf enableIvshmem [ kvmfr ];
extraModprobeConfig = let ivshmemConfig = if enableIvshmem then ''
options kvmfr static_size_mb=${lib.concatStringsSep "," (map (x: toString x.size) cfg.lookingGlass.ivshmem)}
'' else ""; in ''
options vfio-pci ids=${gpuIDs}
options kvm ignore_msrs=1
${ivshmemConfig}
'';
kernelParams = [
(if cfg.intelCpu then "intel_iommu=on" else "amd_iommu=on")
"iommu=pt"
];
kernelModules = [
"vhost-net"
] ++ (if cfg.passGpuAtBoot then [] else [ "vfio_virqfd" ])
++ (if enableIvshmem then [ "kvmfr" ] else []);
};
services.udev.extraRules = lib.mkIf enableIvshmem
(lib.concatStringsSep
"\n"
(lib.imap0
(i: ivshmem: ''
SUBSYSTEM=="kvmfr", KERNEL=="kvmfr${toString i}", OWNER="${ivshmem.owner}", GROUP="kvm", MODE="0660"
'')
cfg.lookingGlass.ivshmem));
# disable early KMS so GPU can be properly unbound
hardware.amdgpu.loadInInitrd = false;
hardware.opengl.enable = true;
# needed for virt-manager
programs.dconf.enable = true;
virtualisation.libvirtd = {
enable = true;
onBoot = "ignore";
onShutdown = "shutdown";
qemu = {
ovmf.enable = true;
# Full is needed for TPM and secure boot emulation
ovmf.packages = [ pkgs.OVMFFull ];
# TPM emulation
swtpm.enable = true;
verbatimConfig = ''
nvram = [ "${pkgs.OVMFFull}/FV/OVMF.fd:${pkgs.OVMFFull}/FV/OVMF_VARS.fd" ]
cgroup_device_acl = [
"/dev/kvmfr0",
"/dev/vfio/vfio", "/dev/vfio/11", "/dev/vfio/12",
"/dev/null", "/dev/full", "/dev/zero",
"/dev/random", "/dev/urandom",
"/dev/ptmx", "/dev/kvm"
]
'';
# might disable this later
runAsRoot = true;
};
};
virtualisation.spiceUSBRedirection.enable = true;
users.groups.libvirtd.members = [ "root" ] ++ cfg.libvirtdGroup;
});
}

43
system/flake.nix Normal file
View file

@ -0,0 +1,43 @@
{
description = "NixOS configuration";
inputs = {
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
utils.url = "github:gytis-ivaskevicius/flake-utils-plus";
nixos-hardware.url = "github:NixOS/nixos-hardware";
};
outputs = inputs@{ self, nixpkgs, utils, nixos-hardware }:
let
hw = nixos-hardware.nixosModules;
# IRL-related stuff I'd rather not put into git
priv = import ./private.nix inputs;
in utils.lib.mkFlake {
inherit self inputs;
hostDefaults.modules = [
./common/vfio.nix
{
# make this flake's nixpkgs available to the whole system
nix = {
generateNixPathFromInputs = true;
generateRegistryFromInputs = true;
linkInputs = true;
};
}
];
hosts = {
nixmsi = {
system = "x86_64-linux";
modules = [
priv.nixmsi
./hosts/nixmsi.nix
hw.common-pc-ssd # enables fstrim
hw.common-cpu-amd # microcode
hw.common-cpu-amd-pstate # amd-pstate
hw.common-gpu-amd # configures drivers
hw.common-pc-laptop # enables tlp
];
};
};
};
}

170
system/hosts/nixmsi.nix Normal file
View file

@ -0,0 +1,170 @@
{ config, lib, pkgs, ... }:
let
cryptroot = "/dev/disk/by-uuid/f4edc0df-b50b-42f6-94ed-1c8f88d6cdbb";
encPart = "/dev/disk/by-uuid/ce6ccdf0-7b6a-43ae-bfdf-10009a55041a";
efiPart = "/dev/disk/by-uuid/D77D-8CE0";
in {
system.stateVersion = "22.11";
### SECTION 1: HARDWARE/BOOT PARAMETERS ###
boot = {
initrd = {
availableKernelModules = [ "nvme" "xhci_pci" ];
# insert crypto_keyfile into initrd so that grub can tell the kernel the
# encryption key once I unlock the /boot partition
secrets."/crypto_keyfile.bin" = "/boot/initrd/crypto_keyfile.bin";
luks.devices."cryptroot" = {
device = encPart;
# idk whether this is needed but it works
preLVM = true;
# see https://asalor.blogspot.de/2011/08/trim-dm-crypt-problems.html before enabling
allowDiscards = true;
# improve SSD performance
bypassWorkqueues = true;
keyFile = "/crypto_keyfile.bin";
};
};
resumeDevice = cryptroot;
kernelParams = [
"resume=/@swap/swapfile"
"resume_offset=533760"
# offset = $(btrfs inspect-internal map-swapfile -r path/to/swapfile)
"fbcon=font:TER16x32"
];
cleanTmpDir = true;
loader = {
grub = {
enable = true;
enableCryptodisk = true;
efiSupport = true;
device = "nodev";
gfxmodeEfi = "1920x1080";
};
efi.canTouchEfiVariables = true;
efi.efiSysMountPoint = "/boot/efi";
};
kernelPackages = pkgs.linuxPackages_zen;
};
nixpkgs.config.allowUnfreePredicate = pkg: (lib.getName pkg) == "steam-original";
hardware = {
steam-hardware.enable = true;
video.hidpi.enable = true;
enableRedistributableFirmware = true;
};
# see common/vfio.nix
vfio.enable = true;
vfio.pciIDs = [ "1002:73df" "1002:ab28" ];
vfio.libvirtdGroup = [ "user" ];
vfio.lookingGlass.ivshmem = [{ owner = "user"; }];
fileSystems = let
device = cryptroot;
fsType = "btrfs";
# max compression! my cpu is pretty good anyway
compress = "compress=zstd:15";
in {
"/" = { inherit device fsType;
options = [ compress "subvol=@" ]; };
"/nix" = { inherit device fsType;
options = [ compress "subvol=@nix" "noatime" ]; };
"/swap" = { inherit device fsType;
options = [ compress "subvol=@swap" "noatime" ]; };
"/home" = { inherit device fsType;
options = [ compress "subvol=@home" ]; };
"/.snapshots" =
{ inherit device fsType;
options = [ compress "subvol=@snapshots" ]; };
"/boot/efi" =
{ device = efiPart;
fsType = "vfat"; };
};
swapDevices = [ { device = "/swap/swapfile"; } ];
### SECTION 2: SYSTEM CONFIG/ENVIRONMENT ###
i18n.defaultLocale = lib.mkDefault "en_US.UTF-8";
i18n.supportedLocales = lib.mkDefault [ "en_US.UTF-8/UTF-8" ];
networking.useDHCP = true;
# networking.firewall.enable = false;
networking.firewall.allowedTCPPorts = [ 27015 25565 7777 ];
# networking.firewall.allowedUDPPorts = [ ... ];
# networking.hostName = "nixmsi";
networking.wireless.iwd.enable = true;
#networking.networkmanager.enable = true;
services.mullvad-vpn.enable = true;
services.mullvad-vpn.package = pkgs.mullvad-vpn;
services.xserver = {
enable = true;
libinput.enable = true;
desktopManager.xterm.enable = false;
# I couldn't get lightdm to start sway, so let's just do this
displayManager.startx.enable = true;
windowManager.i3.enable = true;
};
programs.sway.enable = true;
programs.firejail.enable = true;
environment.systemPackages = with pkgs; [
vim
wget
git
];
services.dbus.enable = true;
security.polkit.enable = true;
services.printing.enable = true;
security.rtkit.enable = true;
services.pipewire = {
enable = true;
alsa.enable = true;
alsa.support32Bit = true;
pulse.enable = true;
jack.enable = true;
};
users.users.user = {
isNormalUser = true;
extraGroups = [ "networkmanager" "wheel" ];
};
nix = {
settings.allowed-users = [ "user" ];
package = pkgs.nixFlakes;
extraOptions = ''
experimental-features = nix-command flakes
'';
};
### RANDOM PATCHES ###
# I can't enable early KMS with VFIO, so this will have to do
# (amdgpu resets the font upon being loaded)
systemd.services."systemd-vconsole-setup2" = {
serviceConfig = {
Type = "oneshot";
RemainAfterExit = true;
ExecStart = "${pkgs.systemd}/lib/systemd/systemd-vconsole-setup";
};
wantedBy = ["graphical.target"];
wants = ["multi-user.target"];
after = ["multi-user.target"];
};
# autologin once after boot
# --skip-login means directly call login instead of first asking for username
# (normally login asks for username too, but getty prefers to do it by itself for whatever reason)
services.getty.extraArgs = ["--skip-login"];
services.getty.loginProgram = with pkgs; writeScript "login-once" ''
#! ${bash}/bin/bash
LOCKFILE=/tmp/login-once.lock
if [ -f $LOCKFILE ]
then
exec ${shadow}/bin/login $@
else
${coreutils}/bin/touch $LOCKFILE
exec ${shadow}/bin/login -f user
fi
'';
}

6
system/private.nix Normal file
View file

@ -0,0 +1,6 @@
{ ... }:
{
nixmsi = {
# insert config here
};
}