Using Duplicati with FTP WORM (write once read many)

Hi together,
i am trying to setup duplicati with my pc backup stored to my QNAP NAS via FTP. My FTP server has the option enabled to write only as a protection against ransome ware. While creating a configuration i receive the below error message as duplicati probably cannot remove the testfile again. Is there a way to tell duplicati to be in write only mode? I walked through the options and docu but was not able to see any of that. would it be meaningful, to pass the configuration by having the priveledges set to write and delete and change it once it is setup?

Failed to connect: error-id:FileMissing, user-information:The file duplicati-access-privileges-test.tmp was not found. Message: Code: 550 Message: /T14s/duplicati-access-privileges-test.tmp: Operation not permitted

Kind regards
knut

You need to do some configuration to get this to work.
First of all, the test connection will probably not work, because it always tries to add and delete a file to see whether it has the permissions for that. Since you verified the connection works, just manually remove the file if possible and don’t press the button again.

The next step is to make sure there is no attempt to remove any files. The way duplicati works, there is only a need to do this if old backup data is no longer wanted. This causes compact operations, where older backup volumes are downloaded, any unused data is removed, and new smaller volumes are uploaded to save space. This will not be possible in your setup, so you should disable it:

--no-auto-compact=true

Then, you also want to keep all versions of the data, as it will otherwise try to remove the file list files for removed versions.

If this isn’t enough and you still get an error, I might have missed some edge case so please post the error if it happens.

1 Like

Thank you for your quick reply. I tried running a sample backup with no-auto-compact and FTP WORM active. It starts pushing the aes files to the NAS and seems to run through initially but then runs into an error on verifying the backend data in the end of the process.

would you have more ideas on this?

