reformat
This commit is contained in:
parent
857140bbd2
commit
44d265ecdb
|
@ -3,7 +3,8 @@
|
||||||
lib,
|
lib,
|
||||||
pkgs,
|
pkgs,
|
||||||
...
|
...
|
||||||
}: {
|
}:
|
||||||
|
{
|
||||||
boot = lib.mkIf (!config.boot.isContainer) {
|
boot = lib.mkIf (!config.boot.isContainer) {
|
||||||
initrd.systemd = {
|
initrd.systemd = {
|
||||||
enable = true;
|
enable = true;
|
||||||
|
@ -14,7 +15,18 @@
|
||||||
storePaths = [ "${pkgs.bashInteractive}/bin/bash" ];
|
storePaths = [ "${pkgs.bashInteractive}/bin/bash" ];
|
||||||
};
|
};
|
||||||
|
|
||||||
initrd.availableKernelModules = ["xhci_pci" "nvme" "r8169" "usb_storage" "usbhid" "sd_mod" "rtsx_pci_sdmmc" "ahci" "uas" "tpm_crb"];
|
initrd.availableKernelModules = [
|
||||||
|
"xhci_pci"
|
||||||
|
"nvme"
|
||||||
|
"r8169"
|
||||||
|
"usb_storage"
|
||||||
|
"usbhid"
|
||||||
|
"sd_mod"
|
||||||
|
"rtsx_pci_sdmmc"
|
||||||
|
"ahci"
|
||||||
|
"uas"
|
||||||
|
"tpm_crb"
|
||||||
|
];
|
||||||
supportedFilesystems = [ "ntfs" ];
|
supportedFilesystems = [ "ntfs" ];
|
||||||
kernelModules = [ "kvm-intel" ];
|
kernelModules = [ "kvm-intel" ];
|
||||||
kernelParams = [
|
kernelParams = [
|
||||||
|
|
|
@ -1,8 +1,5 @@
|
||||||
|
{ inputs, lib, ... }:
|
||||||
{
|
{
|
||||||
inputs,
|
|
||||||
lib,
|
|
||||||
...
|
|
||||||
}: {
|
|
||||||
imports = [
|
imports = [
|
||||||
./boot.nix
|
./boot.nix
|
||||||
./home-manager.nix
|
./home-manager.nix
|
||||||
|
|
|
@ -4,7 +4,8 @@
|
||||||
pkgs,
|
pkgs,
|
||||||
nodes,
|
nodes,
|
||||||
...
|
...
|
||||||
}: {
|
}:
|
||||||
|
{
|
||||||
imports = [
|
imports = [
|
||||||
../../modules-hm/impermanence.nix
|
../../modules-hm/impermanence.nix
|
||||||
../../modules-hm/images.nix
|
../../modules-hm/images.nix
|
||||||
|
@ -18,9 +19,7 @@
|
||||||
spicePkgs = inputs.spicetify-nix.legacyPackages.${pkgs.system};
|
spicePkgs = inputs.spicetify-nix.legacyPackages.${pkgs.system};
|
||||||
};
|
};
|
||||||
sharedModules = [
|
sharedModules = [
|
||||||
{
|
{ home.stateVersion = stateVersion; }
|
||||||
home.stateVersion = stateVersion;
|
|
||||||
}
|
|
||||||
inputs.nix-index-database.hmModules.nix-index
|
inputs.nix-index-database.hmModules.nix-index
|
||||||
inputs.nixos-extra-modules.homeManagerModules.default
|
inputs.nixos-extra-modules.homeManagerModules.default
|
||||||
inputs.nixvim.homeManagerModules.nixvim
|
inputs.nixvim.homeManagerModules.nixvim
|
||||||
|
|
|
@ -3,35 +3,23 @@
|
||||||
lib,
|
lib,
|
||||||
pkgs,
|
pkgs,
|
||||||
...
|
...
|
||||||
}: let
|
}:
|
||||||
onlyHost =
|
let
|
||||||
lib.mkIf (!config.boot.isContainer);
|
onlyHost = lib.mkIf (!config.boot.isContainer);
|
||||||
prune = folder:
|
prune =
|
||||||
|
folder:
|
||||||
pkgs.writers.writePython3Bin "impermanence-prune" { } ''
|
pkgs.writers.writePython3Bin "impermanence-prune" { } ''
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
mounts = [${
|
mounts = [${
|
||||||
lib.concatStringsSep ", "
|
lib.concatStringsSep ", " (
|
||||||
((map (x:
|
(map (
|
||||||
"\""
|
x: "\"" + (if x.home != null then x.home + "/" else "") + x.directory + "\""
|
||||||
+ (
|
) config.environment.persistence.${folder}.directories)
|
||||||
if x.home != null
|
++ (map (
|
||||||
then x.home + "/"
|
x: "\"" + (if x.home != null then x.home + "/" else "") + x.file + "\""
|
||||||
else ""
|
) config.environment.persistence.${folder}.files)
|
||||||
)
|
)
|
||||||
+ x.directory
|
|
||||||
+ "\"")
|
|
||||||
config.environment.persistence.${folder}.directories)
|
|
||||||
++ (map (x:
|
|
||||||
"\""
|
|
||||||
+ (
|
|
||||||
if x.home != null
|
|
||||||
then x.home + "/"
|
|
||||||
else ""
|
|
||||||
)
|
|
||||||
+ x.file
|
|
||||||
+ "\"")
|
|
||||||
config.environment.persistence.${folder}.files))
|
|
||||||
}] # noqa: E501
|
}] # noqa: E501
|
||||||
mounts = [os.path.normpath(x) for x in mounts]
|
mounts = [os.path.normpath(x) for x in mounts]
|
||||||
mounts.sort()
|
mounts.sort()
|
||||||
|
@ -53,11 +41,10 @@
|
||||||
file=sys.stderr)
|
file=sys.stderr)
|
||||||
print("\n".join(erg))
|
print("\n".join(erg))
|
||||||
'';
|
'';
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
# to allow all users to access hm managed persistent folders
|
# to allow all users to access hm managed persistent folders
|
||||||
lib.scripts.impermanence.pruneScripts =
|
lib.scripts.impermanence.pruneScripts = lib.mapAttrs (k: _: prune k) config.environment.persistence;
|
||||||
lib.mapAttrs (k: _: prune k)
|
|
||||||
config.environment.persistence;
|
|
||||||
programs.fuse.userAllowOther = true;
|
programs.fuse.userAllowOther = true;
|
||||||
services.openssh.hostKeys = lib.mkForce [
|
services.openssh.hostKeys = lib.mkForce [
|
||||||
{
|
{
|
||||||
|
@ -68,15 +55,10 @@ in {
|
||||||
environment.persistence."/state" = {
|
environment.persistence."/state" = {
|
||||||
hideMounts = true;
|
hideMounts = true;
|
||||||
|
|
||||||
files =
|
files = [
|
||||||
[
|
|
||||||
"/etc/ssh/ssh_host_ed25519_key"
|
"/etc/ssh/ssh_host_ed25519_key"
|
||||||
"/etc/ssh/ssh_host_ed25519_key.pub"
|
"/etc/ssh/ssh_host_ed25519_key.pub"
|
||||||
]
|
] ++ lib.lists.optionals (!config.boot.isContainer) [ "/etc/machine-id" ];
|
||||||
++ lib.lists.optionals (!config.boot.isContainer)
|
|
||||||
[
|
|
||||||
"/etc/machine-id"
|
|
||||||
];
|
|
||||||
directories = [
|
directories = [
|
||||||
"/var/log"
|
"/var/log"
|
||||||
"/var/lib/systemd"
|
"/var/lib/systemd"
|
||||||
|
@ -99,9 +81,7 @@ in {
|
||||||
fileSystems."/state".neededForBoot = true;
|
fileSystems."/state".neededForBoot = true;
|
||||||
|
|
||||||
# After importing the rpool, rollback the root system to be empty.
|
# After importing the rpool, rollback the root system to be empty.
|
||||||
boot.initrd.systemd.services.impermanence-root =
|
boot.initrd.systemd.services.impermanence-root = onlyHost {
|
||||||
onlyHost
|
|
||||||
{
|
|
||||||
wantedBy = [ "initrd.target" ];
|
wantedBy = [ "initrd.target" ];
|
||||||
after = [ "zfs-import-rpool.service" ];
|
after = [ "zfs-import-rpool.service" ];
|
||||||
before = [ "sysroot.mount" ];
|
before = [ "sysroot.mount" ];
|
||||||
|
|
|
@ -1,8 +1,5 @@
|
||||||
|
{ lib, config, ... }:
|
||||||
{
|
{
|
||||||
lib,
|
|
||||||
config,
|
|
||||||
...
|
|
||||||
}: {
|
|
||||||
networking = {
|
networking = {
|
||||||
useNetworkd = true;
|
useNetworkd = true;
|
||||||
dhcpcd.enable = false;
|
dhcpcd.enable = false;
|
||||||
|
@ -10,8 +7,7 @@
|
||||||
# allow mdns port
|
# allow mdns port
|
||||||
firewall.allowedUDPPorts = [ 5353 ];
|
firewall.allowedUDPPorts = [ 5353 ];
|
||||||
renameInterfacesByMac = lib.mkIf (!config.boot.isContainer) (
|
renameInterfacesByMac = lib.mkIf (!config.boot.isContainer) (
|
||||||
lib.mapAttrs (_: v: v.mac)
|
lib.mapAttrs (_: v: v.mac) (config.secrets.secrets.local.networking.interfaces or { })
|
||||||
(config.secrets.secrets.local.networking.interfaces or {})
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
systemd.network = {
|
systemd.network = {
|
||||||
|
|
|
@ -1,8 +1,5 @@
|
||||||
|
{ config, lib, ... }:
|
||||||
{
|
{
|
||||||
config,
|
|
||||||
lib,
|
|
||||||
...
|
|
||||||
}: {
|
|
||||||
networking.nftables = {
|
networking.nftables = {
|
||||||
stopRuleset = lib.mkDefault ''
|
stopRuleset = lib.mkDefault ''
|
||||||
table inet filter {
|
table inet filter {
|
||||||
|
@ -36,8 +33,23 @@
|
||||||
nnf-ssh.enable = true;
|
nnf-ssh.enable = true;
|
||||||
nnf-icmp = {
|
nnf-icmp = {
|
||||||
enable = true;
|
enable = true;
|
||||||
ipv6Types = ["echo-request" "destination-unreachable" "packet-too-big" "time-exceeded" "parameter-problem" "nd-router-advert" "nd-neighbor-solicit" "nd-neighbor-advert"];
|
ipv6Types = [
|
||||||
ipv4Types = ["echo-request" "destination-unreachable" "router-advertisement" "time-exceeded" "parameter-problem"];
|
"echo-request"
|
||||||
|
"destination-unreachable"
|
||||||
|
"packet-too-big"
|
||||||
|
"time-exceeded"
|
||||||
|
"parameter-problem"
|
||||||
|
"nd-router-advert"
|
||||||
|
"nd-neighbor-solicit"
|
||||||
|
"nd-neighbor-advert"
|
||||||
|
];
|
||||||
|
ipv4Types = [
|
||||||
|
"echo-request"
|
||||||
|
"destination-unreachable"
|
||||||
|
"router-advertisement"
|
||||||
|
"time-exceeded"
|
||||||
|
"parameter-problem"
|
||||||
|
];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -45,11 +57,7 @@
|
||||||
from = [ "untrusted" ];
|
from = [ "untrusted" ];
|
||||||
to = [ "local" ];
|
to = [ "local" ];
|
||||||
|
|
||||||
inherit
|
inherit (config.networking.firewall) allowedTCPPorts allowedUDPPorts;
|
||||||
(config.networking.firewall)
|
|
||||||
allowedTCPPorts
|
|
||||||
allowedUDPPorts
|
|
||||||
;
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,14 +1,15 @@
|
||||||
|
{ inputs, stateVersion, ... }:
|
||||||
{
|
{
|
||||||
inputs,
|
|
||||||
stateVersion,
|
|
||||||
...
|
|
||||||
}: {
|
|
||||||
nix = {
|
nix = {
|
||||||
settings = {
|
settings = {
|
||||||
auto-optimise-store = true;
|
auto-optimise-store = true;
|
||||||
allowed-users = [ "@wheel" ];
|
allowed-users = [ "@wheel" ];
|
||||||
trusted-users = [ "root" ];
|
trusted-users = [ "root" ];
|
||||||
system-features = ["recursive-nix" "repl-flake" "big-parallel"];
|
system-features = [
|
||||||
|
"recursive-nix"
|
||||||
|
"repl-flake"
|
||||||
|
"big-parallel"
|
||||||
|
];
|
||||||
substituters = [
|
substituters = [
|
||||||
"https://nix-community.cachix.org"
|
"https://nix-community.cachix.org"
|
||||||
"https://cache.nixos.org"
|
"https://cache.nixos.org"
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
{lib, ...}: {
|
{ lib, ... }:
|
||||||
|
{
|
||||||
# Enable the OpenSSH daemon.
|
# Enable the OpenSSH daemon.
|
||||||
services.openssh = {
|
services.openssh = {
|
||||||
enable = true;
|
enable = true;
|
||||||
|
|
|
@ -5,24 +5,24 @@
|
||||||
pkgs,
|
pkgs,
|
||||||
config,
|
config,
|
||||||
...
|
...
|
||||||
}: {
|
}:
|
||||||
|
{
|
||||||
system.stateVersion = stateVersion;
|
system.stateVersion = stateVersion;
|
||||||
|
|
||||||
age.rekey = {
|
age.rekey = {
|
||||||
inherit
|
inherit (inputs.self.secretsConfig) masterIdentities extraEncryptionPubkeys;
|
||||||
(inputs.self.secretsConfig)
|
|
||||||
masterIdentities
|
|
||||||
extraEncryptionPubkeys
|
|
||||||
;
|
|
||||||
|
|
||||||
storageMode = "derivation";
|
storageMode = "derivation";
|
||||||
|
|
||||||
forceRekeyOnSystem = builtins.extraBuiltins.unsafeCurrentSystem;
|
forceRekeyOnSystem = builtins.extraBuiltins.unsafeCurrentSystem;
|
||||||
hostPubkey = let
|
hostPubkey =
|
||||||
|
let
|
||||||
pubkeyPath = config.node.secretsDir + "/host.pub";
|
pubkeyPath = config.node.secretsDir + "/host.pub";
|
||||||
in
|
in
|
||||||
lib.mkIf (lib.pathExists pubkeyPath || lib.trace "Missing pubkey for ${config.node.name}: ${toString pubkeyPath} not found, using dummy replacement key for now." false)
|
lib.mkIf (
|
||||||
pubkeyPath;
|
lib.pathExists pubkeyPath
|
||||||
|
|| lib.trace "Missing pubkey for ${config.node.name}: ${toString pubkeyPath} not found, using dummy replacement key for now." false
|
||||||
|
) pubkeyPath;
|
||||||
generatedSecretsDir = config.node.secretsDir + "/generated/";
|
generatedSecretsDir = config.node.secretsDir + "/generated/";
|
||||||
cacheDir = "/var/tmp/agenix-rekey/\"$UID\"";
|
cacheDir = "/var/tmp/agenix-rekey/\"$UID\"";
|
||||||
};
|
};
|
||||||
|
@ -71,7 +71,8 @@
|
||||||
|
|
||||||
powerManagement.cpuFreqGovernor = lib.mkDefault "powersave";
|
powerManagement.cpuFreqGovernor = lib.mkDefault "powersave";
|
||||||
|
|
||||||
secrets.secretFiles = let
|
secrets.secretFiles =
|
||||||
|
let
|
||||||
local = config.node.secretsDir + "/secrets.nix.age";
|
local = config.node.secretsDir + "/secrets.nix.age";
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,11 +1,13 @@
|
||||||
{
|
{
|
||||||
users.mutableUsers = false;
|
users.mutableUsers = false;
|
||||||
users.deterministicIds = let
|
users.deterministicIds =
|
||||||
|
let
|
||||||
uidGid = id: {
|
uidGid = id: {
|
||||||
uid = id;
|
uid = id;
|
||||||
gid = id;
|
gid = id;
|
||||||
};
|
};
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
nscd = uidGid 201;
|
nscd = uidGid 201;
|
||||||
sshd = uidGid 202;
|
sshd = uidGid 202;
|
||||||
tss = uidGid 203;
|
tss = uidGid 203;
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
{pkgs, ...}: {
|
{ pkgs, ... }:
|
||||||
|
{
|
||||||
environment.systemPackages = with pkgs; [ bluetuith ];
|
environment.systemPackages = with pkgs; [ bluetuith ];
|
||||||
|
|
||||||
hardware.bluetooth = {
|
hardware.bluetooth = {
|
||||||
|
@ -24,7 +25,5 @@
|
||||||
'';
|
'';
|
||||||
extraModules = with pkgs; [ pulseaudio-modules-bt ];
|
extraModules = with pkgs; [ pulseaudio-modules-bt ];
|
||||||
};
|
};
|
||||||
environment.persistence."/state".directories = [
|
environment.persistence."/state".directories = [ "/var/lib/bluetooth" ];
|
||||||
"/var/lib/bluetooth"
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1 @@
|
||||||
{
|
{ services.joycond.enable = true; }
|
||||||
services.joycond.enable = true;
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
# Configuration for actual physical machines
|
# Configuration for actual physical machines
|
||||||
{config, ...}: {
|
{ config, ... }:
|
||||||
|
{
|
||||||
hardware = {
|
hardware = {
|
||||||
enableRedistributableFirmware = true;
|
enableRedistributableFirmware = true;
|
||||||
enableAllFirmware = true;
|
enableAllFirmware = true;
|
||||||
|
|
|
@ -13,7 +13,10 @@ lib.optionalAttrs (!minimal) {
|
||||||
# packages = pkgs.linuxPackages_6_6_rt;
|
# packages = pkgs.linuxPackages_6_6_rt;
|
||||||
# };
|
# };
|
||||||
#};
|
#};
|
||||||
environment.systemPackages = with pkgs; [pulseaudio pulsemixer];
|
environment.systemPackages = with pkgs; [
|
||||||
|
pulseaudio
|
||||||
|
pulsemixer
|
||||||
|
];
|
||||||
|
|
||||||
hardware.pulseaudio.enable = lib.mkForce false;
|
hardware.pulseaudio.enable = lib.mkForce false;
|
||||||
security.rtkit.enable = true;
|
security.rtkit.enable = true;
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
{pkgs, ...}: {
|
{ pkgs, ... }:
|
||||||
|
{
|
||||||
environment.systemPackages = with pkgs; [
|
environment.systemPackages = with pkgs; [
|
||||||
yubikey-personalization
|
yubikey-personalization
|
||||||
yubikey-manager
|
yubikey-manager
|
||||||
|
@ -7,5 +8,8 @@
|
||||||
|
|
||||||
services.pcscd.enable = true;
|
services.pcscd.enable = true;
|
||||||
|
|
||||||
services.udev.packages = with pkgs; [yubikey-personalization libu2f-host];
|
services.udev.packages = with pkgs; [
|
||||||
|
yubikey-personalization
|
||||||
|
libu2f-host
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,13 +4,11 @@
|
||||||
pkgs,
|
pkgs,
|
||||||
lib,
|
lib,
|
||||||
...
|
...
|
||||||
}: let
|
}:
|
||||||
inherit
|
let
|
||||||
(lib)
|
inherit (lib) mkOption types;
|
||||||
mkOption
|
in
|
||||||
types
|
{
|
||||||
;
|
|
||||||
in {
|
|
||||||
options.hidpi = mkOption {
|
options.hidpi = mkOption {
|
||||||
default = false;
|
default = false;
|
||||||
type = types.bool;
|
type = types.bool;
|
||||||
|
@ -18,14 +16,10 @@ in {
|
||||||
};
|
};
|
||||||
|
|
||||||
# stylix acceses stylix options on import meaning you can only import this module when you're actually setting stylix options
|
# stylix acceses stylix options on import meaning you can only import this module when you're actually setting stylix options
|
||||||
imports = [
|
imports = [ inputs.stylix.nixosModules.stylix ];
|
||||||
inputs.stylix.nixosModules.stylix
|
|
||||||
];
|
|
||||||
|
|
||||||
config = {
|
config = {
|
||||||
environment.systemPackages = with pkgs; [
|
environment.systemPackages = with pkgs; [ xdg-utils ];
|
||||||
xdg-utils
|
|
||||||
];
|
|
||||||
xdg.portal = {
|
xdg.portal = {
|
||||||
xdgOpenUsePortal = true;
|
xdgOpenUsePortal = true;
|
||||||
enable = true;
|
enable = true;
|
||||||
|
@ -38,9 +32,7 @@ in {
|
||||||
"gtk"
|
"gtk"
|
||||||
"hyprland"
|
"hyprland"
|
||||||
];
|
];
|
||||||
sway.default = [
|
sway.default = [ "wlr" ];
|
||||||
"wlr"
|
|
||||||
];
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
# needed for gnome pinentry
|
# needed for gnome pinentry
|
||||||
|
@ -160,20 +152,19 @@ in {
|
||||||
};
|
};
|
||||||
|
|
||||||
home-manager.sharedModules = [
|
home-manager.sharedModules = [
|
||||||
({
|
(
|
||||||
|
{
|
||||||
pkgs,
|
pkgs,
|
||||||
config,
|
config,
|
||||||
nixosConfig,
|
nixosConfig,
|
||||||
...
|
...
|
||||||
}: {
|
}:
|
||||||
|
{
|
||||||
stylix = {
|
stylix = {
|
||||||
cursor = {
|
cursor = {
|
||||||
package = pkgs.openzone-cursors;
|
package = pkgs.openzone-cursors;
|
||||||
name = "OpenZone_White_Slim";
|
name = "OpenZone_White_Slim";
|
||||||
size =
|
size = if nixosConfig.hidpi then 48 else 18;
|
||||||
if nixosConfig.hidpi
|
|
||||||
then 48
|
|
||||||
else 18;
|
|
||||||
};
|
};
|
||||||
inherit (nixosConfig.stylix) polarity;
|
inherit (nixosConfig.stylix) polarity;
|
||||||
targets = {
|
targets = {
|
||||||
|
@ -194,7 +185,8 @@ in {
|
||||||
"Xft.rgba" = "rgb";
|
"Xft.rgba" = "rgb";
|
||||||
};
|
};
|
||||||
|
|
||||||
gtk = let
|
gtk =
|
||||||
|
let
|
||||||
gtk34extraConfig = {
|
gtk34extraConfig = {
|
||||||
gtk-application-prefer-dark-theme = 1;
|
gtk-application-prefer-dark-theme = 1;
|
||||||
gtk-cursor-theme-size = 18;
|
gtk-cursor-theme-size = 18;
|
||||||
|
@ -205,7 +197,8 @@ in {
|
||||||
gtk-xft-hintstyle = "hintfull";
|
gtk-xft-hintstyle = "hintfull";
|
||||||
gtk-xft-rgba = "rgb";
|
gtk-xft-rgba = "rgb";
|
||||||
};
|
};
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
enable = true;
|
enable = true;
|
||||||
iconTheme = {
|
iconTheme = {
|
||||||
name = "Vimix-Doder";
|
name = "Vimix-Doder";
|
||||||
|
@ -224,7 +217,8 @@ in {
|
||||||
platformTheme.name = "adwaita";
|
platformTheme.name = "adwaita";
|
||||||
style.name = "Adwaita-Dark";
|
style.name = "Adwaita-Dark";
|
||||||
};
|
};
|
||||||
})
|
}
|
||||||
|
)
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,5 @@
|
||||||
|
{ config, pkgs, ... }:
|
||||||
{
|
{
|
||||||
config,
|
|
||||||
pkgs,
|
|
||||||
...
|
|
||||||
}: {
|
|
||||||
age.secrets.initrd_host_ed25519_key.generator.script = "ssh-ed25519";
|
age.secrets.initrd_host_ed25519_key.generator.script = "ssh-ed25519";
|
||||||
|
|
||||||
boot.initrd.network.enable = true;
|
boot.initrd.network.enable = true;
|
||||||
|
@ -30,7 +27,10 @@
|
||||||
${pkgs.openssh}/bin/ssh-keygen -t ed25519 -N "" -f "${config.age.secrets.initrd_host_ed25519_key.path}"
|
${pkgs.openssh}/bin/ssh-keygen -t ed25519 -N "" -f "${config.age.secrets.initrd_host_ed25519_key.path}"
|
||||||
fi
|
fi
|
||||||
'';
|
'';
|
||||||
deps = ["agenixInstall" "users"];
|
deps = [
|
||||||
|
"agenixInstall"
|
||||||
|
"users"
|
||||||
|
];
|
||||||
};
|
};
|
||||||
system.activationScripts.agenixChown.deps = [ "agenixEnsureInitrdHostkey" ];
|
system.activationScripts.agenixChown.deps = [ "agenixEnsureInitrdHostkey" ];
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,11 @@
|
||||||
{pkgs, ...}: {
|
{ pkgs, ... }:
|
||||||
|
{
|
||||||
services.printing = {
|
services.printing = {
|
||||||
enable = true;
|
enable = true;
|
||||||
drivers = [pkgs.hplipWithPlugin pkgs.hplip];
|
drivers = [
|
||||||
|
pkgs.hplipWithPlugin
|
||||||
|
pkgs.hplip
|
||||||
|
];
|
||||||
};
|
};
|
||||||
environment.persistence."/state".directories = [
|
environment.persistence."/state".directories = [
|
||||||
{
|
{
|
||||||
|
|
|
@ -8,10 +8,7 @@
|
||||||
lib.optionalAttrs (!minimal) {
|
lib.optionalAttrs (!minimal) {
|
||||||
environment.systemPackages = [
|
environment.systemPackages = [
|
||||||
# For debugging and troubleshooting Secure Boot.
|
# For debugging and troubleshooting Secure Boot.
|
||||||
(pkgs.sbctl.override
|
(pkgs.sbctl.override { databasePath = "/run/secureboot"; })
|
||||||
{
|
|
||||||
databasePath = "/run/secureboot";
|
|
||||||
})
|
|
||||||
];
|
];
|
||||||
age.secrets.secureboot.rekeyFile = ../../hosts/${config.node.name}/secrets/secureboot.tar.age;
|
age.secrets.secureboot.rekeyFile = ../../hosts/${config.node.name}/secrets/secureboot.tar.age;
|
||||||
system.activationScripts.securebootuntar = {
|
system.activationScripts.securebootuntar = {
|
||||||
|
|
|
@ -8,8 +8,8 @@ lib.optionalAttrs (!minimal) {
|
||||||
programs.steam = {
|
programs.steam = {
|
||||||
enable = true;
|
enable = true;
|
||||||
package = pkgs.steam.override {
|
package = pkgs.steam.override {
|
||||||
extraPkgs = pkgs:
|
extraPkgs =
|
||||||
with pkgs; [
|
pkgs: with pkgs; [
|
||||||
# vampir überlebende braucht diese pkgs
|
# vampir überlebende braucht diese pkgs
|
||||||
libgdiplus
|
libgdiplus
|
||||||
cups
|
cups
|
||||||
|
|
|
@ -28,10 +28,9 @@ lib.optionalAttrs (!minimal) {
|
||||||
disableWhileTyping = true;
|
disableWhileTyping = true;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
services.udev.extraRules = let
|
services.udev.extraRules =
|
||||||
exe =
|
let
|
||||||
pkgs.writeShellScript "set-key-repeat"
|
exe = pkgs.writeShellScript "set-key-repeat" ''
|
||||||
''
|
|
||||||
if [ -d "/tmp/.X11-unix" ]; then
|
if [ -d "/tmp/.X11-unix" ]; then
|
||||||
for D in /tmp/.X11-unix/*; do
|
for D in /tmp/.X11-unix/*; do
|
||||||
file=$(${pkgs.coreutils}/bin/basename $D)
|
file=$(${pkgs.coreutils}/bin/basename $D)
|
||||||
|
@ -43,7 +42,8 @@ lib.optionalAttrs (!minimal) {
|
||||||
done
|
done
|
||||||
fi
|
fi
|
||||||
'';
|
'';
|
||||||
in ''
|
in
|
||||||
|
''
|
||||||
ACTION=="add", SUBSYSTEM=="input", ATTRS{bInterfaceClass}=="03", RUN+="${exe}"
|
ACTION=="add", SUBSYSTEM=="input", ATTRS{bInterfaceClass}=="03", RUN+="${exe}"
|
||||||
'';
|
'';
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,8 @@
|
||||||
config,
|
config,
|
||||||
lib,
|
lib,
|
||||||
...
|
...
|
||||||
}: {
|
}:
|
||||||
|
{
|
||||||
boot.supportedFilesystems = [ "zfs" ];
|
boot.supportedFilesystems = [ "zfs" ];
|
||||||
boot.kernelPackages = lib.mkDefault config.boot.zfs.package.latestCompatibleLinuxPackages;
|
boot.kernelPackages = lib.mkDefault config.boot.zfs.package.latestCompatibleLinuxPackages;
|
||||||
|
|
||||||
|
|
|
@ -8,9 +8,5 @@
|
||||||
enable = true;
|
enable = true;
|
||||||
settings.port = 3000;
|
settings.port = 3000;
|
||||||
};
|
};
|
||||||
environment.persistence."/persist".directories = [
|
environment.persistence."/persist".directories = [ { directory = "/var/lib/private/actual"; } ];
|
||||||
{
|
|
||||||
directory = "/var/lib/private/actual";
|
|
||||||
}
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,5 @@
|
||||||
|
{ config, lib, ... }:
|
||||||
{
|
{
|
||||||
config,
|
|
||||||
lib,
|
|
||||||
...
|
|
||||||
}: {
|
|
||||||
wireguard.elisabeth = {
|
wireguard.elisabeth = {
|
||||||
client.via = "elisabeth";
|
client.via = "elisabeth";
|
||||||
firewallRuleForNode.elisabeth.allowedTCPPorts = [ config.services.adguardhome.port ];
|
firewallRuleForNode.elisabeth.allowedTCPPorts = [ config.services.adguardhome.port ];
|
||||||
|
@ -16,8 +13,12 @@
|
||||||
settings = {
|
settings = {
|
||||||
dns = {
|
dns = {
|
||||||
bind_hosts = [
|
bind_hosts = [
|
||||||
(lib.net.cidr.host config.secrets.secrets.global.net.ips.${config.node.name} config.secrets.secrets.global.net.privateSubnetv4)
|
(lib.net.cidr.host config.secrets.secrets.global.net.ips.${config.node.name}
|
||||||
(lib.net.cidr.host config.secrets.secrets.global.net.ips.${config.node.name} config.secrets.secrets.global.net.privateSubnetv6)
|
config.secrets.secrets.global.net.privateSubnetv4
|
||||||
|
)
|
||||||
|
(lib.net.cidr.host config.secrets.secrets.global.net.ips.${config.node.name}
|
||||||
|
config.secrets.secrets.global.net.privateSubnetv6
|
||||||
|
)
|
||||||
];
|
];
|
||||||
anonymize_client_ip = false;
|
anonymize_client_ip = false;
|
||||||
upstream_dns = [
|
upstream_dns = [
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
{config, ...}: {
|
{ config, ... }:
|
||||||
|
{
|
||||||
age.secrets.cloudflare_token_dns = {
|
age.secrets.cloudflare_token_dns = {
|
||||||
rekeyFile = config.node.secretsDir + "/cloudflare_api_token.age";
|
rekeyFile = config.node.secretsDir + "/cloudflare_api_token.age";
|
||||||
mode = "440";
|
mode = "440";
|
||||||
|
|
|
@ -1,8 +1,5 @@
|
||||||
|
{ config, nodes, ... }:
|
||||||
{
|
{
|
||||||
config,
|
|
||||||
nodes,
|
|
||||||
...
|
|
||||||
}: {
|
|
||||||
i18n.supportedLocales = [ "all" ];
|
i18n.supportedLocales = [ "all" ];
|
||||||
wireguard.elisabeth = {
|
wireguard.elisabeth = {
|
||||||
client.via = "elisabeth";
|
client.via = "elisabeth";
|
||||||
|
|
|
@ -4,9 +4,11 @@
|
||||||
pkgs,
|
pkgs,
|
||||||
lib,
|
lib,
|
||||||
...
|
...
|
||||||
}: let
|
}:
|
||||||
|
let
|
||||||
forgejoDomain = "forge.${config.secrets.secrets.global.domains.web}";
|
forgejoDomain = "forge.${config.secrets.secrets.global.domains.web}";
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
age.secrets.resticpasswd = {
|
age.secrets.resticpasswd = {
|
||||||
generator.script = "alnum";
|
generator.script = "alnum";
|
||||||
};
|
};
|
||||||
|
@ -52,7 +54,9 @@ in {
|
||||||
|
|
||||||
wireguard.elisabeth = {
|
wireguard.elisabeth = {
|
||||||
client.via = "elisabeth";
|
client.via = "elisabeth";
|
||||||
firewallRuleForNode.elisabeth.allowedTCPPorts = [config.services.forgejo.settings.server.HTTP_PORT];
|
firewallRuleForNode.elisabeth.allowedTCPPorts = [
|
||||||
|
config.services.forgejo.settings.server.HTTP_PORT
|
||||||
|
];
|
||||||
};
|
};
|
||||||
networking.firewall.allowedTCPPorts = [ config.services.forgejo.settings.server.SSH_PORT ];
|
networking.firewall.allowedTCPPorts = [ config.services.forgejo.settings.server.SSH_PORT ];
|
||||||
|
|
||||||
|
@ -145,7 +149,8 @@ in {
|
||||||
# see https://github.com/go-gitea/gitea/issues/21376.
|
# see https://github.com/go-gitea/gitea/issues/21376.
|
||||||
systemd.services.forgejo = {
|
systemd.services.forgejo = {
|
||||||
serviceConfig.RestartSec = "60"; # Retry every minute
|
serviceConfig.RestartSec = "60"; # Retry every minute
|
||||||
preStart = let
|
preStart =
|
||||||
|
let
|
||||||
exe = lib.getExe config.services.forgejo.package;
|
exe = lib.getExe config.services.forgejo.package;
|
||||||
providerName = "kanidm";
|
providerName = "kanidm";
|
||||||
clientId = "forgejo";
|
clientId = "forgejo";
|
||||||
|
|
|
@ -4,7 +4,8 @@
|
||||||
nodes,
|
nodes,
|
||||||
config,
|
config,
|
||||||
...
|
...
|
||||||
}: let
|
}:
|
||||||
|
let
|
||||||
version = "v1.106.4";
|
version = "v1.106.4";
|
||||||
immichDomain = "immich.${config.secrets.secrets.global.domains.web}";
|
immichDomain = "immich.${config.secrets.secrets.global.domains.web}";
|
||||||
|
|
||||||
|
@ -136,21 +137,14 @@
|
||||||
serviceConfig = {
|
serviceConfig = {
|
||||||
Restart = "always";
|
Restart = "always";
|
||||||
};
|
};
|
||||||
after = [
|
after = [ "podman-network-immich-default.service" ];
|
||||||
"podman-network-immich-default.service"
|
requires = [ "podman-network-immich-default.service" ];
|
||||||
];
|
partOf = [ "podman-compose-immich-root.target" ];
|
||||||
requires = [
|
wantedBy = [ "podman-compose-immich-root.target" ];
|
||||||
"podman-network-immich-default.service"
|
|
||||||
];
|
|
||||||
partOf = [
|
|
||||||
"podman-compose-immich-root.target"
|
|
||||||
];
|
|
||||||
wantedBy = [
|
|
||||||
"podman-compose-immich-root.target"
|
|
||||||
];
|
|
||||||
};
|
};
|
||||||
processedConfigFile = "/run/agenix/immich.config.json";
|
processedConfigFile = "/run/agenix/immich.config.json";
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
age.secrets.resticpasswd = {
|
age.secrets.resticpasswd = {
|
||||||
generator.script = "alnum";
|
generator.script = "alnum";
|
||||||
};
|
};
|
||||||
|
@ -313,9 +307,7 @@ in {
|
||||||
"${upload_folder}:/usr/src/app/upload:rw"
|
"${upload_folder}:/usr/src/app/upload:rw"
|
||||||
"${environment.DB_PASSWORD_FILE}:${environment.DB_PASSWORD_FILE}:ro"
|
"${environment.DB_PASSWORD_FILE}:${environment.DB_PASSWORD_FILE}:ro"
|
||||||
];
|
];
|
||||||
ports = [
|
ports = [ "3000:3001/tcp" ];
|
||||||
"3000:3001/tcp"
|
|
||||||
];
|
|
||||||
dependsOn = [
|
dependsOn = [
|
||||||
"immich_postgres"
|
"immich_postgres"
|
||||||
"immich_redis"
|
"immich_redis"
|
||||||
|
@ -327,9 +319,7 @@ in {
|
||||||
"--ip=${ipImmichServer}"
|
"--ip=${ipImmichServer}"
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
systemd.services."podman-immich_server" =
|
systemd.services."podman-immich_server" = serviceConfig // {
|
||||||
serviceConfig
|
|
||||||
// {
|
|
||||||
unitConfig.UpheldBy = [
|
unitConfig.UpheldBy = [
|
||||||
"podman-immich_postgres.service"
|
"podman-immich_postgres.service"
|
||||||
"podman-immich_redis.service"
|
"podman-immich_redis.service"
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
{config, ...}: let
|
{ config, ... }:
|
||||||
|
let
|
||||||
kanidmdomain = "auth.${config.secrets.secrets.global.domains.web}";
|
kanidmdomain = "auth.${config.secrets.secrets.global.domains.web}";
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
imports = [ ../../modules/kanidm.nix ];
|
imports = [ ../../modules/kanidm.nix ];
|
||||||
wireguard.elisabeth = {
|
wireguard.elisabeth = {
|
||||||
client.via = "elisabeth";
|
client.via = "elisabeth";
|
||||||
|
@ -84,7 +86,11 @@ in {
|
||||||
displayName = "paperless";
|
displayName = "paperless";
|
||||||
originUrl = "https://ppl.${config.secrets.secrets.global.domains.web}/";
|
originUrl = "https://ppl.${config.secrets.secrets.global.domains.web}/";
|
||||||
basicSecretFile = config.age.secrets.oauth2-paperless.path;
|
basicSecretFile = config.age.secrets.oauth2-paperless.path;
|
||||||
scopeMaps."paperless.access" = ["openid" "email" "profile"];
|
scopeMaps."paperless.access" = [
|
||||||
|
"openid"
|
||||||
|
"email"
|
||||||
|
"profile"
|
||||||
|
];
|
||||||
preferShortUsername = true;
|
preferShortUsername = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -100,7 +106,11 @@ in {
|
||||||
originUrl = "https://nc.${config.secrets.secrets.global.domains.web}/";
|
originUrl = "https://nc.${config.secrets.secrets.global.domains.web}/";
|
||||||
basicSecretFile = config.age.secrets.oauth2-nextcloud.path;
|
basicSecretFile = config.age.secrets.oauth2-nextcloud.path;
|
||||||
allowInsecureClientDisablePkce = true;
|
allowInsecureClientDisablePkce = true;
|
||||||
scopeMaps."nextcloud.access" = ["openid" "email" "profile"];
|
scopeMaps."nextcloud.access" = [
|
||||||
|
"openid"
|
||||||
|
"email"
|
||||||
|
"profile"
|
||||||
|
];
|
||||||
preferShortUsername = true;
|
preferShortUsername = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -117,7 +127,11 @@ in {
|
||||||
basicSecretFile = config.age.secrets.oauth2-immich.path;
|
basicSecretFile = config.age.secrets.oauth2-immich.path;
|
||||||
allowInsecureClientDisablePkce = true;
|
allowInsecureClientDisablePkce = true;
|
||||||
enableLegacyCrypto = true;
|
enableLegacyCrypto = true;
|
||||||
scopeMaps."immich.access" = ["openid" "email" "profile"];
|
scopeMaps."immich.access" = [
|
||||||
|
"openid"
|
||||||
|
"email"
|
||||||
|
"profile"
|
||||||
|
];
|
||||||
preferShortUsername = true;
|
preferShortUsername = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -131,11 +145,31 @@ in {
|
||||||
displayName = "Oauth2-Proxy";
|
displayName = "Oauth2-Proxy";
|
||||||
originUrl = "https://oauth2.${config.secrets.secrets.global.domains.web}/";
|
originUrl = "https://oauth2.${config.secrets.secrets.global.domains.web}/";
|
||||||
basicSecretFile = config.age.secrets.oauth2-proxy.path;
|
basicSecretFile = config.age.secrets.oauth2-proxy.path;
|
||||||
scopeMaps."adguardhome.access" = ["openid" "email" "profile"];
|
scopeMaps."adguardhome.access" = [
|
||||||
scopeMaps."rss.access" = ["openid" "email" "profile"];
|
"openid"
|
||||||
scopeMaps."firefly.access" = ["openid" "email" "profile"];
|
"email"
|
||||||
scopeMaps."ollama.access" = ["openid" "email" "profile"];
|
"profile"
|
||||||
scopeMaps."octoprint.access" = ["openid" "email" "profile"];
|
];
|
||||||
|
scopeMaps."rss.access" = [
|
||||||
|
"openid"
|
||||||
|
"email"
|
||||||
|
"profile"
|
||||||
|
];
|
||||||
|
scopeMaps."firefly.access" = [
|
||||||
|
"openid"
|
||||||
|
"email"
|
||||||
|
"profile"
|
||||||
|
];
|
||||||
|
scopeMaps."ollama.access" = [
|
||||||
|
"openid"
|
||||||
|
"email"
|
||||||
|
"profile"
|
||||||
|
];
|
||||||
|
scopeMaps."octoprint.access" = [
|
||||||
|
"openid"
|
||||||
|
"email"
|
||||||
|
"profile"
|
||||||
|
];
|
||||||
preferShortUsername = true;
|
preferShortUsername = true;
|
||||||
claimMaps.groups = {
|
claimMaps.groups = {
|
||||||
joinType = "array";
|
joinType = "array";
|
||||||
|
@ -157,7 +191,11 @@ in {
|
||||||
displayName = "Forgejo";
|
displayName = "Forgejo";
|
||||||
originUrl = "https://forge.${config.secrets.secrets.global.domains.web}/";
|
originUrl = "https://forge.${config.secrets.secrets.global.domains.web}/";
|
||||||
basicSecretFile = config.age.secrets.oauth2-forgejo.path;
|
basicSecretFile = config.age.secrets.oauth2-forgejo.path;
|
||||||
scopeMaps."forgejo.access" = ["openid" "email" "profile"];
|
scopeMaps."forgejo.access" = [
|
||||||
|
"openid"
|
||||||
|
"email"
|
||||||
|
"profile"
|
||||||
|
];
|
||||||
allowInsecureClientDisablePkce = true;
|
allowInsecureClientDisablePkce = true;
|
||||||
preferShortUsername = true;
|
preferShortUsername = true;
|
||||||
claimMaps.groups = {
|
claimMaps.groups = {
|
||||||
|
@ -166,8 +204,7 @@ in {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
groups."netbird.access" = {
|
groups."netbird.access" = { };
|
||||||
};
|
|
||||||
systems.oauth2.netbird = {
|
systems.oauth2.netbird = {
|
||||||
public = true;
|
public = true;
|
||||||
displayName = "Netbird";
|
displayName = "Netbird";
|
||||||
|
@ -175,7 +212,11 @@ in {
|
||||||
preferShortUsername = true;
|
preferShortUsername = true;
|
||||||
enableLocalhostRedirects = true;
|
enableLocalhostRedirects = true;
|
||||||
enableLegacyCrypto = true;
|
enableLegacyCrypto = true;
|
||||||
scopeMaps."netbird.access" = ["openid" "email" "profile"];
|
scopeMaps."netbird.access" = [
|
||||||
|
"openid"
|
||||||
|
"email"
|
||||||
|
"profile"
|
||||||
|
];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -5,12 +5,17 @@
|
||||||
pkgs,
|
pkgs,
|
||||||
lib,
|
lib,
|
||||||
...
|
...
|
||||||
}: let
|
}:
|
||||||
|
let
|
||||||
priv_domain = config.secrets.secrets.global.domains.mail_private;
|
priv_domain = config.secrets.secrets.global.domains.mail_private;
|
||||||
domain = config.secrets.secrets.global.domains.mail_public;
|
domain = config.secrets.secrets.global.domains.mail_public;
|
||||||
mailDomains = [priv_domain domain];
|
mailDomains = [
|
||||||
|
priv_domain
|
||||||
|
domain
|
||||||
|
];
|
||||||
maddyBackupDir = "/var/cache/backups/maddy";
|
maddyBackupDir = "/var/cache/backups/maddy";
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
systemd.tmpfiles.settings = {
|
systemd.tmpfiles.settings = {
|
||||||
"10-maddy".${maddyBackupDir}.d = {
|
"10-maddy".${maddyBackupDir}.d = {
|
||||||
inherit (config.services.maddy) user group;
|
inherit (config.services.maddy) user group;
|
||||||
|
@ -40,7 +45,10 @@ in {
|
||||||
inherit (config.secrets.secrets.global.hetzner.users.maddy) subUid path;
|
inherit (config.secrets.secrets.global.hetzner.users.maddy) subUid path;
|
||||||
sshAgeSecret = "maddyHetznerSsh";
|
sshAgeSecret = "maddyHetznerSsh";
|
||||||
};
|
};
|
||||||
paths = ["/var/lib/maddy/messages" maddyBackupDir];
|
paths = [
|
||||||
|
"/var/lib/maddy/messages"
|
||||||
|
maddyBackupDir
|
||||||
|
];
|
||||||
pruneOpts = [
|
pruneOpts = [
|
||||||
"--keep-daily 10"
|
"--keep-daily 10"
|
||||||
"--keep-weekly 7"
|
"--keep-weekly 7"
|
||||||
|
@ -49,14 +57,13 @@ in {
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
systemd.services.maddy-backup = let
|
systemd.services.maddy-backup =
|
||||||
|
let
|
||||||
cfg = config.systemd.services.maddy;
|
cfg = config.systemd.services.maddy;
|
||||||
in {
|
in
|
||||||
description = "Maddy db backup";
|
|
||||||
serviceConfig =
|
|
||||||
lib.recursiveUpdate
|
|
||||||
cfg.serviceConfig
|
|
||||||
{
|
{
|
||||||
|
description = "Maddy db backup";
|
||||||
|
serviceConfig = lib.recursiveUpdate cfg.serviceConfig {
|
||||||
ExecStart = "${pkgs.sqlite}/bin/sqlite3 /var/lib/maddy/imapsql.db \".backup '${maddyBackupDir}/imapsql.sqlite3'\"";
|
ExecStart = "${pkgs.sqlite}/bin/sqlite3 /var/lib/maddy/imapsql.db \".backup '${maddyBackupDir}/imapsql.sqlite3'\"";
|
||||||
Restart = "no";
|
Restart = "no";
|
||||||
Type = "oneshot";
|
Type = "oneshot";
|
||||||
|
@ -73,7 +80,10 @@ in {
|
||||||
};
|
};
|
||||||
# Opening ports for additional TLS listeners. This is not yet
|
# Opening ports for additional TLS listeners. This is not yet
|
||||||
# implemented in the module.
|
# implemented in the module.
|
||||||
networking.firewall.allowedTCPPorts = [993 465];
|
networking.firewall.allowedTCPPorts = [
|
||||||
|
993
|
||||||
|
465
|
||||||
|
];
|
||||||
services.maddy = {
|
services.maddy = {
|
||||||
enable = true;
|
enable = true;
|
||||||
hostname = "mx1." + domain;
|
hostname = "mx1." + domain;
|
||||||
|
@ -91,9 +101,7 @@ in {
|
||||||
ensureCredentials = {
|
ensureCredentials = {
|
||||||
"patrick@${domain}".passwordFile = config.age.secrets.patrickPasswd.path;
|
"patrick@${domain}".passwordFile = config.age.secrets.patrickPasswd.path;
|
||||||
};
|
};
|
||||||
ensureAccounts = [
|
ensureAccounts = [ "patrick@${domain}" ];
|
||||||
"patrick@${domain}"
|
|
||||||
];
|
|
||||||
openFirewall = true;
|
openFirewall = true;
|
||||||
config = ''
|
config = ''
|
||||||
## Maddy Mail Server - default configuration file (2022-06-18)
|
## Maddy Mail Server - default configuration file (2022-06-18)
|
||||||
|
@ -288,9 +296,7 @@ in {
|
||||||
useACMEWildcardHost = true;
|
useACMEWildcardHost = true;
|
||||||
locations."=/mail/config-v1.1.xml".alias =
|
locations."=/mail/config-v1.1.xml".alias =
|
||||||
pkgs.writeText "autoconfig.${domain}.xml"
|
pkgs.writeText "autoconfig.${domain}.xml"
|
||||||
/*
|
# xml
|
||||||
xml
|
|
||||||
*/
|
|
||||||
''
|
''
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<clientConfig version="1.1">
|
<clientConfig version="1.1">
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
{config, ...}: {
|
{ config, ... }:
|
||||||
|
{
|
||||||
networking.firewall.allowedUDPPorts = [ config.services.teamspeak3.defaultVoicePort ];
|
networking.firewall.allowedUDPPorts = [ config.services.teamspeak3.defaultVoicePort ];
|
||||||
services.teamspeak3 = {
|
services.teamspeak3 = {
|
||||||
enable = true;
|
enable = true;
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
|
{ config, lib, ... }:
|
||||||
{
|
{
|
||||||
config,
|
|
||||||
lib,
|
|
||||||
...
|
|
||||||
}: {
|
|
||||||
wireguard.elisabeth = {
|
wireguard.elisabeth = {
|
||||||
client.via = "elisabeth";
|
client.via = "elisabeth";
|
||||||
firewallRuleForNode.elisabeth.allowedTCPPorts = [80 3000 3001];
|
firewallRuleForNode.elisabeth.allowedTCPPorts = [
|
||||||
|
80
|
||||||
|
3000
|
||||||
|
3001
|
||||||
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
age.secrets.coturnPassword = {
|
age.secrets.coturnPassword = {
|
||||||
|
@ -19,13 +20,19 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
age.secrets.dataEnc = {
|
age.secrets.dataEnc = {
|
||||||
generator.script = {pkgs, ...}: ''
|
generator.script =
|
||||||
|
{ pkgs, ... }:
|
||||||
|
''
|
||||||
${lib.getExe pkgs.openssl} rand -base64 32
|
${lib.getExe pkgs.openssl} rand -base64 32
|
||||||
'';
|
'';
|
||||||
group = "netbird";
|
group = "netbird";
|
||||||
};
|
};
|
||||||
|
|
||||||
networking.firewall.allowedTCPPorts = [80 3000 3001];
|
networking.firewall.allowedTCPPorts = [
|
||||||
|
80
|
||||||
|
3000
|
||||||
|
3001
|
||||||
|
];
|
||||||
networking.firewall.allowedUDPPorts = [ 3478 ];
|
networking.firewall.allowedUDPPorts = [ 3478 ];
|
||||||
services.netbird = {
|
services.netbird = {
|
||||||
server = {
|
server = {
|
||||||
|
|
|
@ -4,9 +4,11 @@
|
||||||
config,
|
config,
|
||||||
nodes,
|
nodes,
|
||||||
...
|
...
|
||||||
}: let
|
}:
|
||||||
|
let
|
||||||
hostName = "nc.${config.secrets.secrets.global.domains.web}";
|
hostName = "nc.${config.secrets.secrets.global.domains.web}";
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
age.secrets.maddyPasswd = {
|
age.secrets.maddyPasswd = {
|
||||||
generator.script = "alnum";
|
generator.script = "alnum";
|
||||||
mode = "440";
|
mode = "440";
|
||||||
|
@ -20,7 +22,8 @@ in {
|
||||||
mode = "640";
|
mode = "640";
|
||||||
};
|
};
|
||||||
services.maddy.ensureCredentials = {
|
services.maddy.ensureCredentials = {
|
||||||
"nextcloud@${config.secrets.secrets.global.domains.mail_public}".passwordFile = nodes.maddy.config.age.secrets.nextcloudPasswd.path;
|
"nextcloud@${config.secrets.secrets.global.domains.mail_public}".passwordFile =
|
||||||
|
nodes.maddy.config.age.secrets.nextcloudPasswd.path;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
environment.persistence."/persist".directories = [
|
environment.persistence."/persist".directories = [
|
||||||
|
@ -54,7 +57,15 @@ in {
|
||||||
config.adminpassFile = config.age.secrets.ncpasswd.path; # Kinda ok just remember to instanly change after first setup
|
config.adminpassFile = config.age.secrets.ncpasswd.path; # Kinda ok just remember to instanly change after first setup
|
||||||
config.adminuser = "admin";
|
config.adminuser = "admin";
|
||||||
extraApps = with config.services.nextcloud.package.packages.apps; {
|
extraApps = with config.services.nextcloud.package.packages.apps; {
|
||||||
inherit contacts calendar tasks notes maps phonetrack user_oidc;
|
inherit
|
||||||
|
contacts
|
||||||
|
calendar
|
||||||
|
tasks
|
||||||
|
notes
|
||||||
|
maps
|
||||||
|
phonetrack
|
||||||
|
user_oidc
|
||||||
|
;
|
||||||
};
|
};
|
||||||
maxUploadSize = "4G";
|
maxUploadSize = "4G";
|
||||||
extraAppsEnable = true;
|
extraAppsEnable = true;
|
||||||
|
@ -93,14 +104,16 @@ in {
|
||||||
dbtype = "pgsql";
|
dbtype = "pgsql";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
systemd.tmpfiles.rules = let
|
systemd.tmpfiles.rules =
|
||||||
|
let
|
||||||
mailer-passwd-conf = pkgs.writeText "nextcloud-config.php" ''
|
mailer-passwd-conf = pkgs.writeText "nextcloud-config.php" ''
|
||||||
<?php
|
<?php
|
||||||
$CONFIG = [
|
$CONFIG = [
|
||||||
'mail_smtppassword' => trim(file_get_contents('${config.age.secrets.maddyPasswd.path}')),
|
'mail_smtppassword' => trim(file_get_contents('${config.age.secrets.maddyPasswd.path}')),
|
||||||
];
|
];
|
||||||
'';
|
'';
|
||||||
in [
|
in
|
||||||
|
[
|
||||||
"L+ ${config.services.nextcloud.datadir}/config/mailer.config.php - - - - ${mailer-passwd-conf}"
|
"L+ ${config.services.nextcloud.datadir}/config/mailer.config.php - - - - ${mailer-passwd-conf}"
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,5 @@
|
||||||
|
{ config, nodes, ... }:
|
||||||
{
|
{
|
||||||
config,
|
|
||||||
nodes,
|
|
||||||
...
|
|
||||||
}: {
|
|
||||||
wireguard.elisabeth = {
|
wireguard.elisabeth = {
|
||||||
client.via = "elisabeth";
|
client.via = "elisabeth";
|
||||||
firewallRuleForNode.elisabeth.allowedTCPPorts = [ 3000 ];
|
firewallRuleForNode.elisabeth.allowedTCPPorts = [ 3000 ];
|
||||||
|
@ -72,15 +69,15 @@
|
||||||
# it includes the newline terminating the file which
|
# it includes the newline terminating the file which
|
||||||
# makes kanidm reject the secret
|
# makes kanidm reject the secret
|
||||||
age.secrets.oauth2-client-secret-env = {
|
age.secrets.oauth2-client-secret-env = {
|
||||||
generator.dependencies = [
|
generator.dependencies = [ nodes.elisabeth-kanidm.config.age.secrets.oauth2-proxy ];
|
||||||
nodes.elisabeth-kanidm.config.age.secrets.oauth2-proxy
|
generator.script =
|
||||||
];
|
{
|
||||||
generator.script = {
|
|
||||||
lib,
|
lib,
|
||||||
decrypt,
|
decrypt,
|
||||||
deps,
|
deps,
|
||||||
...
|
...
|
||||||
}: ''
|
}:
|
||||||
|
''
|
||||||
echo -n "OAUTH2_PROXY_CLIENT_SECRET="
|
echo -n "OAUTH2_PROXY_CLIENT_SECRET="
|
||||||
${decrypt} ${lib.escapeShellArg (lib.head deps).file}
|
${decrypt} ${lib.escapeShellArg (lib.head deps).file}
|
||||||
'';
|
'';
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
{config, ...}: {
|
{ config, ... }:
|
||||||
|
{
|
||||||
wireguard.elisabeth = {
|
wireguard.elisabeth = {
|
||||||
client.via = "elisabeth";
|
client.via = "elisabeth";
|
||||||
firewallRuleForNode.elisabeth.allowedTCPPorts = [ config.services.octoprint.port ];
|
firewallRuleForNode.elisabeth.allowedTCPPorts = [ config.services.octoprint.port ];
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
{config, ...}: {
|
{ config, ... }:
|
||||||
|
{
|
||||||
wireguard.elisabeth = {
|
wireguard.elisabeth = {
|
||||||
client.via = "elisabeth";
|
client.via = "elisabeth";
|
||||||
firewallRuleForNode.elisabeth.allowedTCPPorts = [ config.services.open-webui.port ];
|
firewallRuleForNode.elisabeth.allowedTCPPorts = [ config.services.open-webui.port ];
|
||||||
|
|
|
@ -4,10 +4,12 @@
|
||||||
config,
|
config,
|
||||||
lib,
|
lib,
|
||||||
...
|
...
|
||||||
}: let
|
}:
|
||||||
|
let
|
||||||
paperlessdomain = "ppl.${config.secrets.secrets.global.domains.web}";
|
paperlessdomain = "ppl.${config.secrets.secrets.global.domains.web}";
|
||||||
paperlessBackupDir = "/var/cache/backups/paperless";
|
paperlessBackupDir = "/var/cache/backups/paperless";
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
systemd.tmpfiles.settings = {
|
systemd.tmpfiles.settings = {
|
||||||
"10-paperless".${paperlessBackupDir}.d = {
|
"10-paperless".${paperlessBackupDir}.d = {
|
||||||
inherit (config.services.paperless) user;
|
inherit (config.services.paperless) user;
|
||||||
|
@ -45,14 +47,13 @@ in {
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
systemd.services.paperless-backup = let
|
systemd.services.paperless-backup =
|
||||||
|
let
|
||||||
cfg = config.systemd.services.paperless-consumer;
|
cfg = config.systemd.services.paperless-consumer;
|
||||||
in {
|
in
|
||||||
description = "Paperless document backup";
|
|
||||||
serviceConfig =
|
|
||||||
lib.recursiveUpdate
|
|
||||||
cfg.serviceConfig
|
|
||||||
{
|
{
|
||||||
|
description = "Paperless document backup";
|
||||||
|
serviceConfig = lib.recursiveUpdate cfg.serviceConfig {
|
||||||
ExecStart = "${config.services.paperless.package}/bin/paperless-ngx document_exporter -na -nt -f -d ${paperlessBackupDir}";
|
ExecStart = "${config.services.paperless.package}/bin/paperless-ngx document_exporter -na -nt -f -d ${paperlessBackupDir}";
|
||||||
ReadWritePaths = cfg.serviceConfig.ReadWritePaths ++ [ paperlessBackupDir ];
|
ReadWritePaths = cfg.serviceConfig.ReadWritePaths ++ [ paperlessBackupDir ];
|
||||||
Restart = "no";
|
Restart = "no";
|
||||||
|
|
|
@ -4,13 +4,15 @@
|
||||||
lib,
|
lib,
|
||||||
pkgs,
|
pkgs,
|
||||||
...
|
...
|
||||||
}: let
|
}:
|
||||||
|
let
|
||||||
prestart = pkgs.writeShellScript "pr-tracker-pre" ''
|
prestart = pkgs.writeShellScript "pr-tracker-pre" ''
|
||||||
if [ ! -d ./nixpkgs ]; then
|
if [ ! -d ./nixpkgs ]; then
|
||||||
${lib.getExe pkgs.git} clone https://github.com/NixOS/nixpkgs.git
|
${lib.getExe pkgs.git} clone https://github.com/NixOS/nixpkgs.git
|
||||||
fi
|
fi
|
||||||
'';
|
'';
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
wireguard.elisabeth = {
|
wireguard.elisabeth = {
|
||||||
client.via = "elisabeth";
|
client.via = "elisabeth";
|
||||||
firewallRuleForNode.elisabeth.allowedTCPPorts = [ 3000 ];
|
firewallRuleForNode.elisabeth.allowedTCPPorts = [ 3000 ];
|
||||||
|
@ -43,7 +45,8 @@ in {
|
||||||
mode = "640";
|
mode = "640";
|
||||||
};
|
};
|
||||||
services.maddy.ensureCredentials = {
|
services.maddy.ensureCredentials = {
|
||||||
"pr-tracker@${config.secrets.secrets.global.domains.mail_public}".passwordFile = nodes.maddy.config.age.secrets.pr-trackerPasswd.path;
|
"pr-tracker@${config.secrets.secrets.global.domains.mail_public}".passwordFile =
|
||||||
|
nodes.maddy.config.age.secrets.pr-trackerPasswd.path;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
systemd.sockets.pr-tracker = {
|
systemd.sockets.pr-tracker = {
|
||||||
|
|
|
@ -4,10 +4,16 @@
|
||||||
config,
|
config,
|
||||||
pkgs, # not unused needed for the usage of attrs later to contains pkgs
|
pkgs, # not unused needed for the usage of attrs later to contains pkgs
|
||||||
...
|
...
|
||||||
} @ attrs: let
|
}@attrs:
|
||||||
|
let
|
||||||
hostName = "radicale.${config.secrets.secrets.global.domains.mail}";
|
hostName = "radicale.${config.secrets.secrets.global.domains.mail}";
|
||||||
in {
|
in
|
||||||
imports = [./containers.nix ./ddclient.nix ./acme.nix];
|
{
|
||||||
|
imports = [
|
||||||
|
./containers.nix
|
||||||
|
./ddclient.nix
|
||||||
|
./acme.nix
|
||||||
|
];
|
||||||
services.nginx = {
|
services.nginx = {
|
||||||
enable = true;
|
enable = true;
|
||||||
upstreams.radicale = {
|
upstreams.radicale = {
|
||||||
|
@ -54,7 +60,10 @@ in {
|
||||||
enable = true;
|
enable = true;
|
||||||
setting = {
|
setting = {
|
||||||
server = {
|
server = {
|
||||||
hosts = ["0.0.0.0:8000" "[::]:8000"];
|
hosts = [
|
||||||
|
"0.0.0.0:8000"
|
||||||
|
"[::]:8000"
|
||||||
|
];
|
||||||
auth = {
|
auth = {
|
||||||
type = "htpasswd";
|
type = "htpasswd";
|
||||||
htpasswd_filename = "/etc/radicale/users";
|
htpasswd_filename = "/etc/radicale/users";
|
||||||
|
@ -106,4 +115,3 @@ in {
|
||||||
#kanidm
|
#kanidm
|
||||||
#remote backups
|
#remote backups
|
||||||
#immich
|
#immich
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,5 @@
|
||||||
|
{ config, lib, ... }:
|
||||||
{
|
{
|
||||||
config,
|
|
||||||
lib,
|
|
||||||
...
|
|
||||||
}: {
|
|
||||||
services.samba-wsdd = {
|
services.samba-wsdd = {
|
||||||
enable = true; # make shares visible for windows 10 clients
|
enable = true; # make shares visible for windows 10 clients
|
||||||
openFirewall = true;
|
openFirewall = true;
|
||||||
|
@ -55,11 +52,17 @@
|
||||||
wireguard.samba-patrick.server = {
|
wireguard.samba-patrick.server = {
|
||||||
host = config.secrets.secrets.global.domains.web;
|
host = config.secrets.secrets.global.domains.web;
|
||||||
port = 51830;
|
port = 51830;
|
||||||
reservedAddresses = ["10.43.0.0/20" "fd00:1765::/112"];
|
reservedAddresses = [
|
||||||
|
"10.43.0.0/20"
|
||||||
|
"fd00:1765::/112"
|
||||||
|
];
|
||||||
openFirewall = true;
|
openFirewall = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
networking.nftables.firewall.zones.untrusted.interfaces = ["samba-patrick" "netbird-samba"];
|
networking.nftables.firewall.zones.untrusted.interfaces = [
|
||||||
|
"samba-patrick"
|
||||||
|
"netbird-samba"
|
||||||
|
];
|
||||||
|
|
||||||
services.samba = {
|
services.samba = {
|
||||||
enable = true;
|
enable = true;
|
||||||
|
@ -106,17 +109,20 @@
|
||||||
"disable spoolss = yes"
|
"disable spoolss = yes"
|
||||||
"show add printer wizard = no"
|
"show add printer wizard = no"
|
||||||
];
|
];
|
||||||
shares = let
|
shares =
|
||||||
mkShare = {
|
let
|
||||||
|
mkShare =
|
||||||
|
{
|
||||||
name,
|
name,
|
||||||
user ? "smb",
|
user ? "smb",
|
||||||
group ? "smb",
|
group ? "smb",
|
||||||
hasBunker ? false,
|
hasBunker ? false,
|
||||||
hasPaperless ? false,
|
hasPaperless ? false,
|
||||||
persistRoot ? "/panzer",
|
persistRoot ? "/panzer",
|
||||||
}: cfg: let
|
}:
|
||||||
config =
|
cfg:
|
||||||
{
|
let
|
||||||
|
config = {
|
||||||
"#persistRoot" = persistRoot;
|
"#persistRoot" = persistRoot;
|
||||||
"#user" = user;
|
"#user" = user;
|
||||||
"#group" = group;
|
"#group" = group;
|
||||||
|
@ -131,28 +137,21 @@
|
||||||
"force directory mode" = "0770";
|
"force directory mode" = "0770";
|
||||||
# Might be necessary for windows user to be able to open thing in smb
|
# Might be necessary for windows user to be able to open thing in smb
|
||||||
"acl allow execute always" = "no";
|
"acl allow execute always" = "no";
|
||||||
}
|
} // cfg;
|
||||||
// cfg;
|
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
"${name}" =
|
"${name}" = config // {
|
||||||
config
|
"path" = "/media/smb/${name}";
|
||||||
// {"path" = "/media/smb/${name}";};
|
};
|
||||||
}
|
}
|
||||||
// lib.optionalAttrs hasBunker
|
// lib.optionalAttrs hasBunker {
|
||||||
{
|
"${name}-important" = config // {
|
||||||
"${name}-important" =
|
|
||||||
config
|
|
||||||
// {
|
|
||||||
"path" = "/media/smb/${name}-important";
|
"path" = "/media/smb/${name}-important";
|
||||||
"#persistRoot" = "/bunker";
|
"#persistRoot" = "/bunker";
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
// lib.optionalAttrs hasPaperless
|
// lib.optionalAttrs hasPaperless {
|
||||||
{
|
"${name}-paperless" = config // {
|
||||||
"${name}-paperless" =
|
|
||||||
config
|
|
||||||
// {
|
|
||||||
"path" = "/media/smb/${name}-paperless";
|
"path" = "/media/smb/${name}-paperless";
|
||||||
"#paperless" = true;
|
"#paperless" = true;
|
||||||
"force user" = "paperless";
|
"force user" = "paperless";
|
||||||
|
@ -199,7 +198,8 @@
|
||||||
user = "family";
|
user = "family";
|
||||||
group = "family";
|
group = "family";
|
||||||
} { })
|
} { })
|
||||||
(mkShare {
|
(mkShare
|
||||||
|
{
|
||||||
name = "media";
|
name = "media";
|
||||||
user = "family";
|
user = "family";
|
||||||
group = "family";
|
group = "family";
|
||||||
|
@ -208,7 +208,8 @@
|
||||||
{
|
{
|
||||||
"read only" = "yes";
|
"read only" = "yes";
|
||||||
"write list" = "@family";
|
"write list" = "@family";
|
||||||
})
|
}
|
||||||
|
)
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
# to get this file start a smbd, add users using 'smbpasswd -a <user>'
|
# to get this file start a smbd, add users using 'smbpasswd -a <user>'
|
||||||
|
@ -216,11 +217,16 @@
|
||||||
age.secrets.smbpassdb = {
|
age.secrets.smbpassdb = {
|
||||||
rekeyFile = config.node.secretsDir + "/smbpassdb.tdb.age";
|
rekeyFile = config.node.secretsDir + "/smbpassdb.tdb.age";
|
||||||
};
|
};
|
||||||
users = let
|
users =
|
||||||
|
let
|
||||||
users = lib.unique (lib.mapAttrsToList (_: val: val."force user") config.services.samba.shares);
|
users = lib.unique (lib.mapAttrsToList (_: val: val."force user") config.services.samba.shares);
|
||||||
groups = lib.unique (users ++ (lib.mapAttrsToList (_: val: val."force group") config.services.samba.shares));
|
groups = lib.unique (
|
||||||
in {
|
users ++ (lib.mapAttrsToList (_: val: val."force group") config.services.samba.shares)
|
||||||
users = lib.mkMerge ((lib.flip map users (user: {
|
);
|
||||||
|
in
|
||||||
|
{
|
||||||
|
users = lib.mkMerge (
|
||||||
|
(lib.flip map users (user: {
|
||||||
${user} = {
|
${user} = {
|
||||||
isNormalUser = true;
|
isNormalUser = true;
|
||||||
home = "/var/empty";
|
home = "/var/empty";
|
||||||
|
@ -230,22 +236,34 @@
|
||||||
group = "${user}";
|
group = "${user}";
|
||||||
};
|
};
|
||||||
}))
|
}))
|
||||||
++ [
|
++ [ { paperless.isNormalUser = lib.mkForce false; } ]
|
||||||
{paperless.isNormalUser = lib.mkForce false;}
|
);
|
||||||
]);
|
groups = lib.mkMerge (
|
||||||
groups = lib.mkMerge ((lib.flip map groups (group: {
|
(lib.flip map groups (group: {
|
||||||
${group} = {
|
${group} = { };
|
||||||
};
|
|
||||||
}))
|
}))
|
||||||
++ [
|
++ [
|
||||||
{
|
{
|
||||||
family.members = ["patrick" "david" "helen" "ggr"];
|
family.members = [
|
||||||
printer.members = ["patrick" "david" "helen" "ggr"];
|
"patrick"
|
||||||
|
"david"
|
||||||
|
"helen"
|
||||||
|
"ggr"
|
||||||
|
];
|
||||||
|
printer.members = [
|
||||||
|
"patrick"
|
||||||
|
"david"
|
||||||
|
"helen"
|
||||||
|
"ggr"
|
||||||
|
];
|
||||||
}
|
}
|
||||||
]);
|
]
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
fileSystems = lib.mkMerge (lib.flip lib.mapAttrsToList config.services.samba.shares (_: v:
|
fileSystems = lib.mkMerge (
|
||||||
|
lib.flip lib.mapAttrsToList config.services.samba.shares (
|
||||||
|
_: v:
|
||||||
lib.optionalAttrs ((v ? "#paperless") && v."#paperless") {
|
lib.optionalAttrs ((v ? "#paperless") && v."#paperless") {
|
||||||
"${v.path}/consume" = {
|
"${v.path}/consume" = {
|
||||||
fsType = "none";
|
fsType = "none";
|
||||||
|
@ -254,17 +272,27 @@
|
||||||
};
|
};
|
||||||
"${v.path}/media/archive" = {
|
"${v.path}/media/archive" = {
|
||||||
fsType = "none ";
|
fsType = "none ";
|
||||||
options = ["bind" "ro"];
|
options = [
|
||||||
|
"bind"
|
||||||
|
"ro"
|
||||||
|
];
|
||||||
device = "/paperless/media/documents/archive/${v."#user"}";
|
device = "/paperless/media/documents/archive/${v."#user"}";
|
||||||
};
|
};
|
||||||
"${v.path}/media/originals" = {
|
"${v.path}/media/originals" = {
|
||||||
fsType = "none ";
|
fsType = "none ";
|
||||||
options = ["bind" "ro"];
|
options = [
|
||||||
|
"bind"
|
||||||
|
"ro"
|
||||||
|
];
|
||||||
device = "/paperless/media/documents/originals/${v."#user"}";
|
device = "/paperless/media/documents/originals/${v."#user"}";
|
||||||
};
|
};
|
||||||
}));
|
}
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
systemd.tmpfiles.settings = lib.mkMerge (lib.flip lib.mapAttrsToList config.services.samba.shares (_: v:
|
systemd.tmpfiles.settings = lib.mkMerge (
|
||||||
|
lib.flip lib.mapAttrsToList config.services.samba.shares (
|
||||||
|
_: v:
|
||||||
lib.optionalAttrs ((v ? "#paperless") && v."#paperless") {
|
lib.optionalAttrs ((v ? "#paperless") && v."#paperless") {
|
||||||
"10-smb-paperless"."/paperless/consume/".d = {
|
"10-smb-paperless"."/paperless/consume/".d = {
|
||||||
user = "paperless";
|
user = "paperless";
|
||||||
|
@ -317,9 +345,13 @@
|
||||||
group = "paperless";
|
group = "paperless";
|
||||||
mode = "0660";
|
mode = "0660";
|
||||||
};
|
};
|
||||||
}));
|
}
|
||||||
environment.persistence = lib.mkMerge (lib.flatten [
|
)
|
||||||
(lib.flip lib.mapAttrsToList config.services.samba.shares (_: v:
|
);
|
||||||
|
environment.persistence = lib.mkMerge (
|
||||||
|
lib.flatten [
|
||||||
|
(lib.flip lib.mapAttrsToList config.services.samba.shares (
|
||||||
|
_: v:
|
||||||
lib.optionalAttrs ((v ? "#persistRoot") && (v."#persistRoot" != "")) {
|
lib.optionalAttrs ((v ? "#persistRoot") && (v."#persistRoot" != "")) {
|
||||||
${v."#persistRoot"}.directories = [
|
${v."#persistRoot"}.directories = [
|
||||||
{
|
{
|
||||||
|
@ -329,7 +361,8 @@
|
||||||
mode = "0770";
|
mode = "0770";
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
}))
|
}
|
||||||
|
))
|
||||||
(lib.flip lib.mapAttrsToList config.services.netbird.tunnels (
|
(lib.flip lib.mapAttrsToList config.services.netbird.tunnels (
|
||||||
_: v: {
|
_: v: {
|
||||||
"/state".directories = [
|
"/state".directories = [
|
||||||
|
@ -340,5 +373,6 @@
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
))
|
))
|
||||||
]);
|
]
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
{config, ...}: {
|
{ config, ... }:
|
||||||
|
{
|
||||||
wireguard.elisabeth = {
|
wireguard.elisabeth = {
|
||||||
client.via = "elisabeth";
|
client.via = "elisabeth";
|
||||||
firewallRuleForNode.elisabeth.allowedTCPPorts = [ 80 ];
|
firewallRuleForNode.elisabeth.allowedTCPPorts = [ 80 ];
|
||||||
|
|
|
@ -3,9 +3,11 @@
|
||||||
lib,
|
lib,
|
||||||
nodes,
|
nodes,
|
||||||
...
|
...
|
||||||
}: let
|
}:
|
||||||
|
let
|
||||||
vaultwardenDomain = "pw.${config.secrets.secrets.global.domains.web}";
|
vaultwardenDomain = "pw.${config.secrets.secrets.global.domains.web}";
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
age.secrets.vaultwarden-env = {
|
age.secrets.vaultwarden-env = {
|
||||||
rekeyFile = config.node.secretsDir + "/vaultwarden-env.age";
|
rekeyFile = config.node.secretsDir + "/vaultwarden-env.age";
|
||||||
mode = "440";
|
mode = "440";
|
||||||
|
@ -64,7 +66,8 @@ in {
|
||||||
mode = "640";
|
mode = "640";
|
||||||
};
|
};
|
||||||
services.maddy.ensureCredentials = {
|
services.maddy.ensureCredentials = {
|
||||||
"vaultwarden@${config.secrets.secrets.global.domains.mail_public}".passwordFile = nodes.maddy.config.age.secrets.vaultwardenPasswd.path;
|
"vaultwarden@${config.secrets.secrets.global.domains.mail_public}".passwordFile =
|
||||||
|
nodes.maddy.config.age.secrets.vaultwardenPasswd.path;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
system.activationScripts.systemd_env_smtp_passwd = {
|
system.activationScripts.systemd_env_smtp_passwd = {
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
|
{ config, pkgs, ... }:
|
||||||
{
|
{
|
||||||
config,
|
|
||||||
pkgs,
|
|
||||||
...
|
|
||||||
}: {
|
|
||||||
wireguard.elisabeth = {
|
wireguard.elisabeth = {
|
||||||
client.via = "elisabeth";
|
client.via = "elisabeth";
|
||||||
firewallRuleForNode.elisabeth.allowedTCPPorts = [3000 80];
|
firewallRuleForNode.elisabeth.allowedTCPPorts = [
|
||||||
|
3000
|
||||||
|
80
|
||||||
|
];
|
||||||
};
|
};
|
||||||
age.secrets.spotifySecret = {
|
age.secrets.spotifySecret = {
|
||||||
owner = "root";
|
owner = "root";
|
||||||
|
|
24
flake.nix
24
flake.nix
|
@ -101,7 +101,8 @@
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
outputs = {
|
outputs =
|
||||||
|
{
|
||||||
self,
|
self,
|
||||||
nixpkgs,
|
nixpkgs,
|
||||||
flake-utils,
|
flake-utils,
|
||||||
|
@ -113,7 +114,8 @@
|
||||||
nixos-extra-modules,
|
nixos-extra-modules,
|
||||||
nix-topology,
|
nix-topology,
|
||||||
...
|
...
|
||||||
} @ inputs: let
|
}@inputs:
|
||||||
|
let
|
||||||
inherit (nixpkgs) lib;
|
inherit (nixpkgs) lib;
|
||||||
stateVersion = "23.05";
|
stateVersion = "23.05";
|
||||||
in
|
in
|
||||||
|
@ -129,8 +131,7 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
inherit stateVersion;
|
inherit stateVersion;
|
||||||
inherit
|
inherit (import ./nix/hosts.nix inputs)
|
||||||
(import ./nix/hosts.nix inputs)
|
|
||||||
hosts
|
hosts
|
||||||
nixosConfigurations
|
nixosConfigurations
|
||||||
minimalConfigurations
|
minimalConfigurations
|
||||||
|
@ -139,15 +140,16 @@
|
||||||
nodes = self.nixosConfigurations // self.guestConfigurations;
|
nodes = self.nixosConfigurations // self.guestConfigurations;
|
||||||
|
|
||||||
inherit
|
inherit
|
||||||
(lib.foldl' lib.recursiveUpdate {}
|
(lib.foldl' lib.recursiveUpdate { } (
|
||||||
(lib.mapAttrsToList
|
lib.mapAttrsToList (import ./nix/generate-installer-package.nix inputs) self.minimalConfigurations
|
||||||
(import ./nix/generate-installer-package.nix inputs)
|
))
|
||||||
self.minimalConfigurations))
|
|
||||||
packages
|
packages
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
// flake-utils.lib.eachDefaultSystem (system: rec {
|
// flake-utils.lib.eachDefaultSystem (system: rec {
|
||||||
apps.setupHetznerStorageBoxes = import (nixos-extra-modules + "/apps/setup-hetzner-storage-boxes.nix") {
|
apps.setupHetznerStorageBoxes =
|
||||||
|
import (nixos-extra-modules + "/apps/setup-hetzner-storage-boxes.nix")
|
||||||
|
{
|
||||||
inherit pkgs;
|
inherit pkgs;
|
||||||
nixosConfigurations = self.nodes;
|
nixosConfigurations = self.nodes;
|
||||||
decryptIdentity = builtins.head self.secretsConfig.masterIdentities;
|
decryptIdentity = builtins.head self.secretsConfig.masterIdentities;
|
||||||
|
@ -191,9 +193,7 @@
|
||||||
.${system};
|
.${system};
|
||||||
};
|
};
|
||||||
|
|
||||||
checks.pre-commit-check =
|
checks.pre-commit-check = pre-commit-hooks.lib.${system}.run {
|
||||||
pre-commit-hooks.lib.${system}.run
|
|
||||||
{
|
|
||||||
src = lib.cleanSource ./.;
|
src = lib.cleanSource ./.;
|
||||||
hooks = {
|
hooks = {
|
||||||
nixfmt = {
|
nixfmt = {
|
||||||
|
|
|
@ -1,8 +1,5 @@
|
||||||
|
{ inputs, lib, ... }:
|
||||||
{
|
{
|
||||||
inputs,
|
|
||||||
lib,
|
|
||||||
...
|
|
||||||
}: {
|
|
||||||
imports = [
|
imports = [
|
||||||
inputs.nixos-hardware.nixosModules.common-gpu-nvidia-nonprime
|
inputs.nixos-hardware.nixosModules.common-gpu-nvidia-nonprime
|
||||||
inputs.nixos-hardware.nixosModules.common-cpu-intel-cpu-only
|
inputs.nixos-hardware.nixosModules.common-cpu-intel-cpu-only
|
||||||
|
@ -51,9 +48,23 @@
|
||||||
device = "/dev/input/event15";
|
device = "/dev/input/event15";
|
||||||
};
|
};
|
||||||
|
|
||||||
boot.binfmt.emulatedSystems = ["aarch64-linux" "riscv64-linux"];
|
boot.binfmt.emulatedSystems = [
|
||||||
nix.settings.system-features = ["kvm" "nixos-test"];
|
"aarch64-linux"
|
||||||
boot.kernelParams = lib.mkForce ["rd.luks.options=timeout=0" "rootflags=x-systemd.device-timeout=0" "nohibernate" "root=fstab" "loglevel=4" "nvidia-drm.modeset=1" "nvidia.NVreg_PreserveVideoMemoryAllocations=1"];
|
"riscv64-linux"
|
||||||
|
];
|
||||||
|
nix.settings.system-features = [
|
||||||
|
"kvm"
|
||||||
|
"nixos-test"
|
||||||
|
];
|
||||||
|
boot.kernelParams = lib.mkForce [
|
||||||
|
"rd.luks.options=timeout=0"
|
||||||
|
"rootflags=x-systemd.device-timeout=0"
|
||||||
|
"nohibernate"
|
||||||
|
"root=fstab"
|
||||||
|
"loglevel=4"
|
||||||
|
"nvidia-drm.modeset=1"
|
||||||
|
"nvidia.NVreg_PreserveVideoMemoryAllocations=1"
|
||||||
|
];
|
||||||
|
|
||||||
services.netbird.enable = true;
|
services.netbird.enable = true;
|
||||||
# Do not cleanup nix store to prevent having to rebuild packages onca a month
|
# Do not cleanup nix store to prevent having to rebuild packages onca a month
|
||||||
|
|
|
@ -3,7 +3,8 @@
|
||||||
nodes,
|
nodes,
|
||||||
lib,
|
lib,
|
||||||
...
|
...
|
||||||
}: {
|
}:
|
||||||
|
{
|
||||||
disko.devices = {
|
disko.devices = {
|
||||||
disk = {
|
disk = {
|
||||||
m2-ssd = rec {
|
m2-ssd = rec {
|
||||||
|
@ -12,9 +13,15 @@
|
||||||
content = with lib.disko.gpt; {
|
content = with lib.disko.gpt; {
|
||||||
type = "gpt";
|
type = "gpt";
|
||||||
partitions = {
|
partitions = {
|
||||||
boot = (partEfi "2GiB") // {device = "${device}-part1";};
|
boot = (partEfi "2GiB") // {
|
||||||
swap = (partSwap "16G") // {device = "${device}-part2";};
|
device = "${device}-part1";
|
||||||
rpool = (partLuksZfs "m2-ssd" "rpool" "100%") // {device = "${device}-part3";};
|
};
|
||||||
|
swap = (partSwap "16G") // {
|
||||||
|
device = "${device}-part2";
|
||||||
|
};
|
||||||
|
rpool = (partLuksZfs "m2-ssd" "rpool" "100%") // {
|
||||||
|
device = "${device}-part3";
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -24,7 +31,9 @@
|
||||||
content = with lib.disko.gpt; {
|
content = with lib.disko.gpt; {
|
||||||
type = "gpt";
|
type = "gpt";
|
||||||
partitions = {
|
partitions = {
|
||||||
panzer = (partLuksZfs "sata-hdd" "panzer" "100%") // {device = "${device}-part1";};
|
panzer = (partLuksZfs "sata-hdd" "panzer" "100%") // {
|
||||||
|
device = "${device}-part1";
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
{config, ...}: {
|
{ config, ... }:
|
||||||
|
{
|
||||||
networking = {
|
networking = {
|
||||||
inherit (config.secrets.secrets.local.networking) hostId;
|
inherit (config.secrets.secrets.local.networking) hostId;
|
||||||
};
|
};
|
||||||
|
|
|
@ -3,9 +3,9 @@
|
||||||
minimal,
|
minimal,
|
||||||
lib,
|
lib,
|
||||||
...
|
...
|
||||||
}: {
|
}:
|
||||||
imports =
|
{
|
||||||
[
|
imports = [
|
||||||
inputs.nixos-hardware.nixosModules.common-pc
|
inputs.nixos-hardware.nixosModules.common-pc
|
||||||
inputs.nixos-hardware.nixosModules.common-pc-ssd
|
inputs.nixos-hardware.nixosModules.common-pc-ssd
|
||||||
inputs.nixos-hardware.nixosModules.common-cpu-amd
|
inputs.nixos-hardware.nixosModules.common-cpu-amd
|
||||||
|
@ -22,10 +22,7 @@
|
||||||
./blog.nix
|
./blog.nix
|
||||||
./net.nix
|
./net.nix
|
||||||
./fs.nix
|
./fs.nix
|
||||||
]
|
] ++ lib.lists.optionals (!minimal) [ ./guests.nix ];
|
||||||
++ lib.lists.optionals (!minimal) [
|
|
||||||
./guests.nix
|
|
||||||
];
|
|
||||||
services.xserver = {
|
services.xserver = {
|
||||||
xkb = {
|
xkb = {
|
||||||
layout = "de";
|
layout = "de";
|
||||||
|
|
|
@ -1,8 +1,5 @@
|
||||||
|
{ config, lib, ... }:
|
||||||
{
|
{
|
||||||
config,
|
|
||||||
lib,
|
|
||||||
...
|
|
||||||
}: {
|
|
||||||
disko.devices = {
|
disko.devices = {
|
||||||
disk = {
|
disk = {
|
||||||
internal-ssd = rec {
|
internal-ssd = rec {
|
||||||
|
@ -11,8 +8,12 @@
|
||||||
content = with lib.disko.gpt; {
|
content = with lib.disko.gpt; {
|
||||||
type = "gpt";
|
type = "gpt";
|
||||||
partitions = {
|
partitions = {
|
||||||
boot = (partEfi "1GiB") // {device = "${device}-part1";};
|
boot = (partEfi "1GiB") // {
|
||||||
rpool = (partLuksZfs "ssd" "rpool" "100%") // {device = "${device}-part2";};
|
device = "${device}-part1";
|
||||||
|
};
|
||||||
|
rpool = (partLuksZfs "ssd" "rpool" "100%") // {
|
||||||
|
device = "${device}-part2";
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -128,7 +129,10 @@
|
||||||
wireguard.scrtiny-patrick.server = {
|
wireguard.scrtiny-patrick.server = {
|
||||||
host = config.secrets.secrets.global.domains.web;
|
host = config.secrets.secrets.global.domains.web;
|
||||||
port = 51831;
|
port = 51831;
|
||||||
reservedAddresses = ["10.44.0.0/16" "fd00:1766::/112"];
|
reservedAddresses = [
|
||||||
|
"10.44.0.0/16"
|
||||||
|
"fd00:1766::/112"
|
||||||
|
];
|
||||||
openFirewall = true;
|
openFirewall = true;
|
||||||
};
|
};
|
||||||
networking.nftables.firewall.zones.untrusted.interfaces = [ "scrtiny-patrick" ];
|
networking.nftables.firewall.zones.untrusted.interfaces = [ "scrtiny-patrick" ];
|
||||||
|
|
|
@ -6,8 +6,11 @@
|
||||||
minimal,
|
minimal,
|
||||||
nodes,
|
nodes,
|
||||||
...
|
...
|
||||||
}: let
|
}:
|
||||||
domainOf = hostName: let
|
let
|
||||||
|
domainOf =
|
||||||
|
hostName:
|
||||||
|
let
|
||||||
domains = {
|
domains = {
|
||||||
adguardhome = "adguardhome";
|
adguardhome = "adguardhome";
|
||||||
forgejo = "forge";
|
forgejo = "forge";
|
||||||
|
@ -28,21 +31,29 @@
|
||||||
octoprint = "print";
|
octoprint = "print";
|
||||||
pr-tracker = "tracker";
|
pr-tracker = "tracker";
|
||||||
};
|
};
|
||||||
in "${domains.${hostName}}.${config.secrets.secrets.global.domains.web}";
|
in
|
||||||
|
"${domains.${hostName}}.${config.secrets.secrets.global.domains.web}";
|
||||||
# TODO hard coded elisabeth nicht so schön
|
# TODO hard coded elisabeth nicht so schön
|
||||||
ipOf = hostName:
|
ipOf =
|
||||||
if nodes ? ${hostName}
|
hostName:
|
||||||
then nodes.${hostName}.config.wireguard.elisabeth.ipv4
|
if nodes ? ${hostName} then
|
||||||
else nodes."elisabeth-${hostName}".config.wireguard.elisabeth.ipv4;
|
nodes.${hostName}.config.wireguard.elisabeth.ipv4
|
||||||
in {
|
else
|
||||||
services.nginx = let
|
nodes."elisabeth-${hostName}".config.wireguard.elisabeth.ipv4;
|
||||||
blockOf = hostName: {
|
in
|
||||||
|
{
|
||||||
|
services.nginx =
|
||||||
|
let
|
||||||
|
blockOf =
|
||||||
|
hostName:
|
||||||
|
{
|
||||||
virtualHostExtraConfig ? "",
|
virtualHostExtraConfig ? "",
|
||||||
maxBodySize ? "500M",
|
maxBodySize ? "500M",
|
||||||
port ? 3000,
|
port ? 3000,
|
||||||
upstream ? hostName,
|
upstream ? hostName,
|
||||||
protocol ? "http",
|
protocol ? "http",
|
||||||
}: {
|
}:
|
||||||
|
{
|
||||||
upstreams.${hostName} = {
|
upstreams.${hostName} = {
|
||||||
servers."${ipOf upstream}:${toString port}" = { };
|
servers."${ipOf upstream}:${toString port}" = { };
|
||||||
extraConfig = ''
|
extraConfig = ''
|
||||||
|
@ -65,7 +76,8 @@ in {
|
||||||
+ virtualHostExtraConfig;
|
+ virtualHostExtraConfig;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
proxyProtect = hostName: cfg: allowedGroup:
|
proxyProtect =
|
||||||
|
hostName: cfg: allowedGroup:
|
||||||
lib.mkMerge [
|
lib.mkMerge [
|
||||||
(blockOf hostName cfg)
|
(blockOf hostName cfg)
|
||||||
{
|
{
|
||||||
|
@ -95,7 +107,9 @@ in {
|
||||||
};
|
};
|
||||||
|
|
||||||
locations."= /oauth2/auth" = {
|
locations."= /oauth2/auth" = {
|
||||||
proxyPass = "http://oauth2-proxy/oauth2/auth" + lib.optionalString allowedGroup "?allowed_groups=${hostName}_access";
|
proxyPass =
|
||||||
|
"http://oauth2-proxy/oauth2/auth"
|
||||||
|
+ lib.optionalString allowedGroup "?allowed_groups=${hostName}_access";
|
||||||
extraConfig = ''
|
extraConfig = ''
|
||||||
internal;
|
internal;
|
||||||
|
|
||||||
|
@ -187,8 +201,7 @@ in {
|
||||||
maxBodySize = "5G";
|
maxBodySize = "5G";
|
||||||
port = 80;
|
port = 80;
|
||||||
})
|
})
|
||||||
(blockOf "kanidm"
|
(blockOf "kanidm" {
|
||||||
{
|
|
||||||
protocol = "https";
|
protocol = "https";
|
||||||
virtualHostExtraConfig = ''
|
virtualHostExtraConfig = ''
|
||||||
proxy_ssl_verify off ;
|
proxy_ssl_verify off ;
|
||||||
|
@ -196,14 +209,18 @@ in {
|
||||||
})
|
})
|
||||||
];
|
];
|
||||||
|
|
||||||
guests = let
|
guests =
|
||||||
mkGuest = guestName: {
|
let
|
||||||
|
mkGuest =
|
||||||
|
guestName:
|
||||||
|
{
|
||||||
enablePanzer ? false,
|
enablePanzer ? false,
|
||||||
enableRenaultFT ? false,
|
enableRenaultFT ? false,
|
||||||
enableBunker ? false,
|
enableBunker ? false,
|
||||||
enableSharedPaperless ? false,
|
enableSharedPaperless ? false,
|
||||||
...
|
...
|
||||||
}: {
|
}:
|
||||||
|
{
|
||||||
autostart = true;
|
autostart = true;
|
||||||
zfs."/state" = {
|
zfs."/state" = {
|
||||||
pool = "rpool";
|
pool = "rpool";
|
||||||
|
@ -235,12 +252,16 @@ in {
|
||||||
../../config/services/${guestName}.nix
|
../../config/services/${guestName}.nix
|
||||||
{
|
{
|
||||||
node.secretsDir = config.node.secretsDir + "/${guestName}";
|
node.secretsDir = config.node.secretsDir + "/${guestName}";
|
||||||
networking.nftables.firewall.zones.untrusted.interfaces = [config.guests.${guestName}.networking.mainLinkName];
|
networking.nftables.firewall.zones.untrusted.interfaces = [
|
||||||
|
config.guests.${guestName}.networking.mainLinkName
|
||||||
|
];
|
||||||
systemd.network.networks."10-${config.guests.${guestName}.networking.mainLinkName}" = {
|
systemd.network.networks."10-${config.guests.${guestName}.networking.mainLinkName}" = {
|
||||||
DHCP = lib.mkForce "no";
|
DHCP = lib.mkForce "no";
|
||||||
address = [
|
address = [
|
||||||
(lib.net.cidr.hostCidr config.secrets.secrets.global.net.ips."${config.guests.${guestName}.nodeName}" config.secrets.secrets.global.net.privateSubnetv4)
|
(lib.net.cidr.hostCidr config.secrets.secrets.global.net.ips."${config.guests.${guestName}.nodeName
|
||||||
(lib.net.cidr.hostCidr config.secrets.secrets.global.net.ips."${config.guests.${guestName}.nodeName}" config.secrets.secrets.global.net.privateSubnetv6)
|
}" config.secrets.secrets.global.net.privateSubnetv4)
|
||||||
|
(lib.net.cidr.hostCidr config.secrets.secrets.global.net.ips."${config.guests.${guestName}.nodeName
|
||||||
|
}" config.secrets.secrets.global.net.privateSubnetv6)
|
||||||
];
|
];
|
||||||
gateway = [ (lib.net.cidr.host 1 config.secrets.secrets.global.net.privateSubnetv4) ];
|
gateway = [ (lib.net.cidr.host 1 config.secrets.secrets.global.net.privateSubnetv4) ];
|
||||||
};
|
};
|
||||||
|
@ -249,9 +270,7 @@ in {
|
||||||
};
|
};
|
||||||
|
|
||||||
mkMicrovm = guestName: cfg: {
|
mkMicrovm = guestName: cfg: {
|
||||||
${guestName} =
|
${guestName} = mkGuest guestName cfg // {
|
||||||
mkGuest guestName cfg
|
|
||||||
// {
|
|
||||||
backend = "microvm";
|
backend = "microvm";
|
||||||
microvm = {
|
microvm = {
|
||||||
system = "x86_64-linux";
|
system = "x86_64-linux";
|
||||||
|
@ -267,13 +286,17 @@ in {
|
||||||
};
|
};
|
||||||
|
|
||||||
mkContainer = guestName: cfg: {
|
mkContainer = guestName: cfg: {
|
||||||
${guestName} =
|
${guestName} = mkGuest guestName cfg // {
|
||||||
mkGuest guestName cfg
|
|
||||||
// {
|
|
||||||
backend = "container";
|
backend = "container";
|
||||||
container.macvlan = "lan";
|
container.macvlan = "lan";
|
||||||
extraSpecialArgs = {
|
extraSpecialArgs = {
|
||||||
inherit lib nodes inputs minimal stateVersion;
|
inherit
|
||||||
|
lib
|
||||||
|
nodes
|
||||||
|
inputs
|
||||||
|
minimal
|
||||||
|
stateVersion
|
||||||
|
;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -292,18 +315,10 @@ in {
|
||||||
// mkContainer "yourspotify" { }
|
// mkContainer "yourspotify" { }
|
||||||
// mkContainer "netbird" { }
|
// mkContainer "netbird" { }
|
||||||
// mkContainer "kanidm" { }
|
// mkContainer "kanidm" { }
|
||||||
// mkContainer "nextcloud" {
|
// mkContainer "nextcloud" { enablePanzer = true; }
|
||||||
enablePanzer = true;
|
// mkContainer "paperless" { enableSharedPaperless = true; }
|
||||||
}
|
// mkContainer "forgejo" { enablePanzer = true; }
|
||||||
// mkContainer "paperless" {
|
// mkMicrovm "immich" { enablePanzer = true; }
|
||||||
enableSharedPaperless = true;
|
|
||||||
}
|
|
||||||
// mkContainer "forgejo" {
|
|
||||||
enablePanzer = true;
|
|
||||||
}
|
|
||||||
// mkMicrovm "immich" {
|
|
||||||
enablePanzer = true;
|
|
||||||
}
|
|
||||||
// mkContainer "samba" {
|
// mkContainer "samba" {
|
||||||
enablePanzer = true;
|
enablePanzer = true;
|
||||||
enableRenaultFT = true;
|
enableRenaultFT = true;
|
||||||
|
|
|
@ -1,14 +1,15 @@
|
||||||
|
{ config, lib, ... }:
|
||||||
{
|
{
|
||||||
config,
|
|
||||||
lib,
|
|
||||||
...
|
|
||||||
}: {
|
|
||||||
networking = {
|
networking = {
|
||||||
inherit (config.secrets.secrets.local.networking) hostId;
|
inherit (config.secrets.secrets.local.networking) hostId;
|
||||||
};
|
};
|
||||||
systemd.network.networks = {
|
systemd.network.networks = {
|
||||||
"10-lan01" = {
|
"10-lan01" = {
|
||||||
address = [(lib.net.cidr.hostCidr config.secrets.secrets.global.net.ips.${config.node.name} config.secrets.secrets.global.net.privateSubnetv4)];
|
address = [
|
||||||
|
(lib.net.cidr.hostCidr config.secrets.secrets.global.net.ips.${config.node.name}
|
||||||
|
config.secrets.secrets.global.net.privateSubnetv4
|
||||||
|
)
|
||||||
|
];
|
||||||
gateway = [ (lib.net.cidr.host 1 config.secrets.secrets.global.net.privateSubnetv4) ];
|
gateway = [ (lib.net.cidr.host 1 config.secrets.secrets.global.net.privateSubnetv4) ];
|
||||||
#matchConfig.MACAddress = config.secrets.secrets.local.networking.interfaces.lan01.mac;
|
#matchConfig.MACAddress = config.secrets.secrets.local.networking.interfaces.lan01.mac;
|
||||||
matchConfig.Name = "lan";
|
matchConfig.Name = "lan";
|
||||||
|
@ -33,7 +34,11 @@
|
||||||
networks = {
|
networks = {
|
||||||
# redo the network cause the livesystem has macvlans
|
# redo the network cause the livesystem has macvlans
|
||||||
"10-lan01" = {
|
"10-lan01" = {
|
||||||
address = [(lib.net.cidr.hostCidr config.secrets.secrets.global.net.ips.${config.node.name} config.secrets.secrets.global.net.privateSubnetv4)];
|
address = [
|
||||||
|
(lib.net.cidr.hostCidr config.secrets.secrets.global.net.ips.${config.node.name}
|
||||||
|
config.secrets.secrets.global.net.privateSubnetv4
|
||||||
|
)
|
||||||
|
];
|
||||||
gateway = [ (lib.net.cidr.host 1 config.secrets.secrets.global.net.privateSubnetv4) ];
|
gateway = [ (lib.net.cidr.host 1 config.secrets.secrets.global.net.privateSubnetv4) ];
|
||||||
matchConfig.MACAddress = config.secrets.secrets.local.networking.interfaces.lan01.mac;
|
matchConfig.MACAddress = config.secrets.secrets.local.networking.interfaces.lan01.mac;
|
||||||
dhcpV6Config.UseDNS = false;
|
dhcpV6Config.UseDNS = false;
|
||||||
|
@ -49,8 +54,13 @@
|
||||||
networking.nftables.firewall.zones.untrusted.interfaces = [ "lan" ];
|
networking.nftables.firewall.zones.untrusted.interfaces = [ "lan" ];
|
||||||
|
|
||||||
wireguard.elisabeth.server = {
|
wireguard.elisabeth.server = {
|
||||||
host = lib.net.cidr.host config.secrets.secrets.global.net.ips.${config.node.name} config.secrets.secrets.global.net.privateSubnetv4;
|
host =
|
||||||
reservedAddresses = ["10.42.0.0/20" "fd00:1764::/112"];
|
lib.net.cidr.host config.secrets.secrets.global.net.ips.${config.node.name}
|
||||||
|
config.secrets.secrets.global.net.privateSubnetv4;
|
||||||
|
reservedAddresses = [
|
||||||
|
"10.42.0.0/20"
|
||||||
|
"fd00:1764::/112"
|
||||||
|
];
|
||||||
openFirewall = true;
|
openFirewall = true;
|
||||||
};
|
};
|
||||||
# To be able to ping containers from the host, it is necessary
|
# To be able to ping containers from the host, it is necessary
|
||||||
|
|
|
@ -9,6 +9,11 @@
|
||||||
./fs.nix
|
./fs.nix
|
||||||
];
|
];
|
||||||
boot.mode = "bios";
|
boot.mode = "bios";
|
||||||
boot.initrd.availableKernelModules = ["virtio_pci" "virtio_net" "virtio_scsi" "virtio_blk"];
|
boot.initrd.availableKernelModules = [
|
||||||
|
"virtio_pci"
|
||||||
|
"virtio_net"
|
||||||
|
"virtio_scsi"
|
||||||
|
"virtio_blk"
|
||||||
|
];
|
||||||
nixpkgs.hostPlatform = "x86_64-linux";
|
nixpkgs.hostPlatform = "x86_64-linux";
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,5 @@
|
||||||
|
{ config, lib, ... }:
|
||||||
{
|
{
|
||||||
config,
|
|
||||||
lib,
|
|
||||||
...
|
|
||||||
}: {
|
|
||||||
disko.devices = {
|
disko.devices = {
|
||||||
disk = {
|
disk = {
|
||||||
drive = rec {
|
drive = rec {
|
||||||
|
@ -11,9 +8,15 @@
|
||||||
content = with lib.disko.gpt; {
|
content = with lib.disko.gpt; {
|
||||||
type = "gpt";
|
type = "gpt";
|
||||||
partitions = {
|
partitions = {
|
||||||
grub = partGrub // {device = "${device}-part1";};
|
grub = partGrub // {
|
||||||
bios = (partEfi "512MiB") // {device = "${device}-part2";};
|
device = "${device}-part1";
|
||||||
rpool = (partLuksZfs "rpool" "rpool" "100%") // {device = "${device}-part3";};
|
};
|
||||||
|
bios = (partEfi "512MiB") // {
|
||||||
|
device = "${device}-part2";
|
||||||
|
};
|
||||||
|
rpool = (partLuksZfs "rpool" "rpool" "100%") // {
|
||||||
|
device = "${device}-part3";
|
||||||
|
};
|
||||||
#(lib.attrsets.recursiveUpdate (partLuksZfs "rpool" "rpool" "17GiB" "100%") {content.extraFormatArgs = ["--pbkdf pbkdf2"];})
|
#(lib.attrsets.recursiveUpdate (partLuksZfs "rpool" "rpool" "17GiB" "100%") {content.extraFormatArgs = ["--pbkdf pbkdf2"];})
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -27,7 +30,5 @@
|
||||||
|
|
||||||
fileSystems."/state".neededForBoot = true;
|
fileSystems."/state".neededForBoot = true;
|
||||||
fileSystems."/persist".neededForBoot = true;
|
fileSystems."/persist".neededForBoot = true;
|
||||||
boot.loader.grub.devices = [
|
boot.loader.grub.devices = [ "/dev/disk/by-id/${config.secrets.secrets.local.disko.drive}" ];
|
||||||
"/dev/disk/by-id/${config.secrets.secrets.local.disko.drive}"
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,20 +1,21 @@
|
||||||
|
{ config, lib, ... }:
|
||||||
{
|
{
|
||||||
config,
|
|
||||||
lib,
|
|
||||||
...
|
|
||||||
}: {
|
|
||||||
networking.hostId = config.secrets.secrets.local.networking.hostId;
|
networking.hostId = config.secrets.secrets.local.networking.hostId;
|
||||||
networking.domain = config.secrets.secrets.global.domains.mail_public;
|
networking.domain = config.secrets.secrets.global.domains.mail_public;
|
||||||
|
|
||||||
boot.initrd.systemd.network = {
|
boot.initrd.systemd.network = {
|
||||||
enable = true;
|
enable = true;
|
||||||
networks = {inherit (config.systemd.network.networks) "lan01";};
|
networks = {
|
||||||
|
inherit (config.systemd.network.networks) "lan01";
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
systemd.network.networks = {
|
systemd.network.networks = {
|
||||||
"lan01" = let
|
"lan01" =
|
||||||
|
let
|
||||||
icfg = config.secrets.secrets.local.networking.interfaces.lan01;
|
icfg = config.secrets.secrets.local.networking.interfaces.lan01;
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
address = [
|
address = [
|
||||||
icfg.hostCidrv4
|
icfg.hostCidrv4
|
||||||
(lib.net.cidr.hostCidr 1 icfg.hostCidrv6)
|
(lib.net.cidr.hostCidr 1 icfg.hostCidrv6)
|
||||||
|
|
|
@ -1,8 +1,5 @@
|
||||||
|
{ inputs, lib, ... }:
|
||||||
{
|
{
|
||||||
inputs,
|
|
||||||
lib,
|
|
||||||
...
|
|
||||||
}: {
|
|
||||||
imports = [
|
imports = [
|
||||||
../../config/basic
|
../../config/basic
|
||||||
../../config/services/octoprint.nix
|
../../config/services/octoprint.nix
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
{lib, ...}: {
|
{ lib, ... }:
|
||||||
|
{
|
||||||
fileSystems = lib.mkForce {
|
fileSystems = lib.mkForce {
|
||||||
"/" = {
|
"/" = {
|
||||||
device = "/dev/disk/by-uuid/44444444-4444-4444-8888-888888888888";
|
device = "/dev/disk/by-uuid/44444444-4444-4444-8888-888888888888";
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
{config, ...}: {
|
{ config, ... }:
|
||||||
|
{
|
||||||
networking = {
|
networking = {
|
||||||
inherit (config.secrets.secrets.local.networking) hostId;
|
inherit (config.secrets.secrets.local.networking) hostId;
|
||||||
wireless.iwd = {
|
wireless.iwd = {
|
||||||
|
|
|
@ -1,8 +1,5 @@
|
||||||
|
{ inputs, lib, ... }:
|
||||||
{
|
{
|
||||||
inputs,
|
|
||||||
lib,
|
|
||||||
...
|
|
||||||
}: {
|
|
||||||
imports = [
|
imports = [
|
||||||
inputs.nixos-hardware.nixosModules.common-cpu-intel
|
inputs.nixos-hardware.nixosModules.common-cpu-intel
|
||||||
# for some reasons the cpu-intel includes the gpu as well
|
# for some reasons the cpu-intel includes the gpu as well
|
||||||
|
@ -45,11 +42,12 @@
|
||||||
layout = "de";
|
layout = "de";
|
||||||
};
|
};
|
||||||
libinput = {
|
libinput = {
|
||||||
touchpad = lib.mkForce {
|
touchpad = lib.mkForce { accelSpeed = "0.5"; };
|
||||||
accelSpeed = "0.5";
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
nixpkgs.hostPlatform = "x86_64-linux";
|
nixpkgs.hostPlatform = "x86_64-linux";
|
||||||
nix.settings.system-features = ["kvm" "nixos-test"];
|
nix.settings.system-features = [
|
||||||
|
"kvm"
|
||||||
|
"nixos-test"
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,5 @@
|
||||||
|
{ config, lib, ... }:
|
||||||
{
|
{
|
||||||
config,
|
|
||||||
lib,
|
|
||||||
...
|
|
||||||
}: {
|
|
||||||
disko.devices = {
|
disko.devices = {
|
||||||
disk = {
|
disk = {
|
||||||
m2-ssd = rec {
|
m2-ssd = rec {
|
||||||
|
@ -11,9 +8,15 @@
|
||||||
content = with lib.disko.gpt; {
|
content = with lib.disko.gpt; {
|
||||||
type = "gpt";
|
type = "gpt";
|
||||||
partitions = {
|
partitions = {
|
||||||
boot = (partEfi "1GiB") // {device = "${device}-part1";};
|
boot = (partEfi "1GiB") // {
|
||||||
swap = (partSwap "16GiB") // {device = "${device}-part2";};
|
device = "${device}-part1";
|
||||||
rpool = (partLuksZfs "rpool" "rpool" "100%") // {device = "${device}-part3";};
|
};
|
||||||
|
swap = (partSwap "16GiB") // {
|
||||||
|
device = "${device}-part2";
|
||||||
|
};
|
||||||
|
rpool = (partLuksZfs "rpool" "rpool" "100%") // {
|
||||||
|
device = "${device}-part3";
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
{config, ...}: {
|
{ config, ... }:
|
||||||
|
{
|
||||||
age.secrets.eduroam = {
|
age.secrets.eduroam = {
|
||||||
rekeyFile = ./secrets/iwd/eduroam.8021x.age;
|
rekeyFile = ./secrets/iwd/eduroam.8021x.age;
|
||||||
path = "/var/lib/iwd/eduroam.8021x";
|
path = "/var/lib/iwd/eduroam.8021x";
|
||||||
|
@ -10,7 +11,11 @@
|
||||||
devoloog-sae20.rekeyFile = ./secrets/iwd/devoloog-sae20.age;
|
devoloog-sae20.rekeyFile = ./secrets/iwd/devoloog-sae20.age;
|
||||||
};
|
};
|
||||||
wireguard.samba-patrick.client.via = "elisabeth-samba";
|
wireguard.samba-patrick.client.via = "elisabeth-samba";
|
||||||
networking.nftables.firewall.zones.untrusted.interfaces = ["lan01" "lan02" "wlan01"];
|
networking.nftables.firewall.zones.untrusted.interfaces = [
|
||||||
|
"lan01"
|
||||||
|
"lan02"
|
||||||
|
"wlan01"
|
||||||
|
];
|
||||||
networking = {
|
networking = {
|
||||||
inherit (config.secrets.secrets.local.networking) hostId;
|
inherit (config.secrets.secrets.local.networking) hostId;
|
||||||
wireless.iwd = {
|
wireless.iwd = {
|
||||||
|
|
|
@ -1,3 +1 @@
|
||||||
inputs: [
|
inputs: [ (import ./misc.nix inputs) ]
|
||||||
(import ./misc.nix inputs)
|
|
||||||
]
|
|
||||||
|
|
14
lib/misc.nix
14
lib/misc.nix
|
@ -1,11 +1,9 @@
|
||||||
_inputs: _self: super: let
|
_inputs: _self: super:
|
||||||
|
let
|
||||||
writeText = text: (super.writeText (builtins.hashString "sha256" "${text}") "${text}");
|
writeText = text: (super.writeText (builtins.hashString "sha256" "${text}") "${text}");
|
||||||
in {
|
in
|
||||||
lib =
|
{
|
||||||
super.lib
|
lib = super.lib // {
|
||||||
// {
|
inherit writeText;
|
||||||
inherit
|
|
||||||
writeText
|
|
||||||
;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,6 @@
|
||||||
{
|
{ lib, config, ... }:
|
||||||
lib,
|
let
|
||||||
config,
|
inherit (lib)
|
||||||
...
|
|
||||||
}: let
|
|
||||||
inherit
|
|
||||||
(lib)
|
|
||||||
mkEnableOption
|
mkEnableOption
|
||||||
mkMerge
|
mkMerge
|
||||||
attrNames
|
attrNames
|
||||||
|
@ -18,7 +14,8 @@
|
||||||
mapAttrs'
|
mapAttrs'
|
||||||
listToAttrs
|
listToAttrs
|
||||||
;
|
;
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
home-manager.sharedModules = [
|
home-manager.sharedModules = [
|
||||||
{
|
{
|
||||||
options.images = {
|
options.images = {
|
||||||
|
@ -39,16 +36,15 @@ in {
|
||||||
|
|
||||||
imports = [
|
imports = [
|
||||||
(
|
(
|
||||||
{config, ...}: {
|
{ config, ... }:
|
||||||
|
{
|
||||||
age.secrets = mkMerge (
|
age.secrets = mkMerge (
|
||||||
flip map
|
flip map (attrNames config.home-manager.users) (
|
||||||
(attrNames config.home-manager.users)
|
|
||||||
(
|
|
||||||
user:
|
user:
|
||||||
mkIf config.home-manager.users.${user}.images.enable (
|
mkIf config.home-manager.users.${user}.images.enable (
|
||||||
listToAttrs (flip map (attrNames (filterAttrs (_: type: type == "regular") (builtins.readDir ../secrets/img)))
|
listToAttrs (
|
||||||
(
|
flip map (attrNames (filterAttrs (_: type: type == "regular") (builtins.readDir ../secrets/img)))
|
||||||
file: {
|
(file: {
|
||||||
name = "images-${user}-${file}";
|
name = "images-${user}-${file}";
|
||||||
value = {
|
value = {
|
||||||
name = removeSuffix ".age" file;
|
name = removeSuffix ".age" file;
|
||||||
|
@ -56,8 +52,8 @@ in {
|
||||||
owner = user;
|
owner = user;
|
||||||
group = user;
|
group = user;
|
||||||
};
|
};
|
||||||
}
|
})
|
||||||
))
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,10 +1,6 @@
|
||||||
{
|
{ config, lib, ... }:
|
||||||
config,
|
let
|
||||||
lib,
|
inherit (lib)
|
||||||
...
|
|
||||||
}: let
|
|
||||||
inherit
|
|
||||||
(lib)
|
|
||||||
flip
|
flip
|
||||||
mapAttrs
|
mapAttrs
|
||||||
attrNames
|
attrNames
|
||||||
|
@ -13,7 +9,8 @@
|
||||||
mkMerge
|
mkMerge
|
||||||
isAttrs
|
isAttrs
|
||||||
;
|
;
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
# Expose a home manager module for each user that allows extending
|
# Expose a home manager module for each user that allows extending
|
||||||
# environment.persistence.${sourceDir}.users.${userName} simply by
|
# environment.persistence.${sourceDir}.users.${userName} simply by
|
||||||
# specifying home.persistence.${sourceDir} in home manager.
|
# specifying home.persistence.${sourceDir} in home manager.
|
||||||
|
@ -22,7 +19,8 @@ in {
|
||||||
options.home.persistence = mkOption {
|
options.home.persistence = mkOption {
|
||||||
description = "Additional persistence config for the given source path";
|
description = "Additional persistence config for the given source path";
|
||||||
default = { };
|
default = { };
|
||||||
type = types.attrsOf (types.submodule {
|
type = types.attrsOf (
|
||||||
|
types.submodule {
|
||||||
options = {
|
options = {
|
||||||
files = mkOption {
|
files = mkOption {
|
||||||
description = "Additional files to persist via NixOS impermanence.";
|
description = "Additional files to persist via NixOS impermanence.";
|
||||||
|
@ -36,39 +34,31 @@ in {
|
||||||
default = [ ];
|
default = [ ];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
});
|
}
|
||||||
|
);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
# For each user that has a home-manager config, merge the locally defined
|
# For each user that has a home-manager config, merge the locally defined
|
||||||
# persistence options that we defined above.
|
# persistence options that we defined above.
|
||||||
imports = let
|
imports =
|
||||||
mkUserFiles = map (x:
|
let
|
||||||
{parentDirectory.mode = "700";}
|
mkUserFiles = map (
|
||||||
// (
|
x: { parentDirectory.mode = "700"; } // (if isAttrs x then x else { file = x; })
|
||||||
if isAttrs x
|
);
|
||||||
then x
|
mkUserDirs = map (x: { mode = "700"; } // (if isAttrs x then x else { directory = x; }));
|
||||||
else {file = x;}
|
in
|
||||||
));
|
[
|
||||||
mkUserDirs = map (x:
|
|
||||||
{mode = "700";}
|
|
||||||
// (
|
|
||||||
if isAttrs x
|
|
||||||
then x
|
|
||||||
else {directory = x;}
|
|
||||||
));
|
|
||||||
in [
|
|
||||||
{
|
{
|
||||||
environment.persistence = mkMerge (
|
environment.persistence = mkMerge (
|
||||||
flip map
|
flip map (attrNames config.home-manager.users) (
|
||||||
(attrNames config.home-manager.users)
|
user:
|
||||||
(
|
let
|
||||||
user: let
|
|
||||||
hmUserCfg = config.home-manager.users.${user};
|
hmUserCfg = config.home-manager.users.${user};
|
||||||
in
|
in
|
||||||
flip mapAttrs hmUserCfg.home.persistence
|
flip mapAttrs hmUserCfg.home.persistence (
|
||||||
(_: sourceCfg: {
|
_: sourceCfg: {
|
||||||
users.${user} = {
|
users.${user} = {
|
||||||
# This needs to be set for allo users with non
|
# This needs to be set for allo users with non
|
||||||
# standart home (not /home/<userName>
|
# standart home (not /home/<userName>
|
||||||
|
@ -77,16 +67,12 @@ in {
|
||||||
# as there will be infinite recursion
|
# as there will be infinite recursion
|
||||||
# If this setting is forgotten there
|
# If this setting is forgotten there
|
||||||
# are assertions in place warning you
|
# are assertions in place warning you
|
||||||
home =
|
home = { root = "/root"; }.${user} or "/home/${user}";
|
||||||
{
|
|
||||||
root = "/root";
|
|
||||||
}
|
|
||||||
.${user}
|
|
||||||
or "/home/${user}";
|
|
||||||
files = mkUserFiles sourceCfg.files;
|
files = mkUserFiles sourceCfg.files;
|
||||||
directories = mkUserDirs sourceCfg.directories;
|
directories = mkUserDirs sourceCfg.directories;
|
||||||
};
|
};
|
||||||
})
|
}
|
||||||
|
)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,6 @@
|
||||||
{
|
{ lib, pkgs, ... }:
|
||||||
lib,
|
let
|
||||||
pkgs,
|
inherit (lib)
|
||||||
...
|
|
||||||
}: let
|
|
||||||
inherit
|
|
||||||
(lib)
|
|
||||||
types
|
types
|
||||||
mkEnableOption
|
mkEnableOption
|
||||||
mkPackageOption
|
mkPackageOption
|
||||||
|
@ -12,9 +8,12 @@
|
||||||
mkIf
|
mkIf
|
||||||
;
|
;
|
||||||
settingsFormat = pkgs.formats.json { };
|
settingsFormat = pkgs.formats.json { };
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
home-manager.sharedModules = [
|
home-manager.sharedModules = [
|
||||||
({config, ...}: let
|
(
|
||||||
|
{ config, ... }:
|
||||||
|
let
|
||||||
cfg = settingsFormat.generate "config.json" {
|
cfg = settingsFormat.generate "config.json" {
|
||||||
streamdeck_ui_version = 2;
|
streamdeck_ui_version = 2;
|
||||||
state = config.programs.streamdeck-ui.settings;
|
state = config.programs.streamdeck-ui.settings;
|
||||||
|
@ -22,7 +21,8 @@ in {
|
||||||
preStart = pkgs.writeShellScript "streamdeck-setup-config" ''
|
preStart = pkgs.writeShellScript "streamdeck-setup-config" ''
|
||||||
${pkgs.coreutils}/bin/cp "${cfg}" "$XDG_RUNTIME_DIR/streamdeck/config.json"
|
${pkgs.coreutils}/bin/cp "${cfg}" "$XDG_RUNTIME_DIR/streamdeck/config.json"
|
||||||
'';
|
'';
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
options.programs.streamdeck-ui = {
|
options.programs.streamdeck-ui = {
|
||||||
enable = mkEnableOption "streamdeck-ui";
|
enable = mkEnableOption "streamdeck-ui";
|
||||||
package = mkPackageOption pkgs "streamdeck-ui" { };
|
package = mkPackageOption pkgs "streamdeck-ui" { };
|
||||||
|
@ -53,6 +53,7 @@ in {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
})
|
}
|
||||||
|
)
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,9 +3,9 @@
|
||||||
pkgs,
|
pkgs,
|
||||||
config,
|
config,
|
||||||
...
|
...
|
||||||
}: let
|
}:
|
||||||
inherit
|
let
|
||||||
(lib)
|
inherit (lib)
|
||||||
types
|
types
|
||||||
mkEnableOption
|
mkEnableOption
|
||||||
mkPackageOption
|
mkPackageOption
|
||||||
|
@ -16,7 +16,8 @@
|
||||||
configFile = formatType.generate "config.json" cfg.settings;
|
configFile = formatType.generate "config.json" cfg.settings;
|
||||||
|
|
||||||
formatType = pkgs.formats.json { };
|
formatType = pkgs.formats.json { };
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
options.services.actual = {
|
options.services.actual = {
|
||||||
enable = mkEnableOption "actual, a privacy focused app for managing your finances";
|
enable = mkEnableOption "actual, a privacy focused app for managing your finances";
|
||||||
package = mkPackageOption pkgs "actual" { };
|
package = mkPackageOption pkgs "actual" { };
|
||||||
|
|
|
@ -1,10 +1,6 @@
|
||||||
{
|
{ lib, config, ... }:
|
||||||
lib,
|
let
|
||||||
config,
|
inherit (lib)
|
||||||
...
|
|
||||||
}: let
|
|
||||||
inherit
|
|
||||||
(lib)
|
|
||||||
concatLists
|
concatLists
|
||||||
flip
|
flip
|
||||||
mapAttrsToList
|
mapAttrsToList
|
||||||
|
@ -16,7 +12,8 @@
|
||||||
;
|
;
|
||||||
|
|
||||||
cfg = config.users.deterministicIds;
|
cfg = config.users.deterministicIds;
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
options = {
|
options = {
|
||||||
users.deterministicIds = mkOption {
|
users.deterministicIds = mkOption {
|
||||||
default = { };
|
default = { };
|
||||||
|
@ -25,7 +22,8 @@ in {
|
||||||
used on the system without specifying a uid/gid, this module will assign the
|
used on the system without specifying a uid/gid, this module will assign the
|
||||||
corresponding ids defined here, or show an error if the definition is missing.
|
corresponding ids defined here, or show an error if the definition is missing.
|
||||||
'';
|
'';
|
||||||
type = types.attrsOf (types.submodule {
|
type = types.attrsOf (
|
||||||
|
types.submodule {
|
||||||
options = {
|
options = {
|
||||||
uid = mkOption {
|
uid = mkOption {
|
||||||
type = types.nullOr types.int;
|
type = types.nullOr types.int;
|
||||||
|
@ -38,31 +36,46 @@ in {
|
||||||
description = mdDoc "The gid to assign if it is missing in `users.groups.<name>`.";
|
description = mdDoc "The gid to assign if it is missing in `users.groups.<name>`.";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
});
|
}
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
users.users = mkOption {
|
users.users = mkOption {
|
||||||
type = types.attrsOf (types.submodule ({name, ...}: {
|
type = types.attrsOf (
|
||||||
config.uid = let
|
types.submodule (
|
||||||
|
{ name, ... }:
|
||||||
|
{
|
||||||
|
config.uid =
|
||||||
|
let
|
||||||
deterministicUid = cfg.${name}.uid or null;
|
deterministicUid = cfg.${name}.uid or null;
|
||||||
in
|
in
|
||||||
mkIf (deterministicUid != null) (mkDefault deterministicUid);
|
mkIf (deterministicUid != null) (mkDefault deterministicUid);
|
||||||
}));
|
}
|
||||||
|
)
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
users.groups = mkOption {
|
users.groups = mkOption {
|
||||||
type = types.attrsOf (types.submodule ({name, ...}: {
|
type = types.attrsOf (
|
||||||
config.gid = let
|
types.submodule (
|
||||||
|
{ name, ... }:
|
||||||
|
{
|
||||||
|
config.gid =
|
||||||
|
let
|
||||||
deterministicGid = cfg.${name}.gid or null;
|
deterministicGid = cfg.${name}.gid or null;
|
||||||
in
|
in
|
||||||
mkIf (deterministicGid != null) (mkDefault deterministicGid);
|
mkIf (deterministicGid != null) (mkDefault deterministicGid);
|
||||||
}));
|
}
|
||||||
|
)
|
||||||
|
);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
config = {
|
config = {
|
||||||
assertions =
|
assertions =
|
||||||
concatLists (flip mapAttrsToList config.users.users (name: user: [
|
concatLists (
|
||||||
|
flip mapAttrsToList config.users.users (
|
||||||
|
name: user: [
|
||||||
{
|
{
|
||||||
assertion = user.uid != null;
|
assertion = user.uid != null;
|
||||||
message = "non-deterministic uid detected for '${name}', please assign one via `users.deterministicIds`";
|
message = "non-deterministic uid detected for '${name}', please assign one via `users.deterministicIds`";
|
||||||
|
@ -71,10 +84,14 @@ in {
|
||||||
assertion = !user.autoSubUidGidRange;
|
assertion = !user.autoSubUidGidRange;
|
||||||
message = "non-deterministic subUids/subGids detected for: ${name}";
|
message = "non-deterministic subUids/subGids detected for: ${name}";
|
||||||
}
|
}
|
||||||
]))
|
]
|
||||||
++ flip mapAttrsToList config.users.groups (name: group: {
|
)
|
||||||
|
)
|
||||||
|
++ flip mapAttrsToList config.users.groups (
|
||||||
|
name: group: {
|
||||||
assertion = group.gid != null;
|
assertion = group.gid != null;
|
||||||
message = "non-deterministic gid detected for '${name}', please assign one via `users.deterministicIds`";
|
message = "non-deterministic gid detected for '${name}', please assign one via `users.deterministicIds`";
|
||||||
});
|
}
|
||||||
|
);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,9 +3,9 @@
|
||||||
lib,
|
lib,
|
||||||
nodes,
|
nodes,
|
||||||
...
|
...
|
||||||
}: let
|
}:
|
||||||
inherit
|
let
|
||||||
(lib)
|
inherit (lib)
|
||||||
attrNames
|
attrNames
|
||||||
concatMap
|
concatMap
|
||||||
concatStringsSep
|
concatStringsSep
|
||||||
|
@ -21,16 +21,20 @@
|
||||||
;
|
;
|
||||||
|
|
||||||
nodeName = config.node.name;
|
nodeName = config.node.name;
|
||||||
mkForwardedOption = path:
|
mkForwardedOption =
|
||||||
|
path:
|
||||||
mkOption {
|
mkOption {
|
||||||
type = mkOptionType {
|
type = mkOptionType {
|
||||||
name = "Same type that the receiving option `${concatStringsSep "." path}` normally accepts.";
|
name = "Same type that the receiving option `${concatStringsSep "." path}` normally accepts.";
|
||||||
merge = _loc: defs:
|
merge =
|
||||||
builtins.filter
|
_loc: defs:
|
||||||
(x: builtins.isAttrs x -> ((x._type or "") != "__distributed_config_empty"))
|
builtins.filter (x: builtins.isAttrs x -> ((x._type or "") != "__distributed_config_empty")) (
|
||||||
(map (x: x.value) defs);
|
map (x: x.value) defs
|
||||||
|
);
|
||||||
|
};
|
||||||
|
default = {
|
||||||
|
_type = "__distributed_config_empty";
|
||||||
};
|
};
|
||||||
default = {_type = "__distributed_config_empty";};
|
|
||||||
description = ''
|
description = ''
|
||||||
Anything specified here will be forwarded to `${concatStringsSep "." path}`
|
Anything specified here will be forwarded to `${concatStringsSep "." path}`
|
||||||
on the given node. Forwarding happens as-is to the raw values,
|
on the given node. Forwarding happens as-is to the raw values,
|
||||||
|
@ -39,23 +43,34 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
forwardedOptions = [
|
forwardedOptions = [
|
||||||
["age" "secrets"]
|
[
|
||||||
["services" "maddy" "ensureCredentials"]
|
"age"
|
||||||
|
"secrets"
|
||||||
|
]
|
||||||
|
[
|
||||||
|
"services"
|
||||||
|
"maddy"
|
||||||
|
"ensureCredentials"
|
||||||
|
]
|
||||||
];
|
];
|
||||||
|
|
||||||
attrsForEachOption = f: (foldl' (acc: path: recursiveUpdate acc (setAttrByPath path (f path))) {} forwardedOptions);
|
attrsForEachOption =
|
||||||
in {
|
f: (foldl' (acc: path: recursiveUpdate acc (setAttrByPath path (f path))) { } forwardedOptions);
|
||||||
|
in
|
||||||
|
{
|
||||||
options.nodes = mkOption {
|
options.nodes = mkOption {
|
||||||
description = "Options forwareded to the given node.";
|
description = "Options forwareded to the given node.";
|
||||||
default = { };
|
default = { };
|
||||||
type = types.attrsOf (types.submodule {
|
type = types.attrsOf (types.submodule { options = attrsForEachOption mkForwardedOption; });
|
||||||
options = attrsForEachOption mkForwardedOption;
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
config = let
|
config =
|
||||||
mergeConfigFromOthers = let
|
let
|
||||||
getConfig = path: otherNode: let
|
mergeConfigFromOthers =
|
||||||
|
let
|
||||||
|
getConfig =
|
||||||
|
path: otherNode:
|
||||||
|
let
|
||||||
cfg = nodes.${otherNode}.config.nodes.${nodeName} or null;
|
cfg = nodes.${otherNode}.config.nodes.${nodeName} or null;
|
||||||
in
|
in
|
||||||
optionals (cfg != null) (getAttrFromPath path cfg);
|
optionals (cfg != null) (getAttrFromPath path cfg);
|
||||||
|
|
|
@ -3,17 +3,18 @@
|
||||||
config,
|
config,
|
||||||
pkgs,
|
pkgs,
|
||||||
...
|
...
|
||||||
}: let
|
}:
|
||||||
|
let
|
||||||
cfg = config.services.homebox;
|
cfg = config.services.homebox;
|
||||||
inherit
|
inherit (lib)
|
||||||
(lib)
|
|
||||||
mkEnableOption
|
mkEnableOption
|
||||||
mkPackageOption
|
mkPackageOption
|
||||||
mkDefault
|
mkDefault
|
||||||
types
|
types
|
||||||
mkIf
|
mkIf
|
||||||
;
|
;
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
options.services.homebox = {
|
options.services.homebox = {
|
||||||
enable = mkEnableOption "homebox";
|
enable = mkEnableOption "homebox";
|
||||||
package = mkPackageOption pkgs "homebox" { };
|
package = mkPackageOption pkgs "homebox" { };
|
||||||
|
|
|
@ -3,16 +3,18 @@
|
||||||
pkgs,
|
pkgs,
|
||||||
config,
|
config,
|
||||||
...
|
...
|
||||||
}: {
|
}:
|
||||||
options.networking.wireless.iwd = let
|
{
|
||||||
inherit
|
options.networking.wireless.iwd =
|
||||||
(lib)
|
let
|
||||||
|
inherit (lib)
|
||||||
mkOption
|
mkOption
|
||||||
literalExample
|
literalExample
|
||||||
types
|
types
|
||||||
hasAttrByPath
|
hasAttrByPath
|
||||||
;
|
;
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
networks = mkOption {
|
networks = mkOption {
|
||||||
default = { };
|
default = { };
|
||||||
example = literalExample ''
|
example = literalExample ''
|
||||||
|
@ -32,21 +34,41 @@
|
||||||
<citerefentry><refentrytitle>iwctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>.
|
<citerefentry><refentrytitle>iwctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>.
|
||||||
'';
|
'';
|
||||||
|
|
||||||
type = types.attrsOf (types.submodule ({config, ...}: {
|
type = types.attrsOf (
|
||||||
|
types.submodule (
|
||||||
|
{ config, ... }:
|
||||||
|
{
|
||||||
config.kind =
|
config.kind =
|
||||||
if (hasAttrByPath ["Security" "Passphrase"] config.settings)
|
if
|
||||||
then "psk"
|
(hasAttrByPath [
|
||||||
else if !(hasAttrByPath ["Security"] config.settings)
|
"Security"
|
||||||
then "open"
|
"Passphrase"
|
||||||
else "8021x";
|
] config.settings)
|
||||||
|
then
|
||||||
|
"psk"
|
||||||
|
else if !(hasAttrByPath [ "Security" ] config.settings) then
|
||||||
|
"open"
|
||||||
|
else
|
||||||
|
"8021x";
|
||||||
|
|
||||||
options = {
|
options = {
|
||||||
kind = mkOption {
|
kind = mkOption {
|
||||||
type = types.enum ["open" "psk" "8021x"];
|
type = types.enum [
|
||||||
|
"open"
|
||||||
|
"psk"
|
||||||
|
"8021x"
|
||||||
|
];
|
||||||
description = "The type of network. This will determine the file ending. The module will try to determine this automatically so this should only be set when the heuristics fail.";
|
description = "The type of network. This will determine the file ending. The module will try to determine this automatically so this should only be set when the heuristics fail.";
|
||||||
};
|
};
|
||||||
settings = mkOption {
|
settings = mkOption {
|
||||||
type = with types; (attrsOf (attrsOf (oneOf [str path])));
|
type =
|
||||||
|
with types;
|
||||||
|
(attrsOf (
|
||||||
|
attrsOf (oneOf [
|
||||||
|
str
|
||||||
|
path
|
||||||
|
])
|
||||||
|
));
|
||||||
description = ''
|
description = ''
|
||||||
Contents of the iwd config file for this network
|
Contents of the iwd config file for this network
|
||||||
The lowest level values should be files, that will be read into the config files
|
The lowest level values should be files, that will be read into the config files
|
||||||
|
@ -54,13 +76,15 @@
|
||||||
default = { };
|
default = { };
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}));
|
}
|
||||||
|
)
|
||||||
|
);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
config = let
|
config =
|
||||||
inherit
|
let
|
||||||
(lib)
|
inherit (lib)
|
||||||
mkIf
|
mkIf
|
||||||
flip
|
flip
|
||||||
mapAttrsToList
|
mapAttrsToList
|
||||||
|
@ -83,22 +107,36 @@
|
||||||
mkIf cfg.enable {
|
mkIf cfg.enable {
|
||||||
systemd.services.iwd = mkIf (cfg.networks != { }) {
|
systemd.services.iwd = mkIf (cfg.networks != { }) {
|
||||||
path = [ encoder ];
|
path = [ encoder ];
|
||||||
preStart = let
|
preStart =
|
||||||
|
let
|
||||||
dataDir = "/var/lib/iwd";
|
dataDir = "/var/lib/iwd";
|
||||||
in ''
|
in
|
||||||
|
''
|
||||||
# Create config files for declaratively defined networks in the NixOS config.
|
# Create config files for declaratively defined networks in the NixOS config.
|
||||||
${concatStringsSep "\n" (flip mapAttrsToList cfg.networks (network: config: ''
|
${concatStringsSep "\n" (
|
||||||
|
flip mapAttrsToList cfg.networks (
|
||||||
|
network: config: ''
|
||||||
filename=${dataDir}/"$(encoder '${network}.${config.kind}')"
|
filename=${dataDir}/"$(encoder '${network}.${config.kind}')"
|
||||||
touch "$filename"
|
touch "$filename"
|
||||||
cat >$filename <<EOF
|
cat >$filename <<EOF
|
||||||
${concatStringsSep "\n" (flip mapAttrsToList config.settings (toplevel: config: ''
|
${concatStringsSep "\n" (
|
||||||
|
flip mapAttrsToList config.settings (
|
||||||
|
toplevel: config: ''
|
||||||
[${toplevel}]
|
[${toplevel}]
|
||||||
${concatStringsSep "\n" (flip mapAttrsToList config (name: value: ''
|
${concatStringsSep "\n" (
|
||||||
|
flip mapAttrsToList config (
|
||||||
|
name: value: ''
|
||||||
${name}=$(<${value})
|
${name}=$(<${value})
|
||||||
''))}
|
''
|
||||||
''))}
|
)
|
||||||
|
)}
|
||||||
|
''
|
||||||
|
)
|
||||||
|
)}
|
||||||
EOF
|
EOF
|
||||||
''))}
|
''
|
||||||
|
)
|
||||||
|
)}
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -4,9 +4,9 @@
|
||||||
options,
|
options,
|
||||||
pkgs,
|
pkgs,
|
||||||
...
|
...
|
||||||
}: let
|
}:
|
||||||
inherit
|
let
|
||||||
(lib)
|
inherit (lib)
|
||||||
any
|
any
|
||||||
attrNames
|
attrNames
|
||||||
attrValues
|
attrValues
|
||||||
|
@ -46,19 +46,26 @@
|
||||||
serverConfigFile = settingsFormat.generate "server.toml" (filterConfig cfg.serverSettings);
|
serverConfigFile = settingsFormat.generate "server.toml" (filterConfig cfg.serverSettings);
|
||||||
clientConfigFile = settingsFormat.generate "kanidm-config.toml" (filterConfig cfg.clientSettings);
|
clientConfigFile = settingsFormat.generate "kanidm-config.toml" (filterConfig cfg.clientSettings);
|
||||||
unixConfigFile = settingsFormat.generate "kanidm-unixd.toml" (filterConfig cfg.unixSettings);
|
unixConfigFile = settingsFormat.generate "kanidm-unixd.toml" (filterConfig cfg.unixSettings);
|
||||||
certPaths = builtins.map builtins.dirOf [cfg.serverSettings.tls_chain cfg.serverSettings.tls_key];
|
certPaths = builtins.map builtins.dirOf [
|
||||||
|
cfg.serverSettings.tls_chain
|
||||||
|
cfg.serverSettings.tls_key
|
||||||
|
];
|
||||||
|
|
||||||
# Merge bind mount paths and remove paths where a prefix is already mounted.
|
# Merge bind mount paths and remove paths where a prefix is already mounted.
|
||||||
# This makes sure that if e.g. the tls_chain is in the nix store and /nix/store is already in the mount
|
# This makes sure that if e.g. the tls_chain is in the nix store and /nix/store is already in the mount
|
||||||
# paths, no new bind mount is added. Adding subpaths caused problems on ofborg.
|
# paths, no new bind mount is added. Adding subpaths caused problems on ofborg.
|
||||||
hasPrefixInList = list: newPath: any (path: hasPrefix (builtins.toString path) (builtins.toString newPath)) list;
|
hasPrefixInList =
|
||||||
mergePaths = foldl' (merged: newPath: let
|
list: newPath: any (path: hasPrefix (builtins.toString path) (builtins.toString newPath)) list;
|
||||||
|
mergePaths = foldl' (
|
||||||
|
merged: newPath:
|
||||||
|
let
|
||||||
# If the new path is a prefix to some existing path, we need to filter it out
|
# If the new path is a prefix to some existing path, we need to filter it out
|
||||||
filteredPaths = filter (p: !hasPrefix (builtins.toString newPath) (builtins.toString p)) merged;
|
filteredPaths = filter (p: !hasPrefix (builtins.toString newPath) (builtins.toString p)) merged;
|
||||||
# If a prefix of the new path is already in the list, do not add it
|
# If a prefix of the new path is already in the list, do not add it
|
||||||
filteredNew = optional (!hasPrefixInList filteredPaths newPath) newPath;
|
filteredNew = optional (!hasPrefixInList filteredPaths newPath) newPath;
|
||||||
in
|
in
|
||||||
filteredPaths ++ filteredNew) [];
|
filteredPaths ++ filteredNew
|
||||||
|
) [ ];
|
||||||
|
|
||||||
defaultServiceConfig = {
|
defaultServiceConfig = {
|
||||||
BindReadOnlyPaths = [
|
BindReadOnlyPaths = [
|
||||||
|
@ -97,12 +104,16 @@
|
||||||
RestrictRealtime = true;
|
RestrictRealtime = true;
|
||||||
RestrictSUIDSGID = true;
|
RestrictSUIDSGID = true;
|
||||||
SystemCallArchitectures = "native";
|
SystemCallArchitectures = "native";
|
||||||
SystemCallFilter = ["@system-service" "~@privileged @resources @setuid @keyring"];
|
SystemCallFilter = [
|
||||||
|
"@system-service"
|
||||||
|
"~@privileged @resources @setuid @keyring"
|
||||||
|
];
|
||||||
# Does not work well with the temporary root
|
# Does not work well with the temporary root
|
||||||
#UMask = "0066";
|
#UMask = "0066";
|
||||||
};
|
};
|
||||||
|
|
||||||
mkPresentOption = what:
|
mkPresentOption =
|
||||||
|
what:
|
||||||
mkOption {
|
mkOption {
|
||||||
description = mdDoc "Whether to ensure that this ${what} is present or absent.";
|
description = mdDoc "Whether to ensure that this ${what} is present or absent.";
|
||||||
type = types.bool;
|
type = types.bool;
|
||||||
|
@ -111,20 +122,21 @@
|
||||||
|
|
||||||
filterPresent = filterAttrs (_: v: v.present);
|
filterPresent = filterAttrs (_: v: v.present);
|
||||||
|
|
||||||
provisionStateJson = pkgs.writeText "provision-state.json" (builtins.toJSON {
|
provisionStateJson = pkgs.writeText "provision-state.json" (
|
||||||
inherit (cfg.provision) groups persons systems;
|
builtins.toJSON { inherit (cfg.provision) groups persons systems; }
|
||||||
});
|
);
|
||||||
|
|
||||||
serverPort =
|
serverPort =
|
||||||
# ipv6:
|
# ipv6:
|
||||||
if hasInfix "]:" cfg.serverSettings.bindaddress
|
if hasInfix "]:" cfg.serverSettings.bindaddress then
|
||||||
then last (splitString "]:" cfg.serverSettings.bindaddress)
|
last (splitString "]:" cfg.serverSettings.bindaddress)
|
||||||
else
|
else
|
||||||
# ipv4:
|
# ipv4:
|
||||||
if hasInfix "." cfg.serverSettings.bindaddress
|
if hasInfix "." cfg.serverSettings.bindaddress then
|
||||||
then last (splitString ":" cfg.serverSettings.bindaddress)
|
last (splitString ":" cfg.serverSettings.bindaddress)
|
||||||
# default is 8443
|
# default is 8443
|
||||||
else "8443";
|
else
|
||||||
|
"8443";
|
||||||
|
|
||||||
# Only recover the admin account if a password should explicitly be provisioned
|
# Only recover the admin account if a password should explicitly be provisioned
|
||||||
# for the account. Otherwise it is not needed for provisioning.
|
# for the account. Otherwise it is not needed for provisioning.
|
||||||
|
@ -141,8 +153,8 @@
|
||||||
# for the account we set it, otherwise we generate a new one because it is required
|
# for the account we set it, otherwise we generate a new one because it is required
|
||||||
# for provisioning.
|
# for provisioning.
|
||||||
recoverIdmAdmin =
|
recoverIdmAdmin =
|
||||||
if cfg.provision.idmAdminPasswordFile != null
|
if cfg.provision.idmAdminPasswordFile != null then
|
||||||
then ''
|
''
|
||||||
KANIDM_IDM_ADMIN_PASSWORD=$(< ${cfg.provision.idmAdminPasswordFile})
|
KANIDM_IDM_ADMIN_PASSWORD=$(< ${cfg.provision.idmAdminPasswordFile})
|
||||||
# We always reset the idm_admin account password if a desired password was specified.
|
# We always reset the idm_admin account password if a desired password was specified.
|
||||||
if ! KANIDM_RECOVER_ACCOUNT_PASSWORD=$KANIDM_IDM_ADMIN_PASSWORD ${cfg.package}/bin/kanidmd recover-account -c ${serverConfigFile} idm_admin --from-environment >/dev/null; then
|
if ! KANIDM_RECOVER_ACCOUNT_PASSWORD=$KANIDM_IDM_ADMIN_PASSWORD ${cfg.package}/bin/kanidmd recover-account -c ${serverConfigFile} idm_admin --from-environment >/dev/null; then
|
||||||
|
@ -150,7 +162,8 @@
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
''
|
''
|
||||||
else ''
|
else
|
||||||
|
''
|
||||||
# Recover idm_admin account
|
# Recover idm_admin account
|
||||||
if ! recover_out=$(${cfg.package}/bin/kanidmd recover-account -c ${serverConfigFile} idm_admin -o json); then
|
if ! recover_out=$(${cfg.package}/bin/kanidmd recover-account -c ${serverConfigFile} idm_admin -o json); then
|
||||||
echo "$recover_out" >&2
|
echo "$recover_out" >&2
|
||||||
|
@ -191,7 +204,8 @@
|
||||||
KANIDM_PROVISION_IDM_ADMIN_TOKEN=$KANIDM_IDM_ADMIN_PASSWORD \
|
KANIDM_PROVISION_IDM_ADMIN_TOKEN=$KANIDM_IDM_ADMIN_PASSWORD \
|
||||||
${getExe pkgs.kanidm-provision} --url "${cfg.provision.instanceUrl}" --state ${provisionStateJson} ${optionalString cfg.provision.acceptInvalidCerts "--accept-invalid-certs"}
|
${getExe pkgs.kanidm-provision} --url "${cfg.provision.instanceUrl}" --state ${provisionStateJson} ${optionalString cfg.provision.acceptInvalidCerts "--accept-invalid-certs"}
|
||||||
'';
|
'';
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
options.services.kanidm = {
|
options.services.kanidm = {
|
||||||
enableClient = mkEnableOption (mdDoc "the Kanidm client");
|
enableClient = mkEnableOption (mdDoc "the Kanidm client");
|
||||||
enableServer = mkEnableOption (mdDoc "the Kanidm server");
|
enableServer = mkEnableOption (mdDoc "the Kanidm server");
|
||||||
|
@ -253,12 +267,20 @@ in {
|
||||||
log_level = mkOption {
|
log_level = mkOption {
|
||||||
description = mdDoc "Log level of the server.";
|
description = mdDoc "Log level of the server.";
|
||||||
default = "info";
|
default = "info";
|
||||||
type = types.enum ["info" "debug" "trace"];
|
type = types.enum [
|
||||||
|
"info"
|
||||||
|
"debug"
|
||||||
|
"trace"
|
||||||
|
];
|
||||||
};
|
};
|
||||||
role = mkOption {
|
role = mkOption {
|
||||||
description = mdDoc "The role of this server. This affects the replication relationship and thereby available features.";
|
description = mdDoc "The role of this server. This affects the replication relationship and thereby available features.";
|
||||||
default = "WriteReplica";
|
default = "WriteReplica";
|
||||||
type = types.enum ["WriteReplica" "WriteReplicaNoUI" "ReadOnlyReplica"];
|
type = types.enum [
|
||||||
|
"WriteReplica"
|
||||||
|
"WriteReplicaNoUI"
|
||||||
|
"ReadOnlyReplica"
|
||||||
|
];
|
||||||
};
|
};
|
||||||
online_backup = {
|
online_backup = {
|
||||||
path = mkOption {
|
path = mkOption {
|
||||||
|
@ -388,7 +410,8 @@ in {
|
||||||
groups = mkOption {
|
groups = mkOption {
|
||||||
description = "Provisioning of kanidm groups";
|
description = "Provisioning of kanidm groups";
|
||||||
default = { };
|
default = { };
|
||||||
type = types.attrsOf (types.submodule (groupSubmod: {
|
type = types.attrsOf (
|
||||||
|
types.submodule (groupSubmod: {
|
||||||
options = {
|
options = {
|
||||||
present = mkPresentOption "group";
|
present = mkPresentOption "group";
|
||||||
|
|
||||||
|
@ -399,17 +422,23 @@ in {
|
||||||
default = [ ];
|
default = [ ];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
config.members = concatLists (flip mapAttrsToList cfg.provision.persons (
|
config.members = concatLists (
|
||||||
|
flip mapAttrsToList cfg.provision.persons (
|
||||||
person: personCfg:
|
person: personCfg:
|
||||||
optional (personCfg.present && builtins.elem groupSubmod.config._module.args.name personCfg.groups) person
|
optional (
|
||||||
));
|
personCfg.present && builtins.elem groupSubmod.config._module.args.name personCfg.groups
|
||||||
}));
|
) person
|
||||||
|
)
|
||||||
|
);
|
||||||
|
})
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
persons = mkOption {
|
persons = mkOption {
|
||||||
description = "Provisioning of kanidm persons";
|
description = "Provisioning of kanidm persons";
|
||||||
default = { };
|
default = { };
|
||||||
type = types.attrsOf (types.submodule {
|
type = types.attrsOf (
|
||||||
|
types.submodule {
|
||||||
options = {
|
options = {
|
||||||
present = mkPresentOption "person";
|
present = mkPresentOption "person";
|
||||||
|
|
||||||
|
@ -440,13 +469,15 @@ in {
|
||||||
default = [ ];
|
default = [ ];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
});
|
}
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
systems.oauth2 = mkOption {
|
systems.oauth2 = mkOption {
|
||||||
description = "Provisioning of oauth2 resource servers";
|
description = "Provisioning of oauth2 resource servers";
|
||||||
default = { };
|
default = { };
|
||||||
type = types.attrsOf (types.submodule {
|
type = types.attrsOf (
|
||||||
|
types.submodule {
|
||||||
options = {
|
options = {
|
||||||
present = mkPresentOption "oauth2 resource server";
|
present = mkPresentOption "oauth2 resource server";
|
||||||
|
|
||||||
|
@ -543,14 +574,19 @@ in {
|
||||||
See [Claim Maps](https://kanidm.github.io/kanidm/master/integrations/oauth2.html#custom-claim-maps) for more information.
|
See [Claim Maps](https://kanidm.github.io/kanidm/master/integrations/oauth2.html#custom-claim-maps) for more information.
|
||||||
'';
|
'';
|
||||||
default = { };
|
default = { };
|
||||||
type = types.attrsOf (types.submodule {
|
type = types.attrsOf (
|
||||||
|
types.submodule {
|
||||||
options = {
|
options = {
|
||||||
joinType = mkOption {
|
joinType = mkOption {
|
||||||
description = ''
|
description = ''
|
||||||
Determines how multiple values are joined to create the claim value.
|
Determines how multiple values are joined to create the claim value.
|
||||||
See [Claim Maps](https://kanidm.github.io/kanidm/master/integrations/oauth2.html#custom-claim-maps) for more information.
|
See [Claim Maps](https://kanidm.github.io/kanidm/master/integrations/oauth2.html#custom-claim-maps) for more information.
|
||||||
'';
|
'';
|
||||||
type = types.enum ["array" "csv" "ssv"];
|
type = types.enum [
|
||||||
|
"array"
|
||||||
|
"csv"
|
||||||
|
"ssv"
|
||||||
|
];
|
||||||
default = "array";
|
default = "array";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -560,54 +596,58 @@ in {
|
||||||
type = types.attrsOf (types.listOf types.str);
|
type = types.attrsOf (types.listOf types.str);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
});
|
}
|
||||||
|
);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
});
|
}
|
||||||
|
);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
config = mkIf (cfg.enableClient || cfg.enableServer || cfg.enablePam) {
|
config = mkIf (cfg.enableClient || cfg.enableServer || cfg.enablePam) {
|
||||||
assertions = let
|
assertions =
|
||||||
entityList = type: attrs: flip mapAttrsToList (filterPresent attrs) (name: _: {inherit type name;});
|
let
|
||||||
|
entityList =
|
||||||
|
type: attrs: flip mapAttrsToList (filterPresent attrs) (name: _: { inherit type name; });
|
||||||
entities =
|
entities =
|
||||||
entityList "group" cfg.provision.groups
|
entityList "group" cfg.provision.groups
|
||||||
++ entityList "person" cfg.provision.persons
|
++ entityList "person" cfg.provision.persons
|
||||||
++ entityList "oauth2" cfg.provision.systems.oauth2;
|
++ entityList "oauth2" cfg.provision.systems.oauth2;
|
||||||
|
|
||||||
# Accumulate entities by name. Track corresponding entity types for later duplicate check.
|
# Accumulate entities by name. Track corresponding entity types for later duplicate check.
|
||||||
entitiesByName =
|
entitiesByName = foldl' (
|
||||||
foldl' (
|
acc: { type, name }: acc // { ${name} = (acc.${name} or [ ]) ++ [ type ]; }
|
||||||
acc: {
|
) { } entities;
|
||||||
type,
|
|
||||||
name,
|
|
||||||
}:
|
|
||||||
acc
|
|
||||||
// {
|
|
||||||
${name} = (acc.${name} or []) ++ [type];
|
|
||||||
}
|
|
||||||
) {}
|
|
||||||
entities;
|
|
||||||
|
|
||||||
assertGroupsKnown = opt: groups: let
|
assertGroupsKnown =
|
||||||
|
opt: groups:
|
||||||
|
let
|
||||||
knownGroups = attrNames (filterPresent cfg.provision.groups);
|
knownGroups = attrNames (filterPresent cfg.provision.groups);
|
||||||
unknownGroups = subtractLists knownGroups groups;
|
unknownGroups = subtractLists knownGroups groups;
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
assertion = (cfg.enableServer && cfg.provision.enable) -> unknownGroups == [ ];
|
assertion = (cfg.enableServer && cfg.provision.enable) -> unknownGroups == [ ];
|
||||||
message = "${opt} refers to unknown groups: ${toString unknownGroups}";
|
message = "${opt} refers to unknown groups: ${toString unknownGroups}";
|
||||||
};
|
};
|
||||||
|
|
||||||
assertEntitiesKnown = opt: entities: let
|
assertEntitiesKnown =
|
||||||
|
opt: entities:
|
||||||
|
let
|
||||||
unknownEntities = subtractLists (attrNames entitiesByName) entities;
|
unknownEntities = subtractLists (attrNames entitiesByName) entities;
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
assertion = (cfg.enableServer && cfg.provision.enable) -> unknownEntities == [ ];
|
assertion = (cfg.enableServer && cfg.provision.enable) -> unknownEntities == [ ];
|
||||||
message = "${opt} refers to unknown entities: ${toString unknownEntities}";
|
message = "${opt} refers to unknown entities: ${toString unknownEntities}";
|
||||||
};
|
};
|
||||||
in
|
in
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
assertion = !cfg.enableServer || ((cfg.serverSettings.tls_chain or null) == null) || (!isStorePath cfg.serverSettings.tls_chain);
|
assertion =
|
||||||
|
!cfg.enableServer
|
||||||
|
|| ((cfg.serverSettings.tls_chain or null) == null)
|
||||||
|
|| (!isStorePath cfg.serverSettings.tls_chain);
|
||||||
message = ''
|
message = ''
|
||||||
<option>services.kanidm.serverSettings.tls_chain</option> points to
|
<option>services.kanidm.serverSettings.tls_chain</option> points to
|
||||||
a file in the Nix store. You should use a quoted absolute path to
|
a file in the Nix store. You should use a quoted absolute path to
|
||||||
|
@ -615,7 +655,10 @@ in {
|
||||||
'';
|
'';
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
assertion = !cfg.enableServer || ((cfg.serverSettings.tls_key or null) == null) || (!isStorePath cfg.serverSettings.tls_key);
|
assertion =
|
||||||
|
!cfg.enableServer
|
||||||
|
|| ((cfg.serverSettings.tls_key or null) == null)
|
||||||
|
|| (!isStorePath cfg.serverSettings.tls_key);
|
||||||
message = ''
|
message = ''
|
||||||
<option>services.kanidm.serverSettings.tls_key</option> points to
|
<option>services.kanidm.serverSettings.tls_key</option> points to
|
||||||
a file in the Nix store. You should use a quoted absolute path to
|
a file in the Nix store. You should use a quoted absolute path to
|
||||||
|
@ -639,9 +682,10 @@ in {
|
||||||
{
|
{
|
||||||
assertion =
|
assertion =
|
||||||
!cfg.enableServer
|
!cfg.enableServer
|
||||||
|| (cfg.serverSettings.domain
|
|| (
|
||||||
== null
|
cfg.serverSettings.domain == null
|
||||||
-> cfg.serverSettings.role == "WriteReplica" || cfg.serverSettings.role == "WriteReplicaNoUI");
|
-> cfg.serverSettings.role == "WriteReplica" || cfg.serverSettings.role == "WriteReplicaNoUI"
|
||||||
|
);
|
||||||
message = ''
|
message = ''
|
||||||
<option>services.kanidm.serverSettings.domain</option> can only be set if this instance
|
<option>services.kanidm.serverSettings.domain</option> can only be set if this instance
|
||||||
is not a ReadOnlyReplica. Otherwise the db would inherit it from
|
is not a ReadOnlyReplica. Otherwise the db would inherit it from
|
||||||
|
@ -655,13 +699,14 @@ in {
|
||||||
# If any secret is provisioned, the kanidm package must have some required patches applied to it
|
# If any secret is provisioned, the kanidm package must have some required patches applied to it
|
||||||
{
|
{
|
||||||
assertion =
|
assertion =
|
||||||
(cfg.provision.enable
|
(
|
||||||
|
cfg.provision.enable
|
||||||
&& (
|
&& (
|
||||||
cfg.provision.adminPasswordFile
|
cfg.provision.adminPasswordFile != null
|
||||||
!= null
|
|
||||||
|| cfg.provision.idmAdminPasswordFile != null
|
|| cfg.provision.idmAdminPasswordFile != null
|
||||||
|| any (x: x.basicSecretFile != null) (attrValues (filterPresent cfg.provision.systems.oauth2))
|
|| any (x: x.basicSecretFile != null) (attrValues (filterPresent cfg.provision.systems.oauth2))
|
||||||
))
|
)
|
||||||
|
)
|
||||||
-> cfg.package.enableSecretProvisioning;
|
-> cfg.package.enableSecretProvisioning;
|
||||||
message = ''
|
message = ''
|
||||||
Specifying an admin account password or oauth2 basicSecretFile requires kanidm to be built with the secret provisioning patches.
|
Specifying an admin account password or oauth2 basicSecretFile requires kanidm to be built with the secret provisioning patches.
|
||||||
|
@ -669,15 +714,20 @@ in {
|
||||||
'';
|
'';
|
||||||
}
|
}
|
||||||
# Entity names must be globally unique:
|
# Entity names must be globally unique:
|
||||||
(let
|
(
|
||||||
|
let
|
||||||
# Filter all names that occurred in more than one entity type.
|
# Filter all names that occurred in more than one entity type.
|
||||||
duplicateNames = filterAttrs (_: v: builtins.length v > 1) entitiesByName;
|
duplicateNames = filterAttrs (_: v: builtins.length v > 1) entitiesByName;
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
assertion = cfg.provision.enable -> duplicateNames == { };
|
assertion = cfg.provision.enable -> duplicateNames == { };
|
||||||
message = ''
|
message = ''
|
||||||
services.kanidm.provision requires all entity names (group, person, oauth2, ...) to be unique!
|
services.kanidm.provision requires all entity names (group, person, oauth2, ...) to be unique!
|
||||||
${concatLines (mapAttrsToList (name: xs: " - '${name}' used as: ${toString xs}") duplicateNames)}'';
|
${concatLines (
|
||||||
})
|
mapAttrsToList (name: xs: " - '${name}' used as: ${toString xs}") duplicateNames
|
||||||
|
)}'';
|
||||||
|
}
|
||||||
|
)
|
||||||
]
|
]
|
||||||
++ flip mapAttrsToList (filterPresent cfg.provision.persons) (
|
++ flip mapAttrsToList (filterPresent cfg.provision.persons) (
|
||||||
person: personCfg:
|
person: personCfg:
|
||||||
|
@ -687,36 +737,55 @@ in {
|
||||||
group: groupCfg:
|
group: groupCfg:
|
||||||
assertEntitiesKnown "services.kanidm.provision.groups.${group}.members" groupCfg.members
|
assertEntitiesKnown "services.kanidm.provision.groups.${group}.members" groupCfg.members
|
||||||
)
|
)
|
||||||
++ concatLists (flip mapAttrsToList (filterPresent cfg.provision.systems.oauth2) (
|
++ concatLists (
|
||||||
|
flip mapAttrsToList (filterPresent cfg.provision.systems.oauth2) (
|
||||||
oauth2: oauth2Cfg:
|
oauth2: oauth2Cfg:
|
||||||
[
|
[
|
||||||
(assertGroupsKnown "services.kanidm.provision.systems.oauth2.${oauth2}.scopeMaps" (attrNames oauth2Cfg.scopeMaps))
|
(assertGroupsKnown "services.kanidm.provision.systems.oauth2.${oauth2}.scopeMaps" (
|
||||||
(assertGroupsKnown "services.kanidm.provision.systems.oauth2.${oauth2}.supplementaryScopeMaps" (attrNames oauth2Cfg.supplementaryScopeMaps))
|
attrNames oauth2Cfg.scopeMaps
|
||||||
|
))
|
||||||
|
(assertGroupsKnown "services.kanidm.provision.systems.oauth2.${oauth2}.supplementaryScopeMaps" (
|
||||||
|
attrNames oauth2Cfg.supplementaryScopeMaps
|
||||||
|
))
|
||||||
]
|
]
|
||||||
++ concatLists (flip mapAttrsToList oauth2Cfg.claimMaps (claim: claimCfg: [
|
++ concatLists (
|
||||||
(assertGroupsKnown "services.kanidm.provision.systems.oauth2.${oauth2}.claimMaps.${claim}.valuesByGroup" (attrNames claimCfg.valuesByGroup))
|
flip mapAttrsToList oauth2Cfg.claimMaps (
|
||||||
|
claim: claimCfg: [
|
||||||
|
(assertGroupsKnown "services.kanidm.provision.systems.oauth2.${oauth2}.claimMaps.${claim}.valuesByGroup" (
|
||||||
|
attrNames claimCfg.valuesByGroup
|
||||||
|
))
|
||||||
# At least one group must map to a value in each claim map
|
# At least one group must map to a value in each claim map
|
||||||
{
|
{
|
||||||
assertion = (cfg.provision.enable && cfg.enableServer) -> any (xs: xs != []) (attrValues claimCfg.valuesByGroup);
|
assertion =
|
||||||
|
(cfg.provision.enable && cfg.enableServer)
|
||||||
|
-> any (xs: xs != [ ]) (attrValues claimCfg.valuesByGroup);
|
||||||
message = "services.kanidm.provision.systems.oauth2.${oauth2}.claimMaps.${claim} does not specify any values for any group";
|
message = "services.kanidm.provision.systems.oauth2.${oauth2}.claimMaps.${claim} does not specify any values for any group";
|
||||||
}
|
}
|
||||||
# Public clients cannot define a basic secret
|
# Public clients cannot define a basic secret
|
||||||
{
|
{
|
||||||
assertion = (cfg.provision.enable && cfg.enableServer && oauth2Cfg.public) -> oauth2Cfg.basicSecretFile == null;
|
assertion =
|
||||||
|
(cfg.provision.enable && cfg.enableServer && oauth2Cfg.public) -> oauth2Cfg.basicSecretFile == null;
|
||||||
message = "services.kanidm.provision.systems.oauth2.${oauth2} is a public client and thus cannot specify a basic secret";
|
message = "services.kanidm.provision.systems.oauth2.${oauth2} is a public client and thus cannot specify a basic secret";
|
||||||
}
|
}
|
||||||
# Public clients cannot disable PKCE
|
# Public clients cannot disable PKCE
|
||||||
{
|
{
|
||||||
assertion = (cfg.provision.enable && cfg.enableServer && oauth2Cfg.public) -> !oauth2Cfg.allowInsecureClientDisablePkce;
|
assertion =
|
||||||
|
(cfg.provision.enable && cfg.enableServer && oauth2Cfg.public)
|
||||||
|
-> !oauth2Cfg.allowInsecureClientDisablePkce;
|
||||||
message = "services.kanidm.provision.systems.oauth2.${oauth2} is a public client and thus cannot disable PKCE";
|
message = "services.kanidm.provision.systems.oauth2.${oauth2} is a public client and thus cannot disable PKCE";
|
||||||
}
|
}
|
||||||
# Non-public clients cannot enable localhost redirects
|
# Non-public clients cannot enable localhost redirects
|
||||||
{
|
{
|
||||||
assertion = (cfg.provision.enable && cfg.enableServer && !oauth2Cfg.public) -> !oauth2Cfg.enableLocalhostRedirects;
|
assertion =
|
||||||
|
(cfg.provision.enable && cfg.enableServer && !oauth2Cfg.public)
|
||||||
|
-> !oauth2Cfg.enableLocalhostRedirects;
|
||||||
message = "services.kanidm.provision.systems.oauth2.${oauth2} is a non-public client and thus cannot enable localhost redirects";
|
message = "services.kanidm.provision.systems.oauth2.${oauth2} is a non-public client and thus cannot enable localhost redirects";
|
||||||
}
|
}
|
||||||
]))
|
]
|
||||||
));
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
environment.systemPackages = mkIf cfg.enableClient [ cfg.package ];
|
environment.systemPackages = mkIf cfg.enableClient [ cfg.package ];
|
||||||
|
|
||||||
|
@ -734,10 +803,12 @@ in {
|
||||||
after = [ "network.target" ];
|
after = [ "network.target" ];
|
||||||
serviceConfig = mkMerge [
|
serviceConfig = mkMerge [
|
||||||
# Merge paths and ignore existing prefixes needs to sidestep mkMerge
|
# Merge paths and ignore existing prefixes needs to sidestep mkMerge
|
||||||
(defaultServiceConfig
|
(
|
||||||
|
defaultServiceConfig
|
||||||
// {
|
// {
|
||||||
BindReadOnlyPaths = mergePaths (defaultServiceConfig.BindReadOnlyPaths ++ certPaths);
|
BindReadOnlyPaths = mergePaths (defaultServiceConfig.BindReadOnlyPaths ++ certPaths);
|
||||||
})
|
}
|
||||||
|
)
|
||||||
{
|
{
|
||||||
StateDirectory = "kanidm";
|
StateDirectory = "kanidm";
|
||||||
StateDirectoryMode = "0700";
|
StateDirectoryMode = "0700";
|
||||||
|
@ -760,7 +831,11 @@ in {
|
||||||
PrivateUsers = mkForce false;
|
PrivateUsers = mkForce false;
|
||||||
# Port needs to be exposed to the host network
|
# Port needs to be exposed to the host network
|
||||||
PrivateNetwork = mkForce false;
|
PrivateNetwork = mkForce false;
|
||||||
RestrictAddressFamilies = ["AF_INET" "AF_INET6" "AF_UNIX"];
|
RestrictAddressFamilies = [
|
||||||
|
"AF_INET"
|
||||||
|
"AF_INET6"
|
||||||
|
"AF_UNIX"
|
||||||
|
];
|
||||||
TemporaryFileSystem = "/:ro";
|
TemporaryFileSystem = "/:ro";
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
@ -771,7 +846,10 @@ in {
|
||||||
description = "Kanidm PAM daemon";
|
description = "Kanidm PAM daemon";
|
||||||
wantedBy = [ "multi-user.target" ];
|
wantedBy = [ "multi-user.target" ];
|
||||||
after = [ "network.target" ];
|
after = [ "network.target" ];
|
||||||
restartTriggers = [unixConfigFile clientConfigFile];
|
restartTriggers = [
|
||||||
|
unixConfigFile
|
||||||
|
clientConfigFile
|
||||||
|
];
|
||||||
serviceConfig = mkMerge [
|
serviceConfig = mkMerge [
|
||||||
defaultServiceConfig
|
defaultServiceConfig
|
||||||
{
|
{
|
||||||
|
@ -796,7 +874,11 @@ in {
|
||||||
];
|
];
|
||||||
# Needs to connect to kanidmd
|
# Needs to connect to kanidmd
|
||||||
PrivateNetwork = mkForce false;
|
PrivateNetwork = mkForce false;
|
||||||
RestrictAddressFamilies = ["AF_INET" "AF_INET6" "AF_UNIX"];
|
RestrictAddressFamilies = [
|
||||||
|
"AF_INET"
|
||||||
|
"AF_INET6"
|
||||||
|
"AF_UNIX"
|
||||||
|
];
|
||||||
TemporaryFileSystem = "/:ro";
|
TemporaryFileSystem = "/:ro";
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
@ -806,9 +888,15 @@ in {
|
||||||
systemd.services.kanidm-unixd-tasks = mkIf cfg.enablePam {
|
systemd.services.kanidm-unixd-tasks = mkIf cfg.enablePam {
|
||||||
description = "Kanidm PAM home management daemon";
|
description = "Kanidm PAM home management daemon";
|
||||||
wantedBy = [ "multi-user.target" ];
|
wantedBy = [ "multi-user.target" ];
|
||||||
after = ["network.target" "kanidm-unixd.service"];
|
after = [
|
||||||
|
"network.target"
|
||||||
|
"kanidm-unixd.service"
|
||||||
|
];
|
||||||
partOf = [ "kanidm-unixd.service" ];
|
partOf = [ "kanidm-unixd.service" ];
|
||||||
restartTriggers = [unixConfigFile clientConfigFile];
|
restartTriggers = [
|
||||||
|
unixConfigFile
|
||||||
|
clientConfigFile
|
||||||
|
];
|
||||||
serviceConfig = {
|
serviceConfig = {
|
||||||
ExecStart = "${cfg.package}/bin/kanidm_unixd_tasks";
|
ExecStart = "${cfg.package}/bin/kanidm_unixd_tasks";
|
||||||
|
|
||||||
|
@ -828,7 +916,12 @@ in {
|
||||||
"/run/kanidm-unixd:/var/run/kanidm-unixd"
|
"/run/kanidm-unixd:/var/run/kanidm-unixd"
|
||||||
];
|
];
|
||||||
# CAP_DAC_OVERRIDE is needed to ignore ownership of unixd socket
|
# CAP_DAC_OVERRIDE is needed to ignore ownership of unixd socket
|
||||||
CapabilityBoundingSet = ["CAP_CHOWN" "CAP_FOWNER" "CAP_DAC_OVERRIDE" "CAP_DAC_READ_SEARCH"];
|
CapabilityBoundingSet = [
|
||||||
|
"CAP_CHOWN"
|
||||||
|
"CAP_FOWNER"
|
||||||
|
"CAP_DAC_OVERRIDE"
|
||||||
|
"CAP_DAC_READ_SEARCH"
|
||||||
|
];
|
||||||
IPAddressDeny = "any";
|
IPAddressDeny = "any";
|
||||||
# Need access to users
|
# Need access to users
|
||||||
PrivateUsers = false;
|
PrivateUsers = false;
|
||||||
|
@ -843,15 +936,11 @@ in {
|
||||||
|
|
||||||
# These paths are hardcoded
|
# These paths are hardcoded
|
||||||
environment.etc = mkMerge [
|
environment.etc = mkMerge [
|
||||||
(mkIf cfg.enableServer {
|
(mkIf cfg.enableServer { "kanidm/server.toml".source = serverConfigFile; })
|
||||||
"kanidm/server.toml".source = serverConfigFile;
|
|
||||||
})
|
|
||||||
(mkIf options.services.kanidm.clientSettings.isDefined {
|
(mkIf options.services.kanidm.clientSettings.isDefined {
|
||||||
"kanidm/config".source = clientConfigFile;
|
"kanidm/config".source = clientConfigFile;
|
||||||
})
|
})
|
||||||
(mkIf cfg.enablePam {
|
(mkIf cfg.enablePam { "kanidm/unixd".source = unixConfigFile; })
|
||||||
"kanidm/unixd".source = unixConfigFile;
|
|
||||||
})
|
|
||||||
];
|
];
|
||||||
|
|
||||||
system.nssModules = mkIf cfg.enablePam [ cfg.package ];
|
system.nssModules = mkIf cfg.enablePam [ cfg.package ];
|
||||||
|
@ -860,12 +949,8 @@ in {
|
||||||
system.nssDatabases.passwd = optional cfg.enablePam "kanidm";
|
system.nssDatabases.passwd = optional cfg.enablePam "kanidm";
|
||||||
|
|
||||||
users.groups = mkMerge [
|
users.groups = mkMerge [
|
||||||
(mkIf cfg.enableServer {
|
(mkIf cfg.enableServer { kanidm = { }; })
|
||||||
kanidm = {};
|
(mkIf cfg.enablePam { kanidm-unixd = { }; })
|
||||||
})
|
|
||||||
(mkIf cfg.enablePam {
|
|
||||||
kanidm-unixd = {};
|
|
||||||
})
|
|
||||||
];
|
];
|
||||||
users.users = mkMerge [
|
users.users = mkMerge [
|
||||||
(mkIf cfg.enableServer {
|
(mkIf cfg.enableServer {
|
||||||
|
@ -886,6 +971,10 @@ in {
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
meta.maintainers = with lib.maintainers; [erictapen Flakebi oddlama];
|
meta.maintainers = with lib.maintainers; [
|
||||||
|
erictapen
|
||||||
|
Flakebi
|
||||||
|
oddlama
|
||||||
|
];
|
||||||
meta.buildDocsInSandbox = false;
|
meta.buildDocsInSandbox = false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,8 @@
|
||||||
{lib, ...}: let
|
{ lib, ... }:
|
||||||
inherit
|
let
|
||||||
(lib)
|
inherit (lib) mkOption types;
|
||||||
mkOption
|
in
|
||||||
types
|
{
|
||||||
;
|
|
||||||
in {
|
|
||||||
options.node = {
|
options.node = {
|
||||||
secretsDir = mkOption {
|
secretsDir = mkOption {
|
||||||
description = "Path to the secrets directory for this node.";
|
description = "Path to the secrets directory for this node.";
|
||||||
|
|
|
@ -3,9 +3,9 @@
|
||||||
lib,
|
lib,
|
||||||
pkgs,
|
pkgs,
|
||||||
...
|
...
|
||||||
}: let
|
}:
|
||||||
inherit
|
let
|
||||||
(lib)
|
inherit (lib)
|
||||||
attrNames
|
attrNames
|
||||||
getExe
|
getExe
|
||||||
literalExpression
|
literalExpression
|
||||||
|
@ -22,8 +22,7 @@
|
||||||
versionOlder
|
versionOlder
|
||||||
;
|
;
|
||||||
|
|
||||||
inherit
|
inherit (lib.types)
|
||||||
(lib.types)
|
|
||||||
attrsOf
|
attrsOf
|
||||||
port
|
port
|
||||||
str
|
str
|
||||||
|
@ -36,7 +35,8 @@
|
||||||
kernel = config.boot.kernelPackages;
|
kernel = config.boot.kernelPackages;
|
||||||
|
|
||||||
cfg = config.services.netbird;
|
cfg = config.services.netbird;
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
meta.maintainers = with maintainers; [
|
meta.maintainers = with maintainers; [
|
||||||
misuzu
|
misuzu
|
||||||
thubrecht
|
thubrecht
|
||||||
|
@ -51,11 +51,8 @@ in {
|
||||||
tunnels = mkOption {
|
tunnels = mkOption {
|
||||||
type = attrsOf (
|
type = attrsOf (
|
||||||
submodule (
|
submodule (
|
||||||
|
{ name, config, ... }:
|
||||||
{
|
{
|
||||||
name,
|
|
||||||
config,
|
|
||||||
...
|
|
||||||
}: {
|
|
||||||
options = {
|
options = {
|
||||||
port = mkOption {
|
port = mkOption {
|
||||||
type = port;
|
type = port;
|
||||||
|
@ -132,8 +129,7 @@ in {
|
||||||
networking.dhcpcd.denyInterfaces = attrNames cfg.tunnels;
|
networking.dhcpcd.denyInterfaces = attrNames cfg.tunnels;
|
||||||
|
|
||||||
systemd.network.networks = mkIf config.networking.useNetworkd (
|
systemd.network.networks = mkIf config.networking.useNetworkd (
|
||||||
mapAttrs'
|
mapAttrs' (
|
||||||
(
|
|
||||||
name: _:
|
name: _:
|
||||||
nameValuePair "50-netbird-${name}" {
|
nameValuePair "50-netbird-${name}" {
|
||||||
matchConfig = {
|
matchConfig = {
|
||||||
|
@ -144,14 +140,12 @@ in {
|
||||||
ActivationPolicy = "manual";
|
ActivationPolicy = "manual";
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
)
|
) cfg.tunnels
|
||||||
cfg.tunnels
|
|
||||||
);
|
);
|
||||||
|
|
||||||
systemd.services =
|
systemd.services = mapAttrs' (
|
||||||
mapAttrs'
|
name:
|
||||||
(
|
{
|
||||||
name: {
|
|
||||||
environment,
|
environment,
|
||||||
stateDir,
|
stateDir,
|
||||||
environmentFile,
|
environmentFile,
|
||||||
|
@ -178,10 +172,7 @@ in {
|
||||||
StateDirectory = stateDir;
|
StateDirectory = stateDir;
|
||||||
StateDirectoryMode = "0700";
|
StateDirectoryMode = "0700";
|
||||||
WorkingDirectory = "/var/lib/${stateDir}";
|
WorkingDirectory = "/var/lib/${stateDir}";
|
||||||
RuntimeDirectoryMode =
|
RuntimeDirectoryMode = if userAccess then "0755" else "0750";
|
||||||
if userAccess
|
|
||||||
then "0755"
|
|
||||||
else "0750";
|
|
||||||
|
|
||||||
# hardening
|
# hardening
|
||||||
LockPersonality = true;
|
LockPersonality = true;
|
||||||
|
@ -222,8 +213,7 @@ in {
|
||||||
|
|
||||||
stopIfChanged = false;
|
stopIfChanged = false;
|
||||||
}
|
}
|
||||||
)
|
) cfg.tunnels;
|
||||||
cfg.tunnels;
|
|
||||||
})
|
})
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,9 +3,9 @@
|
||||||
inputs,
|
inputs,
|
||||||
config,
|
config,
|
||||||
...
|
...
|
||||||
}: let
|
}:
|
||||||
inherit
|
let
|
||||||
(lib)
|
inherit (lib)
|
||||||
mapAttrs
|
mapAttrs
|
||||||
assertMsg
|
assertMsg
|
||||||
types
|
types
|
||||||
|
@ -16,22 +16,25 @@
|
||||||
# If the given expression is a bare set, it will be wrapped in a function,
|
# If the given expression is a bare set, it will be wrapped in a function,
|
||||||
# so that the imported file can always be applied to the inputs, similar to
|
# so that the imported file can always be applied to the inputs, similar to
|
||||||
# how modules can be functions or sets.
|
# how modules can be functions or sets.
|
||||||
constSet = x:
|
constSet = x: if builtins.isAttrs x then (_: x) else x;
|
||||||
if builtins.isAttrs x
|
|
||||||
then (_: x)
|
|
||||||
else x;
|
|
||||||
|
|
||||||
rageImportEncrypted = assert assertMsg (builtins ? extraBuiltins.rageImportEncrypted) "The rageImportEncrypted extra plugin is not loaded";
|
rageImportEncrypted =
|
||||||
|
assert assertMsg (
|
||||||
|
builtins ? extraBuiltins.rageImportEncrypted
|
||||||
|
) "The rageImportEncrypted extra plugin is not loaded";
|
||||||
builtins.extraBuiltins.rageImportEncrypted;
|
builtins.extraBuiltins.rageImportEncrypted;
|
||||||
# This "imports" an encrypted .nix.age file
|
# This "imports" an encrypted .nix.age file
|
||||||
importEncrypted = path:
|
importEncrypted =
|
||||||
|
path:
|
||||||
constSet (
|
constSet (
|
||||||
if builtins.pathExists path
|
if builtins.pathExists path then
|
||||||
then rageImportEncrypted inputs.self.secretsConfig.masterIdentities path
|
rageImportEncrypted inputs.self.secretsConfig.masterIdentities path
|
||||||
else {}
|
else
|
||||||
|
{ }
|
||||||
);
|
);
|
||||||
cfg = config.secrets;
|
cfg = config.secrets;
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
options.secrets = {
|
options.secrets = {
|
||||||
defineRageBuiltins = mkOption {
|
defineRageBuiltins = mkOption {
|
||||||
default = true;
|
default = true;
|
||||||
|
@ -56,15 +59,16 @@ in {
|
||||||
|
|
||||||
secrets = mkOption {
|
secrets = mkOption {
|
||||||
readOnly = true;
|
readOnly = true;
|
||||||
default =
|
default = mapAttrs (_: x: importEncrypted x inputs) cfg.secretFiles;
|
||||||
mapAttrs (_: x: importEncrypted x inputs) cfg.secretFiles;
|
|
||||||
description = mdDoc ''
|
description = mdDoc ''
|
||||||
the secrets decrypted from the secretFiles
|
the secrets decrypted from the secretFiles
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
config.home-manager.sharedModules = [
|
config.home-manager.sharedModules = [
|
||||||
({config, ...}: {
|
(
|
||||||
|
{ config, ... }:
|
||||||
|
{
|
||||||
options = {
|
options = {
|
||||||
userSecretsFile = mkOption {
|
userSecretsFile = mkOption {
|
||||||
default = ../users/${config._module.args.name}/secrets.nix.age;
|
default = ../users/${config._module.args.name}/secrets.nix.age;
|
||||||
|
@ -78,6 +82,7 @@ in {
|
||||||
description = "User secrets";
|
description = "User secrets";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
})
|
}
|
||||||
|
)
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,9 +3,9 @@
|
||||||
config,
|
config,
|
||||||
lib,
|
lib,
|
||||||
...
|
...
|
||||||
}: let
|
}:
|
||||||
inherit
|
let
|
||||||
(lib)
|
inherit (lib)
|
||||||
mkOption
|
mkOption
|
||||||
types
|
types
|
||||||
flip
|
flip
|
||||||
|
@ -19,14 +19,18 @@
|
||||||
"x-systemd.device-timeout=5s"
|
"x-systemd.device-timeout=5s"
|
||||||
"x-systemd.mount-timeout=5s"
|
"x-systemd.mount-timeout=5s"
|
||||||
];
|
];
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
# Give users the ability to add their own smb shares
|
# Give users the ability to add their own smb shares
|
||||||
home-manager.sharedModules = [
|
home-manager.sharedModules = [
|
||||||
{
|
{
|
||||||
options.home.smb = mkOption {
|
options.home.smb = mkOption {
|
||||||
description = "Samba shares to be mountable under $HOME/smb";
|
description = "Samba shares to be mountable under $HOME/smb";
|
||||||
default = [ ];
|
default = [ ];
|
||||||
type = types.listOf (types.submodule ({config, ...}: {
|
type = types.listOf (
|
||||||
|
types.submodule (
|
||||||
|
{ config, ... }:
|
||||||
|
{
|
||||||
options = {
|
options = {
|
||||||
localPath = mkOption {
|
localPath = mkOption {
|
||||||
description = "The path under which the share will be mounted. Defaults to the remotePath";
|
description = "The path under which the share will be mounted. Defaults to the remotePath";
|
||||||
|
@ -53,7 +57,9 @@ in {
|
||||||
type = types.bool;
|
type = types.bool;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}));
|
}
|
||||||
|
)
|
||||||
|
);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
@ -61,22 +67,18 @@ in {
|
||||||
imports = [
|
imports = [
|
||||||
{
|
{
|
||||||
environment.systemPackages = [ pkgs.cifs-utils ];
|
environment.systemPackages = [ pkgs.cifs-utils ];
|
||||||
fileSystems =
|
fileSystems = mkMerge (
|
||||||
mkMerge
|
flip concatMap (attrNames config.home-manager.users) (
|
||||||
(
|
user:
|
||||||
flip
|
let
|
||||||
concatMap
|
|
||||||
(attrNames config.home-manager.users)
|
|
||||||
(
|
|
||||||
user: let
|
|
||||||
parentPath = "/home/${user}/smb";
|
parentPath = "/home/${user}/smb";
|
||||||
cfg = config.home-manager.users.${user}.home.smb;
|
cfg = config.home-manager.users.${user}.home.smb;
|
||||||
inherit (config.users.users.${user}) uid;
|
inherit (config.users.users.${user}) uid;
|
||||||
inherit (config.users.groups.${user}) gid;
|
inherit (config.users.groups.${user}) gid;
|
||||||
in
|
in
|
||||||
flip map cfg (
|
flip map cfg (cfg: {
|
||||||
cfg: {
|
"${parentPath}/${cfg.localPath}" =
|
||||||
"${parentPath}/${cfg.localPath}" = let
|
let
|
||||||
options =
|
options =
|
||||||
baseOptions
|
baseOptions
|
||||||
++ [
|
++ [
|
||||||
|
@ -87,13 +89,13 @@ in {
|
||||||
"credentials=${cfg.credentials}"
|
"credentials=${cfg.credentials}"
|
||||||
]
|
]
|
||||||
++ (optional (!cfg.automatic) "noauto");
|
++ (optional (!cfg.automatic) "noauto");
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
inherit options;
|
inherit options;
|
||||||
device = "//${cfg.address}/${cfg.remotePath}";
|
device = "//${cfg.address}/${cfg.remotePath}";
|
||||||
fsType = "cifs";
|
fsType = "cifs";
|
||||||
};
|
};
|
||||||
}
|
})
|
||||||
)
|
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
{
|
{ self, ... }:
|
||||||
self,
|
system:
|
||||||
...
|
let
|
||||||
}: system: let
|
|
||||||
pkgs = self.pkgs.${system};
|
pkgs = self.pkgs.${system};
|
||||||
in
|
in
|
||||||
pkgs.devshell.mkShell {
|
pkgs.devshell.mkShell {
|
||||||
|
|
|
@ -14,21 +14,40 @@
|
||||||
# '';
|
# '';
|
||||||
# }
|
# }
|
||||||
# ```
|
# ```
|
||||||
{exec, ...}: let
|
{ exec, ... }:
|
||||||
|
let
|
||||||
assertMsg = pred: msg: pred || builtins.throw msg;
|
assertMsg = pred: msg: pred || builtins.throw msg;
|
||||||
hasSuffix = suffix: content: let
|
hasSuffix =
|
||||||
|
suffix: content:
|
||||||
|
let
|
||||||
lenContent = builtins.stringLength content;
|
lenContent = builtins.stringLength content;
|
||||||
lenSuffix = builtins.stringLength suffix;
|
lenSuffix = builtins.stringLength suffix;
|
||||||
in
|
in
|
||||||
lenContent >= lenSuffix && builtins.substring (lenContent - lenSuffix) lenContent content == suffix;
|
lenContent >= lenSuffix && builtins.substring (lenContent - lenSuffix) lenContent content == suffix;
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
# Instead of calling rage directly here, we call a wrapper script that will cache the output
|
# Instead of calling rage directly here, we call a wrapper script that will cache the output
|
||||||
# in a predictable path in /tmp, which allows us to only require the password for each encrypted
|
# in a predictable path in /tmp, which allows us to only require the password for each encrypted
|
||||||
# file once.
|
# file once.
|
||||||
rageImportEncrypted = identities: nixFile:
|
rageImportEncrypted =
|
||||||
assert assertMsg (builtins.isPath nixFile) "The file to decrypt must be given as a path to prevent impurity.";
|
identities: nixFile:
|
||||||
assert assertMsg (hasSuffix ".nix.age" nixFile) "The content of the decrypted file must be a nix expression and should therefore end in .nix.age";
|
assert assertMsg (builtins.isPath nixFile)
|
||||||
exec ([./rage-decrypt-and-cache.sh nixFile] ++ identities);
|
"The file to decrypt must be given as a path to prevent impurity.";
|
||||||
|
assert assertMsg (hasSuffix ".nix.age" nixFile)
|
||||||
|
"The content of the decrypted file must be a nix expression and should therefore end in .nix.age";
|
||||||
|
exec (
|
||||||
|
[
|
||||||
|
./rage-decrypt-and-cache.sh
|
||||||
|
nixFile
|
||||||
|
]
|
||||||
|
++ identities
|
||||||
|
);
|
||||||
# currentSystem
|
# currentSystem
|
||||||
unsafeCurrentSystem = exec ["nix" "eval" "--impure" "--expr" "builtins.currentSystem"];
|
unsafeCurrentSystem = exec [
|
||||||
|
"nix"
|
||||||
|
"eval"
|
||||||
|
"--impure"
|
||||||
|
"--expr"
|
||||||
|
"builtins.currentSystem"
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,15 @@
|
||||||
{self, ...}: nodeName: nodeAttrs: let
|
{ self, ... }:
|
||||||
|
nodeName: nodeAttrs:
|
||||||
|
let
|
||||||
#FIXME inherit nodeAttrs. system;
|
#FIXME inherit nodeAttrs. system;
|
||||||
system = "x86_64-linux";
|
system = "x86_64-linux";
|
||||||
pkgs = self.pkgs.${system};
|
pkgs = self.pkgs.${system};
|
||||||
|
|
||||||
disko-script = pkgs.writeShellScriptBin "disko-script" "${nodeAttrs.config.system.build.diskoScript}";
|
disko-script = pkgs.writeShellScriptBin "disko-script" "${nodeAttrs.config.system.build.diskoScript
|
||||||
|
}";
|
||||||
disko-mount = pkgs.writeShellScriptBin "disko-mount" "${nodeAttrs.config.system.build.mountScript}";
|
disko-mount = pkgs.writeShellScriptBin "disko-mount" "${nodeAttrs.config.system.build.mountScript}";
|
||||||
disko-format = pkgs.writeShellScriptBin "disko-format" "${nodeAttrs.config.system.build.formatScript}";
|
disko-format = pkgs.writeShellScriptBin "disko-format" "${nodeAttrs.config.system.build.formatScript
|
||||||
|
}";
|
||||||
|
|
||||||
install-system = pkgs.writeShellScriptBin "install-system" ''
|
install-system = pkgs.writeShellScriptBin "install-system" ''
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
@ -28,7 +32,8 @@
|
||||||
install-system
|
install-system
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
# Everything required for the installer as a single package,
|
# Everything required for the installer as a single package,
|
||||||
# so it can be used from an existing live system by copying the derivation.
|
# so it can be used from an existing live system by copying the derivation.
|
||||||
packages.${system}.installer-package.${nodeName} = installer-package;
|
packages.${system}.installer-package.${nodeName} = installer-package;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
inputs: let
|
inputs:
|
||||||
|
let
|
||||||
inherit (inputs) self;
|
inherit (inputs) self;
|
||||||
inherit
|
inherit (inputs.nixpkgs.lib)
|
||||||
(inputs.nixpkgs.lib)
|
|
||||||
concatMapAttrs
|
concatMapAttrs
|
||||||
filterAttrs
|
filterAttrs
|
||||||
flip
|
flip
|
||||||
|
@ -12,7 +12,10 @@ inputs: let
|
||||||
;
|
;
|
||||||
|
|
||||||
# Creates a new nixosSystem with the correct specialArgs, pkgs and name definition
|
# Creates a new nixosSystem with the correct specialArgs, pkgs and name definition
|
||||||
mkHost = {minimal}: name: let
|
mkHost =
|
||||||
|
{ minimal }:
|
||||||
|
name:
|
||||||
|
let
|
||||||
pkgs = self.pkgs.x86_64-linux;
|
pkgs = self.pkgs.x86_64-linux;
|
||||||
in
|
in
|
||||||
nixosSystem {
|
nixosSystem {
|
||||||
|
@ -42,22 +45,30 @@ inputs: let
|
||||||
# to instanciate hosts correctly.
|
# to instanciate hosts correctly.
|
||||||
hosts = builtins.attrNames (filterAttrs (_: type: type == "directory") (builtins.readDir ../hosts));
|
hosts = builtins.attrNames (filterAttrs (_: type: type == "directory") (builtins.readDir ../hosts));
|
||||||
# Process each nixosHosts declaration and generatea nixosSystem definitions
|
# Process each nixosHosts declaration and generatea nixosSystem definitions
|
||||||
nixosConfigurations = genAttrs hosts (mkHost {minimal = false;});
|
nixosConfigurations = genAttrs hosts (mkHost {
|
||||||
minimalConfigurations = genAttrs hosts (mkHost {minimal = true;});
|
minimal = false;
|
||||||
|
});
|
||||||
|
minimalConfigurations = genAttrs hosts (mkHost {
|
||||||
|
minimal = true;
|
||||||
|
});
|
||||||
|
|
||||||
# True NixOS nodes can define additional guest nodes that are built
|
# True NixOS nodes can define additional guest nodes that are built
|
||||||
# together with it. We collect all defined guests from each node here
|
# together with it. We collect all defined guests from each node here
|
||||||
# to allow accessing any node via the unified attribute `nodes`.
|
# to allow accessing any node via the unified attribute `nodes`.
|
||||||
guestConfigurations = flip concatMapAttrs self.nixosConfigurations (_: node:
|
guestConfigurations = flip concatMapAttrs self.nixosConfigurations (
|
||||||
|
_: node:
|
||||||
flip mapAttrs' (node.config.guests or { }) (
|
flip mapAttrs' (node.config.guests or { }) (
|
||||||
guestName: guestDef:
|
guestName: guestDef:
|
||||||
nameValuePair guestDef.nodeName (
|
nameValuePair guestDef.nodeName (
|
||||||
if guestDef.backend == "microvm"
|
if guestDef.backend == "microvm" then
|
||||||
then node.config.microvm.vms.${guestName}.config
|
node.config.microvm.vms.${guestName}.config
|
||||||
else node.config.containers.${guestName}.nixosConfiguration
|
else
|
||||||
|
node.config.containers.${guestName}.nixosConfiguration
|
||||||
)
|
)
|
||||||
));
|
)
|
||||||
in {
|
);
|
||||||
|
in
|
||||||
|
{
|
||||||
inherit
|
inherit
|
||||||
hosts
|
hosts
|
||||||
nixosConfigurations
|
nixosConfigurations
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
{pkgs, ...}: {
|
{ pkgs, ... }:
|
||||||
|
{
|
||||||
nix.extraOptions = ''
|
nix.extraOptions = ''
|
||||||
experimental-features = nix-command flakes recursive-nix
|
experimental-features = nix-command flakes recursive-nix
|
||||||
'';
|
'';
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
{
|
{ pkgs, fetchurl }:
|
||||||
pkgs,
|
let
|
||||||
fetchurl,
|
|
||||||
}: let
|
|
||||||
name = "awakened-poe-trade";
|
name = "awakened-poe-trade";
|
||||||
version = "3.22.10003";
|
version = "3.22.10003";
|
||||||
description = "Path of Exile trading app for price checking";
|
description = "Path of Exile trading app for price checking";
|
||||||
|
|
|
@ -9,31 +9,35 @@
|
||||||
deploy = super.callPackage ./deploy.nix { };
|
deploy = super.callPackage ./deploy.nix { };
|
||||||
mongodb-bin = super.callPackage ./mongodb-bin.nix { };
|
mongodb-bin = super.callPackage ./mongodb-bin.nix { };
|
||||||
awakened-poe-trade = super.callPackage ./awakened-poe-trade.nix { };
|
awakened-poe-trade = super.callPackage ./awakened-poe-trade.nix { };
|
||||||
neovim-clean = super.neovim-unwrapped.overrideAttrs (_neovimFinal: neovimPrev: {
|
neovim-clean = super.neovim-unwrapped.overrideAttrs (
|
||||||
|
_neovimFinal: neovimPrev: {
|
||||||
nativeBuildInputs = (neovimPrev.nativeBuildInputs or [ ]) ++ [ super.makeWrapper ];
|
nativeBuildInputs = (neovimPrev.nativeBuildInputs or [ ]) ++ [ super.makeWrapper ];
|
||||||
postInstall =
|
postInstall =
|
||||||
(neovimPrev.postInstall or "")
|
(neovimPrev.postInstall or "")
|
||||||
+ ''
|
+ ''
|
||||||
wrapProgram $out/bin/nvim --add-flags "--clean"
|
wrapProgram $out/bin/nvim --add-flags "--clean"
|
||||||
'';
|
'';
|
||||||
});
|
}
|
||||||
kanidm = super.kanidm.overrideAttrs (old: let
|
);
|
||||||
|
kanidm = super.kanidm.overrideAttrs (
|
||||||
|
old:
|
||||||
|
let
|
||||||
provisionSrc = super.fetchFromGitHub {
|
provisionSrc = super.fetchFromGitHub {
|
||||||
owner = "oddlama";
|
owner = "oddlama";
|
||||||
repo = "kanidm-provision";
|
repo = "kanidm-provision";
|
||||||
rev = "v1.1.0";
|
rev = "v1.1.0";
|
||||||
hash = "sha256-pFOFFKh3la/sZGXj+pAM8x4SMeffvvbOvTjPeHS1XPU=";
|
hash = "sha256-pFOFFKh3la/sZGXj+pAM8x4SMeffvvbOvTjPeHS1XPU=";
|
||||||
};
|
};
|
||||||
in {
|
in
|
||||||
patches =
|
{
|
||||||
old.patches
|
patches = old.patches ++ [
|
||||||
++ [
|
|
||||||
"${provisionSrc}/patches/1.2.0-oauth2-basic-secret-modify.patch"
|
"${provisionSrc}/patches/1.2.0-oauth2-basic-secret-modify.patch"
|
||||||
"${provisionSrc}/patches/1.2.0-recover-account.patch"
|
"${provisionSrc}/patches/1.2.0-recover-account.patch"
|
||||||
];
|
];
|
||||||
passthru.enableSecretProvisioning = true;
|
passthru.enableSecretProvisioning = true;
|
||||||
doCheck = false;
|
doCheck = false;
|
||||||
});
|
}
|
||||||
|
);
|
||||||
kanidm-provision = super.callPackage ./kanidm-provision.nix { };
|
kanidm-provision = super.callPackage ./kanidm-provision.nix { };
|
||||||
})
|
})
|
||||||
]
|
]
|
||||||
|
|
|
@ -3,7 +3,8 @@
|
||||||
writeShellApplication,
|
writeShellApplication,
|
||||||
nvd,
|
nvd,
|
||||||
nix-output-monitor,
|
nix-output-monitor,
|
||||||
}: let
|
}:
|
||||||
|
let
|
||||||
deploy = writeShellApplication {
|
deploy = writeShellApplication {
|
||||||
name = "deploy";
|
name = "deploy";
|
||||||
text = ''
|
text = ''
|
||||||
|
@ -168,5 +169,8 @@
|
||||||
in
|
in
|
||||||
symlinkJoin {
|
symlinkJoin {
|
||||||
name = "deploy and build";
|
name = "deploy and build";
|
||||||
paths = [deploy build];
|
paths = [
|
||||||
|
deploy
|
||||||
|
build
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,8 @@
|
||||||
lib,
|
lib,
|
||||||
buildGoModule,
|
buildGoModule,
|
||||||
fetchFromGitHub,
|
fetchFromGitHub,
|
||||||
}: let
|
}:
|
||||||
|
let
|
||||||
pname = "homebox";
|
pname = "homebox";
|
||||||
version = "0.10.3";
|
version = "0.10.3";
|
||||||
src = "${fetchFromGitHub {
|
src = "${fetchFromGitHub {
|
||||||
|
|
|
@ -19,7 +19,10 @@ rustPlatform.buildRustPackage rec {
|
||||||
meta = with lib; {
|
meta = with lib; {
|
||||||
description = "A small utility to help with kanidm provisioning";
|
description = "A small utility to help with kanidm provisioning";
|
||||||
homepage = "https://github.com/oddlama/kanidm-provision";
|
homepage = "https://github.com/oddlama/kanidm-provision";
|
||||||
license = with licenses; [asl20 mit];
|
license = with licenses; [
|
||||||
|
asl20
|
||||||
|
mit
|
||||||
|
];
|
||||||
maintainers = with maintainers; [ oddlama ];
|
maintainers = with maintainers; [ oddlama ];
|
||||||
mainProgram = "kanidm-provision";
|
mainProgram = "kanidm-provision";
|
||||||
};
|
};
|
||||||
|
|
|
@ -11,27 +11,26 @@ stdenv.mkDerivation {
|
||||||
pname = "mongodb-bin";
|
pname = "mongodb-bin";
|
||||||
version = "1.0.0";
|
version = "1.0.0";
|
||||||
srcs = [
|
srcs = [
|
||||||
(
|
(fetchurl {
|
||||||
fetchurl {
|
|
||||||
url = "https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-ubuntu2204-6.0.14.tgz";
|
url = "https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-ubuntu2204-6.0.14.tgz";
|
||||||
hash = "sha256-1MW3pVIffdxq63gY64ozM1erWM2ou2L8T+MTfG+ZPLg=";
|
hash = "sha256-1MW3pVIffdxq63gY64ozM1erWM2ou2L8T+MTfG+ZPLg=";
|
||||||
}
|
})
|
||||||
)
|
(fetchurl {
|
||||||
(
|
|
||||||
fetchurl {
|
|
||||||
url = "https://downloads.mongodb.com/compass/mongosh-2.1.5-linux-x64.tgz";
|
url = "https://downloads.mongodb.com/compass/mongosh-2.1.5-linux-x64.tgz";
|
||||||
hash = "sha256-R1GGB0ZGqmpJtMUNF2+EJK6iNiChHuoHyOf2vKDcOKA=";
|
hash = "sha256-R1GGB0ZGqmpJtMUNF2+EJK6iNiChHuoHyOf2vKDcOKA=";
|
||||||
}
|
})
|
||||||
)
|
|
||||||
];
|
];
|
||||||
sourceRoot = ".";
|
sourceRoot = ".";
|
||||||
nativeBuildInputs = [
|
nativeBuildInputs = [ autoPatchelfHook ];
|
||||||
autoPatchelfHook
|
|
||||||
];
|
|
||||||
buildPhase = ''
|
buildPhase = ''
|
||||||
mkdir -p $out/bin
|
mkdir -p $out/bin
|
||||||
cp mongosh-2.1.5-linux-x64/bin/mongosh $out/bin/mongo
|
cp mongosh-2.1.5-linux-x64/bin/mongosh $out/bin/mongo
|
||||||
cp mongodb-linux-x86_64-ubuntu2204-6.0.14/bin/mongod $out/bin/mongod
|
cp mongodb-linux-x86_64-ubuntu2204-6.0.14/bin/mongod $out/bin/mongod
|
||||||
'';
|
'';
|
||||||
buildInputs = [openssl curl xz libgcc];
|
buildInputs = [
|
||||||
|
openssl
|
||||||
|
curl
|
||||||
|
xz
|
||||||
|
libgcc
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,10 @@ rustPlatform.buildRustPackage {
|
||||||
cargoHash = "sha256-9bhKtg2g5H4zGn7yVCjTazeXfeoKjtAKAlzkLkCraiw=";
|
cargoHash = "sha256-9bhKtg2g5H4zGn7yVCjTazeXfeoKjtAKAlzkLkCraiw=";
|
||||||
|
|
||||||
nativeBuildInputs = [ pkg-config ];
|
nativeBuildInputs = [ pkg-config ];
|
||||||
buildInputs = [openssl systemd];
|
buildInputs = [
|
||||||
|
openssl
|
||||||
|
systemd
|
||||||
|
];
|
||||||
|
|
||||||
meta = with lib; {
|
meta = with lib; {
|
||||||
description = "Nixpkgs pull request channel tracker";
|
description = "Nixpkgs pull request channel tracker";
|
||||||
|
|
|
@ -7,7 +7,12 @@
|
||||||
}:
|
}:
|
||||||
writeShellApplication {
|
writeShellApplication {
|
||||||
name = "clone-term";
|
name = "clone-term";
|
||||||
runtimeInputs = [ps procps xdotool jq];
|
runtimeInputs = [
|
||||||
|
ps
|
||||||
|
procps
|
||||||
|
xdotool
|
||||||
|
jq
|
||||||
|
];
|
||||||
text = ''
|
text = ''
|
||||||
|
|
||||||
if [[ ''${XDG_CURRENT_DESKTOP-} == sway ]]; then
|
if [[ ''${XDG_CURRENT_DESKTOP-} == sway ]]; then
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
{pkgs, ...}: {
|
{ pkgs, ... }:
|
||||||
|
{
|
||||||
home.packages = [
|
home.packages = [
|
||||||
pkgs.xclip
|
pkgs.xclip
|
||||||
pkgs.xdragon
|
pkgs.xdragon
|
||||||
|
|
|
@ -79,13 +79,15 @@ MOD: TAGS: pkgs:
|
||||||
"${MOD}-m " = "spawn ${pkgs.thunderbird}/bin/thunderbird";
|
"${MOD}-m " = "spawn ${pkgs.thunderbird}/bin/thunderbird";
|
||||||
"Menu" = "spawn rofi -show drun";
|
"Menu" = "spawn rofi -show drun";
|
||||||
}
|
}
|
||||||
// builtins.listToAttrs (map (x: {
|
// builtins.listToAttrs (
|
||||||
|
map (x: {
|
||||||
name = "${MOD}-${x}";
|
name = "${MOD}-${x}";
|
||||||
value = "use_index ${x}";
|
value = "use_index ${x}";
|
||||||
})
|
}) TAGS
|
||||||
TAGS)
|
)
|
||||||
// builtins.listToAttrs (map (x: {
|
// builtins.listToAttrs (
|
||||||
|
map (x: {
|
||||||
name = "${MOD}-Shift-${x}";
|
name = "${MOD}-Shift-${x}";
|
||||||
value = "move_index ${x}";
|
value = "move_index ${x}";
|
||||||
})
|
}) TAGS
|
||||||
TAGS)
|
)
|
||||||
|
|
|
@ -1,18 +1,14 @@
|
||||||
{
|
{ pkgs, lib, ... }:
|
||||||
pkgs,
|
let
|
||||||
lib,
|
|
||||||
...
|
|
||||||
}: let
|
|
||||||
# set the modifier key to WIN
|
# set the modifier key to WIN
|
||||||
MOD = "Super";
|
MOD = "Super";
|
||||||
#set the default resize step for herbstluft
|
#set the default resize step for herbstluft
|
||||||
TAGS = map toString (lib.lists.range 1 9);
|
TAGS = map toString (lib.lists.range 1 9);
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
xsession.windowManager.herbstluftwm = {
|
xsession.windowManager.herbstluftwm = {
|
||||||
enable = true;
|
enable = true;
|
||||||
package = pkgs.herbstluftwm.overrideAttrs (_finalAttrs: _previousAttrs: {
|
package = pkgs.herbstluftwm.overrideAttrs (_finalAttrs: _previousAttrs: { doCheck = false; });
|
||||||
doCheck = false;
|
|
||||||
});
|
|
||||||
extraConfig = ''
|
extraConfig = ''
|
||||||
herbstclient set auto_detect_monitors 1
|
herbstclient set auto_detect_monitors 1
|
||||||
killall polybar
|
killall polybar
|
||||||
|
|
|
@ -3,7 +3,8 @@
|
||||||
pkgs,
|
pkgs,
|
||||||
lib,
|
lib,
|
||||||
...
|
...
|
||||||
}: {
|
}:
|
||||||
|
{
|
||||||
# import shared sway config
|
# import shared sway config
|
||||||
imports = [ ../sway3.nix ];
|
imports = [ ../sway3.nix ];
|
||||||
systemd.user.services = {
|
systemd.user.services = {
|
||||||
|
@ -16,13 +17,17 @@
|
||||||
enableSystemdTarget = true;
|
enableSystemdTarget = true;
|
||||||
config = {
|
config = {
|
||||||
startup = [
|
startup = [
|
||||||
{command = "${pkgs.xorg.xrandr}/bin/xrandr --output DVI-D-0 --mode 1920x1080 --pos 0x0 --rate 60.00 --output DP-4 --mode 2560x1440 --pos 1920x720 --primary --rate 144 --output HDMI-0 --pos 0x1080 --rate 60.00";}
|
{
|
||||||
|
command = "${pkgs.xorg.xrandr}/bin/xrandr --output DVI-D-0 --mode 1920x1080 --pos 0x0 --rate 60.00 --output DP-4 --mode 2560x1440 --pos 1920x720 --primary --rate 144 --output HDMI-0 --pos 0x1080 --rate 60.00";
|
||||||
|
}
|
||||||
];
|
];
|
||||||
menu = "rofi -show drun";
|
menu = "rofi -show drun";
|
||||||
keybindings = let
|
keybindings =
|
||||||
|
let
|
||||||
cfg = config.xsession.windowManager.i3.config;
|
cfg = config.xsession.windowManager.i3.config;
|
||||||
maim = "${pkgs.maim}/bin/maim -qs -b 1 --hidecursor";
|
maim = "${pkgs.maim}/bin/maim -qs -b 1 --hidecursor";
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
"Menu" = "exec ${cfg.menu}";
|
"Menu" = "exec ${cfg.menu}";
|
||||||
"Ctrl+F9" = "exec ${config.xsession.wallpapers.script}";
|
"Ctrl+F9" = "exec ${config.xsession.wallpapers.script}";
|
||||||
"${cfg.modifier}+F12" =
|
"${cfg.modifier}+F12" =
|
||||||
|
@ -40,7 +45,8 @@
|
||||||
${maim} | ${pkgs.xclip}/bin/xclip -selection clipboard -t image/png
|
${maim} | ${pkgs.xclip}/bin/xclip -selection clipboard -t image/png
|
||||||
''
|
''
|
||||||
);
|
);
|
||||||
"${cfg.modifier}+F10" = let
|
"${cfg.modifier}+F10" =
|
||||||
|
let
|
||||||
nsend = ''
|
nsend = ''
|
||||||
${pkgs.libnotify}/bin/notify-send \
|
${pkgs.libnotify}/bin/notify-send \
|
||||||
-h string:category:Screenshot\
|
-h string:category:Screenshot\
|
||||||
|
|
|
@ -13,7 +13,8 @@
|
||||||
pkgs,
|
pkgs,
|
||||||
nixosConfig,
|
nixosConfig,
|
||||||
...
|
...
|
||||||
}: let
|
}:
|
||||||
|
let
|
||||||
color = {
|
color = {
|
||||||
shade1 = "#311B92";
|
shade1 = "#311B92";
|
||||||
shade2 = "#4527A0";
|
shade2 = "#4527A0";
|
||||||
|
@ -58,7 +59,8 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
fontsize = "9";
|
fontsize = "9";
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
services.polybar = {
|
services.polybar = {
|
||||||
enable = true;
|
enable = true;
|
||||||
|
|
||||||
|
@ -89,9 +91,24 @@ in {
|
||||||
};
|
};
|
||||||
|
|
||||||
modules = with lib; {
|
modules = with lib; {
|
||||||
left = concatStringsSep " " ["left1" "title" "left2"];
|
left = concatStringsSep " " [
|
||||||
|
"left1"
|
||||||
|
"title"
|
||||||
|
"left2"
|
||||||
|
];
|
||||||
center = concatStringsSep " " [ "workspaces" ];
|
center = concatStringsSep " " [ "workspaces" ];
|
||||||
right = concatStringsSep " " ["right5" "alsa" "right4" "battery" "right3" "network" "right2" "date" "right1" "keyboardswitcher"];
|
right = concatStringsSep " " [
|
||||||
|
"right5"
|
||||||
|
"alsa"
|
||||||
|
"right4"
|
||||||
|
"battery"
|
||||||
|
"right3"
|
||||||
|
"network"
|
||||||
|
"right2"
|
||||||
|
"date"
|
||||||
|
"right1"
|
||||||
|
"keyboardswitcher"
|
||||||
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
tray = {
|
tray = {
|
||||||
|
@ -108,9 +125,22 @@ in {
|
||||||
dpi = 96;
|
dpi = 96;
|
||||||
height = 22;
|
height = 22;
|
||||||
modules = with lib; {
|
modules = with lib; {
|
||||||
left = concatStringsSep " " ["left1" "title" "left2"];
|
left = concatStringsSep " " [
|
||||||
|
"left1"
|
||||||
|
"title"
|
||||||
|
"left2"
|
||||||
|
];
|
||||||
center = concatStringsSep " " [ "workspaces" ];
|
center = concatStringsSep " " [ "workspaces" ];
|
||||||
right = concatStringsSep " " ["right5" "alsa" "right3" "network" "right2" "date" "right1" "keyboardswitcher"];
|
right = concatStringsSep " " [
|
||||||
|
"right5"
|
||||||
|
"alsa"
|
||||||
|
"right3"
|
||||||
|
"network"
|
||||||
|
"right2"
|
||||||
|
"date"
|
||||||
|
"right1"
|
||||||
|
"keyboardswitcher"
|
||||||
|
];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
patricknix = {
|
patricknix = {
|
||||||
|
@ -120,14 +150,28 @@ in {
|
||||||
dpi = 144;
|
dpi = 144;
|
||||||
height = 33;
|
height = 33;
|
||||||
modules = with lib; {
|
modules = with lib; {
|
||||||
left = concatStringsSep " " ["left1" "title" "left2"];
|
left = concatStringsSep " " [
|
||||||
|
"left1"
|
||||||
|
"title"
|
||||||
|
"left2"
|
||||||
|
];
|
||||||
center = concatStringsSep " " [ "workspaces" ];
|
center = concatStringsSep " " [ "workspaces" ];
|
||||||
right = concatStringsSep " " ["right5" "alsa" "right4" "battery" "right3" "network" "right2" "date" "right1" "keyboardswitcher"];
|
right = concatStringsSep " " [
|
||||||
|
"right5"
|
||||||
|
"alsa"
|
||||||
|
"right4"
|
||||||
|
"battery"
|
||||||
|
"right3"
|
||||||
|
"network"
|
||||||
|
"right2"
|
||||||
|
"date"
|
||||||
|
"right1"
|
||||||
|
"keyboardswitcher"
|
||||||
|
];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
.${nixosConfig.node.name}
|
.${nixosConfig.node.name} or { };
|
||||||
or {};
|
|
||||||
|
|
||||||
# Functional MODULES
|
# Functional MODULES
|
||||||
|
|
||||||
|
@ -296,8 +340,7 @@ in {
|
||||||
interface = "wlan0";
|
interface = "wlan0";
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
.${nixosConfig.node.name}
|
.${nixosConfig.node.name} or { };
|
||||||
or {};
|
|
||||||
|
|
||||||
"module/keyboardswitcher" = {
|
"module/keyboardswitcher" = {
|
||||||
type = "custom/menu";
|
type = "custom/menu";
|
||||||
|
|
|
@ -1,8 +1,5 @@
|
||||||
|
{ pkgs, config, ... }:
|
||||||
{
|
{
|
||||||
pkgs,
|
|
||||||
config,
|
|
||||||
...
|
|
||||||
}: {
|
|
||||||
home = {
|
home = {
|
||||||
packages = with pkgs; [
|
packages = with pkgs; [
|
||||||
zathura
|
zathura
|
||||||
|
|
|
@ -32,63 +32,108 @@ let
|
||||||
trayOutput = "primary";
|
trayOutput = "primary";
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
floating.criteria = [
|
floating.criteria = [ { class = "Pavucontrol"; } ];
|
||||||
{class = "Pavucontrol";}
|
|
||||||
];
|
|
||||||
|
|
||||||
assigns = {
|
assigns = {
|
||||||
"2:d" = [
|
"2:d" = [ { class = "^firefox$"; } ];
|
||||||
{class = "^firefox$";}
|
"2:2" = [ { class = "^spotify$"; } ];
|
||||||
];
|
"3:u" = [ { class = "^thunderbird$"; } ];
|
||||||
"2:2" = [
|
|
||||||
{class = "^spotify$";}
|
|
||||||
];
|
|
||||||
"3:u" = [
|
|
||||||
{class = "^thunderbird$";}
|
|
||||||
];
|
|
||||||
"4:a" = [
|
"4:a" = [
|
||||||
{ class = "^bottles$"; }
|
{ class = "^bottles$"; }
|
||||||
{ class = "^steam$"; }
|
{ class = "^steam$"; }
|
||||||
{ class = "^prismlauncher$"; }
|
{ class = "^prismlauncher$"; }
|
||||||
];
|
];
|
||||||
"1:F1" = [
|
"1:F1" = [ { class = "^discord$"; } ];
|
||||||
{class = "^discord$";}
|
|
||||||
];
|
|
||||||
"2:F2" = [
|
"2:F2" = [
|
||||||
{ class = "^Signal$"; }
|
{ class = "^Signal$"; }
|
||||||
{ class = "^TelegramDesktop$"; }
|
{ class = "^TelegramDesktop$"; }
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
workspaceOutputAssign = let
|
workspaceOutputAssign =
|
||||||
output = out:
|
let
|
||||||
lib.lists.imap1 (i: x: {
|
output =
|
||||||
|
out:
|
||||||
|
lib.lists.imap1 (
|
||||||
|
i: x: {
|
||||||
workspace = "${toString i}:${x}";
|
workspace = "${toString i}:${x}";
|
||||||
output = out;
|
output = out;
|
||||||
});
|
}
|
||||||
|
);
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
"desktopnix" =
|
"desktopnix" =
|
||||||
output "HDMI-0" ["1" "2" "3" "4" "5" "6" "7" "8" "9"]
|
output "HDMI-0" [
|
||||||
++ output "DP-4" ["j" "d" "u" "a" "x" "p"]
|
"1"
|
||||||
++ output "DVI-D-0" ["F1" "F2" "F3" "F4"];
|
"2"
|
||||||
|
"3"
|
||||||
|
"4"
|
||||||
|
"5"
|
||||||
|
"6"
|
||||||
|
"7"
|
||||||
|
"8"
|
||||||
|
"9"
|
||||||
|
]
|
||||||
|
++ output "DP-4" [
|
||||||
|
"j"
|
||||||
|
"d"
|
||||||
|
"u"
|
||||||
|
"a"
|
||||||
|
"x"
|
||||||
|
"p"
|
||||||
|
]
|
||||||
|
++ output "DVI-D-0" [
|
||||||
|
"F1"
|
||||||
|
"F2"
|
||||||
|
"F3"
|
||||||
|
"F4"
|
||||||
|
];
|
||||||
"patricknix" =
|
"patricknix" =
|
||||||
output "eDP-1" ["1" "2" "3" "4" "5" "6" "7" "8" "9"]
|
output "eDP-1" [
|
||||||
++ output "DP-1" ["j" "d" "u" "a" "x" "p"];
|
"1"
|
||||||
"gojo" =
|
"2"
|
||||||
output "eDP-1" ["1" "2" "3" "4" "5" "6"];
|
"3"
|
||||||
|
"4"
|
||||||
|
"5"
|
||||||
|
"6"
|
||||||
|
"7"
|
||||||
|
"8"
|
||||||
|
"9"
|
||||||
|
]
|
||||||
|
++ output "DP-1" [
|
||||||
|
"j"
|
||||||
|
"d"
|
||||||
|
"u"
|
||||||
|
"a"
|
||||||
|
"x"
|
||||||
|
"p"
|
||||||
|
];
|
||||||
|
"gojo" = output "eDP-1" [
|
||||||
|
"1"
|
||||||
|
"2"
|
||||||
|
"3"
|
||||||
|
"4"
|
||||||
|
"5"
|
||||||
|
"6"
|
||||||
|
];
|
||||||
}
|
}
|
||||||
.${nixosConfig.node.name}
|
.${nixosConfig.node.name} or [ ];
|
||||||
or [];
|
|
||||||
|
|
||||||
keybindings =
|
keybindings =
|
||||||
(lib.attrsets.mergeAttrsList (map (x: (let
|
(lib.attrsets.mergeAttrsList (
|
||||||
|
map (
|
||||||
|
x:
|
||||||
|
(
|
||||||
|
let
|
||||||
key = lib.elemAt (lib.strings.splitString ":" x.workspace) 1;
|
key = lib.elemAt (lib.strings.splitString ":" x.workspace) 1;
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
"${modifier}+${key}" = "workspace ${x.workspace}";
|
"${modifier}+${key}" = "workspace ${x.workspace}";
|
||||||
"${modifier}+Shift+${key}" = "move container to workspace ${x.workspace}";
|
"${modifier}+Shift+${key}" = "move container to workspace ${x.workspace}";
|
||||||
}))
|
}
|
||||||
cfg.workspaceOutputAssign))
|
)
|
||||||
|
) cfg.workspaceOutputAssign
|
||||||
|
))
|
||||||
// {
|
// {
|
||||||
"${modifier}+t" = "exec ${terminal}";
|
"${modifier}+t" = "exec ${terminal}";
|
||||||
"${modifier}+b" = "exec firefox";
|
"${modifier}+b" = "exec firefox";
|
||||||
|
@ -137,7 +182,8 @@ let
|
||||||
"${modifier}+period" = "workspace next_on_output";
|
"${modifier}+period" = "workspace next_on_output";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
wayland.windowManager.sway.config = cfg;
|
wayland.windowManager.sway.config = cfg;
|
||||||
xsession.windowManager.i3.config = cfg;
|
xsession.windowManager.i3.config = cfg;
|
||||||
|
|
||||||
|
@ -146,9 +192,7 @@ in {
|
||||||
bars.main = {
|
bars.main = {
|
||||||
blocks =
|
blocks =
|
||||||
[
|
[
|
||||||
{
|
{ block = "net"; }
|
||||||
block = "net";
|
|
||||||
}
|
|
||||||
{
|
{
|
||||||
block = "cpu";
|
block = "cpu";
|
||||||
format = " $icon $utilization ";
|
format = " $icon $utilization ";
|
||||||
|
@ -158,7 +202,10 @@ in {
|
||||||
format = " $icon $utilization $memory $temperature ";
|
format = " $icon $utilization $memory $temperature ";
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
++ {"patricknix" = [{block = "battery";}];}.${nixosConfig.node.name} or []
|
++ {
|
||||||
|
"patricknix" = [ { block = "battery"; } ];
|
||||||
|
}
|
||||||
|
.${nixosConfig.node.name} or [ ]
|
||||||
++ [
|
++ [
|
||||||
{
|
{
|
||||||
block = "sound";
|
block = "sound";
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
{pkgs, ...}: {
|
{ pkgs, ... }:
|
||||||
|
{
|
||||||
imports = [
|
imports = [
|
||||||
../.
|
../.
|
||||||
./fuzzel.nix
|
./fuzzel.nix
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
{pkgs, ...}: {
|
{ pkgs, ... }:
|
||||||
|
{
|
||||||
stylix.targets.fuzzel.enable = true;
|
stylix.targets.fuzzel.enable = true;
|
||||||
home.packages = with pkgs; [
|
home.packages = with pkgs; [
|
||||||
(writeShellScriptBin "fuzzel" ''
|
(writeShellScriptBin "fuzzel" ''
|
||||||
|
|
|
@ -3,9 +3,9 @@
|
||||||
lib,
|
lib,
|
||||||
nixosConfig,
|
nixosConfig,
|
||||||
...
|
...
|
||||||
}: let
|
}:
|
||||||
inherit
|
let
|
||||||
(lib)
|
inherit (lib)
|
||||||
mkMerge
|
mkMerge
|
||||||
optionals
|
optionals
|
||||||
elem
|
elem
|
||||||
|
@ -46,7 +46,8 @@
|
||||||
# Listen to the Hyprland socket for events and process each line with the handle function
|
# Listen to the Hyprland socket for events and process each line with the handle function
|
||||||
${pkgs.socat}/bin/socat -U - UNIX-CONNECT:$XDG_RUNTIME_DIR/hypr/$HYPRLAND_INSTANCE_SIGNATURE/.socket2.sock | while read -r line; do handle "$line"; done
|
${pkgs.socat}/bin/socat -U - UNIX-CONNECT:$XDG_RUNTIME_DIR/hypr/$HYPRLAND_INSTANCE_SIGNATURE/.socket2.sock | while read -r line; do handle "$line"; done
|
||||||
'';
|
'';
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
wayland.windowManager.hyprland = {
|
wayland.windowManager.hyprland = {
|
||||||
enable = true;
|
enable = true;
|
||||||
settings = mkMerge [
|
settings = mkMerge [
|
||||||
|
@ -82,7 +83,8 @@ in {
|
||||||
focus_preferred_method = 1;
|
focus_preferred_method = 1;
|
||||||
workspace_center_on = 1;
|
workspace_center_on = 1;
|
||||||
};
|
};
|
||||||
bind = let
|
bind =
|
||||||
|
let
|
||||||
monitor_binds = {
|
monitor_binds = {
|
||||||
"1" = "j";
|
"1" = "j";
|
||||||
"2" = "d";
|
"2" = "d";
|
||||||
|
@ -146,12 +148,10 @@ in {
|
||||||
|
|
||||||
"SUPER + SHIFT,q,exit"
|
"SUPER + SHIFT,q,exit"
|
||||||
]
|
]
|
||||||
++ flip concatMap (map toString (lib.lists.range 1 9)) (
|
++ flip concatMap (map toString (lib.lists.range 1 9)) (x: [
|
||||||
x: [
|
|
||||||
"SUPER,${monitor_binds."${x}"},workspace,${x}"
|
"SUPER,${monitor_binds."${x}"},workspace,${x}"
|
||||||
"SUPER + SHIFT,${monitor_binds."${x}"},movetoworkspacesilent,${x}"
|
"SUPER + SHIFT,${monitor_binds."${x}"},movetoworkspacesilent,${x}"
|
||||||
]
|
]);
|
||||||
);
|
|
||||||
|
|
||||||
cursor.no_warps = true;
|
cursor.no_warps = true;
|
||||||
debug.disable_logs = false;
|
debug.disable_logs = false;
|
||||||
|
|
|
@ -1,8 +1,5 @@
|
||||||
|
{ config, nixosConfig, ... }:
|
||||||
{
|
{
|
||||||
config,
|
|
||||||
nixosConfig,
|
|
||||||
...
|
|
||||||
}: {
|
|
||||||
# import shared i3 config
|
# import shared i3 config
|
||||||
imports = [ ../sway3.nix ];
|
imports = [ ../sway3.nix ];
|
||||||
stylix.targets.sway.enable = true;
|
stylix.targets.sway.enable = true;
|
||||||
|
@ -42,9 +39,11 @@
|
||||||
map_to_output = "eDP-1";
|
map_to_output = "eDP-1";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
keybindings = let
|
keybindings =
|
||||||
|
let
|
||||||
cfg = config.wayland.windowManager.sway.config;
|
cfg = config.wayland.windowManager.sway.config;
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
"Menu" = "exec ${cfg.menu}";
|
"Menu" = "exec ${cfg.menu}";
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -80,11 +79,12 @@
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
.${nixosConfig.node.name}
|
.${nixosConfig.node.name} or { };
|
||||||
or {};
|
extraConfig =
|
||||||
extraConfig = let
|
let
|
||||||
cfg = config.wayland.windowManager.sway.config;
|
cfg = config.wayland.windowManager.sway.config;
|
||||||
in ''
|
in
|
||||||
|
''
|
||||||
bindgesture swipe:3:left workpace next
|
bindgesture swipe:3:left workpace next
|
||||||
bindgesture swipe:3:right workpace prev
|
bindgesture swipe:3:right workpace prev
|
||||||
bindgesture pinch:4:outward exec ${cfg.menu}
|
bindgesture pinch:4:outward exec ${cfg.menu}
|
||||||
|
|
|
@ -1,8 +1,5 @@
|
||||||
|
{ config, lib, ... }:
|
||||||
{
|
{
|
||||||
config,
|
|
||||||
lib,
|
|
||||||
...
|
|
||||||
}: {
|
|
||||||
services.swaync = {
|
services.swaync = {
|
||||||
enable = true;
|
enable = true;
|
||||||
settings = {
|
settings = {
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue