phpVirtualBox in Go — part 3: implementation and testing roadmap

Mascote LinuxPro e cachorro caramelo cyborg em laboratório de virtualização, com PHP, Go e Vue nos monitores.

Before you start: read about the original project in the article phpVirtualBox: manage VirtualBox from your browser.

In this series: Part 1: phpVirtualBox, Echo and Vue · Part 2: AI and OpenSpec · Part 3: implementation and tests

phpVirtualBox in Go series — part 3 of 3. After analyzing phpVirtualBox and organizing the migration with AI and OpenSpec, it's time to define how to implement and validate the new panel. The goal is not to release a full rewrite all at once: it's to build a sequence of verifiable deliveries.

Delivery 1: prove distribution without touching VMs

Start with an Echo service, a health route, and a Vue page that queries that route. Build the frontend and embed its output using go:embed. At this stage, the panel does not need to know about any virtual machine: the question is whether the API and the interface work in the distributed artifact.

Echo has an official example of embedded resources, and the embed package documentation describes how files are included at compile time. Paths are relative to the package; do not plan to embed files from parent directories with ../. Generate the Vue files before compiling Go.

Código Vue → build do frontend → web/dist
                                   ↓
Código Go + Echo + go:embed → executável do painel

Acceptance criterion: copy only the executable to an empty folder, start it on the loopback and verify the page, the JavaScript files, and the health route. Stop the frontend development server before this test. This demonstrates panel distribution, but it does not yet demonstrate integration with VirtualBox.

Do not embed environment files, credentials, or databases. Those items must remain external to the binary. If the interface uses application routes, define frontend path handling without turning /api/ errors into an HTML page with a success status.

Delivery 2: security and contracts before the real host

Before releasing the panel to others, implement authentication, session, expiration, and authorization. Authentication identifies the user; authorization decides which machines and actions they can access. An authenticated user should not automatically gain access to all hosts.

The API must distinguish invalid input, missing authentication, missing permission, and external service failure. Do not send full SOAP messages or sensitive paths to the browser. Log technical details in a sanitized way on the server and return errors the interface can present.

For the initial lab, configure the service on the loopback address and use test credentials. The production design must specify protected transport, external configuration, secrets management, and access policy.

Delivery 3: real inventory in read-only mode

Implement an adapter dedicated to the integration. The HTTP layer must not know every detail of SOAP: it calls an inventory service that returns the machine representation defined in the specification. This allows testing rules without a real host and, separately, testing the adapter against VirtualBox.

Compare the results with a controlled set of machines: one powered off, one running and, when possible, additional states that your contract commits to support. Record which versions and scenarios were actually verified. Do not use the expression “compatible with all versions” for a test performed in a single environment.

The read-only test must confirm that the query does not trigger change commands. It is not enough for the interface to hide buttons: this restriction must exist in the backend. Also limit the number of queries and set a timeout so connections are not exhausted when a host is unavailable.

A test matrix to track the deliveries

Layer What to check Expected evidence
Distribution API and Vue outside the source tree Executable working without a Node server
HTTP contract Authentication, fields and errors Automated tests per scenario
Adapter Replies, failures, and SOAP timeout Sanitized fixtures and integration tests
Interface Loading, empty, and failure Navigation and visual inspection tests
Operations Initial state, result, and recovery Execution on disposable VMs
Deployment Restart and rollback Procedure reproduced in the lab

Mocks help you reproduce hard-to-trigger failures, but they don't prove compatibility with the real service. Integration tests help validate communication, but they don't replace authorization tests. Each layer answers a different question.

Delivery 4: operations with safety

With the reading validated, I would create separate changes to start machines, request shutdown, monitor operations, and finally manage more sensitive resources. Requesting shutdown from the guest system isn't the same action as cutting power to the VM; the interface and permissions should distinguish those operations.

Long-running operations deserve an explicit task model: identifier, state, start, result, and error. After a timeout, the backend needs to query the actual state before trying again. Automatically retrying an action can duplicate work or produce an unexpected effect.

  • Start and shutdown: validate current state, permissions, and monitoring.
  • Snapshots: treat creation, deletion, and restoration as distinct actions.
  • Disks: differentiate removing a link from deleting the physical file.
  • Multiple hosts: limit failures and permissions by destination.
  • Auditing: register actor, target, and result, without registering credentials.

Before allowing writes, add protection against CSRF when there is cookie-based authentication, object-level authorization, and clear confirmation for destructive operations. The lab should use disposable VMs. A snapshot is not a substitute for a tested backup and restore strategy.

Licensing and deployment: two steps that cannot be left for the end

The phpVirtualBox license file indicates GNU GPL version 3. Rewriting in another language is not a reason to ignore the license of the code, visual assets, or dependencies used. Record the origin of the reused material and assess the applicable obligations before distributing the new project. Original project license.

During deployment, keep the possibility of returning to the previous panel, but do not let two controllers run concurrent changes on the same machine. Start with queries, compare the results, and progressively release operations. If the need is to change hypervisor, that is a different job: the ova2xva guide discusses converting machines to XCP-ng, not replacing the VirtualBox management interface.

Series conclusion: distributing is simple; operating requires evidence

As an engineering project, the proposal makes sense if it solves a concrete problem: simpler distribution, better interface, clear API, and predictable maintenance. phpVirtualBox offers a valuable reference, but the new panel would need to earn trust with tests and compatibility, not just with a different language.

The first milestone should be small and demonstrable: an executable with Echo and Vue embedded, authentication, and a real VM inventory in read-only mode. AI and OpenSpec can speed up the path to it — as long as the tasks are verifiable and no one confuses generated code with validated integration.

In this series: Part 1: phpVirtualBox, Echo and Vue · Part 2: AI and OpenSpec · Part 3: implementation and tests