diff --git a/flake.lock b/flake.lock index 6db188a..9e61219 100644 --- a/flake.lock +++ b/flake.lock @@ -73,11 +73,11 @@ ] }, "locked": { - "lastModified": 1741352980, - "narHash": "sha256-+u2UunDA4Cl5Fci3m7S643HzKmIDAe+fiXrLqYsR2fs=", + "lastModified": 1743550720, + "narHash": "sha256-hIshGgKZCgWh6AYJpJmRgFdR3WUbkY04o82X05xqQiY=", "owner": "hercules-ci", "repo": "flake-parts", - "rev": "f4330d22f1c5d2ba72d3d22df5597d123fdb60a9", + "rev": "c621e8422220273271f52058f618c94e405bb0f5", "type": "github" }, "original": { @@ -108,10 +108,33 @@ "type": "github" } }, + "git-hooks": { + "inputs": { + "flake-compat": "flake-compat", + "gitignore": "gitignore", + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1742649964, + "narHash": "sha256-DwOTp7nvfi8mRfuL1escHDXabVXFGT1VlPD1JHrtrco=", + "owner": "cachix", + "repo": "git-hooks.nix", + "rev": "dcf5072734cb576d2b0c59b2ac44f5050b5eac82", + "type": "github" + }, + "original": { + "owner": "cachix", + "ref": "master", + "repo": "git-hooks.nix", + "type": "github" + } + }, "gitignore": { "inputs": { "nixpkgs": [ - "pre-commit-hooks", + "git-hooks", "nixpkgs" ] }, @@ -136,11 +159,11 @@ ] }, "locked": { - "lastModified": 1741955947, - "narHash": "sha256-2lbURKclgKqBNm7hVRtWh0A7NrdsibD0EaWhahUVhhY=", + "lastModified": 1743869639, + "narHash": "sha256-Xhe3whfRW/Ay05z9m1EZ1/AkbV1yo0tm1CbgjtCi4rQ=", "owner": "nix-community", "repo": "home-manager", - "rev": "4e12151c9e014e2449e0beca2c0e9534b96a26b4", + "rev": "d094c6763c6ddb860580e7d3b4201f8f496a6836", "type": "github" }, "original": { @@ -152,11 +175,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1742069588, - "narHash": "sha256-C7jVfohcGzdZRF6DO+ybyG/sqpo1h6bZi9T56sxLy+k=", + "lastModified": 1744174375, + "narHash": "sha256-oxI9TLgnQbQ/WL0tIwVSIooLbXq4PW1QUhf5aQmXFgk=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "c80f6a7e10b39afcc1894e02ef785b1ad0b0d7e5", + "rev": "ef3a956f697525883b77192cbe208233ea0f8f79", "type": "github" }, "original": { @@ -191,38 +214,15 @@ "type": "github" } }, - "pre-commit-hooks": { - "inputs": { - "flake-compat": "flake-compat", - "gitignore": "gitignore", - "nixpkgs": [ - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1742058297, - "narHash": "sha256-b4SZc6TkKw8WQQssbN5O2DaCEzmFfvSTPYHlx/SFW9Y=", - "owner": "cachix", - "repo": "pre-commit-hooks.nix", - "rev": "59f17850021620cd348ad2e9c0c64f4e6325ce2a", - "type": "github" - }, - "original": { - "owner": "cachix", - "ref": "master", - "repo": "pre-commit-hooks.nix", - "type": "github" - } - }, "root": { "inputs": { "agenix": "agenix", "flake-parts": "flake-parts", "futils": "futils", + "git-hooks": "git-hooks", "home-manager": "home-manager", "nixpkgs": "nixpkgs", "nur": "nur", - "pre-commit-hooks": "pre-commit-hooks", "systems": "systems" } }, diff --git a/flake.nix b/flake.nix index afd3c80..5076729 100644 --- a/flake.nix +++ b/flake.nix @@ -61,10 +61,10 @@ }; }; - pre-commit-hooks = { + git-hooks = { type = "github"; owner = "cachix"; - repo = "pre-commit-hooks.nix"; + repo = "git-hooks.nix"; ref = "master"; inputs = { nixpkgs.follows = "nixpkgs"; diff --git a/flake/checks.nix b/flake/checks.nix index 98e49bd..73e64d5 100644 --- a/flake/checks.nix +++ b/flake/checks.nix @@ -1,7 +1,7 @@ { inputs, ... }: { imports = [ - inputs.pre-commit-hooks.flakeModule + inputs.git-hooks.flakeModule ]; perSystem = { ... }: { diff --git a/flake/dev-shells.nix b/flake/dev-shells.nix index d5f5989..87464a4 100644 --- a/flake/dev-shells.nix +++ b/flake/dev-shells.nix @@ -6,7 +6,6 @@ name = "NixOS-config"; nativeBuildInputs = with pkgs; [ - gitAndTools.pre-commit nixpkgs-fmt ]; diff --git a/flake/home-manager.nix b/flake/home-manager.nix index add889e..093ae8c 100644 --- a/flake/home-manager.nix +++ b/flake/home-manager.nix @@ -3,6 +3,11 @@ let defaultModules = [ # Include generic settings "${self}/modules/home" + { + nixpkgs.overlays = (lib.attrValues self.overlays) ++ [ + inputs.nur.overlays.default + ]; + } { # Basic user information defaults home.username = lib.mkDefault "ambroisie"; @@ -21,18 +26,15 @@ let # * not letting me set `lib` as an extraSpecialArgs # * not respecting `nixpkgs.overlays` [1] # [1]: https://github.com/nix-community/home-manager/issues/2954 - pkgs = import inputs.nixpkgs { - inherit system; - - overlays = (lib.attrValues self.overlays) ++ [ - inputs.nur.overlays.default - ]; - }; + pkgs = inputs.nixpkgs.legacyPackages.${system}; modules = defaultModules ++ [ "${self}/hosts/homes/${name}" ]; + # Use my extended lib in NixOS configuration + inherit (self) lib; + extraSpecialArgs = { # Inject inputs to use them in global registry inherit inputs; diff --git a/flake/nixos.nix b/flake/nixos.nix index fa656dc..bf9eac8 100644 --- a/flake/nixos.nix +++ b/flake/nixos.nix @@ -3,7 +3,7 @@ let defaultModules = [ { # Let 'nixos-version --json' know about the Git revision - system.configurationRevision = self.rev or "dirty"; + system.configurationRevision = self.rev or self.dirtyRev or "dirty"; } { nixpkgs.overlays = (lib.attrValues self.overlays) ++ [ diff --git a/hosts/nixos/porthos/secrets/secrets.nix b/hosts/nixos/porthos/secrets/secrets.nix index 68e90f2..425756c 100644 --- a/hosts/nixos/porthos/secrets/secrets.nix +++ b/hosts/nixos/porthos/secrets/secrets.nix @@ -80,6 +80,8 @@ in "pyload/credentials.age".publicKeys = all; + "servarr/autobrr/session-secret.age".publicKeys = all; + "sso/auth-key.age" = { owner = "nginx-sso"; publicKeys = all; diff --git a/hosts/nixos/porthos/secrets/servarr/autobrr/session-secret.age b/hosts/nixos/porthos/secrets/servarr/autobrr/session-secret.age new file mode 100644 index 0000000..e98b94a --- /dev/null +++ b/hosts/nixos/porthos/secrets/servarr/autobrr/session-secret.age @@ -0,0 +1,7 @@ +age-encryption.org/v1 +-> ssh-ed25519 cKojmg bu09lB+fjaPP31cUQZP6EqSPuseucgNK7k9vAS08iS0 ++NGL+b2QD/qGo6hqHvosAXzHZtDvfodmPdcgnrKlD1o +-> ssh-ed25519 jPowng QDCdRBGWhtdvvMCiDH52cZHz1/W7aomhTatZ4+9IKwI +Ou3jjV/O55G1CPgGS33l3eWhhYWrVdwVNPSiE14d5rE +--- q0ssmpG50OX1WaNSInc2hbtH3DbTwQGDU74VGEoMh94 +mCƑ'hK./Xu(g$'M{fK !MZoR՝͟;yb \ No newline at end of file diff --git a/hosts/nixos/porthos/services.nix b/hosts/nixos/porthos/services.nix index ffd150a..561da27 100644 --- a/hosts/nixos/porthos/services.nix +++ b/hosts/nixos/porthos/services.nix @@ -51,9 +51,9 @@ in passwordFile = secrets."forgejo/mail-password".path; }; }; - # Meta-indexers - indexers = { - prowlarr.enable = true; + # Home inventory + homebox = { + enable = true; }; # Jellyfin media server jellyfin.enable = true; @@ -144,11 +144,21 @@ in sabnzbd.enable = true; # The whole *arr software suite servarr = { - enable = true; + enableAll = true; + autobrr = { + sessionSecretFile = secrets."servarr/autobrr/session-secret".path; + }; # ... But not Lidarr because I don't care for music that much lidarr = { enable = false; }; + # I only use Prowlarr nowadays + jackett = { + enable = false; + }; + nzbhydra = { + enable = false; + }; }; # Because I still need to play sysadmin ssh-server.enable = true; diff --git a/modules/home/default.nix b/modules/home/default.nix index c8183cf..4dbd510 100644 --- a/modules/home/default.nix +++ b/modules/home/default.nix @@ -8,6 +8,7 @@ ./bluetooth ./calibre ./comma + ./delta ./dircolors ./direnv ./discord @@ -23,6 +24,7 @@ ./gtk ./htop ./jq + ./jujutsu ./keyboard ./mail ./mpv diff --git a/modules/home/delta/default.nix b/modules/home/delta/default.nix new file mode 100644 index 0000000..f691fe7 --- /dev/null +++ b/modules/home/delta/default.nix @@ -0,0 +1,85 @@ +{ config, pkgs, lib, ... }: +let + cfg = config.my.home.delta; +in +{ + options.my.home.delta = with lib; { + enable = my.mkDisableOption "delta configuration"; + + package = mkPackageOption pkgs "delta" { }; + + git = { + enable = my.mkDisableOption "git integration"; + }; + + jujutsu = { + enable = my.mkDisableOption "jujutsu integration"; + }; + }; + + config = lib.mkIf cfg.enable { + assertions = [ + { + # For its configuration + assertion = cfg.jujutsu.enable -> cfg.git.enable; + message = '' + `config.my.home.delta.jujutsu` relies on `config.my.home.delta.git` + being enabled. + ''; + } + ]; + + home.packages = [ cfg.package ]; + + programs.git = lib.mkIf cfg.git.enable { + delta = { + enable = true; + inherit (cfg) package; + + options = { + features = "diff-highlight decorations"; + + # Less jarring style for `diff-highlight` emulation + diff-highlight = { + minus-style = "red"; + minus-non-emph-style = "red"; + minus-emph-style = "bold red 52"; + + plus-style = "green"; + plus-non-emph-style = "green"; + plus-emph-style = "bold green 22"; + + whitespace-error-style = "reverse red"; + }; + + # Personal preference for easier reading + decorations = { + commit-style = "raw"; # Do not recolor meta information + keep-plus-minus-markers = true; + paging = "always"; + }; + }; + }; + }; + + programs.jujutsu = lib.mkIf cfg.jujutsu.enable { + settings = { + merge-tools = { + delta = { + # Errors are signaled with exit codes greater or equal to 2 + diff-expected-exit-codes = [ 0 1 ]; + }; + }; + + ui = { + diff = { + # Delta expects a `git diff` input + format = "git"; + }; + + pager = "delta"; + }; + }; + }; + }; +} diff --git a/modules/home/git/default.nix b/modules/home/git/default.nix index c88008f..ca59a5f 100644 --- a/modules/home/git/default.nix +++ b/modules/home/git/default.nix @@ -42,34 +42,6 @@ in lfs.enable = true; - delta = { - enable = true; - - options = { - features = "diff-highlight decorations"; - - # Less jarring style for `diff-highlight` emulation - diff-highlight = { - minus-style = "red"; - minus-non-emph-style = "red"; - minus-emph-style = "bold red 52"; - - plus-style = "green"; - plus-non-emph-style = "green"; - plus-emph-style = "bold green 22"; - - whitespace-error-style = "reverse red"; - }; - - # Personal preference for easier reading - decorations = { - commit-style = "raw"; # Do not recolor meta information - keep-plus-minus-markers = true; - paging = "always"; - }; - }; - }; - # There's more extraConfig = { # Makes it a bit more readable diff --git a/modules/home/jq/default.nix b/modules/home/jq/default.nix index 57e266f..53e5986 100644 --- a/modules/home/jq/default.nix +++ b/modules/home/jq/default.nix @@ -17,6 +17,7 @@ in strings = "0;32"; arrays = "1;39"; objects = "1;39"; + objectKeys = "1;34"; }; }; } diff --git a/modules/home/jujutsu/default.nix b/modules/home/jujutsu/default.nix new file mode 100644 index 0000000..2cf6f64 --- /dev/null +++ b/modules/home/jujutsu/default.nix @@ -0,0 +1,128 @@ +{ config, pkgs, lib, ... }: +let + cfg = config.my.home.jujutsu; + + inherit (lib.my) mkMailAddress; +in +{ + options.my.home.jujutsu = with lib; { + enable = my.mkDisableOption "jujutsu configuration"; + + package = mkPackageOption pkgs "jujutsu" { }; + }; + + config = lib.mkIf cfg.enable { + assertions = [ + { + # For `jj git` commands + assertion = cfg.enable -> config.my.home.git.enable; + message = '' + `config.my.home.jujutsu` relies on `config.my.home.git` being enabled. + ''; + } + ]; + + programs.jujutsu = { + enable = true; + + inherit (cfg) package; + + settings = { + # Who am I? + user = { + name = "Bruno BELANYI"; + email = mkMailAddress "bruno" "belanyi.fr"; + }; + + aliases = { + jj = [ "util" "exec" "--" "jj" ]; + # FIXME: + # * topo sort by default (I think? test it) + # * still not a big fan of the template + lol = [ "log" "-r" "..@" "-T" "builtin_log_oneline" ]; + lola = [ "lol" "-r" "all()" ]; + # TODO: + # * `pick` (https://github.com/jj-vcs/jj/issues/5446): [ "util" "exec" "--" "bash" "-c" "jj log -p -r \"diff_contains($1)\"" ] + # * `root`: `jj workspace root` (barely necessary then) + }; + + # FIXME: git equivalents + # blame = { + # coloring = "repeatedLines"; + # markIgnoredLines = true; + # markUnblamables = true; + # }; + # FIXME: log colors should probably match git + # FIXME: patience diff? + # FIXME: fetch prune/pruneTags? + # FIXME: pull.rebase=true? Probably true TBH + # FIXME: push.default=simple? Probably true TBH + # FIXME: conflict style? ui.conflict-marker-style=git is diff3/zdiff3 + + # FIXME: from ma_9's config, plus my own stuff + # snapshot = { + # auto-track = "none()"; + # }; + # + # ui = { + # diff-editor = ":builtin"; # To silence hints + # movement = { + # edit = false; + # }; + # }; + + templates = { + # Equivalent to `commit.verbose = true` in Git + draft_commit_description = "commit_description_verbose(self)"; + }; + + template-aliases = { + "commit_description_verbose(commit)" = '' + concat( + commit_description(commit), + "JJ: ignore-rest\n", + diff.git(), + ) + ''; + # FIXME: use `diff.summary()` instead? Supported by syntax highlighting + # See https://github.com/jj-vcs/jj/issues/1946#issuecomment-2572986485 + # FIXME: tree-sitter grammar isn't in `nvim-treesitter` (https://github.com/kareigu/tree-sitter-jjdescription) + "commit_description(commit)" = '' + concat( + commit.description(), "\n", + "JJ: This commit contains the following changes:\n", + indent("JJ: ", diff.stat(72)), + ) + ''; + }; + + "--scope" = [ + # Multiple identities + { + "--when" = { + repositories = [ "~/git/EPITA/" ]; + }; + user = { + name = "Bruno BELANYI"; + email = mkMailAddress "bruno.belanyi" "epita.fr"; + }; + } + { + "--when" = { + repositories = [ "~/git/work/" ]; + }; + user = { + name = "Bruno BELANYI"; + email = mkMailAddress "ambroisie" "google.com"; + }; + } + ]; + }; + }; + + # To drop in a `local.toml` configuration, not-versioned + xdg.configFile = { + "jj/conf.d/.keep".text = ""; + }; + }; +} diff --git a/modules/home/vim/after/plugin/mappings/unimpaired.lua b/modules/home/vim/after/plugin/mappings/unimpaired.lua index 82aab05..765b6b1 100644 --- a/modules/home/vim/after/plugin/mappings/unimpaired.lua +++ b/modules/home/vim/after/plugin/mappings/unimpaired.lua @@ -31,8 +31,6 @@ local keys = { { "[u", desc = "URL encode" }, { "[x", desc = "XML encode" }, { "[y", desc = "C string encode" }, - -- Custom - { "[d", lsp.goto_prev_diagnostic, desc = "Previous diagnostic" }, -- Next { "]", group = "Next" }, @@ -62,8 +60,6 @@ local keys = { { "]u", desc = "URL decode" }, { "]x", desc = "XML decode" }, { "]y", desc = "C string decode" }, - -- Custom - { "]d", lsp.goto_next_diagnostic, desc = "Next diagnostic" }, -- Enable option { "[o", group = "Enable option" }, diff --git a/modules/home/vim/default.nix b/modules/home/vim/default.nix index 8e6bd5c..20a74ff 100644 --- a/modules/home/vim/default.nix +++ b/modules/home/vim/default.nix @@ -59,7 +59,6 @@ in # LSP and linting nvim-lspconfig # Easy LSP configuration lsp-format-nvim # Simplified formatting configuration - lsp_lines-nvim # Show diagnostics *over* regions none-ls-nvim # LSP integration for linters and formatters nvim-treesitter.withAllGrammars # Better highlighting nvim-treesitter-textobjects # More textobjects @@ -67,7 +66,6 @@ in # Completion luasnip # Snippet manager compatible with LSP - friendly-snippets # LSP snippets collection nvim-cmp # Completion engine cmp-async-path # More responsive path completion cmp-buffer # Words from open buffers diff --git a/modules/home/vim/init.vim b/modules/home/vim/init.vim index 0b54676..39ef32e 100644 --- a/modules/home/vim/init.vim +++ b/modules/home/vim/init.vim @@ -68,8 +68,6 @@ set listchars=tab:>─,trail:·,nbsp:¤ " Use patience diff set diffopt+=algorithm:patience -" Align similar lines in each hunk -set diffopt+=linematch:50 " Don't redraw when executing macros set lazyredraw diff --git a/modules/home/vim/lua/ambroisie/lsp.lua b/modules/home/vim/lua/ambroisie/lsp.lua index eb53da6..e48de12 100644 --- a/modules/home/vim/lua/ambroisie/lsp.lua +++ b/modules/home/vim/lua/ambroisie/lsp.lua @@ -3,43 +3,6 @@ local M = {} -- Simplified LSP formatting configuration local lsp_format = require("lsp-format") ---- Move to the next/previous diagnostic, automatically showing the diagnostics ---- float if necessary. ---- @param forward bool whether to go forward or backwards -local function goto_diagnostic(forward) - vim.validate({ - forward = { forward, "boolean" }, - }) - - local opts = { - float = false, - } - - -- Only show floating diagnostics if they are otherwise not displayed - local config = vim.diagnostic.config() - if not (config.virtual_text or config.virtual_lines) then - opts.float = true - end - - if forward then - vim.diagnostic.goto_next(opts) - else - vim.diagnostic.goto_prev(opts) - end -end - ---- Move to the next diagnostic, automatically showing the diagnostics float if ---- necessary. -M.goto_next_diagnostic = function() - goto_diagnostic(true) -end - ---- Move to the previous diagnostic, automatically showing the diagnostics float ---- if necessary. -M.goto_prev_diagnostic = function() - goto_diagnostic(false) -end - --- shared LSP configuration callback --- @param client native client configuration --- @param bufnr int? buffer number of the attached client @@ -79,6 +42,10 @@ M.on_attach = function(client, bufnr) vim.diagnostic.config({ virtual_text = text, virtual_lines = lines, + jump = { + -- Show float on jump if no diagnostic text is otherwise shown + float = not (text or lines), + }, }) end diff --git a/modules/home/vim/lua/ambroisie/utils.lua b/modules/home/vim/lua/ambroisie/utils.lua index c9e9292..0ee7c83 100644 --- a/modules/home/vim/lua/ambroisie/utils.lua +++ b/modules/home/vim/lua/ambroisie/utils.lua @@ -38,7 +38,7 @@ end --- @param bufnr int? buffer number --- @return table all active LSP client names M.list_lsp_clients = function(bufnr) - local clients = vim.lsp.get_active_clients({ bufnr = bufnr }) + local clients = vim.lsp.get_clients({ bufnr = bufnr }) local names = {} for _, client in ipairs(clients) do diff --git a/modules/home/vim/plugin/settings/fastfold.lua b/modules/home/vim/plugin/settings/fastfold.lua deleted file mode 100644 index 78ee937..0000000 --- a/modules/home/vim/plugin/settings/fastfold.lua +++ /dev/null @@ -1,5 +0,0 @@ --- Intercept all fold commands --- stylua: ignore -vim.g.fastfold_fold_command_suffixes = { - "x", "X", "a", "A", "o", "O", "c", "C", "r", "R", "m", "M", "i", "n", "N", -} diff --git a/modules/home/vim/plugin/settings/lsp-lines.lua b/modules/home/vim/plugin/settings/lsp-lines.lua deleted file mode 100644 index 9c79818..0000000 --- a/modules/home/vim/plugin/settings/lsp-lines.lua +++ /dev/null @@ -1,3 +0,0 @@ -local lsp_lines = require("lsp_lines") - -lsp_lines.setup() diff --git a/modules/home/vim/plugin/settings/lspconfig.lua b/modules/home/vim/plugin/settings/lspconfig.lua index 1f9abfd..7817d4c 100644 --- a/modules/home/vim/plugin/settings/lspconfig.lua +++ b/modules/home/vim/plugin/settings/lspconfig.lua @@ -16,6 +16,10 @@ vim.diagnostic.config({ update_in_insert = false, -- Show highest severity first severity_sort = true, + jump = { + -- Show float on diagnostic jumps + float = true, + }, }) -- Inform servers we are able to do completion, snippets, etc... @@ -96,6 +100,13 @@ if utils.is_executable("starpls") then end -- Generic +if utils.is_executable("harper-ls") then + lspconfig.harper_ls.setup({ + capabilities = capabilities, + on_attach = lsp.on_attach, + }) +end + if utils.is_executable("typos-lsp") then lspconfig.typos_lsp.setup({ capabilities = capabilities, diff --git a/modules/home/vim/plugin/settings/lualine.lua b/modules/home/vim/plugin/settings/lualine.lua index 5219a95..bbe4647 100644 --- a/modules/home/vim/plugin/settings/lualine.lua +++ b/modules/home/vim/plugin/settings/lualine.lua @@ -1,4 +1,5 @@ local lualine = require("lualine") +local oil = require("oil") local utils = require("ambroisie.utils") local function list_spell_languages() @@ -30,7 +31,7 @@ lualine.setup({ { "mode" }, }, lualine_b = { - { "FugitiveHead" }, + { "branch" }, { "filename", symbols = { readonly = "🔒" } }, }, lualine_c = { @@ -57,5 +58,21 @@ lualine.setup({ extensions = { "fugitive", "quickfix", + { + sections = { + lualine_a = { + { "mode" }, + }, + lualine_b = { + { "branch" }, + }, + lualine_c = { + function() + return vim.fn.fnamemodify(oil.get_current_dir(), ":~") + end, + }, + }, + filetypes = { "oil" }, + }, }, }) diff --git a/modules/home/vim/plugin/settings/luasnip.lua b/modules/home/vim/plugin/settings/luasnip.lua deleted file mode 100644 index 80309d7..0000000 --- a/modules/home/vim/plugin/settings/luasnip.lua +++ /dev/null @@ -1 +0,0 @@ -require("luasnip.loaders.from_vscode").lazy_load() diff --git a/modules/home/zsh/default.nix b/modules/home/zsh/default.nix index 11b6cb2..f4092d8 100644 --- a/modules/home/zsh/default.nix +++ b/modules/home/zsh/default.nix @@ -87,28 +87,26 @@ in # Modal editing is life, but CLI benefits from emacs gymnastics defaultKeymap = "emacs"; - # Make those happen early to avoid doing double the work - initExtraFirst = lib.mkBefore '' - ${ - lib.optionalString cfg.launchTmux '' - # Launch tmux unless already inside one - if [ -z "$TMUX" ]; then - exec tmux new-session - fi - '' - } - ''; + initContent = lib.mkMerge [ + # Make those happen early to avoid doing double the work + (lib.mkBefore (lib.optionalString cfg.launchTmux '' + # Launch tmux unless already inside one + if [ -z "$TMUX" ]; then + exec tmux new-session + fi + '')) - initExtra = lib.mkAfter '' - source ${./completion-styles.zsh} - source ${./extra-mappings.zsh} - source ${./options.zsh} + (lib.mkAfter '' + source ${./completion-styles.zsh} + source ${./extra-mappings.zsh} + source ${./options.zsh} - # Source local configuration - if [ -f "$ZDOTDIR/zshrc.local" ]; then - source "$ZDOTDIR/zshrc.local" - fi - ''; + # Source local configuration + if [ -f "$ZDOTDIR/zshrc.local" ]; then + source "$ZDOTDIR/zshrc.local" + fi + '') + ]; localVariables = { # I like having the full path @@ -151,7 +149,7 @@ in }; # Use OSC-777 to send the notification through SSH - initExtra = lib.mkIf cfg.notify.ssh.useOsc777 '' + initContent = lib.mkIf cfg.notify.ssh.useOsc777 '' done_send_notification() { local exit_status="$1" local title="$2" diff --git a/modules/nixos/services/default.nix b/modules/nixos/services/default.nix index 3992385..27f8765 100644 --- a/modules/nixos/services/default.nix +++ b/modules/nixos/services/default.nix @@ -15,7 +15,6 @@ ./gitea ./grocy ./homebox - ./indexers ./jellyfin ./komga ./lohr diff --git a/modules/nixos/services/homebox/default.nix b/modules/nixos/services/homebox/default.nix index d79e331..8ed5d77 100644 --- a/modules/nixos/services/homebox/default.nix +++ b/modules/nixos/services/homebox/default.nix @@ -19,6 +19,11 @@ in services.homebox = { enable = true; + # Automatic PostgreSQL provisioning + database = { + createLocally = true; + }; + settings = { # FIXME: mailer? HBOX_WEB_PORT = toString cfg.port; @@ -28,6 +33,7 @@ in my.services.nginx.virtualHosts = { homebox = { inherit (cfg) port; + websocketsLocations = [ "/api" ]; }; }; diff --git a/modules/nixos/services/indexers/default.nix b/modules/nixos/services/indexers/default.nix deleted file mode 100644 index 8a42345..0000000 --- a/modules/nixos/services/indexers/default.nix +++ /dev/null @@ -1,78 +0,0 @@ -# Torrent and usenet meta-indexers -{ config, lib, ... }: -let - cfg = config.my.services.indexers; - - jackettPort = 9117; - nzbhydraPort = 5076; - prowlarrPort = 9696; -in -{ - options.my.services.indexers = with lib; { - jackett.enable = mkEnableOption "Jackett torrent meta-indexer"; - nzbhydra.enable = mkEnableOption "NZBHydra2 usenet meta-indexer"; - prowlarr.enable = mkEnableOption "Prowlarr torrent & usenet meta-indexer"; - }; - - config = lib.mkMerge [ - (lib.mkIf cfg.jackett.enable { - services.jackett = { - enable = true; - }; - - # Jackett wants to eat *all* my RAM if left to its own devices - systemd.services.jackett = { - serviceConfig = { - MemoryHigh = "15%"; - MemoryMax = "25%"; - }; - }; - - my.services.nginx.virtualHosts = { - jackett = { - port = jackettPort; - }; - }; - }) - - (lib.mkIf cfg.nzbhydra.enable { - services.nzbhydra2 = { - enable = true; - }; - - my.services.nginx.virtualHosts = { - nzbhydra = { - port = nzbhydraPort; - }; - }; - }) - - (lib.mkIf cfg.prowlarr.enable { - services.prowlarr = { - enable = true; - }; - - my.services.nginx.virtualHosts = { - prowlarr = { - port = prowlarrPort; - }; - }; - - services.fail2ban.jails = { - prowlarr = '' - enabled = true - filter = prowlarr - action = iptables-allports - ''; - }; - - environment.etc = { - "fail2ban/filter.d/prowlarr.conf".text = '' - [Definition] - failregex = ^.*\|Warn\|Auth\|Auth-Failure ip username .*$ - journalmatch = _SYSTEMD_UNIT=prowlarr.service - ''; - }; - }) - ]; -} diff --git a/modules/nixos/services/nextcloud/default.nix b/modules/nixos/services/nextcloud/default.nix index fe94177..cf1b876 100644 --- a/modules/nixos/services/nextcloud/default.nix +++ b/modules/nixos/services/nextcloud/default.nix @@ -35,7 +35,7 @@ in config = lib.mkIf cfg.enable { services.nextcloud = { enable = true; - package = pkgs.nextcloud30; + package = pkgs.nextcloud31; hostName = "nextcloud.${config.networking.domain}"; home = "/var/lib/nextcloud"; maxUploadSize = cfg.maxSize; diff --git a/modules/nixos/services/servarr/autobrr.nix b/modules/nixos/services/servarr/autobrr.nix new file mode 100644 index 0000000..afb07f4 --- /dev/null +++ b/modules/nixos/services/servarr/autobrr.nix @@ -0,0 +1,62 @@ +# IRC-based +{ config, lib, ... }: +let + cfg = config.my.services.servarr.autobrr; +in +{ + options.my.services.servarr.autobrr = with lib; { + enable = mkEnableOption "autobrr IRC announce tracker" // { + default = config.my.services.servarr.enableAll; + }; + + port = mkOption { + type = types.port; + default = 7474; + example = 8080; + description = "Internal port for webui"; + }; + + sessionSecretFile = mkOption { + type = types.str; + example = "/run/secrets/autobrr-secret.txt"; + description = '' + File containing the session secret. + ''; + }; + }; + + config = lib.mkIf cfg.enable { + services.autobrr = { + enable = true; + + settings = { + inherit (cfg) port; + checkForUpdates = false; + }; + + secretFile = cfg.sessionSecretFile; + }; + + my.services.nginx.virtualHosts = { + autobrr = { + inherit (cfg) port; + }; + }; + + services.fail2ban.jails = { + autobrr = '' + enabled = true + filter = autobrr + action = iptables-allports + ''; + }; + + environment.etc = { + "fail2ban/filter.d/autobrr.conf".text = '' + [Definition] + failregex = ^.*Auth: invalid login \[.*\] from: $ + journalmatch = _SYSTEMD_UNIT=autobrr.service + ''; + }; + }; +} diff --git a/modules/nixos/services/servarr/bazarr.nix b/modules/nixos/services/servarr/bazarr.nix new file mode 100644 index 0000000..637da0c --- /dev/null +++ b/modules/nixos/services/servarr/bazarr.nix @@ -0,0 +1,37 @@ +{ config, lib, ... }: +let + cfg = config.my.services.servarr.bazarr; +in +{ + options.my.services.servarr.bazarr = with lib; { + enable = lib.mkEnableOption "Bazarr" // { + default = config.my.services.servarr.enableAll; + }; + + port = mkOption { + type = types.port; + default = 6767; + example = 8080; + description = "Internal port for webui"; + }; + }; + + config = lib.mkIf cfg.enable { + services.bazarr = { + enable = true; + group = "media"; + listenPort = cfg.port; + }; + + # Set-up media group + users.groups.media = { }; + + my.services.nginx.virtualHosts = { + bazarr = { + inherit (cfg) port; + }; + }; + + # Bazarr does not log authentication failures... + }; +} diff --git a/modules/nixos/services/servarr/default.nix b/modules/nixos/services/servarr/default.nix index e25d9cf..409fcdc 100644 --- a/modules/nixos/services/servarr/default.nix +++ b/modules/nixos/services/servarr/default.nix @@ -2,99 +2,21 @@ # Relevant link [1]. # # [1]: https://youtu.be/I26Ql-uX6AM -{ config, lib, ... }: -let - cfg = config.my.services.servarr; - - ports = { - bazarr = 6767; - lidarr = 8686; - radarr = 7878; - readarr = 8787; - sonarr = 8989; - }; - - mkService = service: { - services.${service} = { - enable = true; - group = "media"; - }; - }; - - mkRedirection = service: { - my.services.nginx.virtualHosts = { - ${service} = { - port = ports.${service}; - }; - }; - }; - - mkFail2Ban = service: lib.mkIf cfg.${service}.enable { - services.fail2ban.jails = { - ${service} = '' - enabled = true - filter = ${service} - action = iptables-allports - ''; - }; - - environment.etc = { - "fail2ban/filter.d/${service}.conf".text = '' - [Definition] - failregex = ^.*\|Warn\|Auth\|Auth-Failure ip username .*$ - journalmatch = _SYSTEMD_UNIT=${service}.service - ''; - }; - }; - - mkFullConfig = service: lib.mkIf cfg.${service}.enable (lib.mkMerge [ - (mkService service) - (mkRedirection service) - ]); -in +{ lib, ... }: { + imports = [ + ./autobrr.nix + ./bazarr.nix + ./jackett.nix + ./nzbhydra.nix + ./prowlarr.nix + (import ./starr.nix "lidarr") + (import ./starr.nix "radarr") + (import ./starr.nix "readarr") + (import ./starr.nix "sonarr") + ]; + options.my.services.servarr = { - enable = lib.mkEnableOption "Media automation"; - - bazarr = { - enable = lib.my.mkDisableOption "Bazarr"; - }; - - lidarr = { - enable = lib.my.mkDisableOption "Lidarr"; - }; - - radarr = { - enable = lib.my.mkDisableOption "Radarr"; - }; - - readarr = { - enable = lib.my.mkDisableOption "Readarr"; - }; - - sonarr = { - enable = lib.my.mkDisableOption "Sonarr"; - }; + enableAll = lib.mkEnableOption "media automation suite"; }; - - config = lib.mkIf cfg.enable (lib.mkMerge [ - { - # Set-up media group - users.groups.media = { }; - } - # Bazarr does not log authentication failures... - (mkFullConfig "bazarr") - # Lidarr for music - (mkFullConfig "lidarr") - (mkFail2Ban "lidarr") - # Radarr for movies - (mkFullConfig "radarr") - (mkFail2Ban "radarr") - # Readarr for books - (mkFullConfig "readarr") - (mkFail2Ban "readarr") - # Sonarr for shows - (mkFullConfig "sonarr") - (mkFail2Ban "sonarr") - ]); } diff --git a/modules/nixos/services/servarr/jackett.nix b/modules/nixos/services/servarr/jackett.nix new file mode 100644 index 0000000..481cd3d --- /dev/null +++ b/modules/nixos/services/servarr/jackett.nix @@ -0,0 +1,41 @@ +{ config, lib, ... }: +let + cfg = config.my.services.servarr.jackett; +in +{ + options.my.services.servarr.jackett = with lib; { + enable = lib.mkEnableOption "Jackett" // { + default = config.my.services.servarr.enableAll; + }; + + port = mkOption { + type = types.port; + default = 9117; + example = 8080; + description = "Internal port for webui"; + }; + }; + + config = lib.mkIf cfg.enable { + services.jackett = { + enable = true; + inherit (cfg) port; + }; + + # Jackett wants to eat *all* my RAM if left to its own devices + systemd.services.jackett = { + serviceConfig = { + MemoryHigh = "15%"; + MemoryMax = "25%"; + }; + }; + + my.services.nginx.virtualHosts = { + jackett = { + inherit (cfg) port; + }; + }; + + # Jackett does not log authentication failures... + }; +} diff --git a/modules/nixos/services/servarr/nzbhydra.nix b/modules/nixos/services/servarr/nzbhydra.nix new file mode 100644 index 0000000..7b63986 --- /dev/null +++ b/modules/nixos/services/servarr/nzbhydra.nix @@ -0,0 +1,26 @@ +{ config, lib, ... }: +let + cfg = config.my.services.servarr.nzbhydra; +in +{ + options.my.services.servarr.nzbhydra = with lib; { + enable = lib.mkEnableOption "NZBHydra2" // { + default = config.my.services.servarr.enableAll; + }; + }; + + config = lib.mkIf cfg.enable { + services.nzbhydra2 = { + enable = true; + }; + + my.services.nginx.virtualHosts = { + nzbhydra = { + port = 5076; + websocketsLocations = [ "/" ]; + }; + }; + + # NZBHydra2 does not log authentication failures... + }; +} diff --git a/modules/nixos/services/servarr/prowlarr.nix b/modules/nixos/services/servarr/prowlarr.nix new file mode 100644 index 0000000..ce044c6 --- /dev/null +++ b/modules/nixos/services/servarr/prowlarr.nix @@ -0,0 +1,53 @@ +# Torrent and NZB indexer +{ config, lib, ... }: +let + cfg = config.my.services.servarr.prowlarr; +in +{ + options.my.services.servarr.prowlarr = with lib; { + enable = lib.mkEnableOption "Prowlarr" // { + default = config.my.services.servarr.enableAll; + }; + + port = mkOption { + type = types.port; + default = 9696; + example = 8080; + description = "Internal port for webui"; + }; + }; + + config = lib.mkIf cfg.enable { + services.prowlarr = { + enable = true; + + settings = { + server = { + port = cfg.port; + }; + }; + }; + + my.services.nginx.virtualHosts = { + prowlarr = { + inherit (cfg) port; + }; + }; + + services.fail2ban.jails = { + prowlarr = '' + enabled = true + filter = prowlarr + action = iptables-allports + ''; + }; + + environment.etc = { + "fail2ban/filter.d/prowlarr.conf".text = '' + [Definition] + failregex = ^.*\|Warn\|Auth\|Auth-Failure ip username .*$ + journalmatch = _SYSTEMD_UNIT=prowlarr.service + ''; + }; + }; +} diff --git a/modules/nixos/services/servarr/starr.nix b/modules/nixos/services/servarr/starr.nix new file mode 100644 index 0000000..2bf7c11 --- /dev/null +++ b/modules/nixos/services/servarr/starr.nix @@ -0,0 +1,64 @@ +# Templated *arr configuration +starr: +{ config, lib, ... }: +let + cfg = config.my.services.servarr.${starr}; + ports = { + lidarr = 8686; + radarr = 7878; + readarr = 8787; + sonarr = 8989; + }; +in +{ + options.my.services.servarr.${starr} = with lib; { + enable = lib.mkEnableOption (lib.toSentenceCase starr) // { + default = config.my.services.servarr.enableAll; + }; + + port = mkOption { + type = types.port; + default = ports.${starr}; + example = 8080; + description = "Internal port for webui"; + }; + }; + + config = lib.mkIf cfg.enable { + services.${starr} = { + enable = true; + group = "media"; + + settings = { + server = { + port = cfg.port; + }; + }; + }; + + # Set-up media group + users.groups.media = { }; + + my.services.nginx.virtualHosts = { + ${starr} = { + port = cfg.port; + }; + }; + + services.fail2ban.jails = { + ${starr} = '' + enabled = true + filter = ${starr} + action = iptables-allports + ''; + }; + + environment.etc = { + "fail2ban/filter.d/${starr}.conf".text = '' + [Definition] + failregex = ^.*\|Warn\|Auth\|Auth-Failure ip username .*$ + journalmatch = _SYSTEMD_UNIT=${starr}.service + ''; + }; + }; +} diff --git a/templates/c++-cmake/flake.nix b/templates/c++-cmake/flake.nix index db3b35c..7796f5e 100644 --- a/templates/c++-cmake/flake.nix +++ b/templates/c++-cmake/flake.nix @@ -16,19 +16,18 @@ ref = "nixos-unstable"; }; - pre-commit-hooks = { + git-hooks = { type = "github"; owner = "cachix"; - repo = "pre-commit-hooks.nix"; + repo = "git-hooks.nix"; ref = "master"; inputs = { - flake-utils.follows = "futils"; nixpkgs.follows = "nixpkgs"; }; }; }; - outputs = { self, futils, nixpkgs, pre-commit-hooks }: + outputs = { self, futils, nixpkgs, git-hooks }: { overlays = { default = final: _prev: { @@ -69,7 +68,7 @@ ]; }; - pre-commit = pre-commit-hooks.lib.${system}.run { + pre-commit = git-hooks.lib.${system}.run { src = self; hooks = { @@ -92,12 +91,12 @@ devShells = { default = pkgs.mkShell { - inputsFrom = with self.packages.${system}; [ - project + inputsFrom = [ + self.packages.${system}.project ]; packages = with pkgs; [ - clang-tools + self.checks.${system}.pre-commit.enabledPackages ]; inherit (pre-commit) shellHook; diff --git a/templates/c++-meson/flake.nix b/templates/c++-meson/flake.nix index 5957c62..cb14eb5 100644 --- a/templates/c++-meson/flake.nix +++ b/templates/c++-meson/flake.nix @@ -16,19 +16,18 @@ ref = "nixos-unstable"; }; - pre-commit-hooks = { + git-hooks = { type = "github"; owner = "cachix"; - repo = "pre-commit-hooks.nix"; + repo = "git-hooks.nix"; ref = "master"; inputs = { - flake-utils.follows = "futils"; nixpkgs.follows = "nixpkgs"; }; }; }; - outputs = { self, futils, nixpkgs, pre-commit-hooks }: + outputs = { self, futils, nixpkgs, git-hooks }: { overlays = { default = final: _prev: { @@ -69,7 +68,7 @@ ]; }; - pre-commit = pre-commit-hooks.lib.${system}.run { + pre-commit = git-hooks.lib.${system}.run { src = self; hooks = { @@ -92,12 +91,12 @@ devShells = { default = pkgs.mkShell { - inputsFrom = with self.packages.${system}; [ - project + inputsFrom = [ + self.packages.${system}.project ]; packages = with pkgs; [ - clang-tools + self.checks.${system}.pre-commit.enabledPackages ]; inherit (pre-commit) shellHook; diff --git a/templates/default.nix b/templates/default.nix index 44db753..51864cd 100644 --- a/templates/default.nix +++ b/templates/default.nix @@ -7,6 +7,10 @@ path = ./c++-meson; description = "A C++ project using Meson"; }; + "python-uv" = { + path = ./python-uv; + description = "A Python project using uv"; + }; "rust-cargo" = { path = ./rust-cargo; description = "A Rust project using Cargo"; diff --git a/templates/python-uv/.envrc b/templates/python-uv/.envrc new file mode 100644 index 0000000..390d06d --- /dev/null +++ b/templates/python-uv/.envrc @@ -0,0 +1,6 @@ +# shellcheck shell=bash +if ! has nix_direnv_version || ! nix_direnv_version 3.0.0; then + source_url "https://raw.githubusercontent.com/nix-community/nix-direnv/3.0.0/direnvrc" "sha256-21TMnI2xWX7HkSTjFFri2UaohXVj854mgvWapWrxRXg=" +fi + +use flake diff --git a/templates/python-uv/.gitignore b/templates/python-uv/.gitignore new file mode 100644 index 0000000..c79d1e8 --- /dev/null +++ b/templates/python-uv/.gitignore @@ -0,0 +1,6 @@ +# Virtual environments +.venv + +# Nix generated files +/.pre-commit-config.yaml +/result diff --git a/templates/python-uv/.woodpecker/check.yml b/templates/python-uv/.woodpecker/check.yml new file mode 100644 index 0000000..272c0e4 --- /dev/null +++ b/templates/python-uv/.woodpecker/check.yml @@ -0,0 +1,31 @@ +labels: + backend: local + +steps: +- name: pre-commit check + image: bash + commands: + - nix develop --command pre-commit run --all + +- name: nix flake check + image: bash + commands: + - nix flake check + +- name: notify + image: bash + environment: + ADDRESS: + from_secret: matrix_homeserver + ROOM: + from_secret: matrix_roomid + USER: + from_secret: matrix_username + PASS: + from_secret: matrix_password + commands: + - nix run github:ambroisie/matrix-notifier + when: + status: + - failure + - success diff --git a/templates/python-uv/flake.nix b/templates/python-uv/flake.nix new file mode 100644 index 0000000..5059e64 --- /dev/null +++ b/templates/python-uv/flake.nix @@ -0,0 +1,112 @@ +{ + description = "A Python project"; + + inputs = { + futils = { + type = "github"; + owner = "numtide"; + repo = "flake-utils"; + ref = "main"; + }; + + nixpkgs = { + type = "github"; + owner = "NixOS"; + repo = "nixpkgs"; + ref = "nixos-unstable"; + }; + + git-hooks = { + type = "github"; + owner = "cachix"; + repo = "git-hooks.nix"; + ref = "master"; + inputs = { + nixpkgs.follows = "nixpkgs"; + }; + }; + }; + + outputs = { self, futils, nixpkgs, git-hooks }: + { + overlays = { + default = final: _prev: { + project = with final; python3.pkgs.buildPythonApplication { + pname = "project"; + version = (final.lib.importTOML ./pyproject.toml).project.version; + pyproject = true; + + src = self; + + build-system = with python3.pkgs; [ setuptools ]; + + pythonImportsCheck = [ "project" ]; + + meta = with lib; { + description = "A Python project"; + homepage = "https://git.belanyi.fr/ambroisie/project"; + license = licenses.mit; + maintainers = with maintainers; [ ambroisie ]; + }; + }; + }; + }; + } // futils.lib.eachDefaultSystem (system: + let + pkgs = import nixpkgs { + inherit system; + overlays = [ + self.overlays.default + ]; + }; + + pre-commit = git-hooks.lib.${system}.run { + src = self; + + hooks = { + mypy = { + enable = true; + }; + + nixpkgs-fmt = { + enable = true; + }; + + ruff = { + enable = true; + }; + + ruff-format = { + enable = true; + }; + }; + }; + in + { + checks = { + inherit (self.packages.${system}) project; + + inherit pre-commit; + }; + + devShells = { + default = pkgs.mkShell { + inputsFrom = [ + self.packages.${system}.project + ]; + + packages = with pkgs; [ + uv + self.checks.${system}.pre-commit.enabledPackages + ]; + + inherit (pre-commit) shellHook; + }; + }; + + packages = futils.lib.flattenTree { + default = pkgs.project; + inherit (pkgs) project; + }; + }); +} diff --git a/templates/python-uv/pyproject.toml b/templates/python-uv/pyproject.toml new file mode 100644 index 0000000..7b2d896 --- /dev/null +++ b/templates/python-uv/pyproject.toml @@ -0,0 +1,17 @@ +[build-system] +requires = ["setuptools"] +build-backend = "setuptools.build_meta" + + +[project] +name = "project" +version = "0.0.0" +description = "project description" +requires-python = ">=3.12" +dependencies = [] + +[project.scripts] +project = "project:main" + +[dependency-groups] +dev = [] diff --git a/templates/python-uv/src/project/__init__.py b/templates/python-uv/src/project/__init__.py new file mode 100644 index 0000000..b06117d --- /dev/null +++ b/templates/python-uv/src/project/__init__.py @@ -0,0 +1,2 @@ +def main() -> None: + print("Hello, world!") diff --git a/templates/rust-cargo/flake.nix b/templates/rust-cargo/flake.nix index 6d50369..efd8358 100644 --- a/templates/rust-cargo/flake.nix +++ b/templates/rust-cargo/flake.nix @@ -16,19 +16,18 @@ ref = "nixos-unstable"; }; - pre-commit-hooks = { + git-hooks = { type = "github"; owner = "cachix"; - repo = "pre-commit-hooks.nix"; + repo = "git-hooks.nix"; ref = "master"; inputs = { - flake-utils.follows = "futils"; nixpkgs.follows = "nixpkgs"; }; }; }; - outputs = { self, futils, nixpkgs, pre-commit-hooks }: + outputs = { self, futils, nixpkgs, git-hooks }: { overlays = { default = final: _prev: { @@ -60,7 +59,7 @@ ]; }; - pre-commit = pre-commit-hooks.lib.${system}.run { + pre-commit = git-hooks.lib.${system}.run { src = self; hooks = { @@ -88,14 +87,13 @@ devShells = { default = pkgs.mkShell { - inputsFrom = with self.packages.${system}; [ - project + inputsFrom = [ + self.packages.${system}.project ]; packages = with pkgs; [ - clippy rust-analyzer - rustfmt + self.checks.${system}.pre-commit.enabledPackages ]; RUST_SRC_PATH = "${pkgs.rust.packages.stable.rustPlatform.rustLibSrc}";