Skip to content

Scheduling

Csaba Polyak edited this page Sep 28, 2026 · 1 revision

Scheduling

GitHub Mirror Backup is designed to run unattended.

Once the first manual backup has been completed successfully, the script can be scheduled using either:

  • Linux cron
  • Synology DSM Task Scheduler

The recommended interval depends on how frequently the repositories change.

For most personal and small-business repositories, once per day is a reasonable starting point.


Synology DSM Task Scheduler

Synology DSM provides a built-in Task Scheduler that can run shell scripts automatically.

1. Open Task Scheduler

In DSM:

Control Panel
    ↓
Task Scheduler
    ↓
Create
    ↓
Scheduled Task
    ↓
User-defined script

Give the task a descriptive name, for example:

GitHub Mirror Backup

2. Select the user

Run the task as the same user that was used to configure the backup.

This is important because the user needs access to:

  • ~/.config/github/token
  • ~/.ssh/
  • the backup directory
  • the GitHub SSH key

If the task runs as another user, $HOME will be different and the token and SSH configuration may not be available.

3. Configure the schedule

Open the Schedule section.

Example daily schedule:

Frequency: Daily
Time: 03:00

A backup can also be run more frequently if required.

Examples:

Every day       → 03:00
Every 12 hours  → 03:00 / 15:00
Every 6 hours   → 00:00 / 06:00 / 12:00 / 18:00

The appropriate interval depends on how much repository activity you need to capture.

4. Configure the task command

In the Task Settings section, use the full path to the script.

For example:

/volume1/scripts/github-mirror-backup/github-backup.sh

If necessary, explicitly invoke Bash:

/bin/bash /volume1/scripts/github-mirror-backup/github-backup.sh

Using absolute paths is recommended for scheduled tasks.

5. Save and test

After creating the task, use Run in Task Scheduler to execute it immediately.

Check the task output and the backup log.

The script should perform:

SYSTEM CHECK
GITHUB API
GITHUB SSH
REPOSITORY DISCOVERY
MIRRORING
SUMMARY

Do not rely solely on the Task Scheduler status. The script's own log contains the repository-level results.


Important: $HOME and scheduled tasks

The script uses:

TOKEN_FILE="$HOME/.config/github/token"

Therefore the account running the scheduled task matters.

For example:

Interactive shell:
    /var/services/homes/csiber

Task Scheduler:
    /var/services/homes/backup

The second task would look for the token under the backup user's home directory.

If the token is not there, the backup will fail before repository discovery.

Always verify the task's execution user.


Recommended Synology setup

A clean Synology installation could look like:

/volume1/
├── Archivum/
│   ├── project-a.git/
│   ├── project-b.git/
│   └── _logs/
│
└── scripts/
    └── github-mirror-backup/
        └── github-backup.sh

The backup data and script are kept separately.

The token remains in the user's home directory:

~/.config/github/token

The SSH key remains under:

~/.ssh/

Cron

On a standard Linux system, the same script can be scheduled with cron.

Edit the user's crontab:

crontab -e

For a daily 03:00 backup:

0 3 * * * /path/to/github-backup.sh

Make sure the script is executable:

chmod +x /path/to/github-backup.sh

Using the user's own crontab is preferable because the script then runs with the same $HOME, SSH keys and token configuration.


Cron with explicit Bash

If the script's executable bit is not being used:

0 3 * * * /bin/bash /path/to/github-backup.sh

This can also make the execution environment more obvious.


Redirecting cron output

The script already creates its own log files, so additional output redirection is usually unnecessary.

If you still want cron's own output captured:

0 3 * * * /bin/bash /path/to/github-backup.sh >> /path/to/cron-github-backup.log 2>&1

However, this creates a second log stream.

The script's _logs/ directory should normally be treated as the primary log source.


Running more than once per day

For repositories that change frequently, the backup can run several times per day.

Example every 6 hours:

0 */6 * * * /bin/bash /path/to/github-backup.sh

Example every 12 hours:

0 */12 * * * /bin/bash /path/to/github-backup.sh

The mirror update is incremental, so later runs normally transfer only changes.


Preventing overlapping runs

The script has its own lock:

LOCK_DIR="/tmp/github-backup.lock"

If another backup is already running, a second instance exits rather than modifying the same mirrors simultaneously.

This is particularly useful when the initial backup takes a long time.

For example:

03:00  → backup starts
04:15  → still running

04:00  → another scheduled run starts
         ↓
         lock detected
         ↓
         second run exits

The first backup continues normally.


First run vs. scheduled runs

The first execution can be substantially heavier than normal scheduled runs.

First run

125 repositories
       ↓
125 mirror operations
       ↓
Large amount of network + disk activity

Later runs

125 existing mirrors
       ↓
Fetch changes
       ↓
Only changed Git objects are transferred

Do not schedule the first full backup at the same time as other heavy NAS jobs if the system has limited resources.

After the initial mirror has completed, daily execution should normally be much lighter.


Checking scheduled backups

The most useful indicator is the latest log:

ls -1t /volume1/Archivum/_logs/github-backup-*.log | head -1

Check the end of the latest log:

tail -n 30 "$(ls -1t /volume1/Archivum/_logs/github-backup-*.log | head -1)"

A successful run ends with:

✓ COMPLETED SUCCESSFULLY

A run with repository-level errors ends with:

✗ COMPLETED WITH X ERROR(S)

The script also returns:

0 = success
1 = repository errors
2 = fatal error

This makes it possible for external monitoring to detect failed backups.


Recommended schedule

For a typical personal GitHub account:

03:00 every day

is sufficient for a simple offline/local mirror.

For an active development environment:

Every 6–12 hours

may be more appropriate.

The backup frequency determines how much GitHub-side history could be lost between successful backup runs if the remote repository becomes unavailable.


Scheduling checklist

Before enabling an unattended schedule:

  • First manual backup completed successfully
  • Correct DSM/Linux user selected
  • Token is accessible to that user
  • SSH authentication works for that user
  • Backup directory is writable
  • Script uses an absolute path
  • Logs are being created
  • A manual scheduled-task test succeeds
  • No overlapping backup jobs are configured

Once these checks pass, the backup can run unattended.