Running Duplicati on startup on Freenas / FreeBSD

Hi,

I’m trying to get Duplicate to start automatically in a FreeNas jail. Running it with the below command line works fine.

/usr/local/bin/mono /root/duplicati/Duplicati.Server.exe --webservice-port=8200 --webservice-interface=any --server-datafolder=/root/.duplicati

However, as soon as I put it in a rc.d startup script that looks like this and call service duplicate start I get an error.

/usr/local/etc/rc.d/duplicati
#!/bin/sh

# PROVIDE: duplicati 

. /etc/rc.subr

name="duplicati"
rcvar=${name}_enable 
start_cmd="${name}_start"
stop_cmd=":"

duplicati_start()
{
	if checkyesno ${rcvar}; then
		/usr/local/bin/mono /root/duplicati/Duplicati.Server.exe --webservice-port=8200 --webservice-interface=any --server-datafolder=/root/.duplicati &
	fi
}

load_rc_config ${name}
run_rc_command "$1"

root@backblaze_1:/usr/home/backblaze # service duplicati start
root@backblaze_1:/usr/home/backblaze #
Unhandled Exception:
System.ComponentModel.Win32Exception (0x80004005): ApplicationName=’/root/duplicati/Duplicati.Server.exe’, CommandLine=’"–webservice-port=8200" “–webservice-interface=any” “–server-datafolder=/root/.duplicati”’, CurrentDirectory=’’, Native error= Cannot find the specified file
at System.Diagnostics.Process.StartWithCreateProcess (System.Diagnostics.ProcessStartInfo startInfo) [0x002dc] in :0
at System.Diagnostics.Process.Start () [0x0003a] in :0
at (wrapper remoting-invoke-with-check) System.Diagnostics.Process:Start ()
at System.Diagnostics.Process.Start (System.Diagnostics.ProcessStartInfo startInfo) [0x0001b] in :0
at Duplicati.Library.AutoUpdater.UpdaterManager.RunFromMostRecentSpawn (System.Reflection.MethodInfo method, System.String[] cmdargs, Duplicati.Library.AutoUpdater.AutoUpdateStrategy defaultstrategy) [0x00196] in :0
at Duplicati.Library.AutoUpdater.UpdaterManager.RunFromMostRecent (System.Reflection.MethodInfo method, System.String[] cmdargs, Duplicati.Library.AutoUpdater.AutoUpdateStrategy defaultstrategy) [0x0001b] in :0
at Duplicati.Server.Program.Main (System.String[] args) [0x00014] in <62a3c38a5c9c4c6181771976288a28b1>:0
[ERROR] FATAL UNHANDLED EXCEPTION: System.ComponentModel.Win32Exception (0x80004005): ApplicationName=’/root/duplicati/Duplicati.Server.exe’, CommandLine=’"–webservice-port=8200" “–webservice-interface=any” “–server-datafolder=/root/.duplicati”’, CurrentDirectory=’’, Native error= Cannot find the specified file
at System.Diagnostics.Process.StartWithCreateProcess (System.Diagnostics.ProcessStartInfo startInfo) [0x002dc] in :0
at System.Diagnostics.Process.Start () [0x0003a] in :0
at (wrapper remoting-invoke-with-check) System.Diagnostics.Process:Start ()
at System.Diagnostics.Process.Start (System.Diagnostics.ProcessStartInfo startInfo) [0x0001b] in :0
at Duplicati.Library.AutoUpdater.UpdaterManager.RunFromMostRecentSpawn (System.Reflection.MethodInfo method, System.String[] cmdargs, Duplicati.Library.AutoUpdater.AutoUpdateStrategy defaultstrategy) [0x00196] in :0
at Duplicati.Library.AutoUpdater.UpdaterManager.RunFromMostRecent (System.Reflection.MethodInfo method, System.String[] cmdargs, Duplicati.Library.AutoUpdater.AutoUpdateStrategy defaultstrategy) [0x0001b] in :0
at Duplicati.Server.Program.Main (System.String[] args) [0x00014] in <62a3c38a5c9c4c6181771976288a28b1>:0

Any help will be much appreciated

Thanks

Hi All,

Im really struggling with this so wondering if someones managed to get Duplicate auto started under either FreeBSD or FreeNAS. Like I said above, I can start it from the command line no problem but only when it’s started as an rc.d script it fails. I think it may be something to do with the PATH used when calling a service under FreeBSD.

Thanks

Hi @Dilby, welcome to the forum!

I think you might be right about a pathing (or permissions) issue possibly related to the account under which it’s being run. When you do it on the command line is it as “you” or as “root” (which I assume is what it would run under from rc.d).

The actual path issue might be related to mono (or possibly certificates) as mentioned in these two (non-FreeNAS / BSD related) posts:

If neither of those are helpful perhaps somebody who’s already running it on FreeNAS (such as @Joe or @John_Delisle) might have some suggestions…

Out of curiosity, not including this current issue did you have any difficulties getting Duplicati installed & configured in a FreeNAS jail? I’m wondering if it needs it’s own How-To entry or not.

Hi JonMike,

Thanks for the reply. When running from the command line, I run as root user so should be the same.

Out of curiosity, not including this current issue did you have any difficulties getting Duplicati installed & configured in a FreeNAS jail? I’m wondering if it needs it’s own How-To entry or not.

It was fairly trivial to getting it running under FreeNAS. Simply a pkg install of mono followed by unzipping the zip version of Duplicati to a folder. I think as soon as I figure out the auto starting issue, that may warrant a dedicated howto.

Thanks

I have the following rc script working for starting the service when its jail is started. This is running on a plain FreeBSD jail but should be similar for FreeNAS. My goal was to start the service with a user other than root. In its current form it will not stop the service, but with some more work it should be possible.

#!/bin/sh
#
# PROVIDE: duplicati 
# REQUIRE: NETWORKING
# KEYWORD: duplicati

. /etc/rc.subr

name="duplicati"
rcvar=`set_rcvar`

duplicati_user="duplicati"
duplicati_command="/usr/local/bin/mono /opt/duplicati/Duplicati.Server.exe"     
duplicati_command_args="--webservice-port=8200 --webservice-interface=any --server-datafolder=/opt/duplicati/data"

pidfile="/var/run/${name}/${name}.pid"

command="/usr/sbin/daemon"
command_args="-P ${pidfile} ${duplicati_command} ${duplicati_command_args}"

load_rc_config $name
run_rc_command "$1"
2 Likes

Hi @Dilby
I had exactly this problem. After a bit of digging, I found the PATH was wrong when running from service duplicati start. To fix, just add this to your /etc/rc.d/duplicati

PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin:/root/bin

Hope that helps
Mark

Hi @mf111, welcome to the forum - and thanks for sharing your fix! :slight_smile:

Hopefully @Dilby will be able to use it and we can put together a #howto for this process.

Hey good folks!
I’m gonna go ahead and ”revive” this aging thread.
I’m trying to get Duplicati to play nice with rc.d, but I’m running into trouble, more or less identical to @Ryan_Y that it’s unable to stop the service.
The trouble I’m having is that when mono is launched, it spawns a new child process (mono-sgen).
This new process never receives a terminate signal if I want to stop the service.
I’m unsure what’s causing this behavior, since when the parent is asked to terminate, it should try to kill all its child processes too … but apparently that’s not happening.
How can I get the script to play nice with Duplicati and it’s process spawning?
Thanks in advance!
Best regards

Hey there @tiw, welcome to the forum!

Do you think you are experiencing the same thing as reported on Synology devices here?

Heya @JonMikelV,
And thanks for the welcome!
Unless I’m mistaken, that seems more or less spot on!

I’m not quite sure what I’d need to change in my rc.d script to implement that, or if at all possible.
Any help is welcome :slight_smile:
Thanks again!

Is that rc script online anywhere to see? You could certainly try adapting the cited fix. Click, then click “Files changed”. The method used pkill -P to kill children of the parent Duplicati, which then makes parent exit. Another way to do it is possibly to use pkill -g to kill the process group (parent, child, and anything else). That’s (I think) the same result as an ordinary kill using the parent PID negated, in case you don’t have pkill.

Hey @ts678,
Thanks for your input!
The script should be viewable at [Bash] duplicati rc.d script - Pastebin.com
Thanks :slight_smile:

Unfortunately there’s nothing in that script that stops Duplicati directly, so there’s not much I can point to. FreeBSD (and I’m not sure about FreeNAS, if it’s different) does have good documentation, for example:

Practical rc.d scripting in BSD
rc
rc.subr

Duplicati does not appear to ship a package for FreeNAS or FreeBSD. Are you running somebody’s port?
One view of this is that it’s a porting issue. Another is Duplicati Server should support normal conventions, instead of requiring odd shutdown steps like having to kill the child process instead of the original process. FreeBSD’s rc framework almost certainly is killing the parent. Could you search issues and (if needed) file:

Meanwhile, workarounds might include studying the rc mechanism enough to see what can be overridden, attempting to turn the standard stop into the sort of custom stop that the Synology script got. The BSD rc system does seem to allow more complex rc scripts than the sort of stub you posted, but it’s not clear what limits there might be. In any case, you might want to model the custom code as a one-off of standard code.

