incback
v1.0.2
Published
Node.js CLI tool & Lib for incremental backups using rsync with hard-linking
Maintainers
Readme
incback
A space-efficient incremental backup tool using rsync with hard-link support. Supports both local and remote (SSH) backup scenarios.
Features
- Incremental backups - Only changed files are copied; unchanged files are hard-linked to previous backups, saving disk space
- Timestamped snapshots - Each backup is stored in a separate directory with ISO 8601 timestamp
- Remote support - Backup to/from remote servers via SSH
- Flexible configuration - Configure via CLI arguments or JSON file
- Space efficient - Uses rsync's
--link-destfeature for hard-linking unchanged files - Exclude patterns - Skip files and directories using exclude pattern files
- Logging - Write backup logs to file with timestamps for auditing
- Customizable prefixes - Set custom directory name prefixes for backups
- Docker support - Run in containers for isolated and reproducible backups
Installation
npm install -g incbackQuick Install (Linux & macOS)
You can install the standalone binary directly using curl:
curl -o- https://raw.githubusercontent.com/smelzo/incback/main/install.sh | sudo bashOr run locally:
git clone https://github.com/yourusername/incback.git
cd incback
npm install
npm run buildStandalone Binaries
After running the build scripts, standalone binaries (which do not require Node.js installed) are available in the dist/ directory:
- macOS (Apple Silicon):
dist/mac/arm64/incback(Generate withnpm run build:mac) - Linux (x64):
dist/linux/x64/incback(Generate withnpm run build:linux)
Usage
Configuration File (Recommended)
Create a .incback file in your project directory:
{
"src": "/path/to/source",
"dest": "/path/to/backup",
"excludeFrom": "./exclude-patterns.txt",
"logFile": "./backup.log",
"backupPrefix": "BACKUP-"
}Then run:
incbackCommand Line Arguments
incback -s /path/to/source -d /path/to/backupRemote Backups
Backup from remote source to local destination:
{
"src": "/var/www/html",
"dest": "/home/user/backups",
"remoteRole": "src",
"remoteUser": "root",
"remoteHost": "example.com"
}Backup from local source to remote destination:
{
"src": "/home/user/documents",
"dest": "/backups/documents",
"remoteRole": "dest",
"remoteUser": "backup",
"remoteHost": "backup-server.com"
}Custom Configuration File Path
incback -c /path/to/custom-config.jsonCommand Line Options
| Option | Alias | Description |
|--------|-------|-------------|
| --config <path> | -c | Path to JSON configuration file |
| --src <path> | -s | Source directory path |
| --dest <path> | -d | Destination directory path |
| --remote-role <role> | -R | Which path is remote: src or dest |
| --remote-user <user> | -U | SSH username for remote connection |
| --remote-host <host> | -H | SSH hostname or IP address |
| --exclude-from <file> | -e | Path to file containing exclude patterns (one per line) |
| --log-file <file> | -l | Path to log file for backup operations |
| --backup-prefix <prefix> | -p | Custom prefix for backup directories (default: BACKUP-) |
| --rsync-options <options> | -o | Rsync flags to use for the backup. only flags admitted by incback are "a" "z" and "c" (default: az) |
How It Works
incback creates timestamped backup directories using the format {prefix}{timestamp} (default prefix: BACKUP-):
/backup/destination/
├── BACKUP-2025-11-23T080000/
├── BACKUP-2025-11-23T120000/
└── BACKUP-2025-11-23T160000/Initial Backup
The first backup creates a complete copy of the source directory.
Incremental Backups
Subsequent backups use rsync's --link-dest option to:
- Copy only files that have changed
- Hard-link unchanged files to the previous backup
This means each backup appears as a complete snapshot, but unchanged files don't consume additional disk space.
Example
# Initial backup: 1GB
BACKUP-2025-11-23T080000/ # 1GB disk usage
# Incremental backup: 100MB of changes
BACKUP-2025-11-23T120000/ # Only 100MB additional disk usage
# But appears as complete 1.1GB snapshot
# Another incremental: 50MB of changes
BACKUP-2025-11-23T160000/ # Only 50MB additional disk usage
# But appears as complete 1.15GB snapshotTotal disk usage: ~1.15GB instead of 3.25GB for three full backups.
Requirements
- Node.js 18+ (uses ES modules)
- rsync installed on your system
- SSH access (for remote backups)
- SSH key-based authentication configured (password authentication not supported)
SSH Configuration
For remote backups, ensure:
SSH key-based authentication is set up:
ssh-copy-id user@remote-hostTest SSH connection:
ssh user@remote-hostThe tool uses these SSH options:
BatchMode=yes- No password promptsConnectTimeout=5- 5-second connection timeout
Use Cases
Local Backups
# Backup your documents folder
incback -s ~/Documents -d /mnt/backup/documentsServer Backups
# Backup remote web server to local storage
incback -s /var/www -d ~/backups/website \
-R src -U root -H webserver.comScheduled Backups
Add to crontab for automated backups:
# Backup every day at 2 AM
0 2 * * * cd /path/to/project && incbackAdvanced Usage
Exclude patterns:
Create an exclude file (e.g., exclude.txt) with patterns to skip:
node_modules/
*.log
.git/
*.tmpUse it with:
incback -s ~/projects -d /backup -e exclude.txtLogging to file:
incback -s ~/data -d /backup -l backup.logLogs include timestamps and are written to both console and file.
Custom backup prefix:
incback -s ~/data -d /backup -p "SNAPSHOT-"Creates directories like SNAPSHOT-2025-11-24T080000/ instead of BACKUP-2025-11-24T080000/.
Full CLI Example:
incback \
--src /var/www/html \
--dest /backups/website \
--remote-role dest \
--remote-user backup \
--remote-host backup-server.com \
--exclude-from ./exclude.txt \
--log-file ./backup.log \
--backup-prefix "WEB-"
--rsync-options "az"Combined example:
{
"src": "/var/www/html",
"dest": "/backups/website",
"excludeFrom": "/etc/incback/exclude-web.txt",
"logFile": "/var/log/incback/website.log",
"backupPrefix": "WEB-",
"remoteRole": "dest",
"remoteUser": "backup",
"remoteHost": "backup-server.com",
"rsyncOptions": "az"
}Docker Usage
incback can be run in a Docker container for isolated and reproducible backup operations.
Building the Docker Image
docker build -t incback .The Docker image is based on node:18-alpine and includes:
- Node.js runtime
- rsync and OpenSSH client
- The compiled incback CLI tool
Using Docker Compose
Two example configurations are provided:
Local Backups (docker-compose-local.yml)
For backing up local directories:
services:
incback:
build: .
volumes:
- "/local/src/path:/source:ro" # Source (read-only)
- "/tmp/backup:/dest" # Destination
command: ["-s", "/source", "-d", "/dest"]Run with:
docker compose -f docker-compose-local.yml upRemote Backups (docker-compose-remote.yml)
For backing up to/from remote servers via SSH:
services:
incback:
build: .
volumes:
- "/local/src/path:/source:ro" # Local source
- "${HOME}/.ssh:/root/.ssh:ro" # SSH keys for remote access
command: [
"-s", "/source",
"-d", "/remote/backup/path",
"-H", "remote_host",
"-U", "remote_user",
"-R", "dest"
]Run with:
docker compose -f docker-compose-remote.yml upDocker Run Examples
Local backup:
docker run --rm \
-v /path/to/source:/source:ro \
-v /path/to/backup:/dest \
incback -s /source -d /destRemote backup with exclude patterns:
docker run --rm \
-v /path/to/source:/source:ro \
-v /path/to/exclude.txt:/exclude.txt:ro \
-v ~/.ssh:/root/.ssh:ro \
incback -s /source -d /remote/path \
-H backup-server.com -U backup -R dest \
-e /exclude.txtUsing a configuration file:
docker run --rm \
-v /path/to/.incback:/backup/.incback:ro \
-v /path/to/source:/source:ro \
-v /path/to/backup:/dest \
incback -c /backup/.incbackDocker Notes
- The container's working directory is
/backup - Volumes
/sourceand/destare declared for convenience - For remote backups, mount your SSH keys as read-only (
~/.ssh:/root/.ssh:ro) - Log files can be written to mounted volumes for persistence
Security Considerations
- Uses SSH with
BatchMode=yesto prevent interactive prompts - All shell arguments are properly escaped to prevent injection
- Requires SSH key-based authentication (more secure than passwords)
- Never runs destructive commands without explicit configuration
Troubleshooting
"Configuration file .incback not found"
Create a .incback file in the current directory or use CLI arguments.
"remoteCommand requires remoteUser and remoteHost"
When using remoteRole, both remoteUser and remoteHost must be specified.
SSH Connection Failures
- Verify SSH key-based authentication is set up
- Test manual SSH connection:
ssh user@host - Check firewall settings
- Ensure the remote path exists and is accessible
Permission Errors
- Ensure you have read permissions on source directory
- Ensure you have write permissions on destination directory
- For remote paths, verify SSH user has appropriate permissions
License
MIT
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
