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

+86 -18
View File
@@ -1,26 +1,83 @@
{ pkgs, ... }:
{ config, pkgs, ... }:
{
imports = [
imports = [
./hardware-configuration.nix
../../modules/security/secureboot.nix
../../modules/services/maintenance.nix
../../modules/services/flatpak.nix
../../modules/system/audio.nix
../../modules/system/fonts.nix
../../modules/system/gaming.nix
../../modules/system/graphics.nix
../../modules/profiles/desktop.nix
../../modules/profiles/server.nix
../../modules/services/samba.nix
../../modules/system/nix-ld.nix
../../modules/system/packages.nix
../../modules/system/shells.nix
../../modules/system/users.nix
../../modules/system/networking.nix
../../modules/desktop/firefox.nix
../../modules/desktop/plasma.nix
../../modules/services/containers.nix
../../modules/services/vscode-server.nix
];
age.secrets.miku-homelab-wg.file = ../../secrets/miku-homelab-wg.age;
myNetworking = {
hostName = "miku-homelab";
useNetworkManager = true;
staticIp = {
interface = "enp6s0";
address = "10.1.1.21";
prefixLength = 24;
gateway = "10.1.1.1";
nameservers = [ "1.1.1.1" "8.8.8.8" ];
};
extraUdpPorts = [ 80 443 4242 49983 24800 26900 60977 ];
extraTcpPorts = [ 80 443 4242 49983 24800 26900 60977 ];
sshAllowUsers = [ "emmatherock" ];
wireguard = {
enable = true;
ips = [ "10.20.0.2/24" ];
privateKeyFile = config.age.secrets.miku-homelab-wg.path;
peers = [
{
publicKey = "zERcSEQhan+xtmPOIjuVSkQaBynTjH96SgZZF9CZNV8=";
allowedIPs = [ "10.20.0.1/32" ];
endpoint = "vps.external.mikufanclub.lat:51822";
persistentKeepalive = 25;
}
];
};
};
myUsers = {
admins.emmatherock = {
description = "EmmaTheRock";
shell = pkgs.fish;
extraGroups = [ "plugdev" "networkmanager" "wheel" "video" "mikushare-group" "render" ];
authorizedKeys = [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIA8vfwM5g9RJXqHtqTgNqsYg9SxSm+UMvFqTjBoAsLJ6 emmatherock@MAIN-PC"
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIpTslcK0yQ6k+h8foNl17wVRyJUfEGzq7f1h3014WNB s21 plus"
];
};
serviceUsers.mikushare = {
description = "Acceso remoto Mikufanclub";
group = "mikushare-group";
createHome = false;
};
extraGroups = [ "mikushare-group" "plugdev" ];
};
myContainers = {
enable = true;
storageDriver = "btrfs";
globalNetwork = "homelab_net";
composeStacks = {
tools = {
path = "/mnt/containers/tools";
after = [ "network-online.target" "tailscaled.service" ];
};
arrs = {
path = "/mnt/containers/arrs";
after = [ "docker-compose-tools.service" "local-fs.target" ];
};
gameservers = {
path = "/mnt/containers/gameserver";
after = [ "docker-compose-tools.service" ];
};
};
};
boot = {
loader = {
efi.canTouchEfiVariables = true;
@@ -58,11 +115,22 @@
# Elgato 4K S (all speed modes)
SUBSYSTEM=="usb", ATTR{idVendor}=="0fd9", ATTR{idProduct}=="00af", MODE="0666", GROUP="plugdev"
SUBSYSTEM=="usb", ATTR{idVendor}=="0fd9", ATTR{idProduct}=="00ae", MODE="0666", GROUP="plugdev"
# nvtop
SUBSYSTEM=="drm", KERNEL=="card*", SUBSYSTEMS=="pci", DRIVERS=="amdgpu", RUN+="/bin/sh -c 'chmod -R g+r /sys/class/drm/%k/device/'"
'';
systemd.services.tailscale-udp-gro = {
description = "Configurar UDP GRO para Tailscale";
after = [ "network.target" ];
wantedBy = [ "multi-user.target" ];
serviceConfig = {
Type = "oneshot";
ExecStart = "${pkgs.ethtool}/bin/ethtool -K enp6s0 rx-udp-gro-forwarding on rx-gro-list on";
RemainAfterExit = true;
};
};
nixpkgs.config.allowUnfree = true;
nix.settings = {
experimental-features = [ "nix-command" "flakes" ];
+73
View File
@@ -0,0 +1,73 @@
{ config, ... }:
{
imports = [
./hardware-configuration.nix
../../modules/profiles/server.nix
];
# PLACEHOLDER: secrets/vps-wg.age does not exist yet. It has to be created
# (same way as secrets/miku-homelab-wg.age) once this host is installed and
# its own WireGuard private key has been generated.
age.secrets.vps-wg.file = ../../secrets/vps-wg.age;
myNetworking = {
hostName = "vps";
useNetworkManager = false;
staticIp = {
interface = "eth0";
address = "23.175.41.196";
prefixLength = 27;
gateway = "23.175.41.225";
nameservers = [ "1.1.1.1" "1.0.0.1" ];
};
extraTcpPorts = [ 80 443 ];
extraUdpPorts = [ 51822 ];
sshAllowUsers = [ "emmatherock" ];
wireguard = {
enable = true;
ips = [ "10.20.0.1/24" ];
privateKeyFile = config.age.secrets.vps-wg.path;
listenPort = 51822;
peers = [
{
publicKey = "bqxDHQNxOSFpTo3We9ujC2WljtaRBgiNEewW+Rlu10k=";
allowedIPs = [ "10.20.0.2/32" ];
}
];
};
};
myUsers = {
admins.emmatherock = {
description = "EmmaTheRock";
extraGroups = [ "wheel" ];
authorizedKeys = [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIA8vfwM5g9RJXqHtqTgNqsYg9SxSm+UMvFqTjBoAsLJ6 emmatherock@MAIN-PC"
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIpTslcK0yQ6k+h8foNl17wVRyJUfEGzq7f1h3014WNB s21 plus"
];
};
};
myContainers = {
enable = true;
composeStacks.core = {
path = "/opt/containers/core";
after = [ "network-online.target" ];
};
};
# PLACEHOLDER: adjust once the real VPS image/provider is known (BIOS vs
# UEFI, actual boot device). Assumes a generic BIOS-booted image for now.
boot.loader.grub = {
enable = true;
device = "/dev/sda";
};
time.timeZone = "UTC";
i18n.defaultLocale = "en_US.UTF-8";
nix.settings.experimental-features = [ "nix-command" "flakes" ];
system.stateVersion = "25.11";
}
+23
View File
@@ -0,0 +1,23 @@
{ lib, ... }:
# PLACEHOLDER: this host has not been installed yet. Replace this whole file
# with the real hardware-configuration.nix generated by `nixos-generate-config`
# during the actual installation (it will pick up the real disk UUIDs,
# filesystem types, and kernel modules for the VPS provider's image).
{
imports = [ ];
boot.initrd.availableKernelModules = [ "ata_piix" "uhci_hcd" "virtio_pci" "virtio_scsi" "sd_mod" "sr_mod" ];
boot.initrd.kernelModules = [ ];
boot.kernelModules = [ ];
boot.extraModulePackages = [ ];
fileSystems."/" = {
device = "/dev/disk/by-uuid/00000000-0000-0000-0000-000000000000";
fsType = "ext4";
};
swapDevices = [ ];
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
}