Possibly the easiest thing to do is to wrap whatever is finally launching Duplicati with an additional script to make it behave more conventionally, e.g. when it starts it can record its own PID file, and to stop it can use something like a trap command in bash to catch SIGTERM or whatever, and kill the Duplicati child in one of the mentioned ways. Of course, the script must pass supplied arguments through, for example using “$@”.

There’s probably no urgent need to save the PID on disk and exec. You could maybe just let the new script act as the revised duplicati_command (with better signal handling) that hangs around to track the real one. Possibly all of the processes will even land in the same process group (ps can say), making multi-kills easy.

Another possible approach is to see if you can switch from an rc.subr pidfile approach to a procname one, which looks like it has the potential of either finding the child or finding all of the duplicati server processes.

Please also search the forum and GitHub issues to see if any other thoughts come up. I didn’t do that yet…

Hello again,
Thanks for your thorough reply!
I’m using Duplicati straight off their page (or rather, the github releases).

I found nothing while glancing through their issues, I suppose my next step is filing the issue.

I was considering tinkering with the rc script further to see if I can rewrite or change something to have the service stopping mechanism do some custom work, wherein I find and kill the relevant process(es).

A search and (if needed) issue filed on Duplicati to behave in the standard way would avoid workarounds. The Synology one is incompatible with future-Duplicati in the seemingly-unlikely case it drops parent/child.

Please feel free. I’m sure the code involved is somewhere on your system. The docs I pointed to may help.

Alright, so I took a stab at changing the rc script’s behavior, and it turns out you can just define what happens when you run service foo stop by defining stop_cmd=baz and defining
baz() { /bin/pkill -P $(cat ${pidfile}); }
This in turn makes the rc script use that command to kill the process(es).
Voila:

#!/bin/sh
#
# PROVIDE: duplicati
# REQUIRE: LOGIN
# KEYWORD: shutdown

# Enable duplicati:
# sysrc duplicati_enable="YES"
# 
# Optional parameters:
# sysrc duplicati_user="<user to run as>"
# sysrc duplicati_data_dir="<folder for server data>"

. /etc/rc.subr

name="duplicati"
rcvar="${name}_enable"

load_rc_config $name

: ${duplicati_enable="NO"}
: ${duplicati_user:="duplicati"}
: ${duplicati_data_dir:="/config"}

duplicati_command_args="--webservice-port=8200 --webservice-interface=any --server-datafolder=${duplicati_data_dir}"
duplicati_command="/usr/local/share/${name}/Duplicati.Server.exe ${duplicati_command_args}"
pidfile="${duplicati_data_dir}/${name}.pid"
procname="/usr/local/bin/mono"
command="/usr/sbin/daemon"
command_args="-f -p ${pidfile} ${procname} ${duplicati_command}"
start_precmd=duplicati_precmd
stop_cmd=duplicati_stopcmd

duplicati_precmd() {
	export XDG_CONFIG_HOME=${duplicati_data_dir}

	# avoid root user warning
	export USER=${duplicati_user}

	if [ ! -d ${duplicati_data_dir} ]; then
		install -d -o ${duplicati_user} ${duplicati_data_dir}
	fi
}

duplicati_stopcmd() { /bin/pkill -P $(/bin/cat ${pidfile}); }

run_rc_command "$1"

Everything works like a charm, and turned out to be (quite) simple.
Thanks for pointing me in the right direction(s)! :slight_smile:

2 Likes

Thanks for sharing your workaround! :+1:

Do you think a #howto guide is “needed” for FreeNAS?

Hey!
Documentation is never wrong, so I’m quite confident a number of people would be helped by having a #howto describing a good way to install Duplicati on FreeNAS/FreeBSD – I suppose that the process is more or less identical.
I’m writing a script to automate the installation process on FreeNAS in an iocage jail while separating the Duplicati config from the jail itself, so that it’s easy to reinstall the jail when necessary.
Best regards,
Ted

That’s a good point - though I don’t personally have FreeNAS anymore, and never did figure out how to use jails so I’m probably not a very good one to actually write such a guide. (hint… hint… hint…) :wink:

With FreeNAS 11.3 introducing the community repository, I took a dive and created a duplicati plugin using a good bit of information from this thread. It is called duplicati (shocking I know) and is severely basic, but it does give a couple clicks to a working install. The tricky bits are getting the data you want to back up mounted to the jail, but that is similar anytime you want ot write to/from a pool on freenas from plugins.

2 Likes