CresignSys Learn — Lesson 074

Written by

in

Build hosting-domain

We now need a proper domain management layer.

Until now, we treated:

example.com

as if one domain always equals one website.

A real hosting platform needs more flexibility:

example.com
www.example.com
blog.example.com
shop.example.com

may all have different relationships to the same site.


1. Domain Architecture

The relationship should become:

                         SITE
                          │
            ┌─────────────┼─────────────┐
            ▼             ▼             ▼
        Primary         Alias        Redirect
         Domain         Domain        Domain
            │             │             │
            └─────────────┼─────────────┘
                          ▼
                        Nginx
                          │
                     ┌────┴────┐
                     ▼         ▼
                   HTTP       HTTPS
                               │
                               ▼
                              SSL

2. Why Separate Domain From Site?

Consider:

example.com
www.example.com

Both may point to the same WordPress installation:

/storage/websites/example.com/public

Therefore:

SITE
 └── example.com
      ├── example.com
      └── www.example.com

The second name is an alias, not another website.


3. Domain Types

Use three basic types.

Primary

example.com

The canonical domain.

Alias

www.example.com

Another hostname serving the same site.

Redirect

old-example.com

which redirects to:

example.com

4. Commands

The first version:

sudo hosting-domain-add example.com
sudo hosting-domain-add www.example.com --alias example.com
sudo hosting-domain-add old-example.com --redirect example.com

List:

sudo hosting-domain-list example.com

Remove:

sudo hosting-domain-remove www.example.com

5. Primary Domain

When creating a site:

sudo hosting-create example.com

the initial domain becomes:

TYPE=PRIMARY

Example metadata:

SITE_ID=1027
PRIMARY_DOMAIN=example.com

6. Domain Registry

Create:

/var/lib/cresignsys/domains/

For example:

/var/lib/cresignsys/domains/example.com

But rather than making the domain directory itself the only source of truth, maintain a structured registry.

For the first version:

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

can contain the domain relationships.


7. Better Site Metadata

Example:

SITE_ID=1027
PRIMARY_DOMAIN=example.com
DOMAIN_LIST="example.com www.example.com"

But space-separated lists become fragile.

A better long-term approach is a database.


8. Domain Database Model

Eventually:

sites
-----
id
primary_domain
status

domains
-------
id
site_id
domain
type
target
status

Example:

sites
------------------------------------------------
1027 | example.com | ACTIVE

domains
------------------------------------------------
1 | 1027 | example.com     | PRIMARY  | -
2 | 1027 | www.example.com | ALIAS    | -
3 | 1027 | old-example.com | REDIRECT | example.com

This is much easier to manage.


9. Domain Validation

Before adding:

example.com

validate the hostname.

Reject:

https://example.com

because that is a URL, not a hostname.

Reject:

example.com/path

Reject:

example.com:443

The domain field should contain a valid hostname.


10. Normalize the Domain

Convert:

Example.COM

to:

example.com

DNS names are case-insensitive.

Normalization prevents duplicate entries such as:

example.com
Example.com
EXAMPLE.COM

11. Validate Labels

A domain contains labels:

www
example
com

Each label has restrictions.

For basic hosting:

letters
numbers
hyphen

should be handled.

Don’t accept arbitrary characters into Nginx configuration.


12. Security Principle

Never directly insert unvalidated user input into:

Nginx configuration
shell commands
filesystem paths
SQL

For example, don’t construct:

rm -rf "/storage/websites/$DOMAIN"

without strict domain validation.


13. Check Existing Domain

Before adding:

sudo hosting-domain-add example.com

check whether it already belongs to:

same site
different site
system configuration

Possible result:

Domain already belongs to example.com

or:

ERROR:
example.com belongs to another site.

Never silently reassign it.


14. Primary Domain Rules

Each site should have exactly one:

PRIMARY

For example:

example.com → PRIMARY
www.example.com → ALIAS

You shouldn’t have:

example.com → PRIMARY
shop.com → PRIMARY

inside the same site.

If the user wants to change the primary domain, that should be a separate controlled operation.


15. Alias

Add:

sudo hosting-domain-add www.example.com --alias example.com

The result:

example.com
   │
   └── www.example.com

Both can serve the same application.


16. Alias and Canonical Domain

You must decide whether an alias:

Option A

Serves the same content:

www.example.com
       ↓
same WordPress

or:

Option B

Redirects:

www.example.com
       ↓
301
       ↓
example.com

For WordPress, canonical-domain redirects are often preferable because they avoid duplicate hostname access.


17. Recommended Model

