diff --git a/jobhelper.sh b/jobhelper.sh
index 497b5bae81e8919bb55f2fe237b54e424c0de54a..6b895c138bf4a73cf0483fa62771ef2f87b2d113 100755
--- a/jobhelper.sh
+++ b/jobhelper.sh
@@ -416,60 +416,6 @@ function j_requireUser(){
   fi
 }
 
-# ------------------------------------------------------------
-# call storage helper; "private" function
-# param  string  command, i.e. register|unregister [hostname]
-# ------------------------------------------------------------
-function _j_storagehelper(){
-  # get user and targethost
-  # rsync://[backupuser]@[storage]//[targetdir]/
-
-  sProtocol=`j_getFullTarget "" | cut -f 1 -d ":"`
-  if [ ${sProtocol} = "rsync" -o ${sProtocol} = "scp" -o ${sProtocol} = "sftp" ]; then
-
-    sSshTarget=`j_getFullTarget "" | cut -f 3 -d "/"`
-    # echo target: $sSshTarget
-    if [ ! -z $sSshTarget ]; then
-
-      sSshParams=
-      sFileSshPrivkey=`_j_getvar ${STORAGEFILE} "ssh-privatekey"`
-      if [ ! -z $sFileSshPrivkey ]; then
-        sSshParams="${sSshParams} -i ${sFileSshPrivkey}"
-      fi
-
-      ssh ${sSshParams} $sSshTarget ./storage_helper.sh $*
-
-    fi
-  else
-    echo INFO: storage protocol is $sProtocol - skipping ssh to storage_helper.
-  fi
-}
-
-# ------------------------------------------------------------
-# transfer start: wait for a free slot
-# ------------------------------------------------------------
-function j_transferStart(){
-  iExit=1
-  until [  $iExit -eq 0 ]; do
-    _j_storagehelper register `hostname -f`
-    iExit=$?
-    if [ $iExit -ne 0 ]; then
-        _j_storagehelper status
-        iRnd=$(($RANDOM%30+30))
-        echo "I wait a bit ... random time ... $iRnd sec ..."
-        sleep $iRnd
-    fi
-  done
-}
-
-# ------------------------------------------------------------
-# transfer end: free used slot on storage
-# ------------------------------------------------------------
-function j_transferEnd(){
-    _j_storagehelper unregister `hostname -f`
-}
-
-
 # ----------------------------------------------------------------------
 # INIT
 # ----------------------------------------------------------------------
diff --git a/jobs/transfer.job.dist b/jobs/transfer.job.dist
index d3948e4c4c536792d445ef1bf0d0938922e1796b..e97d3f10ddebb2946808dff1198829667f038759 100644
--- a/jobs/transfer.job.dist
+++ b/jobs/transfer.job.dist
@@ -44,6 +44,14 @@
 # HINT: if using scp:// on Debian 8 enable ssh-backend; default: no value
 # duplicity_ssh-backend = pexpect
 
+# for local or locally mounted targets - you can add a test file that must be found
+# to detect that a backup volume is mounted
+# storage-file = /run/media/backup/I_am_mounted.txt
+
+# OPTIONAL: register for a backup slot
+# storage-register = ssh
+# storage-registercmd = ./storage_helper.sh
+
 
 # ----------------------------------------------------------------------
 # BASIC settings
