marinc is a Python-based utility that automates incremental backups of MariaDB databases using mariabackup.
It supports Telegram notifications, automatic rotation, and secure transfer of backups to a remote host via SCP over SSH.
- 🔁 Incremental & full MariaDB backups using
mariabackup - 🔐 Secure file transfer to remote destination (via SSH + SCP)
- 🧹 Automatic rotation of old incremental backups
- ⚙️ Configurable via
.envor environment variables - 🧱 Lock file protection to avoid multiple concurrent runs
- 📣 Telegram alerts for errors or duplicate runs
- 🪵 Structured logging for all operations
- Checks for an existing lock file to prevent concurrent runs
- Determines whether a full or incremental backup is needed
- Executes the appropriate
mariabackupcommand - Compresses and transfers the backup via
SCPto a remote destination - Rotates older backups, keeping only the most recent ones
- Sends Telegram notifications in case of errors or duplicate runs
git clone https://github.com/yourusername/marinc.git
cd marincpython3.12 -m venv venv
source venv/bin/activatepip install -r requirements.txtCreate a .env file in the project root:
LOG_FILE=/var/log/marinc.log
BACKUP_DIR=/backups
REMOTE_DIR=/backups/inc
MYSQL_CNF_PATH=/root/.my.cnf
LOCAL_KEEP_COUNT=5
DESTINATION_IP=192.168.1.1
DESTINATION_USER=marinc-sync
DESTINATION_PORT=22
DESTINATION_SSH_PRIVATE_KEY_PATH=/root/.ssh/id_rsa_marinc_sync
RETRY_LIMIT=3
RETRY_DELAY=60
TELEGRAM_BOT_TOKEN=your_telegram_bot_token
TELEGRAM_GROUP_CHAT_ID=your_group_chat_id
LOCK_FILE=/var/run/marinc.lockEnsure your /root/.my.cnf contains:
[client]
user=root
password=yourpasswordsudo python3 marinc.pyRun incremental backup every night at 2:00 AM:
0 2 * * * /usr/bin/python3 /path/to/marinc/marinc.py >> /var/log/marinc_cron.log 2>&1🪄 Tip: Use absolute paths in cron to avoid environment issues.
All logs are written to:
/var/log/marinc.log
Each entry includes a timestamp, log level, and detailed message, e.g.:
2025-10-29 02:00:01 - INFO - ===== Starting incremental Marinc sync =====
2025-10-29 02:00:04 - INFO - Performing INCREMENTAL backup based on /backups/inc/inc_20251028_020000...
2025-10-29 02:05:18 - INFO - Transfer complete.
2025-10-29 02:05:19 - INFO - Rotation complete. Retained last 5 incremental.
2025-10-29 02:05:20 - INFO - ===== Incremental backup completed successfully =====
| Variable | Default | Description |
|---|---|---|
| LOG_FILE | /var/log/marinc.log |
Path to log file |
| BACKUP_DIR | /backups |
Root directory for backups |
| REMOTE_DIR | /backups/inc |
Destination path on remote host |
| MYSQL_CNF_PATH | /root/.my.cnf |
MariaDB credentials file path |
| LOCAL_KEEP_COUNT | 5 |
Number of incremental backups to keep locally |
| DESTINATION_IP | — | Remote host IP for SCP transfer |
| DESTINATION_USER | — | SSH username for remote host |
| DESTINATION_PORT | 22 |
SSH port |
| DESTINATION_SSH_PRIVATE_KEY_PATH | — | Path to SSH private key |
| RETRY_LIMIT | 3 |
Max retries for failed transfers |
| RETRY_DELAY | 60 |
Delay (in seconds) between retries |
| TELEGRAM_BOT_TOKEN | — | Telegram bot API token |
| TELEGRAM_GROUP_CHAT_ID | — | Telegram chat/group ID for notifications |
| LOCK_FILE | /var/run/marinc.lock |
Lock file path to prevent multiple runs |
All dependencies are listed in requirements.txt:
bcrypt==5.0.0
certifi==2025.10.5
cffi==2.0.0
charset-normalizer==3.4.4
cryptography==46.0.2
idna==3.11
invoke==2.2.1
paramiko==4.0.0
pycparser==2.23
PyNaCl==1.6.0
python-dotenv==1.1.1
requests==2.32.5
scp==0.15.0
urllib3==2.5.0
Compatible with Python 3.12+
- Ensure the SSH private key (
DESTINATION_SSH_PRIVATE_KEY_PATH) has strict permissions (chmod 600). - The MariaDB credentials file (
.my.cnf) should only be readable by root. - Do not store plain passwords in
.env—use.my.cnffor database access.
Success:
✅ Marinc backup completed successfully.
Failure:
❌ Marinc backup failed: Permission denied while connecting to remote host.
Duplicate run:
⚠️ Backup process already running. Skipping execution.
- Keeps only the latest N incremental backups (defined by
LOCAL_KEEP_COUNT) - Automatically deletes older ones to save disk space
- Full backup is preserved until manually rotated or replaced
If you define RESTORE_SCRIPT_PATH, Marinc can point to your restore script for manual or automated recovery.
Typical restore flow (example):
mariabackup --prepare --target-dir=/backups/full
mariabackup --copy-back --target-dir=/backups/fullMIT License © 2025 Mohamadreza Najarbashi