A pull-based backup system that runs on your NAS and initiates SSH connections to remote machines to perform backups. Designed for integration with n8n for centralized scheduling and monitoring.
The backup-api initiates connections to remote machines to perform backups:
n8n (local) → backup-api (local) → SSH to remote → run backup → download → cleanup
Benefits:
- No API exposure needed - stays internal
- Centralized scheduling via n8n
- Centralized monitoring and error handling
- Same mechanism for local and cloud machines
sudo apt install python3-full python3-venv python3-pip gitgit clone https://github.com/rig0/backup-api
cd backup-apipython3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txtcp .env.example .env
nano .envGenerate a secure API token:
openssl rand -hex 32Update .env:
API_TOKEN=your_generated_token_hereFor each remote machine, generate and copy SSH key:
# Generate key
ssh-keygen -t ed25519 -f ~/.ssh/cloud-server-1 -C "backup-api"
# Copy to remote machine
ssh-copy-id -i ~/.ssh/cloud-server-1.pub root@remote-hostEdit machines.yaml to add your backup sources:
machines:
- id: "cloud-server-1"
name: "Cloud Server 1"
host: "203.0.113.45"
ssh_port: 22
ssh_user: "root"
ssh_key_path: "/home/user/.ssh/cloud-server-1"
backup_type: "dockge"
retention_count: 90
remote_tmp_dir: "/tmp/stack-backup"
local_backup_dir: "/mnt/drive_0/backups/dockge/cloud-server-1"Or add machines via API:
curl -X POST http://localhost:7792/api/machines \
-H "Authorization: Bearer ${API_TOKEN}" \
-H "Content-Type: application/json" \
-d '{
"id": "cloud-server-1",
"name": "Cloud Server 1",
"host": "203.0.113.45",
"ssh_port": 22,
"ssh_user": "root",
"ssh_key_path": "/home/user/.ssh/cloud-server-1",
"backup_type": "dockge",
"retention_count": 90,
"remote_tmp_dir": "/tmp/stack-backup",
"local_backup_dir": "/mnt/drive_0/backups/dockge/cloud-server-1"
}'chmod +x ./start-api.sh
./start-api.shCreate /etc/systemd/system/backup-api.service:
[Unit]
Description=Backup API
After=network.target
[Service]
User=user
Group=user
WorkingDirectory=/home/user/backup-api
ExecStart=/home/user/backup-api/venv/bin/python api.py
Restart=always
Environment="PATH=/home/user/backup-api/venv/bin:/usr/bin"
[Install]
WantedBy=multi-user.targetEnable and start:
sudo systemctl daemon-reload
sudo systemctl enable backup-api
sudo systemctl start backup-api
sudo systemctl status backup-apiAll endpoints require Authorization: Bearer <API_TOKEN> header.
curl http://localhost:7792/healthcurl -X POST http://localhost:7792/api/backup \
-H "Authorization: Bearer ${API_TOKEN}" \
-H "Content-Type: application/json" \
-d '{"machine_id": "cloud-server-1"}'List all machines:
curl http://localhost:7792/api/machines \
-H "Authorization: Bearer ${API_TOKEN}"Get specific machine:
curl http://localhost:7792/api/machines/cloud-server-1 \
-H "Authorization: Bearer ${API_TOKEN}"Update machine:
curl -X PUT http://localhost:7792/api/machines/cloud-server-1 \
-H "Authorization: Bearer ${API_TOKEN}" \
-H "Content-Type: application/json" \
-d '{"name": "Updated Name", "retention_count": 60}'Delete machine:
curl -X DELETE http://localhost:7792/api/machines/cloud-server-1 \
-H "Authorization: Bearer ${API_TOKEN}"Add to n8n environment:
API_TOKEN=your_generated_token_here
BACKUP_API_URL=http://backup-api-host:7792
Schedule Node (Cron: 0 2 * * * - Daily at 2 AM)
↓
HTTP Request Node (Trigger Backup)
{
"method": "POST",
"url": "{{$env.BACKUP_API_URL}}/api/backup",
"headers": {
"Authorization": "Bearer {{$env.API_TOKEN}}",
"Content-Type": "application/json"
},
"body": {
"machine_id": "cloud-server-1"
}
}↓ IF Node (Check success) ↓ Pushover Notification Node (On success/failure)
backup-api/
├── api.py # Main Flask application
├── requirements.txt # Python dependencies
├── machines.yaml # Machine configurations
├── .env # Environment variables (API_TOKEN)
├── modules/
│ ├── __init__.py
│ └── dockge.py # Dockge backup module
└── utils/
├── __init__.py
├── ssh_client.py # SSH client wrapper
└── config.py # Configuration manager
Create a new module in modules/ directory:
# modules/postgres.py
class PostgresBackup:
def execute_backup(self, machine_config):
# Implementation
return (success, message)Configure machine with backup_type: "postgres".
View logs:
tail -f backup-api.logOr with systemd:
sudo journalctl -u backup-api -fTest SSH connectivity manually:
ssh -i /home/user/.ssh/cloud-server-1 root@remote-hostEnsure SSH key has correct permissions:
chmod 600 /home/user/.ssh/cloud-server-1Check if port 7792 is available:
sudo netstat -tulpn | grep 7792