commit 7d7450ebbcaca22d680aa823acb550c3fc366051 Author: chayleaf Date: Tue Jan 24 02:24:40 2023 +0700 init diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..09a4781 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +flake.lock +private.nix diff --git a/home/common/firefox.nix b/home/common/firefox.nix new file mode 100644 index 0000000..10c5c10 --- /dev/null +++ b/home/common/firefox.nix @@ -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 = {}; + }; + }; +} diff --git a/home/common/general.nix b/home/common/general.nix new file mode 100644 index 0000000..379fd3d --- /dev/null +++ b/home/common/general.nix @@ -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 + ]; +} diff --git a/home/common/gui.nix b/home/common/gui.nix new file mode 100644 index 0000000..ef6e5ae --- /dev/null +++ b/home/common/gui.nix @@ -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 + ]; +} diff --git a/home/common/helix.nix b/home/common/helix.nix new file mode 100644 index 0000000..4310455 --- /dev/null +++ b/home/common/helix.nix @@ -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"; + }; + }; +} diff --git a/home/common/i3-sway.nix b/home/common/i3-sway.nix new file mode 100644 index 0000000..4774193 --- /dev/null +++ b/home/common/i3-sway.nix @@ -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 + ''; + }; +} diff --git a/home/common/kakoune.nix b/home/common/kakoune.nix new file mode 100644 index 0000000..2564bd0 --- /dev/null +++ b/home/common/kakoune.nix @@ -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" + ''; +} diff --git a/home/common/options.nix b/home/common/options.nix new file mode 100644 index 0000000..a6895f2 --- /dev/null +++ b/home/common/options.nix @@ -0,0 +1,8 @@ +{ lib, ... }: +{ + options.useAlacritty = lib.mkOption { + type = with lib.types; uniq bool; + description = "Use Alacritty"; + default = true; + }; +} diff --git a/home/common/vim.nix b/home/common/vim.nix new file mode 100644 index 0000000..b5e068f --- /dev/null +++ b/home/common/vim.nix @@ -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 = { + [''] = cmp.mapping.select_prev_item(), + [''] = cmp.mapping.select_next_item(), + [''] = cmp.mapping.complete(), + [''] = cmp.mapping.close(), + [''] = 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', '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', '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 + 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', '', vim.lsp.buf.signature_help, bufopts) + vim.keymap.set('n', 'wa', vim.lsp.buf.add_workspace_folder, bufopts) + vim.keymap.set('n', 'wr', vim.lsp.buf.remove_workspace_folder, bufopts) + vim.keymap.set('n', 'wl', function() + print(vim.inspect(vim.lsp.buf.list_workspace_folders())) + end, bufopts) + vim.keymap.set('n', 'D', vim.lsp.buf.type_definition, bufopts) + vim.keymap.set('n', 'rn', vim.lsp.buf.rename, bufopts) + vim.keymap.set('n', 'ca', vim.lsp.buf.code_action, bufopts) + vim.keymap.set('n', 'gr', vim.lsp.buf.references, bufopts) + vim.keymap.set('n', '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"] = {} + } + } + ''; + } + ]; + }; +} diff --git a/home/flake.nix b/home/flake.nix new file mode 100644 index 0000000..6278b65 --- /dev/null +++ b/home/flake.nix @@ -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 + ]; + }; + }; + }; +} diff --git a/home/hosts/nixmsi.nix b/home/hosts/nixmsi.nix new file mode 100644 index 0000000..7c93ea9 --- /dev/null +++ b/home/hosts/nixmsi.nix @@ -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 + ''; +} diff --git a/home/private.nix b/home/private.nix new file mode 100644 index 0000000..656d658 --- /dev/null +++ b/home/private.nix @@ -0,0 +1,6 @@ +{ ... }: +{ + nixmsi = { + # insert config here + }; +} diff --git a/system/common/vfio.nix b/system/common/vfio.nix new file mode 100644 index 0000000..80bdfbc --- /dev/null +++ b/system/common/vfio.nix @@ -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; + }); +} diff --git a/system/flake.nix b/system/flake.nix new file mode 100644 index 0000000..5f2fc28 --- /dev/null +++ b/system/flake.nix @@ -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 + ]; + }; + }; + }; +} diff --git a/system/hosts/nixmsi.nix b/system/hosts/nixmsi.nix new file mode 100644 index 0000000..7c610e8 --- /dev/null +++ b/system/hosts/nixmsi.nix @@ -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 + ''; +} + diff --git a/system/private.nix b/system/private.nix new file mode 100644 index 0000000..656d658 --- /dev/null +++ b/system/private.nix @@ -0,0 +1,6 @@ +{ ... }: +{ + nixmsi = { + # insert config here + }; +}