Updated mkNginxVHosts to use per-domain certificates (enableACME) instead of shared wildcard certificates (useACMEHost). Each service now requests its own certificate, avoiding conflicts between hosts and following the principle of least privilege. Removed wildcard certificate configuration from both alexandria and trantor. Each host now only obtains certificates for domains it actually serves: - Alexandria: pass.baduhai.dev, cloud.baduhai.dev, jellyfin.baduhai.dev - Trantor: git.baduhai.dev
221 lines
6.1 KiB
Nix
221 lines
6.1 KiB
Nix
{ inputs, lib }:
|
|
|
|
let
|
|
inherit (inputs)
|
|
self
|
|
nixpkgs
|
|
nixpkgs-stable
|
|
home-manager
|
|
agenix
|
|
;
|
|
|
|
# Import shared service definitions
|
|
sharedServices = import ./shared/services.nix;
|
|
in
|
|
|
|
{
|
|
# Re-export shared services for use in host configs
|
|
inherit (sharedServices) services;
|
|
# Tag-based host configuration system
|
|
mkHost =
|
|
{
|
|
hostname,
|
|
tags ? [ ],
|
|
system ? "x86_64-linux",
|
|
extraModules ? [ ],
|
|
}:
|
|
let
|
|
# Validate that server and desktop tags are mutually exclusive
|
|
hasServer = builtins.elem "server" tags;
|
|
hasDesktop = builtins.elem "desktop" tags;
|
|
|
|
# Always include "common" tag implicitly
|
|
allTags =
|
|
if hasServer && hasDesktop then
|
|
throw "Error: 'server' and 'desktop' tags are mutually exclusive for host '${hostname}'"
|
|
else
|
|
[ "common" ] ++ tags;
|
|
|
|
# Choose nixpkgs based on server tag
|
|
pkgs = if builtins.elem "server" allTags then nixpkgs-stable else nixpkgs;
|
|
|
|
# Tag-specific modules: each tag can be either:
|
|
# 1. A file: hosts/modules/${tag}.nix
|
|
# 2. A directory: hosts/modules/${tag}/*.nix (all .nix files imported)
|
|
tagModuleFiles = builtins.concatMap (
|
|
tag:
|
|
let
|
|
filePath = ./hosts/modules/${tag}.nix;
|
|
dirPath = ./hosts/modules/${tag};
|
|
in
|
|
# Check if it's a file first
|
|
if builtins.pathExists filePath then
|
|
[ filePath ]
|
|
# Then check if it's a directory
|
|
else if builtins.pathExists dirPath then
|
|
let
|
|
entries = builtins.readDir dirPath;
|
|
nixFiles = pkgs.lib.filterAttrs (
|
|
name: type: type == "regular" && pkgs.lib.hasSuffix ".nix" name
|
|
) entries;
|
|
in
|
|
map (name: dirPath + "/${name}") (builtins.attrNames nixFiles)
|
|
else
|
|
[ ]
|
|
) allTags;
|
|
|
|
# Automatically import all .nix files from hosts/${hostname}/
|
|
hostModulePath = ./hosts/${hostname};
|
|
hostModuleFiles =
|
|
if builtins.pathExists hostModulePath then
|
|
let
|
|
entries = builtins.readDir hostModulePath;
|
|
nixFiles = pkgs.lib.filterAttrs (
|
|
name: type: type == "regular" && pkgs.lib.hasSuffix ".nix" name && name != "${hostname}.nix"
|
|
) entries;
|
|
in
|
|
map (name: hostModulePath + "/${name}") (builtins.attrNames nixFiles)
|
|
else
|
|
[ ];
|
|
|
|
# Combine all modules
|
|
allModules = [
|
|
agenix.nixosModules.default
|
|
{
|
|
networking.hostName = hostname;
|
|
nix.nixPath = [ "nixos-config=${self.outPath}/nixosConfigurations/${hostname}" ];
|
|
nixpkgs.overlays = [
|
|
agenix.overlays.default
|
|
self.overlays.default
|
|
];
|
|
}
|
|
]
|
|
++ tagModuleFiles
|
|
++ hostModuleFiles
|
|
++ extraModules;
|
|
in
|
|
pkgs.lib.nixosSystem {
|
|
inherit system;
|
|
specialArgs = {
|
|
inherit inputs;
|
|
hostTags = allTags;
|
|
};
|
|
modules = allModules;
|
|
};
|
|
|
|
# Tag-based user configuration system
|
|
mkHome =
|
|
{
|
|
username,
|
|
hostname ? null,
|
|
homeDirectory ? "/home/${username}",
|
|
tags ? [ ],
|
|
extraModules ? [ ],
|
|
}:
|
|
let
|
|
pkgs = nixpkgs.legacyPackages.x86_64-linux;
|
|
|
|
# Always include "common" tag implicitly
|
|
allTags = [ "common" ] ++ tags;
|
|
|
|
# Tag-specific modules: each tag maps to users/modules/${tag}.nix if it exists
|
|
tagModuleFiles = builtins.concatMap (
|
|
tag:
|
|
let
|
|
filePath = ./users/modules/${tag}.nix;
|
|
dirPath = ./users/modules/${tag};
|
|
in
|
|
# Check if it's a file first
|
|
if builtins.pathExists filePath then
|
|
[ filePath ]
|
|
# Then check if it's a directory
|
|
else if builtins.pathExists dirPath then
|
|
let
|
|
entries = builtins.readDir dirPath;
|
|
nixFiles = pkgs.lib.filterAttrs (
|
|
name: type: type == "regular" && pkgs.lib.hasSuffix ".nix" name
|
|
) entries;
|
|
in
|
|
map (name: dirPath + "/${name}") (builtins.attrNames nixFiles)
|
|
else
|
|
[ ]
|
|
) allTags;
|
|
|
|
# Automatically import all .nix files from users/${username}/
|
|
userModulePath = ./users/${username};
|
|
userModuleFiles =
|
|
if builtins.pathExists userModulePath then
|
|
let
|
|
entries = builtins.readDir userModulePath;
|
|
nixFiles = pkgs.lib.filterAttrs (
|
|
name: type: type == "regular" && pkgs.lib.hasSuffix ".nix" name
|
|
) entries;
|
|
in
|
|
map (name: userModulePath + "/${name}") (builtins.attrNames nixFiles)
|
|
else
|
|
[ ];
|
|
|
|
# Combine all modules
|
|
allModules = [
|
|
{
|
|
home = {
|
|
inherit username homeDirectory;
|
|
stateVersion = "22.05";
|
|
};
|
|
}
|
|
]
|
|
++ tagModuleFiles
|
|
++ userModuleFiles
|
|
++ extraModules;
|
|
in
|
|
home-manager.lib.homeManagerConfiguration {
|
|
inherit pkgs;
|
|
extraSpecialArgs = {
|
|
inherit inputs hostname;
|
|
userTags = allTags;
|
|
};
|
|
modules = allModules ++ [
|
|
{
|
|
nixpkgs.overlays = [ self.overlays.default ];
|
|
}
|
|
];
|
|
};
|
|
|
|
# Nginx virtual host utilities
|
|
mkNginxVHosts =
|
|
{ domains }:
|
|
let
|
|
commonVHostConfig = {
|
|
enableACME = true;
|
|
forceSSL = true;
|
|
kTLS = true;
|
|
};
|
|
in
|
|
lib.mapAttrs (_: lib.recursiveUpdate commonVHostConfig) domains;
|
|
|
|
# Split DNS utilities for unbound
|
|
# Generates unbound view config from a list of DNS entries
|
|
mkSplitDNS =
|
|
entries:
|
|
let
|
|
# Generate local-data entries for all domains
|
|
tailscaleData = map (e: ''"${e.domain}. IN A ${e.tailscaleIP}"'') entries;
|
|
lanData = map (e: ''"${e.domain}. IN A ${e.lanIP}"'') entries;
|
|
in
|
|
[
|
|
# Single Tailscale view with all domains
|
|
{
|
|
name = "tailscale";
|
|
view-first = true;
|
|
local-zone = ''"baduhai.dev." transparent'';
|
|
local-data = tailscaleData;
|
|
}
|
|
# Single LAN view with all domains
|
|
{
|
|
name = "lan";
|
|
view-first = true;
|
|
local-zone = ''"baduhai.dev." transparent'';
|
|
local-data = lanData;
|
|
}
|
|
];
|
|
}
|