$ oc create secret generic <secret_name> -n openshift-adp --from-file cloud=<credentials_file_path>
Recover files from a virtual machine (VM) backup by creating a backup, discovering which backups contain the target VM, and restoring individual files through SSH. Complete this end-to-end OADP VM file restore (VMFR) workflow to quickly regain access to your data.
You are logged in to the cluster with the cluster-admin role.
You have installed the OADP Operator.
OKD Virtualization is installed and running on the cluster.
You have installed the virtctl CLI tool to access the VM.
Create a secret for the cloud storage credentials by running the following command:
$ oc create secret generic <secret_name> -n openshift-adp --from-file cloud=<credentials_file_path>
where:
<secret_name>Specifies the name of the cloud credentials secret.
<credentials_file_path>Specifies the path to the file that contains the cloud storage credentials.
Create a DataProtectionApplication (DPA) CR with the VMFR feature enabled and the kubevirt plugin:
apiVersion: oadp.openshift.io/v1alpha1
kind: DataProtectionApplication
metadata:
name: vmfr-dpa
namespace: openshift-adp
spec:
backupLocations:
- velero:
credential:
key: cloud
name: <secret_name>
default: true
objectStorage:
bucket: <bucket_name>
prefix: velero
provider: <provider>
configuration:
velero:
defaultPlugins:
- csi
- openshift
- kubevirt
- <provider>
disableFsBackup: false
nodeAgent:
enable: true
uploaderType: kopia
vmFileRestore:
enable: true
where:
<secret_name>Specifies the name of the cloud credentials secret you created.
<bucket_name>Specifies the name of the object storage bucket.
<provider>Specifies the cloud provider plugin, such as aws, gcp, or azure.
vmFileRestoreEnables the VMFR feature by setting the enable field to true.
Apply the DPA configuration by running the following command:
$ oc apply -f <dpa_cr_filename>
Verify that the DPA is reconciled and the VMFR feature is enabled by running the following command:
$ oc get dpa -n openshift-adp -o yaml
In the output, verify that the status.conditions section includes a condition with type: VMFileRestoreReady and status: "True".
Verify that the velero, nodeAgent, and oadp-vm-file-restore-controller-manager pods are running by running the following command:
$ oc get pod -n openshift-adp
Generate an SSH key pair for accessing the VM:
$ ssh-keygen -t ed25519 -f ~/.ssh/<vm_key_name> -C "<vm_key_name>"
Replace <vm_key_name> with a name for the SSH folder and the key file.
Create a namespace for the VM by running the following command:
$ oc create ns <vm_namespace>
Create a Kubernetes secret with the SSH public key in the VM namespace:
$ oc create secret generic <ssh_secret_name> \
--from-file=key=<path_to_public_key> \
-n <vm_namespace>
where:
<ssh_secret_name>Specifies the name of the secret that contains the SSH public key.
<path_to_public_key>Specifies the path to the SSH public key file you created in an earlier step. For example, $HOME/.ssh/vm-key.pub.
<vm_namespace>Specifies the namespace for the VM.
Create a VirtualMachine CR by using the built-in VM template fedora-server-small:
$ oc process -n openshift fedora-server-small -p NAME=<vm_name> | oc apply -n <vm_namespace> -f -
where:
<vm_name>Specifies the name of the VM.
<vm_namespace>Specifies the namespace for the VM.
Wait for the VM to be ready:
$ oc wait --for=condition=Ready vmi/<vm_name> -n <vm_namespace>
Patch the VM configuration accessCredentials object with the SSH public key:
$ oc patch vm <vm_name> -n <vm_namespace> --type=merge -p '{"spec":{"template":{"spec":{"accessCredentials":[{"sshPublicKey":{"propagationMethod":{"noCloud":{}},"source":{"secret":{"secretName":"<ssh_secret_name>"}}}}]}}}}'
where:
<vm_name>Specifies the name of the VM.
<vm_namespace>Specifies the namespace for the VM.
<ssh_secret_name>Specifies the name of the secret that contains the SSH public key.
SSH to the VM and create a test file:
$ virtctl ssh <vm_user>@vmi/<vm_name> \
-n <vm_namespace> \
--identity-file=$HOME/.ssh/<vm_key_name> \
--local-ssh-opts="-o StrictHostKeyChecking=no" \
-c "echo 'Test file for VMFR validation - $(date)' > /home/fedora/test-vmfr-file.txt"
where:
<vm_user>Specifies the name of the VM user. For the in-built VM template, the user name is fedora.
Create a Backup CR to back up the VM namespace:
apiVersion: velero.io/v1
kind: Backup
metadata:
name: <backup_name>
namespace: openshift-adp
spec:
includedNamespaces:
- <vm_namespace>
snapshotMoveData: true
Apply the Backup CR by running the following command:
$ oc apply -f <backup_cr_filename>
Verify that the backup is complete by running the following command:
$ oc get backup.velero <backup_name> -n openshift-adp -o jsonpath='{.status.phase}'
The output should display Completed.
Create a VirtualMachineBackupsDiscovery CR to identify which backups contain the target VM:
apiVersion: oadp.openshift.io/v1alpha1
kind: VirtualMachineBackupsDiscovery
metadata:
name: <vmbd_name>
namespace: openshift-adp
spec:
virtualMachineName: <vm_name>
virtualMachineNamespace: <vm_namespace>
Apply the VMBD CR by running the following command:
$ oc apply -f <vmbd_cr_filename>
Verify that the discovery is complete by running the following command:
$ oc get vmbd <vmbd_name> -n openshift-adp
The PHASE column should display Completed.
Create a VirtualMachineFileRestore CR with SSH access to restore files from the discovered backups:
apiVersion: oadp.openshift.io/v1alpha1
kind: VirtualMachineFileRestore
metadata:
name: <vmfr_name>
namespace: openshift-adp
spec:
backupsDiscoveryRef: <vmbd_name>
fileAccess:
ssh: {}
The ssh: {} configuration instructs the controller to autogenerate an SSH key pair and store it in a Kubernetes secret. The default SSH username is oadp.
Apply the VMFR CR by running the following command:
$ oc apply -f <vmfr_cr_filename>
Wait for the VMFR phase to complete:
$ oc get vmfr <vmfr_name> -n openshift-adp
The PHASE column should display Completed.
Retrieve the SSH access information by running the following command:
$ oc get vmfr <vmfr_name> -o jsonpath='{.status.fileServingInfo.ssh}' | jq
The output includes the clusterAccess URL and the credentialsSecretRef containing the name and namespace of the auto generated SSH key secret.
Retrieve the private key from the auto generated secret and save it to a file:
$ oc get secret <secret_name> -n <secret_namespace> -o jsonpath='{.data.privateKey}' | base64 -d > id-rsa
Replace <secret_name> and <secret_namespace> with the values from the status.fileServingInfo.ssh.credentialsSecretRef field.
Copy the private key to the VM so that you can use it for scp from within the VM:
$ virtctl scp id-rsa \
<vm_user>@vmi/<vm_name>:/home/<vm_user>/id-rsa \
-n <vm_namespace> \
--identity-file=$HOME/.ssh/<vm_key_name>
Update the file permissions on the private key inside the VM:
$ virtctl ssh <vm_user>@vmi/<vm_name> \
-n <vm_namespace> \
--identity-file=$HOME/.ssh/<vm_key_name> \
--local-ssh-opts="-o StrictHostKeyChecking=no" \
-c "chmod 600 /home/<vm_user>/id-rsa"
Get the name of the file server service created in the VMFR namespace:
$ SVC=$(oc get svc -n <created_namespace> | grep fileserver | awk '{print $1}')
Replace <created_namespace> with the value from the status.createdNamespace field of the VMFR CR.
Restore the file by using scp from within the VM. The remote path format is /restores/<date>/<backup_name>/<vm_name>/<path_to_file>:
$ virtctl ssh <vm_user>@vmi/<vm_name> \
-n <vm_namespace> \
--identity-file=$HOME/.ssh/<vm_key_name> \
--local-ssh-opts="-o StrictHostKeyChecking=no" \
-c "scp -P 2222 \
-i /home/<vm_user>/id-rsa \
-o StrictHostKeyChecking=no \
-o UserKnownHostsFile=/dev/null \
oadp@<fileserver_svc>.<created_namespace>.svc.cluster.local:<remote_path> \
/tmp/restored.txt"
where:
<fileserver_svc>Specifies the name of the file server service you retrieved in an earlier step.
<created_namespace>Specifies the namespace from the status.createdNamespace field.
<remote_path>Specifies the path to the file in the format /restores/<date>/<backup_name>/<vm_name>/<path_to_file>. For example, "/restores/2026-02-10/test-backup/fedora-vm-test/home/fedora/test-vmfr-file.txt"
Verify that the restored file is intact by comparing MD5 checksums:
$ virtctl ssh <vm_user>@vmi/<vm_name> \
-n <vm_namespace> \
--identity-file=$HOME/.ssh/<vm_key_name> \
--local-ssh-opts="-o StrictHostKeyChecking=no" \
-c "echo '===MD5 Checksums===' && md5sum /home/fedora/test-vmfr-file.txt /tmp/restored.txt"
The checksums of the original and restored files should match. You should see an output as shown in the following example:
===MD5 Checksums===
92245490c552e83baf5f2a2e898d9fff /home/fedora/test-vmfr-file.txt
92245490c552e83baf5f2a2e898d9fff /tmp/restored.txt
After you have recovered the files, delete the VMFR CR to clean up resources:
$ oc delete vmfr <vmfr_name> -n openshift-adp