This is a simple Backblaze B2 backup module for Cockpit.
It uses Cockpit Starter Kit as a base
Create, edit, and delete B2 backup jobs via the Cockpit web UI
Save job definitions in /etc/cockpit-backblaze-b2/jobs.json
Run jobs manually or on a schedule using cron
No encryption: app key and ID are stored in plaintext in jobs.json.
(Server security is assumed. Restrict file permissions accordingly.)
Jobs created with this app is stored in /etc/cockpit-backblaze-b2/jobs.json and the format is:
(values below is completely random)
[
{
"jobName": "nightly-home",
"keyId": "0038d8ace473683wq268643",
"appKey": "K003KldOw14BUxPCZpqfdsaffdfasfdsffsff",
"bucket": "my-super-nas",
"folder": "/tank_hdd/shared"
}
]sudo mkdir /etc/cockpit-backblaze-b2
sudo touch /etc/cockpit-backblaze-b2/jobs.json
sudo chmod 600 /etc/cockpit-backblaze-b2/jobs.json
sudo chown root:root /etc/cockpit-backblaze-b2/jobs.jsonTo schedule automatic backups, add a cron entry that runs every minute:
* * * * * /usr/libexec/cockpit-backblaze-b2/runner.jsThe runner.js script should read jobs.json and execute each job as needed.
You may want to run specific jobs at certain times—use your preferred cron logic.
Example for running all jobs at 3:00 AM:
0 3 * * * /usr/libexec/cockpit-backblaze-b2/runner.jsRequire node.js
To install node.js run this:
sudo apt install nodejs npmrunner.js
#!/usr/bin/env node
const fs = require('fs');
const { spawnSync } = require('child_process');
const JOBS_FILE = '/etc/cockpit-backblaze-b2/jobs.json';
if (!fs.existsSync(JOBS_FILE)) {
console.error(`Jobs file not found: ${JOBS_FILE}`);
process.exit(1);
}
const jobs = JSON.parse(fs.readFileSync(JOBS_FILE, 'utf-8'));
for (const job of jobs) {
const { keyId, appKey, bucket, folder, jobName } = job;
console.log(`Running backup job: ${jobName}`);
const result = spawnSync(
'/usr/libexec/cockpit-backblaze-b2/sync.sh',
[keyId, appKey, bucket, folder],
{ stdio: 'inherit' }
);
if (result.error) {
console.error(`Job "${jobName}" failed:`, result.error);
} else {
console.log(`Job "${jobName}" completed.`);
}
}AppKey and KeyId are stored unencrypted. Restrict file permissions!
Only allow trusted users to access /etc/cockpit-backblaze-b2.
Clone this repository to your system:
git clone https://github.com/rabol/backblaze-b2.git
cd backblaze-b2sudo apt install gettext nodejs npm make pipx
pipx ensurepathsudo dnf install gettext nodejs npm make pipx
pipx ensurepathYou must restart your shell or run
source ~/.bashrcafter installingpipx.
This module depends on the official Backblaze B2 CLI.
Install it globally using pipx:
pipx install b2Verify it is available system-wide:
which b2
# Should return: /usr/local/bin/b2To build the Cockpit module:
makeTo install the module system-wide:
sudo make installThis will install the frontend assets to:
/usr/local/share/cockpit/backblaze-b2
And metadata to:
/usr/local/share/metainfo/org.cockpit_project.backblaze_b2.metainfo.xml
To remove a previously installed development version:
rm ~/.local/share/cockpit/backblaze-b2Copy the sync.sh script to a system location:
sudo mkdir -p /usr/libexec/cockpit-backblaze-b2
sudo cp sync.sh /usr/libexec/cockpit-backblaze-b2/sync.sh
sudo chmod +x /usr/libexec/cockpit-backblaze-b2/sync.shEnsure it’s executable and accessible by the Cockpit backend. NOTE: the app only pick up lines that starts with "ERROR:" or "SUCCESS:"
#!/bin/bash
set -euo pipefail
KEY_ID=$1
APP_KEY=$2
BUCKET=$3
FOLDER=$4
# Authorize account using updated syntax, suppress output
if ! b2 account authorize "$KEY_ID" "$APP_KEY" >/dev/null 2>&1; then
echo "ERROR: Failed to authorize with Backblaze B2. Check your Key ID and App Key."
exit 1
fi
# Sync folder using correct --skip-newer flag, suppress output
if ! b2 sync --delete --skip-newer "$FOLDER" "b2://$BUCKET/$(hostname)" >/dev/null 2>&1; then
echo "ERROR: Sync failed. Check folder path, bucket name, and B2 credentials."
exit 1
fi
echo "SUCCESS: Backup completed successfully."