Unverified Commit 2fa5e844 authored by Ryan Lahfa's avatar Ryan Lahfa Committed by GitHub
Browse files

Merge pull request #223749 from Alexis211/add-wgautomesh

wgautomesh: init at 0.1.0
parents a30c6c8e a727a3d6
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -9245,6 +9245,13 @@
    githubId = 2057309;
    name = "Sergey Sofeychuk";
  };
  lx = {
    email = "alex@adnab.me";
    github = "Alexis211";
    githubId = 101484;
    matrix = "@lx:deuxfleurs.fr";
    name = "Alex Auvolat";
  };
  lxea = {
    email = "nix@amk.ie";
    github = "lxea";
+2 −0
Original line number Diff line number Diff line
@@ -107,6 +107,8 @@ In addition to numerous new and upgraded packages, this release has the followin

- [trurl](https://github.com/curl/trurl), a command line tool for URL parsing and manipulation.

- [wgautomesh](https://git.deuxfleurs.fr/Deuxfleurs/wgautomesh), a simple utility to help connect wireguard nodes together in a full mesh topology. Available as [services.wgautomesh](options.html#opt-services.wgautomesh.enable).

- [woodpecker-agents](https://woodpecker-ci.org/), a simple CI engine with great extensibility. Available as [services.woodpecker-agents](#opt-services.woodpecker-agents.agents._name_.enable).

- [woodpecker-server](https://woodpecker-ci.org/), a simple CI engine with great extensibility. Available as [services.woodpecker-server](#opt-services.woodpecker-server.enable).
+1 −0
Original line number Diff line number Diff line
@@ -1044,6 +1044,7 @@
  ./services/networking/wg-netmanager.nix
  ./services/networking/webhook.nix
  ./services/networking/wg-quick.nix
  ./services/networking/wgautomesh.nix
  ./services/networking/wireguard.nix
  ./services/networking/wpa_supplicant.nix
  ./services/networking/wstunnel.nix
+161 −0
Original line number Diff line number Diff line
{ lib, config, pkgs, ... }:
with lib;
let
  cfg = config.services.wgautomesh;
  settingsFormat = pkgs.formats.toml { };
  configFile =
    # Have to remove nulls manually as TOML generator will not just skip key
    # if value is null
    settingsFormat.generate "wgautomesh-config.toml"
      (filterAttrs (k: v: v != null)
        (mapAttrs
          (k: v:
            if k == "peers"
            then map (e: filterAttrs (k: v: v != null) e) v
            else v)
          cfg.settings));
  runtimeConfigFile =
    if cfg.enableGossipEncryption
    then "/run/wgautomesh/wgautomesh.toml"
    else configFile;
in
{
  options.services.wgautomesh = {
    enable = mkEnableOption (mdDoc "the wgautomesh daemon");
    logLevel = mkOption {
      type = types.enum [ "trace" "debug" "info" "warn" "error" ];
      default = "info";
      description = mdDoc "wgautomesh log level.";
    };
    enableGossipEncryption = mkOption {
      type = types.bool;
      default = true;
      description = mdDoc "Enable encryption of gossip traffic.";
    };
    gossipSecretFile = mkOption {
      type = types.path;
      description = mdDoc ''
        File containing the shared secret key to use for gossip encryption.
        Required if `enableGossipEncryption` is set.
      '';
    };
    enablePersistence = mkOption {
      type = types.bool;
      default = true;
      description = mdDoc "Enable persistence of Wireguard peer info between restarts.";
    };
    openFirewall = mkOption {
      type = types.bool;
      default = true;
      description = mdDoc "Automatically open gossip port in firewall (recommended).";
    };
    settings = mkOption {
      type = types.submodule {
        freeformType = settingsFormat.type;
        options = {

          interface = mkOption {
            type = types.str;
            description = mdDoc ''
              Wireguard interface to manage (it is NOT created by wgautomesh, you
              should use another NixOS option to create it such as
              `networking.wireguard.interfaces.wg0 = {...};`).
            '';
            example = "wg0";
          };
          gossip_port = mkOption {
            type = types.port;
            description = mdDoc ''
              wgautomesh gossip port, this MUST be the same number on all nodes in
              the wgautomesh network.
            '';
            default = 1666;
          };
          lan_discovery = mkOption {
            type = types.bool;
            default = true;
            description = mdDoc "Enable discovery of peers on the same LAN using UDP broadcast.";
          };
          upnp_forward_external_port = mkOption {
            type = types.nullOr types.port;
            default = null;
            description = mdDoc ''
              Public port number to try to redirect to this machine's Wireguard
              daemon using UPnP IGD.
            '';
          };
          peers = mkOption {
            type = types.listOf (types.submodule {
              options = {
                pubkey = mkOption {
                  type = types.str;
                  description = mdDoc "Wireguard public key of this peer.";
                };
                address = mkOption {
                  type = types.str;
                  description = mdDoc ''
                    Wireguard address of this peer (a single IP address, multliple
                    addresses or address ranges are not supported).
                  '';
                  example = "10.0.0.42";
                };
                endpoint = mkOption {
                  type = types.nullOr types.str;
                  description = mdDoc ''
                    Bootstrap endpoint for connecting to this Wireguard peer if no
                    other address is known or none are working.
                  '';
                  default = null;
                  example = "wgnode.mydomain.example:51820";
                };
              };
            });
            default = [ ];
            description = mdDoc "wgautomesh peer list.";
          };
        };

      };
      default = { };
      description = mdDoc "Configuration for wgautomesh.";
    };
  };

  config = mkIf cfg.enable {
    services.wgautomesh.settings = {
      gossip_secret_file = mkIf cfg.enableGossipEncryption "$CREDENTIALS_DIRECTORY/gossip_secret";
      persist_file = mkIf cfg.enablePersistence "/var/lib/wgautomesh/state";
    };

    systemd.services.wgautomesh = {
      path = [ pkgs.wireguard-tools ];
      environment = { RUST_LOG = "wgautomesh=${cfg.logLevel}"; };
      description = "wgautomesh";
      serviceConfig = {
        Type = "simple";

        ExecStart = "${getExe pkgs.wgautomesh} ${runtimeConfigFile}";
        Restart = "always";
        RestartSec = "30";
        LoadCredential = mkIf cfg.enableGossipEncryption [ "gossip_secret:${cfg.gossipSecretFile}" ];

        ExecStartPre = mkIf cfg.enableGossipEncryption [
          ''${pkgs.envsubst}/bin/envsubst \
              -i ${configFile} \
              -o ${runtimeConfigFile}''
        ];

        DynamicUser = true;
        StateDirectory = "wgautomesh";
        StateDirectoryMode = "0700";
        RuntimeDirectory = "wgautomesh";
        AmbientCapabilities = "CAP_NET_ADMIN";
        CapabilityBoundingSet = "CAP_NET_ADMIN";
      };
      wantedBy = [ "multi-user.target" ];
    };
    networking.firewall.allowedUDPPorts =
      mkIf cfg.openFirewall [ cfg.settings.gossip_port ];
  };
}
+25 −0
Original line number Diff line number Diff line
{ lib
, fetchFromGitea
, rustPlatform
}:
rustPlatform.buildRustPackage rec {
  pname = "wgautomesh";
  version = "0.1.0";

  src = fetchFromGitea {
    domain = "git.deuxfleurs.fr";
    owner = "Deuxfleurs";
    repo = "wgautomesh";
    rev = "v${version}";
    sha256 = "FiFEpYLSJg52EtBXaZ685ICbaIyY9URrDt0bS0HPi0Q=";
  };

  cargoHash = "sha256-DGDVjQ4fr4/F1RE0qVc5CWcXrrCEswCF7rQQwlKzMPA=";

  meta = with lib; {
    description = "A simple utility to help connect wireguard nodes together in a full mesh topology";
    homepage = "https://git.deuxfleurs.fr/Deuxfleurs/wgautomesh";
    license = licenses.agpl3Only;
    maintainers = [ maintainers.lx ];
  };
}
Loading