From 5ce99497d7be33d2be2997b43ab730348e12fcfc Mon Sep 17 00:00:00 2001 From: "Gustavo \"Guz\" L. de Mello" Date: Mon, 8 Apr 2024 16:37:29 -0300 Subject: [PATCH] refactor!: I went too close into the sun Simlified everything, things were getting out of control --- .sops.yaml | 6 +- flake.nix | 45 +- hosts/homelab/configuration.nix | 129 ++---- hosts/homelab/hardware-configuration.nix | 44 +- hosts/homelab/home.nix | 8 + hosts/homelab/secrets.nix | 49 +- hosts/homelab/services.nix | 63 +++ hosts/homelab/users/default.nix | 9 - hosts/homelab/users/guz.nix | 38 -- modules/client/default.nix | 36 -- modules/home-manager/default.nix | 8 + modules/home-manager/profiles/default.nix | 7 + modules/home-manager/profiles/gterminal.nix | 165 +++++++ .../{programs => programs-old}/davinci.nix | 17 +- .../eww/default.nix | 24 +- .../{programs => programs-old}/eww/eww.scss | 0 .../{programs => programs-old}/eww/eww.yuck | 0 .../{programs => programs-old}/hyprland.nix | 203 ++++---- .../krita/default.nix | 19 +- .../{programs => programs-old}/krita/kritarc | 0 .../krita/kritashortcutsrc | 0 modules/home-manager/programs-old/lf.nix | 94 ++++ .../programs-old/librewolf/default.nix | 437 ++++++++++++++++++ .../librewolf/search.json.mozlz4 | Bin .../{programs => programs-old}/obs.nix | 17 +- .../{programs => programs-old}/obsidian.nix | 24 +- .../{programs => programs-old}/starship.nix | 16 +- .../{programs => programs-old}/tmux.nix | 18 +- modules/home-manager/programs-old/wezterm.nix | 84 ++++ .../{programs => programs-old}/zsh.nix | 18 +- modules/home-manager/programs/default.nix | 8 + modules/home-manager/programs/lf.nix | 95 ---- .../programs/librewolf/default.nix | 416 ----------------- modules/home-manager/programs/neovim.nix | 30 ++ modules/home-manager/programs/wezterm.nix | 145 +++--- modules/home-manager/theme.nix | 20 +- modules/nih/default.nix | 107 ++--- modules/nih/domains/default.nix | 32 ++ modules/nih/domains/tailscale-caddy.nix | 50 ++ modules/nih/domains/tailscale.nix | 24 + modules/nih/networking/default.nix | 41 +- modules/nih/programs/default.nix | 16 +- modules/nih/programs/direnv.nix | 33 +- modules/nih/programs/hyprland.nix | 166 +++---- modules/nih/programs/lf.nix | 71 +-- modules/nih/programs/starship.nix | 31 +- modules/nih/programs/tmux.nix | 19 +- modules/nih/programs/wezterm.nix | 104 +++-- modules/nih/programs/zsh.nix | 18 +- modules/nih/services/adguard.nix | 90 ---- modules/nih/services/adguardhome.nix | 75 +++ modules/nih/services/caddy.nix | 35 +- modules/nih/services/default.nix | 16 +- modules/nih/services/forgejo.nix | 301 ------------ modules/nih/services/tailscale.nix | 82 ++-- modules/nih/sound.nix | 39 +- modules/nih/user-profiles/default.nix | 16 +- modules/nih/user-profiles/gterminal.nix | 207 +++++---- modules/nih/users.nix | 120 ++--- modules/nixos/config/host.nix | 21 +- modules/nixos/default.nix | 10 + modules/nixos/home-manager-helper.nix | 248 ++++++++++ modules/nixos/profiles/default.nix | 7 + modules/nixos/profiles/locale.nix | 64 +++ modules/nixos/programs/default.nix | 7 + modules/nixos/programs/nih/cli.nix | 40 ++ modules/nixos/programs/nih/cli.sh | 124 +++++ modules/nixos/programs/nih/default.nix | 23 + modules/nixos/services/adguardhome.nix | 62 +++ modules/nixos/services/default.nix | 9 + modules/nixos/services/forgejo.nix | 249 ++++++++++ modules/nixos/services/tailscale.nix | 61 +++ modules/nixos/systems/fonts.nix | 20 +- modules/nixos/systems/localization.nix | 16 +- modules/nixos/systems/set-user.nix | 120 ++--- modules/server/adguard.nix | 42 +- modules/server/caddy.nix | 24 +- modules/server/default.nix | 97 ++-- modules/server/forgejo.nix | 406 ++++++++++------ modules/server/jellyfin.nix | 343 +++++++------- modules/server/jellyseerr.nix | 16 +- modules/server/network.nix | 52 ++- modules/server/nextcloud.nix | 17 +- modules/server/photoprism.nix | 16 +- modules/server/tailscale.nix | 19 +- secrets/decrypt.sh | 10 + secrets/homelab-lesser-secrets.json | 33 ++ 87 files changed, 3726 insertions(+), 2415 deletions(-) create mode 100644 hosts/homelab/home.nix create mode 100644 hosts/homelab/services.nix delete mode 100644 hosts/homelab/users/default.nix delete mode 100644 hosts/homelab/users/guz.nix delete mode 100644 modules/client/default.nix create mode 100644 modules/home-manager/default.nix create mode 100644 modules/home-manager/profiles/default.nix create mode 100644 modules/home-manager/profiles/gterminal.nix rename modules/home-manager/{programs => programs-old}/davinci.nix (60%) rename modules/home-manager/{programs => programs-old}/eww/default.nix (95%) rename modules/home-manager/{programs => programs-old}/eww/eww.scss (100%) rename modules/home-manager/{programs => programs-old}/eww/eww.yuck (100%) rename modules/home-manager/{programs => programs-old}/hyprland.nix (65%) rename modules/home-manager/{programs => programs-old}/krita/default.nix (63%) rename modules/home-manager/{programs => programs-old}/krita/kritarc (100%) rename modules/home-manager/{programs => programs-old}/krita/kritashortcutsrc (100%) create mode 100644 modules/home-manager/programs-old/lf.nix create mode 100644 modules/home-manager/programs-old/librewolf/default.nix rename modules/home-manager/{programs => programs-old}/librewolf/search.json.mozlz4 (100%) rename modules/home-manager/{programs => programs-old}/obs.nix (73%) rename modules/home-manager/{programs => programs-old}/obsidian.nix (80%) rename modules/home-manager/{programs => programs-old}/starship.nix (80%) rename modules/home-manager/{programs => programs-old}/tmux.nix (94%) create mode 100644 modules/home-manager/programs-old/wezterm.nix rename modules/home-manager/{programs => programs-old}/zsh.nix (91%) create mode 100644 modules/home-manager/programs/default.nix delete mode 100644 modules/home-manager/programs/lf.nix delete mode 100644 modules/home-manager/programs/librewolf/default.nix create mode 100644 modules/home-manager/programs/neovim.nix create mode 100644 modules/nih/domains/default.nix create mode 100644 modules/nih/domains/tailscale-caddy.nix create mode 100644 modules/nih/domains/tailscale.nix delete mode 100644 modules/nih/services/adguard.nix create mode 100644 modules/nih/services/adguardhome.nix delete mode 100644 modules/nih/services/forgejo.nix create mode 100644 modules/nixos/default.nix create mode 100644 modules/nixos/home-manager-helper.nix create mode 100644 modules/nixos/profiles/default.nix create mode 100644 modules/nixos/profiles/locale.nix create mode 100644 modules/nixos/programs/default.nix create mode 100644 modules/nixos/programs/nih/cli.nix create mode 100644 modules/nixos/programs/nih/cli.sh create mode 100644 modules/nixos/programs/nih/default.nix create mode 100644 modules/nixos/services/adguardhome.nix create mode 100644 modules/nixos/services/default.nix create mode 100644 modules/nixos/services/forgejo.nix create mode 100644 modules/nixos/services/tailscale.nix create mode 100755 secrets/decrypt.sh create mode 100644 secrets/homelab-lesser-secrets.json diff --git a/.sops.yaml b/.sops.yaml index 7a9979c..92b1b2d 100644 --- a/.sops.yaml +++ b/.sops.yaml @@ -5,7 +5,11 @@ creation_rules: key_groups: - age: - *primary - - path_regex: secrets/homex-secrets.yaml$ + - path_regex: secrets/homelab-secrets.yaml$ + key_groups: + - age: + - *primary + - path_regex: secrets/homelab-lesser-secrets.json$ key_groups: - age: - *primary diff --git a/flake.nix b/flake.nix index c148b0e..93a5b41 100644 --- a/flake.nix +++ b/flake.nix @@ -42,37 +42,40 @@ hyprland.url = "github:hyprwm/Hyprland"; xdg-desktop-portal-hyprland.url = "github:hyprwm/xdg-desktop-portal-hyprland"; /* - Note to self: - The last commit with working screen share, as the time of writing this, was - https://github.com/hyprwm/xdg-desktop-portal-hyprland/commit/6a5de92769d5b7038134044053f90e7458f6a197 - https://github.com/hyprwm/Hyprland/commit/3c964a9fdc220250a85b1c498e5b6fad9390272f - so if needed, you can always roll-back. + Note to self: + The last commit with working screen share, as the time of writing this, was + https://github.com/hyprwm/xdg-desktop-portal-hyprland/commit/6a5de92769d5b7038134044053f90e7458f6a197 + https://github.com/hyprwm/Hyprland/commit/3c964a9fdc220250a85b1c498e5b6fad9390272f + so if needed, you can always roll-back. - Fuck discord. + Fuck discord. */ }; - outputs = { self, nixpkgs, home-manager, ... }@inputs: - let - create-host = (configs: builtins.listToAttrs (map + outputs = { + self, + nixpkgs, + home-manager, + ... + } @ inputs: let + create-host = configs: + builtins.listToAttrs (map (c: { name = c; value = nixpkgs.lib.nixosSystem { - specialArgs = { inherit inputs; }; + specialArgs = {inherit inputs;}; modules = [ inputs.home-manager.nixosModules.default - (./. + ("/hosts/" + builtins.replaceStrings [ "@" ] [ "/" ] c) + /configuration.nix) + (./. + ("/hosts/" + builtins.replaceStrings ["@"] ["/"] c) + /configuration.nix) ]; }; }) - configs)); - in - { - nixosConfigurations = (create-host [ - "desktop@default" - "desktop@work" - "homelab" - ]); - }; + configs); + in { + nixosConfigurations = create-host [ + "desktop@default" + "desktop@work" + "homelab" + ]; + }; } - diff --git a/hosts/homelab/configuration.nix b/hosts/homelab/configuration.nix index 951baa2..81a217e 100755 --- a/hosts/homelab/configuration.nix +++ b/hosts/homelab/configuration.nix @@ -1,96 +1,69 @@ # your system. Help is available in the configuration.nix(5) man page # and in the NixOS manual (accessible by running ‘nixos-help’). - -{ config, ... }: - { + config, + pkgs, + ... +}: { imports = [ - ../../modules/nixos/config/host.nix - ../../modules/nih + ../../modules/nixos + ./services.nix + ./secrets.nix ./hardware-configuration.nix ]; - nih = { - enable = true; - name = "homelab"; - ip = "192.168.1.10"; - type = "server"; + programs.nih.enable = true; + programs.nih.flakeDir = "/home/guz/.nix"; + programs.nih.host = "homelab"; - networking = { - interface = "eno1"; - wireless = false; - }; + profiles.locale.enable = true; - services.tailscale = { - enable = true; - exitNode = true; - routingFeatures = "both"; - }; - - users.guz = { - username = "guz"; - password = "$y$j9T$J7gmdB306rufrjdsY5kJq0$spluDZf8jEkG0VYcZXzBIpnACVIk27C8YTbo2vbNFfA"; - - profiles.gterminal.enable = true; - }; + home-manager-helper.enable = true; + home-manager-helper.users."guz" = { + name = "guz"; + shell = pkgs.zsh; + hashedPassword = "$y$j9T$J7gmdB306rufrjdsY5kJq0$spluDZf8jEkG0VYcZXzBIpnACVIk27C8YTbo2vbNFfA"; + home = import ./home.nix; + isNormalUser = true; + extraGroups = ["wheel" "networkmanager"]; }; + environment.sessionVariables = { + EDITOR = "nvim"; + }; - /* - server = { - enable = true; - flakeDir = "/home/guz/.nix#homelab"; - name = "homelab"; - domain = "homelab.local"; + environment.systemPackages = with pkgs; [ + git + ]; - ip = "100.66.139.89"; - localIp = "192.168.1.10"; + programs.zsh.enable = true; - network = { - enable = true; - interface = "eno1"; - }; + nix.settings.experimental-features = ["nix-command" "flakes"]; - nextcloud = { - enable = true; - settings.admin = { - passwordFile = /. + config.sops.secrets."nextcloud/user1/password".path; - }; - }; + networking = { + networkmanager.enable = true; + hostName = "homelab"; + wireless.enable = false; + dhcpcd.enable = true; + defaultGateway = "192.168.1.1"; + interfaces."eno1".ipv4.addresses = [ + { + address = "192.168.1.10"; + prefixLength = 24; + } + ]; + }; - tailscale = { - enable = true; - mode = "both"; - exitNode = true; - }; - - forgejo = { - enable = true; - actions = { - enable = true; - runnerToken = "PYKxHNpeCR2ajtdPgo1C3rvgZHNJqzH4bUXLDwLa"; - }; - settings.server.url = "https://${config.server.forgejo.settings.server.domain}"; - settings.users."user1" = { - name = /. + config.sops.secrets."forgejo/user1/name".path; - email = /. + config.sops.secrets."forgejo/user1/email".path; - password = /. + config.sops.secrets."forgejo/user1/password".path; - admin = true; - }; - settings.ui.themes = [ "forgejo-dark" "arc-green" ]; - I'm hours trying to make pushing via SSH work, but using the {user}@{domain}:{owner}/{repo} - simply isn't working and returns "does not appear to be a git repository". Probably - is a problem with all the "domain handling" stuff with caddy, adguard, etc. This is - a temporary fix, so I don't end up breaking my actual sanity. - settings.security.allowBypassGiteaEnv = true; - }; - - jellyfin = { - enable = true; - }; - }; - */ - services.tailscale.enable = true; + sound.enable = true; + hardware.pulseaudio.enable = false; + security.rtkit.enable = true; + services.pipewire = { + enable = true; + alsa.enable = true; + alsa.support32Bit = true; + pulse.enable = true; + wireplumber.enable = true; + }; # Bootloader. boot.loader.systemd-boot.enable = true; @@ -107,5 +80,3 @@ # (e.g. man configuration.nix or on https://nixos.org/nixos/options.html). system.stateVersion = "23.11"; # Did you read the comment? } - - diff --git a/hosts/homelab/hardware-configuration.nix b/hosts/homelab/hardware-configuration.nix index 73b9a09..f0277c7 100644 --- a/hosts/homelab/hardware-configuration.nix +++ b/hosts/homelab/hardware-configuration.nix @@ -1,31 +1,35 @@ # Do not modify this file! It was generated by ‘nixos-generate-config’ # and may be overwritten by future invocations. Please make changes # to /etc/nixos/configuration.nix instead. -{ config, lib, pkgs, modulesPath, ... }: - { - imports = - [ (modulesPath + "/installer/scan/not-detected.nix") - ]; + config, + lib, + pkgs, + modulesPath, + ... +}: { + imports = [ + (modulesPath + "/installer/scan/not-detected.nix") + ]; - boot.initrd.availableKernelModules = [ "ahci" "xhci_pci" "usbhid" "usb_storage" "sd_mod" "sdhci_acpi" ]; - boot.initrd.kernelModules = [ ]; - boot.kernelModules = [ "kvm-intel" ]; - boot.extraModulePackages = [ ]; + boot.initrd.availableKernelModules = ["ahci" "xhci_pci" "usbhid" "usb_storage" "sd_mod" "sdhci_acpi"]; + boot.initrd.kernelModules = []; + boot.kernelModules = ["kvm-intel"]; + boot.extraModulePackages = []; - fileSystems."/" = - { device = "/dev/disk/by-uuid/26878c61-60d2-4ac9-967f-30faffc0f21f"; - fsType = "ext4"; - }; + fileSystems."/" = { + device = "/dev/disk/by-uuid/26878c61-60d2-4ac9-967f-30faffc0f21f"; + fsType = "ext4"; + }; - fileSystems."/boot" = - { device = "/dev/disk/by-uuid/ACCB-816C"; - fsType = "vfat"; - }; + fileSystems."/boot" = { + device = "/dev/disk/by-uuid/ACCB-816C"; + fsType = "vfat"; + }; - swapDevices = - [ { device = "/dev/disk/by-uuid/878a189a-e5df-4e1c-92d5-df6f77ff53bb"; } - ]; + swapDevices = [ + {device = "/dev/disk/by-uuid/878a189a-e5df-4e1c-92d5-df6f77ff53bb";} + ]; # Enables DHCP on each ethernet and wireless interface. In case of scripted networking # (the default) this is the recommended approach. When using systemd-networkd it's diff --git a/hosts/homelab/home.nix b/hosts/homelab/home.nix new file mode 100644 index 0000000..65364ac --- /dev/null +++ b/hosts/homelab/home.nix @@ -0,0 +1,8 @@ +{...}: { + imports = [ + ../../modules/home-manager + ]; + + profiles.gterminal.enable = true; + programs.wezterm.enable = false; +} diff --git a/hosts/homelab/secrets.nix b/hosts/homelab/secrets.nix index 2334801..ec3fbd8 100644 --- a/hosts/homelab/secrets.nix +++ b/hosts/homelab/secrets.nix @@ -1,34 +1,45 @@ -{ config, ... }: { - imports = [ ]; - options = { }; + config, + inputs, + lib, + pkgs, + ... +}: let + lesser-secrets = with builtins; + fromJSON (readFile ../../secrets/homelab-lesser-secrets.decrypted.json); + jsonType = pkgs.formats.json {}; +in { + imports = [ + inputs.sops-nix.nixosModules.sops + ]; + options.homelab-secrets = with lib; + with lib.types; { + lesser = mkOption { + type = submodule ({...}: { + freeformType = jsonType.type; + options = {}; + }); + default = lesser-secrets; + }; + }; config = { + environment.systemPackages = with pkgs; [ + sops + ]; + sops.defaultSopsFile = ../../secrets/homelab-secrets.yaml; sops.defaultSopsFormat = "yaml"; sops.secrets."forgejo/user1/name" = { - owner = config.server.forgejo.user; + owner = config.services.forgejo.user; }; sops.secrets."forgejo/user1/password" = { - owner = config.server.forgejo.user; + owner = config.services.forgejo.user; }; sops.secrets."forgejo/user1/email" = { - owner = config.server.forgejo.user; + owner = config.services.forgejo.user; }; - /* - sops.secrets."nextcloud/user1/name" = { - owner = config.homelab.nextcloud.user; - }; - sops.secrets."nextcloud/user1/password" = { - owner = config.homelab.nextcloud.user; - }; - sops.secrets."nextcloud/user1/email" = { - owner = config.homelab.nextcloud.user; - }; - */ - sops.age.keyFile = "/home/guz/.config/sops/age/keys.txt"; }; } - diff --git a/hosts/homelab/services.nix b/hosts/homelab/services.nix new file mode 100644 index 0000000..661f0f3 --- /dev/null +++ b/hosts/homelab/services.nix @@ -0,0 +1,63 @@ +{ + config, + lib, + pkgs, + ... +}: let + secrets = config.homelab-secrets.lesser; + deviceIp = config.services.tailscale.deviceIp; +in { + imports = []; + options = {}; + config = { + services.adguardhome.enable = true; + services.adguardhome.dns.rewrites = { + "*.${secrets.homelab-domain}" = deviceIp; + "${secrets.homelab-domain}" = deviceIp; + }; + services.adguardhome.settings.bind_port = secrets.services.adguard.port; + + services.caddy.enable = true; + services.caddy.virtualHosts = + lib.attrsets.mapAttrs' + (name: service: { + name = service.domain; + value = {extraConfig = "reverse_proxy ${deviceIp}:${toString service.port}";}; + }) + secrets.services; + networking.firewall.allowedTCPPorts = [80 433]; + + services.forgejo = { + enable = true; + actions = { + enable = true; + token = secrets.services.forgejo.actions-token; + url = "http://${config.services.tailscale.deviceUrl}:${toString secrets.services.forgejo.port}"; + }; + users = { + user1 = { + name = /. + config.sops.secrets."forgejo/user1/name".path; + password = /. + config.sops.secrets."forgejo/user1/password".path; + email = /. + config.sops.secrets."forgejo/user1/email".path; + admin = true; + }; + }; + settings = { + server = { + ROOT_URL = "https://${secrets.services.forgejo.domain}"; + DOMAIN = "${secrets.services.forgejo.domain}"; + }; + }; + }; + + services.openssh.enable = true; + + services.tailscale = { + enable = true; + useRoutingFeatures = "both"; + exitNode = true; + tailnetName = secrets.tailnet-name; + deviceIp = secrets.device-ip; + }; + }; +} diff --git a/hosts/homelab/users/default.nix b/hosts/homelab/users/default.nix deleted file mode 100644 index 7a06069..0000000 --- a/hosts/homelab/users/default.nix +++ /dev/null @@ -1,9 +0,0 @@ -{ ... }: - -{ - imports = [ - ./guz.nix - ]; - options = { }; - config = { }; -} diff --git a/hosts/homelab/users/guz.nix b/hosts/homelab/users/guz.nix deleted file mode 100644 index 83d43f4..0000000 --- a/hosts/homelab/users/guz.nix +++ /dev/null @@ -1,38 +0,0 @@ -{ config, pkgs, inputs, ... }: - - -{ - imports = [ ]; - - programs.zsh.enable = true; - - set-user.users = [{ - username = "guz"; - shell = pkgs.zsh; - home = { - imports = [ - ../../../modules/home-manager/programs/lf.nix - ../../../modules/home-manager/programs/starship.nix - ../../../modules/home-manager/programs/tmux.nix - ../../../modules/home-manager/programs/zsh.nix - ../../../modules/home-manager/packages/nixi.nix - ../../../modules/home-manager/packages/nixx.nix - ]; - - lf.enable = true; - - starship.enable = true; - starship.enableZsh = true; - - tmux.enable = true; - tmux.shell = "\${pkgs.zsh}/bin/zsh"; - - zsh.enable = true; - zsh.extraConfig.init = '' - export GPG_TTY=$(tty) - - alias tmux="tmux -f /home/guz/.config/tmux/tmux.conf" - ''; - }; - }]; -} diff --git a/modules/client/default.nix b/modules/client/default.nix deleted file mode 100644 index d1e351e..0000000 --- a/modules/client/default.nix +++ /dev/null @@ -1,36 +0,0 @@ -{ config, lib, pkgs, ... }: - -let - cfg = config.client; -in -{ - imports = [ ]; - options.client = with lib; with lib.types; { - enable = mkEnableOption ""; - name = mkOption { - type = str; - default = "client"; - }; - flakeDir = mkOption { - type = str; - }; - domain = mkOption { - type = either str path; - default = "${cfg.name}.local"; - }; - localIp = mkOption { - type = nullOr str; - default = null; - }; - ip = mkOption { - type = nullOr str; - default = cfg.localIp; - }; - users = mkOption { - type = attrsOf (submodule { ... }: { - options = { }; - }); - }; - }; - config = lib.mkIf cfg.enable { }; -} diff --git a/modules/home-manager/default.nix b/modules/home-manager/default.nix new file mode 100644 index 0000000..2f173da --- /dev/null +++ b/modules/home-manager/default.nix @@ -0,0 +1,8 @@ +{...}: { + imports = [ + ./programs + ./profiles + ]; + options = {}; + config = {}; +} diff --git a/modules/home-manager/profiles/default.nix b/modules/home-manager/profiles/default.nix new file mode 100644 index 0000000..d4a5d5e --- /dev/null +++ b/modules/home-manager/profiles/default.nix @@ -0,0 +1,7 @@ +{...}: { + imports = [ + ./gterminal.nix + ]; + options = {}; + config = {}; +} diff --git a/modules/home-manager/profiles/gterminal.nix b/modules/home-manager/profiles/gterminal.nix new file mode 100644 index 0000000..908caf2 --- /dev/null +++ b/modules/home-manager/profiles/gterminal.nix @@ -0,0 +1,165 @@ +{ + config, + lib, + pkgs, + ... +}: let + cfg = config.profiles.gterminal; +in { + imports = [ + ../programs/wezterm.nix + ../programs/neovim.nix + ]; + options.profiles.gterminal = with lib; + with lib.types; { + enable = mkEnableOption ""; + }; + config = with lib; + mkIf cfg.enable { + home.packages = with pkgs; [ + git + lazygit + gcc # Added temporally so my neovim config doesn't break + wget + nixpkgs-fmt + nixpkgs-lint + ]; + programs = { + direnv.enable = true; + direnv.enableZshIntegration = true; + direnv.nix-direnv.enable = true; + + lf.enable = true; + lf.commands = { + dragon-out = ''%${pkgs.xdragon}/bin/xdragon -a -x "$fx"''; + editor-open = ''$$EDITOR $f''; + mkfile = '' ''${{ + printf "Dirname: " + read DIR + + if [[ $DIR = */ ]]; then + mkdir $DIR + else + touch $DIR + fi + }}''; + }; + lf.extraConfig = let + previewer = pkgs.writeShellScriptBin "pv.sh" '' + file=$1 + w=$2 + h=$3 + x=$4 + y=$5 + + if [[ "$(${pkgs.file}/bin/file -Lb --mime-type "$file")" =~ ^image ]]; then + ${pkgs.kitty}/bin/kitty +kitten icat --silent --stdin no --transfer-mode file --place "''${w}x''${h}@''${x}x''${y}" "$file" < /dev/null > /dev/tty + exit 1 + fi + + ${pkgs.pistol}/bin/pistol "$file" + ''; + cleaner = pkgs.writeShellScriptBin "clean.sh" '' + ${pkgs.kitty}/bin/kitty +kitten icat --clear --stdin no --silent --transfer-mode file < /dev/null > /dev/tty + ''; + in + mkDefault '' + set cleaner ${cleaner}/bin/clean.sh + set previewer ${previewer}/bin/pv.sh + ''; + + neovim.enable = true; + + starship.enable = true; + starship.enableZshIntegration = true; + + tmux.baseIndex = 1; + tmux.enable = true; + tmux.extraConfig = '' + set -sg terminal-overrides ",*:RGB" + + set -g renumber-windows on + + bind -T prefix / split-window -v -c "#''''{pane_current_path}" + bind -T prefix \\ split-window -h -c "#''''{pane_current_path}" + ''; + tmux.keyMode = "vi"; + tmux.mouse = true; + tmux.prefix = "C-Space"; + tmux.plugins = with pkgs; [ + { + plugin = tmuxPlugins.catppuccin.overrideAttrs (_: { + src = fetchFromGitHub { + owner = "guz013"; + repo = "frappuccino-tmux"; + rev = "4255b0a769cc6f35e12595fe5a33273a247630aa"; + sha256 = "0k8yprhx5cd8v1ddpcr0dkssspc17lq2a51qniwafkkzxi3kz3i5"; + }; + }); + extraConfig = '' + set -g @catppuccin_window_left_separator "" + set -g @catppuccin_window_right_separator " " + set -g @catppuccin_window_middle_separator " █" + set -g @catppuccin_window_number_position "right" + + set -g @catppuccin_window_default_fill "number" + set -g @catppuccin_window_default_text "#W" + + set -g @catppuccin_window_current_fill "number" + set -g @catppuccin_window_current_text "#W" + + set -g @catppuccin_status_modules_right "application directory session" + set -g @catppuccin_status_left_separator " " + set -g @catppuccin_status_right_separator "" + set -g @catppuccin_status_right_separator_inverse "no" + set -g @catppuccin_status_fill "icon" + set -g @catppuccin_status_connect_separator "no" + + set -g @catppuccin_directory_text "#{pane_current_path}" + ''; + } + { + plugin = tmuxPlugins.better-mouse-mode; + extraConfig = "set-option -g mouse on"; + } + { + plugin = tmuxPlugins.mkTmuxPlugin { + pluginName = "tmux.nvim"; + version = "unstable-2024-04-05"; + src = fetchFromGitHub { + owner = "aserowy"; + repo = "tmux.nvim"; + rev = "63e9c5e054099dd30af306bd8ceaa2f1086e1b07"; + sha256 = "0ynzljwq6hv7415p7pr0aqx8kycp84p3p3dy4jcx61dxfgdpgc4c"; + }; + }; + extraConfig = ''''; + } + ]; + + tmux.shell = "${pkgs.zsh}/bin/zsh"; + tmux.terminal = "screen-256color"; + + wezterm = { + enable = mkDefault true; + config = { + default_prog = ["zsh" "--login"]; + enable_wayland = false; + enable_tab_bar = false; + font = "lua wezterm.font(\"Fira Code\")"; + font_size = 10; + }; + enableZshIntegration = true; + }; + + zsh.enable = true; + zsh.enableAutosuggestions = true; + zsh.enableCompletion = true; + zsh.initExtra = '' + export GPG_TTY=$(tty) + + alias tmux="tmux -f ${config.xdg.configHome}/tmux/tmux.conf"; + ''; + }; + }; +} diff --git a/modules/home-manager/programs/davinci.nix b/modules/home-manager/programs-old/davinci.nix similarity index 60% rename from modules/home-manager/programs/davinci.nix rename to modules/home-manager/programs-old/davinci.nix index f74b28e..abc495f 100644 --- a/modules/home-manager/programs/davinci.nix +++ b/modules/home-manager/programs-old/davinci.nix @@ -1,11 +1,14 @@ -{ config, lib, pkgs, ... }: - -let - cfg = config.davinci; -in { - imports = [ ]; - options.davinci = with lib; with lib.types; { + config, + lib, + pkgs, + ... +}: let + cfg = config.davinci; +in { + imports = []; + options.davinci = with lib; + with lib.types; { enable = mkEnableOption ""; }; config = lib.mkIf cfg.enable { diff --git a/modules/home-manager/programs/eww/default.nix b/modules/home-manager/programs-old/eww/default.nix similarity index 95% rename from modules/home-manager/programs/eww/default.nix rename to modules/home-manager/programs-old/eww/default.nix index 10dcd94..9d1de09 100644 --- a/modules/home-manager/programs/eww/default.nix +++ b/modules/home-manager/programs-old/eww/default.nix @@ -1,6 +1,9 @@ -{ lib, config, pkgs, ... }: - -let +{ + lib, + config, + pkgs, + ... +}: let cfg = config.eww; ewwDir = "${config.xdg.configHome}/eww"; @@ -9,7 +12,7 @@ let jq="${pkgs.jq}/bin/jq" socat="${pkgs.socat}/bin/socat" - $hyprctl monitors -j | + $hyprctl monitors -j | $jq '.[] | select(.focused) | .activeWorkspace.id' $socat -u UNIX-CONNECT:/tmp/hypr/$HYPRLAND_INSTANCE_SIGNATURE/.socket2.sock - | @@ -57,14 +60,13 @@ let echo $rain fi ''; -in -{ - imports = [ ]; - options.eww = with lib; with lib.types; { +in { + imports = []; + options.eww = with lib; + with lib.types; { enable = mkEnableOption ""; }; config = lib.mkIf cfg.enable { - home.packages = with pkgs; [ eww-wayland ]; @@ -73,7 +75,7 @@ in home.file."${ewwDir}/eww.scss".source = ./eww.scss; home.file."${ewwDir}/vars.yuck".text = '' - (deflisten active-workspace :initial "1" + (deflisten active-workspace :initial "1" "${eww-get-active-workspace}/bin/eww-get-active-workspace") (defpoll volume :interval "1s" @@ -111,5 +113,3 @@ in ''; }; } - - diff --git a/modules/home-manager/programs/eww/eww.scss b/modules/home-manager/programs-old/eww/eww.scss similarity index 100% rename from modules/home-manager/programs/eww/eww.scss rename to modules/home-manager/programs-old/eww/eww.scss diff --git a/modules/home-manager/programs/eww/eww.yuck b/modules/home-manager/programs-old/eww/eww.yuck similarity index 100% rename from modules/home-manager/programs/eww/eww.yuck rename to modules/home-manager/programs-old/eww/eww.yuck diff --git a/modules/home-manager/programs/hyprland.nix b/modules/home-manager/programs-old/hyprland.nix similarity index 65% rename from modules/home-manager/programs/hyprland.nix rename to modules/home-manager/programs-old/hyprland.nix index 0a03d3e..8f6b098 100644 --- a/modules/home-manager/programs/hyprland.nix +++ b/modules/home-manager/programs-old/hyprland.nix @@ -1,14 +1,18 @@ -{ config, inputs, lib, pkgs, ... }: - -let - cfg = config.hyprland; -in { - imports = [ ]; - options.hyprland = with lib; with lib.types; { + config, + inputs, + lib, + pkgs, + ... +}: let + cfg = config.hyprland; +in { + imports = []; + options.hyprland = with lib; + with lib.types; { enable = mkEnableOption ""; monitors = mkOption { - default = [ ]; + default = []; /* type = listOf (submodule ({ ... }: { options = { @@ -38,15 +42,15 @@ in */ }; exec = mkOption { - default = [ ]; + default = []; type = listOf str; }; env = mkOption { - default = { }; + default = {}; type = attrsOf str; }; windowRules = mkOption { - default = { }; + default = {}; description = "window = [ \"rule\" ]"; type = attrsOf (listOf str); }; @@ -119,13 +123,15 @@ in }; }; workspaces = mkOption { - default = [ ]; - /* type = { - name = str; - monitor = nullOr str; - default = nullOr bool; - extraRules = nullOr str; - }; */ + default = []; + /* + type = { + name = str; + monitor = nullOr str; + default = nullOr bool; + extraRules = nullOr str; + }; + */ }; binds = { mod = mkOption { @@ -133,11 +139,11 @@ in type = str; }; keyboard = mkOption { - default = [ ]; + default = []; type = listOf str; }; mouse = mkOption { - default = [ ]; + default = []; type = listOf str; }; }; @@ -151,24 +157,36 @@ in wayland.windowManager.hyprland.settings = lib.mkMerge [ # Sets monitor variables ("$name" = "id") so it can be used in rules later - (builtins.listToAttrs (map - (m: { - name = "\$${m.name}"; - value = "${m.id}"; - }) - cfg.monitors) + ( + builtins.listToAttrs (map + (m: { + name = "\$${m.name}"; + value = "${m.id}"; + }) + cfg.monitors) ) { # Construct the "name,resolution@hz,offset,scale" strings - monitor = (map - (m: - "${m.name},${m.resolution}@${ - toString (if m?hz then m.hz else 60) - },${ - if m?offset then m.offset else "0x0" - },${ - toString (if m?scale then m.scale else 1) - }" + monitor = ( + map + ( + m: "${m.name},${m.resolution}@${ + toString ( + if m ? hz + then m.hz + else 60 + ) + },${ + if m ? offset + then m.offset + else "0x0" + },${ + toString ( + if m ? scale + then m.scale + else 1 + ) + }" ) cfg.monitors ); @@ -177,7 +195,8 @@ in # "Hack" to transform attributes sets to lists (because I didn't know other way to do it) # Transform { "envName" = "value" } to [ "envName,value" ] - env = builtins.attrValues + env = + builtins.attrValues (builtins.mapAttrs (n: v: "${n},${v}") (lib.attrsets.mergeAttrsList [ { "XCURSOR_SIZE" = "24"; @@ -186,44 +205,46 @@ in cfg.env ])); - - windowrulev2 = - let - firefoxPipRules = [ - "float" - # "nofullscreenrequest" - "size 480 270" - "fakefullscreen" - "nodim" - "noblur" - ]; - in + windowrulev2 = let + firefoxPipRules = [ + "float" + # "nofullscreenrequest" + "size 480 270" + "fakefullscreen" + "nodim" + "noblur" + ]; + in builtins.concatLists - (builtins.attrValues (builtins.mapAttrs - (w: rs: - (map (r: "${r},${w}") rs) - ) - (lib.attrsets.mergeAttrsList [ - { - "title:^(Picture-in-Picture)$,class:^(firefox)$" = firefoxPipRules; - "title:^(Firefox)$,class:^(firefox)$" = firefoxPipRules; - "title:^(Picture-in-Picture)$" = firefoxPipRules; - "class:^(xwaylandvideobridge)$" = [ - "opacity 0.0 override 0.0 override" - "noanim" - "nofocus" - "noinitialfocus" - ]; - } - cfg.windowRules - ]) - )); + (builtins.attrValues ( + builtins.mapAttrs + ( + w: rs: (map (r: "${r},${w}") rs) + ) + (lib.attrsets.mergeAttrsList [ + { + "title:^(Picture-in-Picture)$,class:^(firefox)$" = firefoxPipRules; + "title:^(Firefox)$,class:^(firefox)$" = firefoxPipRules; + "title:^(Picture-in-Picture)$" = firefoxPipRules; + "class:^(xwaylandvideobridge)$" = [ + "opacity 0.0 override 0.0 override" + "noanim" + "nofocus" + "noinitialfocus" + ]; + } + cfg.windowRules + ]) + )); input = { kb_layout = cfg.input.keyboard.layout; kb_variant = cfg.input.keyboard.variant; - follow_mouse = if cfg.input.mouse.follow then "1" else "0"; + follow_mouse = + if cfg.input.mouse.follow + then "1" + else "0"; sensitivity = toString cfg.input.mouse.sensitivity; }; @@ -240,7 +261,10 @@ in decoration = { rounding = toString cfg.decoration.rouding; - dim_inactive = if cfg.decoration.dim.inactive then "true" else "false"; + dim_inactive = + if cfg.decoration.dim.inactive + then "true" + else "false"; dim_strength = toString cfg.decoration.dim.strength; dim_around = toString cfg.decoration.dim.around; @@ -251,7 +275,10 @@ in }; animations = { - enabled = if cfg.animations.enabled then "yes" else "no"; + enabled = + if cfg.animations.enabled + then "yes" + else "no"; bezier = "myBezier, 0.05, 0.9, 0.1, 1.05"; @@ -278,31 +305,29 @@ in workspace_swipe = "off"; }; - workspace = - (map - (w: "${w.name},${ - if w?monitor then "monitor:${w.monitor}," else "" - }${ - if w?default && w.default then "default:true," else "" - }${ - if w?extraRules then "${w.extraRules}" else "" - }") - cfg.workspaces - ); + workspace = ( + map + (w: "${w.name},${ + if w ? monitor + then "monitor:${w.monitor}," + else "" + }${ + if w ? default && w.default + then "default:true," + else "" + }${ + if w ? extraRules + then "${w.extraRules}" + else "" + }") + cfg.workspaces + ); "$mod" = cfg.binds.mod; bind = cfg.binds.keyboard; bindm = cfg.binds.mouse; - } ]; }; } - - - - - - - diff --git a/modules/home-manager/programs/krita/default.nix b/modules/home-manager/programs-old/krita/default.nix similarity index 63% rename from modules/home-manager/programs/krita/default.nix rename to modules/home-manager/programs-old/krita/default.nix index 03efd9c..fda0aba 100644 --- a/modules/home-manager/programs/krita/default.nix +++ b/modules/home-manager/programs-old/krita/default.nix @@ -1,15 +1,18 @@ -{ config, lib, pkgs, ... }: - -let - cfg = config.krita; -in { - imports = [ ]; - options.krita = with lib; with lib.types; { + config, + lib, + pkgs, + ... +}: let + cfg = config.krita; +in { + imports = []; + options.krita = with lib; + with lib.types; { enable = mkEnableOption ""; }; config = lib.mkIf cfg.enable { - home.packages = with pkgs; [ krita ]; + home.packages = with pkgs; [krita]; home.file."${config.xdg.configHome}/kritarc".source = ./kritarc; home.file."${config.xdg.configHome}/kritashortcutsrc".source = ./kritashortcutsrc; diff --git a/modules/home-manager/programs/krita/kritarc b/modules/home-manager/programs-old/krita/kritarc similarity index 100% rename from modules/home-manager/programs/krita/kritarc rename to modules/home-manager/programs-old/krita/kritarc diff --git a/modules/home-manager/programs/krita/kritashortcutsrc b/modules/home-manager/programs-old/krita/kritashortcutsrc similarity index 100% rename from modules/home-manager/programs/krita/kritashortcutsrc rename to modules/home-manager/programs-old/krita/kritashortcutsrc diff --git a/modules/home-manager/programs-old/lf.nix b/modules/home-manager/programs-old/lf.nix new file mode 100644 index 0000000..ac85676 --- /dev/null +++ b/modules/home-manager/programs-old/lf.nix @@ -0,0 +1,94 @@ +{ + config, + lib, + pkgs, + ... +}: let + cfg = config.lf; +in { + imports = []; + options.lf = with lib; + with lib.types; { + enable = mkEnableOption ""; + }; + config = lib.mkIf cfg.enable { + programs.lf = { + enable = true; + + settings = { + preview = true; + hidden = true; + drawbox = true; + icons = true; + ignorecase = true; + }; + + commands = { + delete-trash = '' ''${{ + touch "${config.xdg.dataHome}/Trash/info/$(basename $f).trashinfo" + + echo "[Trash Info]" > "${config.xdg.dataHome}/Trash/info/$(basename $f).trashinfo" + echo "Path=$f" >> "${config.xdg.dataHome}/Trash/info/$(basename $f).trashinfo" + echo "DeletionDate=$(date +%Y-%m-%dT%H:%M:%S)" >> "${config.xdg.dataHome}/Trash/info/$(basename $f).trashinfo" + + mv $f ${config.xdg.dataHome}/Trash/files + }}''; + dragon-out = ''%${pkgs.xdragon}/bin/xdragon -a -x "$fx"''; + editor-open = ''$$EDITOR $f''; + mkfile = '' ''${{ + printf "Dirname: " + read DIR + + if [[ $DIR = */ ]]; then + mkdir $DIR + else + touch $DIR + fi + }}''; + mkdir = '' ''${{ + printf "Dirname: " + read DIR + mkdir $DIR + }}''; + trash = ''cd ${config.xdg.dataHome}/Trash/files''; + trash-recover = '' ''${{ + mv $f "$(cat "${config.xdg.dataHome}/Trash/info/$(basename $f).trashinfo" | sed -n '2 p' | tr "=" "\n" | sed -n '2 p')" + rm -rf "${config.xdg.dataHome}/Trash/info/$(basename $f).trashinfo" + }}''; + }; + + keybindings = { + "." = "set hidden!"; + "" = "open"; + a = "mkfile"; + A = "mkdir"; + D = "delete"; + R = "trash-recover"; + ee = "editor-open"; + }; + + extraConfig = let + previewer = pkgs.writeShellScriptBin "pv.sh" '' + file=$1 + w=$2 + h=$3 + x=$4 + y=$5 + + if [[ "$(${pkgs.file}/bin/file -Lb --mime-type "$file")" =~ ^image ]]; then + ${pkgs.kitty}/bin/kitty +kitten icat --silent --stdin no --transfer-mode file --place "''${w}x''${h}@''${x}x''${y}" "$file" < /dev/null > /dev/tty + exit 1 + fi + + ${pkgs.pistol}/bin/pistol "$file" + ''; + cleaner = pkgs.writeShellScriptBin "clean.sh" '' + ${pkgs.kitty}/bin/kitty +kitten icat --clear --stdin no --silent --transfer-mode file < /dev/null > /dev/tty + ''; + in '' + set cleaner ${cleaner}/bin/clean.sh + set previewer ${previewer}/bin/pv.sh + ''; + }; + }; +} diff --git a/modules/home-manager/programs-old/librewolf/default.nix b/modules/home-manager/programs-old/librewolf/default.nix new file mode 100644 index 0000000..62a8e77 --- /dev/null +++ b/modules/home-manager/programs-old/librewolf/default.nix @@ -0,0 +1,437 @@ +/* +THIS FILE ISN'T LICENSED UNDER THE WTFPL LICENSE. + +This file is copied from Home-manager's GitHub and was modified to suit my +(Gustavo "Guz" L. de Mello) personal needs. The original file can be found +here: https://github.com/nix-community/home-manager/blob/master/modules/programs/firefox.nix + +Said file is licensed under the MIT License, which a copy is written below: + +MIT License + +Copyright (c) 2017-2023 Home Manager contributors +Copyright (c) 2023-present Gustavo "Guz" L. de Mello + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ +{ + config, + lib, + pkgs, + ... +}: +with lib; let + cfg = config.librewolf; + + jsonFormat = pkgs.formats.json {}; + + firefoxConfigPath = ".librewolf"; + profilesPath = firefoxConfigPath; + + # The extensions path shared by all profiles; will not be supported + # by future Firefox versions. + extensionPath = "extensions/{ec8030f7-c20a-464f-9b0e-13a3a9e97384}"; + + profiles = + flip mapAttrs' cfg.profiles + (_: profile: + nameValuePair "Profile${toString profile.id}" { + Name = profile.name; + Path = profile.path; + IsRelative = 1; + Default = + if profile.isDefault + then 1 + else 0; + }) + // { + General = {StartWithLastProfile = 1;}; + }; + + profilesIni = generators.toINI {} profiles; + + userPrefValue = pref: + builtins.toJSON ( + if isBool pref || isInt pref || isString pref + then pref + else builtins.toJSON pref + ); + + mkUserJs = prefs: extraPrefs: bookmarks: let + prefs' = + lib.optionalAttrs ([] != bookmarks) + { + "browser.bookmarks.file" = toString (firefoxBookmarksFile bookmarks); + "browser.places.importBookmarksHTML" = true; + } + // prefs; + in '' + // Generated by Home Manager. + + ${concatStrings (mapAttrsToList (name: value: '' + user_pref("${name}", ${userPrefValue value}); + '') + prefs')} + + ${extraPrefs} + ''; + + mkContainersJson = containers: let + containerToIdentity = _: container: { + userContextId = container.id; + name = container.name; + icon = container.icon; + color = container.color; + public = true; + }; + in '' + ${builtins.toJSON { + version = 4; + lastUserContextId = + elemAt (mapAttrsToList (_: container: container.id) containers) 0; + identities = mapAttrsToList containerToIdentity containers; + }} + ''; + + firefoxBookmarksFile = bookmarks: let + indent = level: + lib.concatStringsSep "" (map (lib.const " ") (lib.range 1 level)); + + bookmarkToHTML = indentLevel: bookmark: '' + ${indent indentLevel}
${escapeXML bookmark.name}''; + + directoryToHTML = indentLevel: directory: '' + ${indent indentLevel}
${ + if directory.toolbar + then '' +

Bookmarks Toolbar'' + else ''

${escapeXML directory.name}'' + }

+ ${indent indentLevel}

+ ${allItemsToHTML (indentLevel + 1) directory.bookmarks} + ${indent indentLevel}

''; + + itemToHTMLOrRecurse = indentLevel: item: + if item ? "url" + then bookmarkToHTML indentLevel item + else directoryToHTML indentLevel item; + + allItemsToHTML = indentLevel: bookmarks: + lib.concatStringsSep "\n" + (map (itemToHTMLOrRecurse indentLevel) bookmarks); + + bookmarkEntries = allItemsToHTML 1 bookmarks; + in + pkgs.writeText "firefox-bookmarks.html" '' + + + + Bookmarks +

Bookmarks Menu

+

+ ${bookmarkEntries} +

+ ''; + + mkNoDuplicateAssertion = entities: entityKind: ( + let + # Return an attribute set with entity IDs as keys and a list of + # entity names with corresponding ID as value. An ID is present in + # the result only if more than one entity has it. The argument + # entities is a list of AttrSet of one id/name pair. + findDuplicateIds = entities: + filterAttrs (_entityId: entityNames: length entityNames != 1) + (zipAttrs entities); + + duplicates = findDuplicateIds (mapAttrsToList + (entityName: entity: {"${toString entity.id}" = entityName;}) + entities); + + mkMsg = entityId: entityNames: + " - ID ${entityId} is used by " + concatStringsSep ", " entityNames; + in { + assertion = duplicates == {}; + message = + '' + Must not have a Firefox ${entityKind} with an existing ID but + '' + + concatStringsSep "\n" (mapAttrsToList mkMsg duplicates); + } + ); +in { + imports = []; + options.librewolf = with lib; + with lib.types; { + enable = mkEnableOption "Enable module"; + overrides = mkOption { + default = {}; + type = attrsOf (either bool (either int str)); + }; + profiles = mkOption { + type = attrsOf (submodule ({ + config, + name, + ... + }: { + options = { + name = mkOption { + type = str; + default = name; + }; + id = mkOption { + type = ints.unsigned; + default = 0; + }; + settings = mkOption { + type = attrsOf (jsonFormat.type + // { + description = ""; + }); + default = {}; + }; + extraConfig = mkOption { + type = lines; + default = ""; + }; + userChrome = mkOption { + type = lines; + default = ""; + }; + userContent = mkOption { + type = lines; + default = ""; + }; + bookmarks = + mkOption + { + type = let + bookmarkSubmodule = + submodule + ({ + config, + name, + ... + }: { + options = { + name = mkOption { + type = str; + default = name; + }; + tags = mkOption { + type = listOf str; + default = []; + }; + keyword = mkOption { + type = nullOr str; + default = null; + }; + url = mkOption { + type = str; + }; + }; + }); + bookmarkType = addCheck bookmarkSubmodule (x: x ? "url"); + + directoryType = submodule ({ + config, + name, + ... + }: { + options = { + name = mkOption { + type = str; + default = name; + }; + bookmarks = mkOption { + type = listOf nodeType; + default = []; + }; + toolbar = mkOption { + type = bool; + default = false; + }; + }; + }); + + nodeType = either bookmarkType directoryType; + in + with types; + coercedTo (attrsOf nodeType) attrValues (listOf nodeType); + default = []; + }; + path = mkOption { + type = str; + default = name; + }; + isDefault = mkOption { + type = bool; + default = config.id == 0; + }; + # For some reason Librewolf isn't working with the generated file, so + # a static one is passed as a temp fix. + search.file = mkOption { + type = path; + default = ./search.json.mozlz4; + }; + /* + search = { + force = mkOption { + type = bool; + default = false; + }; + default = mkOption { + type = nullOr str; + default = null; + }; + privateDefault = mkOption { + type = nullOr str; + default = null; + }; + order = mkOption { + type = uniq (listOf str); + default = [ ]; + }; + engines = mkOption { + type = attrsOf (attrsOf jsonFormat.type); + default = { }; + }; + }; + */ + containers = mkOption { + type = + attrsOf + (submodule ({name, ...}: { + options = { + name = mkOption { + type = str; + default = name; + }; + id = mkOption { + type = ints.unsigned; + default = 0; + }; + color = mkOption { + type = enum [ + "blue" + "turquoise" + "green" + "yellow" + "orange" + "red" + "pink" + "purple" + "toolbar" + ]; + default = "pink"; + }; + icon = mkOption { + type = enum [ + "briefcase" + "cart" + "circle" + "dollar" + "fence" + "fingerprint" + "gift" + "vacation" + "food" + "fruit" + "pet" + "tree" + "chill" + ]; + default = "fruit"; + }; + }; + })); + default = {}; + }; + extensions = mkOption { + type = listOf package; + default = []; + }; + }; + })); + default = {}; + }; + }; + config = lib.mkIf cfg.enable { + programs.librewolf.enable = true; + programs.librewolf.settings = cfg.overrides; + + home.file = mkMerge ([ + { + "${firefoxConfigPath}/profiles.ini" = mkIf (cfg.profiles != {}) { + text = profilesIni; + force = true; + }; + } + ] + ++ flip mapAttrsToList cfg.profiles (_: profile: { + "${profilesPath}/${profile.path}/.keep".text = ""; + + "${profilesPath}/${profile.path}/chrome/userChrome.css" = + mkIf (profile.userChrome != "") {text = profile.userChrome;}; + + "${profilesPath}/${profile.path}/chrome/userContent.css" = + mkIf (profile.userContent != "") {text = profile.userContent;}; + + "${profilesPath}/${profile.path}/user.js" = + mkIf + (profile.settings + != {} + || profile.extraConfig != "" + || profile.bookmarks != []) + { + text = + mkUserJs profile.settings profile.extraConfig profile.bookmarks; + }; + + "${profilesPath}/${profile.path}/containers.json" = mkIf (profile.containers != {}) { + text = mkContainersJson profile.containers; + }; + + "${profilesPath}/${profile.path}/search.json.mozlz4" = { + force = true; + source = ./search.json.mozlz4; # Use static file, because for some reason this isn't working with Librewolf. + }; + + "${profilesPath}/${profile.path}/extensions" = mkIf (profile.extensions != []) { + source = let + extensionsEnvPkg = pkgs.buildEnv { + name = "hm-firefox-extensions"; + paths = profile.extensions; + }; + in "${extensionsEnvPkg}/share/mozilla/${extensionPath}"; + recursive = true; + force = true; + }; + })); + }; +} diff --git a/modules/home-manager/programs/librewolf/search.json.mozlz4 b/modules/home-manager/programs-old/librewolf/search.json.mozlz4 similarity index 100% rename from modules/home-manager/programs/librewolf/search.json.mozlz4 rename to modules/home-manager/programs-old/librewolf/search.json.mozlz4 diff --git a/modules/home-manager/programs/obs.nix b/modules/home-manager/programs-old/obs.nix similarity index 73% rename from modules/home-manager/programs/obs.nix rename to modules/home-manager/programs-old/obs.nix index 86ae2ca..588ec36 100644 --- a/modules/home-manager/programs/obs.nix +++ b/modules/home-manager/programs-old/obs.nix @@ -1,11 +1,14 @@ -{ config, lib, pkgs, ... }: - -let - cfg = config.obs; -in { - imports = [ ]; - options.obs = with lib; with lib.types; { + config, + lib, + pkgs, + ... +}: let + cfg = config.obs; +in { + imports = []; + options.obs = with lib; + with lib.types; { enable = mkEnableOption ""; }; config = lib.mkIf cfg.enable { diff --git a/modules/home-manager/programs/obsidian.nix b/modules/home-manager/programs-old/obsidian.nix similarity index 80% rename from modules/home-manager/programs/obsidian.nix rename to modules/home-manager/programs-old/obsidian.nix index 78c0895..b468caa 100644 --- a/modules/home-manager/programs/obsidian.nix +++ b/modules/home-manager/programs-old/obsidian.nix @@ -1,7 +1,9 @@ -{ config, lib, pkgs, ... }: - - -let +{ + config, + lib, + pkgs, + ... +}: let cfg = config.obsidian; vaultCmd = pkgs.writeShellScriptBin "vault" '' command="$1"; @@ -18,10 +20,10 @@ let $git push fi ''; -in -{ - imports = [ ]; - options.obsidian = with lib; with lib.types; { +in { + imports = []; + options.obsidian = with lib; + with lib.types; { enable = mkEnableOption ""; vaultCmd = mkOption { type = bool; @@ -37,7 +39,11 @@ in "md.obsidian.Obsidian" ]; home.packages = [ - (if cfg.vaultCmd then vaultCmd else null) + ( + if cfg.vaultCmd + then vaultCmd + else null + ) ]; }; } diff --git a/modules/home-manager/programs/starship.nix b/modules/home-manager/programs-old/starship.nix similarity index 80% rename from modules/home-manager/programs/starship.nix rename to modules/home-manager/programs-old/starship.nix index da0ab50..ef3710a 100644 --- a/modules/home-manager/programs/starship.nix +++ b/modules/home-manager/programs-old/starship.nix @@ -1,11 +1,13 @@ -{ config, lib, ... }: - -let - cfg = config.starship; -in { - imports = [ ]; - options.starship = with lib; with lib.types; { + config, + lib, + ... +}: let + cfg = config.starship; +in { + imports = []; + options.starship = with lib; + with lib.types; { enable = mkEnableOption "Enable module"; enableZsh = mkEnableOption "Enable Zsh Integration"; enableBash = mkEnableOption "Enable Bash Integration"; diff --git a/modules/home-manager/programs/tmux.nix b/modules/home-manager/programs-old/tmux.nix similarity index 94% rename from modules/home-manager/programs/tmux.nix rename to modules/home-manager/programs-old/tmux.nix index ebcbcc5..4d0d1f6 100644 --- a/modules/home-manager/programs/tmux.nix +++ b/modules/home-manager/programs-old/tmux.nix @@ -1,11 +1,15 @@ -{ config, inputs, lib, pkgs, ... }: - -let - cfg = config.tmux; -in { - imports = [ ]; - options.tmux = with lib; with lib.types; { + config, + inputs, + lib, + pkgs, + ... +}: let + cfg = config.tmux; +in { + imports = []; + options.tmux = with lib; + with lib.types; { enable = mkEnableOption "Enable Tmux module"; baseIndex = mkOption { type = ints.unsigned; diff --git a/modules/home-manager/programs-old/wezterm.nix b/modules/home-manager/programs-old/wezterm.nix new file mode 100644 index 0000000..363308f --- /dev/null +++ b/modules/home-manager/programs-old/wezterm.nix @@ -0,0 +1,84 @@ +{ + config, + lib, + ... +}: let + cfg = config.wezterm; +in { + imports = []; + options.wezterm = with lib; + with lib.types; { + enable = mkEnableOption "Enable Wezterm"; + integration = { + zsh = mkEnableOption "Enable Zsh Integration"; + }; + colorScheme = mkOption { + type = str; + default = "system"; + }; + defaultProg = mkOption { + default = []; + }; + font = mkOption { + default = "Fira Code"; + type = str; + }; + fontSize = mkOption { + default = 12; + type = number; + }; + }; + config = lib.mkIf cfg.enable { + programs.wezterm.enable = true; + programs.wezterm.enableZshIntegration = lib.mkIf (cfg.integration.zsh) true; + + programs.wezterm.extraConfig = '' + return { + enable_tab_bar = false; + color_scheme = "${cfg.colorScheme}", + default_prog = { ${lib.concatMapStrings (x: "'" + x + "',") cfg.defaultProg} }, + font = wezterm.font("${cfg.font}"), + font_size = ${toString cfg.fontSize}, + enable_wayland = false, -- TEMPORALLY FIX (see wez/wezterm#4483) + } + ''; + + programs.wezterm.colorSchemes = { + system = with config.colorScheme.palette; { + foreground = "#${base05}"; + background = "#${base00}"; + + cursor_fg = "#${base01}"; + cursor_bg = "#${config.theme.accent}"; + cursor_border = "#${config.theme.accent}"; + + selection_fg = "#${base04}"; + selection_bg = "#${config.theme.accent}"; + + split = "#${base04}"; + + ansi = [ + "#${base03}" + "#${base08}" + "#${base0B}" + "#${base0A}" + "#${base0D}" + "#${base0E}" + "#${base0C}" + "#${base03}" + ]; + + brights = [ + "#${base03}" + "#${base08}" + "#${base0B}" + "#${base0A}" + "#${base0D}" + "#${base0E}" + "#${base0C}" + "#${base03}" + ]; + }; + }; + }; +} diff --git a/modules/home-manager/programs/zsh.nix b/modules/home-manager/programs-old/zsh.nix similarity index 91% rename from modules/home-manager/programs/zsh.nix rename to modules/home-manager/programs-old/zsh.nix index fe53e46..72bed5b 100644 --- a/modules/home-manager/programs/zsh.nix +++ b/modules/home-manager/programs-old/zsh.nix @@ -1,11 +1,13 @@ -{ config, lib, ... }: - -let - cfg = config.zsh; -in { - imports = [ ]; - options.zsh = with lib; with lib.types; { + config, + lib, + ... +}: let + cfg = config.zsh; +in { + imports = []; + options.zsh = with lib; + with lib.types; { enable = mkEnableOption "Enable Zsh shell"; plugins = { suggestions.enable = mkOption { @@ -41,7 +43,7 @@ in }; variables = mkOption { type = attrsOf str; - default = { }; + default = {}; }; }; config = lib.mkIf cfg.enable { diff --git a/modules/home-manager/programs/default.nix b/modules/home-manager/programs/default.nix new file mode 100644 index 0000000..1ecc463 --- /dev/null +++ b/modules/home-manager/programs/default.nix @@ -0,0 +1,8 @@ +{...}: { + imports = [ + ./neovim.nix + ./wezterm.nix + ]; + options = {}; + config = {}; +} diff --git a/modules/home-manager/programs/lf.nix b/modules/home-manager/programs/lf.nix deleted file mode 100644 index fbf6325..0000000 --- a/modules/home-manager/programs/lf.nix +++ /dev/null @@ -1,95 +0,0 @@ -{ config, lib, pkgs, ... }: - -let - cfg = config.lf; -in -{ - imports = [ ]; - options.lf = with lib; with lib.types; { - enable = mkEnableOption ""; - }; - config = lib.mkIf cfg.enable { - programs.lf = { - enable = true; - - settings = { - preview = true; - hidden = true; - drawbox = true; - icons = true; - ignorecase = true; - }; - - commands = { - delete-trash = ''''${{ - touch "${config.xdg.dataHome}/Trash/info/$(basename $f).trashinfo" - - echo "[Trash Info]" > "${config.xdg.dataHome}/Trash/info/$(basename $f).trashinfo" - echo "Path=$f" >> "${config.xdg.dataHome}/Trash/info/$(basename $f).trashinfo" - echo "DeletionDate=$(date +%Y-%m-%dT%H:%M:%S)" >> "${config.xdg.dataHome}/Trash/info/$(basename $f).trashinfo" - - mv $f ${config.xdg.dataHome}/Trash/files - }}''; - dragon-out = ''%${pkgs.xdragon}/bin/xdragon -a -x "$fx"''; - editor-open = ''$$EDITOR $f''; - mkfile = ''''${{ - printf "Dirname: " - read DIR - - if [[ $DIR = */ ]]; then - mkdir $DIR - else - touch $DIR - fi - }}''; - mkdir = ''''${{ - printf "Dirname: " - read DIR - mkdir $DIR - }}''; - trash = ''cd ${config.xdg.dataHome}/Trash/files''; - trash-recover = ''''${{ - mv $f "$(cat "${config.xdg.dataHome}/Trash/info/$(basename $f).trashinfo" | sed -n '2 p' | tr "=" "\n" | sed -n '2 p')" - rm -rf "${config.xdg.dataHome}/Trash/info/$(basename $f).trashinfo" - }}''; - }; - - keybindings = { - "." = "set hidden!"; - "" = "open"; - a = "mkfile"; - A = "mkdir"; - D = "delete"; - R = "trash-recover"; - ee = "editor-open"; - }; - - extraConfig = - let - previewer = pkgs.writeShellScriptBin "pv.sh" '' - file=$1 - w=$2 - h=$3 - x=$4 - y=$5 - - if [[ "$(${pkgs.file}/bin/file -Lb --mime-type "$file")" =~ ^image ]]; then - ${pkgs.kitty}/bin/kitty +kitten icat --silent --stdin no --transfer-mode file --place "''${w}x''${h}@''${x}x''${y}" "$file" < /dev/null > /dev/tty - exit 1 - fi - - ${pkgs.pistol}/bin/pistol "$file" - ''; - cleaner = pkgs.writeShellScriptBin "clean.sh" '' - ${pkgs.kitty}/bin/kitty +kitten icat --clear --stdin no --silent --transfer-mode file < /dev/null > /dev/tty - ''; - in - '' - set cleaner ${cleaner}/bin/clean.sh - set previewer ${previewer}/bin/pv.sh - ''; - }; - }; -} - - diff --git a/modules/home-manager/programs/librewolf/default.nix b/modules/home-manager/programs/librewolf/default.nix deleted file mode 100644 index fa91ef2..0000000 --- a/modules/home-manager/programs/librewolf/default.nix +++ /dev/null @@ -1,416 +0,0 @@ -/* - THIS FILE ISN'T LICENSED UNDER THE WTFPL LICENSE. - - This file is copied from Home-manager's GitHub and was modified to suit my - (Gustavo "Guz" L. de Mello) personal needs. The original file can be found - here: https://github.com/nix-community/home-manager/blob/master/modules/programs/firefox.nix - - Said file is licensed under the MIT License, which a copy is written below: - - MIT License - - Copyright (c) 2017-2023 Home Manager contributors - Copyright (c) 2023-present Gustavo "Guz" L. de Mello - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*/ - -{ config, lib, pkgs, ... }: - -with lib; -let - cfg = config.librewolf; - - jsonFormat = pkgs.formats.json { }; - - firefoxConfigPath = ".librewolf"; - profilesPath = firefoxConfigPath; - - # The extensions path shared by all profiles; will not be supported - # by future Firefox versions. - extensionPath = "extensions/{ec8030f7-c20a-464f-9b0e-13a3a9e97384}"; - - profiles = flip mapAttrs' cfg.profiles - (_: profile: - nameValuePair "Profile${toString profile.id}" { - Name = profile.name; - Path = profile.path; - IsRelative = 1; - Default = if profile.isDefault then 1 else 0; - }) // { - General = { StartWithLastProfile = 1; }; - }; - - profilesIni = generators.toINI { } profiles; - - userPrefValue = pref: - builtins.toJSON (if isBool pref || isInt pref || isString pref then - pref - else - builtins.toJSON pref); - - mkUserJs = prefs: extraPrefs: bookmarks: - let - prefs' = lib.optionalAttrs ([ ] != bookmarks) - { - "browser.bookmarks.file" = toString (firefoxBookmarksFile bookmarks); - "browser.places.importBookmarksHTML" = true; - } // prefs; - in - '' - // Generated by Home Manager. - - ${concatStrings (mapAttrsToList (name: value: '' - user_pref("${name}", ${userPrefValue value}); - '') prefs')} - - ${extraPrefs} - ''; - - mkContainersJson = containers: - let - containerToIdentity = _: container: { - userContextId = container.id; - name = container.name; - icon = container.icon; - color = container.color; - public = true; - }; - in - '' - ${builtins.toJSON { - version = 4; - lastUserContextId = - elemAt (mapAttrsToList (_: container: container.id) containers) 0; - identities = mapAttrsToList containerToIdentity containers; - }} - ''; - - firefoxBookmarksFile = bookmarks: - let - indent = level: - lib.concatStringsSep "" (map (lib.const " ") (lib.range 1 level)); - - bookmarkToHTML = indentLevel: bookmark: - '' - ${indent indentLevel}
${escapeXML bookmark.name}''; - - directoryToHTML = indentLevel: directory: '' - ${indent indentLevel}
${ - if directory.toolbar then - '' -

Bookmarks Toolbar'' - else - ''

${escapeXML directory.name}'' - }

- ${indent indentLevel}

- ${allItemsToHTML (indentLevel + 1) directory.bookmarks} - ${indent indentLevel}

''; - - itemToHTMLOrRecurse = indentLevel: item: - if item ? "url" then - bookmarkToHTML indentLevel item - else - directoryToHTML indentLevel item; - - allItemsToHTML = indentLevel: bookmarks: - lib.concatStringsSep "\n" - (map (itemToHTMLOrRecurse indentLevel) bookmarks); - - bookmarkEntries = allItemsToHTML 1 bookmarks; - in - pkgs.writeText "firefox-bookmarks.html" '' - - - - Bookmarks -

Bookmarks Menu

-

- ${bookmarkEntries} -

- ''; - - mkNoDuplicateAssertion = entities: entityKind: - ( - let - # Return an attribute set with entity IDs as keys and a list of - # entity names with corresponding ID as value. An ID is present in - # the result only if more than one entity has it. The argument - # entities is a list of AttrSet of one id/name pair. - findDuplicateIds = entities: - filterAttrs (_entityId: entityNames: length entityNames != 1) - (zipAttrs entities); - - duplicates = findDuplicateIds (mapAttrsToList - (entityName: entity: { "${toString entity.id}" = entityName; }) - entities); - - mkMsg = entityId: entityNames: - " - ID ${entityId} is used by " + concatStringsSep ", " entityNames; - in - { - assertion = duplicates == { }; - message = '' - Must not have a Firefox ${entityKind} with an existing ID but - '' + concatStringsSep "\n" (mapAttrsToList mkMsg duplicates); - } - ); -in -{ - imports = [ ]; - options.librewolf = with lib; with lib.types; { - enable = mkEnableOption "Enable module"; - overrides = mkOption { - default = { }; - type = attrsOf (either bool (either int str)); - }; - profiles = mkOption { - type = attrsOf (submodule ({ config, name, ... }: { - options = { - name = mkOption { - type = str; - default = name; - }; - id = mkOption { - type = ints.unsigned; - default = 0; - }; - settings = mkOption { - type = attrsOf (jsonFormat.type // { - description = ""; - }); - default = { }; - }; - extraConfig = mkOption { - type = lines; - default = ""; - }; - userChrome = mkOption { - type = lines; - default = ""; - }; - userContent = mkOption { - type = lines; - default = ""; - }; - bookmarks = mkOption - { - type = - let - bookmarkSubmodule = submodule - ({ config, name, ... }: { - options = { - name = mkOption { - type = str; - default = name; - }; - tags = mkOption { - type = listOf str; - default = [ ]; - }; - keyword = mkOption { - type = nullOr str; - default = null; - }; - url = mkOption { - type = str; - }; - }; - }); - bookmarkType = addCheck bookmarkSubmodule (x: x ? "url"); - - directoryType = submodule ({ config, name, ... }: { - options = { - name = mkOption { - type = str; - default = name; - }; - bookmarks = mkOption { - type = listOf nodeType; - default = [ ]; - }; - toolbar = mkOption { - type = bool; - default = false; - }; - }; - }); - - nodeType = either bookmarkType directoryType; - in - with types; - coercedTo (attrsOf nodeType) attrValues (listOf nodeType); - default = [ ]; - }; - path = mkOption { - type = str; - default = name; - }; - isDefault = mkOption { - type = bool; - default = config.id == 0; - }; - # For some reason Librewolf isn't working with the generated file, so - # a static one is passed as a temp fix. - search.file = mkOption { - type = path; - default = ./search.json.mozlz4; - }; - /* - search = { - force = mkOption { - type = bool; - default = false; - }; - default = mkOption { - type = nullOr str; - default = null; - }; - privateDefault = mkOption { - type = nullOr str; - default = null; - }; - order = mkOption { - type = uniq (listOf str); - default = [ ]; - }; - engines = mkOption { - type = attrsOf (attrsOf jsonFormat.type); - default = { }; - }; - }; - */ - containers = mkOption { - type = attrsOf - (submodule ({ name, ... }: { - options = { - name = mkOption { - type = str; - default = name; - }; - id = mkOption { - type = ints.unsigned; - default = 0; - }; - color = mkOption { - type = enum [ - "blue" - "turquoise" - "green" - "yellow" - "orange" - "red" - "pink" - "purple" - "toolbar" - ]; - default = "pink"; - }; - icon = mkOption { - type = enum [ - "briefcase" - "cart" - "circle" - "dollar" - "fence" - "fingerprint" - "gift" - "vacation" - "food" - "fruit" - "pet" - "tree" - "chill" - ]; - default = "fruit"; - }; - }; - })); - default = { }; - }; - extensions = mkOption { - type = listOf package; - default = [ ]; - }; - }; - })); - default = { }; - }; - }; - config = lib.mkIf cfg.enable { - programs.librewolf.enable = true; - programs.librewolf.settings = cfg.overrides; - - home.file = mkMerge ([{ - "${firefoxConfigPath}/profiles.ini" = - mkIf (cfg.profiles != { }) { text = profilesIni; force = true; }; - }] ++ flip mapAttrsToList cfg.profiles (_: profile: { - "${profilesPath}/${profile.path}/.keep".text = ""; - - "${profilesPath}/${profile.path}/chrome/userChrome.css" = - mkIf (profile.userChrome != "") { text = profile.userChrome; }; - - "${profilesPath}/${profile.path}/chrome/userContent.css" = - mkIf (profile.userContent != "") { text = profile.userContent; }; - - "${profilesPath}/${profile.path}/user.js" = mkIf - (profile.settings != { } - || profile.extraConfig != "" || profile.bookmarks != [ ]) - { - text = - mkUserJs profile.settings profile.extraConfig profile.bookmarks; - }; - - "${profilesPath}/${profile.path}/containers.json" = - mkIf (profile.containers != { }) { - text = mkContainersJson profile.containers; - }; - - "${profilesPath}/${profile.path}/search.json.mozlz4" = { - force = true; - source = ./search.json.mozlz4; # Use static file, because for some reason this isn't working with Librewolf. - }; - - "${profilesPath}/${profile.path}/extensions" = - mkIf (profile.extensions != [ ]) { - source = - let - extensionsEnvPkg = pkgs.buildEnv { - name = "hm-firefox-extensions"; - paths = profile.extensions; - }; - in - "${extensionsEnvPkg}/share/mozilla/${extensionPath}"; - recursive = true; - force = true; - }; - })); - - }; -} diff --git a/modules/home-manager/programs/neovim.nix b/modules/home-manager/programs/neovim.nix new file mode 100644 index 0000000..1ecdb7d --- /dev/null +++ b/modules/home-manager/programs/neovim.nix @@ -0,0 +1,30 @@ +{ + config, + lib, + pkgs, + ... +}: let + cfg = config.programs.neovim; +in { + imports = []; + config = with lib; + mkIf cfg.enable { + programs.neovim = { + viAlias = true; + vimAlias = true; + withNodeJs = true; + defaultEditor = true; + }; + + home.sessionVariables = mkIf cfg.defaultEditor { + EDITOR = "nvim"; + }; + + home.packages = with pkgs; [ + git + lazygit + gcc + wget + ]; + }; +} diff --git a/modules/home-manager/programs/wezterm.nix b/modules/home-manager/programs/wezterm.nix index 57ba892..968b5c7 100644 --- a/modules/home-manager/programs/wezterm.nix +++ b/modules/home-manager/programs/wezterm.nix @@ -1,82 +1,73 @@ -{ config, lib, ... }: - -let - cfg = config.wezterm; -in { - imports = [ ]; - options.wezterm = with lib; with lib.types; { - enable = mkEnableOption "Enable Wezterm"; - integration = { - zsh = mkEnableOption "Enable Zsh Integration"; - }; - colorScheme = mkOption { - type = str; - default = "system"; - }; - defaultProg = mkOption { - default = [ ]; - }; - font = mkOption { - default = "Fira Code"; - type = str; - }; - fontSize = mkOption { - default = 12; - type = number; + config, + lib, + pkgs, + ... +}: +with builtins; let + cfg = config.programs.wezterm; + jsonFormat = pkgs.formats.json {}; + toLua = with lib.strings; + v: + if isList v + then "{ ${concatMapStringsSep ", " (i: toLua i) v} }" + else if isAttrs v + then "\{ ${concatStringsSep ", " (attrValues (mapAttrs (n: a: "${n} = ${toLua a}") v))} \}" + else if isNull v + then "nil" + else if isBool v + then + if v + then "true" + else "false" + else if isInt v + then toString v + else if isString v && hasPrefix "lua " v + then "${substring 4 (stringLength v) v}" + else "\"${toString v}\""; + configInLua = pkgs.writeText "nih-wezterm-generated-config" '' + local wezterm = require("wezterm"); + + local nih_generated_config = {}; + ${concatStringsSep "\n" (attrValues (mapAttrs + (n: v: "nih_generated_config.${n} = ${toLua v};") + cfg.config))} + + local function extra_config() + ${cfg.extraConfig} + end + + for k,v in pairs(extra_config()) do nih_generated_config[k] = v end + + return nih_generated_config; + ''; + prettyConfig = pkgs.runCommand "nih-wezterm-pretty-config" {config = configInLua;} '' + echo "Nih's Wezterm configuration file builder"; + echo "input file: $config"; + echo "output file: $out"; + echo "" + echo "Formatting config file with Stylua" + cat $config | ${pkgs.stylua}/bin/stylua - > $out + echo "" + echo "Checking erros with luacheck" + ${pkgs.luajitPackages.luacheck}/bin/luacheck \ + --no-max-line-length \ + --no-unused \ + "$out"; + ''; +in { + imports = []; + options.programs.wezterm = with lib; + with lib.types; { + config = mkOption { + type = submodule ({...}: { + freeformType = jsonFormat.type; + }); + default = {}; }; }; - config = lib.mkIf cfg.enable { - programs.wezterm.enable = true; - programs.wezterm.enableZshIntegration = lib.mkIf (cfg.integration.zsh) true; - - programs.wezterm.extraConfig = '' - return { - enable_tab_bar = false; - color_scheme = "${cfg.colorScheme}", - default_prog = { ${lib.concatMapStrings (x: "'" + x + "',") cfg.defaultProg} }, - font = wezterm.font("${cfg.font}"), - font_size = ${toString cfg.fontSize}, - enable_wayland = false, -- TEMPORALLY FIX (see wez/wezterm#4483) - } - ''; - - programs.wezterm.colorSchemes = { - system = with config.colorScheme.palette; { - foreground = "#${base05}"; - background = "#${base00}"; - - cursor_fg = "#${base01}"; - cursor_bg = "#${config.theme.accent}"; - cursor_border = "#${config.theme.accent}"; - - selection_fg = "#${base04}"; - selection_bg = "#${config.theme.accent}"; - - split = "#${base04}"; - - ansi = [ - "#${base03}" - "#${base08}" - "#${base0B}" - "#${base0A}" - "#${base0D}" - "#${base0E}" - "#${base0C}" - "#${base03}" - ]; - - brights = [ - "#${base03}" - "#${base08}" - "#${base0B}" - "#${base0A}" - "#${base0D}" - "#${base0E}" - "#${base0C}" - "#${base03}" - ]; - }; + config = with lib; + mkIf cfg.enable { + xdg.configFile."wezterm/wezterm.lua".source = prettyConfig; }; - }; } diff --git a/modules/home-manager/theme.nix b/modules/home-manager/theme.nix index 2c4a433..dbdfad3 100644 --- a/modules/home-manager/theme.nix +++ b/modules/home-manager/theme.nix @@ -1,13 +1,17 @@ -{ config, lib, inputs, pkgs, ... }: - -let - cfg = config.theme; -in { + config, + lib, + inputs, + pkgs, + ... +}: let + cfg = config.theme; +in { imports = [ inputs.nix-colors.homeManagerModules.default ]; - options.theme = with lib; with lib.types; { + options.theme = with lib; + with lib.types; { accent = mkOption { type = str; default = "cdd6f4"; @@ -36,8 +40,8 @@ in name = "Catppuccin-Mocha-Compact-Mauve-Dark"; package = pkgs.catppuccin-gtk.override { size = "compact"; - tweaks = [ "rimless" "black" ]; - accents = [ "mauve" ]; + tweaks = ["rimless" "black"]; + accents = ["mauve"]; variant = "mocha"; }; }; diff --git a/modules/nih/default.nix b/modules/nih/default.nix index fab70e2..d9236ca 100644 --- a/modules/nih/default.nix +++ b/modules/nih/default.nix @@ -1,17 +1,20 @@ -{ config, lib, pkgs, ... }: - -let - cfg = config.nih; - applyAttrNames = builtins.mapAttrs (name: f: f name); -in { + config, + lib, + pkgs, + ... +}: let + cfg = config.nih; +in { imports = [ - ./sound.nix - ./users.nix + ./domains ./networking ./services + ./sound.nix + ./users.nix ]; - options.nih = with lib; with lib.types; { + options.nih = with lib; + with lib.types; { domain = mkOption { type = str; default = "${cfg.name}.local"; @@ -20,10 +23,6 @@ in flakeDir = mkOption { type = either str path; }; - handleDomains = mkOption { - type = bool; - default = true; - }; ip = mkOption { type = str; }; @@ -36,64 +35,40 @@ in default = "nih"; }; type = mkOption { - type = enum [ "laptop" "desktop" "server" ]; + type = enum ["laptop" "desktop" "server"]; default = "desktop"; }; + _nih = mkOption { + type = attrsOf anything; + default = with builtins; { + servicesNamesList = readDir ./services; + }; + }; }; - config = with lib; mkIf cfg.enable { - boot = { - loader.systemd-boot.enable = mkDefault true; - loader.efi.canTouchEfiVariables = mkDefault true; - }; - - systemd.services."nih-setup" = with builtins; { - script = '' - echo ${builtins.toJSON cfg.users} - ''; - wantedBy = [ "multi-user.target" ]; - after = [ "forgejo.service" ]; - serviceConfig = { - Type = "oneshot"; - }; - }; - - # Handle domains configuration - - networking.firewall.allowedTCPPorts = mkIf cfg.handleDomains [ 80 433 ]; - - services.openssh.enable = mkDefault (if cfg.type == "server" then true else false); - - systemd.services."tailscaled" = mkIf cfg.handleDomains { - serviceConfig = { - Environment = [ "TS_PERMIT_CERT_UID=caddy" ]; - }; - }; - - nih.services = mkIf cfg.handleDomains { - adguard = { - enable = true; - settings.dns.rewrites = (if hasPrefix "*." cfg.domain then { - "${cfg.domain}" = cfg.ip; - } else { - "${cfg.domain}" = cfg.ip; - "${"*." + cfg.domain}" = cfg.ip; - }); + config = with lib; + mkIf cfg.enable { + boot = { + loader.systemd-boot.enable = mkDefault true; + loader.efi.canTouchEfiVariables = mkDefault true; }; - caddy = - let - nihServices = (filterAttrs (n: v: builtins.isAttrs v && v?domain) cfg.services); - in - mkIf cfg.handleDomains { - enable = true; - virtualHosts = mapAttrs' - (name: value: nameValuePair (value.domain) ({ - extraConfig = '' - reverse_proxy ${cfg.localIp}:${toString value.port} - ''; - })) - nihServices; + systemd.services."nih-setup" = with builtins; { + script = '' + echo ${builtins.toJSON cfg._nih.servicesNamesList} + ''; + wantedBy = ["multi-user.target"]; + after = ["forgejo.service"]; + serviceConfig = { + Type = "oneshot"; }; + }; + + # Handle domains configuration + + services.openssh.enable = mkDefault ( + if cfg.type == "server" + then true + else false + ); }; - }; } diff --git a/modules/nih/domains/default.nix b/modules/nih/domains/default.nix new file mode 100644 index 0000000..be85418 --- /dev/null +++ b/modules/nih/domains/default.nix @@ -0,0 +1,32 @@ +{ + config, + lib, + pkgs, + ... +}: let + cfg = config.nih.domains; +in { + imports = [ + ./tailscale.nix + ./tailscale-caddy.nix + ]; + options.nih.domains = with lib; + with lib.types; { + enable = mkOption { + type = bool; + default = false; + }; + domain = mkOption { + type = str; + default = "${config.nih.name}.local"; + }; + handler = mkOption { + type = enum ["tailscale" "tailscale-caddy" "adguard" "adguard-caddy"]; + default = "tailscale"; + }; + }; + config = with lib; + mkIf cfg.enable { + networking.firewall.allowedTCPPorts = [80 433]; + }; +} diff --git a/modules/nih/domains/tailscale-caddy.nix b/modules/nih/domains/tailscale-caddy.nix new file mode 100644 index 0000000..ca56762 --- /dev/null +++ b/modules/nih/domains/tailscale-caddy.nix @@ -0,0 +1,50 @@ +{ + config, + lib, + pkgs, + ... +}: +with lib; +with builtins; let + tailnetName = config.services.tailscale.tailnetName; + ip = config.nih.ip; + domain = config.nih.domains.domain; + listHas = item: list: (lib.lists.count (x: x == item) list) > 0; + servicesList = filterAttrs (n: v: (listHas n ["adguardhome" "caddy" "tailscale"])) config.services; + servicesWithDomain = filterAttrs (n: v: isAttrs v && v ? nihDomain && v ? nihPort) servicesList; +in { + imports = []; + config = with lib; + mkIf (config.nih.domains.enable && config.nih.domains.handler == "tailscale-caddy") { + services.tailscale = { + enable = mkForce true; + useRoutingFeatures = mkForce "both"; + }; + + services.adguardhome = { + enable = mkForce true; + dns.rewrites = { + "*.homelab.local" = "192.168.1.10"; + "homelab.local" = "192.168.1.10"; + }; + }; + + services.caddy = { + enable = mkForce true; + virtualHosts."homelab.kiko-liberty.ts.net" = { + extraConfig = '' + reverse_proxy 192.168.1.10:4040 + ''; + }; + /* + virtualHosts = mapAttrs' + (n: v: nameValuePair (v.nihDomain) ({ + extraConfig = '' + reverse_proxy 100.66.139.89:${toString v.nihPort} + ''; + })) + servicesWithDomain; + */ + }; + }; +} diff --git a/modules/nih/domains/tailscale.nix b/modules/nih/domains/tailscale.nix new file mode 100644 index 0000000..16b1645 --- /dev/null +++ b/modules/nih/domains/tailscale.nix @@ -0,0 +1,24 @@ +{ + config, + lib, + pkgs, + ... +}: let + cfg = config.nih.domains.handlers.tailscale; +in { + imports = []; + options.nih.domains.handlers.tailscale = with lib; + with lib.types; { + enable = mkOption { + type = bool; + default = config.nih.domains.enable && config.nih.domains.handler == "tailscale"; + }; + }; + config = with lib; + mkIf cfg.enable { + services.tailscale = { + enable = mkDefault true; + useRoutingFeatures = mkDefault "server"; + }; + }; +} diff --git a/modules/nih/networking/default.nix b/modules/nih/networking/default.nix index d2de53d..56a821a 100644 --- a/modules/nih/networking/default.nix +++ b/modules/nih/networking/default.nix @@ -1,10 +1,12 @@ -{ config, lib, ... }: - -let - cfg = config.nih.networking; -in { - options.nih.networking = with lib; with lib.types; { + config, + lib, + ... +}: let + cfg = config.nih.networking; +in { + options.nih.networking = with lib; + with lib.types; { defaultGateway = mkOption { type = str; default = "192.168.1.1"; @@ -23,7 +25,7 @@ in }; nameservers = mkOption { type = listOf str; - default = [ "1.1.1.1" "8.8.8.8" ]; + default = ["1.1.1.1" "8.8.8.8"]; }; networkmanager = mkOption { type = bool; @@ -35,22 +37,33 @@ in }; wireless = mkOption { type = bool; - default = if config.nih.type == "laptop" then true else false; + default = + if config.nih.type == "laptop" + then true + else false; }; }; config = with lib; { - boot.kernel.sysctl."net.ipv4.ip_forward" = if cfg.portForwarding then 1 else 0; - boot.kernel.sysctl."net.ipv6.conf.all.forwarding" = if cfg.portForwarding then 1 else 0; + boot.kernel.sysctl."net.ipv4.ip_forward" = + if cfg.portForwarding + then 1 + else 0; + boot.kernel.sysctl."net.ipv6.conf.all.forwarding" = + if cfg.portForwarding + then 1 + else 0; networking = { hostName = cfg.hostName; defaultGateway = cfg.defaultGateway; dhcpcd.enable = true; interfaces = mkIf (cfg.interface != null) { - "${cfg.interface}".ipv4.addresses = [{ - address = cfg.localIp; - prefixLength = 28; - }]; + "${cfg.interface}".ipv4.addresses = [ + { + address = cfg.localIp; + prefixLength = 28; + } + ]; }; nameservers = cfg.nameservers; networkmanager.enable = cfg.networkmanager; diff --git a/modules/nih/programs/default.nix b/modules/nih/programs/default.nix index 29723ba..38d3a0a 100644 --- a/modules/nih/programs/default.nix +++ b/modules/nih/programs/default.nix @@ -1,9 +1,11 @@ -{ config, lib, pkgs, ... }: - -let - cfg = config.programs; -in { + config, + lib, + pkgs, + ... +}: let + cfg = config.programs; +in { imports = [ ./direnv.nix ./hyprland.nix @@ -13,6 +15,6 @@ in ./wezterm.nix ./zsh.nix ]; - options.programs = { }; - config = { }; + options.programs = {}; + config = {}; } diff --git a/modules/nih/programs/direnv.nix b/modules/nih/programs/direnv.nix index c4ea1fa..f88f059 100644 --- a/modules/nih/programs/direnv.nix +++ b/modules/nih/programs/direnv.nix @@ -1,19 +1,22 @@ -{ config, lib, pkgs, ... }: - -let - cfg = config.programs.direnv; -in { - imports = [ ]; - options.programs.direnv = with lib; with lib.types; { }; - config = with lib; mkIf cfg.enable { - programs.direnv = { - enableBashIntegration = mkDefault config.programs.bash.enable; - enableFishIntegration = mkDefault config.programs.fish.enable; - enableNushellIntegration = mkDefault config.programs.nushell.enable; - enableZshIntegration = mkDefault config.programs.zsh.enable; + config, + lib, + pkgs, + ... +}: let + cfg = config.programs.direnv; +in { + imports = []; + options.programs.direnv = with lib; with lib.types; {}; + config = with lib; + mkIf cfg.enable { + programs.direnv = { + enableBashIntegration = mkDefault config.programs.bash.enable; + enableFishIntegration = mkDefault config.programs.fish.enable; + enableNushellIntegration = mkDefault config.programs.nushell.enable; + enableZshIntegration = mkDefault config.programs.zsh.enable; - nix-direnv.enable = true; + nix-direnv.enable = true; + }; }; - }; } diff --git a/modules/nih/programs/hyprland.nix b/modules/nih/programs/hyprland.nix index 2edf024..797cc5e 100644 --- a/modules/nih/programs/hyprland.nix +++ b/modules/nih/programs/hyprland.nix @@ -1,15 +1,19 @@ -{ config, inputs, lib, pkgs, ... }: - -let - cfg = config.programs.hyprland; -in { - imports = [ ]; - options.programs.hyprland = with lib; with lib.types; { + config, + inputs, + lib, + pkgs, + ... +}: let + cfg = config.programs.hyprland; +in { + imports = []; + options.programs.hyprland = with lib; + with lib.types; { enable = mkEnableOption ""; monitors = mkOption { - default = [ ]; - type = listOf (submodule ({ ... }: { + default = []; + type = listOf (submodule ({...}: { options = { id = mkOption { type = str; @@ -36,15 +40,15 @@ in })); }; exec = mkOption { - default = [ ]; + default = []; type = listOf str; }; env = mkOption { - default = { }; + default = {}; type = attrsOf str; }; windowRules = mkOption { - default = { }; + default = {}; description = "window = [ \"rule\" ]"; type = attrsOf (listOf str); }; @@ -117,9 +121,10 @@ in }; }; workspaces = mkOption { - default = [ ]; - type = listOf - (submodule ({ ... }: { + default = []; + type = + listOf + (submodule ({...}: { options = { name = mkOption { type = str; @@ -145,11 +150,11 @@ in type = str; }; keyboard = mkOption { - default = [ ]; + default = []; type = listOf str; }; mouse = mkOption { - default = [ ]; + default = []; type = listOf str; }; }; @@ -163,16 +168,18 @@ in wayland.windowManager.hyprland.settings = lib.mkMerge [ # Sets monitor variables ("$name" = "id") so it can be used in rules later - (builtins.listToAttrs (map - (m: { - name = "\$${m.name}"; - value = "${m.id}"; - }) - cfg.monitors) + ( + builtins.listToAttrs (map + (m: { + name = "\$${m.name}"; + value = "${m.id}"; + }) + cfg.monitors) ) { # Construct the "name,resolution@hz,offset,scale" strings - monitor = (map + monitor = ( + map (m: "${m.name},${m.resolution}@${toString m.hz},${m.offset},${toString m.scale}") cfg.monitors ); @@ -181,7 +188,8 @@ in # "Hack" to transform attributes sets to lists (because I didn't know other way to do it) # Transform { "envName" = "value" } to [ "envName,value" ] - env = builtins.attrValues + env = + builtins.attrValues (builtins.mapAttrs (n: v: "${n},${v}") (lib.attrsets.mergeAttrsList [ { "XCURSOR_SIZE" = "24"; @@ -190,44 +198,46 @@ in cfg.env ])); - - windowrulev2 = - let - firefoxPipRules = [ - "float" - # "nofullscreenrequest" - "size 480 270" - "fakefullscreen" - "nodim" - "noblur" - ]; - in + windowrulev2 = let + firefoxPipRules = [ + "float" + # "nofullscreenrequest" + "size 480 270" + "fakefullscreen" + "nodim" + "noblur" + ]; + in builtins.concatLists - (builtins.attrValues (builtins.mapAttrs - (w: rs: - (map (r: "${r},${w}") rs) - ) - (lib.attrsets.mergeAttrsList [ - { - "title:^(Picture-in-Picture)$,class:^(firefox)$" = firefoxPipRules; - "title:^(Firefox)$,class:^(firefox)$" = firefoxPipRules; - "title:^(Picture-in-Picture)$" = firefoxPipRules; - "class:^(xwaylandvideobridge)$" = [ - "opacity 0.0 override 0.0 override" - "noanim" - "nofocus" - "noinitialfocus" - ]; - } - cfg.windowRules - ]) - )); + (builtins.attrValues ( + builtins.mapAttrs + ( + w: rs: (map (r: "${r},${w}") rs) + ) + (lib.attrsets.mergeAttrsList [ + { + "title:^(Picture-in-Picture)$,class:^(firefox)$" = firefoxPipRules; + "title:^(Firefox)$,class:^(firefox)$" = firefoxPipRules; + "title:^(Picture-in-Picture)$" = firefoxPipRules; + "class:^(xwaylandvideobridge)$" = [ + "opacity 0.0 override 0.0 override" + "noanim" + "nofocus" + "noinitialfocus" + ]; + } + cfg.windowRules + ]) + )); input = { kb_layout = cfg.input.keyboard.layout; kb_variant = cfg.input.keyboard.variant; - follow_mouse = if cfg.input.mouse.follow then "1" else "0"; + follow_mouse = + if cfg.input.mouse.follow + then "1" + else "0"; sensitivity = toString cfg.input.mouse.sensitivity; }; @@ -244,7 +254,10 @@ in decoration = { rounding = toString cfg.decoration.rouding; - dim_inactive = if cfg.decoration.dim.inactive then "true" else "false"; + dim_inactive = + if cfg.decoration.dim.inactive + then "true" + else "false"; dim_strength = toString cfg.decoration.dim.strength; dim_around = toString cfg.decoration.dim.around; @@ -255,7 +268,10 @@ in }; animations = { - enabled = if cfg.animations.enabled then "yes" else "no"; + enabled = + if cfg.animations.enabled + then "yes" + else "no"; bezier = "myBezier, 0.05, 0.9, 0.1, 1.05"; @@ -282,32 +298,26 @@ in workspace_swipe = "off"; }; - workspace = - (map - (w: "${w.name},${ - if w.monitor != null then "monitor:${w.monitor}," else "" - }${ - if w.default then "default:true," else "" - }${w.extraRules} ") - cfg.workspaces - ); + workspace = ( + map + (w: "${w.name},${ + if w.monitor != null + then "monitor:${w.monitor}," + else "" + }${ + if w.default + then "default:true," + else "" + }${w.extraRules} ") + cfg.workspaces + ); "$ mod " = cfg.binds.mod; bind = cfg.binds.keyboard; bindm = cfg.binds.mouse; - } ]; }; } - - - - - - - - - diff --git a/modules/nih/programs/lf.nix b/modules/nih/programs/lf.nix index 4eb38ab..8d39008 100644 --- a/modules/nih/programs/lf.nix +++ b/modules/nih/programs/lf.nix @@ -1,11 +1,14 @@ -{ config, lib, pkgs, ... }: - -let - cfg = config.programs.lf; -in { - imports = [ ]; - options.programs.lf = with lib; with lib.types; { + config, + lib, + pkgs, + ... +}: let + cfg = config.programs.lf; +in { + imports = []; + options.programs.lf = with lib; + with lib.types; { cmds = { mkfile = mkOption { type = bool; @@ -29,25 +32,25 @@ in default = true; }; }; - config = with lib; mkIf cfg.enable { - programs.lf = { - commands = { - dragon-out = mkIf cfg.cmds.dragon-out ''%${pkgs.xdragon}/bin/xdragon -a -x "$fx"''; - editor-open = mkIf cfg.cmds.editor-open ''$$EDITOR $f''; - mkfile = mkIf cfg.cmds.mkfile ''''${{ - printf "Dirname: " - read DIR + config = with lib; + mkIf cfg.enable { + programs.lf = { + commands = { + dragon-out = mkIf cfg.cmds.dragon-out ''%${pkgs.xdragon}/bin/xdragon -a -x "$fx"''; + editor-open = mkIf cfg.cmds.editor-open ''$$EDITOR $f''; + mkfile = mkIf cfg.cmds.mkfile '' ''${{ + printf "Dirname: " + read DIR - if [[ $DIR = */ ]]; then - mkdir $DIR - else - touch $DIR - fi - }}''; - }; + if [[ $DIR = */ ]]; then + mkdir $DIR + else + touch $DIR + fi + }}''; + }; - extraConfig = - let + extraConfig = let previewer = pkgs.writeShellScriptBin "pv.sh" '' file=$1 w=$2 @@ -66,14 +69,18 @@ in ${pkgs.kitty}/bin/kitty +kitten icat --clear --stdin no --silent --transfer-mode file < /dev/null > /dev/tty ''; in - mkDefault '' - ${if cfg.filePreviewer then '' - set cleaner ${cleaner}/bin/clean.sh - set previewer ${previewer}/bin/pv.sh - '' else ""} + mkDefault '' + ${ + if cfg.filePreviewer + then '' + set cleaner ${cleaner}/bin/clean.sh + set previewer ${previewer}/bin/pv.sh + '' + else "" + } - ${cfg.extraCfg} - ''; + ${cfg.extraCfg} + ''; + }; }; - }; } diff --git a/modules/nih/programs/starship.nix b/modules/nih/programs/starship.nix index 3022261..15b8e14 100644 --- a/modules/nih/programs/starship.nix +++ b/modules/nih/programs/starship.nix @@ -1,17 +1,20 @@ -{ config, lib, pkgs, ... }: - -let - cfg = config.programs.starship; -in { - imports = [ ]; - options.programs.starship = with lib; with lib.types; { }; - config = with lib; mkIf cfg.enable { - programs.starship = { - enableFishIntegration = mkDefault config.programs.fish.enable; - enableIonIntegration = mkDefault config.programs.ion.enable; - enableNushellIntegration = mkDefault config.programs.nushell.enable; - enableZshIntegration = mkDefault config.programs.zsh.enable; + config, + lib, + pkgs, + ... +}: let + cfg = config.programs.starship; +in { + imports = []; + options.programs.starship = with lib; with lib.types; {}; + config = with lib; + mkIf cfg.enable { + programs.starship = { + enableFishIntegration = mkDefault config.programs.fish.enable; + enableIonIntegration = mkDefault config.programs.ion.enable; + enableNushellIntegration = mkDefault config.programs.nushell.enable; + enableZshIntegration = mkDefault config.programs.zsh.enable; + }; }; - }; } diff --git a/modules/nih/programs/tmux.nix b/modules/nih/programs/tmux.nix index d98128a..c354168 100644 --- a/modules/nih/programs/tmux.nix +++ b/modules/nih/programs/tmux.nix @@ -1,11 +1,12 @@ -{ config, lib, pkgs, ... }: - -let - cfg = config.programs.tmux; -in { - imports = [ ]; - options.programs.tmux = with lib; with lib.types; { }; - config = with lib; mkIf cfg.enable { }; + config, + lib, + pkgs, + ... +}: let + cfg = config.programs.tmux; +in { + imports = []; + options.programs.tmux = with lib; with lib.types; {}; + config = with lib; mkIf cfg.enable {}; } - diff --git a/modules/nih/programs/wezterm.nix b/modules/nih/programs/wezterm.nix index 585111e..d7b0b52 100644 --- a/modules/nih/programs/wezterm.nix +++ b/modules/nih/programs/wezterm.nix @@ -1,42 +1,47 @@ -{ config, lib, pkgs, ... }: - -with builtins; -let +{ + config, + lib, + pkgs, + ... +}: +with builtins; let cfg = config.programs.wezterm; - jsonFormat = pkgs.formats.json { }; - toLua = with lib.strings; v: - if isList v then - "{ ${concatMapStringsSep ", " (i: toLua i) v} }" - else if isAttrs v then - "\{ ${concatStringsSep ", " (attrValues (mapAttrs (n: a: "${n} = ${toLua a}") v))} \}" - else if isNull v then - "nil" - else if isBool v then - if v then "true" else "false" - else if isInt v then - toString v - else if isString v && hasPrefix "lua " v then - "${substring 4 (stringLength v) v}" - else - "\"${toString v}\""; - configInLua = - pkgs.writeText "nih-wezterm-generated-config" '' - local wezterm = require("wezterm"); + jsonFormat = pkgs.formats.json {}; + toLua = with lib.strings; + v: + if isList v + then "{ ${concatMapStringsSep ", " (i: toLua i) v} }" + else if isAttrs v + then "\{ ${concatStringsSep ", " (attrValues (mapAttrs (n: a: "${n} = ${toLua a}") v))} \}" + else if isNull v + then "nil" + else if isBool v + then + if v + then "true" + else "false" + else if isInt v + then toString v + else if isString v && hasPrefix "lua " v + then "${substring 4 (stringLength v) v}" + else "\"${toString v}\""; + configInLua = pkgs.writeText "nih-wezterm-generated-config" '' + local wezterm = require("wezterm"); - local nih_generated_config = {}; - ${concatStringsSep "\n" (attrValues (mapAttrs - (n: v: "nih_generated_config.${n} = ${toLua v};") - cfg.config))} + local nih_generated_config = {}; + ${concatStringsSep "\n" (attrValues (mapAttrs + (n: v: "nih_generated_config.${n} = ${toLua v};") + cfg.config))} - local function extra_config() - ${cfg.extraConfig} - end + local function extra_config() + ${cfg.extraConfig} + end - for k,v in pairs(extra_config()) do nih_generated_config[k] = v end + for k,v in pairs(extra_config()) do nih_generated_config[k] = v end - return nih_generated_config; - ''; - prettyConfig = pkgs.runCommand "nih-wezterm-pretty-config" { config = configInLua; } '' + return nih_generated_config; + ''; + prettyConfig = pkgs.runCommand "nih-wezterm-pretty-config" {config = configInLua;} '' echo "Nih's Wezterm configuration file builder"; echo "input file: $config"; echo "output file: $out"; @@ -50,27 +55,24 @@ let --no-unused \ "$out"; ''; -in -{ - imports = [ ]; - options.programs.wezterm = with lib; with lib.types; { +in { + imports = []; + options.programs.wezterm = with lib; + with lib.types; { config = mkOption { - type = submodule ({ ... }: { + type = submodule ({...}: { freeformType = jsonFormat.type; }); - default = { }; + default = {}; }; }; - config = with lib; mkIf cfg.enable { - programs.wezterm = { - enableBashIntegration = mkDefault config.programs.bash.enable; - enableZshIntegration = mkDefault config.programs.zsh.enable; - }; + config = with lib; + mkIf cfg.enable { + programs.wezterm = { + enableBashIntegration = mkDefault config.programs.bash.enable; + enableZshIntegration = mkDefault config.programs.zsh.enable; + }; - xdg.configFile."wezterm/wezterm.lua".source = prettyConfig; - }; + xdg.configFile."wezterm/wezterm.lua".source = prettyConfig; + }; } - - - - diff --git a/modules/nih/programs/zsh.nix b/modules/nih/programs/zsh.nix index a412a14..1cb7098 100644 --- a/modules/nih/programs/zsh.nix +++ b/modules/nih/programs/zsh.nix @@ -1,10 +1,12 @@ -{ config, lib, pkgs, ... }: - -let - cfg = config.programs.zsh; -in { - imports = [ ]; - options.programs.zsh = with lib; with lib.types; { }; - config = with lib; mkIf cfg.enable { }; + config, + lib, + pkgs, + ... +}: let + cfg = config.programs.zsh; +in { + imports = []; + options.programs.zsh = with lib; with lib.types; {}; + config = with lib; mkIf cfg.enable {}; } diff --git a/modules/nih/services/adguard.nix b/modules/nih/services/adguard.nix deleted file mode 100644 index d6b0013..0000000 --- a/modules/nih/services/adguard.nix +++ /dev/null @@ -1,90 +0,0 @@ -{ config, lib, ... }: - -let - cfg = config.nih.services.adguard; -in -{ - imports = [ ]; - options.nih.services.adguard = with lib; with lib.types; { - enable = mkEnableOption ""; - extraArgs = mkOption { - type = listOf str; - default = [ ]; - }; - domain = mkOption { - type = str; - default = "adguard." + config.nih.domain; - }; - port = mkOption { - type = port; - default = 3010; - }; - settings = { - server.domain = mkOption { - type = str; - default = cfg.domain; - }; - server.port = mkOption { - type = port; - default = cfg.port; - }; - server.address = mkOption { - type = str; - default = "0.0.0.0"; - }; - dns.rewrites = mkOption { - type = attrsOf str; - default = { }; - }; - dns.filters = mkOption { - type = attrsOf (submodule ({ lib, ... }: { - options = { - name = mkOption { - type = nullOr str; - default = null; - }; - url = mkOption { - type = str; - }; - enabled = { - type = bool; - default = true; - }; - }; - })); - default = { }; - }; - }; - }; - config = lib.mkIf cfg.enable { - networking.firewall = { - allowedTCPPorts = [ 53 ]; - allowedUDPPorts = [ 53 51820 ]; - }; - services.adguardhome = with builtins; { - enable = true; - settings = { - bind_port = cfg.settings.server.port; - bind_host = cfg.settings.server.address; - http = { - address = "${cfg.settings.server.address}:${toString cfg.settings.server.port}"; - }; - dns.rewrites = (builtins.attrValues (builtins.mapAttrs - (from: to: { - domain = from; - answer = to; - }) - cfg.settings.dns.rewrites)); - filters = (attrValues (mapAttrs - (id: list: { - name = if isNull list.name then id else list.name; - ID = id; - url = list.url; - enabled = list.enabled; - }) - cfg.settings.dns.filters)); - }; - }; - }; -} - diff --git a/modules/nih/services/adguardhome.nix b/modules/nih/services/adguardhome.nix new file mode 100644 index 0000000..197c7f4 --- /dev/null +++ b/modules/nih/services/adguardhome.nix @@ -0,0 +1,75 @@ +{ + config, + lib, + ... +}: let + cfg = config.services.adguardhome; +in { + imports = []; + options.services.adguardhome = with lib; + with lib.types; { + nihDomain = mkOption { + type = str; + default = "adguard.${config.nih.domains.domain}"; + }; + nihPort = mkOption { + type = port; + default = 3053; + }; + dns.filters = mkOption { + type = attrsOf (submodule ({lib, ...}: { + options = { + name = mkOption { + type = nullOr str; + default = null; + }; + url = mkOption { + type = str; + }; + enabled = { + type = bool; + default = true; + }; + }; + })); + default = {}; + }; + dns.rewrites = mkOption { + type = attrsOf str; + default = {}; + }; + }; + config = with lib; + mkIf cfg.enable { + networking.firewall = { + allowedTCPPorts = [53]; + allowedUDPPorts = [53 51820]; + }; + + services.adguardhome = { + settings = { + bind_port = mkForce cfg.nihPort; + http = { + address = "${cfg.settings.bind_host}:${toString cfg.settings.bind_port}"; + }; + dns.rewrites = builtins.attrValues (builtins.mapAttrs + (from: to: { + domain = from; + answer = to; + }) + cfg.dns.rewrites); + filters = attrValues (mapAttrs + (id: list: { + name = + if isNull list.name + then id + else list.name; + ID = id; + url = list.url; + enabled = list.enabled; + }) + cfg.dns.filters); + }; + }; + }; +} diff --git a/modules/nih/services/caddy.nix b/modules/nih/services/caddy.nix index 4eb3d5a..3ecbdbd 100644 --- a/modules/nih/services/caddy.nix +++ b/modules/nih/services/caddy.nix @@ -1,28 +1,11 @@ -{ config, lib, pkgs, ... }: - -let - cfg = config.nih.services.caddy; -in { - imports = [ ]; - options.nih.services.caddy = with lib; with lib.types; { - enable = mkEnableOption ""; - virtualHosts = mkOption { - type = attrsOf (submodule ({ config, lib, ... }: { - options = { - extraConfig = mkOption { - type = lines; - default = ""; - }; - }; - })); - default = { }; - }; - }; - config = with lib; mkIf cfg.enable { - services.caddy = { - enable = true; - virtualHosts = cfg.virtualHosts; - }; - }; + config, + lib, + ... +}: let + cfg = config.server.caddy; +in { + imports = []; + options.server.caddy = with lib; with lib.types; {}; + config = lib.mkIf cfg.enable {}; } diff --git a/modules/nih/services/default.nix b/modules/nih/services/default.nix index ca63206..f08591f 100644 --- a/modules/nih/services/default.nix +++ b/modules/nih/services/default.nix @@ -1,12 +1,16 @@ -{ config, lib, pkgs, ... }: - { + config, + lib, + pkgs, + ... +}: let + cfg = config.services; +in { imports = [ - ./adguard.nix + ./adguardhome.nix ./caddy.nix - ./forgejo.nix ./tailscale.nix ]; - options.nih.services = { }; - config = { }; + options.services = {}; + config = {}; } diff --git a/modules/nih/services/forgejo.nix b/modules/nih/services/forgejo.nix deleted file mode 100644 index d3fe2bc..0000000 --- a/modules/nih/services/forgejo.nix +++ /dev/null @@ -1,301 +0,0 @@ -{ config, lib, pkgs, ... }: - -let - cfg = config.nih.services.forgejo; - users = (builtins.attrValues (builtins.mapAttrs - (username: info: { - name = if isNull info.name then username else info.name; - email = info.email; - password = info.password; - admin = info.admin; - }) - cfg.settings.users)); -in -{ - imports = [ ]; - options.nih.services.forgejo = with lib; with lib.types; { - enable = mkEnableOption ""; - user = mkOption { - type = str; - default = "git"; - }; - package = mkOption { - type = package; - default = pkgs.forgejo; - }; - cliAlias = mkOption { - type = bool; - default = true; - }; - domain = mkOption { - type = str; - default = "forgejo." + config.nih.domain; - }; - port = mkOption { - type = port; - default = 3020; - }; - data = { - root = mkOption { - type = path; - default = config.server.storage + /forgejo; - }; - }; - handleUndeclaredUsers = mkOption { - type = bool; - default = false; - }; - settings = { - users = mkOption { - type = attrsOf (submodule ({ config, lib, ... }: with lib; with lib.types; { - options = { - name = mkOption { - type = nullOr (either str path); - default = null; - }; - password = mkOption { - type = either str path; - }; - email = mkOption { - type = either str path; - }; - admin = mkOption { - type = bool; - default = false; - }; - }; - })); - default = { }; - }; - name = mkOption { - type = str; - default = "Forgejo: Beyond coding. We forge"; - }; - prod = mkOption { - type = bool; - default = true; - }; - repo.defaultUnits = mkOption { - type = listOf (enum [ - "repo.code" - "repo.releases" - "repo.issues" - "repo.pulls" - "repo.wiki" - "repo.projects" - "repo.packages" - "repo.actions" - ]); - default = [ - "repo.code" - "repo.issues" - "repo.pulls" - ]; - }; - repo.disabledUnits = mkOption { - type = listOf (enum [ - "repo.issues" - "repo.ext_issues" - "repo.pulls" - "repo.wiki" - "repo.ext_wiki" - "repo.projects" - "repo.packages" - "repo.actions" - ]); - default = [ ]; - }; - repo.pushCreate = mkOption { - type = bool; - default = false; - }; - cors.enable = mkOption { - type = bool; - default = false; - }; - cors.domains = mkOption { - type = listOf str; - default = [ ]; - }; - cors.methods = mkOption { - type = listOf str; - default = [ ]; - }; - ui.defaultTheme = mkOption { - type = str; - default = "forgejo-auto"; - }; - ui.themes = mkOption { - type = listOf str; - default = [ - "forgejo-auto" - "forgejo-light" - "forgejo-dark" - "auto" - "gitea" - "arc-green" - ]; - }; - server.protocol = mkOption { - type = enum [ "http" "https" "fcgi" "http+unix" "fcgi+unix" ]; - default = "http"; - }; - server.domain = mkOption { - type = str; - default = cfg.domain; - }; - server.port = mkOption { - type = port; - default = cfg.port; - }; - server.address = mkOption { - type = either str path; - default = if hasSuffix "+unix" cfg.settings.server.protocol then "/run/forgejo/forgejo.sock" else "0.0.0.0"; - }; - server.url = mkOption { - type = str; - default = "http://${cfg.settings.server.domain}:${toString cfg.settings.server.port}"; - }; - server.offline = mkOption { - type = bool; - default = false; - }; - server.compression = mkOption { - type = bool; - default = false; - }; - server.landingPage = mkOption { - type = enum [ "home" "explore" "organizations" "login" str ]; - default = "home"; - }; - service.registration = mkOption { - type = bool; - default = false; - }; - security.allowBypassGiteaEnv = mkOption { - type = bool; - default = false; - }; - }; - }; - config = lib.mkIf cfg.enable { - users.users."${cfg.user}" = { - home = cfg.data.root; - useDefaultShell = true; - group = cfg.user; - isSystemUser = true; - initialPassword = "1313"; - }; - users.groups."${cfg.user}" = { }; - - services.forgejo = { - enable = true; - package = cfg.package; - user = cfg.user; - group = cfg.user; - stateDir = toString cfg.data.root; - useWizard = false; - database = { - user = cfg.user; - type = "sqlite3"; - }; - settings = with builtins; { - DEFAULT = { - APP_NAME = cfg.settings.name; - RUN_MODE = if cfg.settings.prod then "prod" else "dev"; - }; - repository = { - DISABLED_REPO_UNITS = concatStringsSep "," cfg.settings.repo.disabledUnits; - DEFAULT_REPO_UNITS = concatStringsSep "," cfg.settings.repo.defaultUnits; - ENABLE_PUSH_CREATE_USER = cfg.settings.repo.pushCreate; - ENABLE_PUSH_CREATE_ORG = cfg.settings.repo.pushCreate; - }; - cors = { - ENABLED = cfg.settings.cors.enable; - ALLOW_DOMAIN = concatStringsSep "," cfg.settings.cors.domains; - METHODS = concatStringsSep "," cfg.settings.cors.methods; - }; - ui = { - DEFAULT_THEME = cfg.settings.ui.defaultTheme; - THEMES = concatStringsSep "," cfg.settings.ui.themes; - }; - server = { - PROTOCOL = cfg.settings.server.protocol; - DOMAIN = cfg.settings.server.domain; - ROOT_URL = cfg.settings.server.url; - HTTP_ADDR = cfg.settings.server.address; - HTTP_PORT = cfg.settings.server.port; - OFFLINE_MODE = cfg.settings.server.offline; - ENABLE_GZIP = cfg.settings.server.compression; - LANDING_PAGE = cfg.settings.server.landingPage; - }; - security = { - ONLY_ALLOW_PUSH_IF_GITEA_ENVIRONMENT_SET = if cfg.settings.security.allowBypassGiteaEnv then false else true; - }; - service = { - DISABLE_REGISTRATION = if cfg.settings.service.registration then false else true; - }; - }; - }; - systemd.services."homelab-forgejo-setup" = with builtins; { - script = '' - - configFile="${toString cfg.data.root}/custom/conf/app.ini"; - touch $configFile - - gum="${pkgs.gum}/bin/gum" - forgejo="${cfg.package}/bin/gitea --config $configFile" - user="$forgejo admin user" - awk="${pkgs.gawk}/bin/awk" - - declaredUsers=(${toString (map (user: "${if isPath user.name then "$(cat ${toString user.name})" else user.name}") users)}); - - $gum log --structured --time timeonly --level info "HANDLING UNDECLARED USERS" - - $user list | $awk '{print $2}' | tail -n +2 | while read username; do - if printf '%s\0' "''${declaredUsers[@]}" | grep -Fxqz -- "$username"; then - $gum log --structured --time timeonly --level warn "Declared user already exists, ignoring" username $username; - else - if [[ "$($user list | tail -n +2 | $awk '{print $2 " " $5}' | grep "$username " | $awk '{print $2}')" == "true" ]]; then - $gum log --structured --time timeonly --level warn "Undeclared user is a ADMIN, ignoring" username $username; - else - ${if cfg.handleUndeclaredUsers then '' - $gum log --structured --time timeonly --level warn "DELETING undeclared user" username $username; - - $user delete -u "$username"; - '' else '' - $gum log --structured --time timeonly --level warn "UNDECLARED user, please declare it in the config so it's reproducible" username "$username"; - ''} - fi - fi - done - - ${toString (map (user: '' - username="${if isPath user.name then "\"$(cat ${toString user.name})\"" else user.name}"; - email="${if isPath user.email then "\"$(cat ${toString user.email})\"" else user.email}"; - password="${if isPath user.password then "\"$(cat ${toString user.password})\"" else user.password}"; - - if [[ "$($user list | grep "$username" | $awk '{print $2}')" ]]; then - $gum log --structured --time timeonly --level warn "User with username already exists" username $username; - - elif [[ "$($user list | grep "$email" | $awk '{print $3}')" ]]; then - $gum log --structured --time timeonly --level warn "User with email already exists" email $email; - - else - $gum log --structured --time timeonly --level info ${if user.admin then "Creating ADMIN user" else "Creating user"} username $username email $email password $password; - $user create --username $username --email $email --password $password ${if user.admin then "--admin" else ""}; - - fi - '') users)} - ''; - wantedBy = [ "multi-user.target" ]; - after = [ "forgejo.service" ]; - serviceConfig = { - Type = "oneshot"; - User = cfg.user; - Group = cfg.user; - }; - }; - }; -} - diff --git a/modules/nih/services/tailscale.nix b/modules/nih/services/tailscale.nix index 265b976..7ed3214 100644 --- a/modules/nih/services/tailscale.nix +++ b/modules/nih/services/tailscale.nix @@ -1,50 +1,54 @@ -{ config, lib, ... }: - -let - cfg = config.nih.services.tailscale; -in { - imports = [ ]; - options.nih.services.tailscale = with lib; with lib.types; { - enable = mkEnableOption ""; + config, + lib, + ... +}: let + cfg = config.services.tailscale; +in { + imports = []; + options.services.tailscale = with lib; + with lib.types; { exitNode = mkOption { type = bool; default = false; }; - port = mkOption { - type = port; - default = 41641; - }; - routingFeatures = mkOption { - type = enum [ "none" "client" "server" "both" ]; - default = "client"; - }; tailnetName = mkOption { - type = nullOr str; - default = null; - apply = v: - if cfg.enable && config.nih.handleDomains && v == null then - throw "The option ${tailnetName} a is used when Tailscale and Nih's domain handling is enabled, but it is not defined." - else null; - }; - upFlags = mkOption { - type = listOf str; - default = [ ]; + type = str; }; }; - config = with lib; { - services.tailscale = { - enable = true; - extraUpFlags = cfg.upFlags ++ [ - (if cfg.exitNode then "--advertise-exit-node" else null) - ]; - port = cfg.port; - useRoutingFeatures = cfg.routingFeatures; - }; + config = with lib; + mkIf cfg.enable { + services.tailscale = { + extraUpFlags = [ + ( + if cfg.exitNode + then "--advertise-exit-node" + else null + ) + ( + if cfg.exitNode + then "--exit-node" + else null + ) + ]; + useRoutingFeatures = mkDefault ( + if config.nih.type == "server" || cfg.exitNode + then "server" + else "client" + ); + }; - nih.networking = mkIf cfg.exitNode { - portForwarding = mkDefault true; - nameservers = [ "100.100.100.100" ]; + networking.firewall.allowedTCPPorts = [80 433]; + + systemd.services."tailscaled" = mkIf config.services.caddy.enable { + serviceConfig = { + Environment = ["TS_PERMIT_CERT_UID=caddy"]; + }; + }; + + nih.networking = mkIf cfg.exitNode { + portForwarding = mkDefault true; + nameservers = ["100.100.100.100"]; + }; }; - }; } diff --git a/modules/nih/sound.nix b/modules/nih/sound.nix index 8e8d4ab..c98cdf9 100644 --- a/modules/nih/sound.nix +++ b/modules/nih/sound.nix @@ -1,10 +1,14 @@ -{ config, lib, pkgs, ... }: -let - cfg = config.nih.sound; -in { - imports = [ ]; - options.nih.sound = with lib; with lib.types; { + config, + lib, + pkgs, + ... +}: let + cfg = config.nih.sound; +in { + imports = []; + options.nih.sound = with lib; + with lib.types; { enable = mkOption { type = bool; default = true; @@ -18,16 +22,17 @@ in default = !cfg.pipewire.enable; }; }; - config = with lib; mkIf cfg.enable { - sound.enable = true; - hardware.pulseaudio.enable = cfg.pulseaudio.enable; - security.rtkit.enable = true; - services.pipewire = mkIf cfg.pipewire.enable { - enable = true; - alsa.enable = mkDefault true; - alsa.support32Bit = mkDefault true; - pulse.enable = mkDefault true; - wireplumber.enable = mkDefault true; + config = with lib; + mkIf cfg.enable { + sound.enable = true; + hardware.pulseaudio.enable = cfg.pulseaudio.enable; + security.rtkit.enable = true; + services.pipewire = mkIf cfg.pipewire.enable { + enable = true; + alsa.enable = mkDefault true; + alsa.support32Bit = mkDefault true; + pulse.enable = mkDefault true; + wireplumber.enable = mkDefault true; + }; }; - }; } diff --git a/modules/nih/user-profiles/default.nix b/modules/nih/user-profiles/default.nix index d0cfcab..de8631c 100644 --- a/modules/nih/user-profiles/default.nix +++ b/modules/nih/user-profiles/default.nix @@ -1,12 +1,14 @@ -{ config, lib, pkgs, ... }: - -let - cfg = config.profiles; -in { + config, + lib, + pkgs, + ... +}: let + cfg = config.profiles; +in { imports = [ ./gterminal.nix ]; - options.profiles = { }; - config = { }; + options.profiles = {}; + config = {}; } diff --git a/modules/nih/user-profiles/gterminal.nix b/modules/nih/user-profiles/gterminal.nix index f0f84ea..c4a16ab 100644 --- a/modules/nih/user-profiles/gterminal.nix +++ b/modules/nih/user-profiles/gterminal.nix @@ -1,104 +1,123 @@ -{ config, lib, pkgs, ... }: - -let - cfg = config.profiles.gterminal; -in { - imports = [ ]; - options.profiles.gterminal = with lib; with lib.types; { + config, + lib, + pkgs, + ... +}: let + cfg = config.profiles.gterminal; +in { + imports = []; + options.profiles.gterminal = with lib; + with lib.types; { enable = mkEnableOption ""; }; - config = with lib; mkIf cfg.enable { - programs = { - direnv.enable = true; - - lf.enable = true; - - starship.enable = true; - - tmux.baseIndex = 1; - tmux.enable = true; - tmux.extraConfig = '' - set -sg terminal-overrides ",*:RGB" - - set -g renumber-windows on - - bind -T prefix / split-window -v -c "#''''{pane_current_path}" - bind -T prefix \\ split-window -h -c "#''''{pane_current_path}" - ''; - tmux.keyMode = "vi"; - tmux.mouse = true; - tmux.prefix = "C-Space"; - tmux.plugins = with pkgs; [ - { - plugin = (tmuxPlugins.catppuccin.overrideAttrs (_: { - src = fetchFromGitHub { - owner = "guz013"; - repo = "frappuccino-tmux"; - rev = "4255b0a769cc6f35e12595fe5a33273a247630aa"; - sha256 = "0k8yprhx5cd8v1ddpcr0dkssspc17lq2a51qniwafkkzxi3kz3i5"; - }; - })); - extraConfig = '' - set -g @catppuccin_window_left_separator "" - set -g @catppuccin_window_right_separator " " - set -g @catppuccin_window_middle_separator " █" - set -g @catppuccin_window_number_position "right" - - set -g @catppuccin_window_default_fill "number" - set -g @catppuccin_window_default_text "#W" - - set -g @catppuccin_window_current_fill "number" - set -g @catppuccin_window_current_text "#W" - - set -g @catppuccin_status_modules_right "application directory session" - set -g @catppuccin_status_left_separator " " - set -g @catppuccin_status_right_separator "" - set -g @catppuccin_status_right_separator_inverse "no" - set -g @catppuccin_status_fill "icon" - set -g @catppuccin_status_connect_separator "no" - - set -g @catppuccin_directory_text "#{pane_current_path}" - ''; - } - { plugin = tmuxPlugins.better-mouse-mode; extraConfig = "set-option -g mouse on"; } - { - plugin = (tmuxPlugins.mkTmuxPlugin { - pluginName = "tmux.nvim"; - version = "unstable-2024-04-05"; - src = fetchFromGitHub { - owner = "aserowy"; - repo = "tmux.nvim"; - rev = "63e9c5e054099dd30af306bd8ceaa2f1086e1b07"; - sha256 = "0ynzljwq6hv7415p7pr0aqx8kycp84p3p3dy4jcx61dxfgdpgc4c"; - }; - }); - extraConfig = ''''; - } + config = with lib; + mkIf cfg.enable { + home.packages = with pkgs; [ + neovim + gcc + wget + git + tmux + lazygit + nixpkgs-fmt + nixpkgs-lint ]; + programs = { + direnv.enable = true; - tmux.shell = "${pkgs.zsh}/bin/zsh"; - tmux.terminal = "screen-256color"; + lf.enable = true; - wezterm = mkIf (config._nih.type != "server") { - enable = true; - config = { - default_prog = [ "zsh" "--login" ]; - enable_wayland = false; - enable_tab_bar = false; - font = "lua wezterm.font(\"Fira Code\")"; - font_size = 10; + neovim.enable = true; + + starship.enable = true; + + tmux.baseIndex = 1; + tmux.enable = true; + tmux.extraConfig = '' + set -sg terminal-overrides ",*:RGB" + + set -g renumber-windows on + + bind -T prefix / split-window -v -c "#''''{pane_current_path}" + bind -T prefix \\ split-window -h -c "#''''{pane_current_path}" + ''; + tmux.keyMode = "vi"; + tmux.mouse = true; + tmux.prefix = "C-Space"; + tmux.plugins = with pkgs; [ + { + plugin = tmuxPlugins.catppuccin.overrideAttrs (_: { + src = fetchFromGitHub { + owner = "guz013"; + repo = "frappuccino-tmux"; + rev = "4255b0a769cc6f35e12595fe5a33273a247630aa"; + sha256 = "0k8yprhx5cd8v1ddpcr0dkssspc17lq2a51qniwafkkzxi3kz3i5"; + }; + }); + extraConfig = '' + set -g @catppuccin_window_left_separator "" + set -g @catppuccin_window_right_separator " " + set -g @catppuccin_window_middle_separator " █" + set -g @catppuccin_window_number_position "right" + + set -g @catppuccin_window_default_fill "number" + set -g @catppuccin_window_default_text "#W" + + set -g @catppuccin_window_current_fill "number" + set -g @catppuccin_window_current_text "#W" + + set -g @catppuccin_status_modules_right "application directory session" + set -g @catppuccin_status_left_separator " " + set -g @catppuccin_status_right_separator "" + set -g @catppuccin_status_right_separator_inverse "no" + set -g @catppuccin_status_fill "icon" + set -g @catppuccin_status_connect_separator "no" + + set -g @catppuccin_directory_text "#{pane_current_path}" + ''; + } + { + plugin = tmuxPlugins.better-mouse-mode; + extraConfig = "set-option -g mouse on"; + } + { + plugin = tmuxPlugins.mkTmuxPlugin { + pluginName = "tmux.nvim"; + version = "unstable-2024-04-05"; + src = fetchFromGitHub { + owner = "aserowy"; + repo = "tmux.nvim"; + rev = "63e9c5e054099dd30af306bd8ceaa2f1086e1b07"; + sha256 = "0ynzljwq6hv7415p7pr0aqx8kycp84p3p3dy4jcx61dxfgdpgc4c"; + }; + }; + extraConfig = ''''; + } + ]; + + tmux.shell = "${pkgs.zsh}/bin/zsh"; + tmux.terminal = "screen-256color"; + + wezterm = mkIf (config._nih.type != "server") { + enable = true; + config = { + default_prog = ["zsh" "--login"]; + enable_wayland = false; + enable_tab_bar = false; + font = "lua wezterm.font(\"Fira Code\")"; + font_size = 10; + }; }; + + zsh.enable = true; + zsh.enableAutosuggestions = true; + zsh.enableCompletion = true; + zsh.initExtra = '' + export GPG_TTY=$(tty) + + alias tmux="tmux -f ${config.xdg.configHome}/tmux/tmux.conf"; + ''; }; - - zsh.enable = true; - zsh.enableAutosuggestions = true; - zsh.enableCompletion = true; - zsh.initExtra = '' - export GPG_TTY=$(tty) - - alias tmux="tmux -f ${config.xdg.configHome}/tmux/tmux.conf"; - ''; }; - }; } diff --git a/modules/nih/users.nix b/modules/nih/users.nix index e0aebd9..1d3da75 100644 --- a/modules/nih/users.nix +++ b/modules/nih/users.nix @@ -1,6 +1,10 @@ -{ config, inputs, lib, pkgs, ... }: - -let +{ + config, + inputs, + lib, + pkgs, + ... +}: let cfg = config.nih; hmModule = lib.types.submoduleWith { description = "Home Manager module"; @@ -8,29 +12,32 @@ let lib = lib; osConfig = config; }; - modules = [ - ({ name, ... }: { - config = { - submoduleSupport.enable = true; - submoduleSupport.externalPackageInstall = cfg.useUserPackages; + modules = + [ + ({name, ...}: { + config = { + submoduleSupport.enable = true; + submoduleSupport.externalPackageInstall = cfg.useUserPackages; - home.username = config.users.users.${name}.name; - home.homeDirectory = config.users.users.${name}.home; + home.username = config.users.users.${name}.name; + home.homeDirectory = config.users.users.${name}.home; - # Make activation script use same version of Nix as system as a whole. - # This avoids problems with Nix not being in PATH. - nix.package = config.nix.package; - }; - }) - ] ++ config.home-manager.sharedModules; + # Make activation script use same version of Nix as system as a whole. + # This avoids problems with Nix not being in PATH. + nix.package = config.nix.package; + }; + }) + ] + ++ config.home-manager.sharedModules; }; -in -{ - imports = [ ]; - options.nih = with lib; with lib.types; { +in { + imports = []; + options.nih = with lib; + with lib.types; { users = mkOption { - type = attrsOf - (submodule ({ ... }: { + type = + attrsOf + (submodule ({...}: { options = { description = mkOption { type = nullOr str; @@ -38,11 +45,11 @@ in }; extraGroups = mkOption { type = listOf str; - default = [ "networkmanager" "wheel" ]; + default = ["networkmanager" "wheel"]; }; home = mkOption { type = attrsOf anything; - default = { }; + default = {}; }; normalUser = mkOption { type = bool; @@ -50,7 +57,7 @@ in }; packages = mkOption { type = listOf package; - default = [ ]; + default = []; }; password = mkOption { type = nullOr (passwdEntry str); @@ -58,15 +65,15 @@ in }; profiles = mkOption { type = attrsOf anything; - default = { }; + default = {}; }; programs = mkOption { type = attrsOf anything; - default = { }; + default = {}; }; services = mkOption { type = attrsOf anything; - default = { }; + default = {}; }; shell = mkOption { type = package; @@ -74,8 +81,11 @@ in }; username = mkOption { type = passwdEntry str; - apply = x: assert (builtins.stringLength - x < 32 || abort "Username '${x}' is longer than 31 characters"); x; + apply = x: + assert (builtins.stringLength + x + < 32 + || abort "Username '${x}' is longer than 31 characters"); x; }; }; })); @@ -83,23 +93,27 @@ in }; config = with lib; { users.users = - (builtins.mapAttrs - (name: value: { - name = value.username; - hashedPassword = value.password; - description = if value.description != null then value.description else value.username; - isNormalUser = value.normalUser; - shell = value.shell; - extraGroups = value.extraGroups ++ [ "wheel" ]; - }) - cfg.users); + builtins.mapAttrs + (name: value: { + name = value.username; + hashedPassword = value.password; + description = + if value.description != null + then value.description + else value.username; + isNormalUser = value.normalUser; + shell = value.shell; + extraGroups = value.extraGroups ++ ["wheel"]; + }) + cfg.users; users.mutableUsers = true; - home-manager.extraSpecialArgs = { inherit inputs; }; + home-manager.extraSpecialArgs = {inherit inputs;}; home-manager.users = - (builtins.mapAttrs - (name: value: mkMerge [ + builtins.mapAttrs + (name: value: + mkMerge [ { imports = [ inputs.nix-index-database.hmModules.nix-index @@ -107,36 +121,38 @@ in ./programs ./user-profiles ]; - options = with lib; with lib.types; { + options = with lib; + with lib.types; { _nih = mkOption { type = attrsOf anything; - default = { }; + default = {}; }; }; config = { - _nih = { type = config.nih.type; }; - profiles = mkMerge [ value.profiles ]; + profiles = mkMerge [value.profiles]; programs = mkMerge [ - { home-manager.enable = true; } + {home-manager.enable = true;} value.programs ]; services = mkMerge [ - { flatpak.enable = mkDefault true; } + {flatpak.enable = mkDefault true;} value.services ]; home = mkMerge [ { username = value.username; - homeDirectory = mkDefault + homeDirectory = + mkDefault "/home/${value.username}"; - stateVersion = mkDefault + stateVersion = + mkDefault "23.11"; # Do not change } value.home @@ -144,6 +160,6 @@ in }; } ]) - cfg.users); + cfg.users; }; } diff --git a/modules/nixos/config/host.nix b/modules/nixos/config/host.nix index 9d7c3cc..d203a44 100644 --- a/modules/nixos/config/host.nix +++ b/modules/nixos/config/host.nix @@ -1,16 +1,20 @@ # Config shared between all host's configuration.nix (NixOS config) -{ config, pkgs, inputs, lib, ... }: - -let - cfg = config.host; -in { + config, + pkgs, + inputs, + lib, + ... +}: let + cfg = config.host; +in { imports = [ inputs.home-manager.nixosModules.default inputs.sops-nix.nixosModules.sops ../systems/localization.nix ]; - options.host = with lib; with lib.types; { + options.host = with lib; + with lib.types; { networking = { hostName = mkOption { default = "nixos"; @@ -31,8 +35,8 @@ in }; }; config = { - # Nix configuration - nix.settings.experimental-features = [ "nix-command" "flakes" ]; + # Nix configuration + nix.settings.experimental-features = ["nix-command" "flakes"]; boot = { loader.systemd-boot.enable = true; @@ -86,6 +90,5 @@ in # Before changing this value read the documentation for this option # (e.g. man configuration.nix or on https://nixos.org/nixos/options.html). system.stateVersion = "23.11"; # Did you read the comment? - }; } diff --git a/modules/nixos/default.nix b/modules/nixos/default.nix new file mode 100644 index 0000000..1742d02 --- /dev/null +++ b/modules/nixos/default.nix @@ -0,0 +1,10 @@ +{...}: { + imports = [ + ./profiles + ./services + ./home-manager-helper.nix + ./programs + ]; + options = {}; + config = {}; +} diff --git a/modules/nixos/home-manager-helper.nix b/modules/nixos/home-manager-helper.nix new file mode 100644 index 0000000..c596a68 --- /dev/null +++ b/modules/nixos/home-manager-helper.nix @@ -0,0 +1,248 @@ +{ + config, + inputs, + lib, + pkgs, + ... +}: +with lib; +with lib.types; let + cfg = config.home-manager-helper; + subordinateUidRange = { + options = { + startUid = mkOption { + type = int; + }; + count = mkOption { + type = int; + default = 1; + }; + }; + }; + + subordinateGidRange = { + options = { + startGid = mkOption { + type = int; + }; + count = mkOption { + type = int; + default = 1; + }; + }; + }; +in { + imports = [ + inputs.home-manager.nixosModules.default + ]; + options.home-manager-helper = with lib; + with lib.types; { + enable = mkEnableOption ""; + users = mkOption { + type = + attrsOf + (submodule + ({ + config, + name, + ... + }: { + options = { + autoSubUidGidRange = mkOption { + type = bool; + default = false; + }; + createHome = mkOption { + type = bool; + default = cfg.users.${name}.homeManager; + }; + cryptHomeLuks = mkOption { + type = nullOr str; + default = null; + }; + description = mkOption { + type = passwdEntry str; + default = ""; + }; + extraGroups = mkOption { + type = listOf str; + default = []; + }; + group = mkOption { + type = str; + default = name; + }; + hashedPassword = mkOption { + type = nullOr (passwdEntry str); + default = null; + }; + hashedPasswordFile = mkOption { + type = nullOr str; + default = null; + }; + home = mkOption { + type = anything; + default = {}; + }; + homeDirectory = mkOption { + type = passwdEntry path; + default = + if cfg.users.${name}.homeManager + then "/home/${name}" + else "/var/empty"; + }; + homeManager = mkOption { + type = bool; + default = + if cfg.users.${name}.isNormalUser + then true + else false; + }; + homeMode = mkOption { + type = strMatching "[0-7]{1,5}"; + default = "700"; + }; + ignoreShellProgramCheck = mkOption { + type = bool; + default = false; + }; + initialHashedPassword = mkOption { + type = nullOr (passwdEntry str); + default = null; + }; + initialPassword = mkOption { + type = nullOr (passwdEntry str); + default = null; + }; + isNormalUser = mkOption { + type = bool; + default = false; + }; + isSystemUser = mkOption { + type = bool; + default = false; + }; + linger = mkOption { + type = bool; + default = false; + }; + name = mkOption { + type = passwdEntry str; + }; + packages = mkOption { + type = listOf package; + default = []; + }; + pamMount = mkOption { + type = attrsOf str; + default = {}; + }; + shell = mkOption { + type = nullOr (either shellPackage (passwdEntry path)); + default = pkgs.shadow; + }; + subGidRanges = mkOption { + type = listOf (submodule subordinateGidRange); + default = []; + }; + subUidRanges = mkOption { + type = listOf (submodule subordinateUidRange); + default = []; + }; + uid = mkOption { + type = nullOr int; + default = null; + }; + useDefaultShell = mkOption { + type = bool; + default = false; + }; + }; + })); + default = {}; + }; + }; + config = with lib; + with builtins; + mkIf cfg.enable { + users.users = + mapAttrs + (name: value: { + inherit + (value) + autoSubUidGidRange + createHome + cryptHomeLuks + description + extraGroups + group + hashedPassword + hashedPasswordFile + homeMode + ignoreShellProgramCheck + initialHashedPassword + initialPassword + isNormalUser + isSystemUser + linger + name + pamMount + shell + subGidRanges + subUidRanges + uid + useDefaultShell + ; + + home = value.homeDirectory; + + packages = + if value.homeManager + then [] + else value.packages; + }) + cfg.users; + + users.mutableUsers = true; + users.groups = + mapAttrs' + (name: value: { + name = name; + value = + mkDefault + { + name = name; + members = ["${name}"]; + }; + }) + cfg.users; + + home-manager.extraSpecialArgs = {inherit inputs;}; + home-manager.users = + mapAttrs + (name: value: (mkMerge [ + { + imports = [ + inputs.nix-index-database.hmModules.nix-index + inputs.flatpaks.homeManagerModules.nix-flatpak + ]; + + home.username = value.name; + home.homeDirectory = value.homeDirectory; + home.packages = + value.packages + ++ ( + if value ? home ? packages + then value.home.packages + else [] + ); + + programs.home-manager.enable = true; + + home.stateVersion = "23.11"; # DO NOT CHANGE + } + value.home + ])) + (filterAttrs (n: v: v.homeManager) cfg.users); + }; +} diff --git a/modules/nixos/profiles/default.nix b/modules/nixos/profiles/default.nix new file mode 100644 index 0000000..a0f9fbb --- /dev/null +++ b/modules/nixos/profiles/default.nix @@ -0,0 +1,7 @@ +{...}: { + imports = [ + ./locale.nix + ]; + options = {}; + config = {}; +} diff --git a/modules/nixos/profiles/locale.nix b/modules/nixos/profiles/locale.nix new file mode 100644 index 0000000..2c1803c --- /dev/null +++ b/modules/nixos/profiles/locale.nix @@ -0,0 +1,64 @@ +{ + config, + lib, + ... +}: let + cfg = config.profiles.locale; +in { + imports = []; + options.profiles.locale = with lib; + with lib.types; { + enable = mkEnableOption ""; + locale = mkOption { + type = str; + default = "en_US.UTF-8"; + }; + extraLocales = mkOption { + type = attrsOf str; + default = rec { + LC_ADDRESS = "pt_BR.UTF-8"; + LC_IDENTIFICATION = LC_ADDRESS; + LC_MEASUREMENT = LC_ADDRESS; + LC_MONETARY = LC_ADDRESS; + LC_NAME = LC_ADDRESS; + LC_NUMERIC = LC_ADDRESS; + LC_PAPER = LC_ADDRESS; + LC_TELEPHONE = LC_ADDRESS; + LC_TIME = LC_ADDRESS; + }; + }; + keymap.layout = mkOption { + type = str; + default = "br"; + }; + keymap.variant = mkOption { + type = str; + default = ""; + }; + keymap.console = mkOption { + type = str; + default = "br-abnt2"; + }; + timeZone = mkOption { + type = str; + default = "America/Sao_Paulo"; + }; + }; + config = { + i18n = { + defaultLocale = cfg.locale; + extraLocaleSettings = cfg.extraLocales; + }; + + services.xserver = { + xkb.layout = cfg.keymap.layout; + xkb.variant = cfg.keymap.variant; + }; + + console.keyMap = cfg.keymap.console; + + time = { + timeZone = cfg.timeZone; + }; + }; +} diff --git a/modules/nixos/programs/default.nix b/modules/nixos/programs/default.nix new file mode 100644 index 0000000..879a486 --- /dev/null +++ b/modules/nixos/programs/default.nix @@ -0,0 +1,7 @@ +{...}: { + imports = [ + ./nih + ]; + options = {}; + config = {}; +} diff --git a/modules/nixos/programs/nih/cli.nix b/modules/nixos/programs/nih/cli.nix new file mode 100644 index 0000000..bfd5bd5 --- /dev/null +++ b/modules/nixos/programs/nih/cli.nix @@ -0,0 +1,40 @@ +{ + config, + lib, + pkgs, + ... +}: let + cfg = config.programs.nih; + cli = pkgs.writeShellScriptBin "nih" '' + # Since alias= doesn't work in bash scripts + function alejandra() { ${pkgs.alejandra}/bin/alejandra "$@"; } + function git() { ${pkgs.git}/bin/git "$@"; } + function gum() { ${pkgs.gum}/bin/gum "$@"; } + function lazygit() { ${pkgs.lazygit}/bin/lazygit "$@"; } + function notify-send() { + (${pkgs.libnotify}/bin/notify-send "$@" &>/dev/null || echo "") + } + function mktemp() { ${pkgs.mktemp}/bin/mktemp "$@"; } + + flake_dir="${toString cfg.flakeDir}"; + host="${toString cfg.host}"; + + + ${builtins.readFile ./cli.sh} + ''; +in { + imports = []; + options.nih = with lib; + with lib.types; { + cli = mkOption { + type = bool; + default = cfg.enable; + }; + }; + config = with lib; + mkIf cfg.enable { + environment.systemPackages = [ + cli + ]; + }; +} diff --git a/modules/nixos/programs/nih/cli.sh b/modules/nixos/programs/nih/cli.sh new file mode 100644 index 0000000..3222f40 --- /dev/null +++ b/modules/nixos/programs/nih/cli.sh @@ -0,0 +1,124 @@ + +function nih-edit() { + local flake_dir="$1" + local host="$2" + + # Exit if a command exits with a non-zero value + set -e + + # Push directory to history + pushd $flake_dir + + # Edit file + $EDITOR "$(gum file "$flakedir")" + + # Skip if there's no changes + if git diff --quiet "*.*"; then + gum log --structured \ + --prefix 'nih edit' \ + --level warn \ + 'No files changed' + popd + exit 0 + fi + + # Autoformat nix files + gum log --structured --prefix 'nih edit' --level debug 'Formatting files' + alejandra . &>/dev/null \ + || (alejandra . ; \ + gum log --structured \ + --prefix 'nih edit' \ + --level error 'Failed to format files' \ + && exit 1) + + # Show modifications + gum log --structured --prefix 'nih edit' --level debug 'Creatting diff files' + temp_file="$(mktemp /tmp/nih-diff-XXXXX)" + git diff -U0 '*.nix' > $temp_file + echo "$(gum format -l diff -t code < $temp_file)" > $temp_file + gum pager < $temp_file + rm $temp_file + + # Build NixOS + gum log --structured --prefix 'nih edit' --level debug 'Building NixOS' + sudo nixos-rebuild switch --flake "$flake_dir#$host" \ + || (gum log --structured --prefix 'nih edit' --level error 'Error building new config' && exit 1) + + gum log --structured \ + --prefix 'nih edit' \ + --level info 'NixOS finished building, please commit the changes' + notify-send -e "NixOS finished building, please commit the changes" \ + --icon=software-update-available \ + --urgency=normal + + case "$(gum choose --limit 1 'Commit' 'Open lazygit' 'No commit')" in + "Commit") + metadata="$(nixos-rebuild list-generations | grep current)" + commit_msg="$(gum write --value "$metadata" --placeholder 'Commit message')" + git commit -am "$commit_msg" + + gum confirm 'Push changes to remote?' \ + && git push \ + || echo ""; + ;; + "Open lazygit") + lazygit + + gum confirm 'Push changes to remote?' \ + && git push \ + || echo ""; + ;; + *) + gum log --structured \ + --prefix 'nih edit' \ + --level info 'Not commiting' + ;; + esac + + gum log --structured --prefix 'nih edit' --level info 'NixOS rebuilt!' + notify-send -e "NixOS Rebuilt!" \ + --icon=software-update-available \ + --urgency=low + + # Pop back to previous directory + popd +} + +function nih-build () { + gum log --structured --prefix 'nih switch' --level debug 'Building NixOS' + sudo nixos-rebuild switch --flake "$flake_dir#$host" \ + || (gum log --structured --prefix 'nih edit' --level error 'Error building new config' && exit 1) + gum log --structured --prefix 'nih switch' --level info 'NixOS rebuilt!' + notify-send -e "NixOS Rebuilt!" \ + --icon=software-update-available \ + --urgency=low +} + +function nih-install() { + local pkgs=() + local index=0 + for arg in "$@"; do + if [[ "$arg" == "--" ]]; then + break + fi + pkgs+=("nixpkgs#$arg") + index=$(($index + 1)) + done + shift $(($index + 1)) + nix shell "${pkgs[@]}" "$@" +} + +function nih-execute() { + local pkg="$1" + shift 1 + nix run "nixpkgs#$pkg" "$@" +} + +case "$1" in + "edit") nih-edit $flake_dir $host ;; + "switch" | "build") nih-build $flake_dir $host ;; + "install" | "i" ) shift 1; nih-install "$@" ;; + "exec" | "x" ) shift 1; nih-execute "$@" ;; + *) gum log --structured --prefix 'nih' --level error "Command $1 does not exist" ;; +esac + diff --git a/modules/nixos/programs/nih/default.nix b/modules/nixos/programs/nih/default.nix new file mode 100644 index 0000000..c0f49db --- /dev/null +++ b/modules/nixos/programs/nih/default.nix @@ -0,0 +1,23 @@ +{ + config, + lib, + pkgs, + ... +}: let + cfg = config.programs.nih; +in { + imports = [ + ./cli.nix + ]; + options.programs.nih = with lib; + with lib.types; { + enable = mkEnableOption ""; + host = mkOption { + type = str; + }; + flakeDir = mkOption { + type = str; + }; + }; + config = with lib; mkIf cfg.enable {}; +} diff --git a/modules/nixos/services/adguardhome.nix b/modules/nixos/services/adguardhome.nix new file mode 100644 index 0000000..01cb5ff --- /dev/null +++ b/modules/nixos/services/adguardhome.nix @@ -0,0 +1,62 @@ +{ + config, + lib, + ... +}: let + cfg = config.services.adguardhome; +in { + imports = []; + options.services.adguardhome = with lib; + with lib.types; { + dns.filters = mkOption { + type = attrsOf (submodule ({lib, ...}: { + options = { + name = mkOption { + type = nullOr str; + default = null; + }; + url = mkOption { + type = str; + }; + enabled = { + type = bool; + default = true; + }; + }; + })); + default = {}; + }; + dns.rewrites = mkOption { + type = attrsOf str; + default = {}; + }; + }; + config = with lib; + mkIf cfg.enable { + networking.firewall.allowedTCPPorts = [53]; + networking.firewall.allowedUDPPorts = [53 51820]; + + services.adguardhome = { + settings = { + http.address = "${cfg.settings.bind_host}:${toString cfg.settings.bind_port}"; + dns.rewrites = builtins.attrValues (builtins.mapAttrs + (from: to: { + domain = from; + answer = to; + }) + cfg.dns.rewrites); + filters = attrValues (mapAttrs + (id: list: { + name = + if isNull list.name + then id + else list.name; + ID = id; + url = list.url; + enabled = list.enabled; + }) + cfg.dns.filters); + }; + }; + }; +} diff --git a/modules/nixos/services/default.nix b/modules/nixos/services/default.nix new file mode 100644 index 0000000..284ebe5 --- /dev/null +++ b/modules/nixos/services/default.nix @@ -0,0 +1,9 @@ +{...}: { + imports = [ + ./adguardhome.nix + ./forgejo.nix + ./tailscale.nix + ]; + options = {}; + config = {}; +} diff --git a/modules/nixos/services/forgejo.nix b/modules/nixos/services/forgejo.nix new file mode 100644 index 0000000..f1d4362 --- /dev/null +++ b/modules/nixos/services/forgejo.nix @@ -0,0 +1,249 @@ +{ + config, + lib, + pkgs, + utils, + ... +}: let + cfg = config.services.forgejo; + yamlFormat = pkgs.formats.yaml {}; + users = builtins.attrValues (builtins.mapAttrs + (username: info: { + name = + if isNull info.name + then username + else info.name; + email = info.email; + password = info.password; + admin = info.admin; + }) + cfg.users); + initList = l: lib.strings.concatStringsSep "," l; +in { + imports = []; + options.services.forgejo = with lib; + with lib.types; { + handleUndeclaredUsers = mkOption { + type = bool; + default = false; + }; + users = mkOption { + type = attrsOf (submodule ({ + config, + lib, + ... + }: + with lib; + with lib.types; { + options = { + name = mkOption { + type = nullOr (either str path); + default = null; + }; + password = mkOption { + type = either str path; + }; + email = mkOption { + type = either str path; + }; + admin = mkOption { + type = bool; + default = false; + }; + }; + })); + default = {}; + }; + actions = { + enable = mkEnableOption ""; + hostPackages = mkOption { + type = listOf package; + default = with pkgs; [ + bash + coreutils + curl + gawk + gitMinimal + gnused + nodejs + wget + ]; + }; + labels = mkOption { + type = listOf str; + default = [ + "host:host" + "shell:host://-self-hosted" + "debian-latest:docker://node:18-bullseye" + "ubuntu-latest:docker://node:18-bullseye" + "debian-slim:docker://node:18-bullseye-slim" + "ubuntu-slim:docker://node:18-bullseye-slim" + "alpine-latest:docker://alpine:latest" + ]; + }; + name = mkOption { + type = str; + default = "Forgejo ${toString cfg.settings.server.HTTP_PORT} - Actions Runner"; + }; + package = mkOption { + type = package; + default = pkgs.forgejo-actions-runner; + }; + settings = mkOption { + type = yamlFormat.type; + default = {}; + }; + token = mkOption { + type = nullOr str; + default = null; + }; + tokenFile = mkOption { + type = nullOr (either path str); + default = null; + }; + url = mkOption { + type = str; + default = cfg.settings.server.ROOT_URL; + }; + }; + }; + config = with lib; + mkIf cfg.enable { + # this opens the port for the internal actions be able to clone and interact with the instance + networking.firewall.allowedTCPPorts = + mkIf cfg.actions.enable [cfg.settings.server.HTTP_PORT]; + + services.forgejo.settings = { + actions = { + ENABLED = mkDefault cfg.actions.enable; + DEFAULT_ACTIONS_URL = mkDefault cfg.settings.server.ROOT_URL; + }; + repository = { + DEFAULT_REPO_UNITS = mkDefault (initList [ + "repo.code" + "repo.issues" + "repo.pulls" + ]); + DISABLED_REPO_UNITS = mkIf (!cfg.actions.enable) (mkDefault "repo.actions"); + }; + security = { + ONLY_ALLOW_PUSH_IF_GITEA_ENVIRONMENT_SET = mkDefault true; + }; + server = { + HTTP_PORT = mkDefault 3617; + DOMAIN = + mkIf config.services.tailscale.enable + (mkDefault "${config.services.tailscale.deviceUrl}"); + }; + service = { + DISABLE_REGISTRATION = mkDefault true; + }; + }; + + virtualisation.docker.enable = mkIf cfg.settings.actions.ENABLED (mkDefault true); + services.gitea-actions-runner.instances."generatedForgejo${toString cfg.settings.server.HTTP_PORT}" = mkIf cfg.actions.enable { + enable = mkDefault true; + hostPackages = mkDefault cfg.actions.hostPackages; + labels = mkDefault cfg.actions.labels; + name = mkDefault cfg.actions.name; + settings = mkDefault cfg.actions.settings; + url = mkDefault cfg.actions.url; + token = cfg.actions.token; + }; + systemd.services = { + "${utils.escapeSystemdPath "generatedForgejo${toString cfg.settings.server.HTTP_PORT}"}" = { + serviceConfig.User = mkIf cfg.actions.enable (mkDefault cfg.user); + }; + }; + + systemd.services."homelab-forgejo-setup" = with builtins; { + script = '' + + configFile="${toString cfg.stateDir}/custom/conf/app.ini"; + touch $configFile + + gum="${pkgs.gum}/bin/gum" + forgejo="${cfg.package}/bin/gitea --config $configFile" + user="$forgejo admin user" + awk="${pkgs.gawk}/bin/awk" + + declaredUsers=(${toString (map (user: "${ + if isPath user.name + then "$(cat ${toString user.name})" + else user.name + }") + users)}); + + $gum log --structured --time timeonly --level info "HANDLING UNDECLARED USERS" + + $user list | $awk '{print $2}' | tail -n +2 | while read username; do + if printf '%s\0' "''${declaredUsers[@]}" | grep -Fxqz -- "$username"; then + $gum log --structured --time timeonly --level warn "Declared user already exists, ignoring" username $username; + else + if [[ "$($user list | tail -n +2 | $awk '{print $2 " " $5}' | grep "$username " | $awk '{print $2}')" == "true" ]]; then + $gum log --structured --time timeonly --level warn "Undeclared user is a ADMIN, ignoring" username $username; + else + ${ + if cfg.handleUndeclaredUsers + then '' + $gum log --structured --time timeonly --level warn "DELETING undeclared user" username $username; + + $user delete -u "$username"; + '' + else '' + $gum log --structured --time timeonly --level warn "UNDECLARED user, please declare it in the config so it's reproducible" username "$username"; + '' + } + fi + fi + done + + ${toString (map (user: '' + username="${ + if isPath user.name + then "\"$(cat ${toString user.name})\"" + else user.name + }"; + email="${ + if isPath user.email + then "\"$(cat ${toString user.email})\"" + else user.email + }"; + password="${ + if isPath user.password + then "\"$(cat ${toString user.password})\"" + else user.password + }"; + + if [[ "$($user list | grep "$username" | $awk '{print $2}')" ]]; then + $gum log --structured --time timeonly --level warn "User with username already exists" username $username; + + elif [[ "$($user list | grep "$email" | $awk '{print $3}')" ]]; then + $gum log --structured --time timeonly --level warn "User with email already exists" email $email; + + else + $gum log --structured --time timeonly --level info ${ + if user.admin + then "Creating ADMIN user" + else "Creating user" + } username $username email $email password $password; + $user create --username $username --email $email --password $password ${ + if user.admin + then "--admin" + else "" + }; + + fi + '') + users)} + ''; + wantedBy = ["multi-user.target"]; + after = ["forgejo.service"]; + serviceConfig = { + Type = "oneshot"; + User = cfg.user; + Group = cfg.group; + }; + }; + }; +} diff --git a/modules/nixos/services/tailscale.nix b/modules/nixos/services/tailscale.nix new file mode 100644 index 0000000..0eb26a6 --- /dev/null +++ b/modules/nixos/services/tailscale.nix @@ -0,0 +1,61 @@ +{ + config, + lib, + ... +}: let + cfg = config.services.tailscale; +in { + imports = []; + options.services.tailscale = with lib; + with lib.types; { + exitNode = mkOption { + type = bool; + default = false; + }; + tailnetName = mkOption { + type = str; + }; + tailnetUrl = mkOption { + type = str; + default = "${config.services.tailscale.tailnetName}.ts.net"; + }; + deviceUrl = mkOption { + type = str; + default = "${config.networking.hostName}.${config.services.tailscale.tailnetUrl}"; + }; + deviceIp = mkOption { + type = str; + }; + }; + config = with lib; + mkIf cfg.enable { + services.tailscale = { + extraUpFlags = [ + ( + if cfg.exitNode + then "--advertise-exit-node" + else null + ) + ( + if cfg.exitNode + then "--exit-node" + else null + ) + ]; + useRoutingFeatures = mkDefault ( + if cfg.exitNode + then "server" + else "client" + ); + }; + + systemd.services."tailscaled" = mkIf config.services.caddy.enable (mkDefault { + serviceConfig = { + Environment = ["TS_PERMIT_CERT_UID=caddy"]; + }; + }); + + boot.kernel.sysctl."net.ipv4.ip_forward" = mkIf cfg.exitNode (mkDefault 1); + boot.kernel.sysctl."net.ipv6.conf.all.forwarding" = mkIf cfg.exitNode (mkDefault 1); + }; +} diff --git a/modules/nixos/systems/fonts.nix b/modules/nixos/systems/fonts.nix index 4a4df74..0d5ef2b 100644 --- a/modules/nixos/systems/fonts.nix +++ b/modules/nixos/systems/fonts.nix @@ -1,15 +1,17 @@ -{ config, lib, ... }: - -let - cfg = config.my-fonts; -in { - imports = [ ]; - options.my-fonts = with lib; with lib.types; { + config, + lib, + ... +}: let + cfg = config.my-fonts; +in { + imports = []; + options.my-fonts = with lib; + with lib.types; { enable = mkEnableOption ""; fonts = mkOption { type = listOf package; - default = [ ]; + default = []; }; user = mkOption { type = str; @@ -35,7 +37,7 @@ in ln -sf /run/current-system/sw/share/X11/fonts /home/${cfg.user}/.fonts; fi ''; - wantedBy = [ "multi-user.target" ]; + wantedBy = ["multi-user.target"]; serviceConfig = { Type = "oneshot"; User = cfg.user; diff --git a/modules/nixos/systems/localization.nix b/modules/nixos/systems/localization.nix index 053d6d2..88583cb 100644 --- a/modules/nixos/systems/localization.nix +++ b/modules/nixos/systems/localization.nix @@ -1,10 +1,14 @@ -{ config, pkgs, inputs, lib, ... }: - -let - cfg = config.localization; -in { - options.localization = with lib; with lib.types; { + config, + pkgs, + inputs, + lib, + ... +}: let + cfg = config.localization; +in { + options.localization = with lib; + with lib.types; { locale = mkOption { default = "en_US.UTF-8"; type = str; diff --git a/modules/nixos/systems/set-user.nix b/modules/nixos/systems/set-user.nix index b43229b..625ed4b 100644 --- a/modules/nixos/systems/set-user.nix +++ b/modules/nixos/systems/set-user.nix @@ -1,13 +1,17 @@ -{ config, pkgs, inputs, lib, ... }: - -let - cfg = config.set-user; -in { - options.set-user = with lib; with lib.types; { + config, + pkgs, + inputs, + lib, + ... +}: let + cfg = config.set-user; +in { + options.set-user = with lib; + with lib.types; { users = mkOption { - default = [ ]; - type = listOf (submodule ({ ... }: { + default = []; + type = listOf (submodule ({...}: { options = { username = mkOption { type = str; @@ -26,11 +30,11 @@ in }; packages = mkOption { type = listOf package; - default = [ ]; + default = []; }; extraGroups = mkOption { type = listOf str; - default = [ "networkmanager" "wheel" ]; + default = ["networkmanager" "wheel"]; }; home = mkOption { type = anything; @@ -43,52 +47,56 @@ in })); }; }; - config = - let - home-default = user: { - imports = [ - ( - if user?flatpak && !user.flatpak - then null - else inputs.flatpaks.homeManagerModules.nix-flatpak - ) - inputs.nix-index-database.hmModules.nix-index - ]; - programs.home-manager.enable = true; - home.username = user.username; - home.homeDirectory = "/home/${user.username}"; - home.stateVersion = "23.11"; # Do not change - }; - in - { - users.users = (builtins.listToAttrs - (map - (u: { - name = u.username; - value = { - description = - if u.description != null then u.description else u.username; - isNormalUser = u.normalUser; - shell = u.shell; - packages = u.packages; - extraGroups = u.extraGroups ++ [ "wheel" ]; - }; - }) - cfg.users + config = let + home-default = user: { + imports = [ + ( + if user ? flatpak && !user.flatpak + then null + else inputs.flatpaks.homeManagerModules.nix-flatpak ) - ); - home-manager.extraSpecialArgs = { inherit inputs; }; - home-manager.users = (builtins.listToAttrs - (map - (u: { - name = u.username; - value = - if u?home then lib.mkMerge [ (home-default u) u.home ] - else (home-default u); - }) - cfg.users - ) - ); + inputs.nix-index-database.hmModules.nix-index + ]; + programs.home-manager.enable = true; + home.username = user.username; + home.homeDirectory = "/home/${user.username}"; + home.stateVersion = "23.11"; # Do not change }; + in { + users.users = ( + builtins.listToAttrs + ( + map + (u: { + name = u.username; + value = { + description = + if u.description != null + then u.description + else u.username; + isNormalUser = u.normalUser; + shell = u.shell; + packages = u.packages; + extraGroups = u.extraGroups ++ ["wheel"]; + }; + }) + cfg.users + ) + ); + home-manager.extraSpecialArgs = {inherit inputs;}; + home-manager.users = ( + builtins.listToAttrs + ( + map + (u: { + name = u.username; + value = + if u ? home + then lib.mkMerge [(home-default u) u.home] + else (home-default u); + }) + cfg.users + ) + ); + }; } - diff --git a/modules/server/adguard.nix b/modules/server/adguard.nix index 084641d..b37cd9f 100644 --- a/modules/server/adguard.nix +++ b/modules/server/adguard.nix @@ -1,15 +1,17 @@ -{ config, lib, ... }: - -let - cfg = config.server.adguard; -in { - imports = [ ]; - options.server.adguard = with lib; with lib.types; { + config, + lib, + ... +}: let + cfg = config.server.adguard; +in { + imports = []; + options.server.adguard = with lib; + with lib.types; { enable = mkEnableOption ""; extraArgs = mkOption { type = listOf str; - default = [ ]; + default = []; }; domain = mkOption { type = str; @@ -34,10 +36,10 @@ in }; dns.rewrites = mkOption { type = attrsOf str; - default = { }; + default = {}; }; dns.filters = mkOption { - type = attrsOf (submodule ({ lib, ... }: { + type = attrsOf (submodule ({lib, ...}: { options = { name = mkOption { type = nullOr str; @@ -52,14 +54,14 @@ in }; }; })); - default = { }; + default = {}; }; }; }; config = lib.mkIf cfg.enable { networking.firewall = { - allowedTCPPorts = [ 53 ]; - allowedUDPPorts = [ 53 51820 ]; + allowedTCPPorts = [53]; + allowedUDPPorts = [53 51820]; }; services.adguardhome = with builtins; { enable = true; @@ -69,22 +71,24 @@ in http = { address = "${cfg.settings.server.address}:${toString cfg.settings.server.port}"; }; - dns.rewrites = (builtins.attrValues (builtins.mapAttrs + dns.rewrites = builtins.attrValues (builtins.mapAttrs (from: to: { domain = from; answer = to; }) - cfg.settings.dns.rewrites)); - filters = (attrValues (mapAttrs + cfg.settings.dns.rewrites); + filters = attrValues (mapAttrs (id: list: { - name = if isNull list.name then id else list.name; + name = + if isNull list.name + then id + else list.name; ID = id; url = list.url; enabled = list.enabled; }) - cfg.settings.dns.filters)); + cfg.settings.dns.filters); }; }; }; } - diff --git a/modules/server/caddy.nix b/modules/server/caddy.nix index ca66e8c..b77b245 100644 --- a/modules/server/caddy.nix +++ b/modules/server/caddy.nix @@ -1,15 +1,21 @@ -{ config, lib, ... }: - -let - cfg = config.server.caddy; -in { - imports = [ ]; - options.server.caddy = with lib; with lib.types; { + config, + lib, + ... +}: let + cfg = config.server.caddy; +in { + imports = []; + options.server.caddy = with lib; + with lib.types; { enable = mkEnableOption ""; settings = { virtualHosts = mkOption { - type = attrsOf (submodule ({ config, lib, ... }: { + type = attrsOf (submodule ({ + config, + lib, + ... + }: { options = { extraConfig = mkOption { type = lines; @@ -17,7 +23,7 @@ in }; }; })); - default = { }; + default = {}; }; }; }; diff --git a/modules/server/default.nix b/modules/server/default.nix index f53fb75..88e8e1d 100644 --- a/modules/server/default.nix +++ b/modules/server/default.nix @@ -1,6 +1,9 @@ -{ config, lib, pkgs, ... }: - -let +{ + config, + lib, + pkgs, + ... +}: let cfg = config.server; server = pkgs.writeShellScriptBin "server" '' gum="${pkgs.gum}/bin/gum"; @@ -13,15 +16,23 @@ let sudo nixos-rebuild switch --flake "$flakeDir" "$@" fi - ${if cfg.forgejo.cliAlias then '' - if [[ "$command" == "forgejo" ]]; then - shift 1; - sudo --user=${cfg.forgejo.user} ${cfg.forgejo.package}/bin/gitea --work-path ${cfg.forgejo.data.root} "$@" - fi - '' else ""} + ${ + if cfg.forgejo.cliAlias + then '' + if [[ "$command" == "forgejo" ]]; then + shift 1; + sudo --user=${cfg.forgejo.user} ${cfg.forgejo.package}/bin/gitea --work-path ${cfg.forgejo.data.root} "$@" + fi + + if [[ "$command" == "forgejo-act" ]]; then + shift 1; + sudo --user=${cfg.forgejo.user} ${cfg.forgejo.actions.package}/bin/act_runner --config /var/lib/gitea-runner/${cfg.forgejo.actions.instanceName} "$@" + fi + '' + else "" + } ''; -in -{ +in { imports = [ ./adguard.nix ./caddy.nix @@ -33,7 +44,8 @@ in ./photoprism.nix ./tailscale.nix ]; - options.server = with lib; with lib.types; { + options.server = with lib; + with lib.types; { enable = mkEnableOption ""; name = mkOption { type = str; @@ -68,42 +80,45 @@ in server ]; - networking.firewall.allowedTCPPorts = lib.mkIf cfg.handleDomains [ 80 433 ]; + networking.firewall.allowedTCPPorts = lib.mkIf cfg.handleDomains [80 433]; systemd.services."tailscaled" = lib.mkIf cfg.handleDomains { serviceConfig = { - Environment = [ "TS_PERMIT_CERT_UID=caddy" ]; + Environment = ["TS_PERMIT_CERT_UID=caddy"]; }; }; - server = with lib; mkIf cfg.handleDomains { - adguard = { - enable = true; - settings.dns.rewrites = (if hasPrefix "*." cfg.domain then { - "${cfg.domain}" = cfg.ip; - } else { - "${cfg.domain}" = cfg.ip; - "${"*." + cfg.domain}" = cfg.ip; - }); - }; - - caddy = - let - homelabServices = (lib.filterAttrs (n: v: builtins.isAttrs v && v?domain) cfg); - in - with lib; - mkIf cfg.handleDomains { + server = with lib; + mkIf cfg.handleDomains { + adguard = { enable = true; - settings.virtualHosts = mapAttrs' - (name: value: nameValuePair (value.domain) ({ - extraConfig = '' - reverse_proxy ${cfg.localIp}:${toString value.port} - ''; - })) - homelabServices; + settings.dns.rewrites = + if hasPrefix "*." cfg.domain + then { + "${cfg.domain}" = cfg.ip; + } + else { + "${cfg.domain}" = cfg.ip; + "${"*." + cfg.domain}" = cfg.ip; + }; }; - }; + + caddy = let + homelabServices = lib.filterAttrs (n: v: builtins.isAttrs v && v ? domain) cfg; + in + with lib; + mkIf cfg.handleDomains { + enable = true; + settings.virtualHosts = + mapAttrs' + (name: value: + nameValuePair (value.domain) { + extraConfig = '' + reverse_proxy ${cfg.localIp}:${toString value.port} + ''; + }) + homelabServices; + }; + }; }; } - - diff --git a/modules/server/forgejo.nix b/modules/server/forgejo.nix index b97b330..f4c7f71 100644 --- a/modules/server/forgejo.nix +++ b/modules/server/forgejo.nix @@ -1,24 +1,67 @@ -{ config, lib, pkgs, ... }: - -let +{ + config, + lib, + pkgs, + utils, + ... +}: let cfg = config.server.forgejo; - users = (builtins.attrValues (builtins.mapAttrs + users = builtins.attrValues (builtins.mapAttrs (username: info: { - name = if isNull info.name then username else info.name; + name = + if isNull info.name + then username + else info.name; email = info.email; password = info.password; admin = info.admin; }) - cfg.settings.users)); -in -{ - imports = [ ]; - options.server.forgejo = with lib; with lib.types; { + cfg.settings.users); + settingsFormat = pkgs.formats.yaml {}; +in { + imports = []; + options.server.forgejo = with lib; + with lib.types; { enable = mkEnableOption ""; user = mkOption { type = str; default = "git"; }; + actions.enable = mkOption { + type = bool; + default = false; + }; + actions.runnerToken = mkOption { + type = str; + }; + actions.package = mkOption { + type = package; + default = pkgs.forgejo-actions-runner; + }; + actions.instanceUrl = mkOption { + type = str; + default = "https://${cfg.domain}"; + }; + actions.url = mkOption { + type = str; + default = "http://localhost:${toString cfg.port}"; + }; + actions.instanceName = mkOption { + type = str; + default = "${cfg.user}Forgejo${toString cfg.port}"; + }; + actions.settings = mkOption { + type = submodule { + freeformType = settingsFormat.type; + options = { + runner.insecure = mkOption { + type = bool; + default = true; + }; + }; + }; + default = {}; + }; package = mkOption { type = package; default = pkgs.forgejo; @@ -47,25 +90,31 @@ in }; settings = { users = mkOption { - type = attrsOf (submodule ({ config, lib, ... }: with lib; with lib.types; { - options = { - name = mkOption { - type = nullOr (either str path); - default = null; + type = attrsOf (submodule ({ + config, + lib, + ... + }: + with lib; + with lib.types; { + options = { + name = mkOption { + type = nullOr (either str path); + default = null; + }; + password = mkOption { + type = either str path; + }; + email = mkOption { + type = either str path; + }; + admin = mkOption { + type = bool; + default = false; + }; }; - password = mkOption { - type = either str path; - }; - email = mkOption { - type = either str path; - }; - admin = mkOption { - type = bool; - default = false; - }; - }; - })); - default = { }; + })); + default = {}; }; name = mkOption { type = str; @@ -103,7 +152,7 @@ in "repo.packages" "repo.actions" ]); - default = [ ]; + default = []; }; repo.pushCreate = mkOption { type = bool; @@ -115,11 +164,11 @@ in }; cors.domains = mkOption { type = listOf str; - default = [ ]; + default = []; }; cors.methods = mkOption { type = listOf str; - default = [ ]; + default = []; }; ui.defaultTheme = mkOption { type = str; @@ -137,7 +186,7 @@ in ]; }; server.protocol = mkOption { - type = enum [ "http" "https" "fcgi" "http+unix" "fcgi+unix" ]; + type = enum ["http" "https" "fcgi" "http+unix" "fcgi+unix"]; default = "http"; }; server.domain = mkOption { @@ -150,7 +199,10 @@ in }; server.address = mkOption { type = either str path; - default = if hasSuffix "+unix" cfg.settings.server.protocol then "/run/forgejo/forgejo.sock" else "0.0.0.0"; + default = + if hasSuffix "+unix" cfg.settings.server.protocol + then "/run/forgejo/forgejo.sock" + else "0.0.0.0"; }; server.url = mkOption { type = str; @@ -165,7 +217,7 @@ in default = false; }; server.landingPage = mkOption { - type = enum [ "home" "explore" "organizations" "login" str ]; + type = enum ["home" "explore" "organizations" "login" str]; default = "home"; }; service.registration = mkOption { @@ -178,134 +230,190 @@ in }; }; }; - config = lib.mkIf cfg.enable { - users.users."${cfg.user}" = { - home = cfg.data.root; - useDefaultShell = true; - group = cfg.user; - isSystemUser = true; - initialPassword = "1313"; - }; - users.groups."${cfg.user}" = { }; + config = let + inherit (utils) escapeSystemdPath; + in + with lib; + mkIf cfg.enable { + users.users."${cfg.user}" = { + home = cfg.data.root; + useDefaultShell = true; + group = cfg.user; + isSystemUser = true; + initialPassword = "1313"; + }; + users.groups."${cfg.user}" = {}; - services.forgejo = { - enable = true; - package = cfg.package; - user = cfg.user; - group = cfg.user; - stateDir = toString cfg.data.root; - useWizard = false; - database = { - user = cfg.user; - type = "sqlite3"; - }; - settings = with builtins; { - DEFAULT = { - APP_NAME = cfg.settings.name; - RUN_MODE = if cfg.settings.prod then "prod" else "dev"; + virtualisation.docker.enable = cfg.actions.enable; + services.gitea-actions-runner.instances."${cfg.actions.instanceName}" = mkIf cfg.actions.enable { + enable = true; + name = cfg.actions.instanceName; + url = cfg.actions.instanceUrl; + token = cfg.actions.runnerToken; + settings = cfg.actions.settings; + labels = [ + "host:host" + "shell:host://-self-hosted" + "debian-latest:docker://node:18-bullseye" + "ubuntu-latest:docker://node:18-bullseye" + "debian-slim:docker://node:18-bullseye-slim" + "ubuntu-slim:docker://node:18-bullseye-slim" + "alpine-latest:docker://alpine:latest" + ]; }; - repository = { - DISABLED_REPO_UNITS = concatStringsSep "," cfg.settings.repo.disabledUnits; - DEFAULT_REPO_UNITS = concatStringsSep "," cfg.settings.repo.defaultUnits; - ENABLE_PUSH_CREATE_USER = cfg.settings.repo.pushCreate; - ENABLE_PUSH_CREATE_ORG = cfg.settings.repo.pushCreate; - }; - cors = { - ENABLED = cfg.settings.cors.enable; - ALLOW_DOMAIN = concatStringsSep "," cfg.settings.cors.domains; - METHODS = concatStringsSep "," cfg.settings.cors.methods; - }; - ui = { - DEFAULT_THEME = cfg.settings.ui.defaultTheme; - THEMES = concatStringsSep "," cfg.settings.ui.themes; - }; - server = { - PROTOCOL = cfg.settings.server.protocol; - DOMAIN = cfg.settings.server.domain; - ROOT_URL = cfg.settings.server.url; - HTTP_ADDR = cfg.settings.server.address; - HTTP_PORT = cfg.settings.server.port; - OFFLINE_MODE = cfg.settings.server.offline; - ENABLE_GZIP = cfg.settings.server.compression; - LANDING_PAGE = cfg.settings.server.landingPage; - }; - security = { - ONLY_ALLOW_PUSH_IF_GITEA_ENVIRONMENT_SET = if cfg.settings.security.allowBypassGiteaEnv then false else true; - }; - service = { - DISABLE_REGISTRATION = if cfg.settings.service.registration then false else true; - }; - }; - }; - systemd.services."homelab-forgejo-setup" = with builtins; { - script = '' - - configFile="${toString cfg.data.root}/custom/conf/app.ini"; - touch $configFile + services.gitea-actions-runner.package = cfg.actions.package; + systemd.services."${escapeSystemdPath cfg.actions.instanceName}".serviceConfig.User = cfg.user; - gum="${pkgs.gum}/bin/gum" - forgejo="${cfg.package}/bin/gitea --config $configFile" - user="$forgejo admin user" - awk="${pkgs.gawk}/bin/awk" + services.forgejo = { + enable = true; + package = cfg.package; + user = cfg.user; + group = cfg.user; + stateDir = toString cfg.data.root; + useWizard = false; + database = { + user = cfg.user; + type = "sqlite3"; + }; + settings = with builtins; { + actions = mkIf cfg.actions.enable { + ENABLED = true; + DEFAULT_ACTIONS_URL = cfg.actions.url; + }; + DEFAULT = { + APP_NAME = cfg.settings.name; + RUN_MODE = + if cfg.settings.prod + then "prod" + else "dev"; + }; + repository = { + DISABLED_REPO_UNITS = concatStringsSep "," cfg.settings.repo.disabledUnits; + DEFAULT_REPO_UNITS = concatStringsSep "," cfg.settings.repo.defaultUnits; + ENABLE_PUSH_CREATE_USER = cfg.settings.repo.pushCreate; + ENABLE_PUSH_CREATE_ORG = cfg.settings.repo.pushCreate; + }; + cors = { + ENABLED = cfg.settings.cors.enable; + ALLOW_DOMAIN = concatStringsSep "," cfg.settings.cors.domains; + METHODS = concatStringsSep "," cfg.settings.cors.methods; + }; + ui = { + DEFAULT_THEME = cfg.settings.ui.defaultTheme; + THEMES = concatStringsSep "," cfg.settings.ui.themes; + }; + server = { + PROTOCOL = cfg.settings.server.protocol; + DOMAIN = cfg.settings.server.domain; + ROOT_URL = cfg.settings.server.url; + HTTP_ADDR = cfg.settings.server.address; + HTTP_PORT = cfg.settings.server.port; + OFFLINE_MODE = cfg.settings.server.offline; + ENABLE_GZIP = cfg.settings.server.compression; + LANDING_PAGE = cfg.settings.server.landingPage; + }; + security = { + ONLY_ALLOW_PUSH_IF_GITEA_ENVIRONMENT_SET = + if cfg.settings.security.allowBypassGiteaEnv + then false + else true; + }; + service = { + DISABLE_REGISTRATION = + if cfg.settings.service.registration + then false + else true; + }; + }; + }; + systemd.services."homelab-forgejo-setup" = with builtins; { + script = '' - declaredUsers=(${toString (map (user: "${if isPath user.name then "$(cat ${toString user.name})" else user.name}") users)}); + configFile="${toString cfg.data.root}/custom/conf/app.ini"; + touch $configFile - $gum log --structured --time timeonly --level info "HANDLING UNDECLARED USERS" - - $user list | $awk '{print $2}' | tail -n +2 | while read username; do - if printf '%s\0' "''${declaredUsers[@]}" | grep -Fxqz -- "$username"; then - $gum log --structured --time timeonly --level warn "Declared user already exists, ignoring" username $username; - else - if [[ "$($user list | tail -n +2 | $awk '{print $2 " " $5}' | grep "$username " | $awk '{print $2}')" == "true" ]]; then - $gum log --structured --time timeonly --level warn "Undeclared user is a ADMIN, ignoring" username $username; - else - ${if cfg.handleUndeclaredUsers then '' + gum="${pkgs.gum}/bin/gum" + forgejo="${cfg.package}/bin/gitea --config $configFile" + user="$forgejo admin user" + awk="${pkgs.gawk}/bin/awk" + + declaredUsers=(${toString (map (user: "${ + if isPath user.name + then "$(cat ${toString user.name})" + else user.name + }") + users)}); + + $gum log --structured --time timeonly --level info "HANDLING UNDECLARED USERS" + + $user list | $awk '{print $2}' | tail -n +2 | while read username; do + if printf '%s\0' "''${declaredUsers[@]}" | grep -Fxqz -- "$username"; then + $gum log --structured --time timeonly --level warn "Declared user already exists, ignoring" username $username; + else + if [[ "$($user list | tail -n +2 | $awk '{print $2 " " $5}' | grep "$username " | $awk '{print $2}')" == "true" ]]; then + $gum log --structured --time timeonly --level warn "Undeclared user is a ADMIN, ignoring" username $username; + else + ${ + if cfg.handleUndeclaredUsers + then '' $gum log --structured --time timeonly --level warn "DELETING undeclared user" username $username; $user delete -u "$username"; - '' else '' + '' + else '' $gum log --structured --time timeonly --level warn "UNDECLARED user, please declare it in the config so it's reproducible" username "$username"; - ''} - fi - fi - done + '' + } + fi + fi + done - ${toString (map (user: '' - username="${if isPath user.name then "\"$(cat ${toString user.name})\"" else user.name}"; - email="${if isPath user.email then "\"$(cat ${toString user.email})\"" else user.email}"; - password="${if isPath user.password then "\"$(cat ${toString user.password})\"" else user.password}"; + ${toString (map (user: '' + username="${ + if isPath user.name + then "\"$(cat ${toString user.name})\"" + else user.name + }"; + email="${ + if isPath user.email + then "\"$(cat ${toString user.email})\"" + else user.email + }"; + password="${ + if isPath user.password + then "\"$(cat ${toString user.password})\"" + else user.password + }"; - if [[ "$($user list | grep "$username" | $awk '{print $2}')" ]]; then - $gum log --structured --time timeonly --level warn "User with username already exists" username $username; + if [[ "$($user list | grep "$username" | $awk '{print $2}')" ]]; then + $gum log --structured --time timeonly --level warn "User with username already exists" username $username; - elif [[ "$($user list | grep "$email" | $awk '{print $3}')" ]]; then - $gum log --structured --time timeonly --level warn "User with email already exists" email $email; + elif [[ "$($user list | grep "$email" | $awk '{print $3}')" ]]; then + $gum log --structured --time timeonly --level warn "User with email already exists" email $email; - else - $gum log --structured --time timeonly --level info ${if user.admin then "Creating ADMIN user" else "Creating user"} username $username email $email password $password; - $user create --username $username --email $email --password $password ${if user.admin then "--admin" else ""}; + else + $gum log --structured --time timeonly --level info ${ + if user.admin + then "Creating ADMIN user" + else "Creating user" + } username $username email $email password $password; + $user create --username $username --email $email --password $password ${ + if user.admin + then "--admin" + else "" + }; - fi - '') users)} - ''; - wantedBy = [ "multi-user.target" ]; - after = [ "forgejo.service" ]; - serviceConfig = { - Type = "oneshot"; - User = cfg.user; - Group = cfg.user; + fi + '') + users)} + ''; + wantedBy = ["multi-user.target"]; + after = ["forgejo.service"]; + serviceConfig = { + Type = "oneshot"; + User = cfg.user; + Group = cfg.user; + }; + }; }; - }; - }; } - - - - - - - - - - - diff --git a/modules/server/jellyfin.nix b/modules/server/jellyfin.nix index 581b728..8d0fead 100644 --- a/modules/server/jellyfin.nix +++ b/modules/server/jellyfin.nix @@ -1,6 +1,9 @@ -{ config, lib, pkgs, ... }: - -let +{ + config, + lib, + pkgs, + ... +}: let cfg = config.server.jellyfin; networkConfig = pkgs.writeTextFile { name = "network.json"; @@ -14,12 +17,12 @@ let name = "encoding.json"; text = builtins.toJSON cfg.settings.system; }; -in -{ +in { imports = [ ./jellyseerr.nix ]; - options.server.jellyfin = with lib; with lib.types; { + options.server.jellyfin = with lib; + with lib.types; { enable = mkEnableOption ""; user = mkOption { type = str; @@ -49,8 +52,8 @@ in }; settings = { network = mkOption { - type = (submodule { - freeformType = (pkgs.formats.json { }).type; + type = submodule { + freeformType = (pkgs.formats.json {}).type; options = { AutoDiscovery = mkOption { type = bool; @@ -185,149 +188,148 @@ in default = "vEthernet*"; }; }; - }); - default = { }; + }; + default = {}; }; encoding = mkOption { - type = - (submodule { - freeformType = (pkgs.formats.json { }).type; - options = { - AllowOnDemandMetadataBasedKeyframeExtractionForExtensions.string = mkOption { - type = listOf str; - default = [ "mkv" ]; - }; - DeinterlaceDoubleRate = mkOption { - type = bool; - default = false; - }; - DeinterlaceMethod = mkOption { - type = str; - default = "yadif"; - }; - DownMixAudioBoost = mkOption { - type = int; - default = 2; - }; - EnableDecodingColorDepth10Hevc = mkOption { - type = bool; - default = true; - }; - EnableDecodingColorDepth10Vp9 = mkOption { - type = bool; - default = true; - }; - EnableEnhancedNvdecDecoder = mkOption { - type = bool; - default = true; - }; - EnableFallbackFont = mkOption { - type = bool; - default = false; - }; - EnableHardwareEncoding = mkOption { - type = bool; - default = true; - }; - EnableIntelLowPowerH264HwEncoder = mkOption { - type = bool; - default = false; - }; - EnableIntelLowPowerHevcHwEncoder = mkOption { - type = bool; - default = false; - }; - EnableSubtitleExtraction = mkOption { - type = bool; - default = true; - }; - EnableThrottling = mkOption { - type = bool; - default = false; - }; - EnableTonemapping = mkOption { - type = bool; - default = false; - }; - EnableVppTonemapping = mkOption { - type = bool; - default = false; - }; - EncoderAppPathDisplay = mkOption { - type = either path str; - default = "${pkgs.jellyfin-ffmpeg}/bin/ffmpeg"; - }; - EncodingThreadCount = mkOption { - type = int; - default = -1; - }; - H264Crf = mkOption { - type = int; - default = 23; - }; - H265Crf = mkOption { - type = int; - default = 28; - }; - HardwareDecodingCodecs.string = mkOption { - type = listOf str; - default = [ "h254" "vc1" ]; - }; - MaxMuxingQueueSize = mkOption { - type = int; - default = 2048; - }; - PreferSystemNativeHwDecoder = mkOption { - type = bool; - default = true; - }; - ThrottleDelaySeconds = mkOption { - type = int; - default = 180; - }; - TonemappingAlgorithm = mkOption { - type = str; - default = "bt2390"; - }; - TonemappingDesat = mkOption { - type = int; - default = 0; - }; - TonemappingMode = mkOption { - type = str; - default = "auto"; - }; - TonemappingParam = mkOption { - type = int; - default = 0; - }; - TonemappingPeak = mkOption { - type = int; - default = 100; - }; - TonemappingRange = mkOption { - type = str; - default = "auto"; - }; - VaapiDevice = mkOption { - type = either path str; - default = "/dev/dri/renderD128"; - }; - VppTonemappingBrightness = mkOption { - type = int; - default = 16; - }; - VppTonemappingContrast = mkOption { - type = int; - default = 1; - }; + type = submodule { + freeformType = (pkgs.formats.json {}).type; + options = { + AllowOnDemandMetadataBasedKeyframeExtractionForExtensions.string = mkOption { + type = listOf str; + default = ["mkv"]; }; - }); - default = { }; + DeinterlaceDoubleRate = mkOption { + type = bool; + default = false; + }; + DeinterlaceMethod = mkOption { + type = str; + default = "yadif"; + }; + DownMixAudioBoost = mkOption { + type = int; + default = 2; + }; + EnableDecodingColorDepth10Hevc = mkOption { + type = bool; + default = true; + }; + EnableDecodingColorDepth10Vp9 = mkOption { + type = bool; + default = true; + }; + EnableEnhancedNvdecDecoder = mkOption { + type = bool; + default = true; + }; + EnableFallbackFont = mkOption { + type = bool; + default = false; + }; + EnableHardwareEncoding = mkOption { + type = bool; + default = true; + }; + EnableIntelLowPowerH264HwEncoder = mkOption { + type = bool; + default = false; + }; + EnableIntelLowPowerHevcHwEncoder = mkOption { + type = bool; + default = false; + }; + EnableSubtitleExtraction = mkOption { + type = bool; + default = true; + }; + EnableThrottling = mkOption { + type = bool; + default = false; + }; + EnableTonemapping = mkOption { + type = bool; + default = false; + }; + EnableVppTonemapping = mkOption { + type = bool; + default = false; + }; + EncoderAppPathDisplay = mkOption { + type = either path str; + default = "${pkgs.jellyfin-ffmpeg}/bin/ffmpeg"; + }; + EncodingThreadCount = mkOption { + type = int; + default = -1; + }; + H264Crf = mkOption { + type = int; + default = 23; + }; + H265Crf = mkOption { + type = int; + default = 28; + }; + HardwareDecodingCodecs.string = mkOption { + type = listOf str; + default = ["h254" "vc1"]; + }; + MaxMuxingQueueSize = mkOption { + type = int; + default = 2048; + }; + PreferSystemNativeHwDecoder = mkOption { + type = bool; + default = true; + }; + ThrottleDelaySeconds = mkOption { + type = int; + default = 180; + }; + TonemappingAlgorithm = mkOption { + type = str; + default = "bt2390"; + }; + TonemappingDesat = mkOption { + type = int; + default = 0; + }; + TonemappingMode = mkOption { + type = str; + default = "auto"; + }; + TonemappingParam = mkOption { + type = int; + default = 0; + }; + TonemappingPeak = mkOption { + type = int; + default = 100; + }; + TonemappingRange = mkOption { + type = str; + default = "auto"; + }; + VaapiDevice = mkOption { + type = either path str; + default = "/dev/dri/renderD128"; + }; + VppTonemappingBrightness = mkOption { + type = int; + default = 16; + }; + VppTonemappingContrast = mkOption { + type = int; + default = 1; + }; + }; + }; + default = {}; }; system = mkOption { - type = (submodule { - freeformType = (pkgs.formats.json { }).type; + type = submodule { + freeformType = (pkgs.formats.json {}).type; options = { ActivityLogRetentionDays = mkOption { type = int; @@ -347,7 +349,7 @@ in }; CorsHost.string = mkOption { type = listOf str; - default = [ "*" ]; + default = ["*"]; }; DisableLiveTvChannelUserDataName = mkOption { type = bool; @@ -439,19 +441,19 @@ in } { ItemType = "MusicVideo"; - DisabledMetadataFetchers.string = [ "The Open Movie Database" ]; - DisabledImageFetchers.string = [ "The Open Movie Database" ]; + DisabledMetadataFetchers.string = ["The Open Movie Database"]; + DisabledImageFetchers.string = ["The Open Movie Database"]; } { ItemType = "Series"; } { ItemType = "MusicAlbum"; - DisabledMetadataFetchers.string = [ "TheAudioDB" ]; + DisabledMetadataFetchers.string = ["TheAudioDB"]; } { ItemType = "MusicArtist"; - DisabledMetadataFetchers.string = [ "TheAudioDB" ]; + DisabledMetadataFetchers.string = ["TheAudioDB"]; } { ItemType = "BoxSet"; @@ -470,27 +472,27 @@ in type = str; }; DisabledMetadataSavers.string = mkOption { - default = [ ]; + default = []; type = listOf str; }; LocalMetadataReaderOrder.string = mkOption { - default = [ ]; + default = []; type = listOf str; }; DisabledMetadataFetchers.string = mkOption { - default = [ ]; + default = []; type = listOf str; }; MetadataFetcherOrder.string = mkOption { - default = [ ]; + default = []; type = listOf str; }; DisabledImageFetchers.string = mkOption { - default = [ ]; + default = []; type = listOf str; }; ImageFetcherOrder.string = mkOption { - default = [ ]; + default = []; type = listOf str; }; }; @@ -517,11 +519,13 @@ in default = ""; }; PluginRepositories.RepositoryInfo = mkOption { - default = [{ - Name = "Jellyfin Stable"; - Url = "https://repo.jellyfin.org/releases/plugin/manifest-stable.json"; - Enabled = true; - }]; + default = [ + { + Name = "Jellyfin Stable"; + Url = "https://repo.jellyfin.org/releases/plugin/manifest-stable.json"; + Enabled = true; + } + ]; type = listOf (submodule { options = { Name = mkOption { @@ -571,23 +575,23 @@ in }; SortRemoveCharacters.string = mkOption { type = listOf str; - default = [ "," "&" "-" "{" "}" "'" ]; + default = ["," "&" "-" "{" "}" "'"]; }; SortRemoveWords.string = mkOption { type = listOf str; - default = [ "the" "a" "an" ]; + default = ["the" "a" "an"]; }; SortReplaceCharacters.string = mkOption { type = listOf str; - default = [ "." "+" "%" ]; + default = ["." "+" "%"]; }; UICulture = mkOption { type = str; default = "en-US"; }; }; - }); - default = { }; + }; + default = {}; }; }; }; @@ -636,12 +640,11 @@ in touch "$jellyfin_dir/config/system.xml"; echo "$(system_file)" > "$jellyfin_dir/config/system.xml"; ''; - wantedBy = [ "multi-user.target" ]; - after = [ "jellyfin.service" ]; + wantedBy = ["multi-user.target"]; + after = ["jellyfin.service"]; serviceConfig = { Type = "oneshot"; }; }; }; } - diff --git a/modules/server/jellyseerr.nix b/modules/server/jellyseerr.nix index d2222c2..7af68d8 100644 --- a/modules/server/jellyseerr.nix +++ b/modules/server/jellyseerr.nix @@ -1,11 +1,13 @@ -{ config, lib, ... }: - -let - cfg = config.server.jellyseerr; -in { - imports = [ ]; - options.server.jellyseerr = with lib; with lib.types; { + config, + lib, + ... +}: let + cfg = config.server.jellyseerr; +in { + imports = []; + options.server.jellyseerr = with lib; + with lib.types; { enable = mkEnableOption ""; domain = mkOption { type = str; diff --git a/modules/server/network.nix b/modules/server/network.nix index 8264ffb..3a6e7f5 100644 --- a/modules/server/network.nix +++ b/modules/server/network.nix @@ -1,11 +1,13 @@ -{ config, lib, ... }: - -let - cfg = config.server.network; -in { - imports = [ ]; - options.server.network = with lib; with lib.types; { + config, + lib, + ... +}: let + cfg = config.server.network; +in { + imports = []; + options.server.network = with lib; + with lib.types; { enable = mkOption { type = bool; default = true; @@ -27,7 +29,7 @@ in }; nameservers = mkOption { type = listOf str; - default = [ "1.1.1.1" "8.8.8.8" ]; + default = ["1.1.1.1" "8.8.8.8"]; }; portForwarding = mkOption { type = bool; @@ -37,25 +39,39 @@ in type = bool; default = true; }; - settings = { }; + settings = {}; }; config = lib.mkIf cfg.enable { host.networking.hostName = cfg.hostName; networking = { dhcpcd.enable = true; - interfaces."${cfg.interface}".ipv4.addresses = [{ - address = cfg.localIp; - prefixLength = 28; - }]; + interfaces."${cfg.interface}".ipv4.addresses = [ + { + address = cfg.localIp; + prefixLength = 28; + } + ]; defaultGateway = cfg.defaultGateway; - nameservers = [ - (if config.server.tailscale.enable then "100.100.100.100" else null) - ] ++ cfg.nameservers; + nameservers = + [ + ( + if config.server.tailscale.enable + then "100.100.100.100" + else null + ) + ] + ++ cfg.nameservers; }; - boot.kernel.sysctl."net.ipv4.ip_forward" = if cfg.portForwarding then 1 else 0; - boot.kernel.sysctl."net.ipv6.conf.all.forwarding" = if cfg.portForwarding then 1 else 0; + boot.kernel.sysctl."net.ipv4.ip_forward" = + if cfg.portForwarding + then 1 + else 0; + boot.kernel.sysctl."net.ipv6.conf.all.forwarding" = + if cfg.portForwarding + then 1 + else 0; services.openssh.enable = cfg.openssh; }; diff --git a/modules/server/nextcloud.nix b/modules/server/nextcloud.nix index 0233817..c3406f2 100644 --- a/modules/server/nextcloud.nix +++ b/modules/server/nextcloud.nix @@ -1,11 +1,14 @@ -{ config, lib, pkgs, ... }: - -let - cfg = config.server.nextcloud; -in { - imports = [ ]; - options.server.nextcloud = with lib; with lib.types; { + config, + lib, + pkgs, + ... +}: let + cfg = config.server.nextcloud; +in { + imports = []; + options.server.nextcloud = with lib; + with lib.types; { enable = mkEnableOption ""; user = mkOption { type = str; diff --git a/modules/server/photoprism.nix b/modules/server/photoprism.nix index 0a1f600..a6b7dfb 100644 --- a/modules/server/photoprism.nix +++ b/modules/server/photoprism.nix @@ -1,11 +1,13 @@ -{ config, lib, ... }: - -let - cfg = config.server.photoprism; -in { - imports = [ ]; - options.server.photoprism = with lib; with lib.types; { + config, + lib, + ... +}: let + cfg = config.server.photoprism; +in { + imports = []; + options.server.photoprism = with lib; + with lib.types; { enable = mkEnableOption ""; user = mkOption { type = str; diff --git a/modules/server/tailscale.nix b/modules/server/tailscale.nix index 02fdeff..a624450 100644 --- a/modules/server/tailscale.nix +++ b/modules/server/tailscale.nix @@ -1,13 +1,15 @@ -{ config, lib, ... }: - -let - cfg = config.server.tailscale; -in { + config, + lib, + ... +}: let + cfg = config.server.tailscale; +in { imports = [ ./network.nix ]; - options.server.tailscale = with lib; with lib.types; { + options.server.tailscale = with lib; + with lib.types; { enable = mkEnableOption ""; mode = mkOption { type = enum [ @@ -21,7 +23,7 @@ in type = bool; default = false; }; - settings = { }; + settings = {}; }; config = lib.mkIf cfg.enable { services.tailscale = { @@ -29,7 +31,6 @@ in useRoutingFeatures = cfg.mode; }; - server.network = lib.mkIf cfg.exitNode { portForwarding = lib.mkDefault true; }; + server.network = lib.mkIf cfg.exitNode {portForwarding = lib.mkDefault true;}; }; } - diff --git a/secrets/decrypt.sh b/secrets/decrypt.sh new file mode 100755 index 0000000..30bc3e7 --- /dev/null +++ b/secrets/decrypt.sh @@ -0,0 +1,10 @@ +#!/usr/bin/env bash + +export SOPS_AGE_KEY_FILE=/home/guz/.config/sops/age/keys.txt + +secrets_dir="/home/guz/.nix/secrets" + +sops --output $secrets_dir/homelab-lesser-secrets.decrypted.json \ + -d $secrets_dir/homelab-lesser-secrets.json + + diff --git a/secrets/homelab-lesser-secrets.json b/secrets/homelab-lesser-secrets.json new file mode 100644 index 0000000..438d3a5 --- /dev/null +++ b/secrets/homelab-lesser-secrets.json @@ -0,0 +1,33 @@ +{ + "tailnet-name": "ENC[AES256_GCM,data:f9T+/IRApqThgMlE,iv:LufRlHxdon5mahAi1+jwbhTqcOZh2bdnUubfEL6QFg0=,tag:KmJ4E0EggzQh8ZCm2fLeGw==,type:str]", + "device-ip": "ENC[AES256_GCM,data:Ed6hS/9F52UGVLpAyw==,iv:sg9iVEmZxA2lNJoc0xwLRyDzoF1Cy48wp9CQf3zOOzQ=,tag:77RYGvjgw0QdZUsPcqVTvA==,type:str]", + "homelab-domain": "ENC[AES256_GCM,data:IQAkzgxJL4WsOqJ0RA==,iv:COJSPyCP33ZJJXz1blr4CTH3DfZ9oH/Em72VWlGWtO0=,tag:sLj91nAgVtvDiRcVzqgIsg==,type:str]", + "services": { + "forgejo": { + "domain": "ENC[AES256_GCM,data:DJDExE7VVmAk4ZLhOkTfD2wBY5i1,iv:tnOgrKCpglvDyk75mnmeoiz2trmD3r3wCL2etHmALC4=,tag:rAiEK9U48cR1q+W7Zbkhvg==,type:str]", + "port": "ENC[AES256_GCM,data:ydSACw==,iv:0RWRLLCU8YyYmOmTawns2Iy+ABiBFbBqgQ10+buZNt0=,tag:3QW0NzbKeUkcfYh/5my3fA==,type:float]", + "actions-token": "ENC[AES256_GCM,data:j9hpNPmbWC2z862ca8RtmB1A62P3F3L6hS1WdpCXiCEunDvHOo9qcg==,iv:DSWebuZqdwx8R9MaJgSvIVRfUOJO7OpR3ORjgp6amzw=,tag:/bPMMWsfeoKbY47JQgC38Q==,type:str]" + }, + "adguard": { + "domain": "ENC[AES256_GCM,data:QquWEbgpXY13UMV9BTXplQ5LhSgv,iv:0AstA5oaS8714QME3QK0/aiv9Khqk1bLCcFdCEPn+IA=,tag:XXIWjIjHQ0gZFSFBHU49Ag==,type:str]", + "port": "ENC[AES256_GCM,data:4JC+Dg==,iv:jACiG3MB0u8mKFhghBN3VzLBGkUYeCC58fGOuLePJ+M=,tag:Lz4Q8U24aOfjIA4tK6yZwg==,type:float]" + } + }, + "sops": { + "kms": null, + "gcp_kms": null, + "azure_kv": null, + "hc_vault": null, + "age": [ + { + "recipient": "age1sseqwwa7fc0ftry8njyuagdg28fkmtdwmj6m7p3etjsj83suee3shfzjyz", + "enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBnL3dCY1VLMmoxRFRmS0Ir\nV0ppTnI0RE5ZMjcvRGNPWkNxWFdJYTBDTG00ClRGQkh1UStGTmc0RE5aNy9nL3FI\nbHJIa3hLR0ZkTjd6WkFzOFkzeFdMNUEKLS0tIDBidk93Qy9LenFlSGZ2aEpuTUFt\nWVM2eS9UdXAvbzE4eEdKMjVEM3RLdm8KKeIhk+YOKVL9Y19lLyb6/Pxv8rbewK2e\nLm96jx+LOMOCFcQGxuFKWqQbTB4br/cPvRKSY5jFmFWqVg7pCPTAzQ==\n-----END AGE ENCRYPTED FILE-----\n" + } + ], + "lastmodified": "2024-04-07T21:39:36Z", + "mac": "ENC[AES256_GCM,data:29gkzrSMR1O6PRVMyBuNxRwvpAHwvY+VZxzfkzukxRdlQ8GKaskVf/xjIzTlojsRZDLRBIP7ZGfCRsmYskwfkoqEZRfQ+/LwEXdol/Lhyd+OM9aP7h+GP9+qjf4KN7JvJSzj3HNdUVJNULDmAFdRaKAkIkRl5lCrVUGZJTgfj3s=,iv:GVGchkF1YllSUePk+cIz2op50OLaeuTpizbuOOF7x0E=,tag:/ZoZllvCtKdaikA5TzsdGA==,type:str]", + "pgp": null, + "unencrypted_suffix": "_unencrypted", + "version": "3.8.1" + } +} \ No newline at end of file