Newb Cron Question

Hi there, another pretty basic newb question I think.

I use rsync to backup work on one AppVM to a remote server.

I’d like this to be automated and run every 15 mins. I’d normally have turned to Cron to handle this, but that doesn’t seem to be an option in Qubes out of the box.

I’ve gone through the various cron related posts on GitHub and here, and I’m more confused then when I started.

I would like to enable Cron for one particular AppVM only, and leave it off for the rest. Is that possible or should I be doing this another way?

Thanks!

Hi @JustAnotherQubesUser

I don’t give you a solution but two possibilities you can explore:

  • cron
  • systemd timer units

cron

It depends of the OS of your AppVM, for example Debian uses crontab. crontab -e allows to add/edit crontab entries for current user (AppMV user or root if you use sudo crontab -e).
So read the documentation of your AppVM distribution (fedora documentation, debian documentation, …).

Qubes specific: the directory where are stored the cron tasks may not be in the /rw AppVM storage (example: crontab uses /var/spool/cron/crontabs). This could be a problem, check by yourself.

Systemd timer units

You could create systemd timer units for your AppVM user.
A systemd timer is used to execute a systemd service for a choose date/time frequency/… like cron (see systemd.timer).
You can create systemd units for the system or only a user (see --user of man systemd / man systemctl).
You can store a systemd service or timer in the System Unit Search Path or User Unit Search Path (see man systemd.unit).
Note that most of User Unit Search Path are in the homedir (so specific to AppVM storage: /rw) and note also that you can store systemd units in /usr/local (so also in /rw).

Thanks for that ludovic, however, I’m still somewhat confused.

My understanding is that the cron service is disabled in Qubes, so although I’m able to go and schedule a cron job, it won’t actually run.

And if I go an enable Cron as a service, it will be enabled for all AppVms which will potentially lead to a performance hit having three or four instances of Fedora running the same scheduled job at the same time.

To clarify my question somewhat - is it possible to enable the cron service for a named AppVM only? And if so, how do I do it?

I’m just following up on this.

I have tried, on numerous occasions to enable cron via qvm-service, I’ve done this for the app-template (Fedora-32) as well as the specific app vm.

I’m not getting any errors in the dom0 terminal when I run qvm-service -e appVMName crond

However, cron is not running in the app vm. I also can’t see any reference to it in /var/spool/

Any help?

So it turns out that you have to install cron…

Once you do that, it is possible for QVM to turn it on…

I’ve been playing around with this and I think the easiest way by far is by using dom0’s cron. It always running and can wake up your VM for running the backups. Plus it doesn’t have problems with the crontab information being deleted upon reboot due to the lack of persistence of the root file system.

@JustAnotherQubesUser let me know if you have any issues.

Explanation

For the sake of simplicity let’s say your AppVM called work. To test if this is working, instead calling rsync, we’ll just create files with the current timestamp. It can later be changed to whatever you may want.

Implementation

The basic idea is:

cron (dom0) -> backup.sh (dom0) -> backup.sh (work AppVM)

In order to be able to test things as we go, we’ll create them in reverse order

backup.sh (work AppVM)

First you create a script on you work AppVM, for example in /home/user/scripts/backup.sh that contains:

# Any other thing could go here
# as this is the script that's executed periodically
touch $(date +%s) # create a file named with the timestamp

Note This script here could be avoided if on the second one we called directly the commands. But for separation of concerns and avoid anything else than it needs on dom0, were’re creating it.

backup.sh (dom0)

Secondly we create a script that will call our first script. For example this can be on /home/<USER>/backup.sh, where <USER> is your dom0 username. It will contain

qvm-run work /home/user/scripts/backup.sh

cron (dom0)

Then, you open a dom0 terminal (XFCE Terminal) and setup a cron job (by running crontab -e) and adding your cron line:

*/2  * * * * /home/user/backup.sh

The above will run it every two minutes. You’ll probably want to change it for whatever you want

1 Like

Thanks for that.

I’d rather not run it in Dom0, as really the script should only fire once the relevant AppVM is working.

I have created a backup.sh file, which I can run as user without sudo in the AppVm.
This works fine when fired manually.

I have create a symlink between a file called ‘crontab’ which exists in /rw/home/user/path/to/file and /etc/crontab

This file’s user / group is root:root

the file contains the normal crontab bumpf as well as:

* * * * * user /rw/home/user/path/to/./backup.sh

Yet the bloody thing doesn’t fire! Is there an error in my crontab file?
When I run, in the AppVM, service crond status, it is up.

This is getting annoying now!

