SaaS Business Management
The ECOSIRE SaaS Business Management module turns Odoo into a control plane for an Odoo hosting business. Provision and manage customer instances on your own servers, bill them on subscription plans, record usage metrics, and monitor instance health -- all from the Odoo backend. It covers provisioning over SSH and Docker (or Kubernetes), custom domains with SSL, backup and restore, migration between versions and servers, a customer self-service portal, and a REST API.
Compatibility: Odoo 17, 18 and 19 (Community or Enterprise)
Price: $499 (one-time)
Current shipped version: 17.0 → 17.0.0.0.10, 18.0 → 18.0.0.0.10, 19.0 → 19.0.0.0.10
Menu map
After installation the app appears as SaaS Business Management in the main menu. Everything in this guide is reached from there:
| Menu | Contains |
|---|---|
| Dashboard | KPI cards and charts for the whole platform |
| Instances | Create Instance, All Instances, Templates/Images |
| Contracts | Subscriptions, Billing |
| Reporting | Analytics, Reports |
| Configuration | Settings, Plans, Servers |
The record you provision for a customer is called an Instance. There is no menu called Tenants.
Key Features
- Multi-instance management with one isolated database per instance
- Automated provisioning over SSH and Docker, with Kubernetes support
- Subscription plans with monthly and yearly pricing
- Usage records for CPU, memory, storage, bandwidth, API calls, active users, transactions and custom metrics
- Instance lifecycle states: Draft, Deploying, Running, Suspended, Cancelled
- Per-server capacity limits with available-slot tracking
- Dashboard with 6 KPI cards and 4 Chart.js charts
- Backup and restore, with configurable retention and scheduling
- Custom domains with SSL certificate status tracking and auto-renewal
- Migration wizard for version and server moves, with rollback on failure
- Customer self-service portal under
/my/saas - REST API under
/saas/api/v1/ - Stripe and PayPal payment integrations
Prerequisites
- Odoo 17, 18 or 19 (Community or Enterprise edition)
- PostgreSQL with permission to create and manage additional databases
- At least one host server you can reach over SSH, with Docker installed
- Python packages on the Odoo host:
paramiko,docker,requests,cryptography,psycopg2,redis,celery - Sufficient disk space for instance data and backups
Installation
- Download the module ZIP from your ECOSIRE Dashboard
- Extract to your Odoo addons directory:
unzip ecosire-saas-business-management-*.zip -d /opt/odoo/addons/
- Restart the Odoo service:
sudo systemctl restart odoo
- Navigate to Apps, click Update Apps List
- Search for "SaaS Business Management" and click Install
Configuration
Configure in this order. Provisioning will not offer you a server until at least one server record is active, connected and has a free slot.
Step 1: Add a Server
- Navigate to SaaS Business Management then Configuration then Servers
- Click New and fill in:
- Server Name
- Server Type -- Docker, Kubernetes, Virtual Machine, Bare Metal, or Simulated (Demo/Sandbox)
- Host Address and SSH Port (default 22)
- SSH User, and either SSH Password or SSH Private Key Path
- Max Instances -- the capacity cap for this server (default 10)
- Region (optional)
- Click Test Connection. The Connection Status field moves to Connected or Connection Failed, and Last Connection Test is stamped.
- Confirm Available Slots is above zero.
Simulated (Demo/Sandbox) servers skip SSH and Docker entirely -- instances are created as records and marked running immediately. Use them for demos and sandboxes, never for real hosting.
A server is only offered in the instance-creation wizard when it is active, connected and has available slots. A server whose connection test failed, or which is full, will not appear in the dropdown.
Step 2: Define Plans
- Navigate to SaaS Business Management then Configuration then Plans
- Click New and configure:
- Plan Name and Description
- Monthly Price (required) and Yearly Price
- Max Users and Max Instances
- Included Modules -- the Odoo modules recorded against this plan
- Sequence -- display order on the pricing page
- Active -- clear this to retire a plan without deleting it
- Click Save
Step 3: Global Settings
Navigate to SaaS Business Management then Configuration then Settings. The available settings are:
| Group | Settings |
|---|---|
| Defaults | Default Odoo Version, Default Server, Max Instances per Server (50), Trial Duration in days (14) |
| Backups | Enable Auto Backup, Backup Frequency (daily, weekly, monthly), Backup Retention in days (30) |
| Monitoring | Enable Monitoring, Alert Email, CPU Threshold % (80), Memory Threshold % (85) |
| Lifecycle | Auto Suspend Inactive Instances, Inactive Threshold in days (30) |
| Notifications | Notification Email, Webhook URL, API Key |
| Docker | Docker Registry URL, Docker Network Name (saas_network) |
| Kubernetes | Enable Kubernetes Support, Default Kubernetes Namespace (odoo-saas), Odoo Docker Image (odoo:19) |
| SSL | Enable SSL by Default, SSL Certificate Path, SSL Key Path |
Public endpoints this module exposes
The module serves 5 externally reachable endpoints. Each path is relative to your Odoo base URL (web.base.url), so a full address looks like https://erp.example.com/saas/api/v1/analytics.
| Endpoint | Method | Auth | Purpose |
|---|---|---|---|
/saas/api/v1/analytics | GET | Public (unauthenticated) | Get analytics data via API |
/saas/api/v1/instances | GET | Public (unauthenticated) | Get SaaS instances via API |
/saas/api/v1/instances/<int:instance_id> | GET | Public (unauthenticated) | Get specific SaaS instance via API |
/saas/api/v1/webhooks | POST | Public (unauthenticated) | Handle incoming webhooks |
/saas/pricing | POST | Public (unauthenticated) | Externally reachable endpoint exposed by the module. |
These paths answer without an Odoo user session — that is what makes them reachable from outside your database. Register each one where the platform expects it (a webhook callback URL, an OAuth redirect URI, or an endpoint your integration calls) exactly as written above; a path the platform does not have on file is never delivered.
Provisioning a New Instance
- Go to SaaS Business Management then Instances then Create Instance
- Fill in the wizard:
- Customer (required) -- the contact the instance belongs to
- Plan (required)
- Subdomain (required) -- for example
mycompanyformycompany.yourdomain.com - Server -- only provisionable servers are listed
- Odoo Version -- 16, 17, 18 or 19
- Custom Domain (optional)
- Trial Instance -- tick to create the instance as a trial
- Notes
- Click one of:
- Create Instance -- creates the instance record in Draft
- Create & Deploy -- creates it and starts deployment immediately
- Deployment creates the database, applies the configuration and moves the instance through Deploying to Running
- Follow progress on the instance record itself -- the Status field and the chatter carry each tracked change
The instance Name is assigned automatically by a sequence; you do not type it. Existing instances are listed under Instances then All Instances, which opens filtered to running instances by default.
Dashboard
SaaS Business Management then Dashboard shows:
- 6 KPI cards -- Total Instances, Monthly Revenue, Active Subscriptions, Server Utilization, New Today, Suspended
- 4 Chart.js charts -- instance trend, revenue trend, server status and subscription status
- A Quick Actions card and a Refresh button for on-demand reload
Instance Lifecycle
An instance carries one of these states:
| State | Description |
|---|---|
| Draft | Created but not yet deployed |
| Deploying | Provisioning in progress |
| Running | Deployed and operational |
| Suspended | Temporarily disabled (payment overdue or manual suspension) |
| Cancelled | Terminated |
Trial status is a separate Trial flag on the instance rather than a state, so a trial instance is Running like any other. An Expiration Date governs when it lapses, and the default trial length comes from Trial Duration (Days) in Settings.
Subscriptions have their own states: Draft, Active, Suspended, Cancelled and Expired.
Customer Portal
Customers sign in to your Odoo and manage their own instances under /my/saas:
| Path | Purpose |
|---|---|
/my/saas | Portal home |
/my/saas/instances | Their instances, and per-instance actions |
/my/saas/subscriptions | Subscriptions |
/my/saas/billing | Billing records |
/my/saas/usage | Usage metrics |
/my/saas/plans | Available plans, and self-service subscribe |
/my/saas/api-keys | Create and revoke API keys; the create form itself is posted to /my/saas/api-keys/create |
/my/saas/support | Support requests |
REST API
Instances can be managed programmatically under /saas/api/v1/instances, supporting GET, POST, PUT and DELETE. API keys are issued from the customer portal.
Backups and Migration
- Backup and restore run from the backup wizard on an instance: choose the operation and backup type, optionally include logs and compress the archive, and watch progress on the wizard.
- Migration runs from the migration wizard: pick a migration type, source and target Odoo version, the instances or servers in scope, and a maintenance window. Backup before migration, validation, customer notification and rollback on failure are all switchable, with a maximum downtime setting.
Troubleshooting
| Issue | Solution |
|---|---|
| No server appears in the creation wizard | The server must be Active, its Connection Status must be Connected, and Available Slots must be above zero. Open Configuration then Servers and run Test Connection. |
| "Selected server cannot host new instances" | The server is inactive, unreachable or full. Choose another server or raise its Max Instances. |
| Provisioning failed | Check PostgreSQL permissions, disk space on the host, and that Docker is running and reachable over SSH. |
| Instance not accessible | Verify DNS for the subdomain or custom domain, and the Odoo proxy configuration. |
| Billing not processing | Confirm the instance has a plan assigned and an active subscription. |
| Backup failures | Check backup storage permissions and available disk space. |
| Migration stuck | Review the migration wizard's status message and confirm the target version is valid for the instance. |