Skip to content

Plugins

Marc Pope edited this page May 9, 2026 · 2 revisions

Plugins

BBS plugins extend backup functionality by adding pre-backup actions, post-backup actions, and specialized backup capabilities. Plugins allow you to customize the backup workflow for each client's specific needs.

Plugin System Overview

The BBS plugin architecture consists of:

  • Plugin Types: Built-in plugins provided by BBS (MySQL, PostgreSQL, Shell Hook, S3 Sync)
  • Plugin Configurations: Named, reusable configurations for each plugin type
  • Backup Plan Association: Plugins are attached to backup plans, not directly to clients
  • Per-Client Enablement: Each plugin must be enabled on a per-client basis before use

How Plugins Work

When a backup job runs:

  1. BBS checks which plugins are attached to the backup plan
  2. The agent receives plugin instructions along with the backup job
  3. Pre-backup plugins execute first (e.g., database dumps, custom scripts)
  4. Borg creates the backup archive
  5. Post-backup plugins execute (e.g., notifications, cleanup scripts)
  6. Post-prune plugins execute after pruning completes (e.g., S3 sync)

Available Plugins

1. MySQL Backup (mysql_dump)

Purpose: Automatically dump MySQL databases before backup

Use Cases:

  • WordPress, Joomla, Drupal site backups
  • Production database backups
  • E-commerce platforms (WooCommerce, Magento)
  • Custom application databases

How It Works:

  • Executes mysqldump before Borg runs
  • Creates .sql files in a specified dump directory
  • Borg includes the dump files in the backup archive
  • Enables one-click MySQL restoration from the BBS web interface

Configuration Parameters:

  • Database host and port
  • Username and password
  • Database names (comma-separated or "all")
  • Dump directory path

See Database-Backups for detailed MySQL backup documentation.


2. PostgreSQL Backup (pg_dump)

Purpose: Automatically dump PostgreSQL databases before backup

Use Cases:

  • Django application databases
  • Rails application databases
  • Data warehouses and analytics platforms
  • Custom PostgreSQL applications

How It Works:

  • Executes pg_dump before Borg runs
  • Creates .dump files in custom format (compressed)
  • Borg includes the dump files in the backup archive
  • Enables one-click PostgreSQL restoration from the BBS web interface

Configuration Parameters:

  • Database host and port
  • Username and password
  • Database names (comma-separated or "all")
  • Dump directory path

See Database-Backups for detailed PostgreSQL backup documentation.


3. Shell Script Hook (shell_hook)

Purpose: Run custom shell scripts before and/or after backups

Use Cases:

  • Stop/start applications for consistent backups
  • Export application state or logs
  • Notify external monitoring systems
  • Custom cleanup or preparation tasks
  • Trigger webhooks or API calls
  • Stream large database dumps directly into a borg archive without using local disk (requires opt-in credential exposure — see below)

How It Works:

  • Pre-backup script: Runs before borg create. If it exits non-zero and "Abort backup if pre-script fails" is enabled, the backup itself is skipped.
  • Post-backup script: Runs after backup completes — always, regardless of whether the backup succeeded, failed, or was warned. (This way services stopped by a pre-script always get restarted.)
  • Scripts run as the agent's user on the client machine. The script path must be absolute, the file must exist on the client, and it must be executable.
  • Environment variables provide backup context.

Configuration Parameters:

Parameter Description Default Example
Pre-Backup Script Path Absolute path; arguments are supported (/path/script.sh before). Empty = skip. (none) /opt/scripts/pre-backup.sh
Post-Backup Script Path Absolute path; arguments supported. Empty = skip. (none) /opt/scripts/post-backup.sh
Abort backup if pre-script fails If checked, the backup is cancelled when the pre-script exits non-zero. enabled
Script Timeout (seconds) Maximum time each script is allowed to run before being killed. 300 600
Expose repository credentials to script (advanced) When enabled, the agent exports BORG_PASSCOMMAND and BORG_REPO so the script can run borg directly. Off by default — see security notes below. disabled

Environment Variables Available to Scripts:

Variable When Description
BBS_ARCHIVE_NAME pre + post Archive name being created, e.g. plan42-2026-05-08_14-23-01
BBS_REPO_PATH pre + post Full repo URL, e.g. ssh://user@host/./repo or /var/bbs/repos/...
BBS_BACKUP_PLAN pre + post Plan name from BBS
BBS_CLIENT_NAME pre + post Client/agent name from BBS
BBS_DIRECTORIES pre + post Newline-separated list of source paths the backup includes
BBS_JOB_ID pre + post Numeric BBS job id, useful for cross-referencing the BBS log
BBS_BACKUP_STATUS pre = pending, post = completed / failed / warning The backup outcome (only meaningful in the post-script)
BORG_PASSCOMMAND pre + post (only when Expose repository credentials is enabled) cat /tmp/bbs-pp-XXXXXX — borg auto-uses this; the temp file is mode 0600 and removed when the script exits
BORG_REPO pre + post (only when Expose repository credentials is enabled) Same value as BBS_REPO_PATH; allows borg create ::archive without the explicit repo arg

Example Pre-backup Script — quiesce services for a consistent backup:

#!/usr/bin/env bash
set -euo pipefail
# Stop Nginx to ensure consistent filesystem state
systemctl stop nginx

# Flush Redis to disk
redis-cli save

# Export application state
/opt/app/bin/export-state.sh

Example Post-backup Script — restart services and send a webhook:

#!/usr/bin/env bash
# Always restart services regardless of backup outcome
systemctl start nginx

# Send notification with the actual outcome
case "$BBS_BACKUP_STATUS" in
    completed)
        curl -fsS -X POST https://monitoring.example.com/webhook \
            -d "status=ok&archive=$BBS_ARCHIVE_NAME&plan=$BBS_BACKUP_PLAN"
        ;;
    warning)
        curl -fsS -X POST https://monitoring.example.com/webhook \
            -d "status=warning&archive=$BBS_ARCHIVE_NAME&plan=$BBS_BACKUP_PLAN"
        ;;
    failed)
        curl -fsS -X POST https://monitoring.example.com/webhook \
            -d "status=failed&client=$BBS_CLIENT_NAME&plan=$BBS_BACKUP_PLAN"
        ;;
esac

Example: streaming a large database into the archive without local disk staging

This is the use case the credential-exposure opt-in is designed for. A multi-TB database can't be dumped to local disk first, but borg create --content-from-command reads stdout from a command and stores it as an archive entry, so the dump streams directly into deduplicated borg storage.

Enable Expose repository credentials to script on this plugin config, then:

#!/usr/bin/env bash
# /home/bbs/hooks/streaming-pg-dump.sh
set -euo pipefail

# BORG_PASSCOMMAND and BORG_REPO are set by BBS when expose_passphrase is on.
# pg_dump streams directly into the archive — no temp file on disk.
borg create \
    --content-from-command \
    "::${BBS_ARCHIVE_NAME}-pgdump" \
    -- pg_dump --format=custom big_database

⚠️ Security note on credential exposure. Even with the more secure BORG_PASSCOMMAND-via-tempfile pattern (instead of putting BORG_PASSPHRASE in the env), a malicious or buggy script can still leak credentials — for example by running env > /tmp/log, by piping data through external services that echo their environment in error paths, or by cat-ing the temp file itself to a remote endpoint. Only enable this option for scripts you control and have reviewed. The temp file is created mode 0600 and deleted as soon as the script exits, but during execution it is readable by the script and any subprocess the script explicitly opens it from.

Creating a Shell Hook Configuration

  1. Navigate to client detail → Plugins tab
  2. Enable Shell Script Hook plugin
  3. Click Add Configuration
  4. Fill in the configuration:
    • Configuration name (the label this config is referenced by in plans)
    • Pre-Backup Script Path (optional)
    • Post-Backup Script Path (optional)
    • Abort backup if pre-script fails (checkbox)
    • Script Timeout (default 300 seconds)
    • Expose repository credentials to script (advanced; off by default)
  5. Click Save

Screenshot: Shell Hook plugin configuration form

Important Notes for Shell Hooks

  • Scripts must be executable (chmod +x script.sh)
  • Scripts run as the agent user (typically bbs-agent)
  • Scripts must exist on the client machine, not the BBS server
  • Non-zero exit codes from pre-backup scripts will abort the backup if "Abort backup if pre-script fails" is enabled (it is, by default)
  • Post-backup scripts always run, regardless of whether the backup succeeded — BBS_BACKUP_STATUS tells you the outcome
  • Use absolute paths for reliability
  • Test scripts manually before attaching to production backups
  • Available since AGENT_VERSION 2.29.13: BBS_* context vars are injected, expose_passphrase opt-in enables BORG_PASSCOMMAND for the script. Older agents only inherit the agent's plain environment.

