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