Hook scripts
A hook is your own script, run by Nyx Backup at a point in the backup run. Typical uses: quiesce a database or stop a service so its files are consistent before the backup reads them, kick off something downstream afterwards, or send a failure alert somewhere the desktop notification cannot reach.
Each backup set can use three hooks, and all three are optional:
| Hook | When it runs | If it exits non-zero |
|---|---|---|
| Pre-backup | Before the run starts | The run is aborted |
| Post-backup | After a successful run, once the manifest is written | Logged as a warning; the run still counts as successful |
| Failure | After a run fails, including a run a pre-hook aborted | Logged as a warning; it cannot re-fail an already-failed run |
The pre-backup hook is the one with teeth. If your script cannot put the system into a safe state, exit non-zero and no backup is taken, rather than one that captures a half-written database.
Where scripts live
Hooks are chosen by filename from an administrator-controlled directory - not typed in as a command line:
| Platform | Directory |
|---|---|
| Windows | C:\ProgramData\NyxBackup\hooks\ |
| Linux | /etc/nyxbackup/hooks/ |
| macOS | /Library/Application Support/NyxBackup/hooks/ |
A backup set stores only the name of a script in that directory, and the service refuses anything that does not resolve inside it.
This is deliberate, and it is the security boundary of the feature. The backup service runs with full privileges - as SYSTEM on Windows, as root on Linux and macOS - so a hook runs with those privileges too. If any user could point a backup set at any executable, configuring a backup would be a way to run arbitrary code as SYSTEM. Instead the directory is writable only by Administrators (Windows) or root (Unix), so placing a script there is already an administrative act.
On Windows the directory is created with an explicit access list rather than
inheriting from ProgramData, whose defaults would otherwise let a standard
user drop files in.
What people use them for
Before a backup: make the data safe to copy
The main use, and the reason pre-backup hooks can abort a run.
A live database cannot be backed up by copying its files. The data files are being written while you read them, so a file-level copy is crash-consistent at best and frequently will not restore at all. The fix is to export a clean copy first, into a folder your backup set includes, and let the backup capture that:
- Dump a database.
mysqldump --single-transactionand equivalents take a consistent read view without locking the database, producing an export that restores anywhere. - Quiesce an application. Stop a service, flush its state, or put it into a maintenance mode for the duration of the run.
- Export from something with no files at all - a device, an API, an appliance - into the backup source.
Two things to set up alongside the hook: add the dump directory to the set’s included paths, and exclude the live data directory, or you will back up both the good export and the unusable raw files.
If the export fails, exit non-zero. The run is aborted, and you get a failed backup you can see rather than a successful one containing a database that will not restore.
After a backup: tell someone, or tidy up
Post-backup hooks run once the manifest is written, so the snapshot exists and
NYX_SNAPSHOT_ID identifies it:
- Send a notification somewhere the desktop cannot reach - email, SMS, or a
chat webhook. Wire the same script as both the post and failure hook and let
it branch on
NYX_STATUS; that is how the examples are written. - Clean up the dump the pre-hook created, so it is not left on disk.
- Trigger something downstream - kick off a second job, update a dashboard, record the snapshot id.
A non-zero exit from a post hook is logged and does not fail the run, which is usually what you want: a failed notification should not turn a good backup into a bad one.
Examples to start from
The service seeds an examples subdirectory on first run with working,
commented scripts. Copy one up a level into the hooks directory, edit the
settings at the top, and select it by name in the backup set.
| Example | Phase | What it does |
|---|---|---|
mysqldump | Pre | Consistent MySQL / MariaDB dump |
pg_dump | Pre | PostgreSQL dump |
mongodump | Pre | MongoDB dump |
sqlite-backup | Pre | SQLite online backup (Linux, macOS) |
mssql-export | Pre | SQL Server export (Windows) |
quiesce-app | Pre | Stop or pause a service around the run (Linux, macOS) |
notify-email | Post + failure | Email via an HTTP API, no local mail server |
notify-sms | Post + failure | SMS |
notify-webhook | Post + failure | POST to a chat or automation webhook |
Shell scripts ship for Linux and macOS, PowerShell for Windows. Each carries install instructions and an explanation of why it is written the way it is.
Nothing in examples is live: a script is only offered as a hook once you move
it up into the hooks directory itself, which requires administrator rights.
Environment variables
Your script is told which set it is running for, and what happened, through environment variables. Three are set for every hook:
| Variable | Value |
|---|---|
NYX_SET_NAME | The backup set’s name, as shown in the app |
NYX_SET_ID | The set’s stable identifier (a UUID) - use this rather than the name if your script keys off a particular set, since names can be edited |
NYX_PHASE | pre, post, or failure - so one script can serve all three roles |
The post-backup hook additionally receives the outcome:
| Variable | Value |
|---|---|
NYX_STATUS | success |
NYX_SNAPSHOT_ID | Identifier of the snapshot just written |
NYX_FILES | Number of files uploaded in this run |
NYX_BYTES | Bytes uploaded in this run |
The failure hook receives what went wrong instead:
| Variable | Value |
|---|---|
NYX_STATUS | failure |
NYX_ERROR | The error text, suitable for putting in an alert |
NYX_ERROR_CODE | A stable category such as storage_missing_object - test this rather than matching on the message, which is written for humans and may change |
The pre-backup hook gets only the three common variables. There is no snapshot or outcome yet - that is the point of running before.
Note that NYX_FILES and NYX_BYTES count what was uploaded, not what was
examined. An incremental run where nothing changed reports zero for both and is
still a success.
Output
Anything your script writes to stdout or stderr is copied into the service log, tagged with the hook phase. That is the simplest way to see what a hook actually did, without turning on debug logging.
If the script is missing
A hook naming a script that is not in the directory is skipped with a warning - not treated as a failure. A renamed or deleted script therefore does not start breaking backups; it stops doing whatever it was doing, and says so in the log.
Timeout
Every hook is subject to a timeout, 300 seconds by default, so a script that hangs cannot stall backups indefinitely. It is configurable per set.
Current limits
Pre- and post-backup hooks are configurable in the app. The failure hook is set
in config.toml; it is not yet exposed in the interface.