4. S3 Offsite Sync (s3_sync)

Purpose: Mirror Borg repositories to S3-compatible storage for offsite disaster recovery

Use Cases:

  • Offsite backup copies for disaster recovery
  • Geographic redundancy
  • Long-term archival in cloud storage
  • Compliance requirements for offsite backups

How It Works:

  • Uses rclone to mirror the Borg repository to S3
  • Automatically runs after successful prune operations
  • Incremental sync (only changed files are transferred)
  • Supports bandwidth limiting

Supported Storage Providers:

  • AWS S3
  • Wasabi
  • Backblaze B2
  • DigitalOcean Spaces
  • MinIO
  • Any S3-compatible object storage

Configuration Methods:

  1. Global S3 Settings (Settings → Offsite Storage): One set of credentials for all clients
  2. Named S3 Plugin Config: Per-client S3 credentials and buckets
  3. Inline Per-Plan Config: Unique S3 settings per backup plan

See S3-Offsite-Sync for detailed S3 sync documentation.


Enabling Plugins

Plugins must be enabled on a per-client basis before they can be used:

  1. Navigate to the client detail page
  2. Click the Plugins tab
  3. Toggle the desired plugins to Enabled
  4. Only enabled plugins can have configurations created

Screenshot: Plugins tab showing plugin enable/disable toggles

Named Configurations

Named configurations are reusable plugin settings that can be shared across multiple backup plans for the same client.

Benefits of Named Configurations

  • Reusability: Create once, use in multiple backup plans
  • Consistency: Same database credentials across all plans
  • Maintenance: Update one config to affect all plans using it
  • Organization: Descriptive names like "Production MySQL" or "Staging DB"

Creating a Named Configuration

  1. Client detail → Plugins tab
  2. Find the plugin you want to configure (must be enabled)
  3. Click Add Configuration
  4. Fill in the configuration form
  5. Give it a descriptive name
  6. Save

Screenshot: Plugin configuration list showing multiple named configs

Editing and Deleting Configurations

  • Edit: Click the edit icon next to a configuration
  • Delete: Click the delete icon (only if not attached to any backup plans)
  • In-Use Indicator: Configurations attached to plans show which plans use them

Configuration Sharing

  • Configurations are per-client (not global)
  • The same configuration can be used by multiple backup plans for the same client
  • Configurations cannot be shared across different clients
  • To use the same settings on multiple clients, create separate configurations for each

Attaching Plugins to Backup Plans

Plugins are activated by attaching their configurations to backup plans:

  1. Navigate to client detail → Backup Plans tab
  2. Create a new plan or edit an existing one
  3. Scroll to the Plugins section
  4. Select plugin configurations from the dropdowns:
    • MySQL Backup: Choose a MySQL config (if enabled)
    • PostgreSQL Backup: Choose a PostgreSQL config (if enabled)
    • Shell Hook: Choose a shell hook config (if enabled)
    • S3 Sync: Choose an S3 config (if enabled)
  5. Save the backup plan

Screenshot: Backup plan editor showing plugin configuration dropdowns

Multiple Plugins on One Plan

A single backup plan can use multiple plugins simultaneously:

  • Example: MySQL dump + Shell hook (to stop/start app) + S3 sync (for offsite copy)
  • Plugins execute in order: Pre-backup hooks → Database dumps → Backup → Post-backup hooks → S3 sync

Plugin Execution Order

  1. Pre-backup phase:
    • Shell hook pre-backup script
    • MySQL dump
    • PostgreSQL dump
  2. Backup phase:
    • borg create runs
  3. Post-backup phase:
    • Shell hook post-backup script
  4. Post-prune phase (after prune jobs only):
    • S3 sync

Testing Plugin Configurations

Before running a production backup, test your plugin configurations:

  1. On the Plugins tab, find your configuration
  2. Click the Test button
  3. BBS queues a plugin_test job
  4. Monitor the test in QueueJob Detail
  5. Review results:
    • Success: Plugin executed correctly
    • Failure: Check error log for issues

