Skip to content

Commit 3012167

Browse files
committed
docs(examples): add another example showcasing a host with predictable guest addresses
1 parent 0e2223d commit 3012167

File tree

2 files changed

+146
-0
lines changed

2 files changed

+146
-0
lines changed

examples/host-static-guest.nix

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
# `nix run microvm#host-static-guests`
2+
{ self, nixpkgs, system }:
3+
4+
nixpkgs.lib.nixosSystem {
5+
inherit system;
6+
7+
modules = [
8+
# for declarative MicroVM management
9+
self.nixosModules.host
10+
# this runs as a MicroVM that nests another MicroVM
11+
# potentially the host doesn't have to be a MicroVM itself
12+
self.nixosModules.microvm
13+
14+
({ config, lib, pkgs, ... }:
15+
let
16+
host = {
17+
MAC = "02:00:00:00:00:01";
18+
};
19+
guest = {
20+
MAC = "02:00:00:00:00:02";
21+
ip4 = "10.0.0.123";
22+
service = {
23+
text = "Hello, World!";
24+
port = 1234;
25+
};
26+
};
27+
in
28+
{
29+
# === Basic Host Setup ===
30+
#
31+
# We just use a nested MicroVM to demonstrate the network configuration
32+
# on the host machine. This configuration can be used on a non-MicroVM
33+
# host as well without any further adaptations (besides taking care of
34+
# collisions with your personal network configuration)
35+
system.stateVersion = config.system.nixos.version;
36+
users.users.root.password = "";
37+
users.motd = ''
38+
Once the nested MicroVM has booted, you can reach the service hosted on it via:
39+
curl ${guest.ip4}:${builtins.toString guest.service.port}
40+
'';
41+
services.getty.autologinUser = "root";
42+
environment.systemPackages = [ pkgs.curl ];
43+
44+
# MicroVM settings
45+
microvm = {
46+
mem = 1024 * 4;
47+
vcpu = 2;
48+
# Use QEMU because nested virtualization and user networking
49+
# are required.
50+
hypervisor = "qemu";
51+
interfaces = [{
52+
type = "user";
53+
id = "qemu";
54+
mac = host.MAC;
55+
}];
56+
};
57+
58+
# === Basic Guest Setup ===
59+
#
60+
# The guest machine is also just using a very minimalistic configuration.
61+
# It hosts a simple `static-web-server` showing a single website on a
62+
# configurable port.
63+
64+
# Nested MicroVM (a *host* option)
65+
microvm.vms.guest.config = {
66+
system.stateVersion = config.system.nixos.version;
67+
networking.hostName = "guest-microvm";
68+
69+
microvm = {
70+
interfaces = [{
71+
type = "tap";
72+
id = "vm-guest";
73+
mac = guest.MAC;
74+
}];
75+
};
76+
77+
# Just use 99-ethernet-default-dhcp.network
78+
systemd.network.enable = true;
79+
80+
# = very basic service =
81+
82+
networking.firewall.allowedTCPPorts = [ 80 443 guest.service.port ];
83+
services.static-web-server = {
84+
enable = true;
85+
listen = "[::]:${builtins.toString guest.service.port}";
86+
root = "${pkgs.writeTextDir "index.html" guest.service.text}";
87+
};
88+
89+
};
90+
91+
# === Network Setup ===
92+
#
93+
# The network config sets up a virtual bridge to connect to the guest
94+
# machine. The bridge uses DHCP to dynamically hand out leases to the
95+
# guest machines. Since we want to access the service on the guest machine
96+
# on a predicatable address, we can use a feature to map the MAC address
97+
# of the guest machine to a static private ip
98+
99+
systemd.network = {
100+
enable = true;
101+
netdevs.virbr0.netdevConfig = {
102+
Kind = "bridge";
103+
Name = "virbr0";
104+
};
105+
networks.virbr0 = {
106+
matchConfig.Name = "virbr0";
107+
# Hand out IP addresses to MicroVMs.
108+
# Use `networkctl status virbr0` to see leases.
109+
networkConfig = {
110+
DHCPServer = true;
111+
IPv6SendRA = true;
112+
};
113+
# here we can map the mac address of the guest system to static ip addresses
114+
dhcpServerStaticLeases = [
115+
{
116+
dhcpServerStaticLeaseConfig = {
117+
MACAddress = guest.MAC;
118+
Address = guest.ip4;
119+
};
120+
}
121+
];
122+
addresses = [{
123+
addressConfig.Address = "10.0.0.1/24";
124+
}];
125+
};
126+
networks.microvm-eth0 = {
127+
matchConfig.Name = "vm-*";
128+
networkConfig.Bridge = "virbr0";
129+
};
130+
};
131+
132+
networking = {
133+
hostName = "microvms-host";
134+
# Allow DHCP server
135+
firewall.allowedUDPPorts = [ 67 ];
136+
# # Allow Internet access
137+
nat = {
138+
enable = true;
139+
enableIPv6 = true;
140+
internalInterfaces = [ "virbr0" ];
141+
};
142+
};
143+
})
144+
];
145+
}

flake.nix

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
};
4848
in {
4949
vm = nixosToApp ./examples/microvms-host.nix;
50+
host-static-guest = nixosToApp ./examples/host-static-guest.nix;
5051
qemu-vnc = nixosToApp ./examples/qemu-vnc.nix;
5152
graphics = {
5253
type = "app";

0 commit comments

Comments
 (0)