diff --git a/lib/bootstrap.py b/lib/bootstrap.py
index 6ebb7c8df679195e8a4cd24ee6707a7f809b5ad1..dc9279257fcbb17123e58511044ac6980ca5035d 100644
--- a/lib/bootstrap.py
+++ b/lib/bootstrap.py
@@ -700,7 +700,7 @@ def FinalizeClusterDestroy(master):
                     " the node: %s", msg)
 
 
-def SetupNodeDaemon(cluster_name, node, ssh_key_check):
+def SetupNodeDaemon(opts, cluster_name, node):
   """Add a node to the cluster.
 
   This function must be called before the actual opcode, and will ssh
@@ -709,36 +709,19 @@ def SetupNodeDaemon(cluster_name, node, ssh_key_check):
 
   @param cluster_name: the cluster name
   @param node: the name of the new node
-  @param ssh_key_check: whether to do a strict key check
 
   """
-  sstore = ssconf.SimpleStore()
-  family = sstore.GetPrimaryIPFamily()
-  sshrunner = ssh.SshRunner(cluster_name,
-                            ipv6=(family == netutils.IP6Address.family))
-
-  # set up inter-node password and certificate and restarts the node daemon
-  # and then connect with ssh to set password and start ganeti-noded
-  # note that all the below variables are sanitized at this point,
-  # either by being constants or by the checks above
-  sshrunner.CopyFileToNode(node, pathutils.NODED_CERT_FILE)
-  sshrunner.CopyFileToNode(node, pathutils.RAPI_CERT_FILE)
-  sshrunner.CopyFileToNode(node, pathutils.SPICE_CERT_FILE)
-  sshrunner.CopyFileToNode(node, pathutils.SPICE_CACERT_FILE)
-  sshrunner.CopyFileToNode(node, pathutils.CONFD_HMAC_KEY)
-  for filename in sstore.GetFileList():
-    sshrunner.CopyFileToNode(node, filename)
-  mycommand = ("%s stop-all; %s start %s" %
-               (pathutils.DAEMON_UTIL, pathutils.DAEMON_UTIL, constants.NODED))
-
-  result = sshrunner.Run(node, constants.SSH_LOGIN_USER, mycommand, batch=False,
-                         ask_key=ssh_key_check,
-                         use_cluster_key=True,
-                         strict_host_check=ssh_key_check)
-  if result.failed:
-    raise errors.OpExecError("Remote command on node %s, error: %s,"
-                             " output: %s" %
-                             (node, result.fail_reason, result.output))
+  data = {
+    constants.NDS_CLUSTER_NAME: cluster_name,
+    constants.NDS_NODE_DAEMON_CERTIFICATE:
+      utils.ReadFile(pathutils.NODED_CERT_FILE),
+    constants.NDS_SSCONF: ssconf.SimpleStore().ReadAll(),
+    constants.NDS_START_NODE_DAEMON: True,
+    }
+
+  RunNodeSetupCmd(cluster_name, node, pathutils.NODE_DAEMON_SETUP,
+                  opts.debug, opts.verbose,
+                  True, opts.ssh_key_check, opts.ssh_key_check, data)
 
   _WaitForNodeDaemon(node)
 
diff --git a/lib/client/gnt_node.py b/lib/client/gnt_node.py
index 04965d3afff4ce4a95a1160c67408b64ef53c83e..6bf6bf683c1ecd7f4682e53d4136d5b592f2edbf 100644
--- a/lib/client/gnt_node.py
+++ b/lib/client/gnt_node.py
@@ -270,7 +270,7 @@ def AddNode(opts, args):
   if opts.node_setup:
     _SetupSSH(opts, cluster_name, node)
 
-  bootstrap.SetupNodeDaemon(cluster_name, node, opts.ssh_key_check)
+  bootstrap.SetupNodeDaemon(opts, cluster_name, node)
 
   if opts.disk_state:
     disk_state = utils.FlatToDict(opts.disk_state)
diff --git a/lib/pathutils.py b/lib/pathutils.py
index b5800c0502b0b38d131789186fa535ac6133675d..8bea0a6e72fc487af25fb2b2fb484ab3076ea971 100644
--- a/lib/pathutils.py
+++ b/lib/pathutils.py
@@ -44,6 +44,7 @@ IMPORT_EXPORT_DAEMON = _autoconf.PKGLIBDIR + "/import-export"
 KVM_CONSOLE_WRAPPER = _autoconf.PKGLIBDIR + "/tools/kvm-console-wrapper"
 KVM_IFUP = _autoconf.PKGLIBDIR + "/kvm-ifup"
 PREPARE_NODE_JOIN = _autoconf.PKGLIBDIR + "/prepare-node-join"
+NODE_DAEMON_SETUP = _autoconf.PKGLIBDIR + "/node-daemon-setup"
 XEN_CONSOLE_WRAPPER = _autoconf.PKGLIBDIR + "/tools/xen-console-wrapper"
 ETC_HOSTS = vcluster.ETC_HOSTS