Separate:

ALIAS

from:

REDIRECT

So:

www.example.com → ALIAS

means:

same site

while:

old-example.com → REDIRECT → example.com

means:

different hostname
     ↓
301 redirect

18. Nginx Server Name

For an alias, Nginx can use:

server_name example.com www.example.com;

This means one server block handles both names.


19. Redirect Domain

For a redirect:

server {
    server_name old-example.com;

    return 301 https://example.com$request_uri;
}

The redirect domain doesn’t need its own WordPress installation.


20. SSL Implications

This is extremely important.

If:

example.com
www.example.com

both serve HTTPS, the certificate needs to cover both names.

Therefore SSL should understand:

PRIMARY
+
ALIASES

21. Certificate Names

For example:

example.com
www.example.com

can be included in the same certificate.

Then:

hosting-ssl example.com

should eventually inspect all active domain names attached to the site.


22. Adding an Alias After SSL

Suppose:

example.com

already has SSL.

Then:

hosting-domain-add www.example.com --alias example.com

creates a new requirement:

certificate currently:
example.com

required:
example.com
www.example.com

Therefore the platform should mark:

SSL_STATE=RENEWAL_REQUIRED

or:

SSL_STATE=NEEDS_UPDATE

until the certificate is updated.


23. Don’t Automatically Break HTTPS

If you modify:

server_name

before updating SSL, you could create:

www.example.com
      ↓
HTTPS
      ↓
certificate mismatch

Therefore domain addition and SSL update must be coordinated.


24. Domain Addition Workflow

For an alias:

hosting-domain-add
        │
        ▼
Validate domain
        │
        ▼
Check uniqueness
        │
        ▼
Register domain
        │
        ▼
Generate Nginx config
        │
        ▼
nginx -t
        │
        ▼
Reload
        │
        ▼
Update SSL requirement

25. DNS Is Not Automatically Controlled

Adding a domain to CHP does not necessarily create DNS records.

These are separate layers:

Domain Registration
        ↓
DNS
        ↓
CHP Domain Registry
        ↓
Nginx
        ↓
SSL

If your platform doesn’t operate authoritative DNS, it should tell the administrator what DNS record is required.


26. DNS Requirement Output

For:

www.example.com

show:

Required DNS:

Type: A
Name: www
Value: YOUR_SERVER_IP

If IPv6 is supported:

Type: AAAA
Name: www
Value: YOUR_IPV6

27. Don’t Assume DNS Is Ready

After adding:

www.example.com

the system should be able to say:

DNS:
PENDING

rather than:

ACTIVE

28. Domain State

Each domain can have:

PENDING_DNS
ACTIVE
SUSPENDED
ERROR
REMOVED

For example:

example.com
    DNS=ACTIVE

www.example.com
    DNS=PENDING

29. Domain Health

Eventually:

hosting-domain-list example.com

can show:

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

30. Create hosting-domain-add

Create:

sudo nano /usr/local/bin/hosting-domain-add

Basic structure:

#!/usr/bin/env bash

set -Eeuo pipefail

Require root:

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

31. Parse Arguments

Basic syntax:

hosting-domain-add DOMAIN

or:

hosting-domain-add DOMAIN --alias TARGET

or:

hosting-domain-add DOMAIN --redirect TARGET

For example:

www.example.com --alias example.com

means:

DOMAIN=www.example.com
TARGET=example.com
TYPE=ALIAS

32. Validate Target

For:

hosting-domain-add www.example.com --alias example.com

verify:

example.com

exists as a CHP site.

Otherwise:

ERROR:
Target site does not exist.

33. Redirect Validation

For:

hosting-domain-add old-example.com --redirect example.com

check:

old-example.com != example.com

and:

target exists

Also avoid redirect loops.


34. Redirect Loop Example

Don’t allow:

old.example.com → example.com
example.com → old.example.com

or:

A → B
B → C
C → A

Your domain registry should detect cycles.


35. Redirect Chain

Prefer:

old.example.com
       ↓
example.com

not:

old.example.com
       ↓
www.example.com
       ↓
example.com

Long redirect chains increase latency and complicate SEO/application behavior.


36. Domain Database Constraints

When you implement the database version, enforce:

domain UNIQUE

This prevents:

example.com → site 1
example.com → site 2

from existing simultaneously.


37. Domain Ownership

A domain can only belong to one site.

Example:

example.com
   ↓
SITE 1027

Another site cannot claim:

example.com

unless the domain is explicitly removed/reassigned.


38. Reassignment

Changing:

example.com
SITE A

