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.
- Go to https://ubuntu.com/download/desktop
- Download the latest Ubuntu Desktop LTS (Long Term Support) version
- You'll get a file named something like
ubuntu-24.04.3-desktop-amd64.iso
Step 2: Create Bootable USB¶
- Download Rufus: Go to https://rufus.ie and download Rufus
- Insert USB drive (at least 8GB, will be erased!)
- Run Rufus as Administrator
- Configure Rufus:
- Device: Select your USB drive
- Boot selection: Click "SELECT" and choose your Ubuntu ISO file
- Partition scheme: GPT
- Target system: UEFI
- Click START and wait for completion (takes 5-15 minutes)
Step 3: Boot Ubuntu from USB¶
- Connect your Ubuntu USB drive to your computer
- 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
- Select your USB drive from the boot menu
- Choose "Try Ubuntu" or "Try or install Ubuntu" (not "Install Ubuntu")
- Connect the Datto Reverse RoundTrip drive to your computer
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:
Next, become root user by typing sudo su
and pressing Enter. You should now see a prompt like root@ubuntu:/home/ubuntu#
:
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
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.):
You will be prompted to enter the pool passphrase. You should have received this passphrase from Datto Support. Enter it when prompted:
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.
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
orfacecafe7722beef2586deadcafebeef
).
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
.
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 datasetrevRT-123456/home/agents/facecafe7722beef2586deadcafebeef
. - The
.detto
files are encrypted disk images that require decryption, like in the example above for the datasetrevRT-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:
- Navigate to the directory containing the
.datto
files, e.g.cd /revRT-123456/home/agents/facecafe7722beef2586deadcafebeef
. - 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. - Now create a mount point and mount the partition:
mkdir -p /home/ubuntu/Datto/volume1
andmount /dev/loop14p1 /home/ubuntu/Datto/volume1
. - You can now access the files in
/home/ubuntu/Datto/volume1
usingls -la /home/ubuntu/Datto/volume1
.
Here's what that looks like for our example agent:
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
- Extract the raw key from the agent's encryption key stash file using the agent password.
- Decrypt the
.detto
file usingcryptsetup
with the extracted raw key. - 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:
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:
- Navigate to the directory containing the
.datto
files, e.g.cd /revRT-123456/home/agents/2586beefcafe2586affe2586beefcafe
. - 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
. - 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
). - 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 forencrypted_volume
, it will be used to create a device mapper entry like/dev/mapper/encrypted_volume
. - Run
partprobe /dev/mapper/encrypted_volume
to update the partition table. - Now create a mount point and mount the partition:
mkdir -p /home/ubuntu/Datto/encrypted_volume1
andmount /dev/loop14p1 /home/ubuntu/Datto/encrypted_volume1
. - You can now access the files in
/home/ubuntu/Datto/encrypted_volume1
usingls -la /home/ubuntu/Datto/encrypted_volume1
.
Here's what that looks like for our example agent:
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: