Skip to content

Accessing Old Backups from Datto Reverse RoundTrip Drives

This guide walks Datto customers through the process of manually recovering original backup data from a Datto Reverse RoundTrip drive using Ubuntu Linux.

While the steps are technical, we've worked to make them as clear and straightforward as possible. If you normally use Windows, don't worry — the guide covers everything you need to follow along.

We're also developing similar guides for recovering backups from Axcient and other providers. For Slide users, see Manually Accessing Backup Data on a Slide Box.

If you need help, contact Slide Support.

Info

This guide is based entirely on analysis by Cursor AI, which examined Datto Reverse RoundTrip drives and uncovered how the encryption works — including how to derive raw decryption keys from agent passphrases and how the data is laid out on disk. We followed its guidance step by step and recorded the full process in a screencast.

The guide was created using only Reverse RoundTrip drives provided by our customers (along with associated pool and agent passphrases) and insights from Cursor AI. No other resources were used.

Overview

This guide will help you to:

  • Create a bootable USB Ubuntu Linux environment
  • Import the ZFS pool from your RoundTrip drive which contains your backup data
  • Decrypt and access your old Datto backups, including files and folders from unencrypted and encrypted agents
  • Mount and copy your important files to another location

Anatomy of a Drive

A Reverse RoundTrip drive contains your backup data in ZFS format, which can be accessed using Ubuntu Linux (or any other Linux distribution that supports ZFS).

Typically, the drive you receive contains two partitions:

  • Partition 1: A 25 MB ext4 partition that contains a metadata.json file. This file contains the original Datto Device ID, the ZFS pool name, and GUIDs for the encrypted ZFS pool.
  • Partition 2: A LUKS-encrypted partition containing the ZFS pool with your backup data. The passphrase for this encryption can be requested from Datto Support. In this guide, we will refer to this passphrase as the pool passphrase.

Once decrypted, the ZFS pool can be imported via zpool import. Your backup data resides on the pool, organized by protected systems (agents). Each agent has its own dataset, which contains one file per volume (e.g. one file for your C:\ drive, one for D:\ drive, etc.).

Your agent backup data may be stored in two formats:

  • For unencrypted agents, each volume is stored as raw disk image files with a single partition. The files can be identified by the .datto extension.
  • For encrypted agents, each volume is stored as AES-XTS-encrypted raw disk image with a single partition. It is encrypted using cryptsetup (plain, aes-xts-plain64). The files can be identified by the .detto extension and require decryption before access (see below). To decrypt these files, you will need the agent password(s), which you should know yourself. Each agent may have a different password.

Prerequisites

  • A Reverse RoundTrip drive from Datto Support (request here)
  • The pool passphrase provided by Datto Support (see instructions here)
  • The agent password(s) if you have encrypted agents (may be different passwords for different agents)
  • A USB drive with at least 8 GB capacity (will be erased)
  • A computer with at least 8 GB RAM and ability to boot from USB
  • Basic comfort following technical instructions

Step 1: Download Ubuntu

Once you received the Reverse RoundTrip drive and are in possession of the pool passphrase, you will need to download Ubuntu Linux to create a bootable USB drive.

  1. Go to https://ubuntu.com/download/desktop
  2. Download the latest Ubuntu Desktop LTS (Long Term Support) version
  3. You'll get a file named something like ubuntu-24.04.3-desktop-amd64.iso

Step 2: Create Bootable USB

  1. Download Rufus: Go to https://rufus.ie and download Rufus
  2. Insert USB drive (at least 8GB, will be erased!)
  3. Run Rufus as Administrator
  4. Configure Rufus:
    • Device: Select your USB drive
    • Boot selection: Click "SELECT" and choose your Ubuntu ISO file
    • Partition scheme: GPT
    • Target system: UEFI
  5. Click START and wait for completion (takes 5-15 minutes)

