{
  lib,
  config,
  ...
}: let
  inherit (lib) mapAttrsToList;
  inherit (lib.attrsets) foldAttrs concatMapAttrs;
  inherit (lib.asserts) assertMsg;
  inherit (lib.lists) filter last init;
  inherit (lib.strings) splitString toInt concatStringsSep;
  inherit (builtins) elem toString;
  hostmap = import ./hostmap.nix;
  myhostName = config.networking.hostName;
  # To turn the hostmap around suitable for networking.hosts the following simple code almost works
  # concatMapAttrs (hostname: ipData: { ${ipData.ipv4} = [hostname]; }) hostmap
  # but breaks as soon as we want to map two different names to the same ip.
  # So the code looks uglier than one would expect.
  globalhosts = foldAttrs (a: b: a ++ b) [] (mapAttrsToList (hostname: ipData: {${ipData.ipv4} = [hostname];}) hostmap);
  # We replace our own ip with 127.0.0.1 in /etc/hosts
  myhosts = concatMapAttrs (ip: hosts:
    if (elem myhostName hosts)
    # nixos maps the hostname to the loopback 127.0.0.2 by default, so we exclude it here.
    # there is also a default localhost to 127.0.0.1 in place
    then {"127.0.0.1" = filter (x: x != myhostName) hosts;}
    else {${ip} = hosts;})
  globalhosts;
  myIp = assert (assertMsg (hostmap ? ${myhostName}.ipv4) "${myhostName} has no ip configured in nixos/roles/hostmap.nix"); hostmap.${myhostName}.ipv4;
in {
  networking = {
    hosts = myhosts;
    interfaces.enX0.ipv4.addresses = [
      {
        address = myIp;
        prefixLength = 16;
      }
    ];
    defaultGateway = let
      addr = splitString "." myIp;
      addrInit = init addr;
      addrLastInt = toString (toInt (last addr) + 127);
    in
      concatStringsSep "." (addrInit ++ [addrLastInt]);
    # https://www.hrz.tu-darmstadt.de/services/it_services/nameserver_dns/index.de.jsp
    nameservers = ["130.83.22.63" "130.83.22.60" "130.83.56.60"];
  };
}