logfile as below

        {

“DeletedFiles”: 0,
“DeletedFolders”: 0,
“ModifiedFiles”: 0,
“ExaminedFiles”: 938,
“OpenedFiles”: 938,
“AddedFiles”: 938,
“SizeOfModifiedFiles”: 0,
“SizeOfAddedFiles”: 524821494,
“SizeOfExaminedFiles”: 524821494,
“SizeOfOpenedFiles”: 524821494,
“NotProcessedFiles”: 0,
“AddedFolders”: 1,
“TooLargeFiles”: 0,
“FilesWithError”: 0,
“ModifiedFolders”: 0,
“ModifiedSymlinks”: 0,
“AddedSymlinks”: 0,
“DeletedSymlinks”: 0,
“PartialBackup”: false,
“Dryrun”: false,
“MainOperation”: “Backup”,
“CompactResults”: null,
“VacuumResults”: null,
“DeleteResults”: null,
“RepairResults”: null,
“TestResults”: null,
“ParsedResult”: “Fatal”,
“Interrupted”: false,
“Version”: “2.1.0.2 (2.1.0.2_beta_2024-11-29)”,
“EndTime”: “2025-01-19T20:16:00.0597808Z”,
“BeginTime”: “2025-01-19T20:13:55.8109345Z”,
“Duration”: “00:02:04.2488463”,
“MessagesActualLength”: 137,
“WarningsActualLength”: 5,
“ErrorsActualLength”: 2,
“Messages”: [
“2025-01-19 21:13:55 +01 - [Information-Duplicati.Library.Main.Controller-StartingOperation]: Die Operation Backup wurde gestartet”,
“2025-01-19 21:13:56 +01 - [Information-Duplicati.Library.Main.BasicResults-BackendEvent]: Backend event: List - Started: ()”,
“2025-01-19 21:13:56 +01 - [Information-Duplicati.Library.Main.BasicResults-BackendEvent]: Backend event: List - Completed: (2 Bytes)”,
“2025-01-19 21:14:07 +01 - [Information-Duplicati.Library.Main.BasicResults-BackendEvent]: Backend event: Put - Started: duplicati-bc44b25e463ab4669b0494c29d48f9db6.dblock.zip.aes (49,24 MB)”,
“2025-01-19 21:14:08 +01 - [Information-Duplicati.Library.Main.BasicResults-BackendEvent]: Backend event: Put - Started: duplicati-b1a028fa04deb424d8c543f12a911f694.dblock.zip.aes (49,04 MB)”,
“2025-01-19 21:14:09 +01 - [Information-Duplicati.Library.Main.BasicResults-BackendEvent]: Backend event: Put - Started: duplicati-bc28ec39193a44c57acc834cc9edda03d.dblock.zip.aes (49,59 MB)”,
“2025-01-19 21:14:09 +01 - [Information-Duplicati.Library.Main.BasicResults-BackendEvent]: Backend event: Put - Started: duplicati-b1a782b51d75c4927b7a8f9b209e78f8f.dblock.zip.aes (49,16 MB)”,
“2025-01-19 21:14:09 +01 - [Information-Duplicati.Library.Main.BasicResults-BackendEvent]: Backend event: Put - Completed: duplicati-bc44b25e463ab4669b0494c29d48f9db6.dblock.zip.aes (49,24 MB)”,
“2025-01-19 21:14:09 +01 - [Information-Duplicati.Library.Main.BasicResults-BackendEvent]: Backend event: Put - Started: duplicati-i50ff81b6351f4f0aa7a014bac8906f2d.dindex.zip.aes (8,01 KB)”,
“2025-01-19 21:14:09 +01 - [Information-Duplicati.Library.Main.BasicResults-BackendEvent]: Backend event: Put - Completed: duplicati-i50ff81b6351f4f0aa7a014bac8906f2d.dindex.zip.aes (8,01 KB)”,
“2025-01-19 21:14:09 +01 - [Information-Duplicati.Library.Main.BasicResults-BackendEvent]: Backend event: Put - Started: duplicati-b5cba4531af2046549225d22315e7d10e.dblock.zip.aes (49,15 MB)”,
“2025-01-19 21:14:12 +01 - [Information-Duplicati.Library.Main.BasicResults-BackendEvent]: Backend event: Put - Completed: duplicati-b1a028fa04deb424d8c543f12a911f694.dblock.zip.aes (49,04 MB)”,
“2025-01-19 21:14:13 +01 - [Information-Duplicati.Library.Main.BasicResults-BackendEvent]: Backend event: Put - Started: duplicati-i0b72d6827dcf485c962d8cd77cda280b.dindex.zip.aes (9,68 KB)”,
“2025-01-19 21:14:13 +01 - [Information-Duplicati.Library.Main.BasicResults-BackendEvent]: Backend event: Put - Retrying: duplicati-bc28ec39193a44c57acc834cc9edda03d.dblock.zip.aes (49,59 MB)”,
“2025-01-19 21:14:13 +01 - [Information-Duplicati.Library.Main.BasicResults-BackendEvent]: Backend event: Put - Completed: duplicati-i0b72d6827dcf485c962d8cd77cda280b.dindex.zip.aes (9,68 KB)”,
“2025-01-19 21:14:13 +01 - [Information-Duplicati.Library.Main.BasicResults-BackendEvent]: Backend event: Put - Started: duplicati-b674af21921e649769da296e79cea93a7.dblock.zip.aes (49,52 MB)”,
“2025-01-19 21:14:14 +01 - [Information-Duplicati.Library.Main.BasicResults-BackendEvent]: Backend event: Put - Retrying: duplicati-b5cba4531af2046549225d22315e7d10e.dblock.zip.aes (49,15 MB)”,
“2025-01-19 21:14:15 +01 - [Information-Duplicati.Library.Main.BasicResults-BackendEvent]: Backend event: Put - Retrying: duplicati-b1a782b51d75c4927b7a8f9b209e78f8f.dblock.zip.aes (49,16 MB)”,
“2025-01-19 21:14:15 +01 - [Information-Duplicati.Library.Main.BasicResults-BackendEvent]: Backend event: Put - Retrying: duplicati-b674af21921e649769da296e79cea93a7.dblock.zip.aes (49,52 MB)”,
“2025-01-19 21:14:23 +01 - [Information-Duplicati.Library.Main.BasicResults-BackendEvent]: Backend event: Put - Rename: duplicati-bc28ec39193a44c57acc834cc9edda03d.dblock.zip.aes (49,59 MB)”
],
“Warnings”: [
“2025-01-19 21:15:18 +01 - [Warning-Duplicati.Library.Main.BackendManager-DeleteRemoteFileFailed]: Die Auflistung bestätigt, dass die Datei duplicati-bc28ec39193a44c57acc834cc9edda03d.dblock.zip.aes nicht gelöscht wurde\r\nFileMissingException: The file duplicati-bc28ec39193a44c57acc834cc9edda03d.dblock.zip.aes was not found. Message: Code: 550 Message: /T14s/duplicati-bc28ec39193a44c57acc834cc9edda03d.dblock.zip.aes: Delete permission denied in WORM folder”,
“2025-01-19 21:15:28 +01 - [Warning-Duplicati.Library.Main.BackendManager-DeleteRemoteFileFailed]: Die Auflistung bestätigt, dass die Datei duplicati-bc28ec39193a44c57acc834cc9edda03d.dblock.zip.aes nicht gelöscht wurde\r\nFileMissingException: The file duplicati-bc28ec39193a44c57acc834cc9edda03d.dblock.zip.aes was not found. Message: Code: 550 Message: /T14s/duplicati-bc28ec39193a44c57acc834cc9edda03d.dblock.zip.aes: Delete permission denied in WORM folder”,
“2025-01-19 21:15:38 +01 - [Warning-Duplicati.Library.Main.BackendManager-DeleteRemoteFileFailed]: Die Auflistung bestätigt, dass die Datei duplicati-bc28ec39193a44c57acc834cc9edda03d.dblock.zip.aes nicht gelöscht wurde\r\nFileMissingException: The file duplicati-bc28ec39193a44c57acc834cc9edda03d.dblock.zip.aes was not found. Message: Code: 550 Message: /T14s/duplicati-bc28ec39193a44c57acc834cc9edda03d.dblock.zip.aes: Delete permission denied in WORM folder”,
“2025-01-19 21:15:49 +01 - [Warning-Duplicati.Library.Main.BackendManager-DeleteRemoteFileFailed]: Die Auflistung bestätigt, dass die Datei duplicati-bc28ec39193a44c57acc834cc9edda03d.dblock.zip.aes nicht gelöscht wurde\r\nFileMissingException: The file duplicati-bc28ec39193a44c57acc834cc9edda03d.dblock.zip.aes was not found. Message: Code: 550 Message: /T14s/duplicati-bc28ec39193a44c57acc834cc9edda03d.dblock.zip.aes: Delete permission denied in WORM folder”,
“2025-01-19 21:15:59 +01 - [Warning-Duplicati.Library.Main.BackendManager-DeleteRemoteFileFailed]: Die Auflistung bestätigt, dass die Datei duplicati-bc28ec39193a44c57acc834cc9edda03d.dblock.zip.aes nicht gelöscht wurde\r\nFileMissingException: The file duplicati-bc28ec39193a44c57acc834cc9edda03d.dblock.zip.aes was not found. Message: Code: 550 Message: /T14s/duplicati-bc28ec39193a44c57acc834cc9edda03d.dblock.zip.aes: Delete permission denied in WORM folder”
],
“Errors”: [
“2025-01-19 21:16:00 +01 - [Error-Duplicati.Library.Main.Operation.BackupHandler-FatalError]: Fatal error\r\nFileMissingException: The file duplicati-bc28ec39193a44c57acc834cc9edda03d.dblock.zip.aes was not found. Message: Code: 550 Message: /T14s/duplicati-bc28ec39193a44c57acc834cc9edda03d.dblock.zip.aes: Delete permission denied in WORM folder”,
“2025-01-19 21:16:00 +01 - [Error-Duplicati.Library.Main.Controller-FailedOperation]: Die Operation Backup ist mit folgenden Fehler fehlgeschlagen: The file duplicati-bc28ec39193a44c57acc834cc9edda03d.dblock.zip.aes was not found. Message: Code: 550 Message: /T14s/duplicati-bc28ec39193a44c57acc834cc9edda03d.dblock.zip.aes: Delete permission denied in WORM folder\r\nFileMissingException: The file duplicati-bc28ec39193a44c57acc834cc9edda03d.dblock.zip.aes was not found. Message: Code: 550 Message: /T14s/duplicati-bc28ec39193a44c57acc834cc9edda03d.dblock.zip.aes: Delete permission denied in WORM folder”
],
“BackendStatistics”: {
“RemoteCalls”: 44,
“BytesUploaded”: 520856539,
“BytesDownloaded”: 0,
“FilesUploaded”: 23,
“FilesDownloaded”: 0,
“FilesDeleted”: 0,
“FoldersCreated”: 0,
“RetryAttempts”: 18,
“UnknownFileSize”: 0,
“UnknownFileCount”: 2,
“KnownFileCount”: 37,
“KnownFileSize”: 1022138647,
“LastBackupDate”: “2025-01-19T21:13:57+01:00”,
“BackupListCount”: 1,
“TotalQuotaSpace”: 0,
“FreeQuotaSpace”: 0,
“AssignedQuotaSpace”: -1,
“ReportedQuotaError”: false,
“ReportedQuotaWarning”: false,
“MainOperation”: “Backup”,
“ParsedResult”: “Success”,
“Interrupted”: false,
“Version”: “2.1.0.2 (2.1.0.2_beta_2024-11-29)”,
“EndTime”: “0001-01-01T00:00:00”,
“BeginTime”: “2025-01-19T20:13:55.8110067Z”,
“Duration”: “00:00:00”,
“MessagesActualLength”: 0,
“WarningsActualLength”: 0,
“ErrorsActualLength”: 0,
“Messages”: null,
“Warnings”: null,
“Errors”: null
}
}

It looks like 18 retries were attempted for uploading. Is there a reason for the connection to be unreliable? If that is the case, it is going to be difficult to fix because if an upload fails some number of times it will try to rename (copy and delete) the file. It probably uses the same name when retrying, which will cause problems when the file already existed partially. So you might need to set the number of retries to zero as well and see if the connection can be improved.

It uses a different name, but I’m not sure that helps. Partial files get cleaned up by delete.
FTP Write-Only seem a bit self-contradictory on view vs. read, but modify seems allowed.

Modify provides both a gap for savvy malware, and also a possible option to copy files up.
For example, if you have disk space, you could do a local backup, then rclone it over FTP.

If Duplicati stops in middle of backup, run-script-after won’t run. Have it check for success.
Interruption of rclone will leave an incomplete remote clone which will be fixed on next run.

At start of a Duplicati backup, cleanups may occur. The idea is to finish them before rclone.

If you can get upload more reliable (so annoyance level is tolerable), you might try opening temporary access for cleanup. I think Verify files button can do that faster than backup.

Any way you go, you’ll need to open up access for Compact sometime, or grow indefinitely.

Hi ts678, i only use the setting of Enable FTP WORM (Write Once Read Many) function, the FTP Write-Only seems to stir even more problems on first sight.
I was not able to check Jojo-1000’s idea yet. Will approach that soon.
Thanks for your comments already :slight_smile:

I don’t have a QNAP, so missed right section on first try, as it’s only there if one expands the
“Configuring FTP Server Settings” section. Regardless, I’m still not clear what exactly it does, because it talks only about folders, and not about files in the folders. If it’s the same, then the suggestion about rclone won’t work, but you’ll be better protected against malware overwrite.

Do you happen to know what filesystem you have? One user uses ZFS snapshots to protect.
Ransomware protection with chattr cites that, and also suggests a sticky-bit-based approach.

i dont really know much about the filesystem but i think i will go with snapshots then which seem to be offered by QNAP for this kind of scenario. Against Ransomware | Protect your data from ransomware | QNAP
Thanks again all for the help

1 Like

Although that sounds like it should be effective unless client malware figures out the QNAP login, encrypting sensitive fields in Duplicati-server.sqlite is also helpful to keep malware out of servers.

There’s even a nag message that I would think is rarely seen because few start Duplicati like this:

C:\Program Files\Duplicati 2>Duplicati.GUI.TrayIcon

C:\Program Files\Duplicati 2>No database encryption key was found. The database will be stored unencrypted. Supply an encryption key via the environment variable SETTINGS_ENCRYPTION_KEY or disable database encryption with the option --disable-db-encryption

Configuring the server encryption discusses, but I question effectiveness against skilled attacks.
This is the reason why server-side protection is superior (short of a keylogging or similar attack).