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.
Leave a Reply