diff --git a/.envrc b/.envrc index f5141c2..a6b1f81 100644 --- a/.envrc +++ b/.envrc @@ -1,3 +1,4 @@ +# 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/flake.lock b/flake.lock index 249cddd..8a54c50 100644 --- a/flake.lock +++ b/flake.lock @@ -14,11 +14,11 @@ ] }, "locked": { - "lastModified": 1723293904, - "narHash": "sha256-b+uqzj+Wa6xgMS9aNbX4I+sXeb5biPDi39VgvSFqFvU=", + "lastModified": 1736955230, + "narHash": "sha256-uenf8fv2eG5bKM8C/UvFaiJMZ4IpUFaQxk9OH5t/1gA=", "owner": "ryantm", "repo": "agenix", - "rev": "f6291c5935fdc4e0bef208cfc0dcab7e3f7a1c41", + "rev": "e600439ec4c273cf11e06fe4d9d906fb98fa097c", "type": "github" }, "original": { @@ -73,11 +73,11 @@ ] }, "locked": { - "lastModified": 1727826117, - "narHash": "sha256-K5ZLCyfO/Zj9mPFldf3iwS6oZStJcU4tSpiXTMYaaL0=", + "lastModified": 1743550720, + "narHash": "sha256-hIshGgKZCgWh6AYJpJmRgFdR3WUbkY04o82X05xqQiY=", "owner": "hercules-ci", "repo": "flake-parts", - "rev": "3d04084d54bedc3d6b8b736c70ef449225c361b1", + "rev": "c621e8422220273271f52058f618c94e405bb0f5", "type": "github" }, "original": { @@ -94,11 +94,11 @@ ] }, "locked": { - "lastModified": 1726560853, - "narHash": "sha256-X6rJYSESBVr3hBoH0WbKE5KvhPU5bloyZ2L4K60/fPQ=", + "lastModified": 1731533236, + "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", "owner": "numtide", "repo": "flake-utils", - "rev": "c1dfcf08411b08f6b8615f7d8971a2bfa81d5e8a", + "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", "type": "github" }, "original": { @@ -108,10 +108,33 @@ "type": "github" } }, + "git-hooks": { + "inputs": { + "flake-compat": "flake-compat", + "gitignore": "gitignore", + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1742649964, + "narHash": "sha256-DwOTp7nvfi8mRfuL1escHDXabVXFGT1VlPD1JHrtrco=", + "owner": "cachix", + "repo": "git-hooks.nix", + "rev": "dcf5072734cb576d2b0c59b2ac44f5050b5eac82", + "type": "github" + }, + "original": { + "owner": "cachix", + "ref": "master", + "repo": "git-hooks.nix", + "type": "github" + } + }, "gitignore": { "inputs": { "nixpkgs": [ - "pre-commit-hooks", + "git-hooks", "nixpkgs" ] }, @@ -136,11 +159,11 @@ ] }, "locked": { - "lastModified": 1729864948, - "narHash": "sha256-CeGSqbN6S8JmzYJX/HqZjr7dMGlvHLLnJJarwB45lPs=", + "lastModified": 1743869639, + "narHash": "sha256-Xhe3whfRW/Ay05z9m1EZ1/AkbV1yo0tm1CbgjtCi4rQ=", "owner": "nix-community", "repo": "home-manager", - "rev": "0c0268a3c80d30b989d0aadbd65f38d4fa27a9a0", + "rev": "d094c6763c6ddb860580e7d3b4201f8f496a6836", "type": "github" }, "original": { @@ -150,13 +173,37 @@ "type": "github" } }, + "nixgl": { + "inputs": { + "flake-utils": [ + "futils" + ], + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1713543440, + "narHash": "sha256-lnzZQYG0+EXl/6NkGpyIz+FEOc/DSEG57AP1VsdeNrM=", + "owner": "nix-community", + "repo": "nixGL", + "rev": "310f8e49a149e4c9ea52f1adf70cdc768ec53f8a", + "type": "github" + }, + "original": { + "owner": "nix-community", + "ref": "main", + "repo": "nixGL", + "type": "github" + } + }, "nixpkgs": { "locked": { - "lastModified": 1729665710, - "narHash": "sha256-AlcmCXJZPIlO5dmFzV3V2XF6x/OpNWUV8Y/FMPGd8Z4=", + "lastModified": 1743689281, + "narHash": "sha256-y7Hg5lwWhEOgflEHRfzSH96BOt26LaYfrYWzZ+VoVdg=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "2768c7d042a37de65bb1b5b3268fc987e534c49d", + "rev": "2bfc080955153be0be56724be6fa5477b4eefabb", "type": "github" }, "original": { @@ -167,44 +214,27 @@ } }, "nur": { - "locked": { - "lastModified": 1729868220, - "narHash": "sha256-OxHE1U+FIIaQ50nZpt/VxLH0bokiqsEqAshehlHhOFs=", - "owner": "nix-community", - "repo": "NUR", - "rev": "70b30d23d33ca2acfb267430b08ddf82ff7116b2", - "type": "github" - }, - "original": { - "owner": "nix-community", - "ref": "master", - "repo": "NUR", - "type": "github" - } - }, - "pre-commit-hooks": { "inputs": { - "flake-compat": "flake-compat", - "gitignore": "gitignore", + "flake-parts": [ + "flake-parts" + ], "nixpkgs": [ "nixpkgs" ], - "nixpkgs-stable": [ - "nixpkgs" - ] + "treefmt-nix": "treefmt-nix" }, "locked": { - "lastModified": 1729104314, - "narHash": "sha256-pZRZsq5oCdJt3upZIU4aslS9XwFJ+/nVtALHIciX/BI=", - "owner": "cachix", - "repo": "pre-commit-hooks.nix", - "rev": "3c3e88f0f544d6bb54329832616af7eb971b6be6", + "lastModified": 1741294988, + "narHash": "sha256-3408u6q615kVTb23WtDriHRmCBBpwX7iau6rvfipcu4=", + "owner": "nix-community", + "repo": "NUR", + "rev": "b30c245e2c44c7352a27485bfd5bc483df660f0e", "type": "github" }, "original": { - "owner": "cachix", + "owner": "nix-community", "ref": "master", - "repo": "pre-commit-hooks.nix", + "repo": "NUR", "type": "github" } }, @@ -213,10 +243,11 @@ "agenix": "agenix", "flake-parts": "flake-parts", "futils": "futils", + "git-hooks": "git-hooks", "home-manager": "home-manager", + "nixgl": "nixgl", "nixpkgs": "nixpkgs", "nur": "nur", - "pre-commit-hooks": "pre-commit-hooks", "systems": "systems" } }, @@ -235,6 +266,27 @@ "repo": "default", "type": "github" } + }, + "treefmt-nix": { + "inputs": { + "nixpkgs": [ + "nur", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1733222881, + "narHash": "sha256-JIPcz1PrpXUCbaccEnrcUS8jjEb/1vJbZz5KkobyFdM=", + "owner": "numtide", + "repo": "treefmt-nix", + "rev": "49717b5af6f80172275d47a418c9719a31a78b53", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "treefmt-nix", + "type": "github" + } } }, "root": "root", diff --git a/flake.nix b/flake.nix index a07ee15..403f308 100644 --- a/flake.nix +++ b/flake.nix @@ -43,6 +43,17 @@ }; }; + nixgl = { + type = "github"; + owner = "nix-community"; + repo = "nixGL"; + ref = "main"; + inputs = { + flake-utils.follows = "futils"; + nixpkgs.follows = "nixpkgs"; + }; + }; + nixpkgs = { type = "github"; owner = "NixOS"; @@ -55,16 +66,19 @@ owner = "nix-community"; repo = "NUR"; ref = "master"; + inputs = { + flake-parts.follows = "flake-parts"; + nixpkgs.follows = "nixpkgs"; + }; }; - pre-commit-hooks = { + git-hooks = { type = "github"; owner = "cachix"; - repo = "pre-commit-hooks.nix"; + repo = "git-hooks.nix"; ref = "master"; inputs = { nixpkgs.follows = "nixpkgs"; - nixpkgs-stable.follows = "nixpkgs"; }; }; diff --git a/flake/checks.nix b/flake/checks.nix index 98e49bd..73e64d5 100644 --- a/flake/checks.nix +++ b/flake/checks.nix @@ -1,7 +1,7 @@ { inputs, ... }: { imports = [ - inputs.pre-commit-hooks.flakeModule + inputs.git-hooks.flakeModule ]; perSystem = { ... }: { diff --git a/flake/dev-shells.nix b/flake/dev-shells.nix index d5f5989..87464a4 100644 --- a/flake/dev-shells.nix +++ b/flake/dev-shells.nix @@ -6,7 +6,6 @@ name = "NixOS-config"; nativeBuildInputs = with pkgs; [ - gitAndTools.pre-commit nixpkgs-fmt ]; diff --git a/flake/home-manager.nix b/flake/home-manager.nix index 34af375..093ae8c 100644 --- a/flake/home-manager.nix +++ b/flake/home-manager.nix @@ -3,6 +3,11 @@ let defaultModules = [ # Include generic settings "${self}/modules/home" + { + nixpkgs.overlays = (lib.attrValues self.overlays) ++ [ + inputs.nur.overlays.default + ]; + } { # Basic user information defaults home.username = lib.mkDefault "ambroisie"; @@ -21,18 +26,15 @@ let # * not letting me set `lib` as an extraSpecialArgs # * not respecting `nixpkgs.overlays` [1] # [1]: https://github.com/nix-community/home-manager/issues/2954 - pkgs = import inputs.nixpkgs { - inherit system; - - overlays = (lib.attrValues self.overlays) ++ [ - inputs.nur.overlay - ]; - }; + pkgs = inputs.nixpkgs.legacyPackages.${system}; modules = defaultModules ++ [ "${self}/hosts/homes/${name}" ]; + # Use my extended lib in NixOS configuration + inherit (self) lib; + extraSpecialArgs = { # Inject inputs to use them in global registry inherit inputs; diff --git a/flake/nixos.nix b/flake/nixos.nix index b48b551..bf9eac8 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 "dirty"; + system.configurationRevision = self.rev or self.dirtyRev or "dirty"; } { nixpkgs.overlays = (lib.attrValues self.overlays) ++ [ - inputs.nur.overlay + inputs.nur.overlays.default ]; } # Include generic settings diff --git a/hosts/homes/ambroisie@mousqueton/default.nix b/hosts/homes/ambroisie@mousqueton/default.nix index 44e62e6..37884d7 100644 --- a/hosts/homes/ambroisie@mousqueton/default.nix +++ b/hosts/homes/ambroisie@mousqueton/default.nix @@ -15,6 +15,9 @@ # 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/porthos/secrets/acme/dns-key.age b/hosts/nixos/porthos/secrets/acme/dns-key.age index fce2a84..d7f159e 100644 --- a/hosts/nixos/porthos/secrets/acme/dns-key.age +++ b/hosts/nixos/porthos/secrets/acme/dns-key.age @@ -1,8 +1,9 @@ age-encryption.org/v1 --> 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 +-> 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 diff --git a/hosts/nixos/porthos/secrets/secrets.nix b/hosts/nixos/porthos/secrets/secrets.nix index 68e90f2..425756c 100644 --- a/hosts/nixos/porthos/secrets/secrets.nix +++ b/hosts/nixos/porthos/secrets/secrets.nix @@ -80,6 +80,8 @@ in "pyload/credentials.age".publicKeys = all; + "servarr/autobrr/session-secret.age".publicKeys = all; + "sso/auth-key.age" = { owner = "nginx-sso"; publicKeys = all; diff --git a/hosts/nixos/porthos/secrets/servarr/autobrr/session-secret.age b/hosts/nixos/porthos/secrets/servarr/autobrr/session-secret.age new file mode 100644 index 0000000..e98b94a --- /dev/null +++ b/hosts/nixos/porthos/secrets/servarr/autobrr/session-secret.age @@ -0,0 +1,7 @@ +age-encryption.org/v1 +-> ssh-ed25519 cKojmg bu09lB+fjaPP31cUQZP6EqSPuseucgNK7k9vAS08iS0 ++NGL+b2QD/qGo6hqHvosAXzHZtDvfodmPdcgnrKlD1o +-> ssh-ed25519 jPowng QDCdRBGWhtdvvMCiDH52cZHz1/W7aomhTatZ4+9IKwI +Ou3jjV/O55G1CPgGS33l3eWhhYWrVdwVNPSiE14d5rE +--- q0ssmpG50OX1WaNSInc2hbtH3DbTwQGDU74VGEoMh94 +mCƑ'hK./Xu(g$'M{fK !MZoR՝͟;yb \ No newline at end of file diff --git a/hosts/nixos/porthos/services.nix b/hosts/nixos/porthos/services.nix index a2339f4..784eb31 100644 --- a/hosts/nixos/porthos/services.nix +++ b/hosts/nixos/porthos/services.nix @@ -51,10 +51,6 @@ in passwordFile = secrets."forgejo/mail-password".path; }; }; - # Meta-indexers - indexers = { - prowlarr.enable = true; - }; # Jellyfin media server jellyfin.enable = true; # Gitea mirrorig service @@ -95,6 +91,9 @@ in nextcloud = { enable = true; passwordFile = secrets."nextcloud/password".path; + collabora = { + enable = true; + }; }; nix-cache = { enable = true; @@ -141,19 +140,24 @@ in sabnzbd.enable = true; # The whole *arr software suite servarr = { - enable = true; + enableAll = true; + autobrr = { + sessionSecretFile = secrets."servarr/autobrr/session-secret".path; + }; # ... But not Lidarr because I don't care for music that much lidarr = { enable = false; }; + # I only use Prowlarr nowadays + jackett = { + enable = false; + }; + nzbhydra = { + enable = false; + }; }; # Because I still need to play sysadmin ssh-server.enable = true; - # 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/default.nix b/modules/home/default.nix index c8183cf..dd3e3cb 100644 --- a/modules/home/default.nix +++ b/modules/home/default.nix @@ -27,6 +27,7 @@ ./mail ./mpv ./nix + ./nix-gl ./nix-index ./nixpkgs ./nm-applet diff --git a/modules/home/direnv/lib/python.sh b/modules/home/direnv/lib/python.sh index 780fbe6..b4b2bce 100644 --- a/modules/home/direnv/lib/python.sh +++ b/modules/home/direnv/lib/python.sh @@ -53,4 +53,5 @@ layout_uv() { PATH_add "$VIRTUAL_ENV/bin" watch_file pyproject.toml watch_file uv.lock + watch_file .python-version } diff --git a/modules/home/firefox/default.nix b/modules/home/firefox/default.nix index 02c74f2..6346dc9 100644 --- a/modules/home/firefox/default.nix +++ b/modules/home/firefox/default.nix @@ -61,19 +61,21 @@ in "ui.systemUsesDarkTheme" = true; # Dark mode }; - 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 - ); + 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 + ); + }; }; }; }; diff --git a/modules/home/git/default.nix b/modules/home/git/default.nix index 1bb2215..c88008f 100644 --- a/modules/home/git/default.nix +++ b/modules/home/git/default.nix @@ -123,11 +123,6 @@ in defaultBranch = "main"; }; - # Local configuration, not-versioned - include = { - path = "config.local"; - }; - merge = { conflictStyle = "zdiff3"; }; @@ -167,8 +162,8 @@ in }; }; - # Multiple identities - includes = [ + includes = lib.mkAfter [ + # Multiple identities { condition = "gitdir:~/git/EPITA/"; contents = { @@ -187,6 +182,10 @@ in }; }; } + # Local configuration, not-versioned + { + path = "config.local"; + } ]; ignores = diff --git a/modules/home/jq/default.nix b/modules/home/jq/default.nix index 57e266f..53e5986 100644 --- a/modules/home/jq/default.nix +++ b/modules/home/jq/default.nix @@ -17,6 +17,7 @@ in strings = "0;32"; arrays = "1;39"; objects = "1;39"; + objectKeys = "1;34"; }; }; } diff --git a/modules/home/mail/accounts/default.nix b/modules/home/mail/accounts/default.nix index 202b9bc..5216ad5 100644 --- a/modules/home/mail/accounts/default.nix +++ b/modules/home/mail/accounts/default.nix @@ -26,20 +26,7 @@ let }; migaduConfig = { - imap = { - host = "imap.migadu.com"; - port = 993; - tls = { - enable = true; - }; - }; - smtp = { - host = "smtp.migadu.com"; - port = 465; - tls = { - enable = true; - }; - }; + flavor = "migadu.com"; }; gmailConfig = { diff --git a/modules/home/nix-gl/default.nix b/modules/home/nix-gl/default.nix new file mode 100644 index 0000000..0f261f9 --- /dev/null +++ b/modules/home/nix-gl/default.nix @@ -0,0 +1,21 @@ +{ config, inputs, lib, ... }: +let + cfg = config.my.home.nix-gl; +in +{ + options.my.home.nix-gl = with lib; { + enable = mkEnableOption "nixGL configuration"; + }; + + config = lib.mkIf cfg.enable (lib.mkMerge [ + { + nixGL = { + inherit (inputs.nixgl) packages; + + defaultWrapper = "mesa"; + + installScripts = [ "mesa" ]; + }; + } + ]); +} diff --git a/modules/home/packages/default.nix b/modules/home/packages/default.nix index 1362a06..43f7111 100644 --- a/modules/home/packages/default.nix +++ b/modules/home/packages/default.nix @@ -1,6 +1,7 @@ -{ config, lib, pkgs, ... }: +{ config, lib, pkgs, osConfig, ... }: let cfg = config.my.home.packages; + useGlobalPkgs = osConfig.home-manager.useGlobalPkgs or false; in { options.my.home.packages = with lib; { @@ -26,9 +27,10 @@ in fd file ripgrep + tree ] ++ cfg.additionalPackages); - nixpkgs.config = { + nixpkgs.config = lib.mkIf (!useGlobalPkgs) { inherit (cfg) allowAliases allowUnfree; }; }; diff --git a/modules/home/pager/default.nix b/modules/home/pager/default.nix index 1119440..e84dcb7 100644 --- a/modules/home/pager/default.nix +++ b/modules/home/pager/default.nix @@ -16,7 +16,11 @@ in LESS = "-R -+X -c"; # Better XDG compliance LESSHISTFILE = "${config.xdg.stateHome}/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 1d36ccd..3e8bb5a 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 f474342..27cdb4e 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/tmux/default.nix b/modules/home/tmux/default.nix index 71ce4ca..08b9202 100644 --- a/modules/home/tmux/default.nix +++ b/modules/home/tmux/default.nix @@ -20,6 +20,8 @@ in enablePassthrough = mkEnableOption "tmux DCS passthrough sequence"; + enableResurrect = mkEnableOption "tmux-resurrect plugin"; + terminalFeatures = mkOption { type = with types; attrsOf (submodule { options = { @@ -47,9 +49,12 @@ in clock24 = true; # I'm one of those heathens escapeTime = 0; # Let vim do its thing instead historyLimit = 100000; # Bigger buffer + mouse = false; # I dislike mouse support + focusEvents = true; # Report focus events terminal = "tmux-256color"; # I want accurate termcap info + aggressiveResize = true; # Automatic resize when switching client size - plugins = with pkgs.tmuxPlugins; [ + plugins = with pkgs.tmuxPlugins; builtins.filter (attr: attr != { }) [ # Open high-lighted files in copy mode open # Better pane management @@ -77,9 +82,23 @@ 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 ${ diff --git a/modules/home/vim/after/ftplugin/query.vim b/modules/home/vim/after/ftplugin/query.vim new file mode 100644 index 0000000..fd2ac73 --- /dev/null +++ b/modules/home/vim/after/ftplugin/query.vim @@ -0,0 +1,6 @@ +" 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/unimpaired.lua b/modules/home/vim/after/plugin/mappings/unimpaired.lua index 82aab05..765b6b1 100644 --- a/modules/home/vim/after/plugin/mappings/unimpaired.lua +++ b/modules/home/vim/after/plugin/mappings/unimpaired.lua @@ -31,8 +31,6 @@ local keys = { { "[u", desc = "URL encode" }, { "[x", desc = "XML encode" }, { "[y", desc = "C string encode" }, - -- Custom - { "[d", lsp.goto_prev_diagnostic, desc = "Previous diagnostic" }, -- Next { "]", group = "Next" }, @@ -62,8 +60,6 @@ local keys = { { "]u", desc = "URL decode" }, { "]x", desc = "XML decode" }, { "]y", desc = "C string decode" }, - -- Custom - { "]d", lsp.goto_next_diagnostic, desc = "Next diagnostic" }, -- Enable option { "[o", group = "Enable option" }, diff --git a/modules/home/vim/default.nix b/modules/home/vim/default.nix index 8e6bd5c..20a74ff 100644 --- a/modules/home/vim/default.nix +++ b/modules/home/vim/default.nix @@ -59,7 +59,6 @@ in # LSP and linting nvim-lspconfig # Easy LSP configuration lsp-format-nvim # Simplified formatting configuration - lsp_lines-nvim # Show diagnostics *over* regions none-ls-nvim # LSP integration for linters and formatters nvim-treesitter.withAllGrammars # Better highlighting nvim-treesitter-textobjects # More textobjects @@ -67,7 +66,6 @@ in # Completion luasnip # Snippet manager compatible with LSP - friendly-snippets # LSP snippets collection nvim-cmp # Completion engine cmp-async-path # More responsive path completion cmp-buffer # Words from open buffers diff --git a/modules/home/vim/init.vim b/modules/home/vim/init.vim index 8202cad..39ef32e 100644 --- a/modules/home/vim/init.vim +++ b/modules/home/vim/init.vim @@ -68,8 +68,6 @@ set listchars=tab:>─,trail:·,nbsp:¤ " Use patience diff set diffopt+=algorithm:patience -" Align similar lines in each hunk -set diffopt+=linematch:50 " Don't redraw when executing macros set lazyredraw @@ -102,7 +100,11 @@ gruvbox.setup({ 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 " Use my preferred colorscheme diff --git a/modules/home/vim/lua/ambroisie/lsp.lua b/modules/home/vim/lua/ambroisie/lsp.lua index eb53da6..e48de12 100644 --- a/modules/home/vim/lua/ambroisie/lsp.lua +++ b/modules/home/vim/lua/ambroisie/lsp.lua @@ -3,43 +3,6 @@ local M = {} -- Simplified LSP formatting configuration local lsp_format = require("lsp-format") ---- Move to the next/previous diagnostic, automatically showing the diagnostics ---- float if necessary. ---- @param forward bool whether to go forward or backwards -local function goto_diagnostic(forward) - vim.validate({ - forward = { forward, "boolean" }, - }) - - local opts = { - float = false, - } - - -- Only show floating diagnostics if they are otherwise not displayed - local config = vim.diagnostic.config() - if not (config.virtual_text or config.virtual_lines) then - opts.float = true - end - - if forward then - vim.diagnostic.goto_next(opts) - else - vim.diagnostic.goto_prev(opts) - end -end - ---- Move to the next diagnostic, automatically showing the diagnostics float if ---- necessary. -M.goto_next_diagnostic = function() - goto_diagnostic(true) -end - ---- Move to the previous diagnostic, automatically showing the diagnostics float ---- if necessary. -M.goto_prev_diagnostic = function() - goto_diagnostic(false) -end - --- shared LSP configuration callback --- @param client native client configuration --- @param bufnr int? buffer number of the attached client @@ -79,6 +42,10 @@ M.on_attach = function(client, bufnr) vim.diagnostic.config({ virtual_text = text, virtual_lines = lines, + jump = { + -- Show float on jump if no diagnostic text is otherwise shown + float = not (text or lines), + }, }) end diff --git a/modules/home/vim/lua/ambroisie/utils.lua b/modules/home/vim/lua/ambroisie/utils.lua index c9e9292..0ee7c83 100644 --- a/modules/home/vim/lua/ambroisie/utils.lua +++ b/modules/home/vim/lua/ambroisie/utils.lua @@ -38,7 +38,7 @@ end --- @param bufnr int? buffer number --- @return table all active LSP client names M.list_lsp_clients = function(bufnr) - local clients = vim.lsp.get_active_clients({ bufnr = bufnr }) + local clients = vim.lsp.get_clients({ bufnr = bufnr }) local names = {} for _, client in ipairs(clients) do diff --git a/modules/home/vim/plugin/settings/fastfold.lua b/modules/home/vim/plugin/settings/fastfold.lua deleted file mode 100644 index 78ee937..0000000 --- a/modules/home/vim/plugin/settings/fastfold.lua +++ /dev/null @@ -1,5 +0,0 @@ --- Intercept all fold commands --- stylua: ignore -vim.g.fastfold_fold_command_suffixes = { - "x", "X", "a", "A", "o", "O", "c", "C", "r", "R", "m", "M", "i", "n", "N", -} diff --git a/modules/home/vim/plugin/settings/lsp-lines.lua b/modules/home/vim/plugin/settings/lsp-lines.lua deleted file mode 100644 index 9c79818..0000000 --- a/modules/home/vim/plugin/settings/lsp-lines.lua +++ /dev/null @@ -1,3 +0,0 @@ -local lsp_lines = require("lsp_lines") - -lsp_lines.setup() diff --git a/modules/home/vim/plugin/settings/lspconfig.lua b/modules/home/vim/plugin/settings/lspconfig.lua index 9e9425c..7817d4c 100644 --- a/modules/home/vim/plugin/settings/lspconfig.lua +++ b/modules/home/vim/plugin/settings/lspconfig.lua @@ -16,6 +16,10 @@ vim.diagnostic.config({ update_in_insert = false, -- Show highest severity first severity_sort = true, + jump = { + -- Show float on diagnostic jumps + float = true, + }, }) -- Inform servers we are able to do completion, snippets, etc... @@ -74,6 +78,16 @@ if utils.is_executable("bash-language-server") then filetypes = { "bash", "sh", "zsh" }, capabilities = capabilities, on_attach = lsp.on_attach, + settings = { + bashIde = { + shfmt = { + -- Simplify the code + simplifyCode = true, + -- Indent switch cases + caseIndent = true, + }, + }, + }, }) end @@ -86,6 +100,13 @@ if utils.is_executable("starpls") then end -- Generic +if utils.is_executable("harper-ls") then + lspconfig.harper_ls.setup({ + capabilities = capabilities, + on_attach = lsp.on_attach, + }) +end + if utils.is_executable("typos-lsp") then lspconfig.typos_lsp.setup({ capabilities = capabilities, diff --git a/modules/home/vim/plugin/settings/lualine.lua b/modules/home/vim/plugin/settings/lualine.lua index 5219a95..bbe4647 100644 --- a/modules/home/vim/plugin/settings/lualine.lua +++ b/modules/home/vim/plugin/settings/lualine.lua @@ -1,4 +1,5 @@ local lualine = require("lualine") +local oil = require("oil") local utils = require("ambroisie.utils") local function list_spell_languages() @@ -30,7 +31,7 @@ lualine.setup({ { "mode" }, }, lualine_b = { - { "FugitiveHead" }, + { "branch" }, { "filename", symbols = { readonly = "🔒" } }, }, lualine_c = { @@ -57,5 +58,21 @@ lualine.setup({ extensions = { "fugitive", "quickfix", + { + sections = { + lualine_a = { + { "mode" }, + }, + lualine_b = { + { "branch" }, + }, + lualine_c = { + function() + return vim.fn.fnamemodify(oil.get_current_dir(), ":~") + end, + }, + }, + filetypes = { "oil" }, + }, }, }) diff --git a/modules/home/vim/plugin/settings/luasnip.lua b/modules/home/vim/plugin/settings/luasnip.lua deleted file mode 100644 index 80309d7..0000000 --- a/modules/home/vim/plugin/settings/luasnip.lua +++ /dev/null @@ -1 +0,0 @@ -require("luasnip.loaders.from_vscode").lazy_load() diff --git a/modules/home/vim/plugin/settings/null-ls.lua b/modules/home/vim/plugin/settings/null-ls.lua index eadf16a..258a209 100644 --- a/modules/home/vim/plugin/settings/null-ls.lua +++ b/modules/home/vim/plugin/settings/null-ls.lua @@ -46,29 +46,3 @@ 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 index a160725..74d5007 100644 --- a/modules/home/vim/plugin/settings/oil.lua +++ b/modules/home/vim/plugin/settings/oil.lua @@ -4,6 +4,8 @@ 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, diff --git a/modules/home/wm/i3/default.nix b/modules/home/wm/i3/default.nix index c432864..029a14b 100644 --- a/modules/home/wm/i3/default.nix +++ b/modules/home/wm/i3/default.nix @@ -127,9 +127,10 @@ in { class = "^Blueman-.*$"; } { title = "^htop$"; } { class = "^Thunderbird$"; instance = "Mailnews"; window_role = "filterlist"; } - { class = "^Pavucontrol.*$"; } + { class = "^pavucontrol.*$"; } { class = "^Arandr$"; } - { class = ".?blueman-manager.*$"; } + { class = "^\\.blueman-manager-wrapped$"; } + { class = "^\\.arandr-wrapped$"; } ]; }; diff --git a/modules/home/xdg/default.nix b/modules/home/xdg/default.nix index 270200e..803167f 100644 --- a/modules/home/xdg/default.nix +++ b/modules/home/xdg/default.nix @@ -30,11 +30,10 @@ in }; # A tidy home is a tidy mind dataFile = { - "bash/.keep".text = ""; - "gdb/.keep".text = ""; - "tig/.keep".text = ""; + "tig/.keep".text = ""; # `tig` uses `XDG_DATA_HOME` specifically... }; stateFile = { + "bash/.keep".text = ""; "python/.keep".text = ""; }; }; diff --git a/modules/home/zsh/default.nix b/modules/home/zsh/default.nix index 11b6cb2..f4092d8 100644 --- a/modules/home/zsh/default.nix +++ b/modules/home/zsh/default.nix @@ -87,28 +87,26 @@ in # Modal editing is life, but CLI benefits from emacs gymnastics defaultKeymap = "emacs"; - # Make those happen early to avoid doing double the work - initExtraFirst = lib.mkBefore '' - ${ - lib.optionalString cfg.launchTmux '' - # Launch tmux unless already inside one - if [ -z "$TMUX" ]; then - exec tmux new-session - fi - '' - } - ''; + initContent = lib.mkMerge [ + # Make those happen early to avoid doing double the work + (lib.mkBefore (lib.optionalString cfg.launchTmux '' + # Launch tmux unless already inside one + if [ -z "$TMUX" ]; then + exec tmux new-session + fi + '')) - initExtra = lib.mkAfter '' - source ${./completion-styles.zsh} - source ${./extra-mappings.zsh} - source ${./options.zsh} + (lib.mkAfter '' + source ${./completion-styles.zsh} + source ${./extra-mappings.zsh} + source ${./options.zsh} - # Source local configuration - if [ -f "$ZDOTDIR/zshrc.local" ]; then - source "$ZDOTDIR/zshrc.local" - fi - ''; + # Source local configuration + if [ -f "$ZDOTDIR/zshrc.local" ]; then + source "$ZDOTDIR/zshrc.local" + fi + '') + ]; localVariables = { # I like having the full path @@ -151,7 +149,7 @@ in }; # Use OSC-777 to send the notification through SSH - initExtra = lib.mkIf cfg.notify.ssh.useOsc777 '' + initContent = lib.mkIf cfg.notify.ssh.useOsc777 '' done_send_notification() { local exit_status="$1" local title="$2" diff --git a/modules/nixos/hardware/bluetooth/default.nix b/modules/nixos/hardware/bluetooth/default.nix index e9b1991..b14ac21 100644 --- a/modules/nixos/hardware/bluetooth/default.nix +++ b/modules/nixos/hardware/bluetooth/default.nix @@ -20,7 +20,7 @@ in # Support for additional bluetooth codecs (lib.mkIf cfg.loadExtraCodecs { - hardware.pulseaudio = { + services.pulseaudio = { extraModules = [ pkgs.pulseaudio-modules-bt ]; package = pkgs.pulseaudioFull; }; diff --git a/modules/nixos/hardware/graphics/default.nix b/modules/nixos/hardware/graphics/default.nix index 89bb1cd..7d8b359 100644 --- a/modules/nixos/hardware/graphics/default.nix +++ b/modules/nixos/hardware/graphics/default.nix @@ -33,9 +33,8 @@ in # AMD GPU (lib.mkIf (cfg.gpuFlavor == "amd") { - boot.initrd.kernelModules = lib.mkIf cfg.amd.enableKernelModule [ "amdgpu" ]; - hardware.amdgpu = { + initrd.enable = cfg.amd.enableKernelModule; # Vulkan amdvlk = lib.mkIf cfg.amd.amdvlk { enable = true; diff --git a/modules/nixos/hardware/sound/default.nix b/modules/nixos/hardware/sound/default.nix index e8ba7f7..cd453de 100644 --- a/modules/nixos/hardware/sound/default.nix +++ b/modules/nixos/hardware/sound/default.nix @@ -54,10 +54,7 @@ in # Pulseaudio setup (lib.mkIf cfg.pulse.enable { - # ALSA - sound.enable = true; - - hardware.pulseaudio.enable = true; + services.pulseaudio.enable = true; }) ]); } diff --git a/modules/nixos/services/aria/default.nix b/modules/nixos/services/aria/default.nix index 2d1b3e2..acbf0b7 100644 --- a/modules/nixos/services/aria/default.nix +++ b/modules/nixos/services/aria/default.nix @@ -65,9 +65,7 @@ in aria-rpc = { port = cfg.rpcPort; # Proxy websockets for RPC - extraConfig = { - locations."/".proxyWebsockets = true; - }; + websocketsLocations = [ "/" ]; }; }; diff --git a/modules/nixos/services/audiobookshelf/default.nix b/modules/nixos/services/audiobookshelf/default.nix index da9ec55..04ec8b9 100644 --- a/modules/nixos/services/audiobookshelf/default.nix +++ b/modules/nixos/services/audiobookshelf/default.nix @@ -30,9 +30,7 @@ in audiobookshelf = { inherit (cfg) port; # Proxy websockets for RPC - extraConfig = { - locations."/".proxyWebsockets = true; - }; + websocketsLocations = [ "/" ]; }; }; diff --git a/modules/nixos/services/default.nix b/modules/nixos/services/default.nix index 651f3f8..27f8765 100644 --- a/modules/nixos/services/default.nix +++ b/modules/nixos/services/default.nix @@ -14,7 +14,7 @@ ./forgejo ./gitea ./grocy - ./indexers + ./homebox ./jellyfin ./komga ./lohr diff --git a/modules/nixos/services/homebox/default.nix b/modules/nixos/services/homebox/default.nix new file mode 100644 index 0000000..d79e331 --- /dev/null +++ b/modules/nixos/services/homebox/default.nix @@ -0,0 +1,42 @@ +# 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; + + settings = { + # FIXME: mailer? + HBOX_WEB_PORT = toString cfg.port; + }; + }; + + my.services.nginx.virtualHosts = { + homebox = { + inherit (cfg) port; + }; + }; + + my.services.backup = { + paths = [ + config.services.homebox.settings.HBOX_STORAGE_DATA + ]; + }; + + # 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 deleted file mode 100644 index 8a42345..0000000 --- a/modules/nixos/services/indexers/default.nix +++ /dev/null @@ -1,78 +0,0 @@ -# Torrent and usenet meta-indexers -{ config, lib, ... }: -let - cfg = config.my.services.indexers; - - jackettPort = 9117; - nzbhydraPort = 5076; - prowlarrPort = 9696; -in -{ - options.my.services.indexers = with lib; { - jackett.enable = mkEnableOption "Jackett torrent meta-indexer"; - nzbhydra.enable = mkEnableOption "NZBHydra2 usenet meta-indexer"; - prowlarr.enable = mkEnableOption "Prowlarr torrent & usenet meta-indexer"; - }; - - config = lib.mkMerge [ - (lib.mkIf cfg.jackett.enable { - services.jackett = { - enable = true; - }; - - # Jackett wants to eat *all* my RAM if left to its own devices - systemd.services.jackett = { - serviceConfig = { - MemoryHigh = "15%"; - MemoryMax = "25%"; - }; - }; - - my.services.nginx.virtualHosts = { - jackett = { - port = jackettPort; - }; - }; - }) - - (lib.mkIf cfg.nzbhydra.enable { - services.nzbhydra2 = { - enable = true; - }; - - my.services.nginx.virtualHosts = { - nzbhydra = { - port = nzbhydraPort; - }; - }; - }) - - (lib.mkIf cfg.prowlarr.enable { - services.prowlarr = { - enable = true; - }; - - my.services.nginx.virtualHosts = { - prowlarr = { - port = prowlarrPort; - }; - }; - - services.fail2ban.jails = { - prowlarr = '' - enabled = true - filter = prowlarr - action = iptables-allports - ''; - }; - - environment.etc = { - "fail2ban/filter.d/prowlarr.conf".text = '' - [Definition] - failregex = ^.*\|Warn\|Auth\|Auth-Failure ip username .*$ - journalmatch = _SYSTEMD_UNIT=prowlarr.service - ''; - }; - }) - ]; -} diff --git a/modules/nixos/services/jellyfin/default.nix b/modules/nixos/services/jellyfin/default.nix index e8910a5..6edeb67 100644 --- a/modules/nixos/services/jellyfin/default.nix +++ b/modules/nixos/services/jellyfin/default.nix @@ -27,17 +27,13 @@ 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; - }; }; }; }; diff --git a/modules/nixos/services/komga/default.nix b/modules/nixos/services/komga/default.nix index e1dc780..9af3cd1 100644 --- a/modules/nixos/services/komga/default.nix +++ b/modules/nixos/services/komga/default.nix @@ -18,13 +18,13 @@ in config = lib.mkIf cfg.enable { services.komga = { enable = true; - inherit (cfg) port; group = "media"; - }; - systemd.services.komga.environment = { - LOGGING_LEVEL_ORG_GOTSON_KOMGA = "DEBUG"; # Needed for fail2ban + settings = { + server.port = cfg.port; + logging.level.org.gotson.komga = "DEBUG"; # Needed for fail2ban + }; }; # Set-up media group diff --git a/modules/nixos/services/nextcloud/collabora.nix b/modules/nixos/services/nextcloud/collabora.nix new file mode 100644 index 0000000..f8f42a7 --- /dev/null +++ b/modules/nixos/services/nextcloud/collabora.nix @@ -0,0 +1,50 @@ +# 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.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 e2c4746..cf1b876 100644 --- a/modules/nixos/services/nextcloud/default.nix +++ b/modules/nixos/services/nextcloud/default.nix @@ -4,6 +4,10 @@ let cfg = config.my.services.nextcloud; in { + imports = [ + ./collabora.nix + ]; + options.my.services.nextcloud = with lib; { enable = mkEnableOption "Nextcloud"; maxSize = mkOption { @@ -31,7 +35,7 @@ in config = lib.mkIf cfg.enable { services.nextcloud = { enable = true; - package = pkgs.nextcloud30; + package = pkgs.nextcloud31; hostName = "nextcloud.${config.networking.domain}"; home = "/var/lib/nextcloud"; maxUploadSize = cfg.maxSize; diff --git a/modules/nixos/services/nginx/default.nix b/modules/nixos/services/nginx/default.nix index e305b29..1e9e38a 100644 --- a/modules/nixos/services/nginx/default.nix +++ b/modules/nixos/services/nginx/default.nix @@ -17,6 +17,16 @@ 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; @@ -60,10 +70,13 @@ let extraConfig = mkOption { type = types.attrs; # FIXME: forward type of virtualHosts example = { - locations."/socket" = { - proxyPass = "http://127.0.0.1:8096/"; - proxyWebsockets = true; - }; + extraConfig = '' + add_header X-Clacks-Overhead "GNU Terry Pratchett"; + ''; + + locations."/".extraConfig = '' + client_max_body_size 1G; + ''; }; default = { }; description = '' @@ -74,10 +87,6 @@ let }); in { - imports = [ - ./sso - ]; - options.my.services.nginx = with lib; { enable = mkEnableOption "Nginx"; @@ -86,7 +95,7 @@ in type = types.str; example = "/var/lib/acme/creds.env"; description = '' - Gandi API key file as an 'EnvironmentFile' (see `systemd.exec(5)`) + OVH API key file as an 'EnvironmentFile' (see `systemd.exec(5)`) ''; }; }; @@ -108,12 +117,7 @@ in }; jellyfin = { port = 8096; - extraConfig = { - locations."/socket" = { - proxyPass = "http://127.0.0.1:8096/"; - proxyWebsockets = true; - }; - }; + websocketsLocations = [ "/socket" ]; }; }; description = '' @@ -195,6 +199,19 @@ 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 @@ -236,11 +253,18 @@ 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 [ @@ -251,8 +275,7 @@ in } # Proxy to port (lib.optionalAttrs (args.port != null) { - locations."/".proxyPass = - "http://127.0.0.1:${toString args.port}"; + locations = mkProxyPass args "http://127.0.0.1:${toString args.port}"; }) # Serve filesystem content (lib.optionalAttrs (args.root != null) { @@ -260,8 +283,7 @@ in }) # Serve to UNIX socket (lib.optionalAttrs (args.socket != null) { - locations."/".proxyPass = - "http://unix:${args.socket}"; + locations = mkProxyPass args "http://unix:${args.socket}"; }) # Redirect to a different domain (lib.optionalAttrs (args.redirect != null) { @@ -281,6 +303,7 @@ in locations."/" = { extraConfig = + # FIXME: check that X-User is dropped otherwise (args.extraConfig.locations."/".extraConfig or "") + '' # Use SSO auth_request /sso-auth; @@ -414,7 +437,8 @@ in { "${domain}" = { extraDomainNames = [ "*.${domain}" ]; - dnsProvider = "gandiv5"; + dnsProvider = "ovh"; + dnsPropagationCheck = false; # OVH is slow inherit (cfg.acme) credentialsFile; }; }; diff --git a/modules/nixos/services/nginx/sso/default.nix b/modules/nixos/services/nginx/sso/default.nix deleted file mode 100644 index d60e31b..0000000 --- a/modules/nixos/services/nginx/sso/default.nix +++ /dev/null @@ -1,84 +0,0 @@ -# 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} - ''; - 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/paperless/default.nix b/modules/nixos/services/paperless/default.nix index f62879a..63f456b 100644 --- a/modules/nixos/services/paperless/default.nix +++ b/modules/nixos/services/paperless/default.nix @@ -1,4 +1,4 @@ -{ config, lib, pkgs, ... }: +{ config, lib, ... }: let cfg = config.my.services.paperless; in @@ -61,11 +61,6 @@ in PAPERLESS_ENABLE_HTTP_REMOTE_USER = true; PAPERLESS_HTTP_REMOTE_USER_HEADER_NAME = "HTTP_X_USER"; - # Use PostgreSQL - PAPERLESS_DBHOST = "/run/postgresql"; - PAPERLESS_DBUSER = "paperless"; - PAPERLESS_DBNAME = "paperless"; - # Security settings PAPERLESS_ALLOWED_HOSTS = paperlessDomain; PAPERLESS_CORS_ALLOWED_HOSTS = "https://${paperlessDomain}"; @@ -80,63 +75,18 @@ in # 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; - }; - systemd.services = { - paperless-scheduler = { - requires = [ "postgresql.service" ]; - after = [ "postgresql.service" ]; + # Secret key + environmentFile = cfg.secretKeyFile; - serviceConfig = { - EnvironmentFile = cfg.secretKeyFile; - }; + # Automatic PostgreSQL provisioning + database = { + createLocally = true; }; - - 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 @@ -152,11 +102,7 @@ in sso = { enable = true; }; - - # Enable websockets on root - extraConfig = { - locations."/".proxyWebsockets = true; - }; + websocketsLocations = [ "/" ]; }; }; diff --git a/modules/nixos/services/postgresql/default.nix b/modules/nixos/services/postgresql/default.nix index bbe46d4..1dca164 100644 --- a/modules/nixos/services/postgresql/default.nix +++ b/modules/nixos/services/postgresql/default.nix @@ -14,7 +14,7 @@ in # Let other services enable postgres when they need it (lib.mkIf cfg.enable { services.postgresql = { - package = pkgs.postgresql_13; + package = pkgs.postgresql_17; }; }) @@ -23,15 +23,15 @@ in environment.systemPackages = let pgCfg = config.services.postgresql; - newPackage' = pkgs.postgresql_13; + newPackage' = pkgs.postgresql_17; oldPackage = if pgCfg.enableJIT then pgCfg.package.withJIT else pgCfg.package; oldData = pgCfg.dataDir; - oldBin = "${if pgCfg.extraPlugins == [] then oldPackage else oldPackage.withPackages pgCfg.extraPlugins}/bin"; + 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.extraPlugins == [] then newPackage else newPackage.withPackages pgCfg.extraPlugins}/bin"; + newBin = "${if pgCfg.extensions == [] then newPackage else newPackage.withPackages pgCfg.extensions}/bin"; in [ (pkgs.writeScriptBin "upgrade-pg-cluster" '' diff --git a/modules/nixos/services/pyload/default.nix b/modules/nixos/services/pyload/default.nix index 88889bf..7257d0f 100644 --- a/modules/nixos/services/pyload/default.nix +++ b/modules/nixos/services/pyload/default.nix @@ -53,6 +53,20 @@ in }; }; - # FIXME: fail2ban + 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 + ''; + }; }; } diff --git a/modules/nixos/services/servarr/autobrr.nix b/modules/nixos/services/servarr/autobrr.nix new file mode 100644 index 0000000..afb07f4 --- /dev/null +++ b/modules/nixos/services/servarr/autobrr.nix @@ -0,0 +1,62 @@ +# IRC-based +{ config, lib, ... }: +let + cfg = config.my.services.servarr.autobrr; +in +{ + options.my.services.servarr.autobrr = with lib; { + enable = mkEnableOption "autobrr IRC announce tracker" // { + default = config.my.services.servarr.enableAll; + }; + + port = mkOption { + type = types.port; + default = 7474; + example = 8080; + description = "Internal port for webui"; + }; + + sessionSecretFile = mkOption { + type = types.str; + example = "/run/secrets/autobrr-secret.txt"; + description = '' + File containing the session secret. + ''; + }; + }; + + config = lib.mkIf cfg.enable { + services.autobrr = { + enable = true; + + settings = { + inherit (cfg) port; + checkForUpdates = false; + }; + + secretFile = cfg.sessionSecretFile; + }; + + my.services.nginx.virtualHosts = { + autobrr = { + inherit (cfg) port; + }; + }; + + services.fail2ban.jails = { + autobrr = '' + enabled = true + filter = autobrr + action = iptables-allports + ''; + }; + + environment.etc = { + "fail2ban/filter.d/autobrr.conf".text = '' + [Definition] + failregex = ^.*Auth: invalid login \[.*\] from: $ + journalmatch = _SYSTEMD_UNIT=autobrr.service + ''; + }; + }; +} diff --git a/modules/nixos/services/servarr/bazarr.nix b/modules/nixos/services/servarr/bazarr.nix new file mode 100644 index 0000000..637da0c --- /dev/null +++ b/modules/nixos/services/servarr/bazarr.nix @@ -0,0 +1,37 @@ +{ config, lib, ... }: +let + cfg = config.my.services.servarr.bazarr; +in +{ + options.my.services.servarr.bazarr = with lib; { + enable = lib.mkEnableOption "Bazarr" // { + default = config.my.services.servarr.enableAll; + }; + + port = mkOption { + type = types.port; + default = 6767; + example = 8080; + description = "Internal port for webui"; + }; + }; + + config = lib.mkIf cfg.enable { + services.bazarr = { + enable = true; + group = "media"; + listenPort = cfg.port; + }; + + # Set-up media group + users.groups.media = { }; + + my.services.nginx.virtualHosts = { + bazarr = { + inherit (cfg) port; + }; + }; + + # Bazarr does not log authentication failures... + }; +} diff --git a/modules/nixos/services/servarr/default.nix b/modules/nixos/services/servarr/default.nix index e25d9cf..409fcdc 100644 --- a/modules/nixos/services/servarr/default.nix +++ b/modules/nixos/services/servarr/default.nix @@ -2,99 +2,21 @@ # Relevant link [1]. # # [1]: https://youtu.be/I26Ql-uX6AM -{ config, lib, ... }: -let - cfg = config.my.services.servarr; - - ports = { - bazarr = 6767; - lidarr = 8686; - radarr = 7878; - readarr = 8787; - sonarr = 8989; - }; - - mkService = service: { - services.${service} = { - enable = true; - group = "media"; - }; - }; - - mkRedirection = service: { - my.services.nginx.virtualHosts = { - ${service} = { - port = ports.${service}; - }; - }; - }; - - mkFail2Ban = service: lib.mkIf cfg.${service}.enable { - services.fail2ban.jails = { - ${service} = '' - enabled = true - filter = ${service} - action = iptables-allports - ''; - }; - - environment.etc = { - "fail2ban/filter.d/${service}.conf".text = '' - [Definition] - failregex = ^.*\|Warn\|Auth\|Auth-Failure ip username .*$ - journalmatch = _SYSTEMD_UNIT=${service}.service - ''; - }; - }; - - mkFullConfig = service: lib.mkIf cfg.${service}.enable (lib.mkMerge [ - (mkService service) - (mkRedirection service) - ]); -in +{ lib, ... }: { + imports = [ + ./autobrr.nix + ./bazarr.nix + ./jackett.nix + ./nzbhydra.nix + ./prowlarr.nix + (import ./starr.nix "lidarr") + (import ./starr.nix "radarr") + (import ./starr.nix "readarr") + (import ./starr.nix "sonarr") + ]; + options.my.services.servarr = { - enable = lib.mkEnableOption "Media automation"; - - bazarr = { - enable = lib.my.mkDisableOption "Bazarr"; - }; - - lidarr = { - enable = lib.my.mkDisableOption "Lidarr"; - }; - - radarr = { - enable = lib.my.mkDisableOption "Radarr"; - }; - - readarr = { - enable = lib.my.mkDisableOption "Readarr"; - }; - - sonarr = { - enable = lib.my.mkDisableOption "Sonarr"; - }; + enableAll = lib.mkEnableOption "media automation suite"; }; - - config = lib.mkIf cfg.enable (lib.mkMerge [ - { - # Set-up media group - users.groups.media = { }; - } - # Bazarr does not log authentication failures... - (mkFullConfig "bazarr") - # Lidarr for music - (mkFullConfig "lidarr") - (mkFail2Ban "lidarr") - # Radarr for movies - (mkFullConfig "radarr") - (mkFail2Ban "radarr") - # Readarr for books - (mkFullConfig "readarr") - (mkFail2Ban "readarr") - # Sonarr for shows - (mkFullConfig "sonarr") - (mkFail2Ban "sonarr") - ]); } diff --git a/modules/nixos/services/servarr/jackett.nix b/modules/nixos/services/servarr/jackett.nix new file mode 100644 index 0000000..481cd3d --- /dev/null +++ b/modules/nixos/services/servarr/jackett.nix @@ -0,0 +1,41 @@ +{ config, lib, ... }: +let + cfg = config.my.services.servarr.jackett; +in +{ + options.my.services.servarr.jackett = with lib; { + enable = lib.mkEnableOption "Jackett" // { + default = config.my.services.servarr.enableAll; + }; + + port = mkOption { + type = types.port; + default = 9117; + example = 8080; + description = "Internal port for webui"; + }; + }; + + config = lib.mkIf cfg.enable { + services.jackett = { + enable = true; + inherit (cfg) port; + }; + + # Jackett wants to eat *all* my RAM if left to its own devices + systemd.services.jackett = { + serviceConfig = { + MemoryHigh = "15%"; + MemoryMax = "25%"; + }; + }; + + my.services.nginx.virtualHosts = { + jackett = { + inherit (cfg) port; + }; + }; + + # Jackett does not log authentication failures... + }; +} diff --git a/modules/nixos/services/servarr/nzbhydra.nix b/modules/nixos/services/servarr/nzbhydra.nix new file mode 100644 index 0000000..7b63986 --- /dev/null +++ b/modules/nixos/services/servarr/nzbhydra.nix @@ -0,0 +1,26 @@ +{ config, lib, ... }: +let + cfg = config.my.services.servarr.nzbhydra; +in +{ + options.my.services.servarr.nzbhydra = with lib; { + enable = lib.mkEnableOption "NZBHydra2" // { + default = config.my.services.servarr.enableAll; + }; + }; + + config = lib.mkIf cfg.enable { + services.nzbhydra2 = { + enable = true; + }; + + my.services.nginx.virtualHosts = { + nzbhydra = { + port = 5076; + websocketsLocations = [ "/" ]; + }; + }; + + # NZBHydra2 does not log authentication failures... + }; +} diff --git a/modules/nixos/services/servarr/prowlarr.nix b/modules/nixos/services/servarr/prowlarr.nix new file mode 100644 index 0000000..ce044c6 --- /dev/null +++ b/modules/nixos/services/servarr/prowlarr.nix @@ -0,0 +1,53 @@ +# Torrent and NZB indexer +{ config, lib, ... }: +let + cfg = config.my.services.servarr.prowlarr; +in +{ + options.my.services.servarr.prowlarr = with lib; { + enable = lib.mkEnableOption "Prowlarr" // { + default = config.my.services.servarr.enableAll; + }; + + port = mkOption { + type = types.port; + default = 9696; + example = 8080; + description = "Internal port for webui"; + }; + }; + + config = lib.mkIf cfg.enable { + services.prowlarr = { + enable = true; + + settings = { + server = { + port = cfg.port; + }; + }; + }; + + my.services.nginx.virtualHosts = { + prowlarr = { + inherit (cfg) port; + }; + }; + + services.fail2ban.jails = { + prowlarr = '' + enabled = true + filter = prowlarr + action = iptables-allports + ''; + }; + + environment.etc = { + "fail2ban/filter.d/prowlarr.conf".text = '' + [Definition] + failregex = ^.*\|Warn\|Auth\|Auth-Failure ip username .*$ + journalmatch = _SYSTEMD_UNIT=prowlarr.service + ''; + }; + }; +} diff --git a/modules/nixos/services/servarr/starr.nix b/modules/nixos/services/servarr/starr.nix new file mode 100644 index 0000000..2bf7c11 --- /dev/null +++ b/modules/nixos/services/servarr/starr.nix @@ -0,0 +1,64 @@ +# Templated *arr configuration +starr: +{ config, lib, ... }: +let + cfg = config.my.services.servarr.${starr}; + ports = { + lidarr = 8686; + radarr = 7878; + readarr = 8787; + sonarr = 8989; + }; +in +{ + options.my.services.servarr.${starr} = with lib; { + enable = lib.mkEnableOption (lib.toSentenceCase starr) // { + default = config.my.services.servarr.enableAll; + }; + + port = mkOption { + type = types.port; + default = ports.${starr}; + example = 8080; + description = "Internal port for webui"; + }; + }; + + config = lib.mkIf cfg.enable { + services.${starr} = { + enable = true; + group = "media"; + + settings = { + server = { + port = cfg.port; + }; + }; + }; + + # Set-up media group + users.groups.media = { }; + + my.services.nginx.virtualHosts = { + ${starr} = { + port = cfg.port; + }; + }; + + services.fail2ban.jails = { + ${starr} = '' + enabled = true + filter = ${starr} + action = iptables-allports + ''; + }; + + environment.etc = { + "fail2ban/filter.d/${starr}.conf".text = '' + [Definition] + failregex = ^.*\|Warn\|Auth\|Auth-Failure ip username .*$ + journalmatch = _SYSTEMD_UNIT=${starr}.service + ''; + }; + }; +} diff --git a/modules/nixos/system/packages/default.nix b/modules/nixos/system/packages/default.nix index ebea06f..6a78ff6 100644 --- a/modules/nixos/system/packages/default.nix +++ b/modules/nixos/system/packages/default.nix @@ -1,5 +1,5 @@ # Common packages -{ config, lib, pkgs, ... }: +{ config, lib, ... }: let cfg = config.my.system.packages; in @@ -13,10 +13,6 @@ in }; config = lib.mkIf cfg.enable { - environment.systemPackages = with pkgs; [ - wget - ]; - programs = { vim = { enable = true; diff --git a/pkgs/bw-pass/bw-pass b/pkgs/bw-pass/bw-pass index 124714a..0e974b7 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/cgt-calc/default.nix b/pkgs/cgt-calc/default.nix deleted file mode 100644 index 9966944..0000000 --- a/pkgs/cgt-calc/default.nix +++ /dev/null @@ -1,47 +0,0 @@ -{ lib -, fetchFromGitHub -, python3Packages -, withTeXLive ? true -, texliveSmall -}: -python3Packages.buildPythonApplication rec { - pname = "cgt-calc"; - version = "1.13.0"; - pyproject = true; - - src = fetchFromGitHub { - owner = "KapJI"; - repo = "capital-gains-calculator"; - rev = "v${version}"; - hash = "sha256-y/Y05wG89nccXyxfjqazyPJhd8dOkfwRJre+Rzx97Hw="; - }; - - build-system = with python3Packages; [ - poetry-core - ]; - - dependencies = with python3Packages; [ - defusedxml - jinja2 - pandas - requests - types-requests - yfinance - ]; - - makeWrapperArgs = lib.optionals withTeXLive [ - "--prefix" - "PATH" - ":" - "${lib.getBin texliveSmall}/bin" - ]; - - meta = with lib; { - description = "UK capital gains tax calculator"; - homepage = "https://github.com/KapJI/capital-gains-calculator"; - license = with licenses; [ mit ]; - mainProgram = "cgt-calc"; - maintainers = with maintainers; [ ambroisie ]; - platforms = platforms.unix; - }; -} diff --git a/pkgs/change-audio/change-audio b/pkgs/change-audio/change-audio index 612fecf..5a1fb9c 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/default.nix b/pkgs/default.nix index 949bcf7..6b7fce1 100644 --- a/pkgs/default.nix +++ b/pkgs/default.nix @@ -2,8 +2,6 @@ pkgs.lib.makeScope pkgs.newScope (pkgs: { bw-pass = pkgs.callPackage ./bw-pass { }; - cgt-calc = pkgs.callPackage ./cgt-calc { }; - change-audio = pkgs.callPackage ./change-audio { }; change-backlight = pkgs.callPackage ./change-backlight { }; diff --git a/pkgs/diff-flake/diff-flake b/pkgs/diff-flake/diff-flake index 0572b4e..a2a3513 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/lohr/default.nix b/pkgs/lohr/default.nix index b89ccff..aeb13b1 100644 --- a/pkgs/lohr/default.nix +++ b/pkgs/lohr/default.nix @@ -10,7 +10,8 @@ rustPlatform.buildRustPackage rec { hash = "sha256-dunQgtap+XCK5LoSyOqIY/6p6HizBeiyPWNuCffwjDU="; }; - cargoHash = "sha256-EUhyrhPe+mUgMmm4o+bxRIiSNReJRfw+/O1fPr8r7lo="; + useFetchCargoVendor = true; + cargoHash = "sha256-R3/N/43+bGx6acE/rhBcrk6kS5zQu8NJ1sVvKJJkK9w="; meta = with lib; { description = "Git mirroring daemon"; diff --git a/pkgs/osc52/osc52 b/pkgs/osc52/osc52 index f64ccb6..de3a982 100755 --- a/pkgs/osc52/osc52 +++ b/pkgs/osc52/osc52 @@ -15,7 +15,7 @@ usage() { exec 1>&2 fi - cat << EOF + cat <&2 fi - cat << EOF + cat < Send a notification (title and message) to the host system using the OSC 777 escape sequence: diff --git a/templates/c++-cmake/.envrc b/templates/c++-cmake/.envrc old mode 100644 new mode 100755 index de77fcb..390d06d --- a/templates/c++-cmake/.envrc +++ b/templates/c++-cmake/.envrc @@ -1,3 +1,4 @@ +# 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/flake.nix b/templates/c++-cmake/flake.nix index db3b35c..7796f5e 100644 --- a/templates/c++-cmake/flake.nix +++ b/templates/c++-cmake/flake.nix @@ -16,19 +16,18 @@ ref = "nixos-unstable"; }; - pre-commit-hooks = { + git-hooks = { type = "github"; owner = "cachix"; - repo = "pre-commit-hooks.nix"; + repo = "git-hooks.nix"; ref = "master"; inputs = { - flake-utils.follows = "futils"; nixpkgs.follows = "nixpkgs"; }; }; }; - outputs = { self, futils, nixpkgs, pre-commit-hooks }: + outputs = { self, futils, nixpkgs, git-hooks }: { overlays = { default = final: _prev: { @@ -69,7 +68,7 @@ ]; }; - pre-commit = pre-commit-hooks.lib.${system}.run { + pre-commit = git-hooks.lib.${system}.run { src = self; hooks = { @@ -92,12 +91,12 @@ devShells = { default = pkgs.mkShell { - inputsFrom = with self.packages.${system}; [ - project + inputsFrom = [ + self.packages.${system}.project ]; packages = with pkgs; [ - clang-tools + self.checks.${system}.pre-commit.enabledPackages ]; inherit (pre-commit) shellHook; diff --git a/templates/c++-meson/.envrc b/templates/c++-meson/.envrc index de77fcb..390d06d 100644 --- a/templates/c++-meson/.envrc +++ b/templates/c++-meson/.envrc @@ -1,3 +1,4 @@ +# 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/flake.nix b/templates/c++-meson/flake.nix index 5957c62..cb14eb5 100644 --- a/templates/c++-meson/flake.nix +++ b/templates/c++-meson/flake.nix @@ -16,19 +16,18 @@ ref = "nixos-unstable"; }; - pre-commit-hooks = { + git-hooks = { type = "github"; owner = "cachix"; - repo = "pre-commit-hooks.nix"; + repo = "git-hooks.nix"; ref = "master"; inputs = { - flake-utils.follows = "futils"; nixpkgs.follows = "nixpkgs"; }; }; }; - outputs = { self, futils, nixpkgs, pre-commit-hooks }: + outputs = { self, futils, nixpkgs, git-hooks }: { overlays = { default = final: _prev: { @@ -69,7 +68,7 @@ ]; }; - pre-commit = pre-commit-hooks.lib.${system}.run { + pre-commit = git-hooks.lib.${system}.run { src = self; hooks = { @@ -92,12 +91,12 @@ devShells = { default = pkgs.mkShell { - inputsFrom = with self.packages.${system}; [ - project + inputsFrom = [ + self.packages.${system}.project ]; packages = with pkgs; [ - clang-tools + self.checks.${system}.pre-commit.enabledPackages ]; inherit (pre-commit) shellHook; diff --git a/templates/default.nix b/templates/default.nix index 44db753..51864cd 100644 --- a/templates/default.nix +++ b/templates/default.nix @@ -7,6 +7,10 @@ path = ./c++-meson; description = "A C++ project using Meson"; }; + "python-uv" = { + path = ./python-uv; + description = "A Python project using uv"; + }; "rust-cargo" = { path = ./rust-cargo; description = "A Rust project using Cargo"; diff --git a/templates/python-uv/.envrc b/templates/python-uv/.envrc new file mode 100644 index 0000000..390d06d --- /dev/null +++ b/templates/python-uv/.envrc @@ -0,0 +1,6 @@ +# shellcheck shell=bash +if ! has nix_direnv_version || ! nix_direnv_version 3.0.0; then + source_url "https://raw.githubusercontent.com/nix-community/nix-direnv/3.0.0/direnvrc" "sha256-21TMnI2xWX7HkSTjFFri2UaohXVj854mgvWapWrxRXg=" +fi + +use flake diff --git a/templates/python-uv/.gitignore b/templates/python-uv/.gitignore new file mode 100644 index 0000000..c79d1e8 --- /dev/null +++ b/templates/python-uv/.gitignore @@ -0,0 +1,6 @@ +# Virtual environments +.venv + +# Nix generated files +/.pre-commit-config.yaml +/result diff --git a/templates/python-uv/.woodpecker/check.yml b/templates/python-uv/.woodpecker/check.yml new file mode 100644 index 0000000..272c0e4 --- /dev/null +++ b/templates/python-uv/.woodpecker/check.yml @@ -0,0 +1,31 @@ +labels: + backend: local + +steps: +- name: pre-commit check + image: bash + commands: + - nix develop --command pre-commit run --all + +- name: nix flake check + image: bash + commands: + - nix flake check + +- name: notify + image: bash + environment: + ADDRESS: + from_secret: matrix_homeserver + ROOM: + from_secret: matrix_roomid + USER: + from_secret: matrix_username + PASS: + from_secret: matrix_password + commands: + - nix run github:ambroisie/matrix-notifier + when: + status: + - failure + - success diff --git a/templates/python-uv/flake.nix b/templates/python-uv/flake.nix new file mode 100644 index 0000000..5059e64 --- /dev/null +++ b/templates/python-uv/flake.nix @@ -0,0 +1,112 @@ +{ + description = "A Python project"; + + inputs = { + futils = { + type = "github"; + owner = "numtide"; + repo = "flake-utils"; + ref = "main"; + }; + + nixpkgs = { + type = "github"; + owner = "NixOS"; + repo = "nixpkgs"; + ref = "nixos-unstable"; + }; + + git-hooks = { + type = "github"; + owner = "cachix"; + repo = "git-hooks.nix"; + ref = "master"; + inputs = { + nixpkgs.follows = "nixpkgs"; + }; + }; + }; + + outputs = { self, futils, nixpkgs, git-hooks }: + { + overlays = { + default = final: _prev: { + project = with final; python3.pkgs.buildPythonApplication { + pname = "project"; + version = (final.lib.importTOML ./pyproject.toml).project.version; + pyproject = true; + + src = self; + + build-system = with python3.pkgs; [ setuptools ]; + + pythonImportsCheck = [ "project" ]; + + meta = with lib; { + description = "A Python project"; + homepage = "https://git.belanyi.fr/ambroisie/project"; + license = licenses.mit; + maintainers = with maintainers; [ ambroisie ]; + }; + }; + }; + }; + } // futils.lib.eachDefaultSystem (system: + let + pkgs = import nixpkgs { + inherit system; + overlays = [ + self.overlays.default + ]; + }; + + pre-commit = git-hooks.lib.${system}.run { + src = self; + + hooks = { + mypy = { + enable = true; + }; + + nixpkgs-fmt = { + enable = true; + }; + + ruff = { + enable = true; + }; + + ruff-format = { + enable = true; + }; + }; + }; + in + { + checks = { + inherit (self.packages.${system}) project; + + inherit pre-commit; + }; + + devShells = { + default = pkgs.mkShell { + inputsFrom = [ + self.packages.${system}.project + ]; + + packages = with pkgs; [ + uv + self.checks.${system}.pre-commit.enabledPackages + ]; + + inherit (pre-commit) shellHook; + }; + }; + + packages = futils.lib.flattenTree { + default = pkgs.project; + inherit (pkgs) project; + }; + }); +} diff --git a/templates/python-uv/pyproject.toml b/templates/python-uv/pyproject.toml new file mode 100644 index 0000000..7b2d896 --- /dev/null +++ b/templates/python-uv/pyproject.toml @@ -0,0 +1,17 @@ +[build-system] +requires = ["setuptools"] +build-backend = "setuptools.build_meta" + + +[project] +name = "project" +version = "0.0.0" +description = "project description" +requires-python = ">=3.12" +dependencies = [] + +[project.scripts] +project = "project:main" + +[dependency-groups] +dev = [] diff --git a/templates/python-uv/src/project/__init__.py b/templates/python-uv/src/project/__init__.py new file mode 100644 index 0000000..b06117d --- /dev/null +++ b/templates/python-uv/src/project/__init__.py @@ -0,0 +1,2 @@ +def main() -> None: + print("Hello, world!") diff --git a/templates/rust-cargo/.envrc b/templates/rust-cargo/.envrc index de77fcb..390d06d 100644 --- a/templates/rust-cargo/.envrc +++ b/templates/rust-cargo/.envrc @@ -1,3 +1,4 @@ +# 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/rust-cargo/flake.nix b/templates/rust-cargo/flake.nix index 6d50369..efd8358 100644 --- a/templates/rust-cargo/flake.nix +++ b/templates/rust-cargo/flake.nix @@ -16,19 +16,18 @@ ref = "nixos-unstable"; }; - pre-commit-hooks = { + git-hooks = { type = "github"; owner = "cachix"; - repo = "pre-commit-hooks.nix"; + repo = "git-hooks.nix"; ref = "master"; inputs = { - flake-utils.follows = "futils"; nixpkgs.follows = "nixpkgs"; }; }; }; - outputs = { self, futils, nixpkgs, pre-commit-hooks }: + outputs = { self, futils, nixpkgs, git-hooks }: { overlays = { default = final: _prev: { @@ -60,7 +59,7 @@ ]; }; - pre-commit = pre-commit-hooks.lib.${system}.run { + pre-commit = git-hooks.lib.${system}.run { src = self; hooks = { @@ -88,14 +87,13 @@ devShells = { default = pkgs.mkShell { - inputsFrom = with self.packages.${system}; [ - project + inputsFrom = [ + self.packages.${system}.project ]; packages = with pkgs; [ - clippy rust-analyzer - rustfmt + self.checks.${system}.pre-commit.enabledPackages ]; RUST_SRC_PATH = "${pkgs.rust.packages.stable.rustPlatform.rustLibSrc}";