Deployment Guide · BaseUp Labs
Installing BaseUp HR on Odoo 19
From the App Store purchase to a working payroll database — where the files go, what has to be installed first, which Python packages the manifest does not declare, and what to change before a customer touches it.
- Data files
- 103
- Version
- 19.0.1.0.4
- Platform
- Odoo 19 Enterprise
- License
- OPL-1
- Odoo deps
- 26
What you get
One module, one Odoo application: baseup_human_resources. There are no companion
modules to install and no ordering to get right.
| Property | Value |
|---|---|
| baseup_human_resources | The whole suite — nothing else to install |
| version | 19.0.1.0.4 |
| license | OPL-1 (Odoo Proprietary License v1.0) |
| application | True — appears as a tile in Apps |
| depends | 26 Odoo modules — see §2 |
| data files | 103, loaded in a fixed order at install |
| migrations | 2 scripts — see §9 |
Because the module is flagged as an application it shows up under the default Apps
filter, so you do not have to clear the filter to find it.
Security groups and ACLs load first, then views and data — 103 files in a fixed sequence. Run the first install from the command line (§5) so a failure gives you the file that broke rather than a browser error.
Prerequisites
Odoo 19.0 Enterprise. Eight of the twenty-six dependencies are Enterprise-only modules, so the install fails outright on Community — there is no reduced mode.
Odoo module dependencies
| Edition | Modules |
|---|---|
| Enterprise required | hr_payroll · hr_payroll_account · hr_payroll_holidays · hr_appraisal · hr_expense_extract · sign · accountant · account_accountant |
| Community standard | base · web · mail · account · contacts · hr · hr_gamification · hr_recruitment · hr_attendance · hr_org_chart · hr_holidays · hr_holidays_attendance · hr_skills_survey · hr_expense · l10n_ph · resource · base_geolocalize · crm |
All are declared in the manifest and resolved by Odoo automatically — you do not install them by hand. The split matters only for deciding whether your license can run this module at all.
Python packages
The manifest declares external_dependencies: {'python': ['requests']}, so Odoo
checks for requests and reports it properly if absent. The other two packages the
code imports are not declared, so Odoo does not check them — a missing one produces an
import traceback or a feature that fails when used, not an "unmet dependency" message.
Install all three before the module:
pip install requests pypdf geopy
| Package | Needed for | If missing |
|---|---|---|
| requests | License sync, holiday sync | Declared — Odoo reports it as an unmet dependency |
| pypdf or PyPDF2 | BIR Form 2316 PDF filling | Undeclared. Import error at module load — the whole module fails, not just the report |
| geopy | Reverse-geocoding for geofenced check-in | Undeclared, though listed in requirements.txt. Import error at module load — models/attendance/partner.py raises if it is absent |
The pypdf import sits at the top of the BIR report module with a fallback to
PyPDF2. If neither is installed the exception propagates during module load, so this
one is not optional.
The requirements.txt at the repository root is a development file, not a runtime
list. It carries babel and genshi left over from the Aeroo reporting
engine this module has migrated away from, plus test-only packages
(faker, coverage, websocket-client,
html2text). It lists geopy but omits pypdf — the
one whose absence stops the module loading. Use the pip install line above instead.
Server
- Python and PostgreSQL — whatever your Odoo 19 build requires; this module adds no constraint of its own.
- Outbound HTTPS — needed for five things: the license API, the public holiday calendar sync, the contribution-table watch (government and mirror sites), Nominatim reverse-geocoding for geofenced check-in, and
cdn.jsdelivr.net, which serves Chart.js for the HR dashboard. See §6. - Timezone — schedules and every payroll computation localise to
Asia/Manilaby default.
Get the files
The module is distributed through the Odoo App Store. Buy it, download the archive, and unpack it
somewhere outside the addons path before you go near odoo.conf.
- Buy the module and download the archive from your Odoo account's purchases.
- Unzip it somewhere outside the addons path first, and look at what came out. You should find a single directory,
baseup_human_resources. The store metadata sets a limit of one installation per purchase, so check the entitlement before deploying to several databases. - Note the version in
baseup_human_resources/__manifest__.pyand check it matches what you expect (19.0.1.0.4at the time of writing).
Do not unpack the archive into odoo/addons/. That directory belongs to the Odoo
distribution and your files will collide with it when Odoo itself is upgraded. Use a separate
custom addons directory, as in §4.
Put it on the addons path
The single most common install failure. What goes in addons_path is the directory
that contains baseup_human_resources — never the module directory itself, and
never a level higher.
Correct layout
/opt/odoo/custom-addons/ # <- this path goes in odoo.conf └── baseup_human_resources/ ├── __manifest__.py # Odoo looks for this one level down ├── models/ views/ data/ ├── security/ reports/ wizard/ ├── controllers/ static/ └── migrations/
Move baseup_human_resources out of the unpacked archive and into your custom addons
directory, or symlink it there. The one thing that must be true is that Odoo sees a directory
containing __manifest__.py exactly one level below a path entry.
[options] addons_path = /opt/odoo/odoo/addons,/opt/odoo/enterprise,/opt/odoo/custom-addons db_host = localhost db_user = odoo db_password = <set this> admin_passwd = <set this> data_dir = /var/lib/odoo ; the dashboard, kiosk and biometric screens are asset-heavy limit_time_cpu = 600 limit_time_real = 1200 ; several payroll reports build large PDFs limit_memory_hard = 4294967296
chown -R odoo:odoo /opt/odoo/custom-addons
find /opt/odoo/custom-addons -type d -exec chmod 755 {} \;
find /opt/odoo/custom-addons -type f -exec chmod 644 {} \;
File-sync tools sometimes leave duplicate copies with a space and a number in the name
— migrations/19.0.1.0.2 2/, or foo 2.py. Odoo ignores migration
directories whose names do not match a version, so they are inert, but they should not ship.
Sweep for them: find . -name "* 2" -o -name "* 2.py".
Install
From the command line — preferred for a first install
You get the full traceback on stderr instead of a browser error, which matters for a module that loads this many data files.
sudo -u odoo /opt/odoo/venv/bin/python /opt/odoo/odoo-bin \
-c /etc/odoo/odoo.conf \
-d <database> \
-i baseup_human_resources \
--stop-after-init
From the interface
- Restart the Odoo service so the new addons path is picked up.
- Enable developer mode, then go to Apps and click Update Apps List. Without this the module will not appear at all.
- Search
BaseUpand install BaseUp Human Resources. It is flagged as an application, so the defaultAppsfilter will not hide it.
One hundred and three data files load in a fixed order: security groups and ACLs first, then views and data. Along the way the module loads the Philippine statutory tables — the SSS Circular 2024-006 schedule, 24 withholding-tax brackets, 23 overtime rate rows, the ND rate table, leave types and the BIR 2316 PDF template — and registers its scheduled jobs. A fresh install is ready to configure, not empty.
Configure
Four things to set before handing the database over. The functional setup — periods, schedules, approvers — is covered in the Operator Guide; this is the deployment layer.
License parameters
The module ships four system parameters that point at the license service. They are loaded
noupdate="1", so they are written once at install and are not refreshed by
later upgrades — whatever is in the database stays there until you change it.
license.sync_api_url # license service endpoint license.sync_api_email # account used to authenticate license.sync_api_password # credential for that account license.api_key # shared key guarding /api/v1/license and its sub-paths
They arrive carrying defaults. Treat them as placeholders to be replaced with values scoped to this deployment, not as working configuration — see §8, which you should act on before the database is reachable by anyone else.
Outbound network access
| Host | Used by | If blocked |
|---|---|---|
| the license service | Sync Licenses from API, hourly | License records stop refreshing |
| public holiday service | HR Payroll: Sync Country Holidays, daily | Holidays must be entered by hand |
| sss.gov.ph · philhealth.gov.ph · pagibigfund.gov.ph · mpm.ph | HR Payroll: Sync Contribution Tables (SSS/PHIC/HDMF), monthly | Table Watch stops flagging new circulars |
| Nominatim (OpenStreetMap) | geopy reverse-geocoding for geofenced check-in | Geofenced check-in cannot resolve addresses |
| cdn.jsdelivr.net | Chart.js, for the HR dashboard | Dashboard charts do not render |
Chart.js is declared in the backend asset bundle as an unpinned CDN URL
(https://cdn.jsdelivr.net/npm/chart.js). There is no version pin and no local
fallback, so the dashboard depends on a third-party host at page load and on whatever version
that host currently serves. For a locked-down deployment, vendor the library into
static/lib/ and change the asset entry to the local path.
Mail and branding
- SMTP From — set this, or outgoing payslips and notices go out with the wrong sender.
- System name — the
app_system_nameparameter replaces the product name in page titles and browser tabs. - Backend theme — a debranding stylesheet ships in the backend bundle and applies automatically.
Scheduled jobs
Twelve jobs are created and enabled. Review them against the deployment before go-live, particularly the three that reach the network and the two biometric jobs, which will try to contact terminals that may not exist yet.
- Auto Import Biometric Attendance · Download Attendance
- HR Payroll: Sync Country Holidays · Sync Licenses from API
- HR Payroll: Sync Contribution Tables (SSS/PHIC/HDMF) · HR Payroll: Activate Due Circulars
- ZKTeco ADMS: Mark Silent Devices Offline · ZKTeco ADMS: Stage Pushed Punches (catch-up)
- Leave Allocation: Check Validity
- Employee: Years in Service · Employee: Compute Age
- HR Employee Data Expiration
Verify
A clean install is not the same as a working one. Six checks, in this order.
- Module state. Apps shows BaseUp Human Resources as Installed at
19.0.1.0.4. - Menus. Employees, Attendances, Overtime, Leaves, Payroll and Salary Loans all appear for an administrator.
- Statutory data loaded. Payroll ▸ Configuration ▸ Premiums and Tax Tables — SSS should hold the Circular 2024-006 schedule, and Withholding Tax Table 24 bracket rows.
- Dashboard renders. Employees ▸ Dashboard. If the counts appear but the charts do not, Chart.js is being blocked — see §6.
- BIR report works. Open any employee, then the Print menu ▸ BIR Form 2316. A PDF must come back. This is the one check that proves
pypdfis installed, because the failure mode otherwise appears at module load. - Payroll computes. Generate one payroll period, one register and one payslip for a test employee with a running contract, and confirm the statutory deductions are non-zero.
Eleven guided tours ship inside the module's own backend asset bundle — employee creation, payroll configuration, period generation, payslip computation, the register, DTR, leave allocation, overtime configuration, multiple attendance, biometric attendance and the chart of accounts. Run them from developer mode; on a fresh deployment they double as a functional smoke test.
Harden before go-live
Three things to settle before the database is reachable by anyone but you. None are optional on a deployment you are handing to someone else.
Give the license parameters per-deployment values
The four license.* system parameters from §6 ship with placeholder defaults so the
module installs cleanly. Replace every one of them with values issued for this specific deployment,
or clear them and supply the credentials another way. Because they are noupdate, an
upgrade will not overwrite what you set.
Any user who can open Settings ▸ Technical ▸ System Parameters can read these values. Treat them like any other credential in a database you do not solely control: scope them to the deployment, and rotate them if that database changes hands.
Close the license API on customer instances
The module serves a small license API at /api/v1/license and below it, used by BaseUp's own
licensing infrastructure. A customer instance never needs to answer those requests, so do not let
it: block the prefix at the reverse proxy in front of Odoo. Write the rule without a trailing slash — location /api/v1/license/ misses POST /api/v1/license, the route that creates licenses.
location ^~ /api/v1/license {
deny all;
return 404;
}
After deploying, confirm the block is live from a machine that is not the server:
curl -i -X POST https://<host>/api/v1/license should return your 404, not an Odoo
response.
Standard Odoo hardening
- Set
admin_passwdinodoo.confand keep the database manager off the public interface —list_db = False, or block/web/database/at the proxy. - Review the scheduled jobs on any instance that should not reach the network — the license sync, the holiday sync and the contribution-table sync all make outbound calls.
- Confirm which BaseupPH Access profile each user holds. That single field drives every group, ACL and record rule, so it is the whole access-control surface.
- Serve the instance over HTTPS only, with
proxy_mode = Trueset inodoo.conf.
Upgrading
The module ships migration scripts, so upgrades run schema and data fixes automatically. Take a backup anyway — payroll data is not reconstructible.
# 1. back up first — database and filestore pg_dump -Fc <database> > baseup-hr-preupgrade.dump tar czf filestore.tgz /var/lib/odoo/filestore/<database> # 2. replace the module files, then upgrade sudo -u odoo /opt/odoo/venv/bin/python /opt/odoo/odoo-bin \ -c /etc/odoo/odoo.conf -d <database> \ -u baseup_human_resources \ --stop-after-init
- Migration scripts present —
migrations/holds1.0.0and19.0.1.0.4. Odoo runs the ones between the installed version and the new one, so do not skip a version by hand-editing the manifest. - License parameters survive — they are
noupdate, so an upgrade will not undo the hardening in §8. - Watch the log for view errors — this module inherits heavily from the Odoo HR views, which is where an Odoo point-release change usually surfaces first.
Troubleshooting the install
| Symptom | Cause | Fix |
|---|---|---|
| Module not in Apps | Apps list not refreshed, or the addons path points one level too high | Update Apps List; confirm __manifest__.py is one level below a path entry |
| Unmet dependency on install | Running Community, or Enterprise addons path missing | Add the enterprise directory to addons_path; §2 lists the eight Enterprise modules |
ImportError for pypdf / PyPDF2 |
Neither package installed; the import is at module load | pip install pypdf into Odoo's own virtualenv, then restart |
| Module loads, BIR 2316 errors | PDF library present but the template attachment did not load | Upgrade the module to reload data/employee/bir_template_data.xml |
| Dashboard counts but no charts | Chart.js CDN unreachable | Allow cdn.jsdelivr.net, or vendor the library locally — §6 |
ImportError for geopy |
geopy not installed; the import is at module load |
pip install geopy, restart |
| Install fails in security files | A partial earlier install left inconsistent groups | Restore the pre-install backup and reinstall clean; do not patch ACLs by hand |
| Salary journal missing on a register | No journal matching the expected name or code for that company | Accept the guided prompt to create it, or add a sales/salary journal per company |
| Upgrade fails on a view | An inherited Odoo HR view changed in a point release | Read the failing external id in the log; the module inherits hr.view_employee_form heavily |