Files
nix-dotfiles/modules/system/users.nix
T
emmatherockandClaude Sonnet 5 42e60a3bb5 feat(hosts): make config multi-host and add vps host
Parametrize networking, users, and containers modules under
myNetworking/myUsers/myContainers so both hosts share the same logic
instead of duplicating it, and split desktop/server module imports
into modules/profiles/. Adds hosts/vps (not installed yet, hardware
config and bootloader device are placeholders) to run Traefik,
Headscale, Headplane, and Gitea via a combined Docker Compose stack.

Wires up agenix for secrets and migrates miku-homelab's WireGuard
private key off a plain filesystem path into an encrypted
secrets/miku-homelab-wg.age. The vps side of that tunnel still needs
its own key generated and encrypted after install.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-12 00:07:55 -03:00

89 lines
2.4 KiB
Nix

{ lib, pkgs, config, ... }:
let
cfg = config.myUsers;
adminOpts = { ... }: {
options = {
description = lib.mkOption {
type = lib.types.str;
description = "Human-readable description (full name) for this user.";
};
shell = lib.mkOption {
type = lib.types.package;
default = pkgs.bash;
description = "Login shell package for this user.";
};
extraGroups = lib.mkOption {
type = lib.types.listOf lib.types.str;
default = [ ];
description = "Extra groups this user belongs to.";
};
authorizedKeys = lib.mkOption {
type = lib.types.listOf lib.types.str;
default = [ ];
description = "OpenSSH public keys authorized to log in as this user.";
};
};
};
serviceUserOpts = { ... }: {
options = {
description = lib.mkOption {
type = lib.types.str;
description = "Human-readable description for this service user.";
};
group = lib.mkOption {
type = lib.types.str;
description = "Primary group for this service user.";
};
createHome = lib.mkOption {
type = lib.types.bool;
default = false;
description = "Whether to create a home directory for this service user.";
};
};
};
in
{
options.myUsers = {
admins = lib.mkOption {
type = lib.types.attrsOf (lib.types.submodule adminOpts);
default = { };
description = "Admin users with interactive shell access.";
};
serviceUsers = lib.mkOption {
type = lib.types.attrsOf (lib.types.submodule serviceUserOpts);
default = { };
description = "Service users without administrative privileges, used for things like file shares.";
};
extraGroups = lib.mkOption {
type = lib.types.listOf lib.types.str;
default = [ ];
description = "Extra system groups to create, beyond the ones implied by admins/serviceUsers.";
};
};
config = {
environment.localBinInPath = true;
users.groups = lib.genAttrs cfg.extraGroups (_: { });
users.users = lib.mapAttrs
(_: admin: {
isNormalUser = true;
inherit (admin) description shell extraGroups;
openssh.authorizedKeys.keys = admin.authorizedKeys;
})
cfg.admins
// lib.mapAttrs
(_: svc: {
isSystemUser = true;
inherit (svc) description group createHome;
})
cfg.serviceUsers;
};
}