Restore

Enterprise

Bacula Enterprise Only

This solution is only available for Bacula Enterprise. For subscription inquiries, please reach out to sales@baculasystems.com.

The plugin supports restoring backed up data either to the local filesystem or directly to a Libvirt hypervisor.

Restore to Local Filesystem

If the user specifies a filesystem path in the Bacula where parameter, the plugin performs a restore to that local path on the Bacula client host.

Restore to a Libvirt Hypervisor

A domain restore operation typically involves the following steps:

  1. Build the target resource definitions by combining the original configuration with any user-specified restore parameters.

  2. Validate that the requested restore options do not conflict with existing objects on the target hypervisor (domain name, UUID, storage pool name, etc.).

  3. For each disk involved in the restore, the plugin: a. Creates a new volume in the selected storage pool. b. Exposes the disk via NBD with write permissions. c. Mounts the disk depending on the backup method. d. Writes all required blocks from the backup Job to the mounted disk.

  4. Creates the domain by combining the original domain configuration with user-specified restore parameters.

  5. For Incremental/Differential, the plugin iterates for each disk.

  6. If start_domain is enabled, start the restored domain.

Restore Parameters

The Libvirt Plugin can restore either:

  • to the local filesystem (raw restore), or

  • to the Libvirt environment (domain restore).

The restore method is selected using the Bacula where parameter:

  • Empty or ‘/’ (example: where=/): triggers a Libvirt restore.

  • Any other path (example: where=/tmp): triggers a raw restore to the local filesystem.

This principle generally applies to other Bacula plugins as well. However, for this plugin it is not recommended to use the raw restore method via the File Daemon. Raw restores preserve the internal headers generated during the backup process in the restored disk files.

If you want to restore a disk image to a local path, use a Libvirt restore where=/ and specify the destination using the to_local_path restore variable. With this approach, the plugin removes the internal headers and produces a standard disk image suitable for reuse.

When using the Libvirt restore method, the following parameters are available to control the restore behavior under “Plugin Options” menu during a bconsole restore session:

Restore Use Cases

The following restore scenarios are supported, and steps to execute them are described:

  1. Restore a domain to the Libvirt hypervisor, to its original location, preserving its configuration:

    1. Run a restore session and select appropriate backup Jobs

    2. Select all the contents of the domain directory (located under @libvirt/domains/ and named after the domain).

    3. Set Where=/.

  2. Restore a domain to the Libvirt hypervisor with a different name:

    • Follow scenario (a).

    • Set new_domain_name to the desired name (or use an empty value).

  3. Restore a domain to the Libvirt hypervisor with a different uuid:

    • Follow scenario (a).

    • Set new_domain_uuid to the desired UUID (or use an empty value).

  4. Restore a domain to the Libvirt hypervisor with different disk names:

    • Follow scenario (a).

    • Set new_storage_volume_names to the desired names (or use an empty value).

  5. Restore a domain to the Libvirt hypervisor and store its disks in a different pool:

    • Follow scenario (a).

    • Set storage_pool_name to the target storage pool name.

  6. Restore a domain to the Libvirt hypervisor start it after the restore:

    • Follow scenario (a).

    • Set start_domain=yes

  7. Restore a domain to the Libvirt hypervisor and and start it with networking disabled:

    • Follow scenario (f).

    • Set no_networks=yes

Restore Examples

Example 1: Restore from Incremental Backup Chain of Domain “debian12”

This example restores domain debian12 from the following backup chain:

  • Full (JobId 13)

  • Incremental 1 (JobId 14)

  • Incremental 2 (JobId 15)

The domain is restored under a new name: debian12-Incremental.

Setting restore parameters
*restore where=/ jobid=13,14,15
You have selected the following JobIds: 13,14,15

Building directory tree for JobId(s) 13,14,15 ...
8 files inserted into the tree.

You are now entering file selection mode where you add (mark) and
remove (unmark) files to be restored. No files are initially added, unless
you used the "all" keyword on the command line.
Enter "done" to leave this mode.

