Connecting the Tray Icon to a systemctl-started Service

I am sorry if this is already answered somewhere, but I haven’t found any forum thread, GitHub issue or documentation article about it.

What I Am Trying to Achieve

I am using duplicati on my Ubuntu device. I have multiple users on my machine. I want to run duplicati as a system service so that it runs all backups of all users, no matter which user is currently logged in.

This seems to be working, however, I cannot get the tray icon to work.

What I Tried

I added DUPLICATI_HOME="/usr/share/Duplicati" to /etc/default/duplicati and enabled the duplicati systemctl service with sudo systemctl enable duplicati. I can now access the Web UI and run backups.

Now I try to start the tray icon, but always get the same error:

Request error: System.Net.WebException: The remote server returned an error: (401) Not logged in.
Full Stack Trace
Request error: System.Net.WebException: The remote server returned an error: (401) Not logged in.
  at System.Net.HttpWebRequest.GetResponseFromData (System.Net.WebResponseStream stream, System.Threading.CancellationToken cancellationToken) [0x0017e] in <a85c1a570f9a4f9f9c3d2cfa5504e34f>:0 
  at System.Net.HttpWebRequest.RunWithTimeoutWorker[T] (System.Threading.Tasks.Task`1[TResult] workerTask, System.Int32 timeout, System.Action abort, System.Func`1[TResult] aborted, System.Threading.CancellationTokenSource cts) [0x00118] in <a85c1a570f9a4f9f9c3d2cfa5504e34f>:0 
  at Duplicati.Library.Utility.AsyncHttpRequest+AsyncWrapper.GetResponseOrStream () [0x0004d] in <b0ec73cdc8b845289fe2e9bdf696ccd0>:0 
  at Duplicati.Library.Utility.AsyncHttpRequest.GetResponse () [0x00044] in <b0ec73cdc8b845289fe2e9bdf696ccd0>:0 
  at Duplicati.GUI.TrayIcon.HttpServerConnection.PerformRequestInternal[T] (System.String method, System.String endpoint, System.Collections.Generic.Dictionary`2[TKey,TValue] queryparams) [0x001d1] in <d8f7365e5553410c9b088018a8456fd3>:0 
  at Duplicati.GUI.TrayIcon.HttpServerConnection.PerformRequest[T] (System.String method, System.String urlfragment, System.Collections.Generic.Dictionary`2[TKey,TValue] queryparams) [0x001bd] in <d8f7365e5553410c9b088018a8456fd3>:0 
  at Duplicati.GUI.TrayIcon.HttpServerConnection.UpdateStatus () [0x00001] in <d8f7365e5553410c9b088018a8456fd3>:0 
  at Duplicati.GUI.TrayIcon.HttpServerConnection..ctor (System.Uri server, System.String password, System.Boolean saltedpassword, Duplicati.GUI.TrayIcon.Program+PasswordSource passwordSource, System.Boolean disableTrayIconLogin, System.Collections.Generic.Dictionary`2[TKey,TValue] options) [0x000cb] in <d8f7365e5553410c9b088018a8456fd3>:0 
  at Duplicati.GUI.TrayIcon.Program.StartTray (System.String[] _args, System.Collections.Generic.Dictionary`2[TKey,TValue] options, System.String toolkit, Duplicati.GUI.TrayIcon.HostedInstanceKeeper hosted, System.String password, System.Boolean saltedpassword) [0x00024] in <d8f7365e5553410c9b088018a8456fd3>:0 
Request error: System.Net.WebException: The remote server returned an error: (401) Not logged in.
  at System.Net.HttpWebRequest.GetResponseFromData (System.Net.WebResponseStream stream, System.Threading.CancellationToken cancellationToken) [0x0017e] in <a85c1a570f9a4f9f9c3d2cfa5504e34f>:0 
  at System.Net.HttpWebRequest.RunWithTimeoutWorker[T] (System.Threading.Tasks.Task`1[TResult] workerTask, System.Int32 timeout, System.Action abort, System.Func`1[TResult] aborted, System.Threading.CancellationTokenSource cts) [0x00118] in <a85c1a570f9a4f9f9c3d2cfa5504e34f>:0 
  at Duplicati.Library.Utility.AsyncHttpRequest+AsyncWrapper.GetResponseOrStream () [0x0004d] in <b0ec73cdc8b845289fe2e9bdf696ccd0>:0 
  at Duplicati.Library.Utility.AsyncHttpRequest.GetResponse () [0x00044] in <b0ec73cdc8b845289fe2e9bdf696ccd0>:0 
  at Duplicati.GUI.TrayIcon.HttpServerConnection.PerformRequestInternal[T] (System.String method, System.String endpoint, System.Collections.Generic.Dictionary`2[TKey,TValue] queryparams) [0x001d1] in <d8f7365e5553410c9b088018a8456fd3>:0 
  at Duplicati.GUI.TrayIcon.HttpServerConnection.PerformRequest[T] (System.String method, System.String urlfragment, System.Collections.Generic.Dictionary`2[TKey,TValue] queryparams) [0x001bd] in <d8f7365e5553410c9b088018a8456fd3>:0 
  at Duplicati.GUI.TrayIcon.HttpServerConnection.UpdateStatus () [0x00001] in <d8f7365e5553410c9b088018a8456fd3>:0 
  at Duplicati.GUI.TrayIcon.HttpServerConnection..ctor (System.Uri server, System.String password, System.Boolean saltedpassword, Duplicati.GUI.TrayIcon.Program+PasswordSource passwordSource, System.Boolean disableTrayIconLogin, System.Collections.Generic.Dictionary`2[TKey,TValue] options) [0x000cb] in <d8f7365e5553410c9b088018a8456fd3>:0 
  at Duplicati.GUI.TrayIcon.Program.StartTray (System.String[] _args, System.Collections.Generic.Dictionary`2[TKey,TValue] options, System.String toolkit, Duplicati.GUI.TrayIcon.HostedInstanceKeeper hosted, System.String password, System.Boolean saltedpassword) [0x00024] in <d8f7365e5553410c9b088018a8456fd3>:0 
