Product
Architecture

Platform Architecture

OEC.sh is a multi-tenant Odoo hosting platform. This page explains how its core entities relate to each other.


Platform Overview

Loading diagram…

The top-level entity is the Organisation. Everything else belongs to one.

EntityBelongs toPurpose
Server / VMOrganisationThe machine Odoo runs on (BYOS or platform-provisioned)
ProjectOrganisationAn Odoo application (version, primary repo, addon selection)
EnvironmentProject + ServerA running Odoo instance (dev / staging / production)
TeamOrganisationGroup of members assigned to projects with a role
Cloud AccountOrganisationCredentials for AWS, Azure, GCP, DO, Vultr, Hetzner
Git ConnectionPlatform or OrgAuthentication for private Git repos
DNS ProviderOrganisationCloudflare, Route53, Azure DNS, etc.
Backup StorageOrganisationS3, R2, B2, MinIO, FTP, SFTP

Repository Hierarchy

Addon repositories follow a four-level cascade — from platform-wide down to per-environment overrides:

Loading diagram…

Levels Explained

🌐 Platform Addon Repos Managed by portal admins. Available to every organisation on the platform. Each repo has a version mapping — a separate Git branch per Odoo version (16.0, 17.0, 18.0 …). Stored at /opt/oecsh/platform/{slug}/.

🏢 Organisation Addon Repos Managed by Org Owners and Admins. Visible only to projects within the organisation. Authenticated via an Org Git Connection. Stored at /opt/oecsh/org_{uuid}/{slug}/.

📁 Project — Module Repositories Attached to one project. Each repo has a branch mapping — a different branch per environment type:

dev   → develop
staging → staging
production → main

The deployer resolves the correct branch automatically for each environment.

📁 Project — Additional Repos Also attached to one project. Unlike module repositories, additional repos use a single branch and are always included in every environment. Used for utility libraries, shared components, or extra OCA modules not in the org repo.

⚙️ Environment — Repo Overrides Environments can override any inherited repo:

  • Branch override — use a different branch than the project default for this env only
  • Exclusion — skip a repo entirely for this env (e.g. exclude heavy dev tools from production)

The override system follows the zero-config principle: no override row = inherit everything from the project. Only set overrides when an environment genuinely needs to diverge.


Environment Internals

Each environment is an isolated stack running on a server:

Environment
├── Odoo container          docker run -e KEY=VALUE ...
├── PostgreSQL              {env_id}_db container
│   ├── PgBouncer           connection pooling (Pro+)
│   └── Read Replica        streaming replication (Odoo 18+, Pro+)
├── Traefik routing         auto-provisioned TLS via Cloudflare
└── Netdata                 real-time metrics (proxied at /_oecsh/netdata/)

Resources (CPU, RAM, disk) are allocated per environment and count against the organisation's quota.


Access Control

Two systems control who can do what:

Organisation-level roles — set on OrganizationMember:

RoleCan do
OwnerEverything, including billing and deleting the org
AdminAll resources except billing management
DeveloperEnvironments assigned to their managed projects
ViewerRead-only across the org

Team-based access — Teams are groups of members assigned to specific projects with a project role (Admin / Developer / Viewer). A user's effective permission on a project is the highest role from any team membership plus their org-level role.

Full permission matrix: Permissions


Key Field Mappings

Some fields have different names between the database and API — notable ones:

Database columnAPI / frontend fieldNotes
project.git_branchdefault_branchPrimary repo branch
module_repository.default_branchdefault_branchModule repo default
project_environments.create_datecreated_atEnvironments table uses create_date, not created_at
project_environments.environment_typeenv_typeEnum: development / staging / production