to:

example.com
SITE B

should be a separate operation:

hosting-domain-move example.com SITE_B

It should not happen implicitly.


39. Why Move Is Dangerous

Moving a domain changes:

Nginx
SSL
WordPress canonical URL
DNS expectations
traffic routing

Therefore it deserves its own controlled workflow.


40. hosting-domain-list

Create:

sudo nano /usr/local/bin/hosting-domain-list

Expected:

CresignSys Domains
==================

Site: example.com

DOMAIN                TYPE       STATUS
------------------------------------------------
example.com            PRIMARY    ACTIVE
www.example.com        ALIAS      ACTIVE
old-example.com        REDIRECT   ACTIVE

41. hosting-domain-remove

This command must be conservative.

For:

hosting-domain-remove www.example.com

remove:

domain registry entry
Nginx hostname
SSL hostname requirement

but do not remove:

website files
database
site itself

42. Never Allow Primary Removal Without Replacement

Suppose:

example.com → PRIMARY

and the user runs:

hosting-domain-remove example.com

Don’t allow it unless:

another domain

is promoted to primary.

Otherwise:

SITE
 ↓
NO PRIMARY DOMAIN

which breaks the site’s identity.


43. Primary Domain Change

A future command:

hosting-domain-primary example.com www.example.com

could change:

OLD:
example.com → PRIMARY
www.example.com → ALIAS

NEW:
www.example.com → PRIMARY
example.com → ALIAS

But this should also update WordPress URLs when appropriate.


44. Domain + WordPress

Changing the primary domain may require:

siteurl
home
canonical URLs
redirects
media URLs
SSL
Nginx

Therefore domain management must eventually coordinate with the application layer.


45. Domain + SSL

The relationship becomes:

Site
 │
 ├── Domain A
 ├── Domain B
 └── Domain C
       │
       ▼
 SSL Certificate
       │
       ├── A
       ├── B
       └── C

So the certificate should be generated from the current domain registry rather than manually listing names.


46. Domain + Backup

Backup doesn’t need to create a separate backup for every alias.

For:

example.com
www.example.com

both use:

same site data

Therefore:

one site backup

is sufficient.


47. Domain + Suspension

If the site is:

SUSPENDED

all domains attached to the site should follow the suspension state.

For example:

example.com
www.example.com

both return:

503

A redirect domain may continue redirecting, depending on your policy, but the final target should remain unavailable.


48. Domain + Health

Health checks should eventually test every active hostname.

For:

example.com
www.example.com

check:

DNS
HTTP
HTTPS
certificate

This catches:

www.example.com

being broken while:

example.com

works.


49. Domain + Backup Restore

When restoring:

example.com

the attached domain registry should not disappear.

Restore customer data, but preserve current infrastructure relationships:

example.com
www.example.com

remain attached to the site.


50. Domain Registry vs Backup

This reinforces our previous architecture:

BACKUP DATA
    │
    ├── WordPress files
    └── Database

CURRENT INFRASTRUCTURE
    │
    ├── Domains
    ├── Nginx
    ├── PHP
    └── SSL

The current infrastructure should generally remain authoritative during restore.


51. Domain Status Example

A complete site might show:

SITE
--------------------------------
Primary:
example.com

Domains:
example.com       PRIMARY
www.example.com   ALIAS
old.example.com   REDIRECT

DNS:
OK

SSL:
OK

Service:
ACTIVE

52. Domain Addition Output

CresignSys Domain Add
=====================

Domain:
www.example.com

Type:
ALIAS

Target:
example.com

[OK] Domain validated
[OK] Target site found
[OK] Domain available
[OK] Domain registered
[OK] Nginx configuration generated
[OK] nginx -t
[OK] Nginx reloaded

DNS:
PENDING

SSL:
UPDATE REQUIRED

This is an honest result.


53. Why SSL UPDATE REQUIRED?

Because adding the hostname changes the set of names the certificate should cover.

The administrator can then run:

sudo hosting-ssl example.com

to update the certificate.

Eventually this can be automated safely.


54. Domain Removal Output

CresignSys Domain Remove
========================

Domain:
www.example.com

Type:
ALIAS

[OK] Domain removed
[OK] Nginx configuration updated
[OK] nginx -t
[OK] Nginx reloaded

SSL:
UPDATE REQUIRED

Again, the website itself remains intact.


55. Redirect Output

CresignSys Domain Add
=====================

Domain:
old-example.com

Type:
REDIRECT

Target:
example.com