Request error: System.Net.WebException: The remote server returned an error: (401) Not logged in.
  at System.Net.HttpWebRequest.GetResponseFromData (System.Net.WebResponseStream stream, System.Threading.CancellationToken cancellationToken) [0x0017e] in <a85c1a570f9a4f9f9c3d2cfa5504e34f>:0 
  at System.Net.HttpWebRequest.RunWithTimeoutWorker[T] (System.Threading.Tasks.Task`1[TResult] workerTask, System.Int32 timeout, System.Action abort, System.Func`1[TResult] aborted, System.Threading.CancellationTokenSource cts) [0x00118] in <a85c1a570f9a4f9f9c3d2cfa5504e34f>:0 
  at Duplicati.Library.Utility.AsyncHttpRequest+AsyncWrapper.GetResponseOrStream () [0x0004d] in <b0ec73cdc8b845289fe2e9bdf696ccd0>:0 
  at Duplicati.Library.Utility.AsyncHttpRequest.GetResponse () [0x00044] in <b0ec73cdc8b845289fe2e9bdf696ccd0>:0 
  at Duplicati.GUI.TrayIcon.HttpServerConnection.PerformRequestInternal[T] (System.String method, System.String endpoint, System.Collections.Generic.Dictionary`2[TKey,TValue] queryparams) [0x001d1] in <d8f7365e5553410c9b088018a8456fd3>:0 
  at Duplicati.GUI.TrayIcon.HttpServerConnection.PerformRequest[T] (System.String method, System.String urlfragment, System.Collections.Generic.Dictionary`2[TKey,TValue] queryparams) [0x001bd] in <d8f7365e5553410c9b088018a8456fd3>:0 
  at Duplicati.GUI.TrayIcon.HttpServerConnection.UpdateStatus () [0x00001] in <d8f7365e5553410c9b088018a8456fd3>:0 
  at Duplicati.GUI.TrayIcon.HttpServerConnection..ctor (System.Uri server, System.String password, System.Boolean saltedpassword, Duplicati.GUI.TrayIcon.Program+PasswordSource passwordSource, System.Boolean disableTrayIconLogin, System.Collections.Generic.Dictionary`2[TKey,TValue] options) [0x000cb] in <d8f7365e5553410c9b088018a8456fd3>:0 
  at Duplicati.GUI.TrayIcon.Program.StartTray (System.String[] _args, System.Collections.Generic.Dictionary`2[TKey,TValue] options, System.String toolkit, Duplicati.GUI.TrayIcon.HostedInstanceKeeper hosted, System.String password, System.Boolean saltedpassword) [0x00024] in <d8f7365e5553410c9b088018a8456fd3>:0 

I tried the following combinations:

duplicati --no-hosted-server --read-config-from-db /usr/share/Duplicati
duplicati --no-hosted-server --webservice-password <the-password>
duplicati --no-hosted-server --read-config-from-db --server-datafolder /usr/share/Duplicati/

My Questions

  1. Does my setup make sense, i.e. is this how duplicati is meant to be used for my use case?
  2. How can I get the tray icon to connect to my duplicati server?

Okay, I found the solution to my second question:

How can I get the tray icon to connect to my duplicati server?

The duplicati tray icon will also examine the DUPLICATI_HOME environment variable.

What I did, step by step:

  1. Added all my users to the users group: sudo usermod -a -G users <username> (the users group already existed on my system. You can reload group assignments by running newgrp users)
  2. Made the database file accessible to the users group with sudo chgrp users /usr/share/Duplicati/Duplicati-server.sqlite and sudo chmod g+r /usr/share/Duplicati/Duplicati-server.sqlite
  3. Started the tray icon with
env DUPLICATI_HOME=/usr/share/Duplicati/ duplicati --no-hosted-server --read-config-from-db
1 Like

Thanks for following up and posting your solution!