CresignSys Learn — Lesson 070

Written by

in

Build hosting-backup

We now have:

hosting-create
hosting-list
hosting-info
hosting-health
hosting-repair
hosting-ssl

The next essential component is backup.

A hosting platform without a reliable restore system is incomplete.

The target command:

sudo hosting-backup example.com

should protect:

Website files
+
Database
+
Site metadata
+
Configuration

1. Backup Architecture

The basic flow:

                hosting-backup
                      │
                      ▼
                Check website
                      │
                      ▼
               Create backup ID
                      │
          ┌───────────┴───────────┐
          ▼                       ▼
     WordPress files          MySQL database
          │                       │
          ▼                       ▼
      Compress                 Dump
          │                       │
          └───────────┬───────────┘
                      ▼
                Create manifest
                      │
                      ▼
                Verify backup
                      │
                      ▼
                  COMPLETE

2. What Must Be Backed Up?

For a WordPress website:

/storage/websites/example.com/

contains important files.

But the database is separate.

Therefore:

BACKUP
│
├── Files
│   ├── wp-content
│   ├── wp-config.php
│   ├── WordPress core
│   └── other site files
│
├── Database
│   └── MySQL dump
│
└── Metadata
    └── CHP configuration

3. Files Alone Are Not Enough

Suppose you back up only:

public/

You still don’t have:

wp_posts
wp_users
wp_options
wp_terms
...

Those are in MySQL.

So:

Files + Database

are both required for a meaningful WordPress backup.


4. Database Alone Is Not Enough

A database backup does not contain:

uploads
themes
plugins
WordPress core
custom PHP files

Therefore:

Database + Files

is the fundamental backup pair.


5. Recommended Backup Layout

Create:

/backup/cresignsys/

Then:

/backup/cresignsys/example.com/

and:

/backup/cresignsys/example.com/
└── 2026-08-13_160000/
    ├── files.tar.zst
    ├── database.sql.gz
    ├── site.conf
    └── manifest.json

6. Why Use a Timestamp?

Suppose you have:

2026-08-13_080000
2026-08-13_120000
2026-08-13_160000

You can restore a particular point in time.

This gives you:

Point-in-Time Backup Selection


7. Create Backup Configuration

Add to:

/etc/cresignsys/hosting.conf

something like:

BACKUP_BASE="/backup/cresignsys"

Then:

sudo mkdir -p /backup/cresignsys

8. Don’t Put Backups Under public

Never use:

/storage/websites/example.com/public/backups/

because a web server could potentially expose them.

Bad:

https://example.com/backups/database.sql

Good:

/backup/cresignsys/example.com/

outside the website document root.


9. Create hosting-backup

Create:

sudo nano /usr/local/bin/hosting-backup

Start:

#!/usr/bin/env bash

set -Eeuo pipefail

10. Require Root

if [[ "$EUID" -ne 0 ]]; then
    echo "ERROR: Run with sudo."
    exit 1
fi

11. Require Domain