Step 3: Boot Ubuntu from USB

  1. Connect your Ubuntu USB drive to your computer
  2. Restart your computer and boot from USB:
    • Dell: Press F12 during startup
    • HP: Press F9 or F12 during startup
    • Lenovo: Press F12 during startup
    • ASUS: Press F8 or ESC during startup
    • Generic: Press F11, F12, DEL, or ESC during startup
  3. Select your USB drive from the boot menu
  4. Choose "Try Ubuntu" or "Try or install Ubuntu" (not "Install Ubuntu")
  5. Connect the Datto Reverse RoundTrip drive to your computer

Try Ubuntu

Booting the Ubuntu Live CD: Select "Try Ubuntu"

Step 4: Access Ubuntu Terminal

Once Ubuntu is running:

First, click the "Show Applications" button (dots in top-left corner), then, type "terminal" and press Enter:

Ubuntu Show Applications Ubuntu Terminal

Opening the Ubuntu Terminal from the Applications menu

Next, become root user by typing sudo su and pressing Enter. You should now see a prompt like root@ubuntu:/home/ubuntu#:

Ubuntu Sudo Su

Become a super user

Step 5: Decrypt the ZFS pool

To access the ZFS pool that contains your agent backup data, you need to first decrypt the ZFS pool. Datto provides instructions in the knowledge base article, but here's a more detailed version:

Step 5.1: Identify Your Drive

Run lsblk to list all connected drives. You should see your Reverse RoundTrip drive listed, typically as /dev/sda, /dev/sdb, or similar. It will have two partitions:

  • one 25 MB partition used for metadata
  • and one large partition that contains the ZFS pool and your backup data

Ubuntu List Block Devices

Identifying the Datto RoundTrip Drive

In this example, the Reverse RoundTrip drive is /dev/sdb with a partition /dev/sdb1 for metadata and /dev/sdb2 for the encrypted ZFS pool.

Step 5.2: Decrypt the Drive

To decrypt the LUKS-encrypted partition, you will use cryptsetup. On an Ubuntu live ISO, cryptsetup is typically installed. If it is not, run apt install cryptsetup to install it.

Run the following command to open the encrypted partition. Be sure to replace the X with the correct letter for your drive (e.g., sda, sdb, etc.):

cryptsetup open /dev/sdX2 rt

Ubuntu Cryptsetup Open

Decrypting the Datto Reverse RoundTrip Drive using cryptsetup

You will be prompted to enter the pool passphrase. You should have received this passphrase from Datto Support. Enter it when prompted:

Enter passphrase for /dev/sdX2:  # <<< Type your pool passphrase here

If successful, you will not see any output, but the partition will be decrypted and available as /dev/mapper/rt. You can confirm this by running lsblk again. You'll see something like this:

sdb      8:16   0   200M  0 disk  
|-sdb1   8:17   0    25M  0 part  
`-sdb2   8:18   0   173M  0 part  
  `-rt 252:0    0   157M  0 crypt  # <<< Decrypted partition

Step 6: Import the ZFS Pool

You're now ready to import the ZFS pool. First, ensure you have the ZFS utilities installed. If not, run apt install zfsutils-linux.

To import the pool, run zpool import to identify the pool name, and then zpool import -f <poolname> to import it. The pool name is typically found in the metadata.json file, but since it's pretty obvious in most cases, we don't really need it.

Ubuntu ZFS Import

Importing the ZFS pool

After it is imported, you can check the status of the pool using zfs list. You'll see something like this:

NAME                                                        USED  AVAIL  REFER  MOUNTPOINT
revRT-123456                                               50.8M  21.2M    24K  /revRT-123456
revRT-123456/home                                          50.5M  21.2M    24K  /revRT-123456/home
revRT-123456/home/agents                                   50.5M  21.2M    25K  /revRT-123456/home/agents
revRT-123456/home/agents/2586beefcafe2586affe2586beefcafe  50.2M  21.2M  50.2M  /revRT-123456/home/agents/2586beefcafe2586affe2586beefcafe
revRT-123456/home/agents/facecafe7722beef2586deadcafebeef   296K  21.2M   294K  /revRT-123456/home/agents/facecafe7722beef2586deadcafebeef

