{"id":46886627,"url":"https://github.com/xnetvn-com/php-backup-remote","last_synced_at":"2026-03-10T22:15:06.079Z","repository":{"id":302012432,"uuid":"1005369465","full_name":"xnetvn-com/php-backup-remote","owner":"xnetvn-com","description":"A PHP CLI tool for automated, encrypted HestiaCP user backups to S3 or FTP. Supports compression, retention, notifications, and resource checks. Fast, secure, and easy to configure for production servers.","archived":false,"fork":false,"pushed_at":"2025-07-07T08:25:34.000Z","size":8082,"stargazers_count":2,"open_issues_count":1,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-07-07T09:37:06.882Z","etag":null,"topics":["7z","aes","aes-256","b2","backblaze","backblaze-b2","backup","ftp","hestiacp","php","php-library","s3","upload","vestacp","zip","zstd"],"latest_commit_sha":null,"homepage":"https://xnetvn.com/","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/xnetvn-com.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":"security_demo.php","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-06-20T05:59:06.000Z","updated_at":"2025-07-07T08:25:37.000Z","dependencies_parsed_at":"2025-07-07T09:26:12.061Z","dependency_job_id":null,"html_url":"https://github.com/xnetvn-com/php-backup-remote","commit_stats":null,"previous_names":["xnetvn-com/php-backup-remote"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/xnetvn-com/php-backup-remote","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xnetvn-com%2Fphp-backup-remote","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xnetvn-com%2Fphp-backup-remote/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xnetvn-com%2Fphp-backup-remote/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xnetvn-com%2Fphp-backup-remote/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/xnetvn-com","download_url":"https://codeload.github.com/xnetvn-com/php-backup-remote/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xnetvn-com%2Fphp-backup-remote/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30357625,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-10T21:41:54.280Z","status":"ssl_error","status_checked_at":"2026-03-10T21:40:59.357Z","response_time":106,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["7z","aes","aes-256","b2","backblaze","backblaze-b2","backup","ftp","hestiacp","php","php-library","s3","upload","vestacp","zip","zstd"],"created_at":"2026-03-10T22:15:05.121Z","updated_at":"2026-03-10T22:15:06.069Z","avatar_url":"https://github.com/xnetvn-com.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"# HestiaCP Remote Backup Tool\n\n[![Build Status](https://github.com/xnetvn-com/php-backup-remote/actions/workflows/ci.yml/badge.svg)](https://github.com/xnetvn-com/php-backup-remote/actions)\n[![Coverage Status](https://codecov.io/gh/xnetvn-com/php-backup-remote/branch/main/graph/badge.svg)](https://codecov.io/gh/xnetvn-com/php-backup-remote)\n[![License: Apache-2.0](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](LICENSE)\n\nA robust PHP command-line utility to automate the backup of Hestia Control Panel user data to various remote storage providers. It supports encryption, compression, retention policies, and multi-channel notifications, optimized for servers with limited resources.\n\n## Project Structure\n\n```text\n├── app/                # Application source code (Backup, Notification, Storage, System, Utils)\n├── config/             # Configuration files (app.php, constant.php)\n├── libs/               # Composer dependencies and autoload\n├── storage/            # Logs and runtime data\n├── tests/              # PHPUnit test cases (unit, integration, E2E, hardening)\n├── tmp/                # Temporary working directory for backup operations\n├── .github/            # GitHub Actions, issue templates, CODEOWNERS, PR template\n├── .env.example        # Example environment configuration\n├── run.php             # Main entry point for backup\n├── download.php        # Restore utility\n├── upload.php          # (Optional) Upload utility\n├── README.md           # Project documentation\n├── LICENSE             # Apache License 2.0\n├── NOTICE              # Attribution notice\n└── CONTRIBUTING.md     # Contribution guidelines\n```\n\n## Features\n\n- **Multiple Storage Backends**: Upload encrypted backups to AWS S3, Backblaze B2, DigitalOcean Spaces, traditional FTP/FTPS servers, or local filesystem via [Flysystem](https://flysystem.thephpleague.com/).\n- **Strong Encryption**: AES-256-CBC encryption (via OpenSSL) or GPG encryption with optional key management.\n- **Flexible Compression**: Support for gzip, zstd, bzip2, xz, zip, 7z formats with configurable compression levels.\n- **Smart Rotation**: Advanced retention policies supporting daily, weekly, monthly, and yearly backup retention with intelligent file grouping.\n- **XBK File Format**: Custom .xbk archive format supporting layered compression and encryption with filename metadata.\n- **Dry-Run Mode**: Safe simulation without creating, uploading, or deleting files for testing configurations.\n- **Structured Logging**: Comprehensive logging with Monolog supporting multiple channels and log levels.\n- **Pre-flight Checks**: CPU load, disk space, time window validation, and dependency verification.\n- **Multi-Channel Notifications**: Email (SMTP), Telegram, Discord, Slack, Microsoft Teams, Google Chat notifications.\n- **Performance Optimized**: Streaming operations for large files, memory-efficient processing, concurrent uploads.\n- **Security Hardened**: Read-only source protection, path traversal prevention, secure credential management.\n- **CLI Tools Integration**: Native support for 7z, zip, gzip, zstd, bzip2, xz CLI tools for optimal performance.\n- **PSR Compliant**: Modern PHP 8.2+ codebase following PSR-4, PSR-12, PSR-3 standards with full type declarations.\n\n## Requirements\n\n- PHP 8.2 or higher\n- Composer\n- PHP Extensions: `ctype`, `mbstring`, `openssl`, `ftp` (for FTP driver)\n- CLI Tools for compression/encryption:\n  - gzip (install: `sudo apt install gzip`)\n  - zstd (install: `sudo apt install zstd`)\n  - bzip2 (install: `sudo apt install bzip2`)\n  - xz-utils (install: `sudo apt install xz-utils`)\n  - zip \u0026 unzip (install: `sudo apt install zip unzip`)\n  - p7zip-full (install: `sudo apt install p7zip-full`)\n  - gnupg (install: `sudo apt install gnupg`)\n\n### Supported Platforms\n\nThis tool has been tested on the following operating systems:\n\n- **Debian/Ubuntu**\n\n  ```bash\n  sudo apt update \u0026\u0026 sudo apt install -y php-cli php-mbstring php-common \\\n    unzip zip gzip zstd bzip2 xz-utils p7zip-full gnupg composer\n  ```\n\n- **CentOS/RHEL**\n\n  ```bash\n  sudo yum install -y epel-release \u0026\u0026 sudo yum install -y php-cli php-mbstring php-common \\\n    unzip zip gzip zstd bzip2 xz p7zip p7zip-plugins gnupg composer\n  ```\n\n- **macOS**\n\n  ```bash\n  brew update \u0026\u0026 brew install php composer zstd xz p7zip gnupg\n  ```\n\n## Installation\n\n```bash\ngit clone https://github.com/xnetvn-com/php-backup-remote.git\ncd php-backup-remote\ncd libs\ncomposer install --no-dev --optimize-autoloader\ncd ..\n```\n\n### Auto-Update (Recommended)\n\nFor safe and convenient updates to the latest version:\n\n```bash\n./auto_update.sh\n```\n\n**Note:**\n\n- The script will automatically detect the default branch (`main` or `master`) from the remote repository.\n\n- If the current directory is a Git repository, it will fetch and **hard reset** to match the remote branch (all local changes will be overwritten).\n\n- If the current directory is not a Git repository, it will clone the correct branch and copy files into the current directory.\n\n- Your configuration files and logs will be preserved.\n\n- Requires `git` to be installed.\n\n\u003e ⚠️ **Warning:** This script will overwrite any local changes in the repository directory. Make sure to back up your work if needed.\n\nSee [UPDATE_GUIDE.md](UPDATE_GUIDE.md) for detailed instructions.\n\n### Quick Start\n\n1. Clone the repository and enter directory:\n\n   ```bash\n   git clone https://github.com/xnetvn-com/php-backup-remote.git\n   cd php-backup-remote\n   ```\n\n2. Install PHP dependencies (production):\n\n   ```bash\n   cd libs\n   composer install --no-dev --optimize-autoloader\n   cd ..\n   ```\n\n   For development (with dev dependencies):\n\n   ```bash\n   cd libs\n   composer install\n   cd ..\n   ```\n\n3. Copy and customize environment settings:\n\n   ```bash\n   cp .env.example .env\n   # Edit .env to configure backup paths, encryption, compression, and storage drivers\n   ```\n\n4. Run a dry-run to verify settings:\n\n   ```bash\n   php run.php --dry-run\n   ```\n\n5. Execute a real backup:\n\n   ```bash\n   php run.php\n   ```\n\n## Example .env Configuration\n\n```ini\n# Core backup settings\nBACKUP_PASSWORD=your-super-secret-encryption-password\nBACKUP_DIRS=/backup,/home,/var/www\nBACKUP_COMPRESSION=gzip   # Options: none, gzip, zstd, bzip2, xz, zip, 7z\nBACKUP_COMPRESSION_LEVEL=6\nBACKUP_ENCRYPTION=aes     # Options: none, aes, gpg, zip, 7z\nBACKUP_ENCRYPTION_KEY_PATH=/path/to/public.key # For GPG (optional)\nTMP_DIR=/tmp/php-backup-remote\n\n# Advanced compression and encryption combinations:\n# - BACKUP_COMPRESSION=7z + BACKUP_ENCRYPTION=7z: Uses 7z CLI for both compression and encryption in one step\n# - BACKUP_COMPRESSION=zip + BACKUP_ENCRYPTION=zip: Uses zip CLI with AES-256 encryption in one step\n# - BACKUP_COMPRESSION=7z + BACKUP_ENCRYPTION=none: Uses 7z CLI for compression only\n# - BACKUP_COMPRESSION=zip + BACKUP_ENCRYPTION=none: Uses zip CLI for compression only\n# - Separate steps: BACKUP_COMPRESSION=gzip + BACKUP_ENCRYPTION=aes (compress first, then encrypt)\n\n# Rotation \u0026 retention\nROTATION_ENABLED=true\nROTATION_KEEP_LATEST=7\nROTATION_KEEP_DAILY=7\nROTATION_KEEP_WEEKLY=4\nROTATION_KEEP_MONTHLY=12\nROTATION_KEEP_YEARLY=3\nROTATION_PATTERN=*.xbk.*\n\n# Remote storage (S3, B2, FTP, Local)\nREMOTE_DRIVER=s3          # Options: s3, b2, ftp, local\n\n# S3 settings\nS3_KEY=your-s3-access-key\nS3_SECRET=your-s3-secret-key\nS3_REGION=ap-southeast-1\nS3_BUCKET=your-s3-bucket-name\nS3_ENDPOINT=https://s3.example.com\nS3_USE_PATH_STYLE=true\n\n# Backblaze B2 settings\nB2_KEY=your-b2-application-key-id\nB2_SECRET=your-b2-application-key\nB2_BUCKET=your-b2-bucket-name\nB2_REGION=us-west-002\n\n# FTP settings\nFTP_HOST=your-ftp-host\nFTP_USER=your-ftp-username\nFTP_PASS=your-ftp-password\nFTP_ROOT=/backups\nFTP_SSL=true\nFTP_PASSIVE=true\n\n# Local storage\nLOCAL_PATH=/mnt/backup-disk\n\n# Performance \u0026 resource limits\nALLOWED_START_TIME=01:00\nALLOWED_END_TIME=05:00\nMAX_CPU_LOAD=2.5\nMIN_DISK_FREE_PERCENT=15\nMEMORY_LIMIT=256M\nTIME_LIMIT=3600\n\n# Notification settings\nEMAIL_SMTP_HOST=smtp.example.com\nEMAIL_SMTP_PORT=587\nEMAIL_SMTP_USER=your-email@example.com\nEMAIL_SMTP_PASS=your-smtp-password\nEMAIL_SMTP_ENCRYPTION=tls\nADMIN_EMAIL=admin@example.com\n\nTELEGRAM_BOT_TOKEN=your-telegram-bot-token\nTELEGRAM_CHAT_ID=your-telegram-chat-id\n\nDISCORD_WEBHOOK=your-discord-webhook-url\nSLACK_WEBHOOK=your-slack-webhook-url\nTEAMS_WEBHOOK=your-teams-webhook-url\nGOOGLE_CHAT_WEBHOOK=your-google-chat-webhook-url\nNOTIFY_INTERVAL_MINUTES=180\n\n# Advanced options\nDRY_RUN=false\nLOG_CHANNEL=app\nLOG_PATH=storage/logs/app.log\nLOG_LEVEL=info\nLOCK_FILE=storage/.backup.lock\n\n# Security\nENFORCE_READONLY=true\nSAFE_MODE=true\n\n# Developer/debug\nDEBUG=false\nVERBOSE=false\n\n# Custom user hooks (optional)\nPRE_BACKUP_HOOK=/path/to/pre-backup.sh\nPOST_BACKUP_HOOK=/path/to/post-backup.sh\n\n# Example for multiple backup sources\n# BACKUP_DIRS=/backup,/home/user1,/home/user2,/var/www/html\n```\n\n## Configuration\n\nCopy the example environment file and edit your settings:\n\n```bash\ncp .env.example .env\n```\n\nOpen `.env` and configure:\n\n| Variable                  | Description                                                         | Default             |\n|---------------------------|---------------------------------------------------------------------|---------------------|\n| BACKUP_PASSWORD           | Password for AES or GPG encryption (choose a strong secret)         | *REQUIRED*          |\n| BACKUP_DIRS               | Comma-separated absolute paths to backup user directories           | `/backup`           |\n| BACKUP_COMPRESSION        | Compression method (`none`, `gzip`, `zstd`, `bzip2`, `xz`, `zip`, `7z`) | `none`              |\n| BACKUP_COMPRESSION_LEVEL  | Compression level (1-9, default 6)                                  | `6`                  |\n| BACKUP_ENCRYPTION         | Encryption method (`none`, `aes`, `gpg`, `zip`, `7z`)              | `aes`               |\n| BACKUP_ENCRYPTION_KEY_PATH| Path to public key for GPG encryption (optional)                   | *Not set*         |\n| REMOTE_DRIVER             | Override to use a single storage driver: `s3`, `b2`, `ftp` or `local` | *Not set*         |\n| TMP_DIR                   | Temporary directory for backup operations                            | `/tmp/php-backup-remote` |\n\n### Compression \u0026 Encryption CLI Usage\n\n| Configuration                                | CLI Tools Used              | Description                                    |\n|----------------------------------------------|------------------------------|------------------------------------------------|\n| `BACKUP_COMPRESSION=7z` + `BACKUP_ENCRYPTION=7z` | `7z a` (single step)    | 7z CLI compresses and encrypts in one command |\n| `BACKUP_COMPRESSION=zip` + `BACKUP_ENCRYPTION=zip` | `zip -e` (single step) | zip CLI compresses with traditional encryption |\n| `BACKUP_COMPRESSION=7z` + `BACKUP_ENCRYPTION=none` | `7z a` (compression only) | 7z CLI for compression only                  |\n| `BACKUP_COMPRESSION=zip` + `BACKUP_ENCRYPTION=none` | `zip` (compression only) | zip CLI for compression only                 |\n| `BACKUP_COMPRESSION=gzip` + `BACKUP_ENCRYPTION=aes` | `gzip` + `openssl`     | Separate compression and encryption steps     |\n| `BACKUP_COMPRESSION=zstd` + `BACKUP_ENCRYPTION=gpg` | `zstd` + `gpg`         | Separate compression and encryption steps     |\n\n**Note**: The zip CLI uses traditional password-based encryption (not AES-256). For stronger encryption, use 7z or separate AES encryption.\n\n### S3 Driver Settings\n\n| Variable                  | Description                                                         |\n|---------------------------|---------------------------------------------------------------------|\n| S3_KEY                    | S3 access key                                                       |\n| S3_SECRET                 | S3 secret key                                                       |\n| S3_REGION                 | S3 region                                                           |\n| S3_BUCKET                 | S3 bucket name                                                      |\n| S3_ENDPOINT               | Custom endpoint (for non-AWS providers)                             |\n| S3_USE_PATH_STYLE         | `true` if using path-style URLs (e.g., DigitalOcean Spaces)       |\n\n### Backblaze B2 Settings\n\n| Variable                  | Description                                                         |\n|---------------------------|---------------------------------------------------------------------|\n| B2_KEY                    | Backblaze B2 application key ID                                     |\n| B2_SECRET                 | Backblaze B2 application key                                        |\n| B2_BUCKET                 | Backblaze B2 bucket name                                            |\n| B2_REGION                 | Backblaze B2 region (optional)                                      |\n\n### FTP Driver Settings\n\n| Variable                  | Description                                                         |\n|---------------------------|---------------------------------------------------------------------|\n| FTP_HOST                  | FTP server hostname                                                 |\n| FTP_USER                  | FTP username                                                        |\n| FTP_PASS                  | FTP password                                                        |\n| FTP_ROOT                  | Base directory on FTP server (optional)                             |\n| FTP_SSL                   | `true` or `false` for FTPS (optional)                               |\n| FTP_PASSIVE               | `true` (passive) or `false` (active) (recommended: `true`)          |\n\n### Local Storage Settings\n\n| Variable                  | Description                                                         |\n|---------------------------|---------------------------------------------------------------------|\n| LOCAL_PATH                | Local file system path for backups                                  |\n\n### Rotation Settings\n\n| Variable                  | Description                 | Default  |\n|---------------------------|-----------------------------|----------|\n| ROTATION_ENABLED          | Enable automatic rotation   | `true`   |\n| ROTATION_KEEP_LATEST      | Number of recent backups to keep | `7` |\n| ROTATION_KEEP_DAILY       | Number of daily backups to keep | `7` |\n| ROTATION_KEEP_WEEKLY      | Number of weekly backups to keep | `4` |\n| ROTATION_KEEP_MONTHLY     | Number of monthly backups to keep | `12` |\n| ROTATION_KEEP_YEARLY      | Number of yearly backups to keep | `3` |\n| ROTATION_PATTERN          | Pattern to match backup files for rotation | `*.xbk.*` |\n\n### Performance Limits\n\n| Variable                  | Description                                                       | Default |\n|---------------------------|-------------------------------------------------------------------|----------|\n| ALLOWED_START_TIME        | Earliest allowed backup time (`HH:MM`), empty to disable           | `01:00`  |\n| ALLOWED_END_TIME          | Latest allowed backup time (`HH:MM`), empty to disable            | `05:00`  |\n| MAX_CPU_LOAD              | Max 1-min CPU load average, 0 to disable                           | `2.5`    |\n| MIN_DISK_FREE_PERCENT     | Minimum free disk % in temp dir                                    | `15`     |\n| MEMORY_LIMIT              | PHP memory limit (e.g., `256M`)                                     | `256M`   |\n| TIME_LIMIT                | Max script time in seconds, 0 for unlimited                        | `3600`   |\n\n### Notification Settings\n\n| Variable                  | Description                                                    | Default |\n|---------------------------|----------------------------------------------------------------|----------|\n| EMAIL_SMTP_HOST           | SMTP server host                                              | -       |\n| EMAIL_SMTP_PORT           | SMTP server port                                              | `587`   |\n| EMAIL_SMTP_USER           | SMTP username                                                 | -       |\n| EMAIL_SMTP_PASS           | SMTP password                                                 | -       |\n| EMAIL_SMTP_ENCRYPTION     | SMTP encryption method (`tls`, `ssl`, or empty for none)    | `tls`   |\n| ADMIN_EMAIL               | Email address to receive notifications                        | -       |\n| TELEGRAM_BOT_TOKEN        | Telegram bot token                                            | -       |\n| TELEGRAM_CHAT_ID          | Telegram chat ID                                              | -       |\n| DISCORD_WEBHOOK           | Discord webhook URL                                           | -       |\n| SLACK_WEBHOOK             | Slack webhook URL                                             | -       |\n| TEAMS_WEBHOOK             | Microsoft Teams webhook URL                                   | -       |\n| GOOGLE_CHAT_WEBHOOK       | Google Chat webhook URL                                       | -       |\n| NOTIFY_INTERVAL_MINUTES   | Cool-down period between notifications (minutes)              | `180`   |\n\n### Advanced Options\n\n| Variable                  | Description                                                    | Default |\n|---------------------------|----------------------------------------------------------------|---------|\n| DRY_RUN                   | Simulate backup without writing/uploading files                | `false` |\n| LOG_CHANNEL               | Log channel name (for Monolog)                                 | `app`   |\n| LOG_PATH                  | Path to log file                                               | `storage/logs/app.log` |\n| LOG_LEVEL                 | Log level (`info`, `debug`, `error`, etc.)                     | `info`  |\n| LOCK_FILE                 | Path to lock file to prevent concurrent runs                   | `storage/.backup.lock` |\n\n### Security Options\n\n| Variable                  | Description                                                    | Default |\n|---------------------------|----------------------------------------------------------------|---------|\n| ENFORCE_READONLY          | Enforce read-only mode for BACKUP_DIRS                         | `true`  |\n| SAFE_MODE                 | Enable extra safety checks (recommended)                       | `true`  |\n\n### Developer/Debug Options\n\n| Variable                  | Description                                                    | Default |\n|---------------------------|----------------------------------------------------------------|---------|\n| DEBUG                     | Enable debug mode                                              | `false` |\n| VERBOSE                   | Enable verbose output                                          | `false` |\n\n### Custom User Hooks\n\n| Variable                  | Description                                                    | Default |\n|---------------------------|----------------------------------------------------------------|---------|\n| PRE_BACKUP_HOOK           | Path to script to run before backup                            | *Not set* |\n| POST_BACKUP_HOOK          | Path to script to run after backup                             | *Not set* |\n\n## Security \u0026 Data Integrity\n\n- **Read-Only Guarantee for BACKUP_DIRS**: All files and directories specified in `BACKUP_DIRS` are treated as strictly read-only. The backup system will never modify, delete, move, or overwrite any original file in these directories. All backup, compression, and encryption operations are performed on temporary copies in a dedicated temp directory (`TMP_DIR`). This ensures absolute safety and integrity of your source data.\n\n- **AES-256-CBC Encryption**: Industry-standard encryption with OpenSSL implementation providing strong data protection at rest and in transit.\n\n- **GPG Encryption Support**: Alternative encryption using GnuPG with public key cryptography for enhanced security scenarios.\n\n- **Path Traversal Protection**: Comprehensive validation to prevent directory traversal attacks and unauthorized file access.\n\n- **Secure Credential Management**: Environment-based credential storage with optional encryption for sensitive configuration values.\n\n- **Automated Security Tests**: The project includes automated tests to verify that no write, delete, or move operations are ever performed directly in `BACKUP_DIRS`.\n\n- **CLI Tool Security**: Secure invocation of external compression and encryption tools with proper argument sanitization.\n\n- **File Permissions**: Proper temporary directory permissions (0700) and secure file handling throughout the backup process.\n\n- **Best Practice**: Always set appropriate file system permissions to enforce read-only access for the backup process user on your backup source directories.\n\n## Usage\n\n### Run Backup\n\n**Real backup:**\n\n```bash\nphp run.php\n```\n\n**Dry-run (simulate):**\n\n```bash\nphp run.php --dry-run\n```\n\n### Restore Backup\n\n```bash\nphp download.php --user=\u003cusername\u003e --version=\u003cYYYY-MM-DD_HH-MM-SS\u003e [--remote=\u003cdriver\u003e] [--outdir=\u003cpath\u003e]\n```\n\n### Automate with Cron\n\n```cron\n30 2 * * * /usr/bin/php /path/to/php-backup-remote/run.php \u003e /dev/null 2\u003e\u00261\n```\n\n## How It Works\n\n1. **Initialization**: Load `.env` and bootstrap services.\n2. **Locking**: Prevent concurrent runs with a lock file.\n3. **Pre-flight Checks**: CPU, disk space, and time-window validation.\n4. **Archive**: Create compressed archive per user directory using TAR with configurable compression.\n5. **Encrypt**: Encrypt archive with AES-256-CBC or GPG using OpenSSL/CLI tools.\n6. **Upload**: Stream to configured remote storage backends (S3/B2/FTP/Local).\n7. **Cleanup**: Remove local temporary files and release lock.\n8. **Rotation**: List remote files and delete older backups beyond retention policy.\n9. **Notification**: Send success or failure alerts via multiple channels.\n\n## Testing\n\nRun PHPUnit unit tests:\n\n```bash\n./libs/vendor/bin/phpunit --configuration=phpunit.xml\n```\n\n### Test Coverage\n\nThe project includes comprehensive test coverage:\n\n- **Unit Tests**: Core functionality, encryption, compression, storage operations\n- **Integration Tests**: Component interaction, backup workflows, storage backends  \n- **Edge Case Tests**: Large files, special characters, error conditions\n- **Security Tests**: Encryption strength, credential management, path validation\n- **Performance Tests**: Memory usage, streaming operations, concurrent access\n\nFor test coverage report generation:\n\n```bash\n# Install Xdebug (if not already installed)\nsudo apt install php8.2-xdebug\n\n# Generate coverage report\n./libs/vendor/bin/phpunit --coverage-html coverage/\n```\n\n## Contributing\n\nWe welcome contributions from the community! Please see [CONTRIBUTING.md](CONTRIBUTING.md) for detailed guidelines. All contributors must follow the [CODEOWNERS](.github/CODEOWNERS) and use the provided [pull request template](.github/pull_request_template.md). Issues and feature requests should use the appropriate [issue templates](.github/ISSUE_TEMPLATE/).\n\n- **Security Contact:** Please report security vulnerabilities via [security_vulnerability.md](.github/ISSUE_TEMPLATE/security_vulnerability.md) or email [license@xnetvn.net](mailto:license@xnetvn.net).\n- **CI/CD:** All code is automatically tested, linted, scanned for secrets and vulnerabilities, and must pass all checks before merging.\n\n## License\n\nThis project is licensed under the Apache License 2.0 - see the [LICENSE](LICENSE) file for details.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fxnetvn-com%2Fphp-backup-remote","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fxnetvn-com%2Fphp-backup-remote","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fxnetvn-com%2Fphp-backup-remote/lists"}