#!/usr/bin/nu # slug pattern: # {thing}-{location}-{kopia|zfs} # TODO: # add the rest of the jobs # run-all command # create checks implementation to use management API to create each one let config = source ~/.config/leonard-brechtel/backups.nuon let secrets = $config.secrets let jobs = $config.jobs def backup [job] { if $job.type == "kopia" { kopiaBackup $job } else if $job.type == "zfs" { zfsBackup $job } else { print $"Invalid job type: " + $job.type } } def zfsBackup [job] { pingStartJob $job.statusSlug try { let output = syncoid --no-sync-snap --create-bookmark --no-privilege-elevation --recursive ($job.source) ($job.target) | complete logJob { slug: $job.statusSlug, output: $output, success: true } pingFinishedJob $job.statusSlug } catch { |err| logJob { slug: $job.statusSlug, output: $err, success: false } pingFailedJob $job.statusSlug $err.debug } } def kopiaBackup [job] { #using sudo is annoying but since this is backing up docker containers #the permissions are often wrong. I should be using podman + rootless pingStartJob $job.statusSlug try { let output = sudo kopia --config-file=($job.target) snapshot create ($job.source) | complete logJob { slug: $job.statusSlug, output: $output, success: true } pingFinishedJob $job.statusSlug } catch { |err| logJob { slug: $job.statusSlug, output: $err, success: false } pingFailedJob $job.statusSlug $err.debug } } def pingStartJob [slug] { print $"starting job: ($slug)" print $"($secrets.hcURL)/ping/($secrets.hcPingKey)/($slug)/start" curl -s $"($secrets.hcURL)/ping/($secrets.hcPingKey)/($slug)/start" | save -f /dev/null } def pingFailedJob [slug, err] { print $"failed to run job: ($slug) with error: ($err)" curl -s $"($secrets.hcURL)/ping/($secrets.hcPingKey)/($slug)/fail" | save -f /dev/null } def pingFinishedJob [slug] { print $"finished job: ($slug)" curl -s $"($secrets.hcURL)/ping/($secrets.hcPingKey)/($slug)" | save -f /dev/null } def logJob [details] { http post -u $secrets.observeUser -p $secrets.observePassword $"($secrets.observeURL)/api/default/backups/_json" ($details | to json) } def createJob [job] { let jobDetails = { name: $job.statusSlug, slug: $job.statusSlug, timeout: 86400 } http post --full --headers {"X-API-Key": $secrets.hcAPIKey } --content-type "application/json" $"($secrets.hcURL)/api/v3/checks/" ($jobDetails | to json) } def "main log" [msg] { logJob { slug: "testing", data: $msg } } def "main list" [] { print "Known jobs:" print $"($jobs | get statusSlug | to text)" } def "main create-missing" [] { let existingSlugs = (curl -H $"X-API-Key: ($secrets.hcAPIKey)" $"($secrets.hcURL)/api/v3/checks/" | from json | get checks.slug | to nuon) let missingJobs = $jobs | filter { |job| not ($job.statusSlug in $existingSlugs) } $missingJobs | each { createJob $in } } def "main run-all" [] { $jobs | each { backup $in } } def main [statusSlug] { let matches = $jobs | where statusSlug == $statusSlug if ($matches | length) == 1 { backup ($matches | first) } else { print $"Did not find exactly one match for ($statusSlug)" exit 1 } } #sudo kopia --config-file=/home/jbrechtel/kopia/leonard-brechtel-backup/repository.config snapshot create /nas1/photos.roo.lol #sudo kopia --config-file=/home/jbrechtel/kopia/leonard-brechtel-backup/repository.config snapshot create /services/photos.roo.lol #sudo kopia --config-file=/home/jbrechtel/kopia/leonard-brechtel-backup/repository.config snapshot create /nas/files #sudo kopia --config-file=/home/jbrechtel/kopia/leonard-brechtel-backup/repository.config snapshot create /services/passwords.roo.lol #sudo kopia --config-file=/home/jbrechtel/kopia/leonard-brechtel-backup/repository.config snapshot create /services/paperless.roo.lol #sudo kopia --config-file=/home/jbrechtel/kopia/leonard-brechtel-backup/repository.config snapshot create /services/caddy #sudo kopia --config-file=/home/jbrechtel/kopia/leonard-brechtel-backup/repository.config snapshot create /services/kitchen.roo.lol #sudo kopia --config-file=/home/jbrechtel/kopia/leonard-brechtel-backup/repository.config snapshot create /services/ha.roo.lol/config/backups