if [[ $# -ne 1 ]]; then
    echo "Usage: hosting-backup DOMAIN"
    exit 1
fi

DOMAIN="$1"

12. Load Configuration

source /etc/cresignsys/hosting.conf

Then:

STATE_DIR="/var/lib/cresignsys/sites"
SITE_DIR="${STATE_DIR}/${DOMAIN}"
SITE_CONF="${SITE_DIR}/site.conf"

13. Verify Website Exists

if [[ ! -f "$SITE_CONF" ]]; then
    echo "ERROR: Site not found: $DOMAIN"
    exit 1
fi

Load:

source "$SITE_CONF"

Now we know:

DOMAIN
SITE_ID
SITE_USER
WEB_ROOT
DB_NAME
DB_USER

14. Generate Backup ID

BACKUP_ID="$(date '+%Y-%m-%d_%H%M%S')"

Then:

BACKUP_DIR="${BACKUP_BASE}/${DOMAIN}/${BACKUP_ID}"

Create:

mkdir -p "$BACKUP_DIR"

15. Example

For:

example.com

you get:

/backup/cresignsys/example.com/2026-08-13_160000/

16. Create Backup Manifest

The manifest describes the backup.

Example:

{
  "domain": "example.com",
  "site_id": "1027",
  "created_at": "2026-08-13T16:00:00",
  "database": "csp1027_wp",
  "status": "STARTED"
}

The final manifest should say:

status = COMPLETE

17. Why a Manifest?

Imagine you have:

200 backup files

You need to know:

Which website?
Which date?
Which database?
Which version?
Was it complete?

The manifest provides that information.


18. Backup the Site Configuration

Copy:

cp "$SITE_CONF" "$BACKUP_DIR/site.conf"

Remember:

Do not store database passwords in site.conf.

Therefore the backup doesn’t accidentally become a password archive.


19. Backup Website Files

A common approach is tar.

For example:

tar -C "$(dirname "$WEB_ROOT")" \
    -czf "$BACKUP_DIR/files.tar.gz" \
    "$(basename "$WEB_ROOT")"

This creates:

files.tar.gz

containing the website’s public files.


20. Why -C?

Instead of creating an archive containing:

/storage/websites/example.com/public/...

you can create a cleaner archive structure:

public/
    wp-admin/
    wp-content/
    wp-includes/

This makes restoration easier.


21. What About private and logs?

You need to decide what constitutes the site’s authoritative data.

For example:

site root
├── public
├── private
└── logs

You may want:

public       → backup
private      → backup
logs         → optional

Logs usually don’t need the same retention policy as customer data.


22. Recommended Initial Policy

For the first CHP version:

public      ✓
private     ✓
logs        optional

Later:

logs → separate operational retention

23. Database Backup

Use mysqldump or the appropriate MySQL logical backup tool.

For a basic WordPress database:

mysqldump \
    --single-transaction \
    --routines \
    --triggers \
    "$DB_NAME" \
    | gzip > "$BACKUP_DIR/database.sql.gz"

The exact options should match your MySQL version and backup requirements.


24. Why --single-transaction?

For transactional tables such as InnoDB, it can provide a consistent logical snapshot without locking the entire database for the duration of the dump.

This is generally preferable for active WordPress sites.


25. Database Credentials

The backup command needs database access.

Instead of exposing passwords on the command line, use a secure credentials mechanism.

For example, the MySQL client can use a protected configuration file or another secret-management approach.

Avoid:

mysqldump -u user -pPASSWORD ...

because command-line secrets can be exposed through process inspection or shell history in some environments.


26. Important Backup Principle

The backup system itself must not create a security problem.

Bad:

backup
 ↓
password exposed

Good:

backup
 ↓
protected credentials
 ↓
database dump

27. Compress Database Backup

The resulting file:

database.sql.gz

is much smaller than:

database.sql

For many WordPress databases this saves substantial storage.


28. File Compression

You can also use:

gzip

or:

zstd

For modern Linux systems, zstd is often attractive because of its speed and compression tradeoff.

For example:

files.tar.zst

could replace:

files.tar.gz

once your backup/restore tooling standardizes on it.


29. Don’t Mix Formats Randomly

Choose one platform standard.

For example:

Website files → tar.zst
Database → sql.gz

or:

Website files → tar.gz
Database → sql.gz

Consistency makes automation much easier.


30. Calculate Checksums

After creating:

files.tar.gz
database.sql.gz

calculate SHA-256:

sha256sum \
    "$BACKUP_DIR/files.tar.gz" \
    "$BACKUP_DIR/database.sql.gz"

Store the result:

checksums.sha256

31. Why Checksums?

Suppose:

backup created

but later:

disk corruption

The archive may still exist but be damaged.

Checksum:

original hash
       ↓
current hash
       ↓
compare

can detect corruption.


32. Verify the Backup

A backup isn’t complete merely because:

files.tar.gz exists

You should verify:

archive readable
database dump readable
checksum correct
manifest complete

33. Test the Archive

For gzip:

gzip -t "$BACKUP_DIR/database.sql.gz"

For tar:

tar -tzf "$BACKUP_DIR/files.tar.gz" >/dev/null

If using zstd, use the corresponding verification commands.


34. Test the Database Dump

At minimum:

zcat "$BACKUP_DIR/database.sql.gz" | head

should produce SQL content.

But don’t rely only on seeing text.

A stronger backup verification is:

restore dump to a temporary database
       ↓
run database checks

This is much more meaningful.


35. Backup Verification Levels

Level 1

file exists

Weak.

Level 2

checksum valid

Better.

Level 3

archive can be read

Better.

Level 4

database dump can be imported

Strong.

Level 5

full restore tested

Best.


36. The Most Important Backup Principle

A backup is not proven until restoration has been tested.

A 500 GB backup that cannot restore is not useful.


37. Create Manifest

A more complete manifest:

{
  "domain": "example.com",
  "site_id": "1027",
  "created_at": "2026-08-13T16:00:00",
  "database": "csp1027_wp",
  "files_archive": "files.tar.gz",
  "database_dump": "database.sql.gz",
  "status": "COMPLETE"
}

Add checksums separately.


38. File Size Information

Record:

files_size
database_size

For example:

{
  "files_size": 1452389120,
  "database_size": 28347120
}

This will later help with:

backup monitoring
storage planning
billing

39. Backup Status

The process should have states:

STARTED
  ↓
FILES_COMPLETE
  ↓
DATABASE_COMPLETE
  ↓
VERIFIED
  ↓
COMPLETE

Failure:

BACKUP_ERROR

40. Why State Matters

The control panel can display:

Last Backup:
2026-08-13 16:00

Status:
COMPLETE

instead of merely:

Backup folder exists

41. Backup Log

Create:

/var/log/cresignsys/backup.log

Example:

2026-08-13 16:00 example.com BACKUP_START
2026-08-13 16:01 example.com FILES_COMPLETE
2026-08-13 16:01 example.com DATABASE_COMPLETE
2026-08-13 16:01 example.com CHECKSUM_COMPLETE
2026-08-13 16:01 example.com VERIFY_COMPLETE
2026-08-13 16:01 example.com BACKUP_COMPLETE

42. Backup Lock

Backup should use the same per-site locking mechanism.

Why?

Avoid:

backup
+
repair
+
delete

running against the same site simultaneously.


43. Site Operation Lock

Eventually all operations should use:

/var/lock/cresignsys-example.com.lock

Operations:

hosting-create
hosting-repair
hosting-backup
hosting-restore
hosting-delete

should coordinate through this lock.


44. Backup While Website Is Online

You generally don’t want:

website
 ↓
STOP
 ↓
backup
 ↓
START

for every backup.

Instead:

website remains online
       ↓
consistent database snapshot
       +
filesystem archive

For larger/high-write systems, filesystem/database consistency becomes more complicated and may require snapshots or application-aware backup strategies.


45. WordPress Uploads

The largest directory in many WordPress sites is:

wp-content/uploads/

Therefore backup size may be dominated by:

images
videos
PDFs
documents

This should influence your storage and retention design.


46. Backup Retention

Suppose a site gets:

1 backup/day

for:

30 days

That’s:

30 backups

If each backup is 2 GB:

60 GB

for one site.

With 100 sites:

6 TB

Therefore retention must be designed carefully.


47. Retention Policy

A simple initial policy:

Daily:
7 backups

Weekly:
4 backups

Monthly:
3 backups

This is only an example policy.

Your actual retention should depend on:

storage
customer plan
business requirements
recovery objectives

48. Don’t Keep Infinite Backups

Bad:

backup
backup
backup
backup
...

Eventually:

DISK FULL

and then:

WordPress sites fail
MySQL fails
backups fail

A backup system can itself become an availability problem.


49. Backup Storage Separation

Eventually:

Server
  │
  ├── Websites
  │
  └── Local backup

is not enough.

If the entire server dies:

server
 ↓
websites lost
 ↓
local backups lost

Therefore use:

Off-Site Backup


50. 3-2-1 Backup Principle

A useful general strategy is:

3 copies
2 different storage media/systems
1 off-site copy

For example:

Primary server
     +
local backup storage
     +
off-site object storage

51. Local Backup

Advantages:

fast
cheap
quick restore

Disadvantages:

same server/storage failure

52. Remote Backup

Advantages:

survives server failure

Disadvantages:

network dependency
storage cost
transfer cost
credential management

53. Recommended CHP Architecture

                    BACKUP
                       │
          ┌────────────┴────────────┐
          ▼                         ▼
    Local Backup              Remote Backup
          │                         │
          ▼                         ▼
   Fast Restore             Disaster Recovery

54. Don’t Upload Plain Backup Files Without Protection

A remote backup may contain:

wp-config.php
database contents
customer uploads
customer information

Therefore remote backups should be protected with appropriate encryption and access controls.


55. Encryption

The ideal architecture:

Website
   ↓
Backup archive
   ↓
Encryption
   ↓
Remote storage

The storage provider should not necessarily have access to the plaintext backup contents.


56. Encryption Key Management

This introduces another problem:

Where is the encryption key?

If the key is stored:

on same server

and the server is compromised:

backup + key

may both be compromised.

Therefore key management needs separate consideration.


57. Backup Security

Treat backups as sensitive data.

Protect:

database dumps
wp-config.php
customer uploads
SSH keys
API credentials
SSL-related metadata

Never place them in:

public_html

or:

public/

58. hosting-backup Output

A successful command could show:

CresignSys Backup
=================

Domain: example.com
Backup ID: 2026-08-13_160000

[OK] Files archived
[OK] Database dumped
[OK] Checksums generated
[OK] Archive verified
[OK] Database dump verified
[OK] Manifest created

Files:
1.4 GB

Database:
28 MB

Status:
COMPLETE

59. Failed Backup

Example:

CresignSys Backup
=================

Domain: example.com

[OK] Files archived
[FAIL] Database dump

Status:
BACKUP_ERROR

Backup is NOT marked as complete.

Do not pretend that:

files backup exists

means:

website fully backed up

60. Backup Manifest Should Say Exactly What Happened

For example:

{
  "status": "ERROR",
  "files": "COMPLETE",
  "database": "FAILED"
}

This is much better than:

{
  "status": "COMPLETE"
}

when the database was missing.


61. Backup Listing

The next useful command will be:

sudo hosting-backup-list example.com

Output:

BACKUP ID                STATUS       SIZE
------------------------------------------------
2026-08-13_160000        COMPLETE     1.4G
2026-08-12_160000        COMPLETE     1.3G
2026-08-11_160000        COMPLETE     1.3G

This will feed directly into restore.


62. Restore Architecture

We are building toward:

hosting-backup
      ↓
backup repository
      ↓
hosting-restore

The restore operation should be:

select backup
      ↓
verify backup
      ↓
lock site
      ↓
backup current state
      ↓
restore files
      ↓
restore database
      ↓
verify
      ↓
health check

63. Never Restore Blindly

Suppose:

example.com

is currently working.

You select an old backup.

A safe restore should first create:

pre-restore backup

so that if the restore is wrong:

restore
 ↓
problem
 ↓
restore previous state

64. Disaster Recovery Model

Eventually:

CURRENT SITE
     │
     ▼
PRE-RESTORE BACKUP
     │
     ▼
RESTORE SELECTED BACKUP
     │
     ▼
HEALTH CHECK
     │
 ┌───┴────┐
 ▼        ▼
PASS     FAIL
 │        │
 ▼        ▼
ACTIVE   ROLLBACK

65. Backup + Repair

These systems now connect:

Health
  ↓
Problem
  ↓
Backup
  ↓
Repair
  ↓
Health

For risky repairs:

Backup
 ↓
Repair
 ↓
Verify

This gives administrators a safety net.


66. Backup + Delete

Eventually:

hosting-delete example.com

should not immediately destroy data.

A safer policy could be:

ACTIVE
 ↓
SUSPENDED
 ↓
FINAL BACKUP
 ↓
DELETED

with configurable retention.


67. Backup + Hosting Plans

Your hosting plans can eventually define:

Starter:
7-day backup retention

Business:
14-day retention

Professional:
30-day retention

Premium:
90-day retention

Again, these are example policies.


68. Backup + Billing

Your control panel can calculate:

Website storage
+
Backup storage

and eventually price backup storage separately if your hosting product requires it.


69. Backup + Monitoring

The dashboard can show:

Website              Last Backup        Status
------------------------------------------------
learn.cresignsys.com  2 hours ago        ✓
shop.cresignsys.com   1 day ago          ✓
example.com           5 days ago         !

This allows administrators to find sites that have quietly stopped backing up.


70. The Complete Data Protection Layer

We now have the architecture:

                    DATA PROTECTION
                          │
             ┌────────────┼────────────┐
             ▼            ▼            ▼
          Backup       Restore       Retention
             │            │            │
             ▼            ▼            ▼
          Local         Recovery     Cleanup
             │
             ▼
          Remote

71. Lesson 070 — Core Principle

A hosting backup system should guarantee three things:

1. Completeness

Files + Database + Metadata

2. Integrity

Checksum + Verification

3. Recoverability

Tested restoration

Therefore:

BACKUP
  ≠
FILES COPIED

Instead:

BACKUP
=
COPY
+
VERIFY
+
STORE
+
RECOVERABILITY

72. Current CresignSys Architecture

Your platform is now developing into:

                         CHP
                          │
      ┌───────────────────┼───────────────────┐
      ▼                   ▼                   ▼
 Provisioning        Observability        Data Protection
      │                   │                   │
      ▼                   ▼                   ▼
hosting-create      hosting-list         hosting-backup
                    hosting-info
                    hosting-health
      │
      ▼
hosting-repair
      │
      ▼
hosting-ssl
      │
      ▼
     SITE

The next major component is:

hosting-restore

because a backup that cannot be restored is not yet a complete recovery system.


Next Lesson — 071

Build hosting-restore

We will design:

sudo hosting-restore example.com BACKUP_ID

with:

Backup verification
        ↓
Current-site safety backup
        ↓
Site lock
        ↓
Maintenance mode
        ↓
Restore files
        ↓
Restore database
        ↓
Fix ownership
        ↓
Verify WordPress
        ↓
Verify Nginx/PHP
        ↓
Health check
        ↓
ACTIVE

and, most importantly, a rollback path if the restoration itself fails.

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *