Installation¶
This page walks through a complete HEMMS installation on a Linux or macOS host with Docker. The two reference deployments — private and gov — are isolated Compose stacks that share the same hemms-odoo:18.0 image. Pick whichever matches the customer profile, or run both side by side on different ports for testing.
Looking for the quick start?
Get Started → Installation is the lighter walkthrough aimed at evaluators. This page is the operations-grade install: it covers production-relevant details (master password, ports, addons mount, verification) that the quick start glosses over.
System requirements¶
| Resource | Minimum (demo) | Recommended (production) |
|---|---|---|
| OS | macOS 13+ / Linux (Ubuntu 22.04+ / RHEL 8+) | Linux (Ubuntu 22.04 LTS) |
| Docker | 24+ with Compose v2 | 24+ with Compose v2 |
| RAM | 4 GB free | 8–16 GB |
| Disk | 10 GB free | 50+ GB (DB + filestore + backups grow) |
| CPU | 2 cores | 4+ cores |
| Network | Outbound HTTPS for image pulls + Google Fonts | Outbound HTTPS, plus inbound 8069/8169 if remote |
Docker Compose v2 syntax
The Makefile and these docs use docker compose (the v2 plugin, with a space), not the legacy docker-compose (with a hyphen) binary. If docker compose version prints an error, install Docker Desktop or the docker-compose-plugin package.
Step 1 — Clone the repository¶
The repo ships everything you need: the Dockerfile that builds the HEMMS Odoo image (Odoo 18 + Sarabun + Noto Sans Thai), all vendored OCA addons under addons/oca/, and all custom roots_hemms_* modules under addons/roots/.
Step 2 — Start the sandbox¶
Pick the deployment profile:
The first run takes a few minutes — Docker has to build the custom image, fetch the Thai fonts from Google Fonts via the Dockerfile, and pull the postgres:15 image. Subsequent runs are instant because the image is cached.
Tail the logs to confirm Odoo finished booting:
You should see odoo.modules.loading: Modules loaded. followed by the HTTP listener line.
Step 3 — Install HEMMS modules¶
The Compose stack starts Odoo with an empty database. The next step installs the four leaf modules, which transitively pull every other roots_hemms_* module and every vendored OCA dependency:
Under the hood this runs:
docker compose -f docker-compose.private.yml exec odoo_private \
odoo -c /etc/odoo/odoo.conf \
-d hemms_private \
-i roots_hemms_mass_import,roots_hemms_spare_parts,roots_hemms_signature,roots_hemms_ha_report \
--stop-after-init
| Leaf module | Pulls (transitively) |
|---|---|
roots_hemms_mass_import | Q6 + roots_hemms_ha_report + roots_hemms_pm + roots_hemms_asset_master |
roots_hemms_spare_parts | Q2 + roots_hemms_pm + roots_hemms_asset_master + roots_hemms_criticality |
roots_hemms_signature | Q4 + roots_hemms_asset_inspection + roots_hemms_service_contracts + sign_oca |
roots_hemms_ha_report | Q5 + roots_hemms_signature + roots_hemms_pm + roots_hemms_asset_inspection |
The install runs once and exits (--stop-after-init). Restart the stack so the long-running Odoo process picks up the new modules:
Step 4 — First login¶
Open http://localhost:8069 (private) or http://localhost:8169 (gov).
| Credential | Default value | Where defined |
|---|---|---|
| Database name | hemms_private / hemms_gov | Makefile (PRIVATE_DB / GOV_DB) |
| Login | admin | Odoo default |
| Password | admin | Odoo default |
| Master password (DB Manager) | hemms_private_master (private) | config/odoo.private.conf (admin_passwd) |
Change every default before going live
The master password, admin password, and Postgres credentials in this repo are demo defaults — rotate them all before exposing the instance to anything beyond your laptop. The master password lives in config/odoo.private.conf (and the gov equivalent); the Postgres user and password are set in docker-compose.private.yml (POSTGRES_USER / POSTGRES_PASSWORD). Match the two if you change either.
Step 5 — Verify the install¶
After logging in:
- Go to Settings → Apps, set the filter to Installed, and search for
roots_hemms. You should see all tenroots_hemms_*modules plus their OCA dependencies (maintenance_plan,maintenance_stock,sign_oca, etc.). - Open the Maintenance app. You should see the bilingual menu, the five-stage Thai BME kanban (PM Scheduled / Submitted / Pending Review / In Repair / Awaiting Pickup), and the HEMMS-specific menus (Asset Inspection, Service Contracts, HA Report, Mass Import, Spare Parts).
- Go to HA Report → Annual Reports. The HA Thailand annual PM report model should be available with seeded demo data when you load the demo profile.
If any module is missing, re-run make install-private and check the logs for tracebacks.
Common gotchas¶
Port 8069 / 8169 already in use
Another Odoo instance, Airflow, or anything else binding :8069 will crash the container start. Either stop the conflicting process or edit the ports: mapping in docker-compose.private.yml. The internal port is fixed at 8069; only the host-side port is adjustable.
Database connection refused
If Odoo logs could not connect to server: Connection refused, Postgres has not finished initialising. The Compose file uses depends_on: service_started, not service_healthy, so on slow disks Odoo can race ahead. Either wait 10 seconds and make down-private && make up-private, or run docker logs hemms_db_private to confirm database system is ready to accept connections.
OCA addons not visible in Apps
The addons_path in config/odoo.private.conf points to /mnt/extra-addons/oca,/mnt/extra-addons/roots. That directory is bind- mounted from ./addons. If you cloned the repo but the OCA addons are not under addons/oca/, check that the submodule or vendoring step completed — see addons/oca/README.md in the repo.
default_productivity_apps = False
HEMMS deliberately disables Odoo's default productivity apps (CRM, etc.) via config/odoo.private.conf. If you need to enable them for a customer, set it back to True and restart — do not delete the line.
Resetting the sandbox¶
To blow away the database and filestore and start fresh (destroys all data!):
That drops the Docker volumes (db_private_data, odoo_private_data) and restarts the stack with an empty DB. You will need to re-run make install-private afterwards.
Next steps¶
- First-time Setup — initial Odoo configuration (timezone, language, demo data)
- Users & Permissions — onboard hospital staff
- Backup & Restore — set up nightly backups before the first real go-live
- Upgrade Guide — keep the deployment current