This commit is contained in:
BOTAlex 2026-04-01 22:53:54 +02:00
parent 38d26110e1
commit f2bb1de7d8
15 changed files with 505 additions and 87 deletions

View file

@ -0,0 +1,27 @@
{
pkgs,
...
}:
{
systemd.services."argo-forward" = {
description = "forwards argo running on kubernetes";
after = [
"network-online.target"
"microvm@kubernetes.service"
];
wants = [ "network-online.target" ];
wantedBy = [ "multi-user.target" ];
script = ''
sleep 10
${pkgs.kubernetes}/bin/kubectl patch cm argocd-cmd-params-cm -n argocd --type merge --patch '{"data":{"server.insecure": "true", "url":"https://argocd.deprived.dev"}}'
${pkgs.kubernetes}/bin/kubectl port-forward svc/argocd-server -n argocd 4325:443 --address 0.0.0.0 || true
'';
serviceConfig = {
User = "root";
Restart = "always";
};
};
}

View file

@ -1,25 +1,42 @@
{ pkgs, ... }: {
{ pkgs, ... }:
{
environment.systemPackages = with pkgs; [ virtiofsd ];
microvm.autostart = [ "kube-daddy" ];
microvm.vms."kube-daddy" = { config = ./kube-daddy.nix; };
microvm.vms."kube-daddy" = {
config = ./kube-daddy.nix;
};
systemd.services.kube-iptable = {
after = [ "network.target" ];
wantedBy = [ "multi-user.target" ];
serviceConfig = {
Type = "oneshot";
ExecStart = "${pkgs.iptables}/bin/iptables -t nat -I POSTROUTING 1 -s 10.0.0.0/24 -o enp8s0 -j MASQUERADE ";
RemainAfterExit = true;
User = "root";
};
stopIfChanged = true;
};
networking = {
# 1. Create a Bridge (The Switch)
bridges = { "br0" = { interfaces = [ "microvm-tap1" "microvm-tap2" ]; }; };
bridges = {
"br0" = {
interfaces = [
"microvm-tap1"
"microvm-tap2"
];
};
};
# 2. Assign the Gateway IP to the Bridge (NOT the taps)
interfaces.br0.ipv4.addresses = [{
address = "10.0.0.1";
prefixLength = 24;
}];
interfaces.br0.ipv4.addresses = [
{
address = "10.0.0.1";
prefixLength = 24;
}
];
# 3. Create persistent TAP interfaces so they exist at boot
# (This requires you to create a systemd service or use ip tuntap commands.
# Below is a "hack" using a dummy script, or use systemd-networkd netdevs if enabled)
# The cleanest NixOS way without networkd is often just letting the bridge create them
# or defining them as virtual devices (requires manual script usually).
#
# Use this script to ensure they exist before the bridge tries to enslave them:
localCommands = ''
ip tuntap add dev microvm-tap1 mode tap user root || true
ip tuntap add dev microvm-tap2 mode tap user root || true
@ -27,18 +44,21 @@
ip link set microvm-tap2 up
'';
# 4. Update NAT to use the Bridge
nat = {
enable = true;
externalInterface = "enp8s0"; # Your physical interface
internalInterfaces = [ "br0" ]; # NAT traffic coming from the bridge
externalInterface = "enp8s0";
internalIPs = [ "10.0.0.0/24" ];
forwardPorts = [
{
sourcePort = 8877;
destination = "10.0.0.2:8888";
proto = "tcp";
}
# { # Access this directly from host by 10.0.0.2:4325
# sourcePort = 4325; # argocd
# destination = "10.0.0.2:8080";
# proto = "tcp";
# }
{
sourcePort = 6443;
destination = "10.0.0.2:6443";
@ -49,6 +69,41 @@
destination = "10.0.0.2:4123";
proto = "tcp";
}
{
sourcePort = 8472;
destination = "10.0.0.2:8472";
proto = "udp";
}
{
sourcePort = 2379;
destination = "10.0.0.2:2379";
proto = "udp";
}
{
sourcePort = 2380;
destination = "10.0.0.2:2380";
proto = "udp";
}
{
sourcePort = 2379;
proto = "tcp";
destination = "10.0.0.2:2379";
}
{
sourcePort = 2380;
destination = "10.0.0.2:2380";
proto = "tcp";
}
{
sourcePort = 4001;
destination = "10.0.0.2:4001";
proto = "udp";
}
{
sourcePort = 4001;
destination = "10.0.0.2:4001";
proto = "tcp";
}
# If your app uses UDP (like HTTP/3 or QUIC), add this too:
# { sourcePort = 8888; destination = "10.0.0.2:8888"; proto = "udp"; }
];
@ -57,4 +112,12 @@
# 5. Update Firewall to trust the Bridge
firewall.trustedInterfaces = [ "br0" ];
};
systemd.tmpfiles.rules = [
"d /var/lib/microvms/shared 0755 microvm kvm -"
"d /var/lib/microvms/shared/kube 0755 microvm kvm -"
"d /var/lib/microvms/shared/docking 0755 microvm kvm -"
"d /var/lib/microvms/shared/.config 0755 microvm kvm -"
"d /var/lib/microvms/shared/.local 0755 microvm kvm -"
];
}

View file

@ -1,4 +1,6 @@
{ pkgs, ... }: {
{ lib, pkgs, ... }:
{
users.users.root = {
openssh.authorizedKeys.keys = [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAhiPhFbCi64NduuV794omgS8mctBLXtqxbaEJyUo6lg botalex@DESKTOPSKTOP-ENDVV0V"
@ -13,8 +15,7 @@
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBLSUXsao6rjC3FDtRHhh7z6wqMtA/mqL50e1Dj9a2wE botserver@botserver"
];
hashedPassword =
"$6$HpwhjoEuhRZuFhJF$jEV3SxbcGKVlRRgbDx6YpySyTHKUIOnmUD0Rd4PLXsXhbnrgeBVCPfkK.cBCUmxUeQjNTzj4CDpP4XBxLz0EV0";
hashedPassword = "$6$HpwhjoEuhRZuFhJF$jEV3SxbcGKVlRRgbDx6YpySyTHKUIOnmUD0Rd4PLXsXhbnrgeBVCPfkK.cBCUmxUeQjNTzj4CDpP4XBxLz0EV0";
shell = pkgs.fish;
@ -22,8 +23,14 @@
environment.variables.EDITOR = "nvim";
services.openssh = { enable = true; };
imports = [ ./../../modules/getNvim.nix ./kubernetes.nix ];
services.openssh = {
enable = true;
};
imports = [
./../../modules/getNvim.nix
./kubernetes.nix
# ./wg-snorre.nix
];
environment.systemPackages = with pkgs; [
neovim
git
@ -42,6 +49,9 @@
openssl
dig
argocd
gnutar
wireguard-tools
python312
];
programs.fish = {
@ -59,11 +69,13 @@
vcpu = 8;
# Create a tap interface or user networking
interfaces = [{
type = "tap";
id = "microvm-tap1"; # Matches the host's first tap
mac = "02:00:00:00:00:01";
}];
interfaces = [
{
type = "tap";
id = "microvm-tap1"; # Matches the host's first tap
mac = "02:00:00:00:00:01";
}
];
# forwardPorts = [
# {
@ -91,42 +103,120 @@
# Mount the host's /nix/store explicitly (read-only)
# This makes the VM start instantly as it shares the host store.
shares = [{
tag = "ro-store";
source = "/nix/store";
mountPoint = "/nix/.ro-store";
}];
shares = [
{
tag = "ro-store";
source = "/nix/store";
mountPoint = "/nix/.ro-store";
}
{
proto = "9p";
tag = "docking-mount";
# Source path can be absolute or relative
# to /var/lib/microvms/$hostName
source = "../shared/docking";
mountPoint = "/root/docking";
}
{
proto = "9p";
tag = "kube-wireguard";
# Source path can be absolute or relative
# to /var/lib/microvms/$hostName
source = "../shared/wg";
mountPoint = "/root/wg";
}
# {
# proto = "9p";
# tag = "kube-mount";
# source = "../shared/kube";
# mountPoint = "/var/lib/kubernetes";
# }
# {
# proto = "9p";
# tag = "config";
# source = "../shared/.config";
# mountPoint = "/root/.config";
# }
# {
# proto = "9p";
# tag = "local";
# source = "../shared/.local";
# mountPoint = "/root/.local";
# }
];
# Writable disk allocation
volumes = [{
image = "/var/lib/microvms/kube-daddy/kube-daddy.img";
mountPoint = "/";
size = 32768; # Size in MB
}];
volumes = [
{
image = "/var/lib/microvms/kube-daddy/kube-daddy.img";
mountPoint = "/";
size = 32768; # Size in MB
}
];
};
services.resolved.enable = true;
networking = {
hostName = "kube-daddy";
useNetworkd = true;
firewall.enable =
false; # Keep disabled for easier testing, or allow port 22
firewall.enable = false;
nameservers = [
"10.0.0.1"
"8.8.8.8"
];
};
interfaces.enp0s4.ipv4.addresses = [{
address = "10.0.0.2";
prefixLength = 24;
}];
defaultGateway = {
address = "10.0.0.1";
interface = "enp0s4";
systemd.network = {
# 1. Define the Bridge Device
netdevs."20-br0" = {
netdevConfig = {
Kind = "bridge";
Name = "br0";
};
};
networks = {
# 2. Configure the Bridge (IP & Gateway go here now)
"30-br0" = {
matchConfig.Name = "br0";
networkConfig = {
Address = "10.0.0.2/24";
Gateway = "10.0.0.1";
DNS = [
"10.0.0.1"
"8.8.8.8"
];
};
linkConfig.RequiredForOnline = "routable";
};
# 3. Catch the changing interface and attach it to the bridge
"40-uplink" = {
# This wildcard matches enp0s7, enp1s0, etc.
matchConfig.Name = "en*";
networkConfig.Bridge = "br0";
};
};
nameservers = [ "1.1.1.1" ];
};
# Allow passwordless root login for testing (Do not use in production!)
services.getty.autologinUser = "root";
users.users.root.password = "";
systemd.services."load-br_netfilter" = {
enable = true;
description = "Modprobe br_netfilter";
before = [ "flannel.service" ];
wantedBy = [
"multi-user.target"
"flannel.service"
];
script = ''
${pkgs.kmod}/bin/modprobe br_netfilter
'';
};
systemd.network.enable = true;
systemd.network.networks."11-microvm" = {
matchConfig.Name = "vm-*";
@ -135,5 +225,11 @@
};
system.stateVersion = "24.11";
}
systemd.tmpfiles.rules = [
"d /root/.kube 0755 root root -"
"d /root/.config 0755 root root -"
"d /root/.local 0755 root root -"
"L+ /root/.kube/config - - - - /etc/kubernetes/cluster-admin.kubeconfig"
];
}

View file

@ -1,4 +1,9 @@
{ config, pkgs, ... }:
{
config,
pkgs,
lib,
...
}:
let
# When using easyCerts=true the IP Address must resolve to the master on creation.
# So use simply 127.0.0.1 in that case. Otherwise you will have errors like this https://github.com/NixOS/nixpkgs/issues/59364
@ -8,17 +13,33 @@ let
in
{
# resolve master hostname
networking.extraHosts = "${kubeMasterIP} ${kubeMasterHostname}";
networking.extraHosts = ''
${kubeMasterIP} ${kubeMasterHostname}
10.0.0.2 kube-daddy
10.0.0.4 kube-desk
10.0.0.5 kube-snorre'';
networking.firewall.enable = false;
imports = [
./argo-forward.nix
./longhorn-deps.nix
];
# packages for administration tasks
environment.systemPackages = with pkgs; [ kompose kubectl kubernetes ];
environment.systemPackages = with pkgs; [
kompose
kubectl
kubernetes
(pkgs.callPackage /etc/nixos/modules/customPackages/wgmesh { })
];
services.kubernetes = {
roles = [ "master" "node" ];
roles = [
"master"
"node"
];
masterAddress = kubeMasterHostname;
apiserverAddress =
"https://${kubeMasterHostname}:${toString kubeMasterAPIServerPort}";
apiserverAddress = "https://${kubeMasterHostname}:${toString kubeMasterAPIServerPort}";
easyCerts = true;
apiserver = {
securePort = kubeMasterAPIServerPort;
@ -31,6 +52,11 @@ in
addons.dns.enable = true;
# needed if you use swap
kubelet.extraOpts = "--fail-swap-on=false";
kubelet.extraOpts = "--fail-swap-on=false --resolv-conf=/run/systemd/resolve/resolv.conf";
};
services.flannel = {
iface = "br0";
publicIp = "10.0.0.2";
};
}

View file

@ -0,0 +1,33 @@
{ config, pkgs, ... }:
{
# 1. Enable iSCSI daemon (Crucial for Longhorn)
services.openiscsi = {
enable = true;
name = "iqn.2026-03.com.proxy-m:${config.networking.hostName}";
};
# 2. Enable NFS support (For RWX volumes)
boot.supportedFilesystems = [ "nfs" ];
services.rpcbind.enable = true;
# 3. Load required kernel modules
boot.kernelModules = [
"iscsi_tcp"
"dm_crypt"
"dm_multipath"
];
# 4. Ensure necessary tools are available in the system path
environment.systemPackages = with pkgs; [
openiscsi
nfs-utils
util-linux # for findmnt, etc.
bash
];
systemd.tmpfiles.rules = [
"L+ /usr/local/bin/iscsiadm - - - - /run/current-system/sw/bin/iscsiadm"
"L+ /usr/bin/iscsiadm - - - - /run/current-system/sw/bin/iscsiadm"
];
}

View file

@ -0,0 +1,35 @@
{ config, ... }:
{
networking.wg-quick.interfaces = {
wg0 = {
# The local IP address for this interface
address = [ "10.13.13.3/32" ];
# The DNS server to use when the tunnel is active
dns = [ "10.0.101.1" ];
# The port to listen on
listenPort = 51820;
# Path to the private key file (using age for security)
privateKeyFile = "/root/wg/priv.key";
peers = [
{
# The public key of the remote peer
publicKey = "QD36zS9c4IWYzqPAjP88hX9nx4wWJ9thB9YlO6vCtzo=";
# Path to the preshared key file (security best practice)
presharedKeyFile = "/root/wg/pre.key";
# The remote endpoint and port
endpoint = "37.49.130.171:51820";
# Traffic to route through the tunnel (0.0.0.0/0 sends everything)
allowedIPs = [ "0.0.0.0/0" ];
}
];
};
};
}