NixOS Configuration
Having first understood the basic concepts from the previous section, we can now configure a
Data Mesher cluster.
NixOS module
We start by including the NixOS module in our NixOS configuration:
Generating Keys
Next, we must generate or make available some keys.
Host
For the host key we can generate a new keypair with:
| ❯ data-mesher generate keypair
|
Network
For our networ, we will generate a new keypair the same as with the host.
For our primary network, we will generate a new one, same as with the host key.
| ❯ data-mesher generate keypair
ID: v8mttEnQXpdJnfH9YLImRRnmvfPx3nkXJoWhgUNdeH0=
Public Key: ./network.pub
Private Key: ./network.key
|
Tip
If you are joining an existing network you can simply copy it's public key.
Service Config
Having generated the necessary keys and included the NixOS module in our configuration, the final step is to configure
the Data Mesher service.
Note
To keep sensitive information safe, we will use sops-nix.
Here is what a basic service config looks like:
flake.nix |
---|
| { config, ... }:
let
inherit (config.sops) secrets;
in
{
# Define our secrets.
config.sops.secrets = {
# We will use a separately generated host key.
data_mesher_host_key = {
owner = config.users.users.data-mesher.name;
group = config.users.groups.data-mesher.name;
};
# We include the network's private key, as we will use it later to automatically inject network settings.
data_mesher_network_key = {
owner = config.users.users.data-mesher.name;
group = config.users.groups.data-mesher.name;
};
# And finally we have our network encryption key
data_mesher_network_encryption_key = {
owner = config.users.users.data-mesher.name;
group = config.users.groups.data-mesher.name;
};
};
config.services.data-mesher = {
enable = true; # Enable the service.
openFirewall = true; # Open necessary ports.
settings = {
host = {
# A list of hostnames we want to claim.
names = [
"mercury"
"venus"
"earth"
];
# Our host key.
key_path = secrets.data_mesher_host_key.path;
};
network.id = "QOoO3r3CwULLJbPumoQapoC8nHwMNYpvZj1Hftc6NJw=";
cluster = {
# The interface over which cluster communication should be performed.
# All the ip addresses associate with this interface will be part of our host claim, including both ipv4 and
# ipv6.
interface = "tailscale0";
# A list of bootstrap nodes that act as an initial gateway when joining the cluster.
# If a bootstrap node is no longer showing up in the cluster membership, we will attempt to connect to it
# periodically.
# See https://github.com/hashicorp/memberlist for more information.
bootstrap_nodes = [
"192.168.1.1:7946"
"192.168.1.2:7946"
];
};
};
# Optional config to bootstrap a network's settings after the data-mesher instance has started.
# The alternative is to manually bootstrap it by hand using the cli.
initNetwork = {
enable = true;
# Path to the network's private key, which will be used to sign the settings.
keyPath = secrets.data_mesher_network_key.path;
# Top level domain for all host names claimed within the network.
# e.g. mercury.sol, venus.sol, earth.sol
tld = "sol";
# Host claim expiry.
hostTTL = "168h"; # 7 days
# A list of host public keys (ed25519),
# State signed by any of the listed host keys will be considered as authoritative for this network.
# State not signed by one of these host keys will be discounted when merging.
# In this example we are using the host key for this instance to also act as a signing key.
signingKeys = [
"lADtqXxxM4dLRytVr2xeDEfOXHrWfb7ewB+0pqCJqGo="
];
};
};
}
|