cwd is: /
$
Invalid command "".  Enter "done" to exit.
$ cd @libvirt/domains/
cwd is: /@libvirt/domains/
$ mark debian12
7 files marked.
$ done
Bootstrap records written to /opt/bacula/working/127.0.0.1-dir.restore.7.bsr

The Job will require the following (*=>InChanger):
Volume(s)                 Storage(s)                SD Device(s)
===========================================================================

    Vol-0002                  File1                     FileStorage1

Volumes marked with "*" are in the Autochanger.


15 BSR records selected to be restored.

Automatically selected Client: 127.0.0.1-fd
Using Catalog "MyCatalog"
Run Restore job
JobName:         RestoreFiles
Bootstrap:       /opt/bacula/working/127.0.0.1-dir.restore.7.bsr
Where:           /
Replace:         Always
FileSet:         Full Set
Backup Client:   127.0.0.1-fd
Restore Client:  127.0.0.1-fd
Storage:         File1
When:            2025-12-16 16:57:35
Catalog:         MyCatalog
Priority:        10
Plugin Options:  *None*
OK to run? (Yes/mod/no): mod
Parameters to modify:
    1: Level
    2: Storage
    3: Job
    4: FileSet
    5: Restore Client
    6: When
    7: Priority
    8: Bootstrap
    9: Where
    10: File Relocation
    11: Replace
    12: JobId
    13: Plugin Options
