How does the SharepointV2 destination work?

Hey everyone, I’ve been using Duplicati for a while now and am thoroughly impressed. However, my company has recently migrated to Microsoft 365, which includes a shitload of storage on SharePoint, which I’d like to use for some of our more sensitive equipment.

However, I can’t figure out how to get Duplicati to play along.

My setup is the following:

  1. Each device has a unique company-issued ID
  2. Duplicati runs as a system service, waking the device up at 02:00 every day to do the backup (configured via Windows TaskScheduler)
  3. We have a SharePoint site, which for privacy reasons, I’ll refer to as BackupRepository.
  4. BackupRepository has an associated Document Library called Backups. In here, each device ID has a corresponding folder, where Duplicati should push the backup chunks to.
    An example URL might be https://MyCompany.sharepoint.com/sites/BackupRepository/Backups/IT-0000-L
  5. I’ve used the Microsoft Graph Explorer to get the ID of the site, using the URL https://graph.microsoft.com/v1.0/sites/root/sites?search=*, which gave the ID: MyCompany.sharepoint.com,... … a whole bunch of hexadecimal stuff.
  6. In the Duplicati interface, I’ve fetched an up-to-date Auth-ID, and entered all the information necessary.
  7. For the destination path I’ve tried just about every combination of the full URL to the folder, the shortened url, /sites/BackupRepository/Backups/IT-0000-L and every combination of it, but Duplicati insists on it not existing, and kindly offers to create it, at which point it stops complaining, however it never finds the correct folder.

I also can’t locate the folder it does end up creating. What am I doing wrong?

Thanks,
Jake

Can you export the target URL (… menu on the destination settings) and see if it matches one of the patterns in the manual? Maybe there is something wrong with the conversion, or it removes or adds some parts of the URL it shouldn’t. Otherwise I don’t really know what could be wrong.

I am not sure, but maybe if you specify the ID you can’t add the x.sharepoint.com/sites/BackupRepository/Backups part. At least that is what I would take from the manual. Did you try that as well? Also did you try the double slash that is in the manual example?

I hate to admit that I’ve tried just about everything I can think of. I can compare the exported URL to the expected one, but other than that, I’m not really sure how to proceed from there.

Anyway, I’m out of office now, but I’ll check tomorrow.
Thanks for your efforts though

Due to privacy reasons, I can’t share the original exported URL, but below is an adapted version.

sharepoint://MyCompany.sharepoint.com/sites/BackupRepository/Backups/IT-0000?authid=auth_id&auth-username=backup-administrator%40mycompany.com

Hello

while I have no insight about Sharepoint (as far as I know there is no free trial Sharepoint as there is one for Onedrive), I can direct you to the backend tool (Duplicati.CommandLine.BackendTool.exe), particularly the LIST command and the --debug-output command line switch (that will provide you the maximum information).

I took a look at the code, and it uses the same Graph API as OneDrive (v2). So if OneDrive works (I tested that a few weeks ago), at least in principle SharePoint should also work. The only difference is that SharePoint needs a site ID and drive path, which are fixed for OneDrive.

What happens internally

This is probably too much detail for you, but I hope it will help us fix your problems in the future:
For reference: Microsoft Graph API

  • The site ID that is passed as an option will be used to generate the drive path (/sites/{site-id}/drive) for the document library. This is going to be correct, assuming the site id is correct.
  • Even though a site ID has to be set explicitly, the path is still used to guess the site path and local path in the URL (this is probably left over from the Sharepoint v1 backend). So it should result in the local path /IT-0000-L (called RootPath in the code)
  • When using a double slash to indicate the separation (e.g. company.sharepoint.com/sites/BackupRepository/Backups//IT-0000-L), it tries to use that to get the site via a request /v1.0/sites/company.sharepoint.com://sites/BackupRepository/Backups. The double slash after the colon should not be there. This is why specifying a double slash probably does not work.
  • If there is no double slash, or the access fails (always), the path is searched from the bottom up for a correct site URL:
    /v1.0/sites/company.sharepoint.com:/sites/BackupRepository/Backups/IT-0000-L
    /v1.0/sites/company.sharepoint.com:/sites/BackupRepository/Backups
    /v1.0/sites/company.sharepoint.com:/sites/BackupRepository
    /v1.0/sites/company.sharepoint.com:/sites
    The first of these that does not result in an error is chosen. The rest of the URL is then used as RootPath. This should also get the site ID and make it unnecessary to specify it, but that does not work. The drive path is not updated with a new site ID.
    If none of these requests work, it is assumed that the URL already is a local path and it is used as RootPath (including the hostname part).
  • Once the root path is chosen, Drive items (files/folders) are accessed via {drive-path}/root:{local-path}, which should be /v1.0/sites/{site-id}/drive/root:/IT-0000-L. The root path is the directory that contains all Duplicati files, so if it does not exist it needs to be created.

What could be wrong

  • If the site ID is correct, you are definitely creating the folder somewhere in your Backups document library. You said you used /sites/root/sites?search=* to get the site ID. Please check that https://graph.microsoft.com/v1.0/sites/company.sharepoint.com:/sites/BackupRepository/Backups returns the same ID, so you’re not accidentally using a wrong path (maybe only BackupRepository?).
  • The method of separating the URL into prefix and local path seems pretty fragile to me. I think this is probably the main thing that could go wrong. In that case I would recommend that you specify the site ID and only the local path (that would be /IT-0000-L). If I understand the code correctly, this should still work, but avoid any difficulty with splitting the path.
  • If the splitting somehow does not work at all, I would guess that the files end up in Backups/company.sharepoint.com/sites/...
  • I don’t think it is possible to get the underlying exception message from the FolderMissingException using the Web UI, because it is not logged anywhere. However, if you are willing to use the backend tool (list command) it should hopefully output the exception message. There is also the backend tester, that will upload and check dummy files.