migrate nixos-container to microvm #28

Merged
kalipso merged 18 commits from microvm into master 2024-11-21 15:59:01 +01:00
9 changed files with 257 additions and 7 deletions

View File

@@ -13,4 +13,5 @@
- [TODO](./todo.md) - [TODO](./todo.md)
- [How-to]() - [How-to]()
- [Updates](./anleitung/updates.md) - [Updates](./anleitung/updates.md)
- [Rollbacks](./anleitung/rollback.md) - [Rollbacks](./anleitung/rollback.md)
- [MicroVM](./anleitung/microvm.md)

View File

@@ -0,0 +1,52 @@
### Declaring a MicroVM
The hosts nixosSystems modules should be declared using the ```makeMicroVM``` helper function.
Use durruti as orientation:
``` nix
modules = makeMicroVM "durruti" "10.0.0.5" [
./durruti/configuration.nix
];
```
"durruti" is the hostname.
"10.0.0.5" is the IP assigned to its tap interface.
### Testing MicroVMs locally
MicroVMs can be built and run easily on your local host.
For durruti this is done by:
``` bash
sudo nix run .\#nixosConfigurations.durruti.config.microvm.declaredRunner
```
It seems to be necessary to run this as root so that the according tap interface can be created.
To be able to ping the VM or give Internet Access to the VM your host needs to be setup as described below.
### Host Setup
#### Network Bridge
To provide network access to the VMs a bridge interface needs to be created on your host.
For that:
- Add the infrastructure flake as input to your hosts flake
- Add ```inputs.malobeo.nixosModules.malobeo``` to your hosts imports
- enable the host bridge: ```services.malobeo.microvm.enableHostBridge = true;```
If you want to provide Internet access to the VM it is necessary to create a nat.
This could be done like this:
``` nix
networking.nat = {
enable = true;
internalInterfaces = [ "microvm" ];
externalInterface = "eth0"; #change to your interface name
};
```
#### Auto Deploy VMs
By default no MicroVMs will be initialized on the host - this should be done using the microvm commandline tool.
But since we want to always deploy certain VMs it can be configured using the ```malobeo.microvm.deployHosts``` option.
VMs configured using this option will be initialized and autostarted at boot.
Updating still needs to be done imperative, or by enabling autoupdates.nix
The following example would init and autostart durruti and gitea:
``` nix
malobeo.microvm.deployHosts = [ "durruti" "gitea" ];
```

74
flake.lock generated
View File

