Control Panel Icon

Phase 4: Hosting Accounts, Sites & Data Layer Foundation

Phase 3 established the panel itself.

Authentication was in place, protected routes were working, and the custom hosting control panel build had started to feel like a real application rather than a Laravel install with ambition.

This phase builds directly on Phase 3, where authentication, protected routes, and the panel layout were first established.

Phase 4 was where the project stepped into actual hosting concepts.

Not provisioning. Not server automation. Not touching the live system.

Just the structure that makes all of that possible later — without turning the application into a tangled mess of assumptions and regret.

This phase focused on building the core data layer for hosting accounts and sites, so the panel could start understanding what it is managing before it ever attempts to manage it.


🧩 Defining the Hosting System in the Custom Hosting Control Panel Build

Before a panel can create system users, generate virtual hosts, or manage PHP pools, it first needs a clear internal model of what a hosting account is and what a site is.

That sounds obvious, but it is one of those steps that smaller projects skip surprisingly often.

It is very easy to jump straight into creating directories and writing config files, only to realise later that the data model underneath is vague, inconsistent, or welded to early assumptions that seemed clever for about five minutes.

Phase 4 deliberately avoided that trap.

The goal here was to define the hosting structure inside the application first, using clean database design, proper relationships, and predictable conventions.


🗂️ The Hosting Account System

The first major addition in this phase was the hosting_accounts table.

This table represents the concept of a hosting account inside the panel. At this stage, that is still conceptual rather than system-backed.

No Linux user is being created yet, but the application now knows what a hosting account looks like and what data it needs to track.

Each hosting account stores core information such as:

  • username – the future system username and internal identifier
  • domain – the primary domain associated with the account
  • home_directory – the planned home path for the account
  • status – the current state of the account within the panel

This is an important distinction.

The panel is not yet creating these accounts at the operating system level, but it is now storing them in a way that mirrors how they will eventually exist.

That means future provisioning logic can work from a structure that already makes sense, rather than bolting itself onto whatever happened to be convenient at the time.


🌐 The Site System

Alongside hosting accounts, Phase 4 introduced the sites table.

If hosting accounts represent the customer or system-user level of the model, sites represent the actual web properties that sit underneath those accounts.

Each site stores fields such as:

  • domain – the site’s domain name
  • document_root – the path the web server will eventually serve from
  • status – the site’s current state within the application

This separation matters.

It would have been simpler in the short term to flatten everything into a single table and pretend an account and a site are basically the same thing.

But they are not.

A hosting account can own more than one site, and building that distinction into the data model early makes the whole system far more flexible.

That gives the panel room to grow into a more realistic hosting platform instead of painting itself into a one-account-one-site corner and then acting surprised later.


🔗 Relationship Structure

Once the two core tables were in place, the next step was wiring up the relationships properly.

The structure used in this phase is straightforward and intentional:

  • User → Hosting Accounts
  • Hosting Account → Sites

In practical terms, that means a panel user can own multiple hosting accounts, and each hosting account can contain multiple sites.

This gives the application a clean hierarchy to build on.

It also keeps the database model aligned with how hosting systems tend to work in the real world, where ownership, account boundaries, and hosted sites are related — but definitely not interchangeable.

From an architecture point of view, this is where the project started to feel less like a generic admin panel and more like the beginnings of an actual control plane.


🧠 Why the Data Relationships Matter

Good structure is not just about tidy tables and satisfying relationships in Eloquent.

It affects everything that comes after.

Provisioning logic will eventually need to know which user owns an account, which account owns a site, where that site lives on disk, what status it is in, and how those records should behave if something fails.

If those foundations are unclear, the automation layer becomes fragile very quickly.

By defining the relationships early, the panel gains a reliable map of the hosting environment before any real infrastructure changes are attempted.

That is a much better place to build from than trying to reverse-engineer structure after system automation has already started creeping in and making confident bad decisions.


📏 Business Logic and Naming Conventions

One of the most useful parts of this phase was not flashy at all.

It was the decision to define the core path conventions early and stick to them.

For hosting accounts, the application now assumes a home directory format of:

  • /home/{username}

For sites, the application now assumes a document root format of:

  • /home/{username}/public_html

At this point, these paths are still just data. They are not being created on disk yet.

But that does not make them any less important.

Defining these conventions early means the application is already speaking the same language as the future provisioning layer.

When Phase 5 and later phases begin creating users, directories, and web server configs, they will be building against rules that have already been established and stored consistently.

That kind of predictability matters more than it looks.

It reduces edge cases, keeps the panel logic clean, and avoids the classic problem of one part of the system assuming a completely different layout from another.


🖥️ Panel Integration

Phase 4 was not only about the database. It also brought the new hosting concepts into the control panel UI.

Two new sections were added to the panel:

  • /accounts
  • /sites

These pages introduced the first practical management views for the hosting layer.

The accounts page lists the hosting accounts currently stored in the system, while the sites page lists the sites linked to those accounts.

For now, both pages use simple table-based layouts, which was exactly the right choice at this stage.

No JavaScript frameworks. No overbuilt widgets. No pretending a basic list needs to become a dashboard within a dashboard.

