Unverified Commit 5366d24e authored by Sandro Jäckel's avatar Sandro Jäckel Committed by GitHub
Browse files

nixos/netbird: automated login using Setup Keys file (#444291)

parents de77917f 8dbd7f2d
Loading
Loading
Loading
Loading
+88 −0
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ let
    mapAttrsToList
    mkAliasOptionModule
    mkDefault
    mkEnableOption
    mkIf
    mkMerge
    mkOption
@@ -31,6 +32,7 @@ let
    optionalAttrs
    optionalString
    optionals
    pipe
    toShellVars
    versionAtLeast
    versionOlder
@@ -40,6 +42,7 @@ let
    attrsOf
    bool
    enum
    listOf
    nullOr
    package
    path
@@ -222,6 +225,26 @@ in
                '';
              };

              login.enable = mkEnableOption "automated login for NetBird client";
              login.setupKeyFile = mkOption {
                type = nullOr str;
                default = null;
                example = "/run/secrets/netbird-priv/setup-key";
                description = ''
                  A Setup Key file path used for automated login of the machine.
                '';
              };
              login.systemdDependencies = mkOption {
                type = listOf str;
                default = [ ];
                example = lib.literalExpression ''
                  [ "sops-install-secrets.service" ]
                '';
                description = ''
                  Additional systemd dependencies required to succeed before the Setup Key file becomes available.
                '';
              };

              openFirewall = mkOption {
                type = bool;
                default = true;
@@ -697,6 +720,71 @@ in
        });
      '';
    })
    # Setup Keys login automation
    {
      systemd.services = pipe cfg.clients [
        (filterAttrs (_: client: client.login.enable))
        (mapAttrs' (
          _: client:
          nameValuePair "${client.service.name}-login" {
            after = [ "${client.service.name}.service" ] ++ client.login.systemdDependencies;
            requires = [ "${client.service.name}.service" ] ++ client.login.systemdDependencies;
            wantedBy = [ "${client.service.name}.service" ];

            serviceConfig = {
              Type = "oneshot";
              RemainAfterExit = true;

              User = client.user.name;
              Group = client.user.group;

              RemoveIPC = true;
              PrivateTmp = "disconnected"; # "disconnected" puts /tmp on `tmpfs`
              ProtectSystem = "strict";
              ProtectHome = "yes";

              LoadCredential = [ "setup-key:${client.login.setupKeyFile}" ];
            };

            environment.NB_SETUP_KEY_FILE = "%d/setup-key";
            /*
              might want to do something similar to the docker entrypoint (watching log messages) instead
              see https://github.com/netbirdio/netbird/blob/dc30dcacce4c322502975f1f491e6774efd7e1e9/client/netbird-entrypoint.sh
            */
            script = ''
              set -x
              # uses a file on a `tmpfs`, because variable updates get lost in the loop
              status_file="/tmp/status.txt"

              refresh_status() {
                '${lib.getExe client.wrapper}' status &>"$status_file" || :
              }

              print_short_setup_key() {
                cut -b1-8 <"$NB_SETUP_KEY_FILE"
              }

              main() {
                refresh_status
                <"$status_file" sed 's/^/STATUS:PRE-CONNECT : /g'

                until refresh_status && <"$status_file" grep --quiet 'Connected\|NeedsLogin' ; do
                  sleep 1
                done
                <"$status_file" sed 's/^/STATUS:POST-CONNECT: /g'

                if <"$status_file" grep --quiet 'NeedsLogin' ; then
                  echo "Using Setup Key File with key: $(print_short_setup_key)" >&2
                  '${lib.getExe client.wrapper}' up --setup-key-file="$NB_SETUP_KEY_FILE"
                fi
              }

              main "$@"
            '';
          }
        ))
      ];
    }
    # migration & temporary fixups section
    {
      systemd.services = toClientAttrs (