Integrations
Sadeem integrates with six categories of external services to provision and manage customer Odoo instances. Each integration follows the same pattern: a connector model stores credentials, a Test Connection action validates them, and service-specific methods perform operations.
Integration Summary
| Service | Connector Model | Test Action | Operations |
|---|---|---|---|
| Cloudflare DNS | sadeem.cloudflare.account |
Test Connection on account | Create / update / delete / check A records |
| Nginx Proxy Manager | sadeem.nginx.server |
Test Connection on server | Create / enable / disable / delete proxy hosts |
| Portainer | sadeem.portainer.server |
Test Connection on server | Create / start / stop / delete Docker stacks |
| Root Server (SSH) | sadeem.root.server |
Test SSH Connection | Execute commands, upload files, monitor |
| Backup Server | sadeem.saas.backup.server |
Test Connection on record | Register subscriptions, query backup state |
| Notification Server | sadeem.ntfy.server |
Test Connection | Create / revoke tokens, send notifications |
| PostgreSQL Server | sadeem.postgresql.server |
(no dedicated test action) | Referenced by Docker stacks for DB configuration |
Cloudflare DNS
Module: sadeem_cloudflare
The Cloudflare integration manages DNS A records for subscription domains. The account record stores the API credentials; each subscription domain gets its own sadeem.cloudflare.record child record.
Models:
sadeem.cloudflare.account— stores API token and email addresssadeem.cloudflare.record— one record per subscription domain; storescloudflare_id,target(IP),proxied,ttl,zone_id
Key methods on sadeem.cloudflare.record:
| Method | What it does |
|---|---|
action_create_cloudflare_record() |
Creates a new A record in Cloudflare for the domain |
action_check_status() |
Queries Cloudflare and updates the local record state |
action_delete_cloudflare_record() |
Removes the A record from Cloudflare |
Tip
Set Auto Create DNS on the Portainer environment or DBFilter server to have Sadeem create Cloudflare records automatically when a subscription is built.
Developer reference: sadeem_cloudflare Reference
Nginx Proxy Manager
Module: sadeem_nginx_proxy_manager
The NPM integration manages reverse proxy hosts and SSL certificates for each subscription domain.
Models:
sadeem.nginx.server— stores NPM API base URL, admin email, and passwordsadeem.nginx.host— one record per domain/stage; storesnginx_id(NPM's internal proxy host ID),state,certificate_id
Key methods on sadeem.nginx.host:
| Method | What it does |
|---|---|
action_check_status() |
Queries NPM and syncs the local host state |
nginx_manager_host_action(action) |
Runs a lifecycle action: create, update, enable, disable, or delete |
Warning
Deleting a proxy host in NPM does not delete the sadeem.nginx.host record in Odoo. Always use Sadeem's Delete action to keep both in sync.
Developer reference: sadeem_nginx_proxy_manager Reference
Portainer
Module: sadeem_portainer
The Portainer integration manages Docker stack lifecycle — creation, startup, shutdown, and deletion.
Models:
sadeem.portainer.server— stores Portainer server URL and API keysadeem.portainer.environment— maps to a Portainer endpoint; carries server-level defaults (Nginx server, Cloudflare account, domain suffix, PostgreSQL server, backup server,next_port)sadeem.portainer.image— Docker image definition with a stack YAML template
Key methods on sadeem.subscription.stage:
| Method | What it does |
|---|---|
action_portainer_create_stack() |
Deploys a new Docker stack from the image template |
action_get_stack_status() |
Polls Portainer for the current stack status |
action_stack_actions() |
Runs lifecycle operations: start, stop, redeploy, delete |
Note
The next_port counter on sadeem.portainer.environment is incremented automatically each time a new stack is created, ensuring port uniqueness across the environment.
Developer reference: sadeem_portainer Reference
Root Server (SSH)
Module: sadeem_saas_base
The root server connector provides direct SSH access to the servers running your infrastructure. It is used for Git operations, log tailing, and low-level administration.
Model: sadeem.root.server — stores IP address, SSH port, username, password or key, and sudo_user
Key method:
root_server.ssh_connect(
commands=[...], # list of shell commands to run
files=[...], # list of files to upload before running commands
return_output=True,
sudo=False
)
The method opens a paramiko SSH session, optionally uploads files, runs each command, and returns output if requested.
Warning
Commands are validated through is_safe_command() in sadeem_saas_docker/utils/utils.py before execution. Never pass user-supplied strings directly as commands.
Developer reference: sadeem_saas_base Infrastructure Reference
Backup Server
Module: sadeem_saas_base
The backup server connector links the Master Odoo to a separate Odoo instance running sadeem_saas_backup_manager. Communication is via HTTP API using an API key.
Models:
sadeem.saas.backup.server— stores base URL, download URL (for browser-side downloads), and API keysadeem.saas.backup.cloud.account— cloud/S3 storage accounts synced from the backup server
Key methods:
| Method | What it does |
|---|---|
action_create_backup_record() |
Registers a subscription with the backup server for scheduled backups |
action_get_backup_line() |
Queries the backup server for the list of backups for a subscription |
Cloud accounts are synced through a wizard (sadeem.saas.backup.cloud.account.wizard) that calls GET /sadeem/backup/cloud-accounts on the backup server and lets the operator select which accounts to associate.
Developer reference: sadeem_saas_base Backup Reference
Notification Server
Module: sadeem_saas_base
The notification server connector integrates with an ntfy-compatible push notification server for operator alerts.
Model: sadeem.ntfy.server — stores server URL and credentials
Operations: create and revoke access tokens, send push notifications triggered by subscription lifecycle events.
PostgreSQL Server
Module: sadeem_portainer / sadeem_saas_base
Model: sadeem.postgresql.server — stores connection details for a PostgreSQL instance
The PostgreSQL server record is referenced by sadeem.portainer.environment and injected into Docker stack templates as the DB_HOST, DB_PORT, and related environment variables. There is no dedicated test action — connection details are validated indirectly when a stack is deployed.
Adding a New Integration
Follow this pattern when building a custom service connector:
- Create a connector model (e.g.,
sadeem.my_service) with fields for all required credentials - Add a Test Connection action that validates the credentials and calls
message_post()on the record with the result — success or failure - Create service-specific operation methods, or extend
sadeem.subscriptionvia_inheritto add the integration to the subscription lifecycle - Return
(message, error)tuples from connector methods, consistent with all existing connectors - Store sensitive fields (API keys, passwords) using
encryption_actions()fromsadeem_saas_base/utils/utils.py
Tip
Look at sadeem_cloudflare as the simplest example of a complete integration — it has one account model, one record model, and three lifecycle methods.