[OK] Domain validated
[OK] Target validated
[OK] Redirect configuration generated
[OK] nginx -t
[OK] Nginx reloaded

Status:
ACTIVE

56. Wildcard Domains

Eventually you may want:

*.example.com

But don’t implement wildcard domains in the first version.

They complicate:

DNS
SSL
routing
security
customer isolation

Start with explicit hostnames.


57. Internationalized Domain Names

International domain names introduce:

Unicode
Punycode

For the initial CHP version, use normalized ASCII/Punycode hostnames.

Internationalized domain support can be added later.


58. Domain Security

The domain-management layer is a major security boundary.

Never allow a customer/site user to register:

google.com

or another customer’s domain unless your platform’s ownership verification process confirms control.


59. Domain Ownership Verification

For a reseller/hosting platform, eventually implement:

Domain
 ↓
DNS verification
 ↓
Ownership confirmed
 ↓
Attach to site

For example:

TXT
_cresignsys-verification.example.com

with a generated token.


60. Why Ownership Verification Matters

Without it, someone could attempt:

hosting-domain-add bank-example.com --alias theirsite.com

and potentially configure your infrastructure to respond for a domain they don’t control.

Therefore domain attachment should eventually require proof of control.


61. DNS Verification Token

Conceptually:

_cresignsys-verification.example.com

TXT:

cresignsys-site-1027-randomtoken

CHP checks:

DNS TXT
   ↓
token matches
   ↓
ownership verified

Then the domain becomes attachable.


62. But Don’t Mix This Into the First Script

First version:

hosting-domain-add

can work for administrator-controlled domains.

Later:

hosting-domain-verify

can provide customer self-service ownership verification.


63. Multi-Domain Site Architecture

We now have:

                      SITE 1027
                          │
        ┌─────────────────┼─────────────────┐
        ▼                 ▼                 ▼
     example.com     www.example.com   old-example.com
      PRIMARY           ALIAS             REDIRECT
        │                 │                 │
        └─────────────────┼─────────────────┘
                          ▼
                        Nginx
                          │
                    ┌─────┴─────┐
                    ▼           ▼
                  PHP         SSL
                    │
                    ▼
                 WordPress

64. Updated CHP Model

The platform is becoming:

                         CHP
                          │
       ┌──────────────────┼──────────────────┐
       ▼                  ▼                  ▼
     Sites              Domains            Services
       │                  │                  │
       ▼                  ▼                  ▼
 WordPress           Primary/Alias       PHP-FPM
 Files               Redirect            Nginx
 Database            DNS                 MySQL
 Backup              SSL                 SSL
 Restore

65. Lesson 074 — Core Principle

A domain is not the same thing as a website.

The correct model is:

SITE
  ├── Primary Domain
  ├── Aliases
  └── Redirect Domains

This separation makes:

SSL
DNS
Nginx
WordPress
suspension
backup
restore

much easier to manage correctly.


66. Current CHP Command Set

hosting-create DOMAIN

hosting-list

hosting-info DOMAIN

hosting-health DOMAIN

hosting-repair DOMAIN --php
hosting-repair DOMAIN --nginx
hosting-repair DOMAIN --permissions
hosting-repair DOMAIN --wordpress

hosting-ssl DOMAIN

hosting-backup DOMAIN
hosting-backup-list DOMAIN
hosting-backup-verify DOMAIN BACKUP_ID
hosting-backup-prune DOMAIN --dry-run
hosting-backup-prune DOMAIN --execute

hosting-restore DOMAIN BACKUP_ID

hosting-suspend DOMAIN
hosting-unsuspend DOMAIN

hosting-domain-add DOMAIN
hosting-domain-add DOMAIN --alias TARGET
hosting-domain-add DOMAIN --redirect TARGET

hosting-domain-list DOMAIN

hosting-domain-remove DOMAIN

Next Lesson — 075

Build hosting-dns-check

The next layer connects the domain registry with actual DNS.

We need a command such as:

sudo hosting-dns-check example.com

that determines:

Domain
  ↓
A record
  ↓
AAAA record
  ↓
CNAME
  ↓
Nameserver resolution
  ↓
Expected server
  ↓
Actual server

The output should distinguish:

DNS = CORRECT
DNS = PENDING
DNS = WRONG
DNS = MULTIPLE
DNS = ERROR

and eventually provide:

Required DNS
----------------
A      @       SERVER_IP
A      www     SERVER_IP
AAAA   @       SERVER_IPV6

This will connect the domain layer → DNS → HTTP → HTTPS → SSL into one complete provisioning workflow.

Comments

Leave a Reply

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