refactor!: I went too close into the sun
Simlified everything, things were getting out of control
This commit is contained in:
@@ -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;
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user