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>
This commit is contained in:
emmatherockandClaude Sonnet 5 committed 2026-08-12 00:07:55 -03:00
1 parent 26bfa56268
commit 42e60a3bb5
13 files changed
+695 -184

No files matched your search

+82 -19
View File
@@ -1,25 +1,88 @@
{ pkgs, ... }: {
environment.localBinInPath = true;
{ lib, pkgs, config, ... }:
users.groups.mikushare-group = {};
users.groups.plugdev = {};
let
cfg = config.myUsers;
users.users.emmatherock = {
isNormalUser = true;
description = "EmmaTheRock";
shell = pkgs.fish;
extraGroups = [ "plugdev" "networkmanager" "wheel" "video" "mikushare-group" "render" ];
openssh.authorizedKeys.keys = [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIA8vfwM5g9RJXqHtqTgNqsYg9SxSm+UMvFqTjBoAsLJ6 emmatherock@MAIN-PC"
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIpTslcK0yQ6k+h8foNl17wVRyJUfEGzq7f1h3014WNB s21 plus"
];
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.";
};
};
};
users.users.mikushare = {
isNormalUser = true;
description = "Acceso remoto Mikufanclub";
group = "mikushare-group";
createHome = false;
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;
};
}