π Generate infrastructure and network diagrams directly from your NixOS configurations
Documentation | Installation and Usage
With nix-topology you can automatically generate infrastructure and network diagrams as SVGs directly from your NixOS configurations, and get something similar to the diagram above. It defines a new global module system where you can specify what nodes and networks you have. Most of the work is done by the included NixOS module which automatically collects all the information from your hosts.
Have a look at the examples directory for some self-contained examples or view the rendered results in the documentation.
I became a little envious of all the manually crafted infrastructure diagrams on r/homelab. But who's got time for that?! I'd rather spend a whole lot more time to create a generator that I will use once or twice in my life π€‘π. Maybe it will be useful for somebody else, too.
Installation should be as simple as adding nix-topology to your flake.nix, defining the global module and adding the NixOS module to your systems:
inputs.nix-topology.url = "github:oddlama/nix-topology";
pkgs = import nixpkgs {
inherit system;
overlays = [nix-topology.overlays.default];
};
nix-topology.nixosModules.default
in your host configs
nixosConfigurations.host1 = lib.nixosSystem {
system = "x86_64-linux";
modules = [
./host1/configuration.nix
nix-topology.nixosModules.default
];
};
topology = import nix-topology { pkgs = /*...*/; };
.
Expose this as an output in your flake so you can access it.
inputs.nix-topology.url = "github:oddlama/nix-topology";
topology = import nix-topology {
inherit pkgs; # Only this package set must include nix-topology.overlays.default
modules = [
# Your own file to define global topology. Works in principle like a nixos module but uses different options.
./topology.nix
# Inline module to inform topology of your existing NixOS hosts.
{ nixosConfigurations = self.nixosConfigurations; }
];
};
nix build .#topology.<current-system>.config.output
, the resulting directory will contain your finished svgs.
Note that this can take a minute, depending on how many hosts you have defined. Evaluating many nixos configurations just takes some time,
and the renderer sometimes struggles with handling bigger PNGs in a timely fashion.{
inputs = {
flake-utils.url = "github:numtide/flake-utils";
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
nix-topology.url = "github:oddlama/nix-topology";
nix-topology.inputs.nixpkgs.follows = "nixpkgs";
};
outputs = { self, flake-utils, nixpkgs, nix-topology, ... }: {
# Example. Use your own hosts and add the module to them
nixosConfigurations.host1 = nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
modules = [
./host1/configuration.nix
nix-topology.nixosModules.default
];
};
}
// flake-utils.lib.eachDefaultSystem (system: rec {
pkgs = import nixpkgs {
inherit system;
overlays = [ nix-topology.overlays.default ];
};
topology = import nix-topology {
inherit pkgs;
modules = [
# Your own file to define global topology. Works in principle like a nixos module but uses different options.
./topology.nix
# Inline module to inform topology of your existing NixOS hosts.
{ nixosConfigurations = self.nixosConfigurations; }
];
};
});
}
After rendering for the first time, the initial diagram might look a little unstructured. That's simply because nix-topology will be missing some important connections that can't be derived from a bunch of NixOS configurations, like physical connections. You'll probably also want to add some common devices like an image for the internet, switches, routers and stuff like that. But don't worry, all of this is quite simple. There's a whole chapter in the documentation that will guide you through it.
TL;DR: You can add connections and networks by specifying this information in the global topology module, or locally in one of your NixOS configs:
# This is a topology module, so use it in your global topology, or under `topology = {};` in any participating NixOS node
{
# Connect node1.lan -> node2.wan
nodes.node1.interfaces.lan.physicalConnections = [{ node = "node2"; interface = "wan"; }];
# Add home network
networks.home = {
name = "Home Network";
cidrv4 = "192.168.1.1/24";
};
# Tell nix-topology that myhost.lan1 is part of this network.
# The network will automatically propagate via the interface's connections.
nodes.myhost.interfaces.lan1.network = "home";
}
Or locally (e.g. host1/configuration.nix
):
{
topology.networks.home = {
name = "Network Made by Host1";
cidrv4 = "192.168.178.1/24";
};
topology.self.interfaces.lan1.network = "home";
}
Yep, there's still a lot that could be added or improved.
Contributions are whole-heartedly welcome! Please feel free to suggest new features, implement extractors, other stuff, or generally help out if you'd like. We'd be happy to have you. There's more information in CONTRIBUTING.md and the Development Chapter in the docs.
Licensed under the MIT license (LICENSE or https://opensource.org/licenses/MIT). Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in this project by you, shall be licensed as above, without any additional terms or conditions.