Open HRMS
Overview
This guide covers deploying and configuring Open HRMS on Ubuntu 24.04 on Azure with a SecureAnyCloud Azure Marketplace image. Open HRMS is the open source human resource management suite from Cybrosys Technologies, delivered as a set of modules built on Odoo 18 Community Edition.
It covers the whole employee lifecycle in one system: employee records and documents, contracts and working shifts, attendance with regularisation, leave and holiday approval, community payroll with salary rules and payslips, appraisals, loans and salary advances, gratuity settlement, insurance, custody of company assets, disciplinary tracking, resignation and transfer workflows, service requests, and an HR dashboard that brings the whole picture together.
The SecureAnyCloud image ships Odoo 18 Community (LGPL-3, installed from the project's own dated release, pinned and SHA-256 verified). It includes 33 Open HRMS modules (LGPL-3 and AGPL-3), already installed and with their schema migrated, on on-box PostgreSQL 16. nginx terminates TLS as the single public listener. Odoo and PostgreSQL bind to the loopback interface only.
The database manager is blocked at the front door, and the database is built without demo data. Everything unique is minted per VM on first boot: the PostgreSQL password, the Odoo master password, a self-signed TLS certificate and the administrator password.
Odoo is a trademark of Odoo S.A. Open HRMS is a product name of Cybrosys Technologies. SecureAnyCloud produces this image and is not affiliated with, endorsed by, or sponsored by either. It ships the free and open source software unmodified. The corresponding sources are Odoo Community (https://github.com/odoo/odoo, branch 18.0) and Open HRMS (https://github.com/CybroOdoo/OpenHRMS, branch 18.0).
What you get:
- Odoo 18 Community Edition: the project's own dated release, pinned by URL and SHA-256 and installed from a single package file, so no third-party APT source is left on the VM
- 33 Open HRMS modules: from the project's 18.0 line, pinned to an exact upstream commit and shipped unmodified, with the schema already migrated
- PostgreSQL 16: the application database, bound to loopback with no host port published
- nginx: the single public listener, terminating TLS, with an HTTP to HTTPS redirect and correct proxy headers
- First-boot secret generation: the database password, Odoo master password, TLS certificate and administrator password, all unique to each VM
- A bundled self-test: signs in as the per-instance administrator, creates an employee record, reads it back, finds it by search and deletes it, which proves the suite works end to end
- 24/7 SecureAnyCloud support
Prerequisites
Before you deploy, make sure you have:
- An Azure subscription with permission to create virtual machines
- An SSH key pair for administrative access
- A network security group that allows inbound TCP 22 (SSH) and TCP 443 (HTTPS) from your own address ranges
- A
Standard_D2s_v3VM size (2 vCPU, 8 GB RAM) or larger. Odoo runs two worker processes alongside PostgreSQL on the same VM, so 8 GB is the practical floor. Choose more memory and a larger disk as your headcount and attachment volume grow.
Deploy from the Azure Portal
- Open the Azure Marketplace and search for Open HRMS on Ubuntu 24.04 LTS by SecureAnyCloud.
- Select Create, then choose your subscription, resource group and region.
- Pick a VM size of
Standard_D2s_v3or larger. - Under Administrator account, select SSH public key and supply your public key.
- Under Inbound port rules, allow SSH (22) and HTTPS (443).
- Select Review + create, then Create.
Deploy from the Azure CLI
Create a resource group, accept the Marketplace terms, then create the VM and open port 443.
az group create --name openhrms-rg --location eastusaz vm image terms accept --urn sac1647283583153:openhrms-ubuntu-24-04:default:latest
az vm create \
--resource-group openhrms-rg \
--name openhrms-vm \
--image sac1647283583153:openhrms-ubuntu-24-04:default:latest \
--size Standard_D2s_v3 \
--admin-username azureuser \
--generate-ssh-keys \
--public-ip-sku Standard
az vm open-port --resource-group openhrms-rg --name openhrms-vm --port 443 --priority 1010First boot takes a couple of minutes. The VM does the following:
- Creates its own PostgreSQL password, Odoo master password, TLS certificate and administrator password.
- Sets the administrator credential through Odoo's own password hasher.
- Starts the application.
- Proves the whole stack with the bundled self-test before it reports ready.
Connect over SSH
Connect to the VM.
ssh azureuser@<public-ip>Confirm the services are running
Check that all five services are active.
systemctl is-active postgresql nginx openhrms-tls odoo openhrms-firstbootYou should see output like this.
active active active active activeopenhrms-tls is a one-shot unit that mints this VM's TLS certificate before nginx starts. openhrms-firstboot is the one-shot unit that created every secret. Both report active after they complete.
Check the versions and the installed module set
Check the Odoo version, the number of staged Open HRMS modules, and the number of installed modules.
dpkg-query -W -f='${Version}\n' odools /opt/openhrms/addons | grep -vE '^(LICENSE|README.md)$' | wc -lsudo -u postgres psql -d openhrms -tAc "select count(*) from ir_module_module where state='installed'"You should see output like this.
18.0.20260909 33 13333 Open HRMS modules are staged on disk. 133 Odoo modules are installed in the database, which is the Open HRMS set plus every Odoo Community module they depend on.
Three modules from the upstream repository are deliberately not shipped, and the image asserts their absence at build time:
- ent_uae_wps_report: Declares the Odoo Proprietary License (OPL-1), which forbids redistribution, and is the only module in the set that depends on Odoo Enterprise addons. The LGPL-3 module uae_wps_report provides the same UAE WPS report on Community payroll and is included.
- oh_hr_zk_attendance: Integrates physical ZKTeco biometric terminals through the PyPI packages zklib (last released 2015) and pyzk (last released 2019), both abandoned and predating Python 3.12. It cannot function without the hardware on your LAN.
- hr_company_policy: Its browser-side template targets an element that the Open HRMS dashboard no longer renders at this release, which breaks the dashboard outright for every user. It is excluded rather than patched, so the image keeps shipping upstream code unmodified.
You can install any of them yourself from the upstream repository if your deployment needs them.
Retrieve the per instance credentials
Every secret on this VM was created on this VM. Read them as root.
sudo cat /root/openhrms-credentials.txtYou should see output like this. Your values will differ, because every VM creates its own.
# Open HRMS on Ubuntu 24.04 — Per-VM Instance Info
# Generated: <generation timestamp>
#
# Every secret below was generated on THIS virtual machine at first boot. None was baked into
# the image and no two sac VMs share any of them. Keep this file secret.
# OPENHRMS_ADMIN_USER=admin OPENHRMS_ADMIN_PASSWORD=<set-at-first-boot> OPENHRMS_URL=https://<your VM's public IP>/ OPENHRMS_DB_NAME=openhrmsThe Odoo master password and the PostgreSQL password are not in that file. They live in /etc/odoo/odoo.conf, which only root and the odoo service account can read. Check the permissions.
sudo stat -c '%a %U:%G %n' /root/openhrms-credentials.txt /etc/odoo/odoo.confYou should see output like this.
600 root:root /root/openhrms-credentials.txt 640 root:odoo /etc/odoo/odoo.confReview the security posture
Only three TCP ports face the network. Odoo's HTTP worker (8069), its websocket worker (8072) and PostgreSQL (5432) are bound to loopback and cannot be reached from outside the VM. List the listeners.
ss -tlnH | awk '{print $4}' | sort -uYou should see output like this.
0.0.0.0:22 0.0.0.0:443 0.0.0.0:80 127.0.0.1:5432 127.0.0.1:8069 127.0.0.1:8072 127.0.0.53%lo:53 127.0.0.54:53 [::]:22 [::]:443 [::]:80The database manager is blocked. Odoo's built-in manager serves its Create, Duplicate, Backup and Restore forms to an unauthenticated visitor even when database listing is switched off. So this image blocks the whole /web/database path at nginx, as well as setting list_db = False. Test the paths.
for U in /healthz /web/health /web/login /web/database/manager /web/database/create /web/database/selector; do printf '%-28s %s\n' "$U" "$(curl -sk -o /dev/null -w '%{http_code}' https://127.0.0.1$U)" doneYou should see output like this.
/healthz 200 /web/health 200 /web/login 200 /web/database/manager 404 /web/database/create 404 /web/database/selector 404Plain HTTP only redirects. Confirm it.
curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1/You should see this output.
301Prove the whole stack with the bundled self-test
Run the self-test.
sudo /usr/local/bin/openhrms-selftestThis is a real feature round trip, not a page load. The test does the following:
- Checks the TLS front door and the HTTP redirect
- Confirms that the login page and its stylesheet and script bundles are served with the right content types
- Confirms that the database manager refuses to serve
- Rejects a deliberately wrong password
- Signs in with this VM's own administrator credential
- Reads all 33 Open HRMS modules back as installed
- Resolves the Open HRMS dashboard
- Creates an employee record, reads it back field by field, finds it by name search and deletes it, then checks that the employee count returns to where it started
- Asserts the exact set of network-facing ports
You should see output like this.
OK openhrms self-test passed: healthz 200, :80 301, login page + text/css + javascript served, /web/health pass, database manager refuses to serve, wrong password rejected, per-VM admin authenticated, all 33 Open HRMS modules installed (both excluded modules absent), dashboard action resolves, hr.employee create/read/search/delete round-trip OK with the count back to 1, backend asset bundle compiled (1185944 bytes of real CSS), anonymous RPC refused, exposed ports exactly {22,80,443}, Odoo 8069/8072 + PostgreSQL 5432 loopback-onlySign in
Open https://<your VM's public IP>/ in a browser. The certificate is self-signed and created on your VM, so your browser warns once. Accept it, or replace the certificate as described in Step 14.
Sign in with the username and password from /root/openhrms-credentials.txt.
The sign-in page is wrapped in Odoo's public website layout with sample content, because the Website module is a dependency of the Open HRMS Employee Background Verification module. After you sign in, you can edit or unpublish those public pages from the Website app.
The Open HRMS dashboard
Signing in lands you on the Open HRMS dashboard, the suite's home view. It draws your own figures from the database: payslip, timesheet and contract counts, the broad factor absence score, a check-in control, and panels for attendance, leave, expenses and projects. It also shows upcoming birthdays, events and announcements.
Further down are the leave and skill analyses, leave request and allocation counts, job applications, departments, and the monthly join, resign and attrition charts.
Add your first employee
- Open the Employees app from the app menu.
- Select New, enter the person's name and job title, and fill in the work email and department.
- Save.
The employee form is Odoo's own, extended by Open HRMS. It adds extra tabs for Insurance and Employee History, smart buttons for Disciplinary Action and Announcements, and menu entries for Document Templates, Legal Actions, Services and Loans & Advances.
The image ships with a single employee record, Administrator, which Odoo's own HR module creates and links to the administrator account.
There is no demo data of any kind: no sample company beyond the default, and no invented employees, contracts or payslips.
Review the installed Open HRMS modules
Open the Apps app, clear the default Apps filter, and search for Open HRMS. Every module in the result set is already installed, so none of them shows an Activate button.
You can confirm the same thing from the shell.
sudo -u postgres psql -d openhrms -tAc "select count(*) from ir_module_module where state='installed' and (name like 'ohrms\_%' or name like 'oh\_%' or name like 'hrms\_%')"You should see this output.
12That counts only the modules whose technical name carries an Open HRMS prefix. The rest of the suite uses hr_-prefixed names shared with Odoo's own HR modules, which is why the full staged count in Step 5 is 33.
Day-to-day operations
Here is where to find each part of the suite.
- Departments and job positions: Employees > Configuration
- Working schedules and shifts: Employees > Configuration > Working Schedules, and the Open HRMS Employee Shift module for shift rosters
- Attendance: the Attendances app, with Open HRMS Attendance Regularization for correcting missed check-ins
- Leave: the Time Off app, with Open HRMS Leave Multi-Level Approval for multi-stage approval chains and Leave Request Aliasing for requests by email
- Payroll: the Payroll app provided by the Open HRMS community payroll modules, covering salary structures, salary rules, contracts and payslips
- Loans and advances: Open HRMS Loan Management and Advance Salary, with the accounting bridge in Loan Accounting
- Appraisals, custody, insurance, resignation, transfer and legal actions: each has its own menu after you sign in
Replace the TLS certificate
The shipped certificate is self-signed and created on your VM. For production, point a DNS name at the VM and install a CA-signed certificate. Place the certificate and key at /etc/nginx/tls/openhrms.crt and /etc/nginx/tls/openhrms.key, keep the key mode 0600, then reload nginx.
If you use Let's Encrypt, install certbot and issue the certificate against your own domain.
sudo apt-get install -y certbot python3-certbot-nginx
sudo certbot --nginx -d your-domain.example.comAfter you change the hostname that customers use, update Odoo's own base URL so generated links point at it. Sign in as the administrator and enable the developer tools. Then open Settings > Technical > System Parameters and set web.base.url to your HTTPS URL.
The image sets web.base.url.freeze to True deliberately, so Odoo does not silently overwrite that value with whatever host an administrator last signed in from.
Back up the database
The whole application state is the PostgreSQL database plus Odoo's filestore. Back up both.
sudo -u postgres pg_dump -Fc openhrms > /var/backups/openhrms-$(date +%F).dump
sudo tar czf /var/backups/openhrms-filestore-$(date +%F).tar.gz -C /var/lib/odoo filestoreOdoo's own browser-based backup tool is not available on this image, because the database manager it lives in is blocked at the front door. pg_dump is the supported path, and it is what you should schedule.
Logs and troubleshooting
Read the Odoo server log and the Odoo journal.
sudo tail -20 /var/log/odoo/odoo-server.logsudo journalctl -u odoo --no-pager | tail -20The first-boot log records everything that was created on this VM.
sudo tail -20 /var/log/sac/sac-firstboot.logIf the web interface is unreachable, work outwards:
- Check
systemctl is-active odoo nginx postgresql. - Confirm that Odoo is answering on loopback with
curl -sf http://127.0.0.1:8069/web/health. - Check that your network security group allows inbound 443.
You can re-run sudo /usr/local/bin/openhrms-selftest at any time. It tells you exactly which layer is broken.
Security notes
- No credential is baked into the image. It ships with every user's password column empty, no
/etc/odoo/odoo.confat all, the PostgreSQL role password reset to a value that is generated and immediately discarded, and no TLS key. systemd gates Odoo itself, and it refuses to start until first boot has written this VM's own configuration. There is no window in which the appliance is reachable with a shared secret. - Odoo and PostgreSQL never face the network. nginx on 443 is the only application listener. Port 80 exists solely to redirect.
- The database manager is blocked. Nobody can list, create, duplicate, drop, back up or restore a database from a browser, with or without the master password.
- Self-registration is not available. Odoo's sign-up flow is not enabled on this image, so an administrator creates accounts from Settings > Users.
- Unattended security upgrades remain enabled, exactly as stock Ubuntu, so the VM keeps patching itself.
- The certificate is self-signed per VM. Replace it with a CA-signed certificate before you put the system in front of staff.
Licensing
Odoo Community Edition is licensed under the LGPL version 3. The Open HRMS modules shipped here are licensed under the LGPL version 3 (28 modules) and the GNU Affero General Public License v3 (5 modules), and are shipped unmodified from the upstream repository at a pinned commit.
There is no per-user or per-employee fee for the software. The SecureAnyCloud charge covers packaging, security hardening, patching, image maintenance and 24/7 support.
The VM records the provenance of everything in the image, including the exact Odoo package and checksum and the exact Open HRMS commit. Read it.
cat /usr/share/doc/openhrms/PROVENANCESecureAnyCloud is not affiliated with, endorsed by or sponsored by Odoo S.A. or Cybrosys Technologies. The Odoo and Open HRMS names are used only to identify the software this image ships.
Support
SecureAnyCloud provides 24/7 support with a guaranteed 24 hour response SLA. Contact support through the Azure Marketplace listing or at https://secureanycloud.com/.
Deploy on Azure
Launch Open HRMS on Ubuntu 24.04 LTS on Azure with 24/7 support from SecureAnyCloud.
View this image
Need Help?
Our support team is available 24/7.
sales@secureanycloud.com