CresignSys Learn — Lesson 078

Written by

in

Build the CHP Site Database

The filesystem model from the previous lessons works for a small number of websites:

/var/lib/cresignsys/sites/example.com/site.conf

But as CresignSys grows, we need structured information such as:

Which sites exist?
Which domains belong to each site?
Which PHP version does each site use?
Which backups exist?
When was the last operation?
What is the current state?
Which SSL certificate belongs to which domains?

A database is much better for this.


1. Important Architecture Decision

Do not use the customer WordPress databases for CHP metadata.

For example:

wordpress_example
wordpress_shop
wordpress_blog

are application databases.

CHP needs its own control-plane database:

cresignsys

So:

                    MySQL
                      │
        ┌─────────────┴─────────────┐
        ▼                           ▼
 CUSTOMER DATABASES            CHP DATABASE
        │                           │
        ▼                           ▼
 WordPress data              Hosting metadata

2. What CHP Database Stores

The CHP database should store:

sites
domains
services
backups
SSL certificates
operations

It should not store:

WordPress posts
WordPress users
WordPress media
customer application tables

Those remain in the site’s own database.


3. Database Architecture

The basic relationship:

                         sites
                           │
          ┌────────────────┼────────────────┐
          ▼                ▼                ▼
       domains          services          backups
          │
          ▼
    ssl_certificates

              operations
                   │
                   ▼
                sites

4. Database Choice

For the first CHP version, there are two reasonable choices:

SQLite

/var/lib/cresignsys/chp.db

Advantages:

  • Very simple
  • No additional database server
  • Excellent for local control-plane metadata
  • Easy backup
  • Easy deployment

MySQL

cresignsys database

Advantages:

  • Familiar in your current server environment
  • Better for future multi-node/control-panel architecture
  • Easier integration if the eventual platform becomes distributed

For your current single-server CHP, I recommend starting with SQLite for CHP metadata, while keeping customer WordPress databases in MySQL.

The architecture can later move to MySQL/PostgreSQL without changing the conceptual data model.


5. Install SQLite

Check:

sqlite3 --version

If unavailable:

sudo apt update
sudo apt install sqlite3

Check:

sqlite3 --version

6. Create CHP Database Directory

sudo mkdir -p /var/lib/cresignsys

Create:

sudo touch /var/lib/cresignsys/chp.db

Set permissions:

sudo chown root:root /var/lib/cresignsys/chp.db
sudo chmod 640 /var/lib/cresignsys/chp.db

7. Database Configuration

Update:

sudo nano /etc/cresignsys/hosting.conf

Add:

CHP_DB="/var/lib/cresignsys/chp.db"

So the configuration becomes:

CHP_ROOT="/etc/cresignsys"

SITE_STATE_ROOT="/var/lib/cresignsys/sites"

CHP_DB="/var/lib/cresignsys/chp.db"

LOG_ROOT="/var/log/cresignsys"

LOCK_ROOT="/var/lock/cresignsys"

WEB_ROOT="/storage/websites"

BACKUP_ROOT="/backup/cresignsys"

SERVER_IPV4="YOUR_SERVER_IPV4"

SERVER_IPV6=""

DEFAULT_PHP_VERSION="8.3"

8. Create Database Library

Create:

sudo nano /etc/cresignsys/lib/database.sh

The library will eventually contain:

db_init
db_query
db_exec
db_transaction
db_site_exists
db_get_site
db_add_site
db_update_site

9. Basic Database Function

Start with:

db_exec() {
    sqlite3 "$CHP_DB" "$1"
}

Then:

db_exec "SELECT name FROM sqlite_master;"

will query the database.


10. Don’t Build SQL by Concatenating User Input

Avoid:

sqlite3 "$CHP_DB" "SELECT * FROM sites WHERE domain='$DOMAIN'"

if:

DOMAIN

comes directly from a user.

Instead, use SQLite’s parameter binding through a safer interface or strictly validated values.

For the first internal scripts, domain validation provides an additional safety layer, but the database layer should still be designed for parameterized queries.


11. Create the sites Table

The first table:

CREATE TABLE sites (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    primary_domain TEXT NOT NULL UNIQUE,
    web_root TEXT NOT NULL,
    php_version TEXT NOT NULL,
    site_user TEXT NOT NULL,
    service_state TEXT NOT NULL DEFAULT 'PROVISIONING',
    health_state TEXT NOT NULL DEFAULT 'UNKNOWN',
    created_at TEXT NOT NULL,
    updated_at TEXT NOT NULL
);