@@ -21,6 +21,24 @@
"url": "https://git.dynamicdiscord.de/kalipso/ep3-bs.nix" "url": "https://git.dynamicdiscord.de/kalipso/ep3-bs.nix"
} }
}, },
"flake-utils": {
"inputs": {
"systems": "systems_3"
},
"locked": {
"lastModified": 1726560853,
"narHash": "sha256-X6rJYSESBVr3hBoH0WbKE5KvhPU5bloyZ2L4K60/fPQ=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "c1dfcf08411b08f6b8615f7d8971a2bfa81d5e8a",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"home-manager": { "home-manager": {
"inputs": { "inputs": {
"nixpkgs": [ "nixpkgs": [
@@ -61,6 +79,28 @@
"type": "github" "type": "github"
} }
}, },
"microvm": {
"inputs": {
"flake-utils": "flake-utils",
"nixpkgs": [
"nixpkgs"
],
"spectrum": "spectrum"
},
"locked": {
"lastModified": 1731240174,
"narHash": "sha256-HYu+bPoV3UILhwc4Ar5iQ7aF+DuQWHXl4mljN6Bwq6A=",
"owner": "astro",
"repo": "microvm.nix",
"rev": "dd89404e1885b8d7033106f3898eaef8db660cb2",
"type": "github"
},
"original": {
"owner": "astro",
"repo": "microvm.nix",
"type": "github"
}
},
"nixlib": { "nixlib": {
"locked": { "locked": {
"lastModified": 1729386149, "lastModified": 1729386149,
@@ -182,6 +222,7 @@
"ep3-bs": "ep3-bs", "ep3-bs": "ep3-bs",
"home-manager": "home-manager", "home-manager": "home-manager",
"mfsync": "mfsync", "mfsync": "mfsync",
"microvm": "microvm",
"nixos-generators": "nixos-generators", "nixos-generators": "nixos-generators",
"nixos-hardware": "nixos-hardware", "nixos-hardware": "nixos-hardware",
"nixpkgs": "nixpkgs_2", "nixpkgs": "nixpkgs_2",
@@ -212,6 +253,22 @@
"type": "github" "type": "github"
} }
}, },
"spectrum": {
"flake": false,
"locked": {
"lastModified": 1729945407,
"narHash": "sha256-iGNMamNOAnVTETnIVqDWd6fl74J8fLEi1ejdZiNjEtY=",
"ref": "refs/heads/main",
"rev": "f1d94ee7029af18637dbd5fdf4749621533693fa",
"revCount": 764,
"type": "git",
"url": "https://spectrum-os.org/git/spectrum"
},
"original": {
"type": "git",
"url": "https://spectrum-os.org/git/spectrum"
}
},
"systems": { "systems": {
"locked": { "locked": {
"lastModified": 1681028828, "lastModified": 1681028828,
@@ -257,6 +314,21 @@
"type": "github" "type": "github"
} }
}, },
"systems_4": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
},
"tasklist": { "tasklist": {
"inputs": { "inputs": {
"nixpkgs": [ "nixpkgs": [
@@ -315,7 +387,7 @@
}, },
"utils_3": { "utils_3": {
"inputs": { "inputs": {
"systems": "systems_3" "systems": "systems_4"
}, },
"locked": { "locked": {
"lastModified": 1726560853, "lastModified": 1726560853,

View File

@@ -8,6 +8,8 @@
sops-nix.url = "github:Mic92/sops-nix"; sops-nix.url = "github:Mic92/sops-nix";
sops-nix.inputs.nixpkgs.follows = "nixpkgs"; sops-nix.inputs.nixpkgs.follows = "nixpkgs";
mfsync.url = "github:k4lipso/mfsync"; mfsync.url = "github:k4lipso/mfsync";
microvm.url = "github:astro/microvm.nix";
microvm.inputs.nixpkgs.follows = "nixpkgs";
utils = { utils = {
url = "github:numtide/flake-utils"; url = "github:numtide/flake-utils";

View File

@@ -40,6 +40,39 @@ let
} }
]; ];
defaultModules = baseModules; defaultModules = baseModules;
makeMicroVM = hostName: ipv4Addr: modules: [
inputs.microvm.nixosModules.microvm
{
microvm = {
hypervisor = "qemu";
shares = [ {
tag = "ro-store";
source = "/nix/store";
mountPoint = "/nix/.ro-store";
} ];
interfaces = [
{
type = "tap";
id = "vm-${hostName}";
mac = "02:00:00:00:00:01";
}
];
};
systemd.network.enable = true;
systemd.network.networks."20-lan" = {
matchConfig.Type = "ether";
networkConfig = {
Address = [ "${ipv4Addr}/24" ];
Gateway = "10.0.0.1";
DNS = ["1.1.1.1"];
DHCP = "no";
};
};
}
] ++ defaultModules ++ modules;
in in
{ {
louise = nixosSystem { louise = nixosSystem {
@@ -53,7 +86,7 @@ in
durruti = nixosSystem { durruti = nixosSystem {
system = "x86_64-linux"; system = "x86_64-linux";
specialArgs.inputs = inputs; specialArgs.inputs = inputs;
modules = defaultModules ++ [ modules = makeMicroVM "durruti" "10.0.0.5" [
./durruti/configuration.nix ./durruti/configuration.nix
]; ];
}; };

View File

@@ -5,7 +5,6 @@ with lib;
{ {
sops.defaultSopsFile = ./secrets.yaml; sops.defaultSopsFile = ./secrets.yaml;
boot.isContainer = true;
networking = { networking = {
hostName = mkDefault "durruti"; hostName = mkDefault "durruti";
useDHCP = false; useDHCP = false;

View File

@@ -44,6 +44,5 @@ in
enableACME= true; enableACME= true;
locations."/".proxyPass = "http://${cfg.host_ip}:80"; locations."/".proxyPass = "http://${cfg.host_ip}:80";
}; };
}; };
} }

View File

@@ -0,0 +1,89 @@
{ config, self, lib, inputs, options, pkgs, ... }:
with lib;
let
cfg = config.services.malobeo.microvm;
in
{
options = {
services.malobeo.microvm = {
enableHostBridge = mkOption {
default = false;
type = types.bool;
description = lib.mdDoc "Setup bridge device for microvms.";
};
enableHostBridgeUnstable = mkOption {
default = false;
type = types.bool;
description = lib.mdDoc "Setup bridge device for microvms.";
};
deployHosts = mkOption {
default = [];
type = types.listOf types.str;
description = ''
List hostnames of MicroVMs that should be automatically initializes and autostart
'';
};
};
};
imports = [
inputs.microvm.nixosModules.host
];
config = {
assertions = [
{
assertion = !(cfg.enableHostBridgeUnstable && cfg.enableHostBridge);
message = ''
Only enableHostBridge or enableHostBridgeUnstable! Not Both!
'';
}
];
systemd.network = mkIf (cfg.enableHostBridge || cfg.enableHostBridgeUnstable) {
enable = true;
# create a bride device that all the microvms will be connected to
netdevs."10-microvm".netdevConfig = {
Kind = "bridge";
Name = "microvm";
};
networks."10-microvm" = {
matchConfig.Name = "microvm";
networkConfig = {
DHCPServer = true;
IPv6SendRA = true;
};
addresses = if cfg.enableHostBridgeUnstable then [
{ Address = "10.0.0.1/24"; }
] else [
{ addressConfig.Address = "10.0.0.1/24"; }
];
};
# connect the vms to the bridge
networks."11-microvm" = {
matchConfig.Name = "vm-*";
networkConfig.Bridge = "microvm";
};
};
microvm.vms =
let
# Map the values to each hostname to then generate a Attrs using listToAttrs
mapperFunc = name: { inherit name; value = {
# Host build-time reference to where the MicroVM NixOS is defined
# under nixosConfigurations
flake = inputs.malobeo;
# Specify from where to let `microvm -u` update later on
updateFlake = "git+https://git.dynamicdiscord.de/kalipso/infrastructure?ref=microvm";
}; };
in
builtins.listToAttrs (map mapperFunc cfg.deployHosts);
};
}

View File

@@ -41,7 +41,7 @@ in (utils.lib.eachSystem (builtins.filter filter_system utils.lib.defaultSystems
apps = { apps = {
docs = { docs = {
type = "app"; type = "app";
program = builtins.toString (pkgs.writeScript "docs" '' program = builtins.toString (pkgs.writeShellScript "docs" ''
${pkgs.mdbook}/bin/mdbook serve --open ./doc ${pkgs.mdbook}/bin/mdbook serve --open ./doc
''); '');
}; };
@@ -52,7 +52,10 @@ in (utils.lib.eachSystem (builtins.filter filter_system utils.lib.defaultSystems
inherit inputs; inherit inputs;
}); });
nixosModules.malobeo = import ./machines/durruti/host_config.nix; nixosModules.malobeo.imports = [
./machines/durruti/host_config.nix
./machines/modules/malobeo/microvm_host.nix
];
hydraJobs = nixpkgs.lib.mapAttrs (_: nixpkgs.lib.hydraJob) ( hydraJobs = nixpkgs.lib.mapAttrs (_: nixpkgs.lib.hydraJob) (
let let