Step 7: Access Agent Datasets

Your backup data is organized by protected systems (agents). Each agent has its own dataset POOLNAME/home/agents/AGENTGUID.

  • POOLNAME is the name of the ZFS pool (e.g. revRT-123456)
  • AGENTGUID is a unique identifier for each agent (e.g. 2586beefcafe2586affe2586beefcafe or facecafe7722beef2586deadcafebeef).

For each agent, you can list the agent's volumes and metadata by navigating to the dataset mountpoint, and using ls to list the files, e.g cd /revRT-123456/home/agents/2586beefcafe2586affe2586beefcafe and then ls -al.

Ubuntu ZFS Agent Datasets

Identifying encrypted and unencrypted Agents in the ZFS datasets

You'll see backup files with either .datto or .detto extensions:

  • The .datto files are unencrypted disk images, like in the example above for the dataset revRT-123456/home/agents/facecafe7722beef2586deadcafebeef.
  • The .detto files are encrypted disk images that require decryption, like in the example above for the dataset revRT-123456/home/agents/2586beefcafe2586affe2586beefcafe.

Step 8: Access Backup Files

Step 8.1: Unencrypted Backups (.datto files)

If you see .datto files, these are unencrypted disk images, similar to a raw bit-by-bit copy of a disk. To access the data on these files, you can create a loop device and then mount the partition(s). Typically, there is only one partition per .datto file.

You can follow these steps to access the unencrypted backups:

  1. Navigate to the directory containing the .datto files, e.g. cd /revRT-123456/home/agents/facecafe7722beef2586deadcafebeef.
  2. Create a loop device for the .datto file, e.g. losetup -fP 99cafe12-beef-cafe-affe-9912abcdabcd.datto. This will automatically assign the next available loop device (e.g. /dev/loop14), and scan for partitions.
  3. Now create a mount point and mount the partition: mkdir -p /home/ubuntu/Datto/volume1 and mount /dev/loop14p1 /home/ubuntu/Datto/volume1.
  4. You can now access the files in /home/ubuntu/Datto/volume1 using ls -la /home/ubuntu/Datto/volume1.

Here's what that looks like for our example agent:

Mount unencrypted .datto file Accessing backup files in the Ubuntu file manager

Accessing the backup data from the command line and the Ubuntu file manager

You can also access the files using a file manager in Ubuntu. Open the file manager in the dock on the left and click on the hard drive icon in the left menu of the file manager. You can now copy files to your USB drive or another location.

To mount all .datto files in the current directory, you can use this script:

for f in *.datto; do
    LOOP="$(losetup -fP --show $f)"
    mkdir -p "/home/ubuntu/Datto/${f%.datto}"
    mount "${LOOP}p1" "/home/ubuntu/Datto/${f%.datto}"
    echo "$f is mounted at /home/ubuntu/Datto/${f%.datto}"
done

Step 8.2: Encrypted Backups (.detto files)

If you see .detto files, these are encrypted and need additional decryption. They are encrypted using cryptsetup and AES-XTS with a key derived from the agent password. To access these files, you will need to

  1. Extract the raw key from the agent's encryption key stash file using the agent password.
  2. Decrypt the .detto file using cryptsetup with the extracted raw key.
  3. Create a loop device and mount the decrypted file to access the partitions (similar to above).

Step 8.2.1: Extract Raw Key

First, create the extract_key.py script by pasting this into your terminal. This script can be used to derive the raw AES-XTS key, using the agent keystash file (.encryptionKeyStash) and the agent password. The script will write the raw key to an output file.

cat > /usr/local/bin/extract_key.py << 'EOF'
#!/usr/bin/env python3
import sys, json, base64
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.backends import default_backend

def b64decode(data):
    return base64.urlsafe_b64decode(data + '=' * (-len(data) % 4))

if len(sys.argv) != 4:
    print("Usage: extract_key.py <keystash_file> <password> <output_file>", file=sys.stderr)
    sys.exit(1)

keystash_file, password, output_file = sys.argv[1], sys.argv[2], sys.argv[3]

# Load and parse JWE
with open(keystash_file) as f:
    jwe_token = json.load(f)['user_keys_jwe'][0]

header, _, iv, ciphertext, auth_tag = [b64decode(part) for part in jwe_token.split('.')]
header = json.loads(header)

# Derive key and decrypt
kdf = PBKDF2HMAC(hashes.SHA3_256(), 32, b64decode(header['p2s']), header['p2c'], default_backend())
key = kdf.derive(password.encode())

cipher = Cipher(algorithms.AES(key), modes.GCM(iv, auth_tag), default_backend())
decryptor = cipher.decryptor()
decryptor.authenticate_additional_data(jwe_token.split('.')[0].encode())
master_key_json = json.loads(decryptor.update(ciphertext) + decryptor.finalize())

master_key_raw = b64decode(master_key_json['k'])

with open(output_file, 'wb') as f:
    f.write(master_key_raw)

print("Agent key written to", output_file)
EOF

chmod +x /usr/local/bin/extract_key.py

Once created, you can run the script to extract the raw key from the agent's encryption key stash file, and the agent password. Check that the script works by running:

$ extract_key.py
Usage: extract_key.py <keystash_file> <password> <output_file>

Step 8.2.2: Decrypt the .detto File

Now that you have the extract_key.py script, you can finally decrypt the .detto files. Follow these steps:

  1. Navigate to the directory containing the .datto files, e.g. cd /revRT-123456/home/agents/2586beefcafe2586affe2586beefcafe.
  2. Extract the raw key using the key stash file and the agent password. Replace PASSWORD with the actual password for the agent: extract_key.py config/*.encryptionKeyStash "PASSWORD" /tmp/agent.key. This will write the raw key to /tmp/agent.key.
  3. Create a loop device for the .detto file, e.g. losetup -f --show 86beef25-cafe-beef-affe-abcd00010002.detto. This will automatically assign the next available loop device (e.g. /dev/loop14).
  4. Decrypt the volume using cryptsetup open --type plain --cipher aes-xts-plain64 --key-size 512 --key-file /tmp/agent.key /dev/loop14 encrypted_volume. Be sure to replace /dev/loop14 with the loop device in the previous step. You can use any name for encrypted_volume, it will be used to create a device mapper entry like /dev/mapper/encrypted_volume.
  5. Run partprobe /dev/mapper/encrypted_volume to update the partition table.
  6. Now create a mount point and mount the partition: mkdir -p /home/ubuntu/Datto/encrypted_volume1 and mount /dev/loop14p1 /home/ubuntu/Datto/encrypted_volume1.
  7. You can now access the files in /home/ubuntu/Datto/encrypted_volume1 using ls -la /home/ubuntu/Datto/encrypted_volume1.

Here's what that looks like for our example agent:

Mount encrypted .detto file Accessing the encrypted backups in the file manager

Accessing the backup data from the command line and the Ubuntu file manager

You can also access the files using a file manager in Ubuntu. Open the file manager in the dock on the left, navigate to Home, Datto and encrypted_volume1 (or hit Ctrl-L and paste /home/ubuntu/Datto/encrypted_volume1). You can now can copy files to your USB drive or another location.

That's a lot of steps, so here's a summary of the commands you need to run (using the example agent 2586beefcafe2586affe2586beefcafe, the password iyuRtmaQ8CXSEmwPtYKp, and the .detto file 86beef25-cafe-beef-affe-abcd00010002.detto):

cd /revRT-123456/home/agents/2586beefcafe2586affe2586beefcafe
extract_key.py config/*.encryptionKeyStash iyuRtmaQ8CXSEmwPtYKp /tmp/agent.key
losetup -f --show 86beef25-cafe-beef-affe-abcd00010002.detto
cryptsetup open --type plain --cipher aes-xts-plain64 --key-size 512 --key-file /tmp/agent.key /dev/loop14 myvol
partprobe /dev/mapper/encrypted_volume
mkdir -p /home/ubuntu/Datto/encrypted_volume1
mount /dev/mapper/encrypted_volume1 /home/ubuntu/Datto/encrypted_volume1
ls -la /home/ubuntu/Datto/encrypted_volume1

Here's a script mount_encrypted.py that will automate the decryption and mounting of a .detto file:

cat > /usr/local/bin/mount_encrypted.py << 'EOF'
#!/usr/bin/env python3
import os
import sys
import subprocess
import tempfile
import shutil
import pathlib

if len(sys.argv) != 4:
    print("Usage: mount_encrypted.py <detto_file> <keystash_file> <password>")
    sys.exit(1)

detto_file, keystash_file, password = sys.argv[1], sys.argv[2], sys.argv[3]
detto_path = pathlib.Path(detto_file).resolve()
basename = detto_path.stem
mount_base = f"/home/ubuntu/Datto/{basename}"
agent_dir = detto_path.parent.resolve()

with tempfile.NamedTemporaryFile(delete=False) as keyfile:
    keyfile_path = keyfile.name

try:
    subprocess.run(["extract_key.py", keystash_file, password, keyfile_path], check=True)
    losetup_out = subprocess.check_output(["losetup", "-f", "--show", str(detto_path)]).decode().strip()
    loop_device = losetup_out

    subprocess.run([
        "cryptsetup", "open", "--type", "plain", "--cipher", "aes-xts-plain64",
        "--key-size", "512", "--key-file", keyfile_path, loop_device, "encrypted_volume"
    ], check=True)

    subprocess.run(["partprobe", "/dev/mapper/encrypted_volume"], check=True)

    os.makedirs(mount_base, exist_ok=True)
    subprocess.run(["mount", "/dev/mapper/encrypted_volume1", mount_base], check=True)

    print(f"Mounted {detto_file} at {mount_base}")
    subprocess.run(["ls", "-la", mount_base])
finally:
    os.remove(keyfile_path)

EOF

chmod +x /usr/local/bin/mount_encrypted.py

You can use it like this:

$ mount_encrypted.py *.detto config/*.encryptionKeyStash iyuRtmaQ8CXSEmwPtYKp
Agent key written to /tmp/tmp6wdw5be6
Mounted 86beef25-cafe-beef-affe-abcd00010002.detto at /home/ubuntu/Datto/86beef25-cafe-beef-affe-abcd00010002
total 4
drwxrwxrwx 1 root root     4096 Aug  4 11:02  .
drwxr-xr-x 6 root root      120 Aug  4 15:07  ..
drwxrwxrwx 1 root root        0 Aug  4 11:02 'Program Files'
drwxrwxrwx 1 root root        0 Aug  4 11:02 'Program Files (x86)'
drwxrwxrwx 1 root root        0 Aug  4 11:02  ProgramData
drwxrwxrwx 1 root root        0 Aug  4 11:02 'System Volume Information'
drwxrwxrwx 1 root root        0 Aug  4 11:02  Users
drwxrwxrwx 1 root root        0 Aug  4 11:02  Windows
-rwxrwxrwx 1 root root 10485760 Aug  4 11:02  hiberfil.sys

Step 9: Copy Your Data

Once mounted, you can copy your important files to a USB drive or network location:

# Insert a USB drive and find its device name
lsblk

# Mount the USB drive (replace sdX1 with your USB partition)
mkdir -p /mnt/usb
mount /dev/sdX1 /mnt/usb

# Copy files (example)
cp -r /home/ubuntu/Datto/volume1/Users/YourUser/Documents/* /mnt/usb/
cp -r /home/ubuntu/Datto/encrypted_volume1/Users/YourUser2/Documents/* /mnt/usb/

Step 10: Cleanup When Done

Before shutting down:

# Unmount filesystems
umount /home/ubuntu/Datto/*
umount /mnt/usb

# Close encrypted devices (if used)
cryptsetup close encrypted_volume

# Detach loop devices
losetup -d /dev/loop14  # Replace with your loop device

# Export ZFS pool
zpool export revRT-123456