Backups are resource demanding because they put additional load on CPU and storage - differential backups in Proxmox Backup Server help by cutting time required to have machines dumped to backup server significantly but not to the point where we could schedule backups e.g. every hour. It's not a lost cause though because there is another mechanism - snapshots. Snapshots are an easy and resource-wise way to protect data stored in containers and virtual machines because they just mark points in time  

Proxmox Virtual Environment  API is a core element that rest of management interfaces is built on. It provides us with an easy way to automate tasks like making and deleting snapshots at programmed intervals. Lets have a look at endpoints that we will need for managing snapshots of LXC container:

In a similar way we can list, create and delete KVM snapshots:

To test how it works we can use pvesh - shell interface for PVE API

Nice! With all this knowledge all what's left is scripting requests to API. Since I'm trying to use Python for most backend stuff, after quick search I've found Proxmoxer that will take care of authentication and making requests. What's left is adding some basic logic and after a while I came up with this short script making snapshots of all VMs and CTs in my cluster:

import proxmoxer, datetime, time

pve = proxmoxer.ProxmoxAPI('10.7.17.11', user='snapshoter@pve', password='passw0rd', verify_ssl=False)

for vm in pve.cluster.resources.get(type='vm'):
    if vm['type'] == 'lxc':
        cur_vm = pve.nodes(vm['node']).lxc(vm['vmid'])
    else vm['type'] == 'qemu':
        cur_vm = pve.nodes(vm['node']).qemu(vm['vmid'])

    cur_vm.snapshot.post(snapname='auto_'+datetime.datetime.now().strftime("%Y%m%d%H"))

Now just to add task to cron that will execute this script every four hours and wait. This is what I saw after two days:

Now I just need a way to prune snapshots older than two days. To keep things simple I have created another script that is executed once a day during the night:

import proxmoxer, datetime, time

pve = proxmoxer.ProxmoxAPI('10.7.17.11', user='snapshoter@pve', password='passw0rd', verify_ssl=False)

for vm in pve.cluster.resources.get(type='vm'):
    if vm['type'] == 'lxc':
        cur_vm = pve.nodes(vm['node']).lxc(vm['vmid'])
    else vm['type'] == 'qemu':
        cur_vm = pve.nodes(vm['node']).qemu(vm['vmid'])

    for snap in cur_vm.snapshot.get():
        if snap['name'] != 'current' and snap['name'][:5] == 'auto_' and snap['name'] < 'auto_'+(datetime.datetime.now()-datetime.timedelta(days=2)).strftime("%Y%m%d%H"):
            cur_vm.snapshot(snap['name']).delete()
            time.sleep(10)