update: there’s a better way of doing this on Qubes: see this unman’s post


I’m not terribly familiar with crontab. But it seems like it should work…

Also, the /etc/crontab will be erased upon reboot as it is not persistent on AppVMs. Have you considered having your crontab file in /rw/config/crontab and adding the following to the /rw/config/rc.local: (which is ran after the AppVM starts)

# symlink /etc/crontab with your crontab configuration (as you were already doing manually)
sudo ln -s /rw/home/user/path/to/file /etc/crontab
# and 

Thanks - yes, I meant to say that I have a similar setting in place, one which overwrites the /etc/crontab with a symlink to the /rw/home/user/path… one.

Should I be using anacrontab?

I’m not the familiar with Fedora, but what I have done would have worked in Debian.

Um, it should be sufficient to enable the crond service for that qube,
using qvm-service , which should just work.
This was mentioned way back in the thread, but because of the brain dead
way in which Forum posts come in email, I find it hard to see if you
resolved this issue or not.
And yes, since the qubes start and stop a lot I would always use
anacron

Thanks @unman

Yes, I have enabled the crond service in qvm, and have confirmed that it is running when the AppVm starts.

From what I can make out, the problem is either:

an incorrect syntax in the crontab entry; or
In fedora, you should be using a different service

There is, I guess, a potential third issue in that the permissions may be incorrect for the symlink.

To recap:

  • Crond has been enabled in qvm
  • service crond status confirms that crond is up when the AppVM is running
  • there is an entry in the rc.local to replace /etc/crontab with /rw/home/user/path/to/new/crontab
  • the script which is invoked in the crontab, runs fine when run manually and doesn’t require sudo
  • yet it doesn’t work!

Can anyone help?!

It’s late now, so I might leave to the morning:
Can you confirm that this is the current position?

Hi @unman

Yes, that is the state of play at the moment.

Thanks!

I have a backup cronjob that I’m trying to implement.
And then I’m wondering if it’s possible to run qvm-copy automatically? Without a pop-up window.
I realise that currently I have to return to my screen and type in the VM name when away, and that it could interrupt my workflow if I happen to be working at that time.
First time doing something like this, so probably some stuff I could improve upon.

Crontab:
0 5 * * 1 ~/.rc/back
Run at 5 am every week

Backup script:

cp ~/db.kdbx ~/db_`date +\%d\%m\%Y`.kdbx
qvm-copy db_`date +\%d\%m\%Y`.kdbx
rm db_`date +\%d\%m\%Y`.kdbx

This will copy from my airgapped VM where the database will be unlocked and modified.
I always make a new file name because qvm-copy fails if the same file already exists on the destination VM.

From there I use nextcloudcmd to sync with the server.

@9009

Is cron working for you in the AppVm or are you using the Dom0 Cron (which I think you are)?

Yes, it is possible. You just need to change the qrexe policy file in /etc/qubes-rpc/policy/qubes.Filecopy and add:

[src_vm] [target_vm] allow

where [src_vm] is the VM where you want to copy the files to and [target_vm] the one you want to copy them to.

But I encourage you to read the documentation on Qubes RPC Policies Files as changing them has security implications:

1 Like

You don’t need to make any entry in rc.local or symlink - Qubes has already covered
this as you will see if you examine /rw/bind-dirs/var/spool/cron, and
cron will work out of the box when you enable the service.

You should use crontab -e to create and change crontab entries.
I see your entry:
* * * * * user /rw/home/user/path/to/./backup.sh

Can you try that without the user field?
It would be helpful if you posted the contents of backup.sh

1 Like
$ sudo systemctl status cron
● cron.service - Regular background program processing daemon
   Loaded: loaded (/lib/systemd/system/cron.service; enabled; vendor preset: enabled)
  Drop-In: /usr/lib/systemd/system/cron.service.d
           └─30_qubes.conf
   Active: inactive (dead)
Condition: start condition failed at Sat 2020-12-19 13:03:38 CET; 8min ago
           └─ ConditionPathExists=/var/run/qubes-service/crond was not met
     Docs: man:cron(8)

Dec 19 13:03:38 VM systemd[1]: Condition check resulted in Regular background program processing daemon being skipped.

I’ve tried sudo and user crontab now, but doesn’t look like anything is being done. /var/run/qubes-service/crond doesn’t exist.

I thought you said this was a Fedora based qube? The service there is
crond isn’t it?
Are you now using a different template?
The error suggests that you have not enabled the crond service:
qvm-service -e <qube> crond

I’m not the OP, but could use some help as well. Looks like the services are different in Debian, since after running that command I still get the same output.