Skip to main content

Architecture

What the pieces are and which one does what. Useful when something is wrong and you need to know where to look, or when you are working on zCloud itself.

The three parts​

Browser → zCloud (Next.js) → builder Odoo → infrastructure provider
(cloud API / Zebroo hardware)

zCloud is the web application you log into. It renders the dashboard, the project wizard and the project screen, and it holds no durable state of its own.

The builder Odoo at hosting.zebroo.de is the system of record. Projects, plans, ownership and billing live there as ordinary Odoo records — hosting.project and hosting.plan among others.

The provider is whatever actually runs the machine. Two are implemented — a cloud backend and Zebroo's own hardware — behind one interface, so the rest of the application does not care which is in use.

zCloud, the web application​

  • Next.js 16 with the App Router, TypeScript and Tailwind 4.
  • Auth.js (NextAuth v5) with the GitHub provider. Repository scope is requested so zCloud can list your repositories, create one from a template, and clone private repositories onto the machine.
  • The UI is a small set of pages — landing, dashboard, project wizard, project detail — with the project screen's tabs as separate panels.
note

The application is versioned against a specific Next.js release and its conventions differ from older versions. Read the guides under node_modules/next/dist/docs/ before changing application code.

The builder Odoo​

zCloud talks to it over JSON-RPC, authenticating with an Odoo API key (res.users.apikeys); the session is cached per process and re-established automatically when it expires.

Errors are translated rather than passed through, which is why the interface gives useful messages:

Odoo raiseszCloud answersMeaning
UserError / ValidationError400The request was fine, the business rule was not — "that name is taken", "that is not a valid DNS name"
AccessError403 / 404No permission for that project, or the action needs a role you do not have
AccessDeniedretriedThe RPC session expired — zCloud logs in again and repeats the call

The distinction matters: a business refusal is deliberately not a 502, so clients and proxies do not treat it as an upstream failure and retry it.

Provisioning​

New machines are configured with cloud-init on first boot. That single step:

  • installs Docker
  • starts Odoo and PostgreSQL as containers
  • applies the security hardening below
  • clones your repository, if the project has one, and mounts addons/ into the Odoo container

The project screen polls while this runs and reports four phases: order placed, machine booting, Docker and Odoo installing, Odoo running.

Hardening​

Applied to every machine, not offered as an option:

MeasureDetail
Fail2BanInstalled and configured for sshd — not merely present
SSHPassword authentication disabled; keys only
FirewallRestricted to the ports the service needs
Unattended upgradesSecurity updates applied without intervention
TLSCertificates issued and renewed automatically

This is the deliberate difference between a hosted Odoo and a virtual machine that somebody has to remember to maintain.

Background jobs​

Two systemd timers run alongside the application:

UnitJob
zcloud-katalogWatches the provider's machine catalogue for changes, so available sizes stay current
zcloud-quellenRecords the state of the Odoo sources, so versions offered in the wizard reflect what actually exists

Configuration​

zCloud is configured by environment, not by code:

VariablePurpose
AUTH_GITHUB_ID / AUTH_GITHUB_SECRETThe GitHub OAuth application
BUILDER_URL / BUILDER_DBWhere the builder Odoo is and which database
BUILDER_LOGIN / BUILDER_API_KEYCredentials for the RPC connection
GITHUB_SOURCE_TOKENRead access to Odoo's private enterprise repository, so Enterprise commits can be listed

Without GITHUB_SOURCE_TOKEN, Enterprise versions cannot be listed — the interface says so rather than showing an empty list.