diff --git a/.envrc b/.envrc index a6b1f81..f5141c2 100644 --- a/.envrc +++ b/.envrc @@ -1,4 +1,3 @@ -# 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 diff --git a/.nvim.lua b/.nvim.lua new file mode 100644 index 0000000..83b17a9 --- /dev/null +++ b/.nvim.lua @@ -0,0 +1,18 @@ +local lspconfig = require("lspconfig") + +-- FIXME: https://github.com/folke/neodev.nvim ? +lspconfig.lua_ls.setup({ + settings = { + Lua = { + runtime = { + version = "LuaJIT", + }, + workspace = { + checkThirdParty = false, + library = { + vim.env.VIMRUNTIME, + }, + }, + }, + }, +}) diff --git a/.woodpecker/check.yml b/.woodpecker/check.yml index 9e885aa..aff6e84 100644 --- a/.woodpecker/check.yml +++ b/.woodpecker/check.yml @@ -7,17 +7,17 @@ steps: commands: - nix flake check -- name: notify +- name: notifiy image: bash - environment: - ADDRESS: - from_secret: matrix_homeserver - ROOM: - from_secret: matrix_roomid - USER: - from_secret: matrix_username - PASS: - from_secret: matrix_password + secrets: + - source: matrix_homeserver + target: address + - source: matrix_roomid + target: room + - source: matrix_username + target: user + - source: matrix_password + target: pass commands: - nix run '.#matrix-notifier' when: diff --git a/flake.lock b/flake.lock index b84e16d..ce8318f 100644 --- a/flake.lock +++ b/flake.lock @@ -14,11 +14,11 @@ ] }, "locked": { - "lastModified": 1762618334, - "narHash": "sha256-wyT7Pl6tMFbFrs8Lk/TlEs81N6L+VSybPfiIgzU8lbQ=", + "lastModified": 1707830867, + "narHash": "sha256-PAdwm5QqdlwIqGrfzzvzZubM+FXtilekQ/FA0cI49/o=", "owner": "ryantm", "repo": "agenix", - "rev": "fcdea223397448d35d9b31f798479227e80183f6", + "rev": "8cb01a0e717311680e0cbca06a76cbceba6f3ed6", "type": "github" }, "original": { @@ -36,11 +36,11 @@ ] }, "locked": { - "lastModified": 1744478979, - "narHash": "sha256-dyN+teG9G82G+m+PX/aSAagkC+vUv0SgUw3XkPhQodQ=", + "lastModified": 1700795494, + "narHash": "sha256-gzGLZSiOhf155FW7262kdHo2YDeugp3VuIFb4/GGng0=", "owner": "lnl7", "repo": "nix-darwin", - "rev": "43975d782b418ebf4969e9ccba82466728c2851b", + "rev": "4b9b83d5a92e8c1fbfd8eb27eda375908c11ec4d", "type": "github" }, "original": { @@ -53,11 +53,11 @@ "flake-compat": { "flake": false, "locked": { - "lastModified": 1761588595, - "narHash": "sha256-XKUZz9zewJNUj46b4AJdiRZJAvSZ0Dqj2BNfXvFlJC4=", + "lastModified": 1696426674, + "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=", "owner": "edolstra", "repo": "flake-compat", - "rev": "f387cd2afec9419c8ee37694406ca490c3f34ee5", + "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33", "type": "github" }, "original": { @@ -73,11 +73,11 @@ ] }, "locked": { - "lastModified": 1763759067, - "narHash": "sha256-LlLt2Jo/gMNYAwOgdRQBrsRoOz7BPRkzvNaI/fzXi2Q=", + "lastModified": 1709336216, + "narHash": "sha256-Dt/wOWeW6Sqm11Yh+2+t0dfEWxoMxGBvv3JpIocFl9E=", "owner": "hercules-ci", "repo": "flake-parts", - "rev": "2cccadc7357c0ba201788ae99c4dfa90728ef5e0", + "rev": "f7b3c975cf067e56e7cda6cb098ebe3fb4d74ca2", "type": "github" }, "original": { @@ -94,11 +94,11 @@ ] }, "locked": { - "lastModified": 1731533236, - "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", + "lastModified": 1709126324, + "narHash": "sha256-q6EQdSeUZOG26WelxqkmR7kArjgWCdw5sfJVHPH/7j8=", "owner": "numtide", "repo": "flake-utils", - "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", + "rev": "d465f4819400de7c8d874d50b982301f28a84605", "type": "github" }, "original": { @@ -108,42 +108,19 @@ "type": "github" } }, - "git-hooks": { - "inputs": { - "flake-compat": "flake-compat", - "gitignore": "gitignore", - "nixpkgs": [ - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1763988335, - "narHash": "sha256-QlcnByMc8KBjpU37rbq5iP7Cp97HvjRP0ucfdh+M4Qc=", - "owner": "cachix", - "repo": "git-hooks.nix", - "rev": "50b9238891e388c9fdc6a5c49e49c42533a1b5ce", - "type": "github" - }, - "original": { - "owner": "cachix", - "ref": "master", - "repo": "git-hooks.nix", - "type": "github" - } - }, "gitignore": { "inputs": { "nixpkgs": [ - "git-hooks", + "pre-commit-hooks", "nixpkgs" ] }, "locked": { - "lastModified": 1709087332, - "narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=", + "lastModified": 1703887061, + "narHash": "sha256-gGPa9qWNc6eCXT/+Z5/zMkyYOuRZqeFZBDbopNZQkuY=", "owner": "hercules-ci", "repo": "gitignore.nix", - "rev": "637db329424fd7e46cf4185293b9cc8c88c95394", + "rev": "43e1aa1308018f37118e34d3a9cb4f5e75dc11d5", "type": "github" }, "original": { @@ -159,11 +136,11 @@ ] }, "locked": { - "lastModified": 1764361670, - "narHash": "sha256-jgWzgpIaHbL3USIq0gihZeuy1lLf2YSfwvWEwnfAJUw=", + "lastModified": 1709988192, + "narHash": "sha256-qxwIkl85P0I1/EyTT+NJwzbXdOv86vgZxcv4UKicjK8=", "owner": "nix-community", "repo": "home-manager", - "rev": "780be8ef503a28939cf9dc7996b48ffb1a3e04c6", + "rev": "b0b0c3d94345050a7f86d1ebc6c56eea4389d030", "type": "github" }, "original": { @@ -175,11 +152,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1764242076, - "narHash": "sha256-sKoIWfnijJ0+9e4wRvIgm/HgE27bzwQxcEmo2J/gNpI=", + "lastModified": 1709703039, + "narHash": "sha256-6hqgQ8OK6gsMu1VtcGKBxKQInRLHtzulDo9Z5jxHEFY=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "2fad6eac6077f03fe109c4d4eb171cf96791faa4", + "rev": "9df3e30ce24fd28c7b3e2de0d986769db5d6225d", "type": "github" }, "original": { @@ -190,38 +167,59 @@ } }, "nur": { - "inputs": { - "flake-parts": [ - "flake-parts" - ], - "nixpkgs": [ - "nixpkgs" - ] - }, "locked": { - "lastModified": 1764449851, - "narHash": "sha256-VnodC1+3KML8MYLLnK84E6U2Fz4ioNacOeQd1pMCSTw=", + "lastModified": 1710013455, + "narHash": "sha256-qzOpU4APTso6JLA+/F4zlO/yL8++n/CsUpmxbQAsy/4=", "owner": "nix-community", "repo": "NUR", - "rev": "b1781c0aa8935d8d1f35d228bcc7127fcebcd363", + "rev": "cf1e9b0e085368cc489c765f285f1d07c2ec8d36", "type": "github" }, "original": { "owner": "nix-community", - "ref": "main", + "ref": "master", "repo": "NUR", "type": "github" } }, + "pre-commit-hooks": { + "inputs": { + "flake-compat": "flake-compat", + "flake-utils": [ + "futils" + ], + "gitignore": "gitignore", + "nixpkgs": [ + "nixpkgs" + ], + "nixpkgs-stable": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1708018599, + "narHash": "sha256-M+Ng6+SePmA8g06CmUZWi1AjG2tFBX9WCXElBHEKnyM=", + "owner": "cachix", + "repo": "pre-commit-hooks.nix", + "rev": "5df5a70ad7575f6601d91f0efec95dd9bc619431", + "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 0bdd180..9c29183 100644 --- a/flake.nix +++ b/flake.nix @@ -54,20 +54,18 @@ type = "github"; owner = "nix-community"; repo = "NUR"; - ref = "main"; - inputs = { - flake-parts.follows = "flake-parts"; - nixpkgs.follows = "nixpkgs"; - }; + ref = "master"; }; - git-hooks = { + pre-commit-hooks = { type = "github"; owner = "cachix"; - repo = "git-hooks.nix"; + repo = "pre-commit-hooks.nix"; ref = "master"; inputs = { + flake-utils.follows = "futils"; nixpkgs.follows = "nixpkgs"; + nixpkgs-stable.follows = "nixpkgs"; }; }; diff --git a/flake/checks.nix b/flake/checks.nix index 73e64d5..98e49bd 100644 --- a/flake/checks.nix +++ b/flake/checks.nix @@ -1,7 +1,7 @@ { inputs, ... }: { imports = [ - inputs.git-hooks.flakeModule + inputs.pre-commit-hooks.flakeModule ]; perSystem = { ... }: { diff --git a/flake/dev-shells.nix b/flake/dev-shells.nix index 87464a4..6c07d95 100644 --- a/flake/dev-shells.nix +++ b/flake/dev-shells.nix @@ -6,6 +6,8 @@ name = "NixOS-config"; nativeBuildInputs = with pkgs; [ + gitAndTools.pre-commit + lua-language-server nixpkgs-fmt ]; diff --git a/flake/home-manager.nix b/flake/home-manager.nix index 88a74e8..34af375 100644 --- a/flake/home-manager.nix +++ b/flake/home-manager.nix @@ -3,11 +3,6 @@ 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"; @@ -22,15 +17,22 @@ let ]; mkHome = name: system: inputs.home-manager.lib.homeManagerConfiguration { - pkgs = inputs.nixpkgs.legacyPackages.${system}; + # Work-around for home-manager + # * 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.overlay + ]; + }; 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 0fbd3a6..b48b551 100644 --- a/flake/nixos.nix +++ b/flake/nixos.nix @@ -3,11 +3,11 @@ let defaultModules = [ { # Let 'nixos-version --json' know about the Git revision - system.configurationRevision = self.rev or self.dirtyRev or "dirty"; + system.configurationRevision = self.rev or "dirty"; } { nixpkgs.overlays = (lib.attrValues self.overlays) ++ [ - inputs.nur.overlays.default + inputs.nur.overlay ]; } # Include generic settings @@ -15,10 +15,8 @@ let ]; buildHost = name: system: lib.nixosSystem { + inherit system; modules = defaultModules ++ [ - { - nixpkgs.hostPlatform = system; - } "${self}/hosts/nixos/${name}" ]; specialArgs = { diff --git a/flake/overlays.nix b/flake/overlays.nix index c10afc3..0c47989 100644 --- a/flake/overlays.nix +++ b/flake/overlays.nix @@ -1,4 +1,4 @@ -{ self, lib, ... }: +{ self, ... }: let default-overlays = import "${self}/overlays"; @@ -8,7 +8,7 @@ let # Expose my custom packages pkgs = _final: prev: { - ambroisie = lib.recurseIntoAttrs (import "${self}/pkgs" { pkgs = prev; }); + ambroisie = prev.recurseIntoAttrs (import "${self}/pkgs" { pkgs = prev; }); }; }; in diff --git a/hosts/homes/ambroisie@bazin/default.nix b/hosts/homes/ambroisie@bazin/default.nix index 365b70d..f52fbce 100644 --- a/hosts/homes/ambroisie@bazin/default.nix +++ b/hosts/homes/ambroisie@bazin/default.nix @@ -4,20 +4,6 @@ services.gpg-agent.enable = lib.mkForce false; my.home = { - atuin = { - package = pkgs.stdenv.mkDerivation { - pname = "atuin"; - version = "18.4.0"; - - buildCommand = '' - mkdir -p $out/bin - ln -s /usr/bin/atuin $out/bin/atuin - ''; - - meta.mainProgram = "atuin"; - }; - }; - git = { package = pkgs.emptyDirectory; }; diff --git a/hosts/homes/ambroisie@mousqueton/default.nix b/hosts/homes/ambroisie@mousqueton/default.nix index 1383618..44e62e6 100644 --- a/hosts/homes/ambroisie@mousqueton/default.nix +++ b/hosts/homes/ambroisie@mousqueton/default.nix @@ -7,20 +7,6 @@ services.gpg-agent.enable = lib.mkForce false; my.home = { - atuin = { - package = pkgs.stdenv.mkDerivation { - pname = "atuin"; - version = "18.4.0"; - - buildCommand = '' - mkdir -p $out/bin - ln -s /usr/bin/atuin $out/bin/atuin - ''; - - meta.mainProgram = "atuin"; - }; - }; - git = { package = pkgs.emptyDirectory; }; @@ -29,9 +15,6 @@ # I use scripts that use the passthrough sequence often on this host enablePassthrough = true; - # Frequent reboots mean that session persistence can be handy - enableResurrect = true; - terminalFeatures = { # HTerm uses `xterm-256color` as its `$TERM`, so use that here xterm-256color = { }; diff --git a/hosts/nixos/aramis/home.nix b/hosts/nixos/aramis/home.nix index e8c99e4..66a0892 100644 --- a/hosts/nixos/aramis/home.nix +++ b/hosts/nixos/aramis/home.nix @@ -2,7 +2,7 @@ { my.home = { # Use graphical pinentry - bitwarden.pinentry = pkgs.pinentry-gtk2; + bitwarden.pinentry = "gtk2"; # Ebook library calibre.enable = true; # Some amount of social life @@ -14,11 +14,13 @@ # Blue light filter gammastep.enable = true; # Use a small popup to enter passwords - gpg.pinentry = pkgs.pinentry-gtk2; + gpg.pinentry = "gtk2"; # Machine specific packages packages.additionalPackages = with pkgs; [ element-desktop # Matrix client + jellyfin-media-player # Wraps the webui and mpv together pavucontrol # Audio mixer GUI + transgui # Transmission remote ]; # Minimal video player mpv.enable = true; @@ -26,8 +28,6 @@ nm-applet.enable = true; # Terminal terminal.program = "alacritty"; - # Transmission remote - trgui.enable = true; # Zathura document viewer zathura.enable = true; }; diff --git a/hosts/nixos/porthos/secrets/acme/dns-key.age b/hosts/nixos/porthos/secrets/acme/dns-key.age index d7f159e..fce2a84 100644 --- a/hosts/nixos/porthos/secrets/acme/dns-key.age +++ b/hosts/nixos/porthos/secrets/acme/dns-key.age @@ -1,9 +1,8 @@ age-encryption.org/v1 --> ssh-ed25519 cKojmg Ec0xt1uJTva8MxUdoTVX5m3uWaIiRlodf345FEM7Uzs -aJIneWFJPB5HVeoUGp57agXih9YeZ6xMEbyQ+zJtWQY --> ssh-ed25519 jPowng B5XotRgv7s/FUegGhceBj7EoukewNUOIFl4TFRQf1EQ -PgGCBd/Pqwp7ayqi7okHBGF1SfFpwT4KlHJ/np6p2uQ ---- AeLgwGz6k3OABb53cXNaCU/sgI4FlU1s6p8PhAaFOlg -1CԹULfI1Hmb}m šg0`XG>\>8rz+Y`ʢ.JBU!z¸Z50*ٟI] I -ĵo۰g¿tncz[{ -j&NNo{ -eP=L 6.SP:e \ No newline at end of file +-> ssh-ed25519 cKojmg bQFr9oAnbo1rI/MpUV8wQz/Xj7iZY4ZU+Swf0nSIQFw +zama2XJ0gdvUlD2GHMhmZqHSxHe+dKSfXnHoWDcSw7Y +-> ssh-ed25519 jPowng gitUwSKTNKWLSxnwa185O7x/u0ul93g8wPESdZaKRk8 +uvBIfAUkZp5sg6rfeEGvL5ZDV8m2uSEotW02kjPN3Hw +--- SZxe5f/CUZBvPQa2Sz/UBY3L68rMkIGGRuZPk7YE+Vg +r&{~v?}= +}+ SQM[]k MAtmM/Ls|ޅmCiYC}x \ No newline at end of file diff --git a/hosts/nixos/porthos/secrets/matrix/sliding-sync-secret.age b/hosts/nixos/porthos/secrets/matrix/sliding-sync-secret.age new file mode 100644 index 0000000..e938cfa --- /dev/null +++ b/hosts/nixos/porthos/secrets/matrix/sliding-sync-secret.age @@ -0,0 +1,8 @@ +age-encryption.org/v1 +-> ssh-ed25519 cKojmg xRtF3XVc7yPicAV/E4U7mn0itvD0h1BWBTjwunuoe2E +OkB9sjGB3ulH4Feuyj3Ed0DBG4+mghW/Qpum9oXL/8c +-> ssh-ed25519 jPowng 1r8drqhz1yZdTq0Kvqya+ArU1C2fkN7Gg9LiWWfeUFg +cjbxntVwHvqLaJpiKs/Y8ojeb6e3/cLFcsoeuoobfFg +--- B1qA2PylJBrdZxZtCzlU2kRPvxLM+IrXTvR+ERxVtTY +"W9bg~/b4ՆI +} -NC7vWb?8=wB UpJClOșnO\ \ No newline at end of file diff --git a/hosts/nixos/porthos/secrets/pdf-edit/login.age b/hosts/nixos/porthos/secrets/pdf-edit/login.age deleted file mode 100644 index 7f13f88..0000000 --- a/hosts/nixos/porthos/secrets/pdf-edit/login.age +++ /dev/null @@ -1,8 +0,0 @@ -age-encryption.org/v1 --> ssh-ed25519 cKojmg VYlHgHSLpfKb5bn1XA3aCpfX7M23DgbraLxxOfo9PDk -Rj+mDvAsWX3WwpuhTrOubmo17j/aud5+P87df5bosBA --> ssh-ed25519 jPowng o9ZFaYrITZ6DjWw07Vk/+TkuU187/ytlEK4sw7G32G4 -zmxlpDvDDEgQFqBVARXeX1ABhvfJ4uAHfa6mIxXzjAY ---- k/d9FWW8/OSo8EllwOBV74pZyX918u54jEljGk3ATUc -4+2{hE7!ҭGA`ׁ_@ߗR_6JL4v,6%#^  BOF|7ܽL]jR -B۾as]xS pbo#J1Q=t}5>O{+. M"7ey \ No newline at end of file diff --git a/hosts/nixos/porthos/secrets/secrets.nix b/hosts/nixos/porthos/secrets/secrets.nix index f1842b4..bea380c 100644 --- a/hosts/nixos/porthos/secrets/secrets.nix +++ b/hosts/nixos/porthos/secrets/secrets.nix @@ -31,14 +31,8 @@ in publicKeys = all; }; - "lohr/secret.age" = { - owner = "lohr"; - publicKeys = all; - }; - "lohr/ssh-key.age" = { - owner = "lohr"; - publicKeys = all; - }; + "lohr/secret.age".publicKeys = all; + "lohr/ssh-key.age".publicKeys = all; "matrix/mail.age" = { owner = "matrix-synapse"; @@ -48,6 +42,9 @@ in owner = "matrix-synapse"; publicKeys = all; }; + "matrix/sliding-sync-secret.age" = { + publicKeys = all; + }; "mealie/mail.age" = { publicKeys = all; @@ -74,15 +71,10 @@ in "paperless/password.age".publicKeys = all; "paperless/secret-key.age".publicKeys = all; - "pdf-edit/login.age".publicKeys = all; - "podgrab/password.age".publicKeys = all; "pyload/credentials.age".publicKeys = all; - "servarr/autobrr/session-secret.age".publicKeys = all; - "servarr/cross-seed/configuration.json.age".publicKeys = all; - "sso/auth-key.age".publicKeys = all; "sso/ambroisie/password-hash.age".publicKeys = all; "sso/ambroisie/totp-secret.age".publicKeys = all; diff --git a/hosts/nixos/porthos/secrets/servarr/autobrr/session-secret.age b/hosts/nixos/porthos/secrets/servarr/autobrr/session-secret.age deleted file mode 100644 index e98b94a..0000000 --- a/hosts/nixos/porthos/secrets/servarr/autobrr/session-secret.age +++ /dev/null @@ -1,7 +0,0 @@ -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/secrets/servarr/cross-seed/configuration.json.age b/hosts/nixos/porthos/secrets/servarr/cross-seed/configuration.json.age deleted file mode 100644 index 94fdf97..0000000 Binary files a/hosts/nixos/porthos/secrets/servarr/cross-seed/configuration.json.age and /dev/null differ diff --git a/hosts/nixos/porthos/services.nix b/hosts/nixos/porthos/services.nix index 96f15d3..a67ae3b 100644 --- a/hosts/nixos/porthos/services.nix +++ b/hosts/nixos/porthos/services.nix @@ -10,11 +10,6 @@ in adblock = { enable = true; }; - # Audiobook and podcast library - audiobookshelf = { - enable = true; - port = 9599; - }; # Backblaze B2 backup backup = { enable = true; @@ -51,9 +46,9 @@ in passwordFile = secrets."forgejo/mail-password".path; }; }; - # Home inventory - homebox = { - enable = true; + # Meta-indexers + indexers = { + prowlarr.enable = true; }; # Jellyfin media server jellyfin.enable = true; @@ -69,6 +64,9 @@ in mailConfigFile = secrets."matrix/mail".path; # Only necessary when doing the initial registration secretFile = secrets."matrix/secret".path; + slidingSync = { + secretFile = secrets."matrix/sliding-sync-secret".path; + }; }; mealie = { enable = true; @@ -95,9 +93,6 @@ in nextcloud = { enable = true; passwordFile = secrets."nextcloud/password".path; - collabora = { - enable = true; - }; }; nix-cache = { enable = true; @@ -127,10 +122,19 @@ in passwordFile = secrets."paperless/password".path; secretKeyFile = secrets."paperless/secret-key".path; }; - # Sometimes, editing PDFs is useful - pdf-edit = { + # The whole *arr software suite + pirate = { enable = true; - loginFile = secrets."pdf-edit/login".path; + # ... But not Lidarr because I don't care for music that much + lidarr = { + enable = false; + }; + }; + # Podcast automatic downloader + podgrab = { + enable = true; + passwordFile = secrets."podgrab/password".path; + port = 9598; }; # Regular backups postgresql-backup.enable = true; @@ -142,29 +146,13 @@ in rss-bridge.enable = true; # Usenet client sabnzbd.enable = true; - # The whole *arr software suite - servarr = { - enableAll = true; - autobrr = { - sessionSecretFile = secrets."servarr/autobrr/session-secret".path; - }; - cross-seed = { - secretSettingsFile = secrets."servarr/cross-seed/configuration.json".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 + # Because I stilll need to play sysadmin ssh-server.enable = true; + # Recipe manager + tandoor-recipes = { + enable = true; + secretKeyFile = secrets."tandoor-recipes/secret-key".path; + }; # Torrent client and webui transmission = { enable = true; diff --git a/modules/home/atuin/default.nix b/modules/home/atuin/default.nix index 40d2b04..b8973cc 100644 --- a/modules/home/atuin/default.nix +++ b/modules/home/atuin/default.nix @@ -1,26 +1,15 @@ -{ config, lib, pkgs, ... }: +{ config, lib, ... }: let cfg = config.my.home.atuin; in { options.my.home.atuin = with lib; { enable = my.mkDisableOption "atuin configuration"; - - package = mkPackageOption pkgs "atuin" { }; - - daemon = { - enable = my.mkDisableOption "atuin daemon"; - }; }; config = lib.mkIf cfg.enable { programs.atuin = { enable = true; - inherit (cfg) package; - - daemon = lib.mkIf cfg.daemon.enable { - enable = true; - }; flags = [ # I *despise* this hijacking of the up key, even though I use Ctrl-p @@ -28,8 +17,6 @@ in ]; settings = { - # Reasonable date format - dialect = "uk"; # The package is managed by Nix update_check = false; # I don't care for the fancy display diff --git a/modules/home/bitwarden/default.nix b/modules/home/bitwarden/default.nix index 0c0dfab..c709f7b 100644 --- a/modules/home/bitwarden/default.nix +++ b/modules/home/bitwarden/default.nix @@ -1,4 +1,4 @@ -{ config, lib, pkgs, ... }: +{ config, lib, ... }: let cfg = config.my.home.bitwarden; in @@ -6,7 +6,12 @@ in options.my.home.bitwarden = with lib; { enable = my.mkDisableOption "bitwarden configuration"; - pinentry = mkPackageOption pkgs "pinentry" { default = [ "pinentry-tty" ]; }; + pinentry = mkOption { + type = types.str; + default = "tty"; + example = "gtk2"; + description = "Which pinentry interface to use"; + }; }; config = lib.mkIf cfg.enable { diff --git a/modules/home/calibre/default.nix b/modules/home/calibre/default.nix index de7c126..6edf654 100644 --- a/modules/home/calibre/default.nix +++ b/modules/home/calibre/default.nix @@ -5,13 +5,11 @@ in { options.my.home.calibre = with lib; { enable = mkEnableOption "calibre configuration"; - - package = mkPackageOption pkgs "calibre" { }; }; config = lib.mkIf cfg.enable { home.packages = with pkgs; [ - cfg.package + calibre ]; }; } diff --git a/modules/home/default.nix b/modules/home/default.nix index ad3b979..c8183cf 100644 --- a/modules/home/default.nix +++ b/modules/home/default.nix @@ -8,7 +8,6 @@ ./bluetooth ./calibre ./comma - ./delta ./dircolors ./direnv ./discord @@ -38,7 +37,6 @@ ./ssh ./terminal ./tmux - ./trgui ./udiskie ./vim ./wget @@ -52,6 +50,9 @@ # First sane reproducible version home.stateVersion = "20.09"; + # Who am I? + home.username = "ambroisie"; + # Start services automatically systemd.user.startServices = "sd-switch"; } diff --git a/modules/home/delta/default.nix b/modules/home/delta/default.nix deleted file mode 100644 index e76edc6..0000000 --- a/modules/home/delta/default.nix +++ /dev/null @@ -1,49 +0,0 @@ -{ 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"; - }; - }; - - config = lib.mkIf cfg.enable { - programs.delta = { - enable = true; - - inherit (cfg) package; - - enableGitIntegration = cfg.git.enable; - - 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"; - }; - }; - }; - }; -} diff --git a/modules/home/direnv/default.nix b/modules/home/direnv/default.nix index 67beb62..93a1f3b 100644 --- a/modules/home/direnv/default.nix +++ b/modules/home/direnv/default.nix @@ -7,9 +7,9 @@ in enable = my.mkDisableOption "direnv configuration"; defaultFlake = mkOption { - type = with types; nullOr str; - default = null; - example = "pkgs"; + type = types.str; + default = "pkgs"; + example = "nixpkgs"; description = '' Which flake from the registry should be used for use pkgs by default. @@ -39,7 +39,7 @@ in in lib.my.genAttrs' files linkLibFile; - home.sessionVariables = lib.mkIf (cfg.defaultFlake != null) { + home.sessionVariables = { DIRENV_DEFAULT_FLAKE = cfg.defaultFlake; }; }; diff --git a/modules/home/direnv/lib/android.sh b/modules/home/direnv/lib/android.sh index 9344aea..fa2f856 100644 --- a/modules/home/direnv/lib/android.sh +++ b/modules/home/direnv/lib/android.sh @@ -1,4 +1,4 @@ -# shellcheck shell=bash +#shellcheck shell=bash # shellcheck disable=2155 use_android() { @@ -32,16 +32,10 @@ use_android() { -b|--build-tools) build_tools_version="$2" shift 2 - if ! [ -e "$ANDROID_HOME/build-tools/$build_tools_version" ]; then - log_error "use_android: build-tools version '$build_tools_version' does not exist" - fi ;; -n|--ndk) ndk_version="$2" shift 2 - if ! [ -e "$ANDROID_HOME/ndk/$ndk_version" ]; then - log_error "use_android: NDK version '$ndk_version' does not exist" - fi ;; --) shift diff --git a/modules/home/direnv/lib/nix.sh b/modules/home/direnv/lib/nix.sh index 4b6c547..a65eb31 100644 --- a/modules/home/direnv/lib/nix.sh +++ b/modules/home/direnv/lib/nix.sh @@ -1,4 +1,4 @@ -# shellcheck shell=bash +#shellcheck shell=bash use_pkgs() { if ! has nix; then diff --git a/modules/home/direnv/lib/postgres.sh b/modules/home/direnv/lib/postgres.sh index 46e171d..c2e6a8f 100644 --- a/modules/home/direnv/lib/postgres.sh +++ b/modules/home/direnv/lib/postgres.sh @@ -1,4 +1,4 @@ -# shellcheck shell=bash +#shellcheck shell=bash layout_postgres() { if ! has postgres || ! has initdb; then diff --git a/modules/home/direnv/lib/python.sh b/modules/home/direnv/lib/python.sh index b1be8a9..15a273f 100644 --- a/modules/home/direnv/lib/python.sh +++ b/modules/home/direnv/lib/python.sh @@ -1,4 +1,4 @@ -# shellcheck shell=bash +#shellcheck shell=bash layout_poetry() { if ! has poetry; then @@ -9,12 +9,12 @@ layout_poetry() { if [[ ! -f pyproject.toml ]]; then # shellcheck disable=2016 - log_error 'layout_poetry: no pyproject.toml found. Use `poetry init` to create one first' + log_error 'layout_poetry: no pyproject.toml found. Use `poetry new` or `poetry init` to create one first' return 1 fi # create venv if it doesn't exist - poetry run -q -- true + poetry run true # shellcheck disable=2155 export VIRTUAL_ENV=$(poetry env info --path) @@ -23,35 +23,3 @@ layout_poetry() { watch_file pyproject.toml watch_file poetry.lock } - -layout_uv() { - if ! has uv; then - # shellcheck disable=2016 - log_error 'layout_uv: `uv` is not in PATH' - return 1 - fi - - if [[ ! -f pyproject.toml ]]; then - # shellcheck disable=2016 - log_error 'layout_uv: no pyproject.toml found. Use `uv init` to create one first' - return 1 - fi - - local default_venv="$PWD/.venv" - : "${VIRTUAL_ENV:=$default_venv}" - - # Use non-default venv path if required - if [ "$VIRTUAL_ENV" != "$default_venv" ]; then - export UV_PROJECT_ENVIRONMENT="$VIRTUAL_ENV" - fi - - # create venv if it doesn't exist - uv venv -q --allow-existing - - export VIRTUAL_ENV - export UV_ACTIVE=1 - PATH_add "$VIRTUAL_ENV/bin" - watch_file pyproject.toml - watch_file uv.lock - watch_file .python-version -} diff --git a/modules/home/discord/default.nix b/modules/home/discord/default.nix index f9892df..7348bb4 100644 --- a/modules/home/discord/default.nix +++ b/modules/home/discord/default.nix @@ -1,24 +1,23 @@ { config, lib, pkgs, ... }: let cfg = config.my.home.discord; + + jsonFormat = pkgs.formats.json { }; in { options.my.home.discord = with lib; { enable = mkEnableOption "discord configuration"; - - package = mkPackageOption pkgs "discord" { }; }; config = lib.mkIf cfg.enable { - programs.discord = { - enable = true; + home.packages = with pkgs; [ + discord + ]; - inherit (cfg) package; - - settings = { + xdg.configFile."discord/settings.json".source = + jsonFormat.generate "discord.json" { # Do not keep me from using the app just to force an update SKIP_HOST_UPDATE = true; }; - }; }; } diff --git a/modules/home/firefox/default.nix b/modules/home/firefox/default.nix index 6346dc9..02c74f2 100644 --- a/modules/home/firefox/default.nix +++ b/modules/home/firefox/default.nix @@ -61,21 +61,19 @@ in "ui.systemUsesDarkTheme" = true; # Dark mode }; - extensions = { - packages = with pkgs.nur.repos.rycee.firefox-addons; ([ - bitwarden - consent-o-matic - form-history-control - reddit-comment-collapser - reddit-enhancement-suite - refined-github - sponsorblock - ublock-origin - ] - ++ lib.optional (cfg.tridactyl.enable) tridactyl - ++ lib.optional (cfg.ff2mpv.enable) ff2mpv - ); - }; + extensions = with pkgs.nur.repos.rycee.firefox-addons; ([ + bitwarden + consent-o-matic + form-history-control + reddit-comment-collapser + reddit-enhancement-suite + refined-github + sponsorblock + ublock-origin + ] + ++ lib.optional (cfg.tridactyl.enable) tridactyl + ++ lib.optional (cfg.ff2mpv.enable) ff2mpv + ); }; }; }; diff --git a/modules/home/firefox/tridactyl/default.nix b/modules/home/firefox/tridactyl/default.nix index 26ddfad..35b58c2 100644 --- a/modules/home/firefox/tridactyl/default.nix +++ b/modules/home/firefox/tridactyl/default.nix @@ -12,7 +12,9 @@ let in { config = lib.mkIf cfg.enable { - xdg.configFile."tridactyl/tridactylrc".source = pkgs.replaceVars ./tridactylrc { + xdg.configFile."tridactyl/tridactylrc".source = pkgs.substituteAll { + src = ./tridactylrc; + editorcmd = lib.concatStringsSep " " [ # Use my configured terminal term diff --git a/modules/home/firefox/tridactyl/tridactylrc b/modules/home/firefox/tridactyl/tridactylrc index 775719c..4dc53cf 100644 --- a/modules/home/firefox/tridactyl/tridactylrc +++ b/modules/home/firefox/tridactyl/tridactylrc @@ -4,7 +4,7 @@ " Use dark color scheme colorscheme dark -" Make tridactyl open Vim in my preferred terminal +" Make tridactyl open Vim in my prefered terminal set editorcmd @editorcmd@ " Remove editor file after use @@ -15,8 +15,8 @@ bind --mode=input editor_rm " Binds {{{ " Reddit et al. {{{ -" Toggle comments on Reddit, Hacker News, Lobste.rs, LWN -bind ;c hint -Jc [class*="expand"],[class*="togg"],[class="comment_folder"],[class="CommentTitle"] +" Toggle comments on Reddit, Hacker News, Lobste.rs +bind ;c hint -Jc [class*="expand"],[class*="togg"],[class="comment_folder"] " Make `gu` take me back to subreddit from comments bindurl reddit.com gu urlparent 3 @@ -26,8 +26,8 @@ bindurl www.google.com f hint -Jc #search a bindurl www.google.com F hint -Jbc #search a " Only hint search results on DuckDuckGo -bindurl ^https://duckduckgo.com f hint -Jc [data-testid="result"] -bindurl ^https://duckduckgo.com F hint -Jbc [data-testid="result"] +bindurl ^https://duckduckgo.com f hint -Jc [data-testid="result-title-a"] +bindurl ^https://duckduckgo.com F hint -Jbc [data-testid="result-title-a"] " Only hint item pages on Hacker News bindurl news.ycombinator.com ;f hint -Jc .age > a diff --git a/modules/home/gdb/default.nix b/modules/home/gdb/default.nix index 1ffc6bd..fe8eb69 100644 --- a/modules/home/gdb/default.nix +++ b/modules/home/gdb/default.nix @@ -6,28 +6,33 @@ in options.my.home.gdb = with lib; { enable = my.mkDisableOption "gdb configuration"; - package = mkPackageOption pkgs "gdb" { }; - rr = { enable = my.mkDisableOption "rr configuration"; - package = mkPackageOption pkgs "rr" { }; + package = mkOption { + type = types.package; + default = pkgs.rr; + defaultText = literalExample "pkgs.rr"; + description = '' + Package providing rr + ''; + }; }; }; config = lib.mkIf cfg.enable (lib.mkMerge [ { home.packages = with pkgs; [ - cfg.package + gdb ]; xdg = { configFile."gdb/gdbinit".source = ./gdbinit; - stateFile."gdb/.keep".text = ""; + dataFile. "gdb/.keep".text = ""; }; home.sessionVariables = { - GDBHISTFILE = "${config.xdg.stateHome}/gdb/gdb_history"; + GDBHISTFILE = "${config.xdg.dataHome}/gdb/gdb_history"; }; } diff --git a/modules/home/git/default.nix b/modules/home/git/default.nix index c3a51a0..1bb2215 100644 --- a/modules/home/git/default.nix +++ b/modules/home/git/default.nix @@ -21,31 +21,57 @@ in config.programs.git = lib.mkIf cfg.enable { enable = true; + # Who am I? + userEmail = mkMailAddress "bruno" "belanyi.fr"; + userName = "Bruno BELANYI"; + inherit (cfg) package; + aliases = { + git = "!git"; + lol = "log --graph --decorate --pretty=oneline --abbrev-commit --topo-order"; + lola = "lol --all"; + assume = "update-index --assume-unchanged"; + unassume = "update-index --no-assume-unchanged"; + assumed = "!git ls-files -v | grep ^h | cut -c 3-"; + pick = "log -p -G"; + push-new = "!git push -u origin " + + ''"$(git branch | grep '^* ' | cut -f2- -d' ')"''; + root = "git rev-parse --show-toplevel"; + }; + 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 - settings = { - # Who am I? - user = { - email = mkMailAddress "bruno" "belanyi.fr"; - name = "Bruno BELANYI"; - }; - - alias = { - git = "!git"; - lol = "log --graph --decorate --pretty=oneline --abbrev-commit --topo-order"; - lola = "lol --all"; - assume = "update-index --assume-unchanged"; - unassume = "update-index --no-assume-unchanged"; - assumed = "!git ls-files -v | grep ^h | cut -c 3-"; - pick = "log -p -G"; - push-new = "!git push -u origin " - + ''"$(git branch | grep '^* ' | cut -f2- -d' ')"''; - root = "git rev-parse --show-toplevel"; - }; - + extraConfig = { # Makes it a bit more readable blame = { coloring = "repeatedLines"; @@ -97,6 +123,11 @@ in defaultBranch = "main"; }; + # Local configuration, not-versioned + include = { + path = "config.local"; + }; + merge = { conflictStyle = "zdiff3"; }; @@ -136,8 +167,8 @@ in }; }; - includes = lib.mkAfter [ - # Multiple identities + # Multiple identities + includes = [ { condition = "gitdir:~/git/EPITA/"; contents = { @@ -156,10 +187,6 @@ in }; }; } - # Local configuration, not-versioned - { - path = "config.local"; - } ]; ignores = diff --git a/modules/home/gpg/default.nix b/modules/home/gpg/default.nix index 2a00baf..7eadf48 100644 --- a/modules/home/gpg/default.nix +++ b/modules/home/gpg/default.nix @@ -1,4 +1,4 @@ -{ config, lib, pkgs, ... }: +{ config, lib, ... }: let cfg = config.my.home.gpg; in @@ -6,7 +6,12 @@ in options.my.home.gpg = with lib; { enable = my.mkDisableOption "gpg configuration"; - pinentry = mkPackageOption pkgs "pinentry" { default = [ "pinentry-tty" ]; }; + pinentry = mkOption { + type = types.str; + default = "tty"; + example = "gtk2"; + description = "Which pinentry interface to use"; + }; }; config = lib.mkIf cfg.enable { @@ -17,7 +22,7 @@ in services.gpg-agent = { enable = true; enableSshSupport = true; # One agent to rule them all - pinentry.package = cfg.pinentry; + pinentryFlavor = cfg.pinentry; extraConfig = '' allow-loopback-pinentry ''; diff --git a/modules/home/gtk/default.nix b/modules/home/gtk/default.nix index f10087d..62d3f81 100644 --- a/modules/home/gtk/default.nix +++ b/modules/home/gtk/default.nix @@ -21,12 +21,12 @@ in }; iconTheme = { - package = pkgs.gnome-themes-extra; + package = pkgs.gnome.gnome-themes-extra; name = "Adwaita"; }; theme = { - package = pkgs.gnome-themes-extra; + package = pkgs.gnome.gnome-themes-extra; name = "Adwaita"; }; }; diff --git a/modules/home/jq/default.nix b/modules/home/jq/default.nix index 53e5986..57e266f 100644 --- a/modules/home/jq/default.nix +++ b/modules/home/jq/default.nix @@ -17,7 +17,6 @@ in strings = "0;32"; arrays = "1;39"; objects = "1;39"; - objectKeys = "1;34"; }; }; } diff --git a/modules/home/mail/accounts/default.nix b/modules/home/mail/accounts/default.nix index 5216ad5..8886139 100644 --- a/modules/home/mail/accounts/default.nix +++ b/modules/home/mail/accounts/default.nix @@ -26,7 +26,20 @@ let }; migaduConfig = { - flavor = "migadu.com"; + imap = { + host = "imap.migadu.com"; + port = 993; + tls = { + enable = true; + }; + }; + smtp = { + host = "smtp.migadu.com"; + port = 465; + tls = { + enable = true; + }; + }; }; gmailConfig = { @@ -45,7 +58,7 @@ in { config.accounts.email.accounts = { personal = lib.mkMerge [ - # Common configuration + # Common configuraton (mkConfig { domain = "belanyi.fr"; address = "bruno"; @@ -57,7 +70,7 @@ in ]; gmail = lib.mkMerge [ - # Common configuration + # Common configuraton (mkConfig { domain = "gmail.com"; address = "brunobelanyi"; diff --git a/modules/home/nix/default.nix b/modules/home/nix/default.nix index 2f435a8..0934189 100644 --- a/modules/home/nix/default.nix +++ b/modules/home/nix/default.nix @@ -22,16 +22,12 @@ in options.my.home.nix = with lib; { enable = my.mkDisableOption "nix configuration"; - gc = { - enable = my.mkDisableOption "nix GC configuration"; - }; - cache = { selfHosted = my.mkDisableOption "self-hosted cache"; }; inputs = { - link = my.mkDisableOption "link inputs to `$XDG_CONFIG_HOME/nix/inputs/`"; + link = my.mkDisableOption "link inputs to `/etc/nix/inputs/`"; addToRegistry = my.mkDisableOption "add inputs and self to registry"; @@ -64,22 +60,6 @@ in }; } - (lib.mkIf cfg.gc.enable { - nix.gc = { - automatic = true; - - # Every week, with some wiggle room - dates = "weekly"; - randomizedDelaySec = "10min"; - - # Use a persistent timer for e.g: laptops - persistent = true; - - # Delete old profiles automatically after 15 days - options = "--delete-older-than 15d"; - }; - }) - (lib.mkIf cfg.cache.selfHosted { nix = { settings = { @@ -116,7 +96,7 @@ in }) (lib.mkIf cfg.inputs.addToNixPath { - nix.nixPath = [ "${config.xdg.configHome}/nix/inputs" ]; + home.sessionVariables.NIX_PATH = "${config.xdg.configHome}/nix/inputs\${NIX_PATH:+:$NIX_PATH}"; }) ]); } diff --git a/modules/home/packages/default.nix b/modules/home/packages/default.nix index 43f7111..1362a06 100644 --- a/modules/home/packages/default.nix +++ b/modules/home/packages/default.nix @@ -1,7 +1,6 @@ -{ config, lib, pkgs, osConfig, ... }: +{ config, lib, pkgs, ... }: let cfg = config.my.home.packages; - useGlobalPkgs = osConfig.home-manager.useGlobalPkgs or false; in { options.my.home.packages = with lib; { @@ -27,10 +26,9 @@ in fd file ripgrep - tree ] ++ cfg.additionalPackages); - nixpkgs.config = lib.mkIf (!useGlobalPkgs) { + nixpkgs.config = { inherit (cfg) allowAliases allowUnfree; }; }; diff --git a/modules/home/pager/default.nix b/modules/home/pager/default.nix index e84dcb7..e304097 100644 --- a/modules/home/pager/default.nix +++ b/modules/home/pager/default.nix @@ -15,12 +15,8 @@ in # Clear the screen on start and exit LESS = "-R -+X -c"; # Better XDG compliance - LESSHISTFILE = "${config.xdg.stateHome}/less/history"; + LESSHISTFILE = "${config.xdg.dataHome}/less/history"; + LESSKEY = "${config.xdg.configHome}/less/lesskey"; }; - - xdg.configFile."lesskey".text = '' - # Quit without clearing the screen on `Q` - Q toggle-option -!^Predraw-on-quit\nq - ''; }; } diff --git a/modules/home/secrets/github/token.age b/modules/home/secrets/github/token.age index 3e8bb5a..1d36ccd 100644 Binary files a/modules/home/secrets/github/token.age and b/modules/home/secrets/github/token.age differ diff --git a/modules/home/secrets/secrets.nix b/modules/home/secrets/secrets.nix index 27cdb4e..f474342 100644 --- a/modules/home/secrets/secrets.nix +++ b/modules/home/secrets/secrets.nix @@ -1,6 +1,6 @@ # Common secrets let - keys = import ../../../keys; + keys = import ../../keys; all = builtins.attrValues keys.users; in diff --git a/modules/home/ssh/default.nix b/modules/home/ssh/default.nix index b0b4167..748b195 100644 --- a/modules/home/ssh/default.nix +++ b/modules/home/ssh/default.nix @@ -17,7 +17,6 @@ in { programs.ssh = { enable = true; - enableDefaultConfig = false; includes = [ # Local configuration, not-versioned @@ -54,12 +53,11 @@ in identityFile = "~/.ssh/shared_rsa"; user = "ambroisie"; }; - - # `*` is automatically made the last match block by the module - "*" = { - addKeysToAgent = "yes"; - }; }; + + extraConfig = '' + AddKeysToAgent yes + ''; }; } diff --git a/modules/home/tmux/default.nix b/modules/home/tmux/default.nix index e3e3daf..501b954 100644 --- a/modules/home/tmux/default.nix +++ b/modules/home/tmux/default.nix @@ -6,7 +6,7 @@ let (config.my.home.wm.windowManager != null) ]; - mkTerminalFeature = opt: flag: + mkTerminalFlags = opt: flag: let mkFlag = term: ''set -as terminal-features ",${term}:${flag}"''; enabledTerminals = lib.filterAttrs (_: v: v.${opt}) cfg.terminalFeatures; @@ -20,8 +20,6 @@ in enablePassthrough = mkEnableOption "tmux DCS passthrough sequence"; - enableResurrect = mkEnableOption "tmux-resurrect plugin"; - terminalFeatures = mkOption { type = with types; attrsOf (submodule { options = { @@ -32,7 +30,7 @@ in }); default = { ${config.my.home.terminal.program} = { }; }; - defaultText = literalExpression '' + defaultText = litteralExpression '' { ''${config.my.home.terminal.program} = { }; }; ''; example = { xterm-256color = { }; }; @@ -48,21 +46,18 @@ in keyMode = "vi"; # Home-row keys and other niceties clock24 = true; # I'm one of those heathens escapeTime = 0; # Let vim do its thing instead - historyLimit = 1000000; # Bigger buffer - mouse = false; # I dislike mouse support - focusEvents = true; # Report focus events + historyLimit = 100000; # Bigger buffer terminal = "tmux-256color"; # I want accurate termcap info - aggressiveResize = true; # Automatic resize when switching client size - plugins = with pkgs.tmuxPlugins; builtins.filter (attr: attr != { }) [ + plugins = with pkgs.tmuxPlugins; [ # Open high-lighted files in copy mode open # Better pane management pain-control # Better session management sessionist - # X clipboard integration { + # X clipboard integration plugin = yank; extraConfig = '' # Use 'clipboard' because of misbehaving apps (e.g: firefox) @@ -71,8 +66,8 @@ in set -g @yank_action 'copy-pipe' ''; } - # Show when prefix has been pressed { + # Show when prefix has been pressed plugin = prefix-highlight; extraConfig = '' # Also show when I'm in copy or sync mode @@ -82,23 +77,9 @@ in set -g status-right '#{prefix_highlight} %a %Y-%m-%d %H:%M' ''; } - # Resurrect sessions - (lib.optionalAttrs cfg.enableResurrect { - plugin = resurrect; - extraConfig = '' - set -g @resurrect-dir '${config.xdg.stateHome}/tmux/resurrect' - ''; - }) ]; extraConfig = '' - # Refresh configuration - bind-key -N "Source tmux.conf" R source-file ${config.xdg.configHome}/tmux/tmux.conf \; display-message "Sourced tmux.conf!" - - # Accept sloppy Ctrl key when switching windows, on top of default mapping - bind-key -N "Select the previous window" C-p previous-window - bind-key -N "Select the next window" C-n next-window - # Better vim mode bind-key -T copy-mode-vi 'v' send -X begin-selection ${ @@ -123,9 +104,9 @@ in } # Force OSC8 hyperlinks for each relevant $TERM - ${mkTerminalFeature "hyperlinks" "hyperlinks"} + ${mkTerminalFlags "hyperlinks" "hyperlinks"} # Force 24-bit color for each relevant $TERM - ${mkTerminalFeature "trueColor" "RGB"} + ${mkTerminalFlags "trueColor" "RGB"} ''; }; } diff --git a/modules/home/trgui/default.nix b/modules/home/trgui/default.nix deleted file mode 100644 index ee545a9..0000000 --- a/modules/home/trgui/default.nix +++ /dev/null @@ -1,17 +0,0 @@ -{ config, lib, pkgs, ... }: -let - cfg = config.my.home.trgui; -in -{ - options.my.home.trgui = with lib; { - enable = mkEnableOption "Transmission GUI onfiguration"; - - package = mkPackageOption pkgs "TrguiNG" { default = "trgui-ng"; }; - }; - - config = lib.mkIf cfg.enable { - home.packages = with pkgs; [ - cfg.package - ]; - }; -} diff --git a/modules/home/vim/after/ftplugin/json.vim b/modules/home/vim/after/ftplugin/json.vim deleted file mode 100644 index 3f7b09d..0000000 --- a/modules/home/vim/after/ftplugin/json.vim +++ /dev/null @@ -1,6 +0,0 @@ -" Create the `b:undo_ftplugin` variable if it doesn't exist -call ftplugined#check_undo_ft() - -" Use a small indentation value on JSON files -setlocal shiftwidth=2 -let b:undo_ftplugin.='|setlocal shiftwidth<' diff --git a/modules/home/vim/after/ftplugin/netrw.vim b/modules/home/vim/after/ftplugin/netrw.vim new file mode 100644 index 0000000..e3689f8 --- /dev/null +++ b/modules/home/vim/after/ftplugin/netrw.vim @@ -0,0 +1,6 @@ +" Create the `b:undo_ftplugin` variable if it doesn't exist +call ftplugined#check_undo_ft() + +" Don't show Netrw in buffer list +setlocal bufhidden=delete +let b:undo_ftplugin='|setlocal bufhidden<' diff --git a/modules/home/vim/after/ftplugin/query.vim b/modules/home/vim/after/ftplugin/query.vim deleted file mode 100644 index fd2ac73..0000000 --- a/modules/home/vim/after/ftplugin/query.vim +++ /dev/null @@ -1,6 +0,0 @@ -" Create the `b:undo_ftplugin` variable if it doesn't exist -call ftplugined#check_undo_ft() - -" Use a small indentation value on query files -setlocal shiftwidth=2 -let b:undo_ftplugin.='|setlocal shiftwidth<' diff --git a/modules/home/vim/after/plugin/mappings/commentary.lua b/modules/home/vim/after/plugin/mappings/commentary.lua new file mode 100644 index 0000000..6ed3b89 --- /dev/null +++ b/modules/home/vim/after/plugin/mappings/commentary.lua @@ -0,0 +1,10 @@ +local wk = require("which-key") + +local keys = { + name = "Comment/uncomment", + c = "Current line", + u = "Uncomment the current and adjacent commented lines", + ["gc"] = "Uncomment the current and adjacent commented lines", +} + +wk.register(keys, { prefix = "gc" }) diff --git a/modules/home/vim/after/plugin/mappings/misc.lua b/modules/home/vim/after/plugin/mappings/misc.lua new file mode 100644 index 0000000..6aa25a2 --- /dev/null +++ b/modules/home/vim/after/plugin/mappings/misc.lua @@ -0,0 +1,7 @@ +local wk = require("which-key") + +local keys = { + [""] = { "nohls", "Clear search highlight" }, +} + +wk.register(keys, { prefix = "" }) diff --git a/modules/home/vim/after/plugin/mappings/telescope.lua b/modules/home/vim/after/plugin/mappings/telescope.lua new file mode 100644 index 0000000..0867b36 --- /dev/null +++ b/modules/home/vim/after/plugin/mappings/telescope.lua @@ -0,0 +1,15 @@ +local wk = require("which-key") +local telescope_builtin = require("telescope.builtin") + +local keys = { + f = { + name = "Fuzzy finder", + b = { telescope_builtin.buffers, "Open buffers" }, + f = { telescope_builtin.git_files, "Git tracked files" }, + F = { telescope_builtin.find_files, "Files" }, + g = { telescope_builtin.live_grep, "Grep string" }, + G = { telescope_builtin.grep_string, "Grep string under cursor" }, + }, +} + +wk.register(keys, { prefix = "" }) diff --git a/modules/home/vim/after/plugin/mappings/tree-sitter-textobjects.lua b/modules/home/vim/after/plugin/mappings/tree-sitter-textobjects.lua new file mode 100644 index 0000000..631731c --- /dev/null +++ b/modules/home/vim/after/plugin/mappings/tree-sitter-textobjects.lua @@ -0,0 +1,30 @@ +local wk = require("which-key") + +local motions = { + ["]m"] = "Next method start", + ["]M"] = "Next method end", + ["]S"] = "Next statement start", + ["]]"] = "Next class start", + ["]["] = "Next class end", + ["[m"] = "Previous method start", + ["[M"] = "Previous method end", + ["[S"] = "Previous statement start", + ["[["] = "Previous class start", + ["[]"] = "Previous class end", +} + +local objects = { + ["aa"] = "a parameter", + ["ia"] = "inner parameter", + ["ab"] = "a block", + ["ib"] = "inner block", + ["ac"] = "a class", + ["ic"] = "inner class", + ["af"] = "a function", + ["if"] = "inner function", + ["ak"] = "a comment", + ["aS"] = "a statement", +} + +wk.register(motions, { mode = "n" }) +wk.register(objects, { mode = "o" }) diff --git a/modules/home/vim/after/plugin/mappings/unimpaired.lua b/modules/home/vim/after/plugin/mappings/unimpaired.lua index 765b6b1..f502056 100644 --- a/modules/home/vim/after/plugin/mappings/unimpaired.lua +++ b/modules/home/vim/after/plugin/mappings/unimpaired.lua @@ -3,120 +3,126 @@ local wk = require("which-key") local lsp = require("ambroisie.lsp") local keys = { - -- Previous - { "[", group = "Previous" }, - -- Edition and navigation mappings - { "[", desc = "Insert blank line above" }, - { "[", desc = "Previous location list file" }, - { "[", desc = "Previous quickfix list file" }, - { "[", desc = "Previous tag in preview window" }, - { "[a", desc = "Previous argument" }, - { "[A", desc = "First argument" }, - { "[b", desc = "Previous buffer" }, - { "[B", desc = "First buffer" }, - { "[e", desc = "Exchange previous line" }, - { "[f", desc = "Previous file in directory" }, - { "[l", desc = "Previous location list entry" }, - { "[L", desc = "First Location list entry" }, - { "[n", desc = "Previous conflict marker/diff hunk" }, - { "[p", desc = "Paste line above" }, - { "[P", desc = "Paste line above" }, - { "[q", desc = "Previous quickfix list entry" }, - { "[Q", desc = "First quickfix list entry" }, - { "[t", desc = "Previous matching tag" }, - { "[T", desc = "First matching tag" }, - { "[z", desc = "Previous fold" }, - -- Encoding - { "[C", desc = "C string encode" }, - { "[u", desc = "URL encode" }, - { "[x", desc = "XML encode" }, - { "[y", desc = "C string encode" }, + -- Edition and navigation mappins + ["["] = { + name = "Previous", + [""] = "Insert blank line above", + [""] = "Previous location list file", + [""] = "Previous quickfix list file", + [""] = "Previous tag in preview window", + a = "Previous argument", + A = "First argument", + b = "Previous buffer", + B = "First buffer", + e = "Exchange previous line", + f = "Previous file in directory", + l = "Previous location list entry", + L = "First Location list entry", + n = "Previous conflict marker/diff hunk", + p = "Paste line above", + P = "Paste line above", + q = "Previous quickfix list entry", + Q = "First quickfix list entry", + t = "Previous matching tag", + T = "First matching tag", + z = "Previous fold", + -- Encoding + C = "C string encode", + u = "URL encode", + x = "XML encode", + y = "C string encode", + -- Custom + d = { lsp.goto_prev_diagnostic, "Previous diagnostic" }, + }, + ["]"] = { + name = "Next", + [""] = "Insert blank line below", + [""] = "Next location list file", + [""] = "Next quickfix list file", + [""] = "Next tag in preview window", + a = "Next argument", + A = "Last argument", + b = "Next buffer", + B = "Last buffer", + e = "Exchange next line", + f = "Next file in directory", + l = "Next location list entry", + L = "Last Location list entry", + n = "Next conflict marker/diff hunk", + p = "Paste line below", + P = "Paste line below", + q = "Next quickfix list entry", + Q = "Last quickfix list entry", + t = "Next matching tag", + T = "Last matching tag", + z = "Next fold", + -- Decoding + C = "C string decode", + u = "URL decode", + x = "XML decode", + y = "C string decode", + -- Custom + d = { lsp.goto_next_diagnostic, "Next diagnostic" }, + }, - -- Next - { "]", group = "Next" }, - -- Edition and navigation mappings - { "]", desc = "Insert blank line below" }, - { "]", desc = "Next location list file" }, - { "]", desc = "Next quickfix list file" }, - { "]", desc = "Next tag in preview window" }, - { "]a", desc = "Next argument" }, - { "]A", desc = "Last argument" }, - { "]b", desc = "Next buffer" }, - { "]B", desc = "Last buffer" }, - { "]e", desc = "Exchange next line" }, - { "]f", desc = "Next file in directory" }, - { "]l", desc = "Next location list entry" }, - { "]L", desc = "Last Location list entry" }, - { "]n", desc = "Next conflict marker/diff hunk" }, - { "]p", desc = "Paste line below" }, - { "]P", desc = "Paste line below" }, - { "]q", desc = "Next quickfix list entry" }, - { "]Q", desc = "Last quickfix list entry" }, - { "]t", desc = "Next matching tag" }, - { "]T", desc = "Last matching tag" }, - { "]z", desc = "Next fold" }, - -- Decoding - { "]C", desc = "C string decode" }, - { "]u", desc = "URL decode" }, - { "]x", desc = "XML decode" }, - { "]y", desc = "C string decode" }, - - -- Enable option - { "[o", group = "Enable option" }, - { "[ob", desc = "Light background" }, - { "[oc", desc = "Cursor line" }, - { "[od", desc = "Diff" }, - { "[of", "FormatEnable", desc = "LSP Formatting" }, - { "[oh", desc = "Search high-lighting" }, - { "[oi", desc = "Case insensitive search" }, - { "[ol", desc = "List mode" }, - { "[on", desc = "Line numbers" }, - { "[or", desc = "Relative line numbers" }, - { "[op", "lwindow", desc = "Location list" }, - { "[oq", "cwindow", desc = "Quickfix list" }, - { "[ou", desc = "Cursor column" }, - { "[ov", desc = "Virtual editing" }, - { "[ow", desc = "Text wrapping" }, - { "[ox", desc = "Cursor line and column" }, - { "[oz", desc = "Spell checking" }, - - -- Disable option - { "]o", group = "Disable option" }, - { "]ob", desc = "Light background" }, - { "]oc", desc = "Cursor line" }, - { "]od", desc = "Diff" }, - { "]of", "FormatDisable", desc = "LSP Formatting" }, - { "]oh", desc = "Search high-lighting" }, - { "]oi", desc = "Case insensitive search" }, - { "]ol", desc = "List mode" }, - { "]on", desc = "Line numbers" }, - { "]op", "lclose", desc = "Location list" }, - { "]oq", "cclose", desc = "Quickfix list" }, - { "]or", desc = "Relative line numbers" }, - { "]ou", desc = "Cursor column" }, - { "]ov", desc = "Virtual editing" }, - { "]ow", desc = "Text wrapping" }, - { "]ox", desc = "Cursor line and column" }, - { "]oz", desc = "Spell checking" }, - - -- Toggle option - { "yo", group = "Toggle option" }, - { "yob", desc = "Light background" }, - { "yoc", desc = "Cursor line" }, - { "yod", desc = "Diff" }, - { "yof", "FormatToggle", desc = "LSP Formatting" }, - { "yoh", desc = "Search high-lighting" }, - { "yoi", desc = "Case insensitive search" }, - { "yol", desc = "List mode" }, - { "yon", desc = "Line numbers" }, - { "yop", "(qf_loc_toggle)", desc = "Location list" }, - { "yoq", "(qf_qf_toggle)", desc = "Quickfix list" }, - { "yor", desc = "Relative line numbers" }, - { "you", desc = "Cursor column" }, - { "yov", desc = "Virtual editing" }, - { "yow", desc = "Text wrapping" }, - { "yox", desc = "Cursor line and column" }, - { "yoz", desc = "Spell checking" }, + -- Option mappings + ["[o"] = { + name = "Enable option", + b = "Light background", + c = "Cursor line", + d = "Diff", + f = { "FormatEnable", "LSP Formatting" }, + h = "Search high-lighting", + i = "Case insensitive search", + l = "List mode", + n = "Line numbers", + r = "Relative line numbers", + p = { "lwindow", "Location list" }, + q = { "cwindow", "Quickfix list" }, + u = "Cursor column", + v = "Virtual editing", + w = "Text wrapping", + x = "Cursor line and column", + z = "Spell checking", + }, + ["]o"] = { + name = "Option off", + b = "Light background", + c = "Cursor line", + d = "Diff", + f = { "FormatDisable", "LSP Formatting" }, + h = "Search high-lighting", + i = "Case insensitive search", + l = "List mode", + n = "Line numbers", + p = { "lclose", "Location list" }, + q = { "cclose", "Quickfix list" }, + r = "Relative line numbers", + u = "Cursor column", + v = "Virtual editing", + w = "Text wrapping", + x = "Cursor line and column", + z = "Spell checking", + }, + ["yo"] = { + name = "Option toggle", + b = "Light background", + c = "Cursor line", + d = "Diff", + f = { "FormatToggle", "LSP Formatting" }, + h = "Search high-lighting", + i = "Case insensitive search", + l = "List mode", + n = "Line numbers", + p = { "(qf_loc_toggle)", "Location list" }, + q = { "(qf_qf_toggle)", "Quickfix list" }, + r = "Relative line numbers", + u = "Cursor column", + v = "Virtual editing", + w = "Text wrapping", + x = "Cursor line and column", + z = "Spell checking", + }, } -wk.add(keys) +wk.register(keys) diff --git a/modules/home/vim/after/queries/diff/highlights.scm b/modules/home/vim/after/queries/diff/highlights.scm deleted file mode 100644 index c998725..0000000 --- a/modules/home/vim/after/queries/diff/highlights.scm +++ /dev/null @@ -1,5 +0,0 @@ -; extends - -; I want to the line added/removed markers to be the correct color -"+" @diff.plus -"-" @diff.minus diff --git a/modules/home/vim/after/queries/gitcommit/highlights.scm b/modules/home/vim/after/queries/gitcommit/highlights.scm deleted file mode 100644 index 05162c9..0000000 --- a/modules/home/vim/after/queries/gitcommit/highlights.scm +++ /dev/null @@ -1,6 +0,0 @@ -; extends - -; Highlight over-extended subject lines (rely on wrapping for message body) -((subject) @comment.error - (#vim-match? @comment.error ".\{50,}") - (#offset! @comment.error 0 50 0 0)) diff --git a/modules/home/vim/default.nix b/modules/home/vim/default.nix index 930a853..07711cc 100644 --- a/modules/home/vim/default.nix +++ b/modules/home/vim/default.nix @@ -40,18 +40,25 @@ in lualine-lsp-progress # Show progress for LSP servers # tpope essentials + vim-commentary # Easy comments vim-eunuch # UNIX integrations vim-fugitive # A 'git' wrapper vim-git # Sane git syntax files vim-repeat # Enanche '.' for plugins vim-rsi # Readline mappings vim-unimpaired # Some ex command mappings + vim-vinegar # Better netrw # Languages + rust-vim vim-beancount + vim-jsonnet + vim-nix + vim-toml # General enhancements vim-qf # Better quick-fix list + nvim-osc52 # Send clipboard data through terminal escape for SSH # Other wrappers git-messenger-vim # A simple blame window @@ -59,13 +66,16 @@ 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 + nvim-ts-context-commentstring # Comment string in nested language blocks plenary-nvim # 'null-ls', 'telescope' dependency # 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 @@ -78,8 +88,8 @@ in dressing-nvim # Integrate native UI hooks with Telescope etc... gitsigns-nvim # Fast git UI integration nvim-surround # Deal with pairs, now in Lua - oil-nvim # Better alternative to NetrW telescope-fzf-native-nvim # Use 'fzf' fuzzy matching algorithm + telescope-lsp-handlers-nvim # Use 'telescope' for various LSP actions telescope-nvim # Fuzzy finder interface which-key-nvim # Show available mappings ]; @@ -95,11 +105,8 @@ in nixpkgs-fmt # Shell - bash-language-server + nodePackages.bash-language-server shfmt - - # Generic - typos-lsp ]; }; diff --git a/modules/home/vim/ftdetect/glsl.lua b/modules/home/vim/ftdetect/glsl.lua new file mode 100644 index 0000000..2f4f1dd --- /dev/null +++ b/modules/home/vim/ftdetect/glsl.lua @@ -0,0 +1,7 @@ +-- Use GLSL filetype for common shader file extensions +vim.filetype.add({ + extension = { + frag = "glsl", + vert = "glsl", + }, +}) diff --git a/modules/home/vim/ftdetect/gn.lua b/modules/home/vim/ftdetect/gn.lua new file mode 100644 index 0000000..37d772e --- /dev/null +++ b/modules/home/vim/ftdetect/gn.lua @@ -0,0 +1,7 @@ +-- Use GN filetype for Chromium Generate Ninja files +vim.filetype.add({ + extension = { + gn = "gn", + gni = "gn", + }, +}) diff --git a/modules/home/vim/ftdetect/kbuild.lua b/modules/home/vim/ftdetect/kbuild.lua new file mode 100644 index 0000000..799570e --- /dev/null +++ b/modules/home/vim/ftdetect/kbuild.lua @@ -0,0 +1,6 @@ +-- Kbuild is just a Makefile under a different name +vim.filetype.add({ + filename = { + ["Kbuild"] = "make", + }, +}) diff --git a/modules/home/vim/ftdetect/tikz.lua b/modules/home/vim/ftdetect/tikz.lua new file mode 100644 index 0000000..93b7db0 --- /dev/null +++ b/modules/home/vim/ftdetect/tikz.lua @@ -0,0 +1,6 @@ +-- Use LaTeX filetype for TikZ files +vim.filetype.add({ + extension = { + tikz = "tex", + }, +}) diff --git a/modules/home/vim/init.vim b/modules/home/vim/init.vim index 1142925..bd63d25 100644 --- a/modules/home/vim/init.vim +++ b/modules/home/vim/init.vim @@ -1,4 +1,4 @@ -" Basic configuration {{{ +" Basic configuraion {{{ """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" " Use UTF-8 set encoding=utf-8 @@ -38,10 +38,10 @@ set tabstop=8 " File parameters {{{ """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" -" Disable swap files +" Disable backups, we have source control for that +set nobackup +" Disable swapfiles too set noswapfile -" Enable undo files -set undofile " }}} " UI and UX parameters {{{ @@ -68,6 +68,8 @@ 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 @@ -81,29 +83,11 @@ set updatetime=250 " Disable all mouse integrations set mouse= -" Setup some overrides for gruvbox -lua << EOF -local gruvbox = require("gruvbox") -local colors = gruvbox.palette +" Set dark mode by default +set background=dark -gruvbox.setup({ - overrides = { - -- Only URLs should be underlined - ["@string.special.path"] = { link = "GruvboxOrange" }, - -- Revert back to the better diff highlighting - DiffAdd = { fg = colors.green, bg = "NONE" }, - DiffChange = { fg = colors.aqua, bg = "NONE" }, - DiffDelete = { fg = colors.red, bg = "NONE" }, - DiffText = { fg = colors.yellow, bg = colors.bg0 }, - -- Directories "pop" better in blue - Directory = { link = "GruvboxBlueBold" }, - }, - italic = { - -- Comments should not be italic, for e.g: box drawing - comments = false, - }, -}) -EOF +" 24 bit colors +set termguicolors " Use my preferred colorscheme colorscheme gruvbox " }}} diff --git a/modules/home/vim/lua/ambroisie/lsp.lua b/modules/home/vim/lua/ambroisie/lsp.lua index fef0487..31a5bd1 100644 --- a/modules/home/vim/lua/ambroisie/lsp.lua +++ b/modules/home/vim/lua/ambroisie/lsp.lua @@ -3,9 +3,46 @@ 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 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 +--- @param bufnr int? buffer number of the attched client M.on_attach = function(client, bufnr) -- Format on save lsp_format.on_attach(client, bufnr) @@ -42,10 +79,6 @@ 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 @@ -53,36 +86,32 @@ M.on_attach = function(client, bufnr) vim.diagnostic.open_float(nil, { scope = "buffer" }) end - local function toggle_inlay_hints() - vim.lsp.inlay_hint.enable(not vim.lsp.inlay_hint.is_enabled()) - end - local keys = { - buffer = bufnr, - -- LSP navigation - { "K", vim.lsp.buf.hover, desc = "Show symbol information" }, - { "", vim.lsp.buf.signature_help, desc = "Show signature information" }, - { "gd", vim.lsp.buf.definition, desc = "Go to definition" }, - { "gD", vim.lsp.buf.declaration, desc = "Go to declaration" }, - { "gi", vim.lsp.buf.implementation, desc = "Go to implementation" }, - { "gr", vim.lsp.buf.references, desc = "List all references" }, - -- Code - { "c", group = "Code" }, - { "ca", vim.lsp.buf.code_action, desc = "Code actions" }, - { "cd", cycle_diagnostics_display, desc = "Cycle diagnostics display" }, - { "cD", show_buffer_diagnostics, desc = "Show buffer diagnostics" }, - { "ch", toggle_inlay_hints, desc = "Toggle inlay hints" }, - { "cr", vim.lsp.buf.rename, desc = "Rename symbol" }, - { "cs", vim.lsp.buf.signature_help, desc = "Show signature" }, - { "ct", vim.lsp.buf.type_definition, desc = "Go to type definition" }, - -- Workspace - { "cw", group = "Workspace" }, - { "cwa", vim.lsp.buf.add_workspace_folder, desc = "Add folder to workspace" }, - { "cwl", list_workspace_folders, desc = "List folders in workspace" }, - { "cwr", vim.lsp.buf.remove_workspace_folder, desc = "Remove folder from workspace" }, + K = { vim.lsp.buf.hover, "Show symbol information" }, + [""] = { vim.lsp.buf.signature_help, "Show signature information" }, + ["gd"] = { vim.lsp.buf.definition, "Go to definition" }, + ["gD"] = { vim.lsp.buf.declaration, "Go to declaration" }, + ["gi"] = { vim.lsp.buf.implementation, "Go to implementation" }, + ["gr"] = { vim.lsp.buf.references, "List all references" }, + + ["c"] = { + name = "Code", + a = { vim.lsp.buf.code_action, "Code actions" }, + d = { cycle_diagnostics_display, "Cycle diagnostics display" }, + D = { show_buffer_diagnostics, "Show buffer diagnostics" }, + r = { vim.lsp.buf.rename, "Rename symbol" }, + s = { vim.lsp.buf.signature_help, "Show signature" }, + t = { vim.lsp.buf.type_definition, "Go to type definition" }, + w = { + name = "Workspace", + a = { vim.lsp.buf.add_workspace_folder, "Add folder to workspace" }, + l = { list_workspace_folders, "List folders in workspace" }, + r = { vim.lsp.buf.remove_workspace_folder, "Remove folder from workspace" }, + }, + }, } - wk.add(keys) + wk.register(keys, { buffer = bufnr }) end return M diff --git a/modules/home/vim/lua/ambroisie/utils.lua b/modules/home/vim/lua/ambroisie/utils.lua index 0ee7c83..3d2dd3b 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_clients({ bufnr = bufnr }) + local clients = vim.lsp.get_active_clients({ bufnr = bufnr }) local names = {} for _, client in ipairs(clients) do @@ -48,22 +48,4 @@ M.list_lsp_clients = function(bufnr) return names end ---- partially apply a function with given arguments -M.partial = function(f, ...) - local a = { ... } - local a_len = select("#", ...) - - return function(...) - local tmp = { ... } - local tmp_len = select("#", ...) - - -- Merge arg lists - for i = 1, tmp_len do - a[a_len + i] = tmp[i] - end - - return f(unpack(a, 1, a_len + tmp_len)) - end -end - return M diff --git a/modules/home/vim/plugin/numbertoggle.lua b/modules/home/vim/plugin/numbertoggle.lua index b1e3df2..1f97fc8 100644 --- a/modules/home/vim/plugin/numbertoggle.lua +++ b/modules/home/vim/plugin/numbertoggle.lua @@ -7,18 +7,17 @@ local numbertoggle = vim.api.nvim_create_augroup("numbertoggle", { clear = true vim.api.nvim_create_autocmd({ "BufEnter", "FocusGained", "InsertLeave", "WinEnter" }, { pattern = "*", group = numbertoggle, - callback = function() - if vim.opt.number:get() then - vim.opt.relativenumber = true - end - end, + command = "if &nu | setlocal rnu | endif", }) vim.api.nvim_create_autocmd({ "BufLeave", "FocusLost", "InsertEnter", "WinLeave" }, { pattern = "*", group = numbertoggle, - callback = function() - if vim.opt.number:get() then - vim.opt.relativenumber = false - end - end, + command = "if &nu | setlocal nornu | endif", +}) + +-- Never show the sign column in a terminal buffer +vim.api.nvim_create_autocmd({ "TermOpen" }, { + pattern = "*", + group = numbertoggle, + command = "setlocal nonu nornu", }) diff --git a/modules/home/vim/plugin/settings/fastfold.lua b/modules/home/vim/plugin/settings/fastfold.lua new file mode 100644 index 0000000..78ee937 --- /dev/null +++ b/modules/home/vim/plugin/settings/fastfold.lua @@ -0,0 +1,5 @@ +-- 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/git.lua b/modules/home/vim/plugin/settings/git.lua index b9b92a6..4dbebca 100644 --- a/modules/home/vim/plugin/settings/git.lua +++ b/modules/home/vim/plugin/settings/git.lua @@ -1,75 +1,58 @@ local gitsigns = require("gitsigns") -local utils = require("ambroisie.utils") local wk = require("which-key") ---- Transform `f` into a function which acts on the current visual selection -local function make_visual(f) - return function() - local first = vim.fn.line("v") - local last = vim.fn.line(".") - f({ first, last }) - end -end - -local function nav_hunk(dir) - if vim.wo.diff then - local map = { - prev = "[c", - next = "]c", - } - vim.cmd.normal({ map[dir], bang = true }) - else - gitsigns.nav_hunk(dir) - end -end - gitsigns.setup({ current_line_blame_opts = { -- Show the blame quickly delay = 100, }, - -- Work-around for https://github.com/lewis6991/gitsigns.nvim/issues/929 - signs_staged_enable = false, }) local keys = { -- Navigation - { "[c", utils.partial(nav_hunk, "prev"), desc = "Previous hunk/diff" }, - { "]c", utils.partial(nav_hunk, "next"), desc = "Next hunk/diff" }, + ["[c"] = { "&diff ? '[c' : 'Gitsigns prev_hunk'", "Previous hunk/diff", expr = true }, + ["]c"] = { "&diff ? ']c' : 'Gitsigns next_hunk'", "Next hunk/diff", expr = true }, + -- Commands - { "g", group = "Git" }, - { "gb", gitsigns.toggle_current_line_blame, desc = "Toggle blame virtual text" }, - { "gd", gitsigns.diffthis, desc = "Diff buffer" }, - { "gD", utils.partial(gitsigns.diffthis, "~"), desc = "Diff buffer against last commit" }, - { "gg", "Git", desc = "Git status" }, - { "gh", gitsigns.toggle_deleted, desc = "Show deleted hunks" }, - { "gL", ":spT:Gllog --follow -- %:p", desc = "Current buffer log" }, - { "gm", "(git-messenger)", desc = "Current line blame" }, - { "gp", gitsigns.preview_hunk, desc = "Preview hunk" }, - { "gr", gitsigns.reset_hunk, desc = "Restore hunk" }, - { "gR", gitsigns.reset_buffer, desc = "Restore buffer" }, - { "gs", gitsigns.stage_hunk, desc = "Stage hunk" }, - { "gS", gitsigns.stage_buffer, desc = "Stage buffer" }, - { "gu", gitsigns.undo_stage_hunk, desc = "Undo stage hunk" }, - { "g[", utils.partial(gitsigns.nav_hunk, "prev"), desc = "Previous hunk" }, - { "g]", utils.partial(gitsigns.nav_hunk, "next"), desc = "Next hunk" }, + ["g"] = { + name = "Git", + -- Actions + b = { gitsigns.toggle_current_line_blame, "Toggle blame virtual text" }, + d = { gitsigns.diffthis, "Diff buffer" }, + -- stylua: ignore + D = { function() gitsigns.diffthis("~") end, "Diff buffer against last commit" }, + g = { "Git", "Git status" }, + h = { gitsigns.toggle_deleted, "Show deleted hunks" }, + L = { ":spT:Gllog --follow -- %:p", "Current buffer log" }, + m = { "(git-messenger)", "Current line blame" }, + p = { gitsigns.preview_hunk, "Preview hunk" }, + r = { gitsigns.reset_hunk, "Restore hunk" }, + R = { gitsigns.reset_buffer, "Restore buffer" }, + s = { gitsigns.stage_hunk, "Stage hunk" }, + S = { gitsigns.stage_buffer, "Stage buffer" }, + u = { gitsigns.undo_stage_hunk, "Undo stage hunk" }, + ["["] = { gitsigns.prev_hunk, "Previous hunk" }, + ["]"] = { gitsigns.next_hunk, "Next hunk" }, + }, } local objects = { - mode = "o", - { "ih", gitsigns.select_hunk, desc = "Git hunk" }, -} --- Visual -local visual = { - mode = { "x" }, - { "ih", gitsigns.select_hunk, desc = "Git hunk" }, - { "g", group = "Git" }, - { "gp", gitsigns.preview_hunk, desc = "Preview selection" }, - { "gr", make_visual(gitsigns.reset_hunk), desc = "Restore selection" }, - { "gs", make_visual(gitsigns.stage_hunk), desc = "Stage selection" }, - { "gu", gitsigns.undo_stage_hunk, desc = "Undo stage selection" }, + ["ih"] = { gitsigns.select_hunk, "Git hunk" }, } -wk.add(keys) -wk.add(objects) -wk.add(visual) +local visual = { + ["ih"] = { gitsigns.select_hunk, "Git hunk" }, + + -- Only the actual command can make use of the visual selection... + ["g"] = { + name = "Git", + p = { ":Gitsigns preview_hunk", "Preview selection" }, + r = { ":Gitsigns reset_hunk", "Restore selection" }, + s = { ":Gitsigns stage_hunk", "Stage selection" }, + u = { ":Gitsigns undo_stage_hunk", "Undo stage selection" }, + }, +} + +wk.register(keys, { buffer = bufnr }) +wk.register(objects, { buffer = bufnr, mode = "o" }) +wk.register(visual, { buffer = bufnr, mode = "x" }) diff --git a/modules/home/vim/plugin/settings/lsp-lines.lua b/modules/home/vim/plugin/settings/lsp-lines.lua new file mode 100644 index 0000000..9c79818 --- /dev/null +++ b/modules/home/vim/plugin/settings/lsp-lines.lua @@ -0,0 +1,3 @@ +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 1596e84..628eab9 100644 --- a/modules/home/vim/plugin/settings/lspconfig.lua +++ b/modules/home/vim/plugin/settings/lspconfig.lua @@ -1,3 +1,4 @@ +local lspconfig = require("lspconfig") local lsp = require("ambroisie.lsp") local utils = require("ambroisie.utils") @@ -15,57 +16,63 @@ 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... local capabilities = require("cmp_nvim_lsp").default_capabilities() --- Shared configuration -vim.lsp.config("*", { - capabilities = capabilities, - on_attach = lsp.on_attach, -}) - -local servers = { - -- C/C++ - clangd = {}, - -- Haskell - hls = {}, - -- Nix - nil_ls = {}, - -- Python - pyright = {}, - ruff = {}, - -- Rust - rust_analyzer = {}, - -- Shell - bashls = { - filetypes = { "bash", "sh", "zsh" }, - settings = { - bashIde = { - shfmt = { - -- Simplify the code - simplifyCode = true, - -- Indent switch cases - caseIndent = true, - }, - }, - }, - }, - -- Starlark - starpls = {}, - -- Generic - harper_ls = {}, - typos_lsp = {}, -} - -for server, config in pairs(servers) do - if not vim.tbl_isempty(config) then - vim.lsp.config(server, config) - end - vim.lsp.enable(server) +-- C/C++ +if utils.is_executable("clangd") then + lspconfig.clangd.setup({ + capabilities = capabilities, + on_attach = lsp.on_attach, + }) +end + +-- Haskell +if utils.is_executable("haskell-language-server-wrapper") then + lspconfig.hls.setup({ + capabilities = capabilities, + on_attach = lsp.on_attach, + }) +end + +-- Nix +if utils.is_executable("nil") then + lspconfig.nil_ls.setup({ + capabilities = capabilities, + on_attach = lsp.on_attach, + }) +end + +-- Python +if utils.is_executable("pyright") then + lspconfig.pyright.setup({ + capabilities = capabilities, + on_attach = lsp.on_attach, + }) +end + +if utils.is_executable("ruff-lsp") then + lspconfig.ruff_lsp.setup({ + capabilities = capabilities, + on_attach = lsp.on_attach, + }) +end + +-- Rust +if utils.is_executable("rust-analyzer") then + lspconfig.rust_analyzer.setup({ + capabilities = capabilities, + on_attach = lsp.on_attach, + }) +end + +-- Shell +if utils.is_executable("bash-language-server") then + lspconfig.bashls.setup({ + filetypes = { "bash", "sh", "zsh" }, + capabilities = capabilities, + on_attach = lsp.on_attach, + }) end diff --git a/modules/home/vim/plugin/settings/lualine.lua b/modules/home/vim/plugin/settings/lualine.lua index bbe4647..5219a95 100644 --- a/modules/home/vim/plugin/settings/lualine.lua +++ b/modules/home/vim/plugin/settings/lualine.lua @@ -1,5 +1,4 @@ local lualine = require("lualine") -local oil = require("oil") local utils = require("ambroisie.utils") local function list_spell_languages() @@ -31,7 +30,7 @@ lualine.setup({ { "mode" }, }, lualine_b = { - { "branch" }, + { "FugitiveHead" }, { "filename", symbols = { readonly = "🔒" } }, }, lualine_c = { @@ -58,21 +57,5 @@ 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 new file mode 100644 index 0000000..80309d7 --- /dev/null +++ b/modules/home/vim/plugin/settings/luasnip.lua @@ -0,0 +1 @@ +require("luasnip.loaders.from_vscode").lazy_load() diff --git a/modules/home/vim/plugin/settings/null-ls.lua b/modules/home/vim/plugin/settings/null-ls.lua index 258a209..e7265c7 100644 --- a/modules/home/vim/plugin/settings/null-ls.lua +++ b/modules/home/vim/plugin/settings/null-ls.lua @@ -18,6 +18,16 @@ null_ls.register({ }), }) +-- C, C++ +null_ls.register({ + null_ls.builtins.formatting.clang_format.with({ + -- Only used if available, but prefer clangd formatting if available + condition = function() + return utils.is_executable("clang-format") and not utils.is_executable("clangd") + end, + }), +}) + -- Nix null_ls.register({ null_ls.builtins.formatting.nixpkgs_fmt.with({ @@ -46,3 +56,29 @@ null_ls.register({ condition = utils.is_executable_condition("isort"), }), }) + +-- Shell (non-POSIX) +null_ls.register({ + null_ls.builtins.formatting.shfmt.with({ + -- Indent with 4 spaces, simplify the code, indent switch cases, + -- add space after redirection, use bash dialect + extra_args = { "-i", "4", "-s", "-ci", "-sr", "-ln", "bash" }, + -- Restrict to bash and zsh + filetypes = { "bash", "zsh" }, + -- Only used if available + condition = utils.is_executable_condition("shfmt"), + }), +}) + +-- Shell (POSIX) +null_ls.register({ + null_ls.builtins.formatting.shfmt.with({ + -- Indent with 4 spaces, simplify the code, indent switch cases, + -- add space after redirection, use POSIX + extra_args = { "-i", "4", "-s", "-ci", "-sr", "-ln", "posix" }, + -- Restrict to POSIX sh + filetypes = { "sh" }, + -- Only used if available + condition = utils.is_executable_condition("shfmt"), + }), +}) diff --git a/modules/home/vim/plugin/settings/oil.lua b/modules/home/vim/plugin/settings/oil.lua deleted file mode 100644 index 74d5007..0000000 --- a/modules/home/vim/plugin/settings/oil.lua +++ /dev/null @@ -1,36 +0,0 @@ -local oil = require("oil") -local wk = require("which-key") - -local detail = false - -oil.setup({ - -- Don't show icons - columns = {}, - view_options = { - -- Show files and directories that start with "." by default - show_hidden = true, - -- But never '..' - is_always_hidden = function(name, bufnr) - return name == ".." - end, - }, - keymaps = { - ["gd"] = { - desc = "Toggle file detail view", - callback = function() - detail = not detail - if detail then - oil.set_columns({ "icon", "permissions", "size", "mtime" }) - else - oil.set_columns({ "icon" }) - end - end, - }, - }, -}) - -local keys = { - { "-", oil.open, desc = "Open parent directory" }, -} - -wk.add(keys) diff --git a/modules/home/vim/plugin/settings/ssh.lua b/modules/home/vim/plugin/settings/ssh.lua new file mode 100644 index 0000000..992a707 --- /dev/null +++ b/modules/home/vim/plugin/settings/ssh.lua @@ -0,0 +1,17 @@ +if not require("ambroisie.utils").is_ssh() then + return +end + +local function copy(lines, _) + require("osc52").copy(table.concat(lines, "\n")) +end + +local function paste() + return { vim.fn.split(vim.fn.getreg(""), "\n"), vim.fn.getregtype("") } +end + +vim.g.clipboard = { + name = "osc52", + copy = { ["+"] = copy, ["*"] = copy }, + paste = { ["+"] = paste, ["*"] = paste }, +} diff --git a/modules/home/vim/plugin/settings/telescope.lua b/modules/home/vim/plugin/settings/telescope.lua index 810d51c..4548ec5 100644 --- a/modules/home/vim/plugin/settings/telescope.lua +++ b/modules/home/vim/plugin/settings/telescope.lua @@ -1,6 +1,4 @@ local telescope = require("telescope") -local telescope_builtin = require("telescope.builtin") -local wk = require("which-key") telescope.setup({ defaults = { @@ -23,14 +21,4 @@ telescope.setup({ }) telescope.load_extension("fzf") - -local keys = { - { "f", group = "Fuzzy finder" }, - { "fb", telescope_builtin.buffers, desc = "Open buffers" }, - { "ff", telescope_builtin.git_files, desc = "Git tracked files" }, - { "fF", telescope_builtin.find_files, desc = "Files" }, - { "fg", telescope_builtin.live_grep, desc = "Grep string" }, - { "fG", telescope_builtin.grep_string, desc = "Grep string under cursor" }, -} - -wk.add(keys) +telescope.load_extension("lsp_handlers") diff --git a/modules/home/vim/plugin/settings/tree-sitter.lua b/modules/home/vim/plugin/settings/tree-sitter.lua index d5fff46..5503857 100644 --- a/modules/home/vim/plugin/settings/tree-sitter.lua +++ b/modules/home/vim/plugin/settings/tree-sitter.lua @@ -1,5 +1,4 @@ local ts_config = require("nvim-treesitter.configs") - ts_config.setup({ highlight = { enable = true, @@ -15,16 +14,16 @@ ts_config.setup({ -- Jump to matching text objects lookahead = true, keymaps = { - ["aa"] = { query = "@parameter.outer", desc = "a parameter" }, - ["ia"] = { query = "@parameter.inner", desc = "inner parameter" }, - ["ab"] = { query = "@block.outer", desc = "a block" }, - ["ib"] = { query = "@block.inner", desc = "inner block" }, - ["ac"] = { query = "@class.outer", desc = "a class" }, - ["ic"] = { query = "@class.inner", desc = "inner class" }, - ["af"] = { query = "@function.outer", desc = "a function" }, - ["if"] = { query = "@function.inner", desc = "inner function" }, - ["ak"] = { query = "@comment.outer", desc = "a comment" }, - ["aS"] = { query = "@statement.outer", desc = "a statement" }, + ["aa"] = "@parameter.outer", + ["ia"] = "@parameter.inner", + ["ab"] = "@block.outer", + ["ib"] = "@block.inner", + ["ac"] = "@class.outer", + ["ic"] = "@class.inner", + ["af"] = "@function.outer", + ["if"] = "@function.inner", + ["ak"] = "@comment.outer", + ["aS"] = "@statement.outer", }, }, move = { @@ -32,22 +31,22 @@ ts_config.setup({ -- Add to jump list set_jumps = true, goto_next_start = { - ["]m"] = { query = "@function.outer", desc = "Next method start" }, - ["]S"] = { query = "@statement.outer", desc = "Next statement start" }, - ["]]"] = { query = "@class.outer", desc = "Next class start" }, + ["]m"] = "@function.outer", + ["]S"] = "@statement.outer", + ["]]"] = "@class.outer", }, goto_next_end = { - ["]M"] = { query = "@function.outer", desc = "Next method end" }, - ["]["] = { query = "@class.outer", desc = "Next class end" }, + ["]M"] = "@function.outer", + ["]["] = "@class.outer", }, goto_previous_start = { - ["[m"] = { query = "@function.outer", desc = "Previous method start" }, - ["[S"] = { query = "@statement.outer", desc = "Previous statement start" }, - ["[["] = { query = "@class.outer", desc = "Previous class start" }, + ["[m"] = "@function.outer", + ["[S"] = "@statement.outer", + ["[["] = "@class.outer", }, goto_previous_end = { - ["[M"] = { query = "@function.outer", desc = "Previous method end" }, - ["[]"] = { query = "@class.outer", desc = "Previous class end" }, + ["[M"] = "@function.outer", + ["[]"] = "@class.outer", }, }, }, diff --git a/modules/home/vim/plugin/settings/which-key.lua b/modules/home/vim/plugin/settings/which-key.lua index 3dc260a..2edfd70 100644 --- a/modules/home/vim/plugin/settings/which-key.lua +++ b/modules/home/vim/plugin/settings/which-key.lua @@ -1,33 +1,2 @@ local wk = require("which-key") -wk.setup({ - icons = { - -- I don't like icons - mappings = false, - breadcrumb = "»", - separator = "➜", - group = "+", - ellipsis = "…", - keys = { - Up = " ", - Down = " ", - Left = " ", - Right = " ", - C = "", - M = "", - D = "", - S = "", - CR = "", - Esc = " ", - NL = "", - BS = "", - Space = "", - Tab = " ", - }, - }, -}) - -local keys = { - { "", vim.cmd.nohlsearch, desc = "Clear search highlight" }, -} - -wk.add(keys) +wk.setup() diff --git a/modules/home/vim/plugin/signtoggle.lua b/modules/home/vim/plugin/signtoggle.lua index 3deca34..d6a26e2 100644 --- a/modules/home/vim/plugin/signtoggle.lua +++ b/modules/home/vim/plugin/signtoggle.lua @@ -1,21 +1,20 @@ local signtoggle = vim.api.nvim_create_augroup("signtoggle", { clear = true }) --- Only show sign column for the currently focused buffer, if it has a number column +-- Only show sign column for the currently focused buffer vim.api.nvim_create_autocmd({ "BufEnter", "FocusGained", "WinEnter" }, { pattern = "*", group = signtoggle, - callback = function() - if vim.opt.number:get() then - vim.opt.signcolumn = "yes" - end - end, + command = "setlocal signcolumn=yes", }) vim.api.nvim_create_autocmd({ "BufLeave", "FocusLost", "WinLeave" }, { pattern = "*", group = signtoggle, - callback = function() - if vim.opt.number:get() then - vim.opt.signcolumn = "no" - end - end, + command = "setlocal signcolumn=yes", +}) + +-- Never show the sign column in a terminal buffer +vim.api.nvim_create_autocmd({ "TermOpen" }, { + pattern = "*", + group = signtoggle, + command = "setlocal signcolumn=no", }) diff --git a/modules/home/wget/default.nix b/modules/home/wget/default.nix index 1be5397..32c13c0 100644 --- a/modules/home/wget/default.nix +++ b/modules/home/wget/default.nix @@ -20,7 +20,7 @@ in }; xdg.configFile."wgetrc".text = '' - hsts-file = ${config.xdg.stateHome}/wget-hsts + hsts-file = ${config.xdg.dataHome}/wget-hsts ''; }; } diff --git a/modules/home/wm/default.nix b/modules/home/wm/default.nix index ae1e136..449918a 100644 --- a/modules/home/wm/default.nix +++ b/modules/home/wm/default.nix @@ -58,7 +58,7 @@ in service = "some-service-name"; } ]; - description = "list of block configurations, merged with the defaults"; + description = "list of block configurations, merged with the defauls"; }; }; }; diff --git a/modules/home/wm/i3/default.nix b/modules/home/wm/i3/default.nix index 5f22bbe..69246f0 100644 --- a/modules/home/wm/i3/default.nix +++ b/modules/home/wm/i3/default.nix @@ -127,11 +127,9 @@ in { class = "^Blueman-.*$"; } { title = "^htop$"; } { class = "^Thunderbird$"; instance = "Mailnews"; window_role = "filterlist"; } - { class = "^firefox$"; instance = "Places"; window_role = "Organizer"; } - { class = "^pavucontrol.*$"; } + { class = "^Pavucontrol.*$"; } { class = "^Arandr$"; } - { class = "^\\.blueman-manager-wrapped$"; } - { class = "^\\.arandr-wrapped$"; } + { class = ".?blueman-manager.*$"; } ]; }; @@ -373,7 +371,8 @@ in }; startup = [ - # NOTE: rely on systemd user services instead... + # FIXME + # { commdand; always; notification; } ]; window = { diff --git a/modules/home/wm/screen-lock/default.nix b/modules/home/wm/screen-lock/default.nix index 5e6874e..3b2ead6 100644 --- a/modules/home/wm/screen-lock/default.nix +++ b/modules/home/wm/screen-lock/default.nix @@ -2,7 +2,7 @@ let cfg = config.my.home.wm.screen-lock; - notificationCmd = + notficationCmd = let duration = toString (cfg.notify.delay * 1000); notifyCmd = "${lib.getExe pkgs.libnotify} -u critical -t ${duration}"; @@ -48,7 +48,7 @@ in "-notify" "${toString cfg.notify.delay}" "-notifier" - notificationCmd + notficationCmd ]; }; }; diff --git a/modules/home/xdg/default.nix b/modules/home/xdg/default.nix index 7a0c517..fb2668c 100644 --- a/modules/home/xdg/default.nix +++ b/modules/home/xdg/default.nix @@ -11,7 +11,7 @@ in enable = true; # File types mime.enable = true; - # File associations + # File associatons mimeApps = { enable = true; }; @@ -30,11 +30,9 @@ in }; # A tidy home is a tidy mind dataFile = { - "tig/.keep".text = ""; # `tig` uses `XDG_DATA_HOME` specifically... - }; - stateFile = { "bash/.keep".text = ""; - "python/.keep".text = ""; + "gdb/.keep".text = ""; + "tig/.keep".text = ""; }; }; @@ -45,18 +43,15 @@ in CARGO_HOME = "${dataHome}/cargo"; DOCKER_CONFIG = "${configHome}/docker"; GRADLE_USER_HOME = "${dataHome}/gradle"; - HISTFILE = "${stateHome}/bash/history"; + HISTFILE = "${dataHome}/bash/history"; INPUTRC = "${configHome}/readline/inputrc"; - PSQL_HISTORY = "${stateHome}/psql_history"; + PSQL_HISTORY = "${dataHome}/psql_history"; PYTHONPYCACHEPREFIX = "${cacheHome}/python/"; PYTHONUSERBASE = "${dataHome}/python/"; PYTHON_HISTORY = "${stateHome}/python/history"; - REDISCLI_HISTFILE = "${stateHome}/redis/rediscli_history"; + REDISCLI_HISTFILE = "${dataHome}/redis/rediscli_history"; REPO_CONFIG_DIR = "${configHome}/repo"; XCOMPOSECACHE = "${dataHome}/X11/xcompose"; _JAVA_OPTIONS = "-Djava.util.prefs.userRoot=${configHome}/java"; }; - - # Some modules *optionally* use `XDG_*_HOME` when told to - config.home.preferXdgDirectories = lib.mkIf cfg.enable true; } diff --git a/modules/home/zsh/default.nix b/modules/home/zsh/default.nix index 9524262..a277366 100644 --- a/modules/home/zsh/default.nix +++ b/modules/home/zsh/default.nix @@ -1,6 +1,14 @@ { config, pkgs, lib, ... }: let cfg = config.my.home.zsh; + + # Have a nice relative path for XDG_CONFIG_HOME, without leading `/` + relativeXdgConfig = + let + noHome = lib.removePrefix config.home.homeDirectory; + noSlash = lib.removePrefix "/"; + in + noSlash (noHome config.xdg.configHome); in { options.my.home.zsh = with lib; { @@ -8,22 +16,16 @@ in launchTmux = mkEnableOption "auto launch tmux at shell start"; - completionSync = { - enable = mkEnableOption "zsh-completion-sync plugin"; - }; - notify = { enable = mkEnableOption "zsh-done notification"; exclude = mkOption { type = with types; listOf str; default = [ - "bat" "delta" "direnv reload" "fg" "git (?!push|pull|fetch)" - "home-manager (?!switch|build)" "htop" "less" "man" @@ -55,7 +57,7 @@ in programs.zsh = { enable = true; - dotDir = "${config.xdg.configHome}/zsh"; # Don't clutter $HOME + dotDir = "${relativeXdgConfig}/zsh"; # Don't clutter $HOME enableCompletion = true; history = { @@ -66,13 +68,13 @@ in ignoreSpace = true; ignoreDups = true; share = false; - path = "${config.xdg.stateHome}/zsh/zsh_history"; + path = "${config.xdg.dataHome}/zsh/zsh_history"; }; plugins = [ { name = "fast-syntax-highlighting"; - file = "share/zsh/plugins/fast-syntax-highlighting/fast-syntax-highlighting.plugin.zsh"; + file = "share/zsh/site-functions/fast-syntax-highlighting.plugin.zsh"; src = pkgs.zsh-fast-syntax-highlighting; } { @@ -85,26 +87,28 @@ in # Modal editing is life, but CLI benefits from emacs gymnastics defaultKeymap = "emacs"; - 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 - '')) + # 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 + '' + } + ''; - (lib.mkAfter '' - source ${./completion-styles.zsh} - source ${./extra-mappings.zsh} - source ${./options.zsh} + initExtra = 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 @@ -122,18 +126,6 @@ in }; } - (lib.mkIf cfg.completionSync.enable { - programs.zsh = { - plugins = [ - { - name = "zsh-completion-sync"; - file = "share/zsh-completion-sync/zsh-completion-sync.plugin.zsh"; - src = pkgs.zsh-completion-sync; - } - ]; - }; - }) - (lib.mkIf cfg.notify.enable { programs.zsh = { plugins = [ @@ -159,7 +151,7 @@ in }; # Use OSC-777 to send the notification through SSH - initContent = lib.mkIf cfg.notify.ssh.useOsc777 '' + initExtra = lib.mkIf cfg.notify.ssh.useOsc777 '' done_send_notification() { local exit_status="$1" local title="$2" diff --git a/modules/home/zsh/options.zsh b/modules/home/zsh/options.zsh index 7bcad03..32da8d8 100644 --- a/modules/home/zsh/options.zsh +++ b/modules/home/zsh/options.zsh @@ -12,7 +12,7 @@ setopt rc_quotes setopt auto_resume # Show history expansion before running a command setopt hist_verify -# Append commands to history as they are executed +# Append commands to history as they are exectuted setopt inc_append_history_time # Remove useless whitespace from commands setopt hist_reduce_blanks diff --git a/modules/nixos/hardware/bluetooth/default.nix b/modules/nixos/hardware/bluetooth/default.nix index b14ac21..c019b31 100644 --- a/modules/nixos/hardware/bluetooth/default.nix +++ b/modules/nixos/hardware/bluetooth/default.nix @@ -20,10 +20,28 @@ in # Support for additional bluetooth codecs (lib.mkIf cfg.loadExtraCodecs { - services.pulseaudio = { + hardware.pulseaudio = { extraModules = [ pkgs.pulseaudio-modules-bt ]; package = pkgs.pulseaudioFull; }; + + services.pipewire.wireplumber.configPackages = [ + (pkgs.writeTextDir "share/wireplumber/bluetooth.lua.d/51-bluez-config.lua" '' + bluez_monitor.properties = { + -- SBC XQ provides better audio + ["bluez5.enable-sbc-xq"] = true, + + -- mSBC provides better audio + microphone + ["bluez5.enable-msbc"] = true, + + -- Synchronize volume with bluetooth device + ["bluez5.enable-hw-volume"] = true, + + -- FIXME: Some devices may now support both hsp_ag and hfp_ag + ["bluez5.headset-roles"] = "[ hsp_hs hsp_ag hfp_hf hfp_ag ]" + } + '') + ]; }) # Support for A2DP audio profile diff --git a/modules/nixos/hardware/graphics/default.nix b/modules/nixos/hardware/graphics/default.nix index 7d8b359..3baac02 100644 --- a/modules/nixos/hardware/graphics/default.nix +++ b/modules/nixos/hardware/graphics/default.nix @@ -26,30 +26,28 @@ in config = lib.mkIf cfg.enable (lib.mkMerge [ { - hardware.graphics = { + hardware.opengl = { enable = true; }; } # AMD GPU (lib.mkIf (cfg.gpuFlavor == "amd") { - hardware.amdgpu = { - initrd.enable = cfg.amd.enableKernelModule; - # Vulkan - amdvlk = lib.mkIf cfg.amd.amdvlk { - enable = true; - support32Bit = { - enable = true; - }; - }; - }; + boot.initrd.kernelModules = lib.mkIf cfg.amd.enableKernelModule [ "amdgpu" ]; - hardware.graphics = { + hardware.opengl = { extraPackages = with pkgs; [ # OpenCL rocmPackages.clr rocmPackages.clr.icd - ]; + ] + ++ lib.optional cfg.amd.amdvlk amdvlk + ; + + extraPackages32 = with pkgs; [ + ] + ++ lib.optional cfg.amd.amdvlk driversi686Linux.amdvlk + ; }; }) @@ -61,7 +59,7 @@ in VDPAU_DRIVER = "va_gl"; }; - hardware.graphics = { + hardware.opengl = { extraPackages = with pkgs; [ # Open CL intel-compute-runtime @@ -71,13 +69,6 @@ in intel-vaapi-driver libvdpau-va-gl ]; - - extraPackages32 = with pkgs.driversi686Linux; [ - # VA API - intel-media-driver - intel-vaapi-driver - libvdpau-va-gl - ]; }; }) ]); diff --git a/modules/nixos/hardware/sound/default.nix b/modules/nixos/hardware/sound/default.nix index cd453de..e8ba7f7 100644 --- a/modules/nixos/hardware/sound/default.nix +++ b/modules/nixos/hardware/sound/default.nix @@ -54,7 +54,10 @@ in # Pulseaudio setup (lib.mkIf cfg.pulse.enable { - services.pulseaudio.enable = true; + # ALSA + sound.enable = true; + + hardware.pulseaudio.enable = true; }) ]); } diff --git a/modules/nixos/hardware/trackball/default.nix b/modules/nixos/hardware/trackball/default.nix index a9b24e3..7a99247 100644 --- a/modules/nixos/hardware/trackball/default.nix +++ b/modules/nixos/hardware/trackball/default.nix @@ -11,7 +11,7 @@ in config = lib.mkIf cfg.enable { services.xserver = { # This section must be *after* the one configured by `libinput` - # for the `ScrollMethod` configuration to not be overridden + # for the `ScrollMethod` configuration to not be overriden inputClassSections = lib.mkAfter [ # MX Ergo '' diff --git a/modules/nixos/profiles/default.nix b/modules/nixos/profiles/default.nix index dbd4be3..43d5a84 100644 --- a/modules/nixos/profiles/default.nix +++ b/modules/nixos/profiles/default.nix @@ -1,4 +1,4 @@ -# Configuration that spans across system and home, or are almagations of modules +# Configuration that spans accross system and home, or are almagations of modules { ... }: { imports = [ diff --git a/modules/nixos/profiles/laptop/default.nix b/modules/nixos/profiles/laptop/default.nix index 68c65b8..20a29d7 100644 --- a/modules/nixos/profiles/laptop/default.nix +++ b/modules/nixos/profiles/laptop/default.nix @@ -9,7 +9,7 @@ in config = lib.mkIf cfg.enable { # Enable touchpad support - services.libinput.enable = true; + services.xserver.libinput.enable = true; # Enable TLP power management my.services.tlp.enable = true; diff --git a/modules/nixos/profiles/wm/default.nix b/modules/nixos/profiles/wm/default.nix index bca4d70..c227328 100644 --- a/modules/nixos/profiles/wm/default.nix +++ b/modules/nixos/profiles/wm/default.nix @@ -24,8 +24,6 @@ in my.home.udiskie.enable = true; # udiskie fails if it can't find this dbus service services.udisks2.enable = true; - # Ensure i3lock can actually unlock the session - security.pam.services.i3lock.enable = true; }) ]; } diff --git a/modules/nixos/profiles/x/default.nix b/modules/nixos/profiles/x/default.nix index 874f36f..ea77939 100644 --- a/modules/nixos/profiles/x/default.nix +++ b/modules/nixos/profiles/x/default.nix @@ -13,7 +13,7 @@ in # Nice wallpaper services.xserver.displayManager.lightdm.background = let - wallpapers = "${pkgs.kdePackages.plasma-workspace-wallpapers}/share/wallpapers"; + wallpapers = "${pkgs.plasma5Packages.plasma-workspace-wallpapers}/share/wallpapers"; in "${wallpapers}/summer_1am/contents/images/2560x1600.jpg"; diff --git a/modules/nixos/services/aria/default.nix b/modules/nixos/services/aria/default.nix index acbf0b7..2d1b3e2 100644 --- a/modules/nixos/services/aria/default.nix +++ b/modules/nixos/services/aria/default.nix @@ -65,7 +65,9 @@ in aria-rpc = { port = cfg.rpcPort; # Proxy websockets for RPC - websocketsLocations = [ "/" ]; + extraConfig = { + locations."/".proxyWebsockets = true; + }; }; }; diff --git a/modules/nixos/services/audiobookshelf/default.nix b/modules/nixos/services/audiobookshelf/default.nix deleted file mode 100644 index 04ec8b9..0000000 --- a/modules/nixos/services/audiobookshelf/default.nix +++ /dev/null @@ -1,53 +0,0 @@ -# Audiobook and podcast library -{ config, lib, ... }: -let - cfg = config.my.services.audiobookshelf; -in -{ - options.my.services.audiobookshelf = with lib; { - enable = mkEnableOption "Audiobookshelf, a self-hosted podcast manager"; - - port = mkOption { - type = types.port; - default = 8000; - example = 4242; - description = "The port on which Audiobookshelf will listen for incoming HTTP traffic."; - }; - }; - - config = lib.mkIf cfg.enable { - services.audiobookshelf = { - enable = true; - inherit (cfg) port; - - group = "media"; - }; - - # Set-up media group - users.groups.media = { }; - - my.services.nginx.virtualHosts = { - audiobookshelf = { - inherit (cfg) port; - # Proxy websockets for RPC - websocketsLocations = [ "/" ]; - }; - }; - - services.fail2ban.jails = { - audiobookshelf = '' - enabled = true - filter = audiobookshelf - port = http,https - ''; - }; - - environment.etc = { - "fail2ban/filter.d/audiobookshelf.conf".text = '' - [Definition] - failregex = ^.*ERROR: \[Auth\] Failed login attempt for username ".*" from ip - journalmatch = _SYSTEMD_UNIT=audiobookshelf.service - ''; - }; - }; -} diff --git a/modules/nixos/services/default.nix b/modules/nixos/services/default.nix index e03eca1..3b32d06 100644 --- a/modules/nixos/services/default.nix +++ b/modules/nixos/services/default.nix @@ -4,7 +4,6 @@ imports = [ ./adblock ./aria - ./audiobookshelf ./backup ./blog ./calibre-web @@ -14,9 +13,8 @@ ./forgejo ./gitea ./grocy - ./homebox + ./indexers ./jellyfin - ./komga ./lohr ./matrix ./mealie @@ -27,7 +25,7 @@ ./nginx ./nix-cache ./paperless - ./pdf-edit + ./pirate ./podgrab ./postgresql ./postgresql-backup @@ -35,10 +33,8 @@ ./quassel ./rss-bridge ./sabnzbd - ./servarr ./ssh-server ./tandoor-recipes - ./thelounge ./tlp ./transmission ./vikunja diff --git a/modules/nixos/services/drone/server/default.nix b/modules/nixos/services/drone/server/default.nix index d6148f4..a3a1e49 100644 --- a/modules/nixos/services/drone/server/default.nix +++ b/modules/nixos/services/drone/server/default.nix @@ -6,8 +6,8 @@ in config = lib.mkIf cfg.enable { systemd.services.drone-server = { wantedBy = [ "multi-user.target" ]; - after = [ "postgresql.target" ]; - requires = [ "postgresql.target" ]; + after = [ "postgresql.service" ]; + requires = [ "postgresql.service" ]; serviceConfig = { EnvironmentFile = [ cfg.secretFile diff --git a/modules/nixos/services/flood/default.nix b/modules/nixos/services/flood/default.nix index f3fe90b..155e73d 100644 --- a/modules/nixos/services/flood/default.nix +++ b/modules/nixos/services/flood/default.nix @@ -1,5 +1,5 @@ # A nice UI for various torrent clients -{ config, lib, ... }: +{ config, lib, pkgs, ... }: let cfg = config.my.services.flood; in @@ -13,13 +13,31 @@ in example = 3000; description = "Internal port for Flood UI"; }; + + stateDir = mkOption { + type = types.str; + default = "flood"; + example = "floodUI"; + description = "Directory under `/var/run` for storing Flood's files"; + }; }; config = lib.mkIf cfg.enable { - services.flood = { - enable = true; + systemd.services.flood = { + description = "Flood torrent UI"; + after = [ "network.target" ]; + wantedBy = [ "multi-user.target" ]; - inherit (cfg) port; + serviceConfig = { + ExecStart = lib.concatStringsSep " " [ + (lib.getExe pkgs.flood) + "--port ${builtins.toString cfg.port}" + "--rundir /var/lib/${cfg.stateDir}" + ]; + DynamicUser = true; + StateDirectory = cfg.stateDir; + ReadWritePaths = ""; + }; }; my.services.nginx.virtualHosts = { @@ -27,7 +45,5 @@ in inherit (cfg) port; }; }; - - # NOTE: unfortunately flood does not log connection failures for fail2ban }; } diff --git a/modules/nixos/services/forgejo/default.nix b/modules/nixos/services/forgejo/default.nix index 511724b..0f3dfc5 100644 --- a/modules/nixos/services/forgejo/default.nix +++ b/modules/nixos/services/forgejo/default.nix @@ -1,4 +1,4 @@ -# A low-resource, full-featured git forge. +# A low-ressource, full-featured git forge. { config, lib, ... }: let cfg = config.my.services.forgejo; @@ -83,11 +83,7 @@ in # I configure my backup system manually below. dump.enable = false; - secrets = { - mailer = lib.mkIf cfg.mail.enable { - PASSWD = cfg.mail.passwordFile; - }; - }; + mailerPasswordFile = lib.mkIf cfg.mail.enable cfg.mail.passwordFile; settings = { DEFAULT = { diff --git a/modules/nixos/services/gitea/default.nix b/modules/nixos/services/gitea/default.nix index 95bdf42..212f59c 100644 --- a/modules/nixos/services/gitea/default.nix +++ b/modules/nixos/services/gitea/default.nix @@ -1,4 +1,4 @@ -# A low-resource, full-featured git forge. +# A low-ressource, full-featured git forge. { config, lib, ... }: let cfg = config.my.services.gitea; diff --git a/modules/nixos/services/grocy/default.nix b/modules/nixos/services/grocy/default.nix index 9045b03..87927d6 100644 --- a/modules/nixos/services/grocy/default.nix +++ b/modules/nixos/services/grocy/default.nix @@ -36,7 +36,5 @@ in forceSSL = true; useACMEHost = config.networking.domain; }; - - # NOTE: unfortunately grocy does not log connection failures for fail2ban }; } diff --git a/modules/nixos/services/homebox/default.nix b/modules/nixos/services/homebox/default.nix deleted file mode 100644 index 524a6d7..0000000 --- a/modules/nixos/services/homebox/default.nix +++ /dev/null @@ -1,48 +0,0 @@ -# Home inventory made easy -{ config, lib, ... }: -let - cfg = config.my.services.homebox; -in -{ - options.my.services.homebox = with lib; { - enable = mkEnableOption "Homebox home inventory"; - - port = mkOption { - type = types.port; - default = 7745; - example = 8080; - description = "Internal port for webui"; - }; - }; - - config = lib.mkIf cfg.enable { - services.homebox = { - enable = true; - - # Automatic PostgreSQL provisioning - database = { - createLocally = true; - }; - - settings = { - # FIXME: mailer? - HBOX_WEB_PORT = toString cfg.port; - }; - }; - - my.services.nginx.virtualHosts = { - homebox = { - inherit (cfg) port; - websocketsLocations = [ "/api" ]; - }; - }; - - my.services.backup = { - paths = [ - (lib.removePrefix "file://" config.services.homebox.settings.HBOX_STORAGE_CONN_STRING) - ]; - }; - - # NOTE: unfortunately homebox does not log connection failures for fail2ban - }; -} diff --git a/modules/nixos/services/indexers/default.nix b/modules/nixos/services/indexers/default.nix new file mode 100644 index 0000000..8a42345 --- /dev/null +++ b/modules/nixos/services/indexers/default.nix @@ -0,0 +1,78 @@ +# 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/jellyfin/default.nix b/modules/nixos/services/jellyfin/default.nix index 6edeb67..f5aaa99 100644 --- a/modules/nixos/services/jellyfin/default.nix +++ b/modules/nixos/services/jellyfin/default.nix @@ -27,31 +27,19 @@ in my.services.nginx.virtualHosts = { jellyfin = { port = 8096; - websocketsLocations = [ "/socket" ]; extraConfig = { locations."/" = { extraConfig = '' proxy_buffering off; ''; }; + # Too bad for the repetition... + locations."/socket" = { + proxyPass = "http://127.0.0.1:8096/"; + proxyWebsockets = true; + }; }; }; }; - - services.fail2ban.jails = { - jellyfin = '' - enabled = true - filter = jellyfin - port = http,https - ''; - }; - - environment.etc = { - "fail2ban/filter.d/jellyfin.conf".text = '' - [Definition] - failregex = ^.*Authentication request for .* has been denied \(IP: "?"?\)\. - journalmatch = _SYSTEMD_UNIT=jellyfin.service - ''; - }; }; } diff --git a/modules/nixos/services/komga/default.nix b/modules/nixos/services/komga/default.nix deleted file mode 100644 index 9af3cd1..0000000 --- a/modules/nixos/services/komga/default.nix +++ /dev/null @@ -1,55 +0,0 @@ -# A Comics/Manga media server -{ config, lib, ... }: -let - cfg = config.my.services.komga; -in -{ - options.my.services.komga = with lib; { - enable = mkEnableOption "Komga comics server"; - - port = mkOption { - type = types.port; - default = 4584; - example = 8080; - description = "Internal port for webui"; - }; - }; - - config = lib.mkIf cfg.enable { - services.komga = { - enable = true; - - group = "media"; - - settings = { - server.port = cfg.port; - logging.level.org.gotson.komga = "DEBUG"; # Needed for fail2ban - }; - }; - - # Set-up media group - users.groups.media = { }; - - my.services.nginx.virtualHosts = { - komga = { - inherit (cfg) port; - }; - }; - - services.fail2ban.jails = { - komga = '' - enabled = true - filter = komga - port = http,https - ''; - }; - - environment.etc = { - "fail2ban/filter.d/komga.conf".text = '' - [Definition] - failregex = ^.* ip=,.*Bad credentials.*$ - journalmatch = _SYSTEMD_UNIT=komga.service - ''; - }; - }; -} diff --git a/modules/nixos/services/lohr/default.nix b/modules/nixos/services/lohr/default.nix index 21ed93b..21aadba 100644 --- a/modules/nixos/services/lohr/default.nix +++ b/modules/nixos/services/lohr/default.nix @@ -99,7 +99,7 @@ in }; }; "${lohrHome}/.ssh/id_ed25519" = { - "L+" = { + "f+" = { user = "lohr"; group = "lohr"; mode = "0700"; diff --git a/modules/nixos/services/matrix/bridges.nix b/modules/nixos/services/matrix/bridges.nix deleted file mode 100644 index 70f4118..0000000 --- a/modules/nixos/services/matrix/bridges.nix +++ /dev/null @@ -1,143 +0,0 @@ -# Matrix bridges for some services I use -{ config, lib, ... }: -let - cfg = config.my.services.matrix.bridges; - synapseCfg = config.services.matrix-synapse; - - domain = config.networking.domain; - serverName = synapseCfg.settings.server_name; - - mkBridgeOption = n: lib.mkEnableOption "${n} bridge" // { default = cfg.enable; }; - mkPortOption = n: default: lib.mkOption { - type = lib.types.port; - inherit default; - example = 8080; - description = "${n} bridge port"; - }; - mkEnvironmentFileOption = n: lib.mkOption { - type = lib.types.str; - example = "/run/secret/matrix/${lib.toLower n}-bridge-secrets.env"; - description = '' - Path to a file which should contain the secret values for ${n} bridge. - - Using through the following format: - - ``` - MATRIX_APPSERVICE_AS_TOKEN= - MATRIX_APPSERVICE_HS_TOKEN= - ``` - - Each bridge should use a different set of secrets, as they each register - their own independent double-puppetting appservice. - ''; - }; -in -{ - options.my.services.matrix.bridges = with lib; { - enable = mkEnableOption "bridges configuration"; - - admin = mkOption { - type = types.str; - default = "ambroisie"; - example = "admin"; - description = "Local username for the admin"; - }; - - facebook = { - enable = mkBridgeOption "Facebook"; - - port = mkPortOption "Facebook" 29321; - - environmentFile = mkEnvironmentFileOption "Facebook"; - }; - }; - - config = lib.mkMerge [ - (lib.mkIf cfg.facebook.enable { - services.mautrix-meta.instances.facebook = { - enable = true; - # Automatically register the bridge with synapse - registerToSynapse = true; - - # Provide `AS_TOKEN`, `HS_TOKEN` - inherit (cfg.facebook) environmentFile; - - settings = { - homeserver = { - domain = serverName; - address = "http://localhost:${toString config.my.services.matrix.port}"; - }; - - appservice = { - hostname = "localhost"; - inherit (cfg.facebook) port; - address = "http://localhost:${toString cfg.facebook.port}"; - public_address = "https://facebook-bridge.${domain}"; - - as_token = "$MATRIX_APPSERVICE_AS_TOKEN"; - hs_token = "$MATRIX_APPSERVICE_HS_TOKEN"; - - bot = { - username = "fbbot"; - }; - }; - - backfill = { - enabled = true; - }; - - bridge = { - delivery_receipts = true; - permissions = { - "*" = "relay"; - ${serverName} = "user"; - "@${cfg.admin}:${serverName}" = "admin"; - }; - }; - - database = { - type = "postgres"; - uri = "postgres:///mautrix-meta-facebook?host=/var/run/postgresql/"; - }; - - double_puppet = { - secrets = { - ${serverName} = "as_token:$MATRIX_APPSERVICE_AS_TOKEN"; - }; - }; - - network = { - # Don't be picky on Facebook/Messenger - allow_messenger_com_on_fb = true; - displayname_template = ''{{or .DisplayName .Username "Unknown user"}} (FB)''; - }; - - provisioning = { - shared_secret = "disable"; - }; - }; - }; - - services.postgresql = { - enable = true; - ensureDatabases = [ "mautrix-meta-facebook" ]; - ensureUsers = [{ - name = "mautrix-meta-facebook"; - ensureDBOwnership = true; - }]; - }; - - systemd.services.mautrix-meta-facebook = { - wants = [ "postgres.service" ]; - after = [ "postgres.service" ]; - }; - - my.services.nginx.virtualHosts = { - # Proxy to the bridge - "facebook-bridge" = { - inherit (cfg.facebook) port; - }; - }; - }) - ]; -} diff --git a/modules/nixos/services/matrix/default.nix b/modules/nixos/services/matrix/default.nix index 97dec2e..b958f76 100644 --- a/modules/nixos/services/matrix/default.nix +++ b/modules/nixos/services/matrix/default.nix @@ -1,49 +1,24 @@ -# Matrix homeserver setup. +# Matrix homeserver setup, using different endpoints for federation and client +# traffic. The main trick for this is defining two nginx servers endpoints for +# matrix.domain.com, each listening on different ports. +# +# Configuration shamelessly stolen from [1] +# +# [1]: https://github.com/alarsyo/nixos-config/blob/main/services/matrix.nix { config, lib, pkgs, ... }: let cfg = config.my.services.matrix; - adminPkg = pkgs.synapse-admin-etkecc; - + federationPort = { public = 8448; private = 11338; }; + clientPort = { public = 443; private = 11339; }; domain = config.networking.domain; matrixDomain = "matrix.${domain}"; - - serverConfig = { - "m.server" = "${matrixDomain}:443"; - }; - clientConfig = { - "m.homeserver" = { - "base_url" = "https://${matrixDomain}"; - "server_name" = domain; - }; - "m.identity_server" = { - "base_url" = "https://vector.im"; - }; - }; - - # ACAO required to allow element-web on any URL to request this json file - mkWellKnown = data: '' - default_type application/json; - add_header Access-Control-Allow-Origin *; - return 200 '${builtins.toJSON data}'; - ''; in { - imports = [ - ./bridges.nix - ]; - options.my.services.matrix = with lib; { enable = mkEnableOption "Matrix Synapse"; - port = mkOption { - type = types.port; - default = 8448; - example = 8008; - description = "Internal port for listeners"; - }; - secretFile = mkOption { type = with types; nullOr str; default = null; @@ -51,6 +26,21 @@ in description = "Shared secret to register users"; }; + slidingSync = { + port = mkOption { + type = types.port; + default = 8009; + example = 8084; + description = "Port used by sliding sync server"; + }; + + secretFile = mkOption { + type = types.str; + example = "/var/lib/matrix/sliding-sync-secret-file.env"; + description = "Secret file which contains SYNCV3_SECRET definition"; + }; + }; + mailConfigFile = mkOption { type = types.str; example = "/var/lib/matrix/email-config.yaml"; @@ -83,22 +73,22 @@ in enable_registration = false; listeners = [ + # Federation { - inherit (cfg) port; bind_addresses = [ "::1" ]; - type = "http"; - tls = false; + port = federationPort.private; + tls = false; # Terminated by nginx. x_forwarded = true; - resources = [ - { - names = [ "client" ]; - compress = true; - } - { - names = [ "federation" ]; - compress = false; - } - ]; + resources = [{ names = [ "federation" ]; compress = false; }]; + } + + # Client + { + bind_addresses = [ "::1" ]; + port = clientPort.private; + tls = false; # Terminated by nginx. + x_forwarded = true; + resources = [{ names = [ "client" ]; compress = false; }]; } ]; @@ -116,17 +106,38 @@ in ] ++ lib.optional (cfg.secretFile != null) cfg.secretFile; }; + services.matrix-sliding-sync = { + enable = true; + + settings = { + SYNCV3_SERVER = "https://${matrixDomain}"; + SYNCV3_BINDADDR = "127.0.0.1:${toString cfg.slidingSync.port}"; + }; + + environmentFile = cfg.slidingSync.secretFile; + }; + my.services.nginx.virtualHosts = { # Element Web app deployment chat = { root = pkgs.element-web.override { conf = { - default_server_config = clientConfig; - show_labs_settings = true; - default_country_code = "FR"; # cocorico - room_directory = { + default_server_config = { + "m.homeserver" = { + "base_url" = "https://${matrixDomain}"; + "server_name" = domain; + }; + "m.identity_server" = { + "base_url" = "https://vector.im"; + }; + "org.matrix.msc3575.proxy" = { + "url" = "https://matrix-sync.${domain}"; + }; + }; + showLabsSettings = true; + defaultCountryCode = "FR"; # cocorico + roomDirectory = { "servers" = [ - domain "matrix.org" "mozilla.org" ]; @@ -134,54 +145,109 @@ in }; }; }; - matrix = { - # Somewhat unused, but necessary for port collision detection - inherit (cfg) port; - - extraConfig = { - locations = { - # Or do a redirect instead of the 404, or whatever is appropriate - # for you. But do not put a Matrix Web client here! See the - # Element web section above. - "/".return = "404"; - - "/_matrix".proxyPass = "http://[::1]:${toString cfg.port}"; - "/_synapse".proxyPass = "http://[::1]:${toString cfg.port}"; - - "= /admin".return = "307 /admin/"; - "/admin/" = { - alias = "${adminPkg}/"; - priority = 500; - tryFiles = "$uri $uri/ /index.html"; - }; - "~ ^/admin/.*\\.(?:css|js|jpg|jpeg|gif|png|svg|ico|woff|woff2|ttf|eot|webp)$" = { - priority = 400; - root = adminPkg; - extraConfig = '' - rewrite ^/admin/(.*)$ /$1 break; - expires 30d; - more_set_headers "Cache-Control: public"; - ''; - }; - }; - }; + # Dummy VHosts for port collision detection + matrix-federation = { + port = federationPort.private; + }; + matrix-client = { + port = clientPort.private; + }; + # Sliding sync + matrix-sync = { + inherit (cfg.slidingSync) port; }; }; - # Setup well-known locations + # Those are too complicated to use my wrapper... services.nginx.virtualHosts = { + ${matrixDomain} = { + onlySSL = true; + useACMEHost = domain; + + locations = + let + proxyToClientPort = { + proxyPass = "http://[::1]:${toString clientPort.private}"; + }; + in + { + # Or do a redirect instead of the 404, or whatever is appropriate + # for you. But do not put a Matrix Web client here! See the + # Element web section below. + "/".return = "404"; + + "/_matrix" = proxyToClientPort; + "/_synapse/client" = proxyToClientPort; + + # Sliding sync + "~ ^/(client/|_matrix/client/unstable/org.matrix.msc3575/sync)" = { + proxyPass = "http://${config.services.matrix-sliding-sync.settings.SYNCV3_BINDADDR}"; + }; + }; + + listen = [ + { addr = "0.0.0.0"; port = clientPort.public; ssl = true; } + { addr = "[::]"; port = clientPort.public; ssl = true; } + ]; + + }; + + # same as above, but listening on the federation port + "${matrixDomain}_federation" = { + onlySSL = true; + serverName = matrixDomain; + useACMEHost = domain; + + locations."/".return = "404"; + + locations."/_matrix" = { + proxyPass = "http://[::1]:${toString federationPort.private}"; + }; + + listen = [ + { addr = "0.0.0.0"; port = federationPort.public; ssl = true; } + { addr = "[::]"; port = federationPort.public; ssl = true; } + ]; + }; + "${domain}" = { forceSSL = true; useACMEHost = domain; - locations."= /.well-known/matrix/server".extraConfig = mkWellKnown serverConfig; - locations."= /.well-known/matrix/client".extraConfig = mkWellKnown clientConfig; + locations."= /.well-known/matrix/server".extraConfig = + let + server = { "m.server" = "${matrixDomain}:${toString federationPort.public}"; }; + in + '' + add_header Content-Type application/json; + return 200 '${builtins.toJSON server}'; + ''; + + locations."= /.well-known/matrix/client".extraConfig = + let + client = { + "m.homeserver" = { "base_url" = "https://${matrixDomain}"; }; + "m.identity_server" = { "base_url" = "https://vector.im"; }; + "org.matrix.msc3575.proxy" = { "url" = "https://matrix-sync.${domain}"; }; + }; + # ACAO required to allow element-web on any URL to request this json file + in + '' + add_header Content-Type application/json; + add_header Access-Control-Allow-Origin *; + return 200 '${builtins.toJSON client}'; + ''; }; }; # For administration tools. environment.systemPackages = [ pkgs.matrix-synapse ]; + networking.firewall.allowedTCPPorts = [ + clientPort.public + federationPort.public + ]; + my.services.backup = { paths = [ config.services.matrix-synapse.dataDir diff --git a/modules/nixos/services/mealie/default.nix b/modules/nixos/services/mealie/default.nix index f3774e1..ebbebb2 100644 --- a/modules/nixos/services/mealie/default.nix +++ b/modules/nixos/services/mealie/default.nix @@ -32,48 +32,41 @@ in BASE_URL = "https://mealie.${config.networking.domain}"; TZ = config.time.timeZone; ALLOw_SIGNUP = "false"; - TOKEN_TIME = 24 * 180; # 180 days - }; - # Automatic PostgreSQL provisioning - database = { - createLocally = true; + # Use PostgreSQL + DB_ENGINE = "postgres"; + POSTGRES_USER = "mealie"; + POSTGRES_PASSWORD = ""; + POSTGRES_SERVER = "/run/postgresql"; + # Pydantic and/or mealie doesn't handle the URI correctly, hijack it + # with query parameters... + POSTGRES_DB = "mealie?host=/run/postgresql&dbname=mealie"; }; }; + systemd.services = { + mealie = { + after = [ "postgresql.service" ]; + requires = [ "postgresql.service" ]; + }; + }; + + # Set-up database + services.postgresql = { + enable = true; + ensureDatabases = [ "mealie" ]; + ensureUsers = [ + { + name = "mealie"; + ensureDBOwnership = true; + } + ]; + }; + my.services.nginx.virtualHosts = { mealie = { inherit (cfg) port; - - extraConfig = { - # Allow bulk upload of recipes for import/export - locations."/".extraConfig = '' - client_max_body_size 0; - ''; - }; }; }; - - my.services.backup = { - paths = [ - "/var/lib/mealie" - ]; - }; - - services.fail2ban.jails = { - mealie = '' - enabled = true - filter = mealie - port = http,https - ''; - }; - - environment.etc = { - "fail2ban/filter.d/mealie.conf".text = '' - [Definition] - failregex = ^.*ERROR.*Incorrect username or password from - journalmatch = _SYSTEMD_UNIT=mealie.service - ''; - }; }; } diff --git a/modules/nixos/services/miniflux/default.nix b/modules/nixos/services/miniflux/default.nix index 400ae00..5104c8b 100644 --- a/modules/nixos/services/miniflux/default.nix +++ b/modules/nixos/services/miniflux/default.nix @@ -48,21 +48,5 @@ in inherit (cfg) port; }; }; - - services.fail2ban.jails = { - miniflux = '' - enabled = true - filter = miniflux - port = http,https - ''; - }; - - environment.etc = { - "fail2ban/filter.d/miniflux.conf".text = '' - [Definition] - failregex = ^.*msg="[^"]*(Incorrect|Invalid) username or password[^"]*".*client_ip= - journalmatch = _SYSTEMD_UNIT=miniflux.service - ''; - }; }; } diff --git a/modules/nixos/services/navidrome/default.nix b/modules/nixos/services/navidrome/default.nix index c513b91..944a97a 100644 --- a/modules/nixos/services/navidrome/default.nix +++ b/modules/nixos/services/navidrome/default.nix @@ -52,21 +52,5 @@ in inherit (cfg) port; }; }; - - services.fail2ban.jails = { - navidrome = '' - enabled = true - filter = navidrome - port = http,https - ''; - }; - - environment.etc = { - "fail2ban/filter.d/navidrome.conf".text = '' - [Definition] - failregex = ^.*msg="Unsuccessful login".*X-Real-Ip:\[\] - journalmatch = _SYSTEMD_UNIT=navidrome.service - ''; - }; }; } diff --git a/modules/nixos/services/nextcloud/collabora.nix b/modules/nixos/services/nextcloud/collabora.nix deleted file mode 100644 index 408b232..0000000 --- a/modules/nixos/services/nextcloud/collabora.nix +++ /dev/null @@ -1,56 +0,0 @@ -# Document editor with Nextcloud -{ config, lib, ... }: -let - cfg = config.my.services.nextcloud.collabora; -in -{ - options.my.services.nextcloud.collabora = with lib; { - enable = mkEnableOption "Collabora integration"; - - port = mkOption { - type = types.port; - default = 9980; - example = 8080; - description = "Internal port for API"; - }; - }; - - config = lib.mkIf cfg.enable { - services.nextcloud = { - extraApps = { - inherit (config.services.nextcloud.package.packages.apps) richdocuments; - }; - }; - - services.collabora-online = { - enable = true; - inherit (cfg) port; - - aliasGroups = [ - { - host = "https://collabora.${config.networking.domain}"; - # Allow using from nextcloud - aliases = [ "https://${config.services.nextcloud.hostName}" ]; - } - ]; - - settings = { - # Rely on reverse proxy for SSL - ssl = { - enable = false; - termination = true; - }; - }; - }; - - my.services.nginx.virtualHosts = { - collabora = { - inherit (cfg) port; - websocketsLocations = [ - "~ ^/cool/(.*)/ws$" - "^~ /cool/adminws" - ]; - }; - }; - }; -} diff --git a/modules/nixos/services/nextcloud/default.nix b/modules/nixos/services/nextcloud/default.nix index 24515ff..51195df 100644 --- a/modules/nixos/services/nextcloud/default.nix +++ b/modules/nixos/services/nextcloud/default.nix @@ -4,10 +4,6 @@ let cfg = config.my.services.nextcloud; in { - imports = [ - ./collabora.nix - ]; - options.my.services.nextcloud = with lib; { enable = mkEnableOption "Nextcloud"; maxSize = mkOption { @@ -35,7 +31,7 @@ in config = lib.mkIf cfg.enable { services.nextcloud = { enable = true; - package = pkgs.nextcloud32; + package = pkgs.nextcloud28; hostName = "nextcloud.${config.networking.domain}"; home = "/var/lib/nextcloud"; maxUploadSize = cfg.maxSize; @@ -44,15 +40,11 @@ in adminuser = cfg.admin; adminpassFile = cfg.passwordFile; dbtype = "pgsql"; + dbhost = "/run/postgresql"; }; https = true; - # Automatic PostgreSQL provisioning - database = { - createLocally = true; - }; - settings = { overwriteprotocol = "https"; # Nginx only allows SSL }; @@ -62,16 +54,22 @@ in # Allow using the push service without hard-coding my IP in the configuration bendDomainToLocalhost = true; }; + }; - extraApps = { - inherit (config.services.nextcloud.package.packages.apps) - calendar - contacts - deck - tasks - ; - # notify_push is automatically installed by the module - }; + services.postgresql = { + enable = true; + ensureDatabases = [ "nextcloud" ]; + ensureUsers = [ + { + name = "nextcloud"; + ensureDBOwnership = true; + } + ]; + }; + + systemd.services."nextcloud-setup" = { + requires = [ "postgresql.service" ]; + after = [ "postgresql.service" ]; }; # The service above configures the domain, no need for my wrapper @@ -89,25 +87,5 @@ in "${config.services.nextcloud.home}/data/appdata_*/preview" ]; }; - - services.fail2ban.jails = { - nextcloud = '' - enabled = true - filter = nextcloud - port = http,https - ''; - }; - - environment.etc = { - "fail2ban/filter.d/nextcloud.conf".text = '' - [Definition] - _groupsre = (?:(?:,?\s*"\w+":(?:"[^"]+"|\w+))*) - datepattern = ,?\s*"time"\s*:\s*"%%Y-%%m-%%d[T ]%%H:%%M:%%S(%%z)?" - failregex = ^[^{]*\{%(_groupsre)s,?\s*"remoteAddr":""%(_groupsre)s,?\s*"message":"Login failed: - ^[^{]*\{%(_groupsre)s,?\s*"remoteAddr":""%(_groupsre)s,?\s*"message":"Trusted domain error. - ^[^{]*\{%(_groupsre)s,?\s*"remoteAddr":""%(_groupsre)s,?\s*"message":"Two-factor challenge failed: - journalmatch = _SYSTEMD_UNIT=phpfpm-nextcloud.service - ''; - }; }; } diff --git a/modules/nixos/services/nginx/default.nix b/modules/nixos/services/nginx/default.nix index ff530b0..7980ad9 100644 --- a/modules/nixos/services/nginx/default.nix +++ b/modules/nixos/services/nginx/default.nix @@ -17,16 +17,6 @@ let ''; }; - websocketsLocations = mkOption { - type = with types; listOf str; - default = [ ]; - example = [ "/socket" ]; - description = '' - Which locations on this virtual host should be configured for - websockets. - ''; - }; - port = mkOption { type = with types; nullOr port; default = null; @@ -69,15 +59,14 @@ let extraConfig = mkOption { type = types.attrs; # FIXME: forward type of virtualHosts - example = { - extraConfig = '' - add_header X-Clacks-Overhead "GNU Terry Pratchett"; - ''; - - locations."/".extraConfig = '' - client_max_body_size 1G; - ''; - }; + example = litteralExample '' + { + locations."/socket" = { + proxyPass = "http://127.0.0.1:8096/"; + proxyWebsockets = true; + }; + } + ''; default = { }; description = '' Any extra configuration that should be applied to this virtual host. @@ -87,6 +76,10 @@ let }); in { + imports = [ + ./sso + ]; + options.my.services.nginx = with lib; { enable = mkEnableOption "Nginx"; @@ -95,7 +88,7 @@ in type = types.str; example = "/var/lib/acme/creds.env"; description = '' - OVH API key file as an 'EnvironmentFile' (see `systemd.exec(5)`) + Gandi API key file as an 'EnvironmentFile' (see `systemd.exec(5)`) ''; }; }; @@ -107,19 +100,26 @@ in virtualHosts = mkOption { type = types.attrsOf virtualHostOption; default = { }; - example = { - gitea = { - subdomain = "git"; - port = 8080; - }; - dev = { - root = "/var/www/dev"; - }; - jellyfin = { - port = 8096; - websocketsLocations = [ "/socket" ]; - }; - }; + example = litteralExample '' + { + gitea = { + subdomain = "git"; + port = 8080; + }; + dev = { + root = "/var/www/dev"; + }; + jellyfin = { + port = 8096; + extraConfig = { + locations."/socket" = { + proxyPass = "http://127.0.0.1:8096/"; + proxyWebsockets = true; + }; + }; + }; + } + ''; description = '' List of virtual hosts to set-up using default settings. ''; @@ -163,21 +163,25 @@ in }; }; }); - example = { - alice = { - passwordHashFile = "/var/lib/nginx-sso/alice/password-hash.txt"; - totpSecretFile = "/var/lib/nginx-sso/alice/totp-secret.txt"; - }; - }; + example = litteralExample '' + { + alice = { + passwordHashFile = "/var/lib/nginx-sso/alice/password-hash.txt"; + totpSecretFile = "/var/lib/nginx-sso/alice/totp-secret.txt"; + }; + } + ''; description = "Definition of users"; }; groups = mkOption { type = with types; attrsOf (listOf str); - example = { - root = [ "alice" ]; - users = [ "alice" "bob" ]; - }; + example = litteralExample '' + { + root = [ "alice" ]; + users = [ "alice" "bob" ]; + } + ''; description = "Groups of users"; }; }; @@ -199,19 +203,6 @@ in } configured. ''; })) - ++ (lib.flip lib.mapAttrsToList cfg.virtualHosts (_: { subdomain, ... } @ args: - let - proxyPass = [ "port" "socket" ]; - proxyPassUsed = lib.any (v: args.${v} != null) proxyPass; - in - { - assertion = args.websocketsLocations != [ ] -> proxyPassUsed; - message = '' - Subdomain '${subdomain}' can only use 'websocketsLocations' with one of ${ - lib.concatStringsSep ", " (builtins.map (v: "'${v}'") proxyPass) - }. - ''; - })) ++ ( let ports = lib.my.mapFilter @@ -253,18 +244,11 @@ in recommendedOptimisation = true; recommendedProxySettings = true; recommendedTlsSettings = true; + recommendedZstdSettings = true; virtualHosts = let domain = config.networking.domain; - mkProxyPass = { websocketsLocations, ... }: proxyPass: - let - websockets = lib.genAttrs websocketsLocations (_: { - inherit proxyPass; - proxyWebsockets = true; - }); - in - { "/" = { inherit proxyPass; }; } // websockets; mkVHost = ({ subdomain, ... } @ args: lib.nameValuePair "${subdomain}.${domain}" (lib.my.recursiveMerge [ @@ -275,7 +259,8 @@ in } # Proxy to port (lib.optionalAttrs (args.port != null) { - locations = mkProxyPass args "http://127.0.0.1:${toString args.port}"; + locations."/".proxyPass = + "http://127.0.0.1:${toString args.port}"; }) # Serve filesystem content (lib.optionalAttrs (args.root != null) { @@ -283,7 +268,8 @@ in }) # Serve to UNIX socket (lib.optionalAttrs (args.socket != null) { - locations = mkProxyPass args "http://unix:${args.socket}"; + locations."/".proxyPass = + "http://unix:${args.socket}"; }) # Redirect to a different domain (lib.optionalAttrs (args.redirect != null) { @@ -303,7 +289,6 @@ in locations."/" = { extraConfig = - # FIXME: check that X-User is dropped otherwise (args.extraConfig.locations."/".extraConfig or "") + '' # Use SSO auth_request /sso-auth; @@ -437,14 +422,13 @@ in { "${domain}" = { extraDomainNames = [ "*.${domain}" ]; - dnsProvider = "ovh"; - dnsPropagationCheck = false; # OVH is slow + dnsProvider = "gandiv5"; inherit (cfg.acme) credentialsFile; }; }; }; - systemd.services."acme-order-renew-${domain}" = { + systemd.services."acme-${domain}" = { serviceConfig = { Environment = [ # Since I do a "weird" setup with a wildcard CNAME diff --git a/modules/nixos/services/nginx/sso/default.nix b/modules/nixos/services/nginx/sso/default.nix new file mode 100644 index 0000000..4a78282 --- /dev/null +++ b/modules/nixos/services/nginx/sso/default.nix @@ -0,0 +1,89 @@ +# I must override the module to allow having runtime secrets +{ config, lib, pkgs, utils, ... }: +let + cfg = config.services.nginx.sso; + pkg = lib.getBin cfg.package; + confPath = "/var/lib/nginx-sso/config.json"; +in +{ + disabledModules = [ "services/security/nginx-sso.nix" ]; + + + options.services.nginx.sso = with lib; { + enable = mkEnableOption "nginx-sso service"; + + package = mkOption { + type = types.package; + default = pkgs.nginx-sso; + defaultText = "pkgs.nginx-sso"; + description = '' + The nginx-sso package that should be used. + ''; + }; + + configuration = mkOption { + type = types.attrsOf types.unspecified; + default = { }; + example = literalExample '' + { + listen = { addr = "127.0.0.1"; port = 8080; }; + + providers.token.tokens = { + myuser = "MyToken"; + }; + + acl = { + rule_sets = [ + { + rules = [ { field = "x-application"; equals = "MyApp"; } ]; + allow = [ "myuser" ]; + } + ]; + }; + } + ''; + description = '' + nginx-sso configuration + (documentation) + as a Nix attribute set. + ''; + }; + }; + + config = lib.mkIf cfg.enable { + systemd.services.nginx-sso = { + description = "Nginx SSO Backend"; + after = [ "network.target" ]; + wantedBy = [ "multi-user.target" ]; + serviceConfig = { + StateDirectory = "nginx-sso"; + WorkingDirectory = "/var/lib/nginx-sso"; + # The files to be merged might not have the correct permissions + ExecStartPre = ''+${pkgs.writeShellScript "merge-nginx-sso-config" '' + rm -f '${confPath}' + ${utils.genJqSecretsReplacementSnippet cfg.configuration confPath} + + # Fix permissions + chown nginx-sso:nginx-sso ${confPath} + chmod 0600 ${confPath} + '' + }''; + ExecStart = lib.mkForce '' + ${lib.getExe pkg} \ + --config ${confPath} \ + --frontend-dir ${pkg}/share/frontend + ''; + Restart = "always"; + User = "nginx-sso"; + Group = "nginx-sso"; + }; + }; + + users.users.nginx-sso = { + isSystemUser = true; + group = "nginx-sso"; + }; + + users.groups.nginx-sso = { }; + }; +} diff --git a/modules/nixos/services/nix-cache/default.nix b/modules/nixos/services/nix-cache/default.nix index f3a29aa..1ce3161 100644 --- a/modules/nixos/services/nix-cache/default.nix +++ b/modules/nixos/services/nix-cache/default.nix @@ -40,7 +40,7 @@ in inherit (cfg) priority; }; - signKeyPaths = [ cfg.secretKeyFile ]; + signKeyPath = cfg.secretKeyFile; }; my.services.nginx.virtualHosts = { diff --git a/modules/nixos/services/paperless/default.nix b/modules/nixos/services/paperless/default.nix index 1195977..f62879a 100644 --- a/modules/nixos/services/paperless/default.nix +++ b/modules/nixos/services/paperless/default.nix @@ -1,4 +1,4 @@ -{ config, lib, ... }: +{ config, lib, pkgs, ... }: let cfg = config.my.services.paperless; in @@ -52,39 +52,91 @@ in mediaDir = lib.mkIf (cfg.documentPath != null) cfg.documentPath; - settings = { - # Use SSO - PAPERLESS_ENABLE_HTTP_REMOTE_USER = true; - PAPERLESS_ENABLE_HTTP_REMOTE_USER_API = true; - PAPERLESS_HTTP_REMOTE_USER_HEADER_NAME = "HTTP_X_USER"; + settings = + let + paperlessDomain = "paperless.${config.networking.domain}"; + in + { + # Use SSO + PAPERLESS_ENABLE_HTTP_REMOTE_USER = true; + PAPERLESS_HTTP_REMOTE_USER_HEADER_NAME = "HTTP_X_USER"; - # Security settings - PAPERLESS_URL = "https://paperless.${config.networking.domain}"; - PAPERLESS_USE_X_FORWARD_HOST = true; - PAPERLESS_PROXY_SSL_HEADER = [ "HTTP_X_FORWARDED_PROTO" "https" ]; + # Use PostgreSQL + PAPERLESS_DBHOST = "/run/postgresql"; + PAPERLESS_DBUSER = "paperless"; + PAPERLESS_DBNAME = "paperless"; - # OCR settings - PAPERLESS_OCR_LANGUAGE = "fra+eng"; + # Security settings + PAPERLESS_ALLOWED_HOSTS = paperlessDomain; + PAPERLESS_CORS_ALLOWED_HOSTS = "https://${paperlessDomain}"; - # Workers - PAPERLESS_TASK_WORKERS = 3; - PAPERLESS_THREADS_PER_WORKER = 4; + # OCR settings + PAPERLESS_OCR_LANGUAGE = "fra+eng"; - # Misc - PAPERLESS_TIME_ZONE = config.time.timeZone; - PAPERLESS_ADMIN_USER = cfg.username; - }; + # Workers + PAPERLESS_TASK_WORKERS = 3; + PAPERLESS_THREADS_PER_WORKER = 4; + + # Misc + PAPERLESS_TIME_ZONE = config.time.timeZone; + PAPERLESS_ADMIN_USER = cfg.username; + + # Fix classifier hangs + LD_LIBRARY_PATH = "${lib.getLib pkgs.mkl}/lib"; + }; # Admin password passwordFile = cfg.passwordFile; + }; - # Secret key - environmentFile = cfg.secretKeyFile; + systemd.services = { + paperless-scheduler = { + requires = [ "postgresql.service" ]; + after = [ "postgresql.service" ]; - # Automatic PostgreSQL provisioning - database = { - createLocally = true; + serviceConfig = { + EnvironmentFile = cfg.secretKeyFile; + }; }; + + paperless-consumer = { + requires = [ "postgresql.service" ]; + after = [ "postgresql.service" ]; + + serviceConfig = { + EnvironmentFile = cfg.secretKeyFile; + }; + }; + + paperless-web = { + requires = [ "postgresql.service" ]; + after = [ "postgresql.service" ]; + + serviceConfig = { + EnvironmentFile = cfg.secretKeyFile; + }; + }; + + paperless-task-queue = { + requires = [ "postgresql.service" ]; + after = [ "postgresql.service" ]; + + serviceConfig = { + EnvironmentFile = cfg.secretKeyFile; + }; + }; + }; + + # Set-up database + services.postgresql = { + enable = true; + ensureDatabases = [ "paperless" ]; + ensureUsers = [ + { + name = "paperless"; + ensureDBOwnership = true; + } + ]; }; # Set-up media group @@ -100,7 +152,11 @@ in sso = { enable = true; }; - websocketsLocations = [ "/" ]; + + # Enable websockets on root + extraConfig = { + locations."/".proxyWebsockets = true; + }; }; }; diff --git a/modules/nixos/services/pdf-edit/default.nix b/modules/nixos/services/pdf-edit/default.nix deleted file mode 100644 index d59507b..0000000 --- a/modules/nixos/services/pdf-edit/default.nix +++ /dev/null @@ -1,73 +0,0 @@ -{ config, lib, ... }: -let - cfg = config.my.services.pdf-edit; -in -{ - options.my.services.pdf-edit = with lib; { - enable = mkEnableOption "PDF edition service"; - - port = mkOption { - type = types.port; - default = 8089; - example = 8080; - description = "Internal port for webui"; - }; - - loginFile = mkOption { - type = types.str; - example = "/run/secrets/pdf-edit/login.env"; - description = '' - `SECURITY_INITIALLOGIN_USERNAME` and `SECURITY_INITIALLOGIN_PASSWORD` - defined in the format of 'EnvironmentFile' (see `systemd.exec(5)`). - ''; - }; - }; - - config = lib.mkIf cfg.enable { - services.stirling-pdf = lib.mkIf cfg.enable { - enable = true; - - environment = { - SERVER_PORT = cfg.port; - SECURITY_CSRFDISABLED = "false"; - - SYSTEM_SHOWUPDATE = "false"; # We don't care about update notifications - INSTALL_BOOK_AND_ADVANCED_HTML_OPS = "true"; # Installed by the module - - SECURITY_ENABLELOGIN = "true"; - SECURITY_LOGINATTEMPTCOUNT = "-1"; # Rely on fail2ban instead - }; - - environmentFiles = [ cfg.loginFile ]; - }; - - my.services.nginx.virtualHosts = { - pdf-edit = { - inherit (cfg) port; - - extraConfig = { - # Allow upload of PDF files up to 1G - locations."/".extraConfig = '' - client_max_body_size 1G; - ''; - }; - }; - }; - - services.fail2ban.jails = { - stirling-pdf = '' - enabled = true - filter = stirling-pdf - port = http,https - ''; - }; - - environment.etc = { - "fail2ban/filter.d/stirling-pdf.conf".text = '' - [Definition] - failregex = ^.*Failed login attempt from IP: $ - journalmatch = _SYSTEMD_UNIT=stirling-pdf.service - ''; - }; - }; -} diff --git a/modules/nixos/services/pirate/default.nix b/modules/nixos/services/pirate/default.nix new file mode 100644 index 0000000..e500b54 --- /dev/null +++ b/modules/nixos/services/pirate/default.nix @@ -0,0 +1,92 @@ +# The total autonomous media delivery system. +# Relevant link [1]. +# +# [1]: https://youtu.be/I26Ql-uX6AM +{ config, lib, ... }: +let + cfg = config.my.services.pirate; + + ports = { + bazarr = 6767; + lidarr = 8686; + radarr = 7878; + 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 +{ + options.my.services.pirate = { + enable = lib.mkEnableOption "Media automation"; + + bazarr = { + enable = lib.my.mkDisableOption "Bazarr"; + }; + + lidarr = { + enable = lib.my.mkDisableOption "Lidarr"; + }; + + radarr = { + enable = lib.my.mkDisableOption "Radarr"; + }; + + sonarr = { + enable = lib.my.mkDisableOption "Sonarr"; + }; + }; + + 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") + # Sonarr for shows + (mkFullConfig "sonarr") + (mkFail2Ban "sonarr") + ]); +} diff --git a/modules/nixos/services/podgrab/default.nix b/modules/nixos/services/podgrab/default.nix index 3ced8d3..5ceebb6 100644 --- a/modules/nixos/services/podgrab/default.nix +++ b/modules/nixos/services/podgrab/default.nix @@ -13,16 +13,7 @@ in example = "/run/secrets/password.env"; description = '' The path to a file containing the PASSWORD environment variable - definition for Podgrab's authentication. - ''; - }; - - dataDir = mkOption { - type = with types; nullOr str; - default = null; - example = "/mnt/podgrab"; - description = '' - Path to the directory to store the podcasts. Use default if null + definition for Podgrab's authentification. ''; }; @@ -38,14 +29,8 @@ in services.podgrab = { enable = true; inherit (cfg) passwordFile port; - - group = "media"; - dataDirectory = lib.mkIf (cfg.dataDir != null) cfg.dataDir; }; - # Set-up media group - users.groups.media = { }; - my.services.nginx.virtualHosts = { podgrab = { inherit (cfg) port; diff --git a/modules/nixos/services/postgresql/default.nix b/modules/nixos/services/postgresql/default.nix index 1dca164..6f51f3e 100644 --- a/modules/nixos/services/postgresql/default.nix +++ b/modules/nixos/services/postgresql/default.nix @@ -14,34 +14,30 @@ in # Let other services enable postgres when they need it (lib.mkIf cfg.enable { services.postgresql = { - package = pkgs.postgresql_17; + package = pkgs.postgresql_13; }; }) # Taken from the manual (lib.mkIf cfg.upgradeScript { + containers.temp-pg.config.services.postgresql = { + enable = true; + package = pkgs.postgresql_13; + }; + environment.systemPackages = let - pgCfg = config.services.postgresql; - newPackage' = pkgs.postgresql_17; - - oldPackage = if pgCfg.enableJIT then pgCfg.package.withJIT else pgCfg.package; - oldData = pgCfg.dataDir; - oldBin = "${if pgCfg.extensions == [] then oldPackage else oldPackage.withPackages pgCfg.extensions}/bin"; - - newPackage = if pgCfg.enableJIT then newPackage'.withJIT else newPackage'; - newData = "/var/lib/postgresql/${newPackage.psqlSchema}"; - newBin = "${if pgCfg.extensions == [] then newPackage else newPackage.withPackages pgCfg.extensions}/bin"; + newpg = config.containers.temp-pg.config.services.postgresql; in [ (pkgs.writeScriptBin "upgrade-pg-cluster" '' #!/usr/bin/env bash - set -eux - export OLDDATA="${oldData}" - export NEWDATA="${newData}" - export OLDBIN="${oldBin}" - export NEWBIN="${newBin}" + set -x + export OLDDATA="${config.services.postgresql.dataDir}" + export NEWDATA="${newpg.dataDir}" + export OLDBIN="${config.services.postgresql.package}/bin" + export NEWBIN="${newpg.package}/bin" if [ "$OLDDATA" -ef "$NEWDATA" ]; then echo "Cannot migrate to same data directory" >&2 @@ -50,21 +46,14 @@ in install -d -m 0700 -o postgres -g postgres "$NEWDATA" cd "$NEWDATA" - sudo -u postgres "$NEWBIN/initdb" -D "$NEWDATA" + sudo -u postgres $NEWBIN/initdb -D "$NEWDATA" systemctl stop postgresql # old one - sudo -u postgres "$NEWBIN/pg_upgrade" \ + sudo -u postgres $NEWBIN/pg_upgrade \ --old-datadir "$OLDDATA" --new-datadir "$NEWDATA" \ - --old-bindir "$OLDBIN" --new-bindir "$NEWBIN" \ + --old-bindir $OLDBIN --new-bindir $NEWBIN \ "$@" - - cat << EOF - Run the following commands after setting: - services.postgresql.package = pkgs.postgresql_${lib.versions.major newPackage.version} - sudo -u postgres vacuumdb --all --analyze-in-stages - ${newData}/delete_old_cluster.sh - EOF '') ]; }) diff --git a/modules/nixos/services/pyload/default.nix b/modules/nixos/services/pyload/default.nix index 7257d0f..88889bf 100644 --- a/modules/nixos/services/pyload/default.nix +++ b/modules/nixos/services/pyload/default.nix @@ -53,20 +53,6 @@ in }; }; - services.fail2ban.jails = { - pyload = '' - enabled = true - filter = pyload - port = http,https - ''; - }; - - environment.etc = { - "fail2ban/filter.d/pyload.conf".text = '' - [Definition] - failregex = ^.*Login failed for user '.*' \[CLIENT: \]$ - journalmatch = _SYSTEMD_UNIT=pyload.service - ''; - }; + # FIXME: fail2ban }; } diff --git a/modules/nixos/services/rss-bridge/default.nix b/modules/nixos/services/rss-bridge/default.nix index 52b1030..85e37c2 100644 --- a/modules/nixos/services/rss-bridge/default.nix +++ b/modules/nixos/services/rss-bridge/default.nix @@ -11,9 +11,7 @@ in config = lib.mkIf cfg.enable { services.rss-bridge = { enable = true; - config = { - system.enabled_bridges = [ "*" ]; # Whitelist all - }; + whitelist = [ "*" ]; # Whitelist all virtualHost = "rss-bridge.${config.networking.domain}"; }; diff --git a/modules/nixos/services/servarr/autobrr.nix b/modules/nixos/services/servarr/autobrr.nix deleted file mode 100644 index c3370cb..0000000 --- a/modules/nixos/services/servarr/autobrr.nix +++ /dev/null @@ -1,63 +0,0 @@ -# IRC-based indexer -{ 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; - websocketsLocations = [ "/api" ]; - }; - }; - - services.fail2ban.jails = { - autobrr = '' - enabled = true - filter = autobrr - action = iptables-allports - ''; - }; - - environment.etc = { - "fail2ban/filter.d/autobrr.conf".text = '' - [Definition] - failregex = "message":"Auth: Failed login attempt username: \[.*\] ip: " - journalmatch = _SYSTEMD_UNIT=autobrr.service - ''; - }; - }; -} diff --git a/modules/nixos/services/servarr/bazarr.nix b/modules/nixos/services/servarr/bazarr.nix deleted file mode 100644 index 637da0c..0000000 --- a/modules/nixos/services/servarr/bazarr.nix +++ /dev/null @@ -1,37 +0,0 @@ -{ 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/cross-seed.nix b/modules/nixos/services/servarr/cross-seed.nix deleted file mode 100644 index 74f216a..0000000 --- a/modules/nixos/services/servarr/cross-seed.nix +++ /dev/null @@ -1,96 +0,0 @@ -# Automatic cross-seeding for video media -{ config, lib, ... }: -let - cfg = config.my.services.servarr.cross-seed; -in -{ - options.my.services.servarr.cross-seed = with lib; { - enable = mkEnableOption "cross-seed daemon" // { - default = config.my.services.servarr.enableAll; - }; - - port = mkOption { - type = types.port; - default = 2468; - example = 8080; - description = "Internal port for daemon"; - }; - - linkDirectory = mkOption { - type = types.str; - default = "/data/downloads/complete/links"; - example = "/var/lib/cross-seed/links"; - description = "Link directory"; - }; - - secretSettingsFile = mkOption { - type = types.str; - example = "/run/secrets/cross-seed-secrets.json"; - description = '' - File containing secret settings. - ''; - }; - }; - - config = lib.mkIf cfg.enable { - services.cross-seed = { - enable = true; - group = "media"; - - # Rely on recommended defaults for tracker snatches etc... - useGenConfigDefaults = true; - - settings = { - inherit (cfg) port; - host = "127.0.0.1"; - - # Inject torrents to client directly - action = "inject"; - # Query the client for torrents to match - useClientTorrents = true; - # Use hardlinks - linkType = "hardlink"; - # Use configured link directory - linkDirs = [ cfg.linkDirectory ]; - # Match as many torrents as possible - matchMode = "partial"; - # Cross-seed full season if at least 50% of episodes are already downloaded - seasonFromEpisodes = 0.5; - }; - - settingsFile = cfg.secretSettingsFile; - }; - - systemd.services.cross-seed = { - serviceConfig = { - # Loose umask to make cross-seed links readable by `media` - UMask = "0002"; - }; - }; - - # Set-up media group - users.groups.media = { }; - - my.services.nginx.virtualHosts = { - cross-seed = { - inherit (cfg) port; - }; - }; - - services.fail2ban.jails = { - cross-seed = '' - enabled = true - filter = cross-seed - action = iptables-allports - ''; - }; - - environment.etc = { - "fail2ban/filter.d/cross-seed.conf".text = '' - [Definition] - failregex = ^.*Unauthorized API access attempt to .* from $ - journalmatch = _SYSTEMD_UNIT=cross-seed.service - ''; - }; - }; -} diff --git a/modules/nixos/services/servarr/default.nix b/modules/nixos/services/servarr/default.nix deleted file mode 100644 index dca57cf..0000000 --- a/modules/nixos/services/servarr/default.nix +++ /dev/null @@ -1,23 +0,0 @@ -# The total autonomous media delivery system. -# Relevant link [1]. -# -# [1]: https://youtu.be/I26Ql-uX6AM -{ lib, ... }: -{ - imports = [ - ./autobrr.nix - ./bazarr.nix - ./cross-seed.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 = { - enableAll = lib.mkEnableOption "media automation suite"; - }; -} diff --git a/modules/nixos/services/servarr/jackett.nix b/modules/nixos/services/servarr/jackett.nix deleted file mode 100644 index 481cd3d..0000000 --- a/modules/nixos/services/servarr/jackett.nix +++ /dev/null @@ -1,41 +0,0 @@ -{ 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 deleted file mode 100644 index 7b63986..0000000 --- a/modules/nixos/services/servarr/nzbhydra.nix +++ /dev/null @@ -1,26 +0,0 @@ -{ 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 deleted file mode 100644 index ce044c6..0000000 --- a/modules/nixos/services/servarr/prowlarr.nix +++ /dev/null @@ -1,53 +0,0 @@ -# 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 deleted file mode 100644 index 2bf7c11..0000000 --- a/modules/nixos/services/servarr/starr.nix +++ /dev/null @@ -1,64 +0,0 @@ -# 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/modules/nixos/services/tandoor-recipes/default.nix b/modules/nixos/services/tandoor-recipes/default.nix index 4b4ed1a..f5dc2db 100644 --- a/modules/nixos/services/tandoor-recipes/default.nix +++ b/modules/nixos/services/tandoor-recipes/default.nix @@ -26,16 +26,18 @@ in services.tandoor-recipes = { enable = true; - database = { - createLocally = true; - }; - port = cfg.port; extraConfig = let tandoorRecipesDomain = "recipes.${config.networking.domain}"; in { + # Use PostgreSQL + DB_ENGINE = "django.db.backends.postgresql"; + POSTGRES_HOST = "/run/postgresql"; + POSTGRES_USER = "tandoor_recipes"; + POSTGRES_DB = "tandoor_recipes"; + # Security settings ALLOWED_HOSTS = tandoorRecipesDomain; CSRF_TRUSTED_ORIGINS = "https://${tandoorRecipesDomain}"; @@ -47,25 +49,31 @@ in systemd.services = { tandoor-recipes = { + after = [ "postgresql.service" ]; + requires = [ "postgresql.service" ]; + serviceConfig = { EnvironmentFile = cfg.secretKeyFile; }; }; }; + # Set-up database + services.postgresql = { + enable = true; + ensureDatabases = [ "tandoor_recipes" ]; + ensureUsers = [ + { + name = "tandoor_recipes"; + ensureDBOwnership = true; + } + ]; + }; + my.services.nginx.virtualHosts = { recipes = { inherit (cfg) port; - - extraConfig = { - # Allow bulk upload of recipes for import/export - locations."/".extraConfig = '' - client_max_body_size 0; - ''; - }; }; }; - - # NOTE: unfortunately tandoor-recipes does not log connection failures for fail2ban }; } diff --git a/modules/nixos/services/thelounge/default.nix b/modules/nixos/services/thelounge/default.nix deleted file mode 100644 index e224839..0000000 --- a/modules/nixos/services/thelounge/default.nix +++ /dev/null @@ -1,59 +0,0 @@ -# Web IRC client -{ config, lib, ... }: -let - cfg = config.my.services.thelounge; -in -{ - options.my.services.thelounge = with lib; { - enable = mkEnableOption "The Lounge, a self-hosted web IRC client"; - - port = mkOption { - type = types.port; - default = 9050; - example = 4242; - description = "The port on which The Lounge will listen for incoming HTTP traffic."; - }; - }; - - config = lib.mkIf cfg.enable { - services.thelounge = { - enable = true; - inherit (cfg) port; - - extraConfig = { - reverseProxy = true; - }; - }; - - my.services.nginx.virtualHosts = { - irc = { - inherit (cfg) port; - # Proxy websockets for RPC - websocketsLocations = [ "/" ]; - - extraConfig = { - locations."/".extraConfig = '' - proxy_read_timeout 1d; - ''; - }; - }; - }; - - services.fail2ban.jails = { - thelounge = '' - enabled = true - filter = thelounge - port = http,https - ''; - }; - - environment.etc = { - "fail2ban/filter.d/thelounge.conf".text = '' - [Definition] - failregex = Authentication failed for user .* from $ - Authentication for non existing user attempted from $ - journalmatch = _SYSTEMD_UNIT=thelounge.service - ''; - }; - }; -} diff --git a/modules/nixos/services/transmission/default.nix b/modules/nixos/services/transmission/default.nix index 6a7fbc7..aeb88b7 100644 --- a/modules/nixos/services/transmission/default.nix +++ b/modules/nixos/services/transmission/default.nix @@ -47,7 +47,6 @@ in enable = true; package = pkgs.transmission_4; group = "media"; - webHome = pkgs.trgui-ng-web; downloadDirPermissions = "775"; @@ -66,19 +65,13 @@ in # Proxied behind Nginx. rpc-whitelist-enabled = true; rpc-whitelist = "127.0.0.1"; - - umask = "002"; # To go with `downloadDirPermissions` }; }; + # Transmission wants to eat *all* my RAM if left to its own devices systemd.services.transmission = { serviceConfig = { - # Transmission wants to eat *all* my RAM if left to its own devices MemoryMax = "33%"; - # Avoid errors due to high number of open files. - LimitNOFILE = 1048576; - # Longer stop timeout to finish all torrents - TimeoutStopSec = "5m"; }; }; @@ -97,7 +90,5 @@ in allowedTCPPorts = [ cfg.peerPort ]; allowedUDPPorts = [ cfg.peerPort ]; }; - - # NOTE: unfortunately transmission does not log connection failures for fail2ban }; } diff --git a/modules/nixos/services/vikunja/default.nix b/modules/nixos/services/vikunja/default.nix index 2753da3..6e7700f 100644 --- a/modules/nixos/services/vikunja/default.nix +++ b/modules/nixos/services/vikunja/default.nix @@ -41,7 +41,7 @@ in service = { # Only allow registration of users through the CLI enableregistration = false; - # Use the host's timezone + # Ues the host's timezone timezone = config.time.timeZone; # Use UNIX socket for serving the API unixsocket = socketPath; @@ -99,7 +99,5 @@ in config.services.vikunja.settings.files.basepath ]; }; - - # NOTE: unfortunately vikunja does not log connection failures for fail2ban }; } diff --git a/modules/nixos/services/wireguard/default.nix b/modules/nixos/services/wireguard/default.nix index 840ac33..a76e424 100644 --- a/modules/nixos/services/wireguard/default.nix +++ b/modules/nixos/services/wireguard/default.nix @@ -206,7 +206,7 @@ in ]; } - # Additional interface is only used to get access to "LAN" from wireguard + # Additional inteface is only used to get access to "LAN" from wireguard (lib.mkIf cfg.internal.enable { networking.wg-quick.interfaces."${cfg.internal.name}" = mkInterface [ "${cfg.net.v4.subnet}.0/${toString cfg.net.v4.mask}" diff --git a/modules/nixos/services/woodpecker/agent-exec/default.nix b/modules/nixos/services/woodpecker/agent-exec/default.nix index 24161b0..7ae21c8 100644 --- a/modules/nixos/services/woodpecker/agent-exec/default.nix +++ b/modules/nixos/services/woodpecker/agent-exec/default.nix @@ -44,8 +44,6 @@ in serviceConfig = { # Same option as upstream, without @setuid SystemCallFilter = lib.mkForce "~@clock @privileged @cpu-emulation @debug @keyring @module @mount @obsolete @raw-io @reboot @swap"; - # NodeJS requires RWX memory... - MemoryDenyWriteExecute = lib.mkForce false; BindPaths = [ "/nix/var/nix/daemon-socket/socket" diff --git a/modules/nixos/services/woodpecker/server/default.nix b/modules/nixos/services/woodpecker/server/default.nix index caf0179..adf533e 100644 --- a/modules/nixos/services/woodpecker/server/default.nix +++ b/modules/nixos/services/woodpecker/server/default.nix @@ -24,8 +24,8 @@ in }; systemd.services.woodpecker-server = { - after = [ "postgresql.target" ]; - requires = [ "postgresql.target" ]; + after = [ "postgresql.service" ]; + requires = [ "postgresql.service" ]; serviceConfig = { # Set username for DB access diff --git a/modules/nixos/system/nix/default.nix b/modules/nixos/system/nix/default.nix index 12a395e..ad13539 100644 --- a/modules/nixos/system/nix/default.nix +++ b/modules/nixos/system/nix/default.nix @@ -22,10 +22,6 @@ in options.my.system.nix = with lib; { enable = my.mkDisableOption "nix configuration"; - gc = { - enable = my.mkDisableOption "nix GC configuration"; - }; - cache = { selfHosted = my.mkDisableOption "self-hosted cache"; }; @@ -66,22 +62,6 @@ in }; } - (lib.mkIf cfg.gc.enable { - nix.gc = { - automatic = true; - - # Every week, with some wiggle room - dates = "weekly"; - randomizedDelaySec = "10min"; - - # Use a persistent timer for e.g: laptops - persistent = true; - - # Delete old profiles automatically after 15 days - options = "--delete-older-than 15d"; - }; - }) - (lib.mkIf cfg.cache.selfHosted { nix = { settings = { diff --git a/modules/nixos/system/packages/default.nix b/modules/nixos/system/packages/default.nix index 6a78ff6..5c29aa0 100644 --- a/modules/nixos/system/packages/default.nix +++ b/modules/nixos/system/packages/default.nix @@ -1,5 +1,5 @@ # Common packages -{ config, lib, ... }: +{ config, lib, pkgs, ... }: let cfg = config.my.system.packages; in @@ -13,11 +13,13 @@ in }; config = lib.mkIf cfg.enable { + environment.systemPackages = with pkgs; [ + vim + wget + ]; + programs = { - vim = { - enable = true; - defaultEditor = true; # Modal editing is life - }; + vim.defaultEditor = true; # Modal editing is life zsh = { enable = true; # Use integrations diff --git a/overlays/downgrade-transmission/default.nix b/overlays/downgrade-transmission/default.nix deleted file mode 100644 index 9d3fc8a..0000000 --- a/overlays/downgrade-transmission/default.nix +++ /dev/null @@ -1,14 +0,0 @@ -self: prev: -{ - transmission_4 = prev.transmission_4.overrideAttrs (_: { - version = "4.0.5"; - - src = self.fetchFromGitHub { - owner = "transmission"; - repo = "transmission"; - rev = "4.0.5"; - hash = "sha256-gd1LGAhMuSyC/19wxkoE2mqVozjGPfupIPGojKY0Hn4="; - fetchSubmodules = true; - }; - }); -} diff --git a/overlays/gruvbox-nvim-better-diff/colours.patch b/overlays/gruvbox-nvim-better-diff/colours.patch new file mode 100644 index 0000000..5b0d61a --- /dev/null +++ b/overlays/gruvbox-nvim-better-diff/colours.patch @@ -0,0 +1,28 @@ +From 416b3c9c5e783d173ac0fd5310a76c1b144b92c1 Mon Sep 17 00:00:00 2001 +From: eeeXun +Date: Thu, 19 Oct 2023 02:34:12 +0800 +Subject: Use better diff colours + +--- + README.md | 3 ++- + lua/gruvbox.lua | 7 ++++--- + 2 files changed, 6 insertions(+), 4 deletions(-) + +diff --git a/lua/gruvbox.lua b/lua/gruvbox.lua +index ceba0735..a319fc6a 100644 +--- a/lua/gruvbox.lua ++++ b/lua/gruvbox.lua +@@ -360,9 +361,9 @@ local function get_groups() + PmenuSel = { fg = colors.bg2, bg = colors.blue, bold = config.bold }, + PmenuSbar = { bg = colors.bg2 }, + PmenuThumb = { bg = colors.bg4 }, +- DiffDelete = { bg = colors.dark_red }, +- DiffAdd = { bg = colors.dark_green }, +- DiffChange = { bg = colors.dark_aqua }, +- DiffText = { bg = colors.yellow, fg = colors.bg0 }, ++ DiffDelete = { fg = colors.red }, ++ DiffAdd = { fg = colors.green }, ++ DiffChange = { fg = colors.aqua }, ++ DiffText = { fg = colors.yellow, bg = colors.bg0 }, + SpellCap = { link = "GruvboxBlueUnderline" }, + SpellBad = { link = "GruvboxRedUnderline" }, diff --git a/overlays/gruvbox-nvin-expose-palette/default.nix b/overlays/gruvbox-nvim-better-diff/default.nix similarity index 100% rename from overlays/gruvbox-nvin-expose-palette/default.nix rename to overlays/gruvbox-nvim-better-diff/default.nix diff --git a/overlays/gruvbox-nvim-better-diff/generated.nix b/overlays/gruvbox-nvim-better-diff/generated.nix new file mode 100644 index 0000000..82a18c2 --- /dev/null +++ b/overlays/gruvbox-nvim-better-diff/generated.nix @@ -0,0 +1,10 @@ +{ ... }: + +_final: prev: { + gruvbox-nvim = prev.gruvbox-nvim.overrideAttrs (oa: { + patches = (oa.patches or [ ]) ++ [ + # Inspired by https://github.com/ellisonleao/gruvbox.nvim/pull/291 + ./colours.patch + ]; + }); +} diff --git a/overlays/gruvbox-nvin-expose-palette/generated.nix b/overlays/gruvbox-nvin-expose-palette/generated.nix deleted file mode 100644 index c52ad04..0000000 --- a/overlays/gruvbox-nvin-expose-palette/generated.nix +++ /dev/null @@ -1,14 +0,0 @@ -{ fetchpatch, ... }: - -_final: prev: { - gruvbox-nvim = prev.gruvbox-nvim.overrideAttrs (oa: { - patches = (oa.patches or [ ]) ++ [ - # https://github.com/ellisonleao/gruvbox.nvim/pull/319 - (fetchpatch { - name = "expose-color-palette.patch"; - url = "https://github.com/ellisonleao/gruvbox.nvim/commit/07a493ba4f8b650aab9ed9e486caa89822be0996.patch"; - hash = "sha256-iGwt8qIHe2vaiAUcpaUxyGlM472F89vobTdQ7CF/H70="; - }) - ]; - }); -} diff --git a/pkgs/bt-migrate/default.nix b/pkgs/bt-migrate/default.nix new file mode 100644 index 0000000..df99c55 --- /dev/null +++ b/pkgs/bt-migrate/default.nix @@ -0,0 +1,61 @@ +{ lib +, boost +, cmake +, cxxopts +, digestpp +, fetchFromGitHub +, fmt +, jsoncons +, pugixml +, sqlite_orm +, stdenv +}: +stdenv.mkDerivation { + pname = "bt-migrate"; + version = "0-unstable-2023-08-17"; + + src = fetchFromGitHub { + owner = "mikedld"; + repo = "bt-migrate"; + rev = "e15a489c0c76f98355586ebbee08223af4e9bf50"; + hash = "sha256-kA6yxhbIh3ThmgF8Zyoe3I79giLVmdNr9IIrw5Xx4s0="; + }; + + nativeBuildInputs = [ + cmake + ]; + + buildInputs = [ + boost + cxxopts + fmt + jsoncons + pugixml + sqlite_orm + ]; + + cmakeFlags = [ + (lib.strings.cmakeBool "USE_VCPKG" false) + # NOTE: digestpp does not have proper CMake packaging (yet?) + (lib.strings.cmakeBool "USE_FETCHCONTENT" true) + (lib.strings.cmakeFeature "FETCHCONTENT_SOURCE_DIR_DIGESTPP" "${digestpp}/include/digestpp") + ]; + + # NOTE: no install target in CMake... + installPhase = '' + runHook preInstall + + mkdir -p $out/bin + cp BtMigrate $out/bin + + runHook postInstall + ''; + + meta = with lib; { + description = "Torrent state migration tool"; + homepage = "https://github.com/mikedld/bt-migrate"; + license = licenses.gpl3Only; + maintainers = with maintainers; [ ambroisie ]; + mainProgram = "BtMigrate"; + }; +} diff --git a/pkgs/bw-pass/bw-pass b/pkgs/bw-pass/bw-pass index 0e974b7..124714a 100755 --- a/pkgs/bw-pass/bw-pass +++ b/pkgs/bw-pass/bw-pass @@ -66,7 +66,7 @@ query_password() { printf '%s\n' "$PASSWORD" } -if [ $# -lt 1 ] || [ $# -gt 2 ]; then +if [ $# -lt 1 ] || [ $# -gt 2 ]; then usage exit 1 fi diff --git a/pkgs/change-audio/change-audio b/pkgs/change-audio/change-audio index 5a1fb9c..612fecf 100755 --- a/pkgs/change-audio/change-audio +++ b/pkgs/change-audio/change-audio @@ -62,7 +62,7 @@ do_toggle() { } case "$1" in - up | down) + up|down) do_change_volume "$@" ;; toggle) diff --git a/pkgs/comma/comma b/pkgs/comma/comma index b03a7f2..4367a26 100755 --- a/pkgs/comma/comma +++ b/pkgs/comma/comma @@ -12,9 +12,9 @@ usage() { find_program() { local CANDIDATE - CANDIDATE="$(nix-locate --minimal --at-root --whole-name "/bin/$1")" + CANDIDATE="$(nix-locate --top-level --minimal --at-root --whole-name "/bin/$1")" if [ "$(printf '%s\n' "$CANDIDATE" | wc -l)" -gt 1 ]; then - CANDIDATE="$(printf '%s' "$CANDIDATE" | "${COMMA_PICKER:-fzf-tmux}")" + CANDIDATE="$(printf '%s' "$CANDIDATE" | fzf-tmux)" fi printf '%s' "$CANDIDATE" } diff --git a/pkgs/default.nix b/pkgs/default.nix index 6b7fce1..e82a90c 100644 --- a/pkgs/default.nix +++ b/pkgs/default.nix @@ -1,5 +1,7 @@ { pkgs }: pkgs.lib.makeScope pkgs.newScope (pkgs: { + bt-migrate = pkgs.callPackage ./bt-migrate { }; + bw-pass = pkgs.callPackage ./bw-pass { }; change-audio = pkgs.callPackage ./change-audio { }; @@ -10,6 +12,8 @@ pkgs.lib.makeScope pkgs.newScope (pkgs: { diff-flake = pkgs.callPackage ./diff-flake { }; + digestpp = pkgs.callPackage ./digestpp { }; + dragger = pkgs.callPackage ./dragger { }; drone-rsync = pkgs.callPackage ./drone-rsync { }; @@ -26,6 +30,8 @@ pkgs.lib.makeScope pkgs.newScope (pkgs: { rbw-pass = pkgs.callPackage ./rbw-pass { }; + sqlite_orm = pkgs.callPackage ./sqlite_orm { }; + unbound-zones-adblock = pkgs.callPackage ./unbound-zones-adblock { }; zsh-done = pkgs.callPackage ./zsh-done { }; diff --git a/pkgs/diff-flake/diff-flake b/pkgs/diff-flake/diff-flake index a2a3513..0572b4e 100755 --- a/pkgs/diff-flake/diff-flake +++ b/pkgs/diff-flake/diff-flake @@ -81,23 +81,23 @@ parse_args() { shift case "$opt" in - -h | --help) + -h|--help) usage exit ;; - -f | --flake-output) + -f|--flake-output) FLAKE_OUTPUTS+=("$1") shift ;; - -o | --output) + -o|--output) OUTPUT_FILE="$1" shift ;; - -n | --new-rev) + -n|--new-rev) NEW_REV="$(git rev-parse "$1")" shift ;; - -p | --previous-rev) + -p|--previous-rev) PREVIOUS_REV="$(git rev-parse "$1")" shift ;; @@ -157,7 +157,7 @@ list_dev_shells() { } diff_output() { - local PREV NEW + local PREV NEW; PREV="$(mktemp --dry-run)" NEW="$(mktemp --dry-run)" @@ -169,7 +169,7 @@ diff_output() { printf 'Closure diff for `%s`:\n```\n' "$1" nix store diff-closures "$PREV" "$NEW" | sanitize_output printf '```\n\n' - } >>"$OUTPUT_FILE" + } >> "$OUTPUT_FILE" } parse_args "$@" diff --git a/pkgs/digestpp/default.nix b/pkgs/digestpp/default.nix new file mode 100644 index 0000000..2fd90db --- /dev/null +++ b/pkgs/digestpp/default.nix @@ -0,0 +1,31 @@ +{ lib +, fetchFromGitHub +, stdenv +}: +stdenv.mkDerivation { + pname = "digestpp"; + version = "0-unstable-2023-11-07"; + + src = fetchFromGitHub { + owner = "kerukuro"; + repo = "digestpp"; + rev = "ebb699402c244e22c3aff61d2239bcb2e87b8ef8"; + hash = "sha256-9X/P7DgZB6bSYjQWRli4iAXEFjhmACOVv3EYQrXuH5c="; + }; + + installPhase = '' + runHook preInstall + + mkdir -p $out/include/digestpp + cp -r *.hpp algorithm/ detail/ $out/include/digestpp + + runHook postInstall + ''; + + meta = with lib; { + description = "C++11 header-only message digest library"; + homepage = "https://github.com/kerukuro/digestpp"; + license = licenses.unlicense; + maintainers = with maintainers; [ ambroisie ]; + }; +} diff --git a/pkgs/lohr/default.nix b/pkgs/lohr/default.nix index d8545e0..ddeac7a 100644 --- a/pkgs/lohr/default.nix +++ b/pkgs/lohr/default.nix @@ -1,16 +1,16 @@ { lib, fetchFromGitHub, rustPlatform }: rustPlatform.buildRustPackage rec { pname = "lohr"; - version = "0.4.6"; + version = "0.4.5"; src = fetchFromGitHub { owner = "alarsyo"; repo = "lohr"; rev = "v${version}"; - hash = "sha256-dunQgtap+XCK5LoSyOqIY/6p6HizBeiyPWNuCffwjDU="; + hash = "sha256-p6E/r+OxFTpxDpOKSlacOxvRLfHSKg1mHNAfTytfqDY="; }; - cargoHash = "sha256-R3/N/43+bGx6acE/rhBcrk6kS5zQu8NJ1sVvKJJkK9w="; + cargoHash = "sha256-hext0S0o9D9pN9epzXtD5dwAYMPCLpBBOBT4FX0mTMk="; meta = with lib; { description = "Git mirroring daemon"; diff --git a/pkgs/osc52/osc52 b/pkgs/osc52/osc52 index de3a982..f64ccb6 100755 --- a/pkgs/osc52/osc52 +++ b/pkgs/osc52/osc52 @@ -15,7 +15,7 @@ usage() { exec 1>&2 fi - cat <&2 fi - cat < Send a notification (title and message) to the host system using the OSC 777 escape sequence: diff --git a/pkgs/sqlite_orm/default.nix b/pkgs/sqlite_orm/default.nix new file mode 100644 index 0000000..3891eee --- /dev/null +++ b/pkgs/sqlite_orm/default.nix @@ -0,0 +1,32 @@ +{ lib +, cmake +, fetchFromGitHub +, sqlite +, stdenv +}: +stdenv.mkDerivation (finalAttrs: { + pname = "sqlite_orm"; + version = "1.8.2"; + + src = fetchFromGitHub { + owner = "fnc12"; + repo = "sqlite_orm"; + rev = "v${finalAttrs.version}"; + hash = "sha256-KqphGFcnR1Y11KqL7sxODSv7lEvcURdF6kLd3cg84kc="; + }; + + nativeBuildInputs = [ + cmake + ]; + + propagatedBuildInputs = [ + sqlite + ]; + + meta = with lib; { + description = "Light header only SQLite ORM"; + homepage = "https://sqliteorm.com/"; + license = licenses.agpl3Only; # MIT license is commercial + maintainers = with maintainers; [ ambroisie ]; + }; +}) diff --git a/pkgs/unbound-zones-adblock/default.nix b/pkgs/unbound-zones-adblock/default.nix index 11a6c90..642ac41 100644 --- a/pkgs/unbound-zones-adblock/default.nix +++ b/pkgs/unbound-zones-adblock/default.nix @@ -1,7 +1,7 @@ { lib, gawk, stdenvNoCC, stevenblack-blocklist }: stdenvNoCC.mkDerivation { name = "unbound-zones-adblock"; - inherit (stevenblack-blocklist) version; + version = stevenblack-blocklist.rev; src = stevenblack-blocklist; @@ -30,7 +30,7 @@ stdenvNoCC.mkDerivation { description = "Unified host lists, ready to be used by unbound"; longDescription = '' This is a simple derivation based on StevenBlack's unified hosts list. - The files have been modified for easy use with unbound. + The files have been modified for easy use wih unbound. ''; homepage = "https://github.com/StevenBlack/hosts"; license = licenses.mit; diff --git a/pkgs/zsh-done/default.nix b/pkgs/zsh-done/default.nix index 8fac813..bdb6af3 100644 --- a/pkgs/zsh-done/default.nix +++ b/pkgs/zsh-done/default.nix @@ -26,7 +26,7 @@ stdenvNoCC.mkDerivation rec { description = '' A zsh plug-in to receive notifications when long processes finish ''; - homepage = "https://git.belanyi.fr/ambroisie/zsh-done"; + homepage = "https://gitea.belanyi.fr/ambroisie/zsh-done"; license = licenses.mit; platforms = platforms.unix; maintainers = with maintainers; [ ambroisie ]; diff --git a/templates/c++-cmake/.envrc b/templates/c++-cmake/.envrc old mode 100755 new mode 100644 index 390d06d..de77fcb --- a/templates/c++-cmake/.envrc +++ b/templates/c++-cmake/.envrc @@ -1,4 +1,3 @@ -# 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 diff --git a/templates/c++-cmake/.woodpecker/check.yml b/templates/c++-cmake/.woodpecker/check.yml index 272c0e4..9135f7b 100644 --- a/templates/c++-cmake/.woodpecker/check.yml +++ b/templates/c++-cmake/.woodpecker/check.yml @@ -12,19 +12,19 @@ steps: commands: - nix flake check -- name: notify +- name: notifiy image: bash - environment: - ADDRESS: - from_secret: matrix_homeserver - ROOM: - from_secret: matrix_roomid - USER: - from_secret: matrix_username - PASS: - from_secret: matrix_password + secrets: + - source: matrix_homeserver + target: address + - source: matrix_roomid + target: room + - source: matrix_username + target: user + - source: matrix_password + target: pass commands: - - nix run github:ambroisie/matrix-notifier + - nix run '.#matrix-notifier' when: status: - failure diff --git a/templates/c++-cmake/flake.nix b/templates/c++-cmake/flake.nix index 7796f5e..cb468e7 100644 --- a/templates/c++-cmake/flake.nix +++ b/templates/c++-cmake/flake.nix @@ -16,18 +16,19 @@ ref = "nixos-unstable"; }; - git-hooks = { + pre-commit-hooks = { type = "github"; owner = "cachix"; - repo = "git-hooks.nix"; + repo = "pre-commit-hooks.nix"; ref = "master"; inputs = { + flake-utils.follows = "futils"; nixpkgs.follows = "nixpkgs"; }; }; }; - outputs = { self, futils, nixpkgs, git-hooks }: + outputs = { self, futils, nixpkgs, pre-commit-hooks }: { overlays = { default = final: _prev: { @@ -51,7 +52,7 @@ meta = with lib; { description = "A C++ project"; - homepage = "https://git.belanyi.fr/ambroisie/project"; + homepage = "https://gitea.belanyi.fr/ambroisie/project"; license = licenses.mit; maintainers = with maintainers; [ ambroisie ]; platforms = platforms.unix; @@ -68,7 +69,7 @@ ]; }; - pre-commit = git-hooks.lib.${system}.run { + pre-commit = pre-commit-hooks.lib.${system}.run { src = self; hooks = { @@ -91,12 +92,12 @@ devShells = { default = pkgs.mkShell { - inputsFrom = [ - self.packages.${system}.project + inputsFrom = with self.packages.${system}; [ + project ]; packages = with pkgs; [ - self.checks.${system}.pre-commit.enabledPackages + clang-tools ]; inherit (pre-commit) shellHook; diff --git a/templates/c++-meson/.envrc b/templates/c++-meson/.envrc index 390d06d..de77fcb 100644 --- a/templates/c++-meson/.envrc +++ b/templates/c++-meson/.envrc @@ -1,4 +1,3 @@ -# 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 diff --git a/templates/c++-meson/.woodpecker/check.yml b/templates/c++-meson/.woodpecker/check.yml index 272c0e4..9135f7b 100644 --- a/templates/c++-meson/.woodpecker/check.yml +++ b/templates/c++-meson/.woodpecker/check.yml @@ -12,19 +12,19 @@ steps: commands: - nix flake check -- name: notify +- name: notifiy image: bash - environment: - ADDRESS: - from_secret: matrix_homeserver - ROOM: - from_secret: matrix_roomid - USER: - from_secret: matrix_username - PASS: - from_secret: matrix_password + secrets: + - source: matrix_homeserver + target: address + - source: matrix_roomid + target: room + - source: matrix_username + target: user + - source: matrix_password + target: pass commands: - - nix run github:ambroisie/matrix-notifier + - nix run '.#matrix-notifier' when: status: - failure diff --git a/templates/c++-meson/flake.nix b/templates/c++-meson/flake.nix index cb14eb5..9cfed0d 100644 --- a/templates/c++-meson/flake.nix +++ b/templates/c++-meson/flake.nix @@ -16,18 +16,19 @@ ref = "nixos-unstable"; }; - git-hooks = { + pre-commit-hooks = { type = "github"; owner = "cachix"; - repo = "git-hooks.nix"; + repo = "pre-commit-hooks.nix"; ref = "master"; inputs = { + flake-utils.follows = "futils"; nixpkgs.follows = "nixpkgs"; }; }; }; - outputs = { self, futils, nixpkgs, git-hooks }: + outputs = { self, futils, nixpkgs, pre-commit-hooks }: { overlays = { default = final: _prev: { @@ -51,7 +52,7 @@ meta = with lib; { description = "A C++ project"; - homepage = "https://git.belanyi.fr/ambroisie/project"; + homepage = "https://gitea.belanyi.fr/ambroisie/project"; license = licenses.mit; maintainers = with maintainers; [ ambroisie ]; platforms = platforms.unix; @@ -68,7 +69,7 @@ ]; }; - pre-commit = git-hooks.lib.${system}.run { + pre-commit = pre-commit-hooks.lib.${system}.run { src = self; hooks = { @@ -91,12 +92,12 @@ devShells = { default = pkgs.mkShell { - inputsFrom = [ - self.packages.${system}.project + inputsFrom = with self.packages.${system}; [ + project ]; packages = with pkgs; [ - self.checks.${system}.pre-commit.enabledPackages + clang-tools ]; inherit (pre-commit) shellHook; diff --git a/templates/default.nix b/templates/default.nix index 51864cd..f58fd72 100644 --- a/templates/default.nix +++ b/templates/default.nix @@ -5,14 +5,6 @@ }; "c++-meson" = { 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"; + description = "A C++ project using CMake"; }; } diff --git a/templates/python-uv/.envrc b/templates/python-uv/.envrc deleted file mode 100644 index 390d06d..0000000 --- a/templates/python-uv/.envrc +++ /dev/null @@ -1,6 +0,0 @@ -# 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 deleted file mode 100644 index c79d1e8..0000000 --- a/templates/python-uv/.gitignore +++ /dev/null @@ -1,6 +0,0 @@ -# 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 deleted file mode 100644 index 272c0e4..0000000 --- a/templates/python-uv/.woodpecker/check.yml +++ /dev/null @@ -1,31 +0,0 @@ -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 deleted file mode 100644 index 5059e64..0000000 --- a/templates/python-uv/flake.nix +++ /dev/null @@ -1,112 +0,0 @@ -{ - 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 deleted file mode 100644 index 7b2d896..0000000 --- a/templates/python-uv/pyproject.toml +++ /dev/null @@ -1,17 +0,0 @@ -[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 deleted file mode 100644 index b06117d..0000000 --- a/templates/python-uv/src/project/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -def main() -> None: - print("Hello, world!") diff --git a/templates/rust-cargo/.envrc b/templates/rust-cargo/.envrc deleted file mode 100644 index 390d06d..0000000 --- a/templates/rust-cargo/.envrc +++ /dev/null @@ -1,6 +0,0 @@ -# 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/rust-cargo/.gitignore b/templates/rust-cargo/.gitignore deleted file mode 100644 index 5f360ff..0000000 --- a/templates/rust-cargo/.gitignore +++ /dev/null @@ -1,6 +0,0 @@ -# Rust build directory -/target - -# Nix generated files -/.pre-commit-config.yaml -/result diff --git a/templates/rust-cargo/.woodpecker/check.yml b/templates/rust-cargo/.woodpecker/check.yml deleted file mode 100644 index 272c0e4..0000000 --- a/templates/rust-cargo/.woodpecker/check.yml +++ /dev/null @@ -1,31 +0,0 @@ -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/rust-cargo/Cargo.lock b/templates/rust-cargo/Cargo.lock deleted file mode 100644 index 4f9c86e..0000000 --- a/templates/rust-cargo/Cargo.lock +++ /dev/null @@ -1,7 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "project" -version = "0.0.0" diff --git a/templates/rust-cargo/Cargo.toml b/templates/rust-cargo/Cargo.toml deleted file mode 100644 index 4dfdc0b..0000000 --- a/templates/rust-cargo/Cargo.toml +++ /dev/null @@ -1,8 +0,0 @@ -[package] -name = "project" -version = "0.0.0" -edition = "2021" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] diff --git a/templates/rust-cargo/flake.nix b/templates/rust-cargo/flake.nix deleted file mode 100644 index efd8358..0000000 --- a/templates/rust-cargo/flake.nix +++ /dev/null @@ -1,110 +0,0 @@ -{ - description = "A Rust 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; rustPlatform.buildRustPackage { - pname = "project"; - version = (final.lib.importTOML ./Cargo.toml).package.version; - - src = self; - - cargoLock = { - lockFile = "${self}/Cargo.lock"; - }; - - meta = with lib; { - description = "A Rust 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 = { - clippy = { - enable = true; - settings = { - denyWarnings = true; - }; - }; - - nixpkgs-fmt = { - enable = true; - }; - - rustfmt = { - enable = true; - }; - }; - }; - in - { - checks = { - inherit (self.packages.${system}) project; - }; - - devShells = { - default = pkgs.mkShell { - inputsFrom = [ - self.packages.${system}.project - ]; - - packages = with pkgs; [ - rust-analyzer - self.checks.${system}.pre-commit.enabledPackages - ]; - - RUST_SRC_PATH = "${pkgs.rust.packages.stable.rustPlatform.rustLibSrc}"; - - inherit (pre-commit) shellHook; - }; - }; - - packages = futils.lib.flattenTree { - default = pkgs.project; - inherit (pkgs) project; - }; - }); -} diff --git a/templates/rust-cargo/rustfmt.toml b/templates/rust-cargo/rustfmt.toml deleted file mode 100644 index e69de29..0000000 diff --git a/templates/rust-cargo/src/main.rs b/templates/rust-cargo/src/main.rs deleted file mode 100644 index e7a11a9..0000000 --- a/templates/rust-cargo/src/main.rs +++ /dev/null @@ -1,3 +0,0 @@ -fn main() { - println!("Hello, world!"); -}