Just clear information presented cleanly inside the panel layout introduced in Phase 3.

That kept the focus where it needed to be: structure, workflow, and correctness.


✍️ Create Forms and Input Handling

This phase also introduced the ability to create hosting accounts and sites directly through the panel.

That included:

  • Create Hosting Account form
  • Create Site form

When creating a hosting account, the panel stores the username and domain, then derives the home directory using the established convention.

When creating a site, the panel stores the domain, links it to the selected hosting account, and derives the document root from that account’s username.

Again, the important point here is that this logic remains at the data layer only.

No directories are created. No users are added to the operating system. No Nginx files appear out of nowhere in the background.

The forms only create records in the database, which is exactly what they should be doing at this stage.


✅ Validation and Clean Input Rules

To support those forms properly, validation rules were added to keep the input predictable and consistent.

That includes validation around values such as:

  • username
  • domain
  • hosting_account_id

This is the kind of work that does not get much attention in screenshots, but it is part of what separates a usable system from one that quietly lets bad data creep in until everything hurts later.

By validating input now, the panel keeps its data clean and gives future provisioning logic a much safer foundation to rely on.

That is especially important in a hosting environment, where one sloppy input field today can turn into broken paths, invalid configs, or failed automation tomorrow.


🧭 Controllers and Routing Structure

Another important step in Phase 4 was reinforcing the application structure behind the scenes.

Rather than relying on route closures to handle these new features, the hosting system was built using proper controllers:

  • HostingAccountController
  • SiteController

Routes were added for listing and creating both accounts and sites, giving the panel a cleaner and more scalable flow:

  • /accounts
  • /accounts/create
  • /sites
  • /sites/create

This keeps the hosting logic organised where it belongs and makes later expansion much easier.

The more the panel grows, the more important that separation becomes.

It is not the kind of decision that makes for dramatic before-and-after screenshots, but it is exactly the kind that stops a project from turning into a pile of “temporary” shortcuts that somehow become permanent.

The relationship handling and model structure in this phase followed the same principles described in the Laravel Eloquent relationships documentation, which helped keep the application logic clean and predictable from the start.


🚫 Why Provisioning Was Deliberately Left Out

One of the most important decisions in this phase was deciding what not to build yet.

It would have been very easy to jump from “create hosting account” straight into “also create the Linux user, also make the home directory, also write the web server config while we are at it.”

That sounds efficient right up until the point it isn’t.

Phase 4 stayed intentionally focused on the data layer, application structure, and hosting abstraction.

That meant no system user creation, no file system operations, no Nginx automation, no PHP-FPM pool generation, and no provisioning logic.

This was not avoidance. It was sequencing.

Building the structure first keeps the logic predictable and gives future provisioning work something stable to operate against.

It also makes troubleshooting far easier, because the application layer and the system layer are not being introduced at the same time.

Sometimes the fastest way to make a project harder is to do too much in one phase.


⚠️ Challenges and Design Discipline

From a technical point of view, this phase was less about solving one dramatic problem and more about resisting messy decisions.

The challenge was not whether the panel could store hosting data. Laravel makes that part fairly straightforward.

The real challenge was making sure the structure being introduced now would still make sense once the panel starts provisioning real resources later.

That meant thinking ahead without overbuilding, defining conventions without pretending the automation already existed, and making sure the application model was clean enough to support future phases without constant rewrites.

In other words, this phase was the architectural equivalent of measuring twice before picking up the power tools.


🧠 Why Phase 4 Matters

Phase 4 marks the point where the KR0311 Control Panel stopped being just a secured Laravel panel with a custom interface and started becoming a hosting system in its own right.

Not because it is provisioning anything yet, but because it now understands the core entities it will be responsible for managing.

Hosting accounts exist in the database. Sites exist in the database. The relationships between users, accounts, and sites are defined. The business rules for directory layout are established. The panel UI can create and display those records cleanly.

That is a major shift.

It creates the foundation for everything that comes next and prevents later automation from being built on vague assumptions or scattered logic.

Instead of improvising structure as the project grows, the project now has a hosting model it can build on deliberately.


🔜 What Comes Next in Phase 5

With the data layer now in place, the next phase is where the panel begins crossing the line from application structure into controlled system interaction.

That will include work around:

  • system user creation
  • directory creation
  • Nginx automation
  • PHP-FPM pools
  • queue-based provisioning

That is where things start getting more serious, because from that point onward the panel is no longer just storing intent.

It is acting on it.

Which is exactly why this phase had to come first.


🏁 Final Thoughts

Phase 4 was not the loudest phase in the build series, but it may end up being one of the most important.

It introduced the hosting model, established the data relationships, brought those concepts into the UI, and defined the conventions that future provisioning work will rely on.

Most importantly, it did all of that without rushing into system-level execution before the panel was ready for it.

That kind of groundwork is rarely glamorous, but it is the difference between building a platform and building a future headache with a nice logo.

The KR0311 Control Panel now has a real hosting foundation under it.

Next comes the part where it has to prove it can use it.

Previous Update Phase 3: Authentication, Panel Layout & Core Structure
Next Update Phase 5: Provisioning Engine & System Integration

Leave a Reply

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