WIP: network module

This commit is contained in:
Sagar Ch 2024-05-28 21:01:46 +00:00
parent ade7b261ae
commit e4cdc2cae5
4 changed files with 354 additions and 0 deletions

79
nixos/modules/network.nix Normal file
View file

@ -0,0 +1,79 @@
{ config, pkgs, lib, ... }:
with lib;
let
ipv4Regex =
let
compRegex = "(25[0-5]|(2[0-4]|10|1?[1-9])?[0-9])";
in
"(${compRegex}\\.){3}${compRegex}";
cidr4Regex = "${ipv4Regex}/(3[0-2]|[1-2]?[0-9])";
in
{
options = {
startOnBoot = mkOption {
type = types.bool;
default = false;
description = "Whether to start this network on boot regardless if a VM is needing this network.";
};
namespace = mkOption {
type = types.nullOr types.str;
default = null;
description = "Linux network namespace under which this network is created. If not declared, it will create under hosts network namespace.";
};
type = mkOption {
type =types.enum [ "user" "nat" "natWANOnly" "routed" "routedWANOnly" "isolated" "bridge" ];
description = ''
Network types.
- "user" is qemu slirp user network, which can be shared across multiple VMs if needed
- "nat" is a NAT with an internal network, with a DHCP/DNS server, a domainsearch name and masqueraded access to the host's network
- "natWANOnly" just like nat but no access to the host itself, or other networks on the host, while allowing WAN access through the hosts default gateway
- "routed" is an internal network, with a DHCP/DNS server, a domainsearch name and routed inbound and outbound access to the host's network
- "routedWANOnly" just like routed, but no access to the host itself, or other networks on the host, while allowing WAN inbound and outbound access through the hosts default gateway
- "isolated" creates an internal network, a DHCP/DNS server, a domainsearch name with no access to host's network or WAN
- "bridge" is a bridge with another network or a host's network interface
'';
};
ipv4Range = mkOption {
type = types.strMatching cidr4Regex;
description = "IPv4 Range in x.x.x.x/y format to be assigned to the network.";
};
dhcp.enable = mkOption {
type = types.bool;
default = true;
description = "Whether to start a DHCP server within this network.";
};
dhcp.startAddress = mkOption {
type = types.strMatching ipv4Regex;
description = "Starting IP Address for DHCP clients.";
};
dhcp.endAddress = mkOption {
type = types.strMatching ipv4Regex;
description = "Ending IP Address for DHCP clients.";
};
dns.upstream = mkOption {
type = types.listOf (types.strMatching ipv4Regex);
default = [];
description = "List of IP Addresses of DNS servers to use as upstream DNS servers in the DHCP/DNS server. If left empty, it will use host's DNS servers";
};
dns.zonefiles = mkOption {
description = "Additional zonefiles to add for the DNS server";
};
routes.internal.add = mkOption {
description = "Additional routes to add on the internal network";
};
routes.host.add = mkOption {
description = "Addtional routes to add on the host's network namespace";
};
};
}

125
nixos/modules/vm.nix Normal file
View file

@ -0,0 +1,125 @@
{ config, pkgs, lib, ... }:
with lib;
let
networkModule = import ./network.nix { inherit config pkgs lib ;};
in
{
options = {
cpu =
mkOption {
type = types.str;
default = "host";
description = ''
The CPU model to emulate.
'';
};
smp =
mkOption {
type = types.ints.positive;
default = 1;
description = ''
Specify the number of cores the guest is permitted to use.
The number can be higher than the available cores on the
host system.
'';
};
memSize =
mkOption {
type = types.ints.positive;
default = 1024;
description = ''
The memory size in megabytes of the virtual machine.
'';
};
diskSize =
mkOption {
type = types.str;
default = "";
description = ''
The disk size in qemu params.
'';
};
osImage =
mkOption {
type = types.package;
description = ''
OS image stored in the nix store, either built with vmixLib.images or fetched from the internet.
'';
};
persistantOverlayImagePath =
mkOption {
type = types.nullOr types.path;
default = null;
description = ''
Path where the persistant overlay is stored. If path is non-existant, a qcow2 image backed by the original osImage is created.
'';
};
startOnBoot =
mkOption {
type = types.bool;
description = ''
Whether to start the VM automatically on system boot.
'';
default = true;
};
sharedDirectories =
lib.mkOption {
type = types.attrsOf
(types.submodule {
options = {
source = lib.mkOption {
type = types.str;
description = "The path of the directory to share, can be a shell variable";
};
target = lib.mkOption {
type = types.str;
description = "The mount point of the directory inside the virtual machine";
};
};
});
example = {
my-share = { source = "/path/to/be/shared"; target = "/mnt/shared"; };
};
default = { };
};
networks = lib.mkOption {
type = types.attrsOf
(types.submodule networkModule);
example = {
my-share = { source = "/path/to/be/shared"; target = "/mnt/shared"; };
};
default = { };
};
};
functions.mkVMService = name: cfg:
let
vmCfg = cfg // { inherit name };
mkDiskImageFrom
diskImage =
qemuArgs = ''
--name ${vmCfg.name} \
--cpu ${vmCfg.cpu} \
--smp ${vmCfg.cores} \
--
'';
in
{
};
}
//storage
//
//networking - DNS, VPNs, Bridges, NATs, isolation, connecting with others,host
//run adhoc
//run and die
//