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