diff --git a/plugins/register/readme.md b/plugins/register/readme.md
new file mode 100644
index 0000000000000000000000000000000000000000..1885646b5c4dfc0ba0a0a015198cae92ddda65e4
--- /dev/null
+++ b/plugins/register/readme.md
@@ -0,0 +1,58 @@
+# Help plugins/register/
+
+Here are plugins to control count of simultanous backups.
+
+For SSH based backup of more than - let's say - 10 servers you should
+think about to enable that feature.
+
+A backup will register before starting a file transfer
+and unregister when the backup is finished.
+
+Plugins:
+
+* ssh.sh - execute a remote command via ssh on backup target using backup user
+
+The configuration is in `[APPDIR]/jobs/transfer.job`
+
+```text
+# register for a backup slot
+storage-register = [plugin]
+```
+
+## Plugins
+
+### ssh
+
+Executes a ssh command. Its limitation is that it automatically connects
+with the same user, its privatekey and the same host like ssh backend.
+
+You need just one additional config entry for the remote command to execute.
+
+Example config:
+
+```text
+# register for a backup slot
+storage-register = ssh
+storage-registercmd = ./storage_helper.sh
+```
+
+See the project https://git-repo.iml.unibe.ch/iml-open-source/iml-backup-server
+for a bash implementation of a counter with `storage_helper.sh`.
+
+## Developer notes
+
+You can create another registration process. You need to add your own
+register plugin `[plugin].sh` that contains these functions:
+
+* registerBackupSlot \
+  A command on a control instance can handles the counts. If the limit is reached it sends returncode <> 0.
+  The backup client will wait a random time before asking for a free slot again.
+
+* unregisterBackupSlot \
+  A backup sends an unregister command to unlock a given slot.
+  The control instance needs to free the slot.
+
+* statusBackupSlot \
+  Show currently used slots.
+
+The file needs no execute permissions - read permissions are enough i.e. `chmod 644 [plugin].sh`.
diff --git a/plugins/register/ssh.sh b/plugins/register/ssh.sh
new file mode 100755
index 0000000000000000000000000000000000000000..fcaaa1c4594bd814cafb5a9ac31b0b85a5939fc5
--- /dev/null
+++ b/plugins/register/ssh.sh
@@ -0,0 +1,65 @@
+#!/usr/bin/env bash
+# ================================================================================
+#
+# REGISTER :: SSH
+# SSH command to register/ unregister
+#
+# --------------------------------------------------------------------------------
+# ah - Axel Hahn <axel.hahn@iml.unibe.ch>
+#
+# 2021-05-31  ah  v1.0  first lines
+# ================================================================================
+
+# --------------------------------------------------------------------------------
+# FUNCTIONS
+# --------------------------------------------------------------------------------
+
+# @private function
+# detect ssh params and storage-registercmd to run ssh remote command
+# param  string  action; one of register|unregrister|status
+# param  string  hostname; given for register and unregister
+function _runssh(){
+  
+  sProtocol=`j_getFullTarget "" | cut -f 1 -d ":"`
+  if [ ${sProtocol} = "rsync" -o ${sProtocol} = "scp" -o ${sProtocol} = "sftp" ]; then
+
+    sSshTarget=`j_getFullTarget "" | cut -f 3 -d "/"`
+    if [ ! -z $sSshTarget ]; then
+
+      sSshParams=
+      sFileSshPrivkey=`_j_getvar ${STORAGEFILE} "ssh-privatekey"`
+      if [ ! -z $sFileSshPrivkey ]; then
+        sSshParams="${sSshParams} -i ${sFileSshPrivkey}"
+      fi
+
+      sSshCmd=`_j_getvar ${STORAGEFILE} "storage-registercmd"`
+      
+      if [ -z "$sSshCmd" ]; then
+        echo "WARNING: Missing storage-registercmd = ... in ${STORAGEFILE} for a command to execute via SSH."
+      else
+        echo ssh ${sSshParams} ${sSshTarget} ${sSshCmd} $*
+        color cmd
+        ssh ${sSshParams} ${sSshTarget} ${sSshCmd} $*
+        color reset
+      fi
+    fi
+  else
+    echo INFO: storage protocol is $sProtocol - skipping register via ssh.
+  fi
+}
+
+# --------------------------------------------------------------------------------
+# functions called in [APPDIR]/transfer.sh
+
+function registerBackupSlot(){
+    _runssh register $1
+}
+
+function unregisterBackupSlot(){
+    _runssh unregister $1
+}
+function statusBackupSlot(){
+    _runssh status
+}
+
+# --------------------------------------------------------------------------------
\ No newline at end of file
diff --git a/transfer.sh b/transfer.sh
index 70a2ab6b5e8358e4953d0e813570ebe0967f54c1..35cf788821d9a826a576d1bc49615059e29e91eb 100755
--- a/transfer.sh
+++ b/transfer.sh
@@ -45,6 +45,8 @@
   STORAGE_TESTFILE=`_j_getvar ${STORAGEFILE} "storage-file"`
   PASSPHRASE=`_j_getvar ${STORAGEFILE} "passphrase"`
 
+  STORAGE_REGISTER=`_j_getvar ${STORAGEFILE} "storage-register"`
+
   # check
   if [ -z "$STORAGE_BIN" ]; then
     # STORAGE_BIN=restic
@@ -99,15 +101,16 @@
 
 
   
-  h1 `date` TRANSFER LOCAL DATA TO STORAGE                                             | tee -a $transferlog
+  h1 `date` TRANSFER LOCAL DATA TO STORAGE                      | tee -a $transferlog
   
-  echo "METHOD: $METHOD"                                                               | tee -a $transferlog
-  echo "TARGET: ${STORAGE_BASEDIR}"                                                    | tee -a $transferlog
-  echo "TOOL  : $STORAGE_BIN"                                                          | tee -a $transferlog
-  echo                                                                                 | tee -a $transferlog
+  echo "METHOD   : $METHOD"                                     | tee -a $transferlog
+  echo "TARGET   : ${STORAGE_BASEDIR}"                          | tee -a $transferlog
+  echo "REGISTER : ${STORAGE_REGISTER}"                         | tee -a $transferlog
+  echo "TOOL     : $STORAGE_BIN"                                | tee -a $transferlog
+  echo                                                          | tee -a $transferlog
 
   . `dirname $0`/plugins/transfer/$STORAGE_BIN.sh || exit 1
-
+  test -z "$STORAGE_REGISTER" || . `dirname $0`/plugins/register/$STORAGE_REGISTER.sh || exit 1
 
 # --------------------------------------------------------------------------------
 # ----- Check requirements
@@ -197,7 +200,24 @@
 # ----- PRE transfer
 
   h2 "`date` Wait for a free slot"
-  j_transferStart | tee -a $transferlog
+  if [ -z "$STORAGE_REGISTER" ]; then
+    echo "SKIP"
+  else
+    iExit=1
+    until [ $iExit -eq 0 ]; do
+      registerBackupSlot `hostname -f`
+      iExit=$?
+      if [ $iExit -ne 0 ]; then
+          statusBackupSlot
+          iRnd=$(($RANDOM%30+30))
+          echo "I wait a bit ... random time ... $iRnd sec ..."
+          sleep $iRnd
+      fi
+    done
+  fi | tee -a $transferlog
+
+  # TODO: remove in jobhelper
+  # j_transferStart | tee -a $transferlog
 
   h2 "`date` PRE transfer tasks"
   t_backupDoPreTasks
@@ -302,13 +322,17 @@
   h2 "`date` POST transfer tasks"
   t_backupDoPostTasks
 
-
   rm -f "${lockfile}" "${rcfile}"
   echo "Local lock file was removed."
 
+  h2 "`date` Unregister used slot"
+  if [ -z "$STORAGE_REGISTER" ]; then
+    echo "SKIP"
+  else
+    unregisterBackupSlot `hostname -f`
+  fi | tee -a $transferlog
 
-  j_transferEnd
-
+  h2 "`date` Backup finished"
   echo STATUS $0 exit with final returncode rc=$rc                                    | tee -a $transferlog
   echo                                                                                | tee -a $transferlog
   if [ $rc -eq 0 ]; then