Skip to content

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

git clone https://github.com/jakapolr/hemms-demo.git
cd hemms-demo

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:

make up-private

Brings up hemms_odoo_private (Odoo on port 8069) plus hemms_db_private (Postgres 15).

make up-gov

Brings up hemms_odoo_gov (Odoo on port 8169) plus hemms_db_gov (Postgres 15).

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:

make logs-private    # or logs-gov

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:

make install-private    # or install-gov

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:

make down-private && make up-private

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:

  1. Go to Settings → Apps, set the filter to Installed, and search for roots_hemms. You should see all ten roots_hemms_* modules plus their OCA dependencies (maintenance_plan, maintenance_stock, sign_oca, etc.).
  2. 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).
  3. 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!):

make reset-private    # or reset-gov

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