Select parameter to modify (1-13): 13
Automatically selected : libvirt: debug=1 domain=debian12 backup_method=block_dev uri="qemu:///system" nbd_server_address="0.0.0.0" nbd_client_address="localhost" ssh_private_key_path="/opt/bacula/etc/id_ed25519" libvirt_user="libvirt-qemu" libvirt_group="kvm" tmp_dir="/tmp/"
Plugin Restore Options
Option                         Current Value        Default Value
debug:                         *None*               (*None*)
use_sudo:                      *None*               (*None*)
uri:                           *None*               (*None*)
nbd_server_address:            *None*               (*None*)
nbd_server_port:               *None*               (*None*)
nbd_client_address:            *None*               (*None*)
nbd_client_port:               *None*               (*None*)
tmp_dir:                       *None*               (*None*)
nbd_access:                    *None*               (*None*)
storage_pool_name:             *None*               (*None*)
new_domain_name:               *None*               (*None*)
new_storage_volume_names:      *None*               (*None*)
new_domain_uuid:               *None*               (*None*)
start_domain:                  *None*               (False)
ssh_port:                      *None*               (*None*)
ssh_private_key_path:          *None*               (*None*)
timeout_ssh_auth:              *None*               (*None*)
timeout_ssh_end_session:       *None*               (*None*)
no_network:                    *None*               (*None*)
Use above plugin configuration? (Yes/mod/no): mod
You have the following choices:
    1: debug (Change debug level)
    2: use_sudo (Use sudo to grant permissions to external commands)
    3: uri (Specifies the URI to connect with QEMU/KVM hypervisor)
    4: nbd_server_address (Specifies which address will expose the device via NBD)
    5: nbd_server_port (Specifies which port will expose the device via NBD)
    6: nbd_client_address (Specifies which address will consume the NBD)
    7: nbd_client_port (Specifies which port will consume the NBD)
    8: tmp_dir (Indicates temporary folder to restore)
    9: nbd_access (Restore the domain's disks using a specific nbd access)
    10: storage_pool_name (Restore all domain's disks in the specific storage pool)
    11: new_domain_name (Restore the domain with other name. Write 'bee_random' to use a random name.)
    12: new_storage_volume_names (Restore the domain's disk with other names. Write 'bee_random' to use a random values.)
    13: new_domain_uuid (Restore the domain with other uuid. Write 'bee_random' to use a random UUID.)
    14: start_domain (Start the domain just after restoring it)
    15: ssh_port (Specifies the ssh port to connect with remote host)
    16: ssh_private_key_path (Specifies the private ssh key to connect with remote host)
    17: timeout_ssh_auth (Timeout to ssh connect to remote host)
    18: timeout_ssh_end_session (Timeout to end ssh connection)
    19: no_network (Restore the domain without activate its networks)
Select parameter to modify (1-19): 11
Please enter a value for new_domain_name: debian12-Incremental
Plugin Restore Options
Option                         Current Value        Default Value
debug:                         *None*               (*None*)
use_sudo:                      *None*               (*None*)
uri:                           *None*               (*None*)
nbd_server_address:            *None*               (*None*)
nbd_server_port:               *None*               (*None*)
nbd_client_address:            *None*               (*None*)
nbd_client_port:               *None*               (*None*)
tmp_dir:                       *None*               (*None*)
nbd_access:                    *None*               (*None*)
storage_pool_name:             *None*               (*None*)
new_domain_name:               debian12-Incremental (*None*)
new_storage_volume_names:      *None*               (*None*)
new_domain_uuid:               *None*               (*None*)
start_domain:                  *None*               (False)
ssh_port:                      *None*               (*None*)
ssh_private_key_path:          *None*               (*None*)
timeout_ssh_auth:              *None*               (*None*)
timeout_ssh_end_session:       *None*               (*None*)
no_network:                    *None*               (*None*)
Use above plugin configuration? (Yes/mod/no): yes
Run Restore job
JobName:         RestoreFiles
Bootstrap:       /opt/bacula/working/127.0.0.1-dir.restore.7.bsr
Where:           /
Replace:         Always
FileSet:         Full Set
Backup Client:   127.0.0.1-fd
Restore Client:  127.0.0.1-fd
Storage:         File1
When:            2025-12-16 16:57:35
Catalog:         MyCatalog
Priority:        10
Plugin Options:  User specified
OK to run? (Yes/mod/no): yes
Job queued. JobId=23
Job log: restore
16-Dec 16:57 127.0.0.1-dir JobId 23: Start Restore Job RestoreFiles.2025-12-16_16.57.36_42
16-Dec 16:57 127.0.0.1-dir JobId 23: Restoring files from JobId(s) 13,14,15
16-Dec 16:57 127.0.0.1-dir JobId 23: Connected to Storage "File1" at 127.0.0.1:8103 with TLS
16-Dec 16:57 127.0.0.1-dir JobId 23: Using Device "FileStorage1" to read.
16-Dec 16:57 127.0.0.1-dir JobId 23: Connected to Client "127.0.0.1-fd" at 127.0.0.1:8102 with TLS
16-Dec 16:57 127.0.0.1-fd JobId 23: Connected to Storage at 127.0.0.1:8103 with TLS
16-Dec 16:57 127.0.0.1-sd JobId 23: Ready to read from volume "Vol-0002" on File device "FileStorage1" (/opt/bacula/tmp).
16-Dec 16:57 127.0.0.1-sd JobId 23: Forward spacing Volume "Vol-0002" to addr=6549440140
16-Dec 16:57 127.0.0.1-fd JobId 23: libvirt: Plugin log of this job available in: /opt/bacula/working/libvirt/libvirt-debug-4.log
16-Dec 16:57 127.0.0.1-fd JobId 23: libvirt: Connected correctly to hypervisor
16-Dec 16:57 127.0.0.1-fd JobId 23: libvirt: Checked the restore requirements
16-Dec 16:57 127.0.0.1-fd JobId 23: libvirt: The user want to change the volume name from [debian12_data.qcow2] to [debian12_data-23.qcow2]
16-Dec 16:57 127.0.0.1-fd JobId 23: libvirt: A new volume [debian12_data-23.qcow2] was created in storage pool [default]
16-Dec 16:57 127.0.0.1-fd JobId 23: libvirt: The user want to change the volume name from [debian12_system.qcow2] to [debian12_system-23.qcow2]
16-Dec 16:57 127.0.0.1-fd JobId 23: libvirt: A new volume [debian12_system-23.qcow2] was created in storage pool [default]
16-Dec 16:57 127.0.0.1-sd JobId 23: Elapsed time=00:00:10, Transfer rate=351.2 M Bytes/second
16-Dec 16:57 127.0.0.1-fd JobId 23: libvirt: The user want to change the domain name from [debian12] to [debian12-Incremental]
16-Dec 16:57 127.0.0.1-fd JobId 23: libvirt: A new domain [debian12-Incremental] was created
16-Dec 16:57 127.0.0.1-fd JobId 23: libvirt: No more items to restore. Restore ended
16-Dec 16:57 127.0.0.1-dir JobId 23: Bacula 127.0.0.1-dir 18.2.1 (24Oct25):
Build OS:               x86_64-pc-linux-gnu ubuntu 25.10
JobId:                  23
Job:                    RestoreFiles.2025-12-16_16.57.36_42
Restore Client:         "127.0.0.1-fd" 18.2.1 (24Oct25) x86_64-pc-linux-gnu,ubuntu,25.10
Where:                  /
Replace:                Always
Start time:             16-Dec-2025 16:57:38
End time:               16-Dec-2025 16:57:50
Elapsed time:           12 secs
Files Expected:         15
Files Restored:         15
Bytes Restored:         3,512,461,787 (3.512 GB)
Rate:                   292705.1 KB/s
FD Errors:              0
FD termination status:  OK
SD termination status:  OK
Termination:            Restore OK

16-Dec 16:57 127.0.0.1-dir JobId 23: Begin pruning Jobs older than 6 months .
16-Dec 16:57 127.0.0.1-dir JobId 23: No Jobs found to prune.
16-Dec 16:57 127.0.0.1-dir JobId 23: Begin pruning Files.
16-Dec 16:57 127.0.0.1-dir JobId 23: No Files found to prune.
16-Dec 16:57 127.0.0.1-dir JobId 23: End auto prune.

Example 2: Restore from Differential Backup Chain of Domain “debian12”

This example restores domain debian12 from the following backup chain:

  • Full (JobId 13)

  • Differential (JobId 16)

The domain is restored under a new name: debian12-Differential.

Setting restore parameters
*restore jobid=13,16 where=/
You have selected the following JobIds: 13,16

Building directory tree for JobId(s) 13,16 ...
8 files inserted into the tree.

You are now entering file selection mode where you add (mark) and
remove (unmark) files to be restored. No files are initially added, unless
you used the "all" keyword on the command line.
Enter "done" to leave this mode.

cwd is: /
$
Invalid command "".  Enter "done" to exit.
$ cd @libvirt/domains/
cwd is: /@libvirt/domains/
$ mark debian12
7 files marked.
$ done
Bootstrap records written to /opt/bacula/working/127.0.0.1-dir.restore.8.bsr

The Job will require the following (*=>InChanger):
Volume(s)                 Storage(s)                SD Device(s)
===========================================================================

    Vol-0002                  File1                     FileStorage1

Volumes marked with "*" are in the Autochanger.


11 BSR records selected to be restored.

Automatically selected Client: 127.0.0.1-fd
Using Catalog "MyCatalog"
Run Restore job
JobName:         RestoreFiles
Bootstrap:       /opt/bacula/working/127.0.0.1-dir.restore.8.bsr
Where:           /
Replace:         Always
FileSet:         Full Set
Backup Client:   127.0.0.1-fd
Restore Client:  127.0.0.1-fd
Storage:         File1
When:            2025-12-16 16:58:07
Catalog:         MyCatalog
Priority:        10
Plugin Options:  *None*
OK to run? (Yes/mod/no): mod
Parameters to modify:
    1: Level
    2: Storage
    3: Job
    4: FileSet
    5: Restore Client
    6: When
    7: Priority
    8: Bootstrap
    9: Where
    10: File Relocation
    11: Replace
    12: JobId
    13: Plugin Options
Select parameter to modify (1-13): 13
Automatically selected : libvirt: debug=1 domain=debian12 backup_method=block_dev uri="qemu:///system" nbd_server_address="0.0.0.0" nbd_client_address="localhost" ssh_private_key_path="/root/.ssh/id_ed25519" libvirt_user="libvirt-qemu" libvirt_group="kvm" tmp_dir="/tmp/"
Plugin Restore Options
Option                         Current Value        Default Value
debug:                         *None*               (*None*)
use_sudo:                      *None*               (*None*)
uri:                           *None*               (*None*)
nbd_server_address:            *None*               (*None*)
nbd_server_port:               *None*               (*None*)
nbd_client_address:            *None*               (*None*)
nbd_client_port:               *None*               (*None*)
tmp_dir:                       *None*               (*None*)
nbd_access:                    *None*               (*None*)
storage_pool_name:             *None*               (*None*)
new_domain_name:               *None*               (*None*)
new_storage_volume_names:      *None*               (*None*)
new_domain_uuid:               *None*               (*None*)
start_domain:                  *None*               (False)
ssh_port:                      *None*               (*None*)
ssh_private_key_path:          *None*               (*None*)
timeout_ssh_auth:              *None*               (*None*)
timeout_ssh_end_session:       *None*               (*None*)
no_network:                    *None*               (*None*)
Use above plugin configuration? (Yes/mod/no): mod
You have the following choices:
    1: debug (Change debug level)
    2: use_sudo (Use sudo to grant permissions to external commands)
    3: uri (Specifies the URI to connect with QEMU/KVM hypervisor)
    4: nbd_server_address (Specifies which address will expose the device via NBD)
    5: nbd_server_port (Specifies which port will expose the device via NBD)
    6: nbd_client_address (Specifies which address will consume the NBD)
    7: nbd_client_port (Specifies which port will consume the NBD)
    8: tmp_dir (Indicates temporary folder to restore)
    9: nbd_access (Restore the domain's disks using a specific nbd access)
    10: storage_pool_name (Restore all domain's disks in the specific storage pool)
    11: new_domain_name (Restore the domain with other name. Write 'bee_random' to use a random name.)
    12: new_storage_volume_names (Restore the domain's disk with other names. Write 'bee_random' to use a random values.)
    13: new_domain_uuid (Restore the domain with other uuid. Write 'bee_random' to use a random UUID.)
    14: start_domain (Start the domain just after restoring it)
    15: ssh_port (Specifies the ssh port to connect with remote host)
    16: ssh_private_key_path (Specifies the private ssh key to connect with remote host)
    17: timeout_ssh_auth (Timeout to ssh connect to remote host)
    18: timeout_ssh_end_session (Timeout to end ssh connection)
    19: no_network (Restore the domain without activate its networks)
Select parameter to modify (1-19): 11
Please enter a value for new_domain_name: debian12-Differential
Plugin Restore Options
Option                         Current Value        Default Value
debug:                         *None*               (*None*)
use_sudo:                      *None*               (*None*)
uri:                           *None*               (*None*)
nbd_server_address:            *None*               (*None*)
nbd_server_port:               *None*               (*None*)
nbd_client_address:            *None*               (*None*)
nbd_client_port:               *None*               (*None*)
tmp_dir:                       *None*               (*None*)
nbd_access:                    *None*               (*None*)
storage_pool_name:             *None*               (*None*)
new_domain_name:               debian12-Differential (*None*)
new_storage_volume_names:      *None*               (*None*)
new_domain_uuid:               *None*               (*None*)
start_domain:                  *None*               (False)
ssh_port:                      *None*               (*None*)
ssh_private_key_path:          *None*               (*None*)
timeout_ssh_auth:              *None*               (*None*)
timeout_ssh_end_session:       *None*               (*None*)
no_network:                    *None*               (*None*)
Use above plugin configuration? (Yes/mod/no): yes
Run Restore job
JobName:         RestoreFiles
Bootstrap:       /opt/bacula/working/127.0.0.1-dir.restore.8.bsr
Where:           /
Replace:         Always
FileSet:         Full Set
Backup Client:   127.0.0.1-fd
Restore Client:  127.0.0.1-fd
Storage:         File1
When:            2025-12-16 16:58:07
Catalog:         MyCatalog
Priority:        10
Plugin Options:  User specified
OK to run? (Yes/mod/no): yes
Job queued. JobId=24
Job log: restore
16-Dec 16:58 127.0.0.1-dir JobId 24: Start Restore Job RestoreFiles.2025-12-16_16.58.07_45
16-Dec 16:58 127.0.0.1-dir JobId 24: Restoring files from JobId(s) 13,16
16-Dec 16:58 127.0.0.1-dir JobId 24: Connected to Storage "File1" at 127.0.0.1:8103 with TLS
16-Dec 16:58 127.0.0.1-dir JobId 24: Using Device "FileStorage1" to read.
16-Dec 16:58 127.0.0.1-dir JobId 24: Connected to Client "127.0.0.1-fd" at 127.0.0.1:8102 with TLS
16-Dec 16:58 127.0.0.1-fd JobId 24: Connected to Storage at 127.0.0.1:8103 with TLS
16-Dec 16:58 127.0.0.1-sd JobId 24: Ready to read from volume "Vol-0002" on File device "FileStorage1" (/opt/bacula/tmp).
16-Dec 16:58 127.0.0.1-sd JobId 24: Forward spacing Volume "Vol-0002" to addr=6549440140
16-Dec 16:58 127.0.0.1-fd JobId 24: libvirt: Plugin log of this job available in: /opt/bacula/working/libvirt/libvirt-debug-4.log
16-Dec 16:58 127.0.0.1-fd JobId 24: libvirt: Connected correctly to hypervisor
16-Dec 16:58 127.0.0.1-fd JobId 24: libvirt: Checked the restore requirements
16-Dec 16:58 127.0.0.1-fd JobId 24: libvirt: The user want to change the volume name from [debian12_data.qcow2] to [debian12_data-24.qcow2]
16-Dec 16:58 127.0.0.1-fd JobId 24: libvirt: A new volume [debian12_data-24.qcow2] was created in storage pool [default]
16-Dec 16:58 127.0.0.1-fd JobId 24: libvirt: The user want to change the volume name from [debian12_system.qcow2] to [debian12_system-24.qcow2]
16-Dec 16:58 127.0.0.1-fd JobId 24: libvirt: A new volume [debian12_system-24.qcow2] was created in storage pool [default]
16-Dec 16:58 127.0.0.1-sd JobId 24: Elapsed time=00:00:10, Transfer rate=354.2 M Bytes/second
16-Dec 16:58 127.0.0.1-fd JobId 24: libvirt: The user want to change the domain name from [debian12] to [debian12-Differential]
16-Dec 16:58 127.0.0.1-fd JobId 24: libvirt: A new domain [debian12-Differential] was created
16-Dec 16:58 127.0.0.1-fd JobId 24: libvirt: No more items to restore. Restore ended
16-Dec 16:58 127.0.0.1-dir JobId 24: Bacula 127.0.0.1-dir 18.2.1 (24Oct25):
Build OS:               x86_64-pc-linux-gnu ubuntu 25.10
JobId:                  24
Job:                    RestoreFiles.2025-12-16_16.58.07_45
Restore Client:         "127.0.0.1-fd" 18.2.1 (24Oct25) x86_64-pc-linux-gnu,ubuntu,25.10
Where:                  /
Replace:                Always
Start time:             16-Dec-2025 16:58:09
End time:               16-Dec-2025 16:58:20
Elapsed time:           11 secs
Files Expected:         11
Files Restored:         11
Bytes Restored:         3,542,345,372 (3.542 GB)
Rate:                   322031.4 KB/s
FD Errors:              0
FD termination status:  OK
SD termination status:  OK
Termination:            Restore OK

16-Dec 16:58 127.0.0.1-dir JobId 24: Begin pruning Jobs older than 6 months .
16-Dec 16:58 127.0.0.1-dir JobId 24: No Jobs found to prune.
16-Dec 16:58 127.0.0.1-dir JobId 24: Begin pruning Files.
16-Dec 16:58 127.0.0.1-dir JobId 24: No Files found to prune.
16-Dec 16:58 127.0.0.1-dir JobId 24: End auto prune.

See also

Previous articles:

Next articles:

Go back to: Libvirt Plugin: Operations.