Screenshot: Plugin configuration card with Test button

What Testing Does

  • MySQL/PostgreSQL: Connects to database, performs a test dump, verifies dump files created
  • Shell Hook: Executes the scripts in a test environment, captures output and exit codes
  • S3 Sync: Tests S3 credentials, attempts to create a test file in the bucket

Common Test Failures

Plugin Error Solution
MySQL Connection refused Check host/port, verify MySQL is running
MySQL Access denied Verify username/password, check user privileges
PostgreSQL authentication failed Check credentials, review pg_hba.conf
Shell Hook Script not found Verify path is absolute and file exists on client
Shell Hook Permission denied Make script executable, check file permissions
S3 Sync Invalid credentials Verify access key and secret key
S3 Sync Bucket not found Check bucket name, ensure it exists

Plugin Job Types

Plugins create jobs that appear in the Queue:

Job Type Description When It Runs
backup Regular backup with plugin pre/post actions Scheduled or manual
plugin_test Test a plugin configuration Manual test button
restore_mysql Restore MySQL databases from archive Manual restore
restore_pg Restore PostgreSQL databases from archive Manual restore
s3_sync Sync repository to S3 After successful prune

Plugin Security

Credential Storage

  • All plugin credentials (database passwords, S3 keys) are encrypted using BBS's APP_KEY
  • Credentials are never logged or displayed in plain text
  • Agents receive decrypted credentials over HTTPS only when needed for job execution

Access Control

  • Only client owners (or admins) can view/edit plugin configurations
  • Regular users cannot see other users' client plugins
  • API keys authenticate agent-to-server communication

Script Execution Security (Shell Hooks)

  • Scripts run as the agent user (limited privileges) on the client machine
  • Scripts cannot access BBS server resources
  • Validate script sources before deployment — anyone able to edit the plugin config can run arbitrary code on the client
  • Credential exposure (expose_passphrase checkbox) is off by default. When enabled, the agent writes the borg passphrase to a mode-0600 temp file and exports BORG_PASSCOMMAND=cat <tempfile> to the script. The temp file is deleted as soon as the script exits. We use BORG_PASSCOMMAND rather than BORG_PASSPHRASE because env vars are inherited by every subprocess the script spawns — BORG_PASSCOMMAND is only consulted when something explicitly shells out to read it (which is borg itself by design), so the leak surface is much smaller. Even so, only enable this for scripts you control and have reviewed.

Best Practices

General Plugin Usage

  • Test First: Always test plugin configurations before production use
  • Name Clearly: Use descriptive names like "Production MySQL" not "Config 1"
  • Monitor Jobs: Check Queue regularly to ensure plugins execute successfully
  • Update Credentials: Rotate database passwords periodically, update configs accordingly

Performance Considerations

  • Database Dumps: Large databases increase pre-backup time. Monitor dump duration.
  • Shell Scripts: Keep scripts fast. Long-running scripts delay backups.
  • S3 Sync: Bandwidth limiting prevents saturating network connections
  • Concurrent Jobs: Multiple plugins on one plan execute sequentially, not in parallel

Maintenance

  • Remove Unused Configs: Delete configurations no longer attached to plans
  • Review Logs: Check job detail logs for plugin warnings or errors
  • Update Scripts: Keep shell hook scripts in version control
  • Document Configs: Add comments or notes in configuration names

Troubleshooting

Plugin Won't Enable

  • Cause: Missing dependencies on client (e.g., pg_dump not installed)
  • Solution: Install required software on client machine, restart agent

Configuration Test Fails

  • Cause: Incorrect credentials, unreachable services, missing directories
  • Solution: Verify all configuration parameters, check network connectivity, review error logs

Plugin Doesn't Execute During Backup

  • Cause: Configuration not attached to backup plan
  • Solution: Edit backup plan, select the plugin configuration in the Plugins section

Shell Hook Script Fails

  • Cause: Script syntax error, missing executable permission, incorrect path
  • Solution: Test script manually on client (bash /path/to/script.sh), check permissions (ls -l)

S3 Sync Slow or Failing

  • Cause: Bandwidth limits too restrictive, network issues, bucket permissions
  • Solution: Adjust bandwidth limit, verify S3 credentials, check bucket policies

Related Documentation

Clone this wiki locally