Vibe coding a VestaCP alternative
This is a placeholder for things to come.
It will be a journey, and I want you all with me.
I will make some decisions that probably will make you all question me as a person.
Well, we all have our preferences; sometimes we don't agree, and that is fine.
The initial plan for this "fun" project is to vibe-code most parts. Manual edits of files will be kept at a minimum.
I will share some of the prompts, often the larger ones that make a lot of changes to the codebase.
Plans will be shared here, and of course the GitHub URL.
All when available.
I'm writing this to let you know about the plan. I hope there will be some updates later tonight.
Right now I have other pressing business to attend to.
“Technology is best when it brings people together.” – Matt Mullenweg




Comments
Enjoy ! Have fun ! And enjoy again .
I believe in good luck. Harder that I work ,luckier i get.
This is going to be fun.
TierHive - Hourly VPS - NAT Native - /24 per customer - DE, UK, SG, CA, USA x4, FR x2, AU, PL, NL, JP
FREE tokens on sign up, try before you buy. | Static Hosting Free for life: https://tierhive.com/static-hosting/
Vibe the vibe, it will be fun
BillingServ - Easy, simple, and hassle-free online invoicing solution. Contact us today.
White Label VPN | Software Licensing Billing | WHMCS Alternative
Best of luck :-)
What set up are you planning to use? agent, model, expected costs?
This will be coded by Claude, my AI-assistant. The models and efforts will vary, depending on how many tokens I have left on my company account.
I had very little time this evening, so I started by putting on the Plan hat on Claude, feeding this prompt.
And after many, long, boring minutes ..... this plan was formed, almost 2500 words.
Plan: LESta Hosting Control Plane Rewrite
TL;DR: Rebuild the Vesta product as a Laravel 13.17 and React 19 control plane, preserving the compact hosting-panel workflows while replacing privileged PHP shell execution, flat-file state, wildcard sudo, and executable queues. The first implementation milestone is a complete web-hosting vertical slice on Ubuntu LTS with a Go node agent boundary. Mail remains an MVP capability, but is isolated as a separately gated subsystem because it carries the highest abuse and operational risk.
Steps
Phase 0, decisions and product contract
src/react/src/containers/ControlPanelContent,src/react/src/components/MainNav,web/inc/i18n/en.php,web/add,web/edit,web/delete,web/suspend,web/api/v1,bin/v-*,data/packages, anddata/users. Record resource fields, lifecycle verbs, quotas, suspension semantics, role visibility, and cross-resource effects. Treat the Claude artifact as supplementary only because it is not publicly readable from this environment.RunCommand, no arbitrary command-plus-arguments API, noexecfrom controllers, no wildcard sudo, no raw user filesystem paths, no secrets in props/logs/job payloads, and no executable queue files.Phase 1, control-plane foundation
session.lookuser switching without an explicit, audited impersonation model.Phase 2, first vertical slice, web hosting
WebProvisionerand a fake adapter first, followed by the Go agent capability for staged configuration rendering, ownership and permission assignment, syntax validation, atomic activation, service reload, health check, and rollback. Laravel must never execute host commands directly. Operations must be bounded, idempotent, retryable, observable, and safe after lost responses.Phase 3, core resource slices
Phase 4, higher-risk operations
Phase 5, frontend parity and operations
resources/js/components/{web,dns,mail,databases,cron,files,server,backups}and page props underresources/js/types. Use generated@/routesand@/actionsfor every backend call. Keep global Inertia props limited to authenticated identity, current account, permissions needed for navigation, and flash data.Phase 6, review, optimization, and release
Relevant files
-
/Users/mikho/Herd/LESta/composer.jsonand/Users/mikho/Herd/LESta/package.json, current Laravel 13.17, Inertia 3, React 19, Fortify, Wayfinder, Pest, and Tailwind 4 baseline. Do not add dependencies without approval.-
/Users/mikho/Herd/LESta/routes/web.phpand/Users/mikho/Herd/LESta/routes/settings.php, authenticated Inertia route boundaries and settings conventions.-
/Users/mikho/Herd/LESta/app/Models/User.phpand/Users/mikho/Herd/LESta/app/Http/Middleware/HandleInertiaRequests.php, identity and minimal shared props.-
/Users/mikho/Herd/LESta/app/Actions/Fortify/,/Users/mikho/Herd/LESta/config/fortify.php, and/Users/mikho/Herd/LESta/app/Providers/FortifyServiceProvider.php, existing authentication extension points.-
/Users/mikho/Herd/LESta/database/migrations/,/Users/mikho/Herd/LESta/database/factories/, and/Users/mikho/Herd/LESta/app/Models/, ordered schema, factories, relationships, casts, and lifecycle state.-
/Users/mikho/Herd/LESta/app/Http/Controllers/,/Users/mikho/Herd/LESta/app/Http/Requests/,/Users/mikho/Herd/LESta/app/Policies/, and/Users/mikho/Herd/LESta/app/Actions/, thin HTTP boundaries, validation, authorization, and use cases.-
/Users/mikho/Herd/LESta/app/Jobs/,/Users/mikho/Herd/LESta/app/Events/,/Users/mikho/Herd/LESta/app/Listeners/,/Users/mikho/Herd/LESta/app/Console/Commands/, and/Users/mikho/Herd/LESta/routes/console.php, durable provisioning, outbox processing, usage, backups, and scheduler integration.-
/Users/mikho/Herd/LESta/app/Contracts/and/Users/mikho/Herd/LESta/app/Services/, typed provisioner contracts, agent client, idempotency, secrets, path safety, and query/read services.-
/Users/mikho/Herd/LESta/resources/js/app.tsx,/Users/mikho/Herd/LESta/resources/js/layouts/,/Users/mikho/Herd/LESta/resources/js/pages/,/Users/mikho/Herd/LESta/resources/js/components/,/Users/mikho/Herd/LESta/resources/js/types/, and/Users/mikho/Herd/LESta/resources/css/app.css, the existing Inertia shell, pages, reusable UI, types, and theme.-
/Users/mikho/Herd/LESta/resources/js/routes/,/Users/mikho/Herd/LESta/resources/js/actions/, and/Users/mikho/Herd/LESta/resources/js/wayfinder/, generated route/controller contracts, never hand-edited.-
/Users/mikho/Herd/LESta/tests/Pest.php,/Users/mikho/Herd/LESta/tests/Feature/,/Users/mikho/Herd/LESta/tests/Unit/, and/Users/mikho/Herd/LESta/tests/Browser/, feature, unit, architecture, and browser coverage.-
/Users/mikho/Herd/LESta/.github/workflows/, CI and release checks. The Go agent should be a separately versioned deployable component, not embedded in Laravel request execution.- Legacy references:
https://github.com/outroll/vestapathsbin/,web/api/v1/,data/packages/,data/users/,install/,src/deb/,src/rpm/, andsrc/react/src/. Use them for contract extraction only, never as implementation templates.Verification
1. Before implementation, approve the threat model, capability matrix, MySQL/MariaDB version target, Ubuntu LTS version, mail stack support matrix, and first-slice acceptance criteria.
2. For the web slice, run the narrow Pest tests first, then Pint, PHPStan, ESLint, Prettier, TypeScript, Wayfinder generation, and the production Vite build.
3. Assert every mutation is policy-authorized, transactionally persisted, dispatched after commit, idempotent under retry, serialized per resource/node where required, and visible as a structured provisioning state.
4. Run security tests for tenant isolation, CSRF, MFA gates, rate limiting, command injection, path traversal, archive extraction, secret redaction, agent authentication, replay, and privilege boundaries.
5. Run reliability tests for duplicate operations, lost responses, offline agents, stale versions, invalid service configuration, rollback, partial subsystem failure, disk-full, backup corruption, and restore.
6. Manually verify the primary React workflow at desktop and mobile widths, role-aware navigation, loading/error/empty states, destructive confirmations, dark mode, accessibility, and absence of browser JavaScript errors.
7. Before production, rehearse signed installation, node bootstrap, database migration, queue/scheduler health, backup restore, alerting, rollback, and controlled feature enablement.
Decisions
- The requested first release is core hosting plus self-hosted mail, not billing.
- Deployment starts as one Ubuntu LTS node but every resource is node-assigned and the protocol is multi-node ready.
- Provider administrators and customers are the initial tenancy model. Reseller nesting is reserved until the account/membership model is proven.
- MySQL/MariaDB is a hard requirement. PostgreSQL is not used unless a later ADR changes the decision.
- A Go system service is the recommended node-agent implementation.
- Fresh installs are the initial migration strategy. Vesta import/coexistence is later and dry-run first.
- Web hosting is the first implementation milestone. Mail is MVP scope but must be gated behind its own capability, threat model, and operational readiness review.
- Preserve UI vocabulary, navigation patterns, and resource workflows. Do not preserve legacy URLs, shell command names, flat-file state, or unsafe privilege assumptions.
- No production implementation should begin until this plan is approved. No commit or branch creation is part of this plan.
Tradeoff analysis
- MySQL/MariaDB meets the stated requirement and is familiar in hosting environments, but PostgreSQL would provide stronger native constraints and more flexible reporting primitives. The design compensates with strict schema constraints, indexed relational read models, and explicit application services.
- A Go agent adds a second deployable component and release pipeline, but it creates the necessary privilege boundary and keeps Laravel horizontally scalable. A PHP/Bash adapter would be faster only for a prototype and would recreate the main risk.
- Self-hosted mail preserves Vesta parity and customer control, but it creates abuse, reputation, deliverability, storage, and incident-response obligations. It is therefore isolated, quota-limited, observable, and gated rather than mixed into generic domain provisioning.
- A relational source of truth plus asynchronous reconciliation is more complex than direct config writes, but it enables transactions, retries, auditing, drift detection, rollback, multi-node growth, and recoverable failures.
Scope boundaries
- Included in the plan: authentication, authorization, accounts, packages, quotas, web, DNS, mail, databases, cron, backups, node health, typed provisioning, audit, responsive React UI, testing, and production operations.
- Excluded from the first implementation slice: billing, Vesta import, broad OS support, reseller nesting, unrestricted file manager, arbitrary firewall/service editors, plugin marketplace, and full multi-node failover.
- The current environment does not contain the legacy Vesta checkout, and the linked Claude artifact is unavailable without access. Exact field mappings and vulnerability claims must be confirmed against a pinned commit and representative production data before migration work.
Tomorrow I will read all these words, form an opinion on the content, and probably run a couple of more prompts on it before any code is written.
Question to the audience .... should the original UI be kept or should a more modern UI be built?
“Technology is best when it brings people together.” – Matt Mullenweg
I've been accused of "vibe coding" enough that I have to defend myself in advance every time I talk about it. I do not "vibe code" anything that meets two requirements: public facing, contains or can access anything of consequence.
But when the job is something where you compromising it just makes me laugh and delete it, it's super fun to just explain what you want, sit back, and watch it go. It's easily as entertaining as a good movie. I've got a ton of projects just sitting in a folder that were vibe coded just to see what the AI could do on its own. Sometimes they're even useful because the AI figured out a way to do something that you were struggling with, so you get to take that concept back to production code.
Do everything as though everyone you’ll ever know is watching.
Can I also share some of Vibe Coded Server Panel I found for your references?
https://microlxc.net/
Sure, why not.
“Technology is best when it brings people together.” – Matt Mullenweg
I'm not sure if this fits to your topic, but here you go:
100% Vibe Coding.
https://microlxc.net/
Thanks!
I’m sure there are keywords in there that I can use when writing the prompts.
Don’t want to miss out on the security and features.
“Technology is best when it brings people together.” – Matt Mullenweg
This sounds like a fun project to follow, especially with the decision to keep manual code changes to a minimum. A VestaCP alternative built in the open should attract plenty of opinions once the first parts start taking shape. Sharing the larger prompts and design decisions will also be interesting since those choices often have as much impact as the code itself. Looking forward to seeing what you end up with.
I like the simplicity of the original UI, but a subtle refresh might not hurt.
Thats my thoughts exactly.
No icons to keep things fast and simple, just text. Properly formatted.
“Technology is best when it brings people together.” – Matt Mullenweg
Step two.
I had a little extra time while waiting for a meeting to start, so I took a jab at the first prompt and result.
My native language is not English; it's Swedish, so my first step after creating the plan was to have a second project in Claude with a short instruction.
This is the project folder (path to local directory with the documentation (ie markdown files)). I will write prompts in Swedish; translate them to English for me to use in my coding project.
This is the translation of my prompt:
an extremly long second prompt including service installation layer, .install directory, and build sequencing decision
With the plan laid out in LESta-rewrite-plan.md, do not start implementing service features yet. This step resolves the part of the plan that is still underspecified: how the underlying host services are installed, how their configuration files are owned and rendered over the product's lifetime, in what order the services are taken on, and whether the installation layer or the UI layer is built first.
Read LESta-rewrite-plan.md in full first and treat it as the governing document. Where anything below conflicts with the plan, say so explicitly instead of silently resolving it.
Role
Continue as the four-agent team defined in the first prompt: Architect designs, Engineer specifies the concrete artifacts, Reviewer attacks the result for security and operational failure modes, Optimizer checks it for long-term maintenance cost. Act as a senior technical lead who will own this product for five or more years. Challenge weak decisions in the plan rather than implementing them faithfully. Prioritize simplicity, and prefer fewer moving parts over cleverness.
Objective
Produce a reviewed, decided, and documented service installation and configuration architecture for LESta, plus the .install directory that will hold it, plus a decided build order. This is a design and scaffolding step. The only code written in this step is the scaffolding, contracts, and at most one reference implementation that proves the contract, as decided in Task 4.
Task 1, audit the plan's installation and configuration story
The plan commits to a Go node agent, to Laravel never executing host commands, to staged rendering with syntax validation, atomic activation, reload, health check, and rollback (step 10), and to replacing curl-to-root installation with a signed, pinned deployment process that publishes checksums and SBOMs and never silently replaces existing host configuration (step 24). It does not yet say how a bare Ubuntu LTS node gets nginx, Apache, BIND, Exim, Dovecot, MariaDB, ClamAV, SpamAssassin, cron, the firewall, and ACME tooling in the first place, nor who owns the resulting files on disk for the rest of the product's life.
Go through the plan in detail and answer, with reasoning:
Bootstrap versus runtime. Draw the exact boundary between one-time host bootstrap, which installs packages and lays down a hardened baseline, and continuous runtime provisioning, which renders per-tenant configuration on every mutation. State which of the two .install owns. State what must never leak across that boundary. In particular, confirm or refute that the control plane must never invoke an .install script, directly or through the agent, at request time, and explain what mechanism prevents it from being reintroduced later.
Language and ownership of the installer. The plan already introduces a Go agent as a deployable component. Decide whether the installers are POSIX shell scripts, a Go subcommand of the agent, a declarative manifest consumed by the agent, or a combination, and justify the choice against auditability, offline installation, operator trust, testability, and the cost of maintaining a second toolchain. If shell is chosen, say why the agent is not the better home.
Configuration file ownership model. Given that MySQL/MariaDB is the authoritative desired state and the on-node configuration is a derived artifact, specify precisely:
which files LESta owns and will overwrite without warning, which files it reads but never writes, and which files it must refuse to touch,
how LESta-owned configuration is namespaced away from distribution defaults and from operator edits, for example include directories and drop-in fragments per service rather than rewriting the main configuration file,
how generated files are staged, validated, activated atomically, and rolled back, and where the previous generation is retained,
how observed-state digests detect drift when an operator edits a generated file by hand, and what the product does when it finds drift, including whether it reconciles, warns, or refuses,
how templates are versioned so that an upgrade of LESta can re-render every existing tenant's configuration safely,
how secrets inside configuration, DKIM private keys, database credentials, ACME account keys, are stored, permissioned, rotated, and kept out of logs, backups in plaintext, Inertia props, and job payloads.
Idempotency and re-run semantics. Specify what happens when an installer is run twice, run against a partially installed node, run after a failed run, run against a node where an administrator has already installed a conflicting package or service, and run during an upgrade to a newer LESta release. Define whether installation is convergent or one-shot, and how a failed installation is unwound.
Capability registration. The plan models node capabilities in step 5 and a versioned capability-named node protocol in step 8. Specify how a completed installation registers the capability it enables, how the control plane learns that a node can now serve a given resource type, and how a capability is marked degraded or withdrawn when a service is unhealthy.
Gaps and corrections. List every place where the plan's installation and configuration story is incomplete, internally inconsistent, or would push unsafe legacy Vesta behavior back into the new runtime. Propose the correction. Do not defend the plan for its own sake.
Task 2, create the .install directory
Create a directory named .install in the repository root, /mikho/LESta/.install/. This directory is the single home for all installation logic for the underlying services.
Requirements:
Design the internal structure so that each service is self-contained and discoverable, and so that a shared base layer, for example package repositories, system users, directory layout, TLS trust, and firewall baseline, is expressed once rather than copied per service. Propose the layout and justify it. Include where per-service configuration templates live, and whether they live beside the installer in .install or in the runtime agent's own asset tree, and why.
Write a .install/README.md that states the purpose of the directory, the boundary from Task 1, the execution model, and the rule that nothing in the application ever calls these scripts at request time.
Write a written installer contract that every service installer must satisfy, and that is testable. At minimum it must cover: non-interactive and unattended execution, no network fetch of unpinned code, no curl | bash, explicit version pinning and checksum verification of anything downloaded, deterministic exit-code semantics, structured machine-readable output so the control plane can record the result, a required dry-run mode, a preflight check that verifies OS release, architecture, free disk, ports, and conflicting packages before any change is made, logging to a known location with secrets redacted, and a declared list of the capabilities the installer provides and depends on.
Add a per-service metadata manifest format so that dependency order, provided capabilities, required capabilities, supported Ubuntu LTS releases, and the packages and ports touched are declared as data rather than encoded in script order.
Verify that a dot-prefixed directory is actually workable here. Confirm it is tracked by git, not excluded by .gitignore, .gitattributes, export-ignore rules, Vite or Composer packaging, or the release artifact build. If the dot prefix creates a real risk of the directory being silently dropped from a build or overlooked by an operator, say so and recommend the alternative rather than quietly complying.
Do not write the full set of service installers in this step. Which installers get written, and when, is the output of Task 4.
Task 3, decide the service order
Decide and justify the order in which the underlying services are taken on, from a bare Ubuntu LTS node to a complete panel. Produce a dependency graph, not just a list.
Account for at least:
the base layer that everything else assumes,
that MySQL/MariaDB appears twice, once as the control plane's own authoritative store and once as the managed database service offered to tenants, and whether those are the same instance, and what the security consequence is either way,
the web server, and whether the first release supports nginx, Apache, both, or nginx as a proxy in front of Apache as the original does, and what that choice costs in template surface,
ACME and certificate issuance, including whether it is a separate service in the order or a property of the web service, and how issuance is rate limited and retried,
DNS, and its ordering relationship to certificate issuance and to mail,
cron, and the command policy the plan requires in step 16,
the firewall, and whether a baseline is part of the base layer while tenant-visible rules stay deferred as the plan requires in step 19,
mail last, isolated behind its own capability gate, threat model, and operational readiness review, as the plan requires in steps 14 and 19,
backups, statistics, and node health, and where they fall relative to the rest.
For each service state the ordering rationale, the hard prerequisites, the risk it introduces, and the acceptance gate that must pass before the next service starts. Explicitly call out any place where the plan's phase order and the installation dependency order disagree, and say which one wins.
Task 4, decide the build sequencing strategy
Decide, and justify, between these strategies, or a better one you can defend:
A, installation layer first. Write every service installer and the full configuration contract for all services, then build the UI and the control plane intelligence that couples the UI to the services on top of a finished service layer.
B, UI first. Build the React and Inertia surface across resource types first against fake adapters, then add installers and coupling intelligence per service afterwards.
C, vertical slice per service. For one service at a time, take the whole chain to done, installer, configuration rendering, agent capability, provisioner contract, control plane actions, UI, and tests, before starting the next service.
Requirements for this decision:
Reconcile your answer with the plan, which already commits to a web-hosting vertical slice as the first implementation milestone in Phase 2 and builds WebProvisioner against a fake adapter before the real Go agent capability. If your recommendation deviates from that commitment, justify the deviation explicitly and state what in the plan must change.
Evaluate each strategy against: time to a demonstrable working product, the risk of designing the wrong contract before any real service has been touched, rework cost, the ability to test without a live node, the cost of context switching between Laravel, React, Go, and shell, the risk of a half-finished installation layer rotting before it is ever exercised, and the fact that this is a single developer project rather than a staffed team.
Name the alternatives you rejected and the specific reason each was rejected.
Produce a concrete phased sequence with entry and exit criteria per phase, mapped onto the service order from Task 3 and onto the plan's existing phase numbering. Say what is built in the first phase down to the artifact level.
State what must be true for you to revisit the decision later, so the decision is falsifiable rather than permanent by default.
Non-negotiable constraints
These come from the plan and hold for everything produced here:
No generic RunCommand, no arbitrary command-plus-arguments API, no exec from controllers, no wildcard sudo, no raw user filesystem paths, no secrets in props, logs, or job payloads, no executable queue files.
Laravel never executes host commands. Every host effect goes through a named, schema-validated, idempotent, bounded, observable agent capability.
Ubuntu LTS, single managed node in the first release, but every resource is node-assigned and the protocol stays multi-node ready.
MySQL/MariaDB is the authoritative store. PostgreSQL is out unless a later ADR changes it.
Do not add dependencies without approval. Do not create commits or branches. Do not begin production implementation of service features in this step.
Legacy Vesta is a contract reference only, never an implementation template. Its install/, src/deb/, and src/rpm/ trees may be read to extract what a working panel actually needs on a host, and must not be ported.
Deliverables
An ADR-style decision document written to the repository, covering Task 1's answers, Task 3's service order with its dependency graph, and Task 4's sequencing decision, each with tradeoffs and rejected alternatives stated.
The .install directory, its README.md, the installer contract, the per-service manifest format, the shared base layer definition, and the directory skeleton for every planned service.
A written specification of the configuration file ownership and rendering model from Task 1, item 3, precise enough that two different implementers would produce the same on-disk result.
Whatever installer or slice Task 4's decision says should exist first, and nothing beyond it.
A short list of the open questions that need my approval before implementation continues, phrased as decisions with options rather than open-ended questions.
Verification
Show that the .install directory is tracked by git and survives the release artifact build.
Show that the installer contract is enforceable by something automated, and say what that something is.
Walk the Reviewer through the failure cases: installer interrupted midway, installer run twice, operator has edited a generated configuration file by hand, service fails its syntax check after render, service reloads but fails its health check, node loses the agent connection between staging and activation, secret present in an installer log, an unpinned package version changing behavior between two nodes installed a month apart.
Confirm that nothing produced here allows the control plane to reach a shell.
Out of scope for this step
Billing, Vesta data import, non-Ubuntu operating systems, reseller nesting, an unrestricted file manager, arbitrary firewall or service editors, multi-node failover, and any production implementation of resource features beyond what Task 4 explicitly authorizes.
pretty interesting how it draws some conlusion from those few lines, while some other decisions are left to myself to chose from.
I decided to add the following line to the end of the prompt.
“Technology is best when it brings people together.” – Matt Mullenweg
While runnning the second prompt the following questions were asked
What Ubuntu LTS version should be supported?
Answer both 24.0 & 26.04
While reading the chat log I noticed this
The .install skeleton is complete for the decided service set: base, node health, firewall, nginx, ACME, BIND9, MariaDB, cron, backups, statistics, and gated mail. No Apache directory was added because the ADR explicitly defers Apache support. I’m now running contract-level checks across every manifest, checking the dependency graph and forbidden runtime paths, then I’ll stage only these new files so Git can prove they are tracked without creating a commit.Especially this: No Apache directory was added because the ADR explicitly defers Apache support.
Which I don't understand as the prompt states:
the web server, and whether the first release supports nginx, Apache, both, or nginx as a proxy in front of Apache as the original does, and what that choice costs in template surface,It did make a decision on it own, without consulting me.
So i had to add a 3rd prompt, short and sweet.
Result;
Next steps
Approve the exact M* ariaDB/MySQL version.
Think this requires a commit and push to github
“Technology is best when it brings people together.” – Matt Mullenweg
Awesome to follow! Also, from what I’ve seen, agents are far better than most of the junk development shops put out these days… also even if you pay for human coding, what’s to stop them just having an agent write it and then reviewing…
Currently building a whmcs alternative (like a lot of people) with agents, human code, human review and 3rd party review. Probably way better than the junk from web pro’s!
Rock Solid Web Hosting, VPS & VDS with a Refreshing Approach - Xeon + EPYC with DDoS protection and Enterprise Hardware! HostBilby Inc.