aboutsummaryrefslogblamecommitdiff
path: root/nix/wgautomesh.nix
blob: 0e0b7b3d9e0b2d2fc06023c41911b407b8795a15 (plain) (tree)
1
2
3
4


                                                    
                                                     




















                                                          



                                                                         



                                                                   
















































                                                                                             

                                                                            

                                                                 




                                                                                                 
                                          
 
                                         















                                                                   

                                                                                                         
                             


                                        








                                                                                     
let
  src = builtins.fetchGit {
    url = "https://git.deuxfleurs.fr/lx/wgautomesh";
    rev = "65e979de801daa5f6ef77ed875e6505aa902fd9c";
  };
  wgautomesh = (import src).packages.x86_64-linux.default;
in

{ lib, config, pkgs, ... }:
with lib;
let 
  cfg = config.services.wgautomesh;
in
  with builtins;
  {
    options.services.wgautomesh = {
      enable = mkEnableOption "wgautomesh";
      interface = mkOption {
        type = types.str;
        description = "Wireguard interface to manage";
      };
      gossipPort = mkOption {
        type = types.port;
        description = "wgautomesh gossip port";
      };
      gossipSecretFile = mkOption {
        type = types.nullOr types.str;
        description = "File containing the gossip secret encryption key";
      };
      persistFile = mkOption {
        type = types.nullOr types.str;
        description = "Path where to persist known peer addresses";
      };
      lanDiscovery = mkOption {
        type = types.bool;
        default = true;
        description = "Enable discovery using LAN broadcast";
      };
      openFirewall = mkOption {
        type = types.bool;
        default = true;
        description = "Automatically open gossip port in firewall";
      };
      upnpForwardPublicPort = mkOption {
        type = types.nullOr types.port;
        default = null;
        description = "Public port number to try to redirect to this machine using UPnP IGD";
      };
      peers = mkOption {
        type = types.listOf (types.submodule {
          options = {
            pubkey = mkOption {
              type = types.str;
              description = "Wireguard public key";
            };
            address = mkOption {
              type = types.str;
              description = "Wireguard peer address";
            };
            endpoint = mkOption {
              type = types.nullOr types.str;
              description = "bootstrap endpoint";
            };
          };
        });
        description = "wgautomesh peer list";
      };
    };

    config = mkIf cfg.enable ( 
    let
      peerDefs = map (peer:
        let endpointDef = if peer.endpoint == null then ""
        else ''endpoint = "${peer.endpoint}"'';
        in
        ''
          [[peers]]
          pubkey = "${peer.pubkey}"
          address = "${peer.address}"
          ${endpointDef}
        '') cfg.peers;
      extraDefs = (if cfg.lanDiscovery then ["lan_discovery = true"] else [])
        ++ (if (cfg.gossipSecretFile != null)
          then [''gossip_secret_file = "${cfg.gossipSecretFile}"''] else [])
        ++ (if (cfg.persistFile != null)
          then [''persist_file = "${cfg.persistFile}"''] else [])
        ++ (if (cfg.upnpForwardPublicPort != null)
          then [''upnp_forward_external_port = ${toString cfg.upnpForwardPublicPort}''] else []);
      configfile = pkgs.writeText "wgautomesh.toml" ''
        interface = "${cfg.interface}"
        gossip_port = ${toString cfg.gossipPort}
        ${concatStringsSep "\n" extraDefs}

        ${concatStringsSep "\n" peerDefs}
        '';
    in {
      systemd.services.wgautomesh = {
        enable = true;
        path = [ pkgs.wireguard-tools ];
        environment = {
          RUST_LOG = "wgautomesh=info";
        };
        description = "wgautomesh";
        serviceConfig = {
          Type = "simple";

          ExecStart = "${wgautomesh}/bin/wgautomesh ${configfile}";
          Restart = "always";
          RestartSec = "30";

          ExecStartPre = [ "+${pkgs.coreutils}/bin/chown wgautomesh /var/lib/wgautomesh/gossip_secret" ];

          DynamicUser = true;
          User = "wgautomesh";
          StateDirectory = "wgautomesh";
          StateDirectoryMode = "0700";
          AmbientCapabilities = "CAP_NET_ADMIN CAP_NET_BIND_SERVICE";
          CapabilityBoundingSet = "CAP_NET_ADMIN CAP_NET_BIND_SERVICE";
        };
        wantedBy = [ "multi-user.target" ];
      };
      networking.firewall.allowedUDPPorts = mkIf cfg.openFirewall [ cfg.gossipPort ];
    });
  }