diff --git a/backup-tar/backup.sh b/backup-tar/backup.sh
index ac1bc7918ccb56078e0c215278b546637c9061f1..c36972d73219accb15f6e280f4612b0eb99c78fa 100755
--- a/backup-tar/backup.sh
+++ b/backup-tar/backup.sh
@@ -1,6 +1,6 @@
 #!/usr/bin/env bash
 
-set -e
+set -Eeuo pipefail
 
 SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
 
@@ -13,7 +13,7 @@ fail() {
     exit 1
 }
 
-if [[ $1 ]]; then
+if [[ ${1:-} ]]; then
     . $1
     [[ $WORK_DIR ]] && mkdir -p $WORK_DIR && cd $WORK_DIR
 else
@@ -22,12 +22,13 @@ else
     SOURCES_FILE=$SCRIPT_DIR/sources_$SHORT_HOST
     . $SOURCES_FILE
 fi
-[[ $TARGET ]] || fail "TARGET expected to be set in config"
-[[ $SOURCES ]] || fail "SOURCES expected to be set in $SOURCES_FILE or config"
+[[ ${TARGET:-} ]] || fail "TARGET expected to be set in config"
+[[ ${SOURCES:-} ]] || fail "SOURCES expected to be set in $SOURCES_FILE or config"
 TIMESTAMP=$(date +"%Y-%m-%d")
 
 mkdir lock || fail "ERROR: backup already in progress (lock dir exists)"
-trap "rmdir lock" EXIT
+function trap_global { rmdir lock; }
+trap trap_global EXIT
 
 get_snars() { find $1/ -type f -name '*.snar' -printf '%f\n' | sort; }
 get_type() {
@@ -91,20 +92,28 @@ for SRC in $SOURCES; do
     fi
 
     ssh $TARGET "mkdir -p stamps/${SRC_ID} ${SRC_ID}"
-    [[ "$TYPE" != "daily" ]] && echo "Backup $SRC ($TYPE)…"
+
+    function trap_local {
+        ssh $TARGET "rm -f $BACKUP_FILE.tmp $INCFILE.tmp"
+        rm -f $INCFILE_TMP
+        trap_global
+    }
+    trap trap_local EXIT;
+
+    echo "Backup $SRC ($TYPE)…"
     {
         {
             tar --create --xattrs --acls --listed-incremental=$INCFILE_TMP $SRC | \
                     xz -T$COMPRESS_THRS -3 | \
-                    ssh $TARGET "umask 0027; cat > $BACKUP_FILE"
+                    ssh $TARGET "umask 0027; cat > $BACKUP_FILE.tmp"
         } 3>&1 1>&2 2>&3 | \
                 { grep -v "Removing leading \`/'" || true; } | \
                 { grep -v "socket ignored" || true; }
     } 3>&1 1>&2 2>&3
-    xz -T$COMPRESS_THRS --keep --stdout $INCFILE_TMP | ssh $TARGET "umask 0027; cat > $INCFILE_TGT"
+    xz -T$COMPRESS_THRS --keep --stdout $INCFILE_TMP | ssh $TARGET "umask 0027; cat > $INCFILE_TGT.tmp"
     if echo $SRC | grep -q '^/home'; then
         USR=$(echo $SRC | sed 's|^/home/\([^/]*\).*$|\1|')
-        ssh $TARGET "setfacl -m 'u:$USR:r' $BACKUP_FILE"
+        ssh $TARGET "setfacl -m 'u:$USR:r' $BACKUP_FILE.tmp"
         DIR=$(dirname $BACKUP_FILE)
         while true; do
             ssh $TARGET "setfacl -m 'u:$USR:rx' $DIR"
@@ -112,5 +121,7 @@ for SRC in $SOURCES; do
             DIR=$(dirname $DIR)
         done
     fi
+    ssh $TARGET "mv $BACKUP_FILE{.tmp,}; mv $INCFILE_TGT{.tmp,}"
+    trap trap_global EXIT
     mv $INCFILE_TMP $INCFILE
 done