12. Why id?

Don’t use:

example.com

as the internal primary key.

Use:

id = 1

Then:

1 → example.com

This makes relationships much cleaner.


13. Example

sites

id | primary_domain | web_root | php_version | state
-----------------------------------------------------
1  | example.com   | ...      | 8.3         | ACTIVE
2  | shop.com      | ...      | 8.3         | ACTIVE

14. Why Keep primary_domain?

Even though domains have their own table, keeping:

sites.primary_domain

is useful for fast access and clear site identity.

However, the database must ensure it doesn’t contradict the domain table.

Later we can refine this relationship.


15. Create the domains Table

CREATE TABLE domains (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    site_id INTEGER NOT NULL,
    domain TEXT NOT NULL UNIQUE,
    domain_type TEXT NOT NULL,
    redirect_target TEXT,
    dns_state TEXT NOT NULL DEFAULT 'PENDING',
    ssl_state TEXT NOT NULL DEFAULT 'PENDING',
    created_at TEXT NOT NULL,
    updated_at TEXT NOT NULL,

    FOREIGN KEY (site_id)
        REFERENCES sites(id)
        ON DELETE CASCADE
);

16. Domain Types

Use:

PRIMARY
ALIAS
REDIRECT

For example:

example.com       PRIMARY
www.example.com   ALIAS
old-example.com   REDIRECT

17. Domain Relationship

The database now represents:

SITE 1
 │
 ├── example.com
 ├── www.example.com
 └── old-example.com

instead of storing:

DOMAIN_LIST="example.com www.example.com old-example.com"

inside a text field.

This is much better.


18. services Table

Create:

CREATE TABLE services (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    site_id INTEGER NOT NULL,
    service_name TEXT NOT NULL,
    status TEXT NOT NULL,
    version TEXT,
    socket_path TEXT,
    updated_at TEXT NOT NULL,

    FOREIGN KEY (site_id)
        REFERENCES sites(id)
        ON DELETE CASCADE
);

19. What Services Can Represent?

Examples:

NGINX
PHP_FPM
MYSQL
WORDPRESS

For example:

site_id | service_name | status
--------------------------------
1       | NGINX        | OK
1       | PHP_FPM      | OK
1       | MYSQL        | OK
1       | WORDPRESS    | OK

20. Don’t Confuse Service State With Site State

For example:

site:
ACTIVE

while:

PHP_FPM:
FAIL

is possible.

Therefore:

site state

and:

service health

must remain separate.


21. backups Table

Create:

CREATE TABLE backups (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    site_id INTEGER NOT NULL,
    backup_path TEXT NOT NULL,
    backup_type TEXT NOT NULL,
    size_bytes INTEGER,
    status TEXT NOT NULL,
    checksum TEXT,
    created_at TEXT NOT NULL,
    verified_at TEXT,

    FOREIGN KEY (site_id)
        REFERENCES sites(id)
        ON DELETE CASCADE
);

22. Backup Types

For example:

DAILY
WEEKLY
MONTHLY
MANUAL
PRE_RESTORE
PRE_UPDATE

This gives the system much more information than simply having files in a directory.


23. Backup Status

Use:

CREATED
VERIFIED
FAILED
DELETED

Example:

backup #102
status = VERIFIED

24. ssl_certificates Table

Create:

CREATE TABLE ssl_certificates (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    site_id INTEGER NOT NULL,
    certificate_path TEXT,
    private_key_path TEXT,
    issuer TEXT,
    expires_at TEXT,
    status TEXT NOT NULL,
    last_renewed_at TEXT,
    created_at TEXT NOT NULL,
    updated_at TEXT NOT NULL,

    FOREIGN KEY (site_id)
        REFERENCES sites(id)
        ON DELETE CASCADE
);

25. Certificate-Domain Relationship

One certificate can cover:

example.com
www.example.com

So eventually a many-to-many relationship may be useful.

Create:

CREATE TABLE certificate_domains (
    certificate_id INTEGER NOT NULL,
    domain_id INTEGER NOT NULL,

    PRIMARY KEY (certificate_id, domain_id),

    FOREIGN KEY (certificate_id)
        REFERENCES ssl_certificates(id)
        ON DELETE CASCADE,

    FOREIGN KEY (domain_id)
        REFERENCES domains(id)
        ON DELETE CASCADE
);

26. Why Separate This?

Suppose:

Certificate #1

covers:

example.com
www.example.com

Then:

certificate_domains

certificate_id | domain_id
--------------------------
1              | 1
1              | 2

This accurately represents the relationship.


27. operations Table

This will become extremely useful.

CREATE TABLE operations (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    site_id INTEGER,
    operation TEXT NOT NULL,
    status TEXT NOT NULL,
    message TEXT,
    started_at TEXT NOT NULL,
    finished_at TEXT,

    FOREIGN KEY (site_id)
        REFERENCES sites(id)
        ON DELETE SET NULL
);

28. Example Operations

CREATE
DELETE
SUSPEND
UNSUSPEND
BACKUP
RESTORE
REPAIR
DOMAIN_ADD
DOMAIN_REMOVE
SSL_ISSUE
SSL_RENEW

29. Why Operations Matter

Suppose:

hosting-restore example.com 102

fails.

The database can record:

operation:
RESTORE

status:
FAILED

message:
Database restore failed

started:
19:20

finished:
19:24

Now the control panel has a history.


30. Complete Database Model

                         SITES
                           │
          ┌────────────────┼─────────────────┐
          │                │                 │
          ▼                ▼                 ▼
       DOMAINS          SERVICES          BACKUPS
          │
          ▼
   CERTIFICATE_DOMAINS
          │
          ▼
   SSL_CERTIFICATES

              OPERATIONS
                   │
                   ▼
                 SITES

31. Create the Schema File

Create:

sudo mkdir -p /etc/cresignsys/schema

Then:

sudo nano /etc/cresignsys/schema/001_initial.sql

Put all initial CREATE TABLE statements there.

This is better than putting SQL directly inside the Bash scripts.


32. Schema Versioning

Later:

schema/
├── 001_initial.sql
├── 002_add_site_limits.sql
├── 003_add_users.sql
├── 004_add_dns_records.sql

This allows controlled database upgrades.


33. Migration Table

Create:

CREATE TABLE schema_migrations (
    version INTEGER PRIMARY KEY,
    filename TEXT NOT NULL,
    applied_at TEXT NOT NULL
);

Then CHP knows:

Current schema:
4

and can determine whether migrations are needed.


34. Why Migrations Matter

Imagine version 1 has:

sites

Later you add:

storage_limit

You don’t want to manually recreate the entire database.

Instead:

001
 ↓
002
 ↓
003
 ↓
004

updates the existing installation.


35. Create hosting-db-init

Create:

sudo nano /usr/local/bin/hosting-db-init

The command should:

1. Check SQLite
2. Create database
3. Apply schema
4. Record migration
5. Verify tables

36. Expected Output

CresignSys Database Initialization
==================================

Database:
 /var/lib/cresignsys/chp.db

[OK] SQLite available
[OK] Database created
[OK] Schema 001 applied
[OK] Sites table
[OK] Domains table
[OK] Services table
[OK] Backups table
[OK] SSL table
[OK] Operations table

Database:
READY

37. Verify Manually

Run:

sqlite3 /var/lib/cresignsys/chp.db

Then:

.tables

Expected:

backups
certificate_domains
domains
operations
schema_migrations
services
sites
ssl_certificates

Exit:

.quit

38. Add Indexes

As the database grows, indexes become important.

For domains:

CREATE INDEX idx_domains_site_id
ON domains(site_id);

For services:

CREATE INDEX idx_services_site_id
ON services(site_id);

For backups:

CREATE INDEX idx_backups_site_id
ON backups(site_id);

For operations:

CREATE INDEX idx_operations_site_id
ON operations(site_id);

39. Domain Lookup

Because:

domain TEXT UNIQUE

we can quickly find:

example.com

and determine:

site_id = 1

This becomes the foundation of nearly every CHP command.


40. Site Lookup Flow

When the user runs:

hosting-info example.com

the flow becomes:

example.com
     │
     ▼
domains table
     │
     ▼
site_id = 1
     │
     ▼
sites table
     │
     ├── web root
     ├── PHP version
     ├── state
     └── health

41. Why Domain Should Be the User-Facing Identifier

Users naturally know:

example.com

not:

site_id=17

Therefore commands should continue to accept:

hosting-info example.com

while internally using:

site_id

42. Site ID Should Be Internal

Use:

site_id=17

for:

foreign keys
database relationships
internal operations

but not as the primary customer-facing interface.


43. Add Site

A future hosting-create workflow:

hosting-create example.com
       │
       ▼
Validate domain
       │
       ▼
Create filesystem
       │
       ▼
Create database record
       │
       ▼
Create domain record
       │
       ▼
Create service records
       │
       ▼
Generate Nginx

44. Database Transaction

This is where transactions become important.

Suppose:

filesystem created
database record created
domain record failed

Now the system is inconsistent.

A transaction helps with the database portion:

BEGIN
   create site
   create domain
   create services
COMMIT

If a database operation fails:

ROLLBACK

45. But Transactions Don’t Roll Back Filesystem Changes

This is important.

A database transaction cannot undo:

mkdir /storage/websites/example.com

Therefore the full operation needs a compensation strategy:

DATABASE TRANSACTION
+
FILESYSTEM ROLLBACK

46. Provisioning Pattern

Use:

PREPARE
   ↓
FILESYSTEM CREATE
   ↓
DATABASE TRANSACTION
   ↓
CONFIG GENERATION
   ↓
VALIDATE
   ↓
COMMIT OPERATION

If something fails:

ROLLBACK DATABASE
ROLLBACK FILESYSTEM
REMOVE TEMP CONFIG

where safe.


47. Don’t Delete Customer Data Automatically After Every Failure

Rollback must be carefully classified.

For a brand-new site:

creation failed

removing the newly created empty directory may be safe.

For an existing site:

repair failed

automatically deleting the website would be dangerous.

Therefore:

CREATE

and:

REPAIR

need different rollback policies.


48. Database and Existing Sites

You already have websites created under:

/storage/websites/

Don’t immediately migrate everything destructively.

Use:

DISCOVER
   ↓
IMPORT
   ↓
VERIFY
   ↓
ACTIVATE DATABASE MANAGEMENT

49. Build hosting-db-import

Eventually:

sudo hosting-db-import example.com

will inspect the existing site:

/storage/websites/example.com

and create corresponding database records.


50. Import Example

Existing:

/storage/websites/example.com/public

CHP discovers:

domain:
example.com

web root:
/storage/websites/example.com/public

PHP:
8.3

Nginx:
exists

WordPress:
installed

Then creates:

site_id = 1

51. Import Must Be Idempotent

If you run:

hosting-db-import example.com

twice, it should not create:

site 1
site 2

for the same site.

It should say:

Site already imported.

or:

Site already exists.

52. Database Becomes Source of Truth

After successful migration:

CHP DATABASE

should become authoritative for:

site identity
domain relationships
service metadata
backup inventory
SSL metadata
operation history

Filesystem remains authoritative for:

actual website files

53. Two Different Kinds of Truth

This distinction is critical.

Control-plane truth

Database

knows:

What should exist?

Data-plane truth

Filesystem/Nginx/PHP/MySQL

knows:

What actually exists and is running?

54. Reconciliation

This leads to an important future feature:

hosting-reconcile example.com

It compares:

DATABASE
      VS
ACTUAL SERVER

55. Example Reconciliation

Database says:

PHP_VERSION=8.3

Actual Nginx configuration says:

PHP 8.2

Then:

DRIFT DETECTED

56. Another Example

Database says:

www.example.com

belongs to:

site_id=1

but Nginx configuration doesn’t contain it.

Result:

CONFIGURATION DRIFT

57. Another Example

Database says:

SSL=ACTIVE

but certificate is expired.

Result:

STATE DRIFT

The platform can then recommend:

hosting-ssl example.com

58. Database Status vs Actual Health

Never assume:

database.status = truth

for runtime health.

For example:

DB metadata:
PHP_FPM = OK

but the process may have crashed.

So:

DATABASE

stores the expected/configured state.

Runtime checks determine:

ACTUAL HEALTH

59. This Creates a Powerful Model

                    CHP DATABASE
                         │
                  DESIRED STATE
                         │
                         ▼
                   RECONCILIATION
                         │
                         ▼
                   ACTUAL SERVER
                         │
                         ▼
                    HEALTH CHECK

This is similar to how larger infrastructure-management systems work.


60. hosting-info

After the database migration, the command can become:

hosting-info example.com

Output:

CresignSys Site Information
===========================

Site ID:
1

Primary Domain:
example.com

Web Root:
/storage/websites/example.com/public

PHP:
8.3

Service State:
ACTIVE

Health:
HEALTHY

Domains:
  example.com
  www.example.com

Backups:
  12

SSL:
  ACTIVE

Created:
2026-08-13 19:00:00

61. hosting-list

Instead of scanning directories:

ls /storage/websites

it can query:

SELECT ...
FROM sites
ORDER BY primary_domain;

Then display:

DOMAIN                  STATE       HEALTH
------------------------------------------------
example.com             ACTIVE      HEALTHY
shop.example.com        ACTIVE      HEALTHY
medical.example.com     SUSPENDED   HEALTHY

62. hosting-domain-list

Query:

SELECT domain, domain_type, dns_state, ssl_state
FROM domains
WHERE site_id = ?;

Output:

DOMAIN                 TYPE       DNS       SSL
------------------------------------------------
example.com             PRIMARY    CORRECT   ACTIVE
www.example.com         ALIAS      CORRECT   ACTIVE
old.example.com         REDIRECT   CORRECT   ACTIVE

63. hosting-backup-list

Query:

SELECT id, backup_type, size_bytes, status, created_at
FROM backups
WHERE site_id = ?
ORDER BY created_at DESC;

Output:

ID    TYPE       STATUS      DATE
-----------------------------------------
102   DAILY      VERIFIED    Aug 13
101   DAILY      VERIFIED    Aug 12
100   WEEKLY     VERIFIED    Aug 11

64. hosting-site-status

This command now has two information sources:

DATABASE
   +
LIVE CHECKS

For example:

Configured PHP:
8.3

Actual PHP:
8.3

Result:
OK

65. Database as Control Plane

The complete model becomes:

                 CHP CONTROL PLANE
                        │
                        ▼
                 SQLite Database
                        │
       ┌────────────────┼────────────────┐
       ▼                ▼                ▼
     Sites           Domains          Backups
       │                │                │
       ▼                ▼                ▼
   Services            SSL           Operations
                        │
                        ▼
                 DESIRED STATE
                        │
                        ▼
                  SERVER ENGINE

66. Customer Data Plane

                    DATA PLANE
                        │
         ┌──────────────┼──────────────┐
         ▼              ▼              ▼
     WordPress        MySQL          Uploads
         │              │              │
         └──────────────┼──────────────┘
                        ▼
                  Website Traffic

67. Why This Separation Is Powerful

If the CHP database becomes corrupted:

customer website files

can still exist.

If a WordPress database breaks:

CHP database

can still know:

site exists
domain exists
backup exists
PHP version
service state

This separation improves recovery.


68. CHP Database Backup

Because the CHP database is now critical, back it up.

For SQLite:

sqlite3 /var/lib/cresignsys/chp.db \
    ".backup '/backup/cresignsys/chp.db'"

Do this regularly.


69. Don’t Store Backups Only Inside the Same Disk

If:

/storage

and:

/backup

are on the same physical disk and that disk fails, both can disappear.

Eventually use:

LOCAL BACKUP
+
REMOTE BACKUP

for important hosting data.


70. CHP Database Restore

You should eventually have:

hosting-db-backup
hosting-db-verify
hosting-db-restore

But these are infrastructure-level commands and should be protected carefully.


71. Database Locking

SQLite handles concurrent access well for many control-plane workloads, but writes still need coordination.

Your existing CHP operation lock remains useful:

SITE LOCK

For global database migrations:

GLOBAL CHP LOCK

72. Two Lock Levels

Use:

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

for site operations.

And:

/var/lock/cresignsys/chp-global.lock

for:

schema migration
database restore
global configuration changes

73. Never Run Schema Migration During Normal Operations

Don’t let:

hosting-site-status

automatically modify the schema.

Database schema changes should be explicit:

sudo hosting-db-migrate

74. Database Migration Command

Create:

sudo nano /usr/local/bin/hosting-db-migrate

Its workflow:

Check root
   ↓
Acquire global lock
   ↓
Read current schema
   ↓
Find pending migrations
   ↓
Apply transaction
   ↓
Record migration
   ↓
Verify
   ↓
Release lock

75. Migration Output

CresignSys Database Migration
=============================

Current schema:
1

Available schema:
4

Applying:
002_add_site_limits.sql
[OK]

Applying:
003_add_dns_records.sql
[OK]

Applying:
004_add_users.sql
[OK]

Database:
UP TO DATE

76. Future Site Limits

The database can later support:

storage_limit
bandwidth_limit
database_limit
domain_limit
backup_limit

Example:

sites
-----------------------------------------
storage_limit_mb = 10240
domain_limit = 10
backup_retention_days = 30

This becomes the foundation for hosting plans.


77. Hosting Plans

Eventually:

plans
-----
Starter
Business
Professional
Multi-Domain

and:

site_plans
----------
site_id
plan_id

Then CHP can enforce:

maximum storage
maximum domains
maximum databases
maximum backups

This connects directly to your future reseller/hosting business architecture.


78. Future Customer Accounts

Later:

customers
    │
    ▼
sites

Example:

Customer
   │
   ├── example.com
   ├── shop.example.com
   └── blog.example.com

This is the foundation for a real hosting control panel.


79. Future Users

Eventually:

customers
users
sites
domains

can support:

Administrator
Reseller
Customer
Developer
Support

with different permissions.

But don’t implement this yet.


80. Current Database Scope

For now keep it to:

sites
domains
services
backups
ssl_certificates
certificate_domains
operations
schema_migrations

That is enough for the current platform.


81. Recommended Schema

The initial CHP schema should therefore look like:

sites
├── id
├── primary_domain
├── web_root
├── php_version
├── site_user
├── service_state
├── health_state
├── created_at
└── updated_at

domains
├── id
├── site_id
├── domain
├── domain_type
├── redirect_target
├── dns_state
├── ssl_state
├── created_at
└── updated_at

services
├── id
├── site_id
├── service_name
├── status
├── version
├── socket_path
└── updated_at

backups
├── id
├── site_id
├── backup_path
├── backup_type
├── size_bytes
├── status
├── checksum
├── created_at
└── verified_at

ssl_certificates
├── id
├── site_id
├── certificate_path
├── private_key_path
├── issuer
├── expires_at
├── status
└── timestamps

operations
├── id
├── site_id
├── operation
├── status
├── message
├── started_at
└── finished_at

82. Migration Strategy

Do not immediately delete:

/var/lib/cresignsys/sites/

The migration should be:

OLD FILESYSTEM STATE
        │
        ▼
DISCOVER
        │
        ▼
IMPORT INTO DATABASE
        │
        ▼
VERIFY
        │
        ▼
DATABASE BECOMES AUTHORITATIVE
        │
        ▼
OLD STATE KEPT AS FALLBACK

Only remove the old state after successful verification.


83. First Database Command Set

We now add:

hosting-db-init
hosting-db-migrate
hosting-db-backup
hosting-db-verify
hosting-db-import

Eventually:

hosting-db-restore

84. Updated CHP Command Architecture

SYSTEM
│
├── Database
│   ├── hosting-db-init
│   ├── hosting-db-migrate
│   ├── hosting-db-backup
│   ├── hosting-db-verify
│   └── hosting-db-import
│
├── Sites
│   ├── hosting-create
│   ├── hosting-list
│   ├── hosting-info
│   ├── hosting-site-status
│   └── hosting-health
│
├── Domains
│   ├── hosting-domain-add
│   ├── hosting-domain-list
│   └── hosting-domain-remove
│
├── DNS
│   └── hosting-dns-check
│
├── SSL
│   └── hosting-ssl
│
├── Backup
│   ├── hosting-backup
│   ├── hosting-backup-list
│   ├── hosting-backup-verify
│   ├── hosting-backup-prune
│   └── hosting-restore
│
└── Service
    ├── hosting-suspend
    ├── hosting-unsuspend
    └── hosting-repair

85. Lesson 078 — Core Principle

We now have a clear distinction:

                    CRESIGNSYS
                         │
             ┌───────────┴───────────┐
             ▼                       ▼
       CONTROL PLANE             DATA PLANE
             │                       │
             ▼                       ▼
       CHP Database             Website Files
             │                   WordPress
             │                   MySQL
             │                   Uploads
             ▼
       Desired State
             │
             ▼
       CHP Engine
             │
             ▼
       Nginx / PHP / SSL

The database is the control plane.

The website files and application databases remain the data plane.

That separation is what allows CresignSys to eventually become a proper hosting-management platform rather than a collection of shell scripts.


Next Lesson — 079

Migrate Existing Websites Into the CHP Database

The next step should be practical because your server already contains websites.

We will build:

sudo hosting-db-import example.com

which will inspect an existing website and discover:

Domain
Web root
Linux owner
PHP version
PHP-FPM socket
Nginx configuration
WordPress installation
WordPress database
Database name
SSL status
Backup configuration

Then it will create the corresponding:

sites
domains
services
ssl_certificates

records without modifying the existing website.

The migration principle will be:

EXISTING WEBSITE
       ↓
READ ONLY DISCOVERY
       ↓
CHP DATABASE
       ↓
VERIFY
       ↓
CHP MANAGEMENT

This is the safest way to bring your existing /storage/websites/... installations under CHP management.

Comments

Leave a Reply

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