I don’t think this can be done securely. One nasty case the password prevents is privilege escalation, where an attacker has managed to get execute access in a sandbox.
If there was a magic header to set, the attacker would be able to use this header and bypass the security.
Wish granted
Let me know if there are considerations to include before we merge this.
I’m a bit confused, as you said it can’t be done securely and yet you enable basically the same thing insecurely. As I see it, the https request from the proxy should be secure, and if you stored the defined “tokens” in the database along with trusted IPs, rather than in plain-text of the Duplicati server service that would be better. I suppose the token may not be secure on the proxy config and that I’m not sure how to make better but at least the connections can only come from the trusted IPs.
I misunderstood. From your text, I read that this was a proposed static header value, like:
X-From: HA-Proxy
That would not be secure, as the value is documented, so an attacker can send the same value.
Re-reading your post, I see I mentally skipped the part where you mention “secure token” which is exactly what I also suggested.
For the IP restriction, would it be sufficient to add this to a firewall or sorts?
The PR I have was based on the request from @felixilgatto where the need was to not invoke a tool as part of the spin-up. For that reason, the solution does not store any values in the database, but requires a value to be passed at startup, and is only kept in memory.
Do you have additional needs for your setup? Does it need to be persisted and IP locked?
Personally I would rather Duplicati controlled this, in my case the firewall would only be protecting from external access and I don’t have any exposed this way.
I feel there should still be a secure way to store these settings and still keep someway to override them via command-line which can also be beneficial for troubleshooting.
I have no real needs myself, I was mostly interested in this thread and wanted to add the extra information regarding HAProxy options. I don’t think there needs to be any kind of persistence.
Thank you for the solution to my issue—it’s much appreciated.
I don’t think a flawless solution is possible in this case, and it’s important to remember that Duplicati is not primarily a security tool. It’s understandable that experienced users may not trust the security layer implemented in it. I do respect the intention to protect casual users by default, as a minimum level of protection is definitely important.
However, I also believe it’s equally important to provide an option to disable such features for more experienced users who want to tailor their experience or improve usability.
This would then add the additional check of IPs. We could choose to store the string in the database, and then use commandline options (or server-util) to set/reset them.
Ok, then I suggest anyone who does need it, can create an issue and we can look at it then.
While Duplicati is not a security tool as such, any backup tool will have access to a lot of information and should be guarded.
And my goal is to make it “secure by default”, but this should not prevent using it differently by people who understand the consequences.
The pre-auth headers are part of the 2.1.0.113 release that will be up soon.
The implementation uses PreAuth to avoid breaking anything with the regular Bearer token. If there is no preauth configured, this part of the authorization code is never loaded by the server, so for most users, preauth is not possible.
The Bearer is for the regular tokens, including the forever-token option.
Thank you for your answer.
I have applied the header in Nginx.
Now, I am having the following error in the WebUI: The connection to the server is lost, attempting again in 0:10 …
There is no error appearing in Duplicati console itself.
My reverse proxy returns the following error: duplicati.mydomain.com 874.457.563.87- - [02/May/2025:15:58:00 +0200] "POST /api/v1/auth/refresh HTTP/2.0" 404 0 "https://duplicati.mydomain.com/ngax/index.html" "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:138.0) Gecko/20100101 Firefox/138.0"
Not sure why that is. The 404 should not be from Duplicati, as it will return 403 if the token is invalid, so I am guessing that the routing is somehow not hitting the right path?