diff --git a/flake.lock b/flake.lock index d86d6b5..65b8f04 100644 --- a/flake.lock +++ b/flake.lock @@ -175,11 +175,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1743689281, - "narHash": "sha256-y7Hg5lwWhEOgflEHRfzSH96BOt26LaYfrYWzZ+VoVdg=", + "lastModified": 1744777043, + "narHash": "sha256-O6jgTxz9BKUiaJl03JsVHvSjtCOC8gHfDvC2UCfcLMc=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "2bfc080955153be0be56724be6fa5477b4eefabb", + "rev": "7a6f7f4c1c69eee05641beaa40e7f85da8e69fb0", "type": "github" }, "original": { diff --git a/flake/home-manager.nix b/flake/home-manager.nix index add889e..093ae8c 100644 --- a/flake/home-manager.nix +++ b/flake/home-manager.nix @@ -3,6 +3,11 @@ let defaultModules = [ # Include generic settings "${self}/modules/home" + { + nixpkgs.overlays = (lib.attrValues self.overlays) ++ [ + inputs.nur.overlays.default + ]; + } { # Basic user information defaults home.username = lib.mkDefault "ambroisie"; @@ -21,18 +26,15 @@ let # * not letting me set `lib` as an extraSpecialArgs # * not respecting `nixpkgs.overlays` [1] # [1]: https://github.com/nix-community/home-manager/issues/2954 - pkgs = import inputs.nixpkgs { - inherit system; - - overlays = (lib.attrValues self.overlays) ++ [ - inputs.nur.overlays.default - ]; - }; + pkgs = inputs.nixpkgs.legacyPackages.${system}; modules = defaultModules ++ [ "${self}/hosts/homes/${name}" ]; + # Use my extended lib in NixOS configuration + inherit (self) lib; + extraSpecialArgs = { # Inject inputs to use them in global registry inherit inputs; diff --git a/hosts/homes/ambroisie@bazin/default.nix b/hosts/homes/ambroisie@bazin/default.nix index f52fbce..23f0ba5 100644 --- a/hosts/homes/ambroisie@bazin/default.nix +++ b/hosts/homes/ambroisie@bazin/default.nix @@ -13,8 +13,8 @@ enablePassthrough = true; terminalFeatures = { - # HTerm uses `xterm-256color` as its `$TERM`, so use that here - xterm-256color = { }; + # HTerm configured to use a more accurate terminfo entry than `xterm-256color` + hterm-256color = { }; }; }; diff --git a/hosts/homes/ambroisie@mousqueton/default.nix b/hosts/homes/ambroisie@mousqueton/default.nix index 37884d7..163fbe2 100644 --- a/hosts/homes/ambroisie@mousqueton/default.nix +++ b/hosts/homes/ambroisie@mousqueton/default.nix @@ -19,8 +19,8 @@ enableResurrect = true; terminalFeatures = { - # HTerm uses `xterm-256color` as its `$TERM`, so use that here - xterm-256color = { }; + # HTerm configured to use a more accurate terminfo entry than `xterm-256color` + hterm-256color = { }; }; }; }; diff --git a/hosts/nixos/porthos/secrets/secrets.nix b/hosts/nixos/porthos/secrets/secrets.nix index 425756c..b3812b4 100644 --- a/hosts/nixos/porthos/secrets/secrets.nix +++ b/hosts/nixos/porthos/secrets/secrets.nix @@ -81,6 +81,7 @@ in "pyload/credentials.age".publicKeys = all; "servarr/autobrr/session-secret.age".publicKeys = all; + "servarr/cross-seed/configuration.json.age".publicKeys = all; "sso/auth-key.age" = { owner = "nginx-sso"; diff --git a/hosts/nixos/porthos/secrets/servarr/cross-seed/configuration.json.age b/hosts/nixos/porthos/secrets/servarr/cross-seed/configuration.json.age new file mode 100644 index 0000000..e9af03f Binary files /dev/null and b/hosts/nixos/porthos/secrets/servarr/cross-seed/configuration.json.age differ diff --git a/hosts/nixos/porthos/services.nix b/hosts/nixos/porthos/services.nix index 784eb31..96f15d3 100644 --- a/hosts/nixos/porthos/services.nix +++ b/hosts/nixos/porthos/services.nix @@ -51,6 +51,10 @@ in passwordFile = secrets."forgejo/mail-password".path; }; }; + # Home inventory + homebox = { + enable = true; + }; # Jellyfin media server jellyfin.enable = true; # Gitea mirrorig service @@ -144,6 +148,9 @@ in 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; diff --git a/modules/home/atuin/default.nix b/modules/home/atuin/default.nix index 3f06263..dbd9690 100644 --- a/modules/home/atuin/default.nix +++ b/modules/home/atuin/default.nix @@ -8,6 +8,10 @@ in # I want the full experience by default package = mkPackageOption pkgs "atuin" { }; + + daemon = { + enable = my.mkDisableOption "atuin daemon"; + }; }; config = lib.mkIf cfg.enable { @@ -15,12 +19,18 @@ in 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 "--disable-up-arrow" ]; 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/tmux/default.nix b/modules/home/tmux/default.nix index 08b9202..1ac11c4 100644 --- a/modules/home/tmux/default.nix +++ b/modules/home/tmux/default.nix @@ -6,13 +6,16 @@ let (config.my.home.wm.windowManager != null) ]; - mkTerminalFlags = opt: flag: + mkTerminalFlags = tmuxVar: opt: flag: let - mkFlag = term: ''set -as terminal-features ",${term}:${flag}"''; + mkFlag = term: ''set -as ${tmuxVar} ",${term}:${flag}"''; enabledTerminals = lib.filterAttrs (_: v: v.${opt}) cfg.terminalFeatures; terminals = lib.attrNames enabledTerminals; in lib.concatMapStringsSep "\n" mkFlag terminals; + + mkTerminalFeatures = mkTerminalFlags "terminal-features"; + mkTerminalOverrides = mkTerminalFlags "terminal-overrides"; in { options.my.home.tmux = with lib; { @@ -28,6 +31,8 @@ in hyperlinks = my.mkDisableOption "hyperlinks through OSC8"; trueColor = my.mkDisableOption "24-bit (RGB) color support"; + + underscoreStyle = my.mkDisableOption "underscore style/color support"; }; }); @@ -54,6 +59,20 @@ in terminal = "tmux-256color"; # I want accurate termcap info aggressiveResize = true; # Automatic resize when switching client size + # FIXME + # * Sixel support + # * OSC 133 prompt integration + # FIXME: when sensible-on-top is disabled: check if any of those are unset + # * tmux bind-key $prefix_without_ctrl last-window + # * + # * tmux bind-key C-b send-prefix: included + # * aggressive resize? done + # * tmux bind-key C-p previous-window: done + # * tmux bind-key C-n next-window: done + # * C-r to refresh my config: done + # * tmux set-option -g focus-events on: done + + # FIXME: make PRs for `bind-key` description plugins = with pkgs.tmuxPlugins; builtins.filter (attr: attr != { }) [ # Open high-lighted files in copy mode open @@ -123,9 +142,14 @@ in } # Force OSC8 hyperlinks for each relevant $TERM - ${mkTerminalFlags "hyperlinks" "hyperlinks"} + ${mkTerminalFeatures "hyperlinks" "hyperlinks"} # Force 24-bit color for each relevant $TERM - ${mkTerminalFlags "trueColor" "RGB"} + ${mkTerminalFeatures "trueColor" "RGB"} + # Force underscore style/color for each relevant $TERM + ${mkTerminalFeatures "underscoreStyle" "usstyle"} + # FIXME: see https://github.com/folke/tokyonight.nvim#fix-undercurls-in-tmux for additional overrides + # ${mkTerminalOverrides "underscoreStyle" "Smulx=\\E[4::%p1%dm"} + # ${mkTerminalOverrides "underscoreStyle" "Setulc=\\E[58::2::::%p1%{65536}%/%d::%p1%{256}%/%{255}%&%d::%p1%{255}%&%d%;m"} ''; }; } diff --git a/modules/home/vim/plugin/numbertoggle.lua b/modules/home/vim/plugin/numbertoggle.lua index 8042710..b1e3df2 100644 --- a/modules/home/vim/plugin/numbertoggle.lua +++ b/modules/home/vim/plugin/numbertoggle.lua @@ -22,13 +22,3 @@ vim.api.nvim_create_autocmd({ "BufLeave", "FocusLost", "InsertEnter", "WinLeave" end end, }) - --- Never show the sign column in a terminal buffer -vim.api.nvim_create_autocmd({ "TermOpen" }, { - pattern = "*", - group = numbertoggle, - callback = function() - vim.opt.number = false - vim.opt.relativenumber = false - end, -}) diff --git a/modules/home/vim/plugin/signtoggle.lua b/modules/home/vim/plugin/signtoggle.lua index 9765a81..3deca34 100644 --- a/modules/home/vim/plugin/signtoggle.lua +++ b/modules/home/vim/plugin/signtoggle.lua @@ -1,26 +1,21 @@ local signtoggle = vim.api.nvim_create_augroup("signtoggle", { clear = true }) --- Only show sign column for the currently focused buffer +-- Only show sign column for the currently focused buffer, if it has a number column vim.api.nvim_create_autocmd({ "BufEnter", "FocusGained", "WinEnter" }, { pattern = "*", group = signtoggle, callback = function() - vim.opt.signcolumn = "yes" + if vim.opt.number:get() then + vim.opt.signcolumn = "yes" + end end, }) vim.api.nvim_create_autocmd({ "BufLeave", "FocusLost", "WinLeave" }, { pattern = "*", group = signtoggle, callback = function() - vim.opt.signcolumn = "no" - end, -}) - --- Never show the sign column in a terminal buffer -vim.api.nvim_create_autocmd({ "TermOpen" }, { - pattern = "*", - group = signtoggle, - callback = function() - vim.opt.signcolumn = "no" + if vim.opt.number:get() then + vim.opt.signcolumn = "no" + end end, }) diff --git a/modules/nixos/services/homebox/default.nix b/modules/nixos/services/homebox/default.nix index d79e331..8ed5d77 100644 --- a/modules/nixos/services/homebox/default.nix +++ b/modules/nixos/services/homebox/default.nix @@ -19,6 +19,11 @@ in services.homebox = { enable = true; + # Automatic PostgreSQL provisioning + database = { + createLocally = true; + }; + settings = { # FIXME: mailer? HBOX_WEB_PORT = toString cfg.port; @@ -28,6 +33,7 @@ in my.services.nginx.virtualHosts = { homebox = { inherit (cfg) port; + websocketsLocations = [ "/api" ]; }; }; diff --git a/modules/nixos/services/servarr/autobrr.nix b/modules/nixos/services/servarr/autobrr.nix index afb07f4..c3370cb 100644 --- a/modules/nixos/services/servarr/autobrr.nix +++ b/modules/nixos/services/servarr/autobrr.nix @@ -1,4 +1,4 @@ -# IRC-based +# IRC-based indexer { config, lib, ... }: let cfg = config.my.services.servarr.autobrr; @@ -40,6 +40,7 @@ in my.services.nginx.virtualHosts = { autobrr = { inherit (cfg) port; + websocketsLocations = [ "/api" ]; }; }; @@ -54,7 +55,7 @@ in environment.etc = { "fail2ban/filter.d/autobrr.conf".text = '' [Definition] - failregex = ^.*Auth: invalid login \[.*\] from: $ + failregex = "message":"Auth: Failed login attempt username: \[.*\] ip: " journalmatch = _SYSTEMD_UNIT=autobrr.service ''; }; diff --git a/modules/nixos/services/servarr/cross-seed.nix b/modules/nixos/services/servarr/cross-seed.nix new file mode 100644 index 0000000..74f216a --- /dev/null +++ b/modules/nixos/services/servarr/cross-seed.nix @@ -0,0 +1,96 @@ +# 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 index 409fcdc..dca57cf 100644 --- a/modules/nixos/services/servarr/default.nix +++ b/modules/nixos/services/servarr/default.nix @@ -7,6 +7,7 @@ imports = [ ./autobrr.nix ./bazarr.nix + ./cross-seed.nix ./jackett.nix ./nzbhydra.nix ./prowlarr.nix diff --git a/modules/nixos/services/transmission/default.nix b/modules/nixos/services/transmission/default.nix index ac8b24d..16d51e3 100644 --- a/modules/nixos/services/transmission/default.nix +++ b/modules/nixos/services/transmission/default.nix @@ -65,6 +65,8 @@ in # Proxied behind Nginx. rpc-whitelist-enabled = true; rpc-whitelist = "127.0.0.1"; + + umask = "002"; # To go with `downloadDirPermissions` }; };