refactor!: I went too close into the sun
Simlified everything, things were getting out of control
This commit is contained in:
@@ -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
|
||||
|
||||
45
flake.nix
45
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"
|
||||
];
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -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?
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
8
hosts/homelab/home.nix
Normal file
8
hosts/homelab/home.nix
Normal file
@@ -0,0 +1,8 @@
|
||||
{...}: {
|
||||
imports = [
|
||||
../../modules/home-manager
|
||||
];
|
||||
|
||||
profiles.gterminal.enable = true;
|
||||
programs.wezterm.enable = false;
|
||||
}
|
||||
@@ -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";
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
63
hosts/homelab/services.nix
Normal file
63
hosts/homelab/services.nix
Normal file
@@ -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;
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
{ ... }:
|
||||
|
||||
{
|
||||
imports = [
|
||||
./guz.nix
|
||||
];
|
||||
options = { };
|
||||
config = { };
|
||||
}
|
||||
@@ -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"
|
||||
'';
|
||||
};
|
||||
}];
|
||||
}
|
||||
@@ -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 { };
|
||||
}
|
||||
8
modules/home-manager/default.nix
Normal file
8
modules/home-manager/default.nix
Normal file
@@ -0,0 +1,8 @@
|
||||
{...}: {
|
||||
imports = [
|
||||
./programs
|
||||
./profiles
|
||||
];
|
||||
options = {};
|
||||
config = {};
|
||||
}
|
||||
7
modules/home-manager/profiles/default.nix
Normal file
7
modules/home-manager/profiles/default.nix
Normal file
@@ -0,0 +1,7 @@
|
||||
{...}: {
|
||||
imports = [
|
||||
./gterminal.nix
|
||||
];
|
||||
options = {};
|
||||
config = {};
|
||||
}
|
||||
165
modules/home-manager/profiles/gterminal.nix
Normal file
165
modules/home-manager/profiles/gterminal.nix
Normal file
@@ -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";
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -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 {
|
||||
@@ -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
|
||||
'';
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
}
|
||||
];
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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;
|
||||
94
modules/home-manager/programs-old/lf.nix
Normal file
94
modules/home-manager/programs-old/lf.nix
Normal file
@@ -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!";
|
||||
"<enter>" = "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
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
||||
437
modules/home-manager/programs-old/librewolf/default.nix
Normal file
437
modules/home-manager/programs-old/librewolf/default.nix
Normal file
@@ -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}<DT><A HREF="${
|
||||
escapeXML bookmark.url
|
||||
}" ADD_DATE="1" LAST_MODIFIED="1"${
|
||||
lib.optionalString (bookmark.keyword != null)
|
||||
" SHORTCUTURL=\"${escapeXML bookmark.keyword}\""
|
||||
}${
|
||||
lib.optionalString (bookmark.tags != [])
|
||||
" TAGS=\"${escapeXML (concatStringsSep "," bookmark.tags)}\""
|
||||
}>${escapeXML bookmark.name}</A>'';
|
||||
|
||||
directoryToHTML = indentLevel: directory: ''
|
||||
${indent indentLevel}<DT>${
|
||||
if directory.toolbar
|
||||
then ''
|
||||
<H3 ADD_DATE="1" LAST_MODIFIED="1" PERSONAL_TOOLBAR_FOLDER="true">Bookmarks Toolbar''
|
||||
else ''<H3 ADD_DATE="1" LAST_MODIFIED="1">${escapeXML directory.name}''
|
||||
}</H3>
|
||||
${indent indentLevel}<DL><p>
|
||||
${allItemsToHTML (indentLevel + 1) directory.bookmarks}
|
||||
${indent indentLevel}</DL><p>'';
|
||||
|
||||
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" ''
|
||||
<!DOCTYPE NETSCAPE-Bookmark-file-1>
|
||||
<!-- This is an automatically generated file.
|
||||
It will be read and overwritten.
|
||||
DO NOT EDIT! -->
|
||||
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=UTF-8">
|
||||
<TITLE>Bookmarks</TITLE>
|
||||
<H1>Bookmarks Menu</H1>
|
||||
<DL><p>
|
||||
${bookmarkEntries}
|
||||
</DL>
|
||||
'';
|
||||
|
||||
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;
|
||||
};
|
||||
}));
|
||||
};
|
||||
}
|
||||
@@ -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 {
|
||||
@@ -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
|
||||
)
|
||||
];
|
||||
};
|
||||
}
|
||||
@@ -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";
|
||||
@@ -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;
|
||||
84
modules/home-manager/programs-old/wezterm.nix
Normal file
84
modules/home-manager/programs-old/wezterm.nix
Normal file
@@ -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}"
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -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 {
|
||||
8
modules/home-manager/programs/default.nix
Normal file
8
modules/home-manager/programs/default.nix
Normal file
@@ -0,0 +1,8 @@
|
||||
{...}: {
|
||||
imports = [
|
||||
./neovim.nix
|
||||
./wezterm.nix
|
||||
];
|
||||
options = {};
|
||||
config = {};
|
||||
}
|
||||
@@ -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!";
|
||||
"<enter>" = "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
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -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}<DT><A HREF="${
|
||||
escapeXML bookmark.url
|
||||
}" ADD_DATE="1" LAST_MODIFIED="1"${
|
||||
lib.optionalString (bookmark.keyword != null)
|
||||
" SHORTCUTURL=\"${escapeXML bookmark.keyword}\""
|
||||
}${
|
||||
lib.optionalString (bookmark.tags != [ ])
|
||||
" TAGS=\"${escapeXML (concatStringsSep "," bookmark.tags)}\""
|
||||
}>${escapeXML bookmark.name}</A>'';
|
||||
|
||||
directoryToHTML = indentLevel: directory: ''
|
||||
${indent indentLevel}<DT>${
|
||||
if directory.toolbar then
|
||||
''
|
||||
<H3 ADD_DATE="1" LAST_MODIFIED="1" PERSONAL_TOOLBAR_FOLDER="true">Bookmarks Toolbar''
|
||||
else
|
||||
''<H3 ADD_DATE="1" LAST_MODIFIED="1">${escapeXML directory.name}''
|
||||
}</H3>
|
||||
${indent indentLevel}<DL><p>
|
||||
${allItemsToHTML (indentLevel + 1) directory.bookmarks}
|
||||
${indent indentLevel}</DL><p>'';
|
||||
|
||||
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" ''
|
||||
<!DOCTYPE NETSCAPE-Bookmark-file-1>
|
||||
<!-- This is an automatically generated file.
|
||||
It will be read and overwritten.
|
||||
DO NOT EDIT! -->
|
||||
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=UTF-8">
|
||||
<TITLE>Bookmarks</TITLE>
|
||||
<H1>Bookmarks Menu</H1>
|
||||
<DL><p>
|
||||
${bookmarkEntries}
|
||||
</DL>
|
||||
'';
|
||||
|
||||
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;
|
||||
};
|
||||
}));
|
||||
|
||||
};
|
||||
}
|
||||
30
modules/home-manager/programs/neovim.nix
Normal file
30
modules/home-manager/programs/neovim.nix
Normal file
@@ -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
|
||||
];
|
||||
};
|
||||
}
|
||||
@@ -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;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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";
|
||||
};
|
||||
};
|
||||
|
||||
@@ -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
|
||||
);
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
32
modules/nih/domains/default.nix
Normal file
32
modules/nih/domains/default.nix
Normal file
@@ -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];
|
||||
};
|
||||
}
|
||||
50
modules/nih/domains/tailscale-caddy.nix
Normal file
50
modules/nih/domains/tailscale-caddy.nix
Normal file
@@ -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;
|
||||
*/
|
||||
};
|
||||
};
|
||||
}
|
||||
24
modules/nih/domains/tailscale.nix
Normal file
24
modules/nih/domains/tailscale.nix
Normal file
@@ -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";
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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 = {};
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
}
|
||||
];
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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}
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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 {};
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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 {};
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
75
modules/nih/services/adguardhome.nix
Normal file
75
modules/nih/services/adguardhome.nix
Normal file
@@ -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);
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -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 {};
|
||||
}
|
||||
|
||||
@@ -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 = {};
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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"];
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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 = {};
|
||||
}
|
||||
|
||||
@@ -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";
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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?
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
10
modules/nixos/default.nix
Normal file
10
modules/nixos/default.nix
Normal file
@@ -0,0 +1,10 @@
|
||||
{...}: {
|
||||
imports = [
|
||||
./profiles
|
||||
./services
|
||||
./home-manager-helper.nix
|
||||
./programs
|
||||
];
|
||||
options = {};
|
||||
config = {};
|
||||
}
|
||||
248
modules/nixos/home-manager-helper.nix
Normal file
248
modules/nixos/home-manager-helper.nix
Normal file
@@ -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);
|
||||
};
|
||||
}
|
||||
7
modules/nixos/profiles/default.nix
Normal file
7
modules/nixos/profiles/default.nix
Normal file
@@ -0,0 +1,7 @@
|
||||
{...}: {
|
||||
imports = [
|
||||
./locale.nix
|
||||
];
|
||||
options = {};
|
||||
config = {};
|
||||
}
|
||||
64
modules/nixos/profiles/locale.nix
Normal file
64
modules/nixos/profiles/locale.nix
Normal file
@@ -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;
|
||||
};
|
||||
};
|
||||
}
|
||||
7
modules/nixos/programs/default.nix
Normal file
7
modules/nixos/programs/default.nix
Normal file
@@ -0,0 +1,7 @@
|
||||
{...}: {
|
||||
imports = [
|
||||
./nih
|
||||
];
|
||||
options = {};
|
||||
config = {};
|
||||
}
|
||||
40
modules/nixos/programs/nih/cli.nix
Normal file
40
modules/nixos/programs/nih/cli.nix
Normal file
@@ -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
|
||||
];
|
||||
};
|
||||
}
|
||||
124
modules/nixos/programs/nih/cli.sh
Normal file
124
modules/nixos/programs/nih/cli.sh
Normal file
@@ -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
|
||||
|
||||
23
modules/nixos/programs/nih/default.nix
Normal file
23
modules/nixos/programs/nih/default.nix
Normal file
@@ -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 {};
|
||||
}
|
||||
62
modules/nixos/services/adguardhome.nix
Normal file
62
modules/nixos/services/adguardhome.nix
Normal file
@@ -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);
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
9
modules/nixos/services/default.nix
Normal file
9
modules/nixos/services/default.nix
Normal file
@@ -0,0 +1,9 @@
|
||||
{...}: {
|
||||
imports = [
|
||||
./adguardhome.nix
|
||||
./forgejo.nix
|
||||
./tailscale.nix
|
||||
];
|
||||
options = {};
|
||||
config = {};
|
||||
}
|
||||
249
modules/nixos/services/forgejo.nix
Normal file
249
modules/nixos/services/forgejo.nix
Normal file
@@ -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;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
61
modules/nixos/services/tailscale.nix
Normal file
61
modules/nixos/services/tailscale.nix
Normal file
@@ -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);
|
||||
};
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
)
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -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 = {};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;};
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
10
secrets/decrypt.sh
Executable file
10
secrets/decrypt.sh
Executable file
@@ -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
|
||||
|
||||
|
||||
33
secrets/homelab-lesser-secrets.json
Normal file
33
secrets/homelab-lesser-secrets.json
Normal file
@@ -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"
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user