1
1
Fork 1
mirror of https://github.com/oddlama/nix-config.git synced 2025-10-10 14:50:40 +02:00

feat: remove old "freeform" globals and use new structured globals

This commit is contained in:
oddlama 2024-07-31 15:49:44 +02:00
parent 4e717fab96
commit a128dd5f40
No known key found for this signature in database
GPG key ID: 14EFE510775FE39A
35 changed files with 214 additions and 59 deletions

View file

@ -35,7 +35,7 @@ Make sure to utilize the github search if you know what you need!
- `pkgs/` Custom packages and scripts
- `secrets/` Global secrets and age identities
- `global.nix.age` Repository-wide global secrets. Available on nodes via the repo module as `config.repo.secrets.global`.
- `global.nix.age` Repository-wide global secrets. Will be merged with regular globals, structure is defined by `modules/globals.nix`.
- `backup.pub` Backup age-identity in case I ever lose my YubiKey or it breaks.
- `yk1-nix-rage.pub` Master YubiKey split-identity. Used as a key-grab.

View file

@ -1,5 +1,6 @@
{
config,
globals,
lib,
pkgs,
...
@ -8,7 +9,7 @@
boot = {
initrd.systemd = {
enable = true;
emergencyAccess = config.repo.secrets.global.root.hashedPassword;
emergencyAccess = globals.root.hashedPassword;
# TODO good idea? targets.emergency.wants = ["network.target" "sshd.service"];
extraBin.ip = "${pkgs.iproute2}/bin/ip";
extraBin.ping = "${pkgs.iputils}/bin/ping";

View file

@ -8,10 +8,7 @@
repo.secretFiles = let
local = config.node.secretsDir + "/local.nix.age";
in
{
global = ../secrets/global.nix.age;
}
// lib.optionalAttrs (lib.pathExists local) {inherit local;};
lib.optionalAttrs (lib.pathExists local) {inherit local;};
# Setup secret rekeying parameters
age.rekey = {

View file

@ -1,6 +1,20 @@
{config, ...}: let
{
inputs,
config,
lib,
...
}: let
inherit (config) globals;
# Try to access the extra builtin we loaded via nix-plugins.
# Throw an error if that doesn't exist.
rageImportEncrypted = assert lib.assertMsg (builtins ? extraBuiltins.rageImportEncrypted) "The extra builtin 'rageImportEncrypted' is not available, so repo.secrets cannot be decrypted. Did you forget to add nix-plugins and point it to `./nix/extra-builtins.nix` ?";
builtins.extraBuiltins.rageImportEncrypted;
in {
imports = [
(rageImportEncrypted inputs.self.secretsConfig.masterIdentities ./secrets/global.nix.age)
];
globals = {
net = {
home-wan = {

View file

@ -1,9 +1,10 @@
{
config,
globals,
lib,
...
}: let
mailDomains = config.repo.secrets.global.domains.mail;
mailDomains = globals.domains.mail;
primaryDomain = mailDomains.primary;
idmailDomain = "alias.${primaryDomain}";
in {

View file

@ -1,13 +1,14 @@
{
config,
globals,
lib,
...
}: let
icfg = config.repo.secrets.local.networking.interfaces.wan;
in {
networking.hostId = config.repo.secrets.local.networking.hostId;
networking.domain = config.repo.secrets.global.domains.mail.primary;
networking.hosts."127.0.0.1" = ["mx1.${config.repo.secrets.global.domains.mail.primary}"];
networking.domain = globals.domains.mail.primary;
networking.hosts."127.0.0.1" = ["mail.${globals.domains.mail.primary}"];
globals.monitoring.ping.envoy = {
hostv4 = lib.net.cidr.ip icfg.hostCidrv4;

View file

@ -1,10 +1,11 @@
{
config,
globals,
lib,
pkgs,
...
}: let
mailDomains = config.repo.secrets.global.domains.mail;
mailDomains = globals.domains.mail;
primaryDomain = mailDomains.primary;
stalwartDomain = "mail.${primaryDomain}";
dataDir = "/var/lib/stalwart-mail";

View file

@ -1,5 +1,6 @@
{
config,
globals,
lib,
pkgs,
...
@ -11,7 +12,7 @@
mkForce
;
hostDomain = config.repo.secrets.global.domains.me;
hostDomain = globals.domains.me;
coturnDomain = "coturn.${hostDomain}";
in {
age.secrets.coturn-password-netbird = {

View file

@ -26,7 +26,7 @@
services.nginx.enable = true;
services.nginx.recommendedSetup = true;
services.nginx.virtualHosts.${config.repo.secrets.global.domains.me} = {
services.nginx.virtualHosts.${globals.domains.me} = {
forceSSL = true;
useACMEWildcardHost = true;
locations."/".root = pkgs.runCommand "index.html" {} ''

View file

@ -1,12 +1,13 @@
{
config,
globals,
lib,
...
}: let
icfg = config.repo.secrets.local.networking.interfaces.wan;
in {
networking.hostId = config.repo.secrets.local.networking.hostId;
networking.domain = config.repo.secrets.global.domains.me;
networking.domain = globals.domains.me;
globals.monitoring.ping.sentinel = {
hostv4 = lib.net.cidr.ip icfg.hostCidrv4;

View file

@ -6,8 +6,8 @@
}: {
meta.oauth2-proxy = {
enable = true;
cookieDomain = config.repo.secrets.global.domains.me;
portalDomain = "oauth2.${config.repo.secrets.global.domains.me}";
cookieDomain = globals.domains.me;
portalDomain = "oauth2.${globals.domains.me}";
# TODO portal redirect to dashboard (in case someone clicks on kanidm "Web services")
};

View file

@ -1,5 +1,9 @@
{config, ...}: let
openWebuiDomain = "chat.${config.repo.secrets.global.domains.me}";
{
config,
globals,
...
}: let
openWebuiDomain = "chat.${globals.domains.me}";
in {
microvm.mem = 1024 * 16;
microvm.vcpu = 20;
@ -76,7 +80,7 @@ in {
oauth2 = {
enable = true;
allowedGroups = ["access_openwebui"];
X-Email = "\${upstream_http_x_auth_request_preferred_username}@${config.repo.secrets.global.domains.personal}";
X-Email = "\${upstream_http_x_auth_request_preferred_username}@${globals.domains.personal}";
};
extraConfig = ''
client_max_body_size 128M;

View file

@ -6,7 +6,7 @@
...
}: let
wardWebProxyCfg = nodes.ward-web-proxy.config;
grafanaDomain = "grafana.${config.repo.secrets.global.domains.me}";
grafanaDomain = "grafana.${globals.domains.me}";
in {
wireguard.proxy-sentinel = {
client.via = "sentinel";

View file

@ -7,7 +7,7 @@
}: let
sentinelCfg = nodes.sentinel.config;
wardWebProxyCfg = nodes.ward-web-proxy.config;
immichDomain = "immich.${config.repo.secrets.global.domains.me}";
immichDomain = "immich.${globals.domains.me}";
ipImmichMachineLearning = "10.89.0.10";
ipImmichPostgres = "10.89.0.12";

View file

@ -1,5 +1,6 @@
{
config,
globals,
lib,
nodes,
pkgs,
@ -7,7 +8,7 @@
}: let
sentinelCfg = nodes.sentinel.config;
wardCfg = nodes.ward.config;
influxdbDomain = "influxdb.${config.repo.secrets.global.domains.me}";
influxdbDomain = "influxdb.${globals.domains.me}";
influxdbPort = 8086;
in {
wireguard.proxy-sentinel = {

View file

@ -1,11 +1,12 @@
{
config,
globals,
nodes,
...
}: let
sentinelCfg = nodes.sentinel.config;
wardWebProxyCfg = nodes.ward-web-proxy.config;
lokiDomain = "loki.${config.repo.secrets.global.domains.me}";
lokiDomain = "loki.${globals.domains.me}";
in {
wireguard.proxy-sentinel = {
client.via = "sentinel";

View file

@ -1,13 +1,14 @@
# FIXME: todo: host the proxy on sentinel so the IPs are not lost in natting
{
config,
pkgs,
globals,
lib,
pkgs,
...
}: let
inherit (lib) getExe;
minecraftDomain = "mc.${config.repo.secrets.global.domains.me}";
minecraftDomain = "mc.${globals.domains.me}";
dataDir = "/var/lib/minecraft";
minecraft-attach = pkgs.writeShellApplication {

View file

@ -8,7 +8,7 @@
}: let
sentinelCfg = nodes.sentinel.config;
wardWebProxyCfg = nodes.ward-web-proxy.config;
paperlessDomain = "paperless.${config.repo.secrets.global.domains.me}";
paperlessDomain = "paperless.${globals.domains.me}";
paperlessBackupDir = "/var/cache/paperless-backup";
in {
microvm.mem = 1024 * 9;

View file

@ -5,7 +5,7 @@
pkgs,
...
}: let
adguardhomeDomain = "adguardhome.${config.repo.secrets.global.domains.me}";
adguardhomeDomain = "adguardhome.${globals.domains.me}";
in {
wireguard.proxy-sentinel = {
client.via = "sentinel";
@ -88,7 +88,7 @@ in {
# wireguard address for influxdb
{
inherit (globals.services.influxdb) domain;
answer = config.repo.secrets.global.domains.me;
answer = globals.domains.me;
}
]
# Use the local mirror-proxy for some services (not necessary, just for speed)
@ -102,8 +102,8 @@ in {
globals.services.influxdb.domain
globals.services.loki.domain
globals.services.paperless.domain
"home.${config.repo.secrets.global.domains.me}"
"fritzbox.${config.repo.secrets.global.domains.me}"
"home.${globals.domains.me}"
"fritzbox.${globals.domains.me}"
];
filters = [
{

View file

@ -6,7 +6,7 @@
pkgs,
...
}: let
forgejoDomain = "git.${config.repo.secrets.global.domains.me}";
forgejoDomain = "git.${globals.domains.me}";
in {
wireguard.proxy-sentinel = {
client.via = "sentinel";

View file

@ -3,8 +3,7 @@
globals,
...
}: let
inherit (config.repo.secrets.global) domains;
kanidmDomain = "auth.${domains.me}";
kanidmDomain = "auth.${globals.domains.me}";
kanidmPort = 8300;
mkRandomSecret = {
@ -108,7 +107,7 @@ in {
adminPasswordFile = config.age.secrets.kanidm-admin-password.path;
idmAdminPasswordFile = config.age.secrets.kanidm-idm-admin-password.path;
inherit (config.repo.secrets.global.kanidm) persons;
inherit (globals.kanidm) persons;
# Immich
groups."immich.access" = {};
@ -191,7 +190,7 @@ in {
groups."web-sentinel.openwebui" = {};
systems.oauth2.web-sentinel = {
displayName = "Web Sentinel";
originUrl = "https://oauth2.${domains.me}/";
originUrl = "https://oauth2.${globals.domains.me}/";
basicSecretFile = config.age.secrets.kanidm-oauth2-web-sentinel.path;
preferShortUsername = true;
scopeMaps."web-sentinel.access" = ["openid" "email"];

View file

@ -6,7 +6,7 @@
...
}: let
sentinelCfg = nodes.sentinel.config;
netbirdDomain = "netbird.${config.repo.secrets.global.domains.me}";
netbirdDomain = "netbird.${globals.domains.me}";
in {
wireguard.proxy-sentinel = {
client.via = "sentinel";
@ -48,8 +48,8 @@ in {
dashboard.settings.AUTH_AUTHORITY = "https://${globals.services.kanidm.domain}/oauth2/openid/netbird";
management = {
singleAccountModeDomain = "internal.${config.repo.secrets.global.domains.me}";
dnsDomain = "internal.${config.repo.secrets.global.domains.me}";
singleAccountModeDomain = "internal.${globals.domains.me}";
dnsDomain = "internal.${globals.domains.me}";
disableAnonymousMetrics = true;
oidcConfigEndpoint = "https://${globals.services.kanidm.domain}/oauth2/openid/netbird/.well-known/openid-configuration";
turnDomain = globals.services.coturn.domain;

View file

@ -1,5 +1,9 @@
{config, ...}: let
radicaleDomain = "radicale.${config.repo.secrets.global.domains.personal}";
{
config,
globals,
...
}: let
radicaleDomain = "radicale.${globals.domains.personal}";
in {
wireguard.proxy-sentinel = {
client.via = "sentinel";

View file

@ -1,9 +1,10 @@
{
config,
globals,
lib,
...
}: let
vaultwardenDomain = "pw.${config.repo.secrets.global.domains.personal}";
vaultwardenDomain = "pw.${globals.domains.personal}";
in {
wireguard.proxy-sentinel = {
client.via = "sentinel";

View file

@ -4,7 +4,7 @@
...
}: let
inherit (config.repo.secrets.local) acme;
fritzboxDomain = "fritzbox.${config.repo.secrets.global.domains.me}";
fritzboxDomain = "fritzbox.${globals.domains.me}";
in {
wireguard.proxy-home = {
client.via = "ward";

View file

@ -1,5 +1,4 @@
{
config,
lib,
globals,
utils,
@ -67,11 +66,11 @@ in {
ip-address = globals.net.home-lan.hosts.sire-samba.ipv4;
}
{
hw-address = config.repo.secrets.global.macs.wallbox;
hw-address = globals.macs.wallbox;
ip-address = globals.net.home-lan.hosts.wallbox.ipv4;
}
{
hw-address = config.repo.secrets.global.macs.home-assistant;
hw-address = globals.macs.home-assistant;
ip-address = globals.net.home-lan.hosts.home-assistant-temp.ipv4;
}
];

View file

@ -6,8 +6,8 @@
pkgs,
...
}: let
homeDomain = "home.${config.repo.secrets.global.domains.me}";
fritzboxDomain = "fritzbox.${config.repo.secrets.global.domains.me}";
homeDomain = "home.${globals.domains.me}";
fritzboxDomain = "fritzbox.${globals.domains.me}";
in {
wireguard.proxy-home.firewallRuleForNode.ward-web-proxy.allowedTCPPorts = [
config.services.home-assistant.config.http.server_port

View file

@ -1,5 +1,6 @@
{
config,
globals,
lib,
...
}: let
@ -19,13 +20,13 @@ in {
type = types.attrsOf (types.submodule (submod: {
options = {
name = mkOption {
description = "The name of the storage box to backup to. The box must be defined in the global secrets. Defaults to the attribute name.";
description = "The name of the storage box to backup to. The box must be defined in the globals. Defaults to the attribute name.";
default = submod.config._module.args.name;
type = types.str;
};
subuser = mkOption {
description = "The name of the storage box subuser as defined in the global secrets, mapping this user to a subuser id.";
description = "The name of the storage box subuser as defined in the globals, mapping this user to a subuser id.";
type = types.str;
};
@ -45,7 +46,7 @@ in {
(boxCfg: {
"storage-box-${boxCfg.name}" = {
hetznerStorageBox = let
box = config.repo.secrets.global.hetzner.storageboxes.${boxCfg.name};
box = globals.hetzner.storageboxes.${boxCfg.name};
in {
enable = true;
inherit (box) mainUser;

View file

@ -21,6 +21,24 @@ in {
default = {};
type = types.submodule {
options = {
root = {
hashedPassword = mkOption {
type = types.str;
description = "My root user's password hash.";
};
};
myuser = {
name = mkOption {
type = types.str;
description = "My unix username.";
};
hashedPassword = mkOption {
type = types.str;
description = "My unix password hash.";
};
};
net = mkOption {
type = types.attrsOf (types.submodule (netSubmod: {
options = {
@ -195,6 +213,97 @@ in {
});
};
};
domains = {
me = mkOption {
type = types.str;
description = "My main domain.";
};
personal = mkOption {
type = types.str;
description = "My personal domain.";
};
mail.all = mkOption {
type = types.listOf types.str;
description = "All domains to configure on the mail server.";
};
mail.primary = mkOption {
type = types.str;
description = "The primary mail domain.";
};
};
macs = mkOption {
default = {};
type = types.attrsOf types.str;
description = "Known MAC addresses for external devices.";
};
hetzner.storageboxes = mkOption {
default = {};
description = "Storage box configurations.";
type = types.attrsOf (types.submodule {
options = {
mainUser = mkOption {
type = types.str;
description = "Main username for the storagebox";
};
users = mkOption {
default = {};
description = "Subuser configurations.";
type = types.attrsOf (types.submodule {
options = {
subUid = mkOption {
type = types.int;
description = "The subuser id";
};
path = mkOption {
type = types.str;
description = "The home path for this subuser (i.e. backup destination)";
};
};
});
};
};
});
};
# Mirror of the kanidm.persons option.
kanidm.persons = mkOption {
description = "Provisioning of kanidm persons";
default = {};
type = types.attrsOf (types.submodule {
options = {
displayName = mkOption {
description = "Display name";
type = types.str;
};
legalName = mkOption {
description = "Full legal name";
type = types.nullOr types.str;
default = null;
};
mailAddresses = mkOption {
description = "Mail addresses. First given address is considered the primary address.";
type = types.listOf types.str;
default = [];
};
groups = mkOption {
description = "List of groups this person should belong to.";
type = types.listOf types.str;
default = [];
};
};
});
};
};
};
};

View file

@ -9,6 +9,7 @@
prefix = ["globals"];
specialArgs = {
inherit (inputs.self.pkgs.x86_64-linux) lib;
inherit inputs;
};
modules = [
../modules/globals.nix
@ -27,7 +28,18 @@
in {
# Make sure the keys of this attrset are trivially evaluatable to avoid infinite recursion,
# therefore we inherit relevant attributes from the config.
inherit (globalsSystem.config.globals) net services monitoring;
inherit
(globalsSystem.config.globals)
domains
hetzner
kanidm
macs
monitoring
myuser
net
root
services
;
};
};
}

View file

@ -1,9 +1,13 @@
{inputs, ...}: {
perSystem = {pkgs, ...}: {
perSystem = {
config,
pkgs,
...
}: {
apps.setupHetznerStorageBoxes = import (inputs.nixos-extra-modules + "/apps/setup-hetzner-storage-boxes.nix") {
inherit pkgs;
nixosConfigurations = inputs.self.nodes;
decryptIdentity = builtins.head inputs.self.secretsConfig.masterIdentities;
decryptIdentity = builtins.head config.secretsConfig.masterIdentities;
};
};
}

Binary file not shown.

View file

@ -4,8 +4,8 @@
settings = {
add_newline = false;
format = lib.concatStrings [
"$username"
"$hostname"
"($username )"
"($hostname )"
"$directory "
"($git_branch )"
"($git_commit )"

View file

@ -1,17 +1,18 @@
{
config,
lib,
globals,
pkgs,
minimal,
...
}: let
myuser = config.repo.secrets.global.myuser.name;
myuser = globals.myuser.name;
in
lib.optionalAttrs (!minimal) {
users.groups.${myuser}.gid = config.users.users.${myuser}.uid;
users.users.${myuser} = {
uid = 1000;
inherit (config.repo.secrets.global.myuser) hashedPassword;
inherit (globals.myuser) hashedPassword;
createHome = true;
group = myuser;
extraGroups = ["wheel" "input" "video"];

View file

@ -1,10 +1,11 @@
{
config,
globals,
pkgs,
...
}: {
users.users.root = {
inherit (config.repo.secrets.global.root) hashedPassword;
inherit (globals.root) hashedPassword;
openssh.authorizedKeys.keys = ["ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIA5Uq+CDy5Pmt3If5M6d8K/Q7HArU6sZ7sgoj3T521Wm"];
shell = pkgs.zsh;
};