# CoreERP — Backup and Restore Guide

> **Project:** CoreERP — TAN General Supply Limited  
> **Date prepared:** 2026-07-14

---

## 1. MySQL Database Backup (Manual)

### Backup command template

Replace the placeholders with your actual values. **Do not store real credentials in this file.**

```bash
mysqldump \
  --host=YOUR_DB_HOST \
  --port=3306 \
  --user=YOUR_DB_USER \
  --password=YOUR_DB_PASSWORD \
  --single-transaction \
  --routines \
  --triggers \
  --events \
  YOUR_DB_NAME > /path/to/backups/coreerp_$(date +%Y%m%d_%H%M%S).sql
```

**Key flags explained:**

| Flag | Purpose |
|------|---------|
| `--single-transaction` | Consistent snapshot without locking tables (InnoDB) |
| `--routines` | Include stored procedures and functions |
| `--triggers` | Include triggers |
| `--events` | Include scheduled events |

### Compress the backup

```bash
gzip /path/to/backups/coreerp_YYYYMMDD_HHMMSS.sql
```

This produces a `.sql.gz` file — typically 80-95% smaller than the raw SQL dump.

---

## 2. MySQL Restore Command Template

```bash
# Decompress first (if gzipped)
gunzip /path/to/backups/coreerp_YYYYMMDD_HHMMSS.sql.gz

# Restore into the database
mysql \
  --host=YOUR_DB_HOST \
  --port=3306 \
  --user=YOUR_DB_USER \
  --password=YOUR_DB_PASSWORD \
  YOUR_DB_NAME < /path/to/backups/coreerp_YYYYMMDD_HHMMSS.sql
```

> **Warning:** Restore replaces existing data. Only run on a staging/local environment first to validate the backup before restoring to production.

---

## 3. Laravel Storage Backup

### 3.1 User-uploaded files

Uploaded files (attachments, imports, exports) live in:

```
storage/app/public/
```

Back up this directory:

```bash
tar -czf /path/to/backups/storage_app_public_$(date +%Y%m%d).tar.gz \
  /var/www/coreerp/storage/app/public/
```

### 3.2 Company images and logos

Company-specific images are stored in:

```
public/company/
```

Back up this directory:

```bash
tar -czf /path/to/backups/company_images_$(date +%Y%m%d).tar.gz \
  /var/www/coreerp/public/company/
```

### 3.3 Reports folder

Generated reports live in:

```
storage/app/reports/
```

Back up if reports are archived long-term:

```bash
tar -czf /path/to/backups/reports_$(date +%Y%m%d).tar.gz \
  /var/www/coreerp/storage/app/reports/
```

---

## 4. Recommended Backup Schedule

| Frequency | Scope | Retention |
|-----------|-------|-----------|
| **Daily** | Full MySQL database dump (gzipped) | Keep 14 days |
| **Weekly** | Full storage backup (`storage/app/public/` + `public/company/`) | Keep 8 weeks |
| **Monthly** | Complete offsite archive (DB + all storage) | Keep 12 months |

> **Before every production deployment:** Take an immediate on-demand backup of the database before running `php artisan migrate`.

---

## 5. Backup Verification Checklist

After every backup, verify:

- [ ] **File exists** — the `.sql.gz` or `.tar.gz` file was actually created.
- [ ] **File size is non-zero** — a 0-byte backup means the command failed silently.
- [ ] **Timestamp is recent** — check `ls -lh /path/to/backups/` to confirm today's date.
- [ ] **Test restore** — periodically restore to a local or staging environment and confirm:
  - The database tables exist.
  - Row counts in key tables (customers, tax_invoices, stock_movements) are plausible.
  - Application boots without errors after restore.

```bash
# Quick non-destructive check: count tables in a restored dump
grep -c "CREATE TABLE" /path/to/backups/coreerp_YYYYMMDD.sql
```

---

## 6. Backup Security Guidelines

1. **Never store backups inside the web root** (`public/` folder). A backup file stored in `public/backups/coreerp.sql` is accessible to anyone with the URL.

2. **Restrict backup directory permissions:**
   ```bash
   chmod 700 /path/to/backups/
   chown root:root /path/to/backups/
   ```

3. **Encrypt sensitive backups:**
   ```bash
   gpg --symmetric --cipher-algo AES256 coreerp_YYYYMMDD.sql.gz
   ```

4. **Store offsite:** Copy backups to a separate server, cloud storage (S3, Backblaze B2, Google Cloud Storage), or an external drive that is not on the same machine as the application.

5. **Rotate old backups:** Automate deletion of backups older than the retention period to avoid disk exhaustion.

6. **Never commit backup files to git.** Ensure `.gitignore` includes:
   ```
   *.sql
   *.sql.gz
   *.tar.gz
   /backups/
   ```

---

## 7. Automated Backup (Cron Example)

Add to the server's crontab (`crontab -e` as root or the deploy user):

```cron
# Daily DB backup at 2:00 AM
0 2 * * * /var/www/coreerp/scripts/backup_mysql_example.sh >> /var/log/coreerp_backup.log 2>&1
```

See `scripts/backup_mysql_example.sh` for the script template. **Edit the placeholders before enabling the cron job.**

---

*Prepared as part of Phase 15A-15C — Backup & Deployment Preparation.*
