Deployment Guide · BaseUp Labs

Installing BaseUp HR on Odoo 18

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, the license check that runs before anything loads, and what to change before a customer touches it.

Data files
100
Version
18.0.0.6
Platform
Odoo 18 Enterprise
License
OPL-1
Odoo deps
26
01

What you get

One module: baseup_human_resources. There are no companion modules to install and no ordering to get right.

PropertyValue
baseup_human_resourcesThe whole suite — nothing else to install
version18.0.0.6
licenseOPL-1 (Odoo Proprietary License v1.0)
applicationFalse — hidden by the default Apps filter
depends26 Odoo modules — see §2
data files100, loaded in a fixed order at install
pre-install hookValidates the license online — see §5
migrationsNone ship with 18.0.0.6 — see §9

Because the module is not flagged as an application, the default Apps filter hides it. Clear the filter before you search for it.

What a first install does

A license check runs first and stops the install if it fails. Then security groups and ACLs load, then views and data — 100 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.

02

Prerequisites

Odoo 18.0 Enterprise. Seven of the twenty-six dependencies are Enterprise-only modules, so the install fails outright on Community — there is no reduced mode.

Odoo module dependencies

EditionModules
Enterprise required hr_payroll · hr_payroll_account · hr_payroll_holidays · hr_expense_extract · sign · accountant · account_accountant
Community standard base · web · mail · account · contacts · hr · hr_contract · hr_gamification · hr_recruitment · hr_attendance · hr_org_chart · hr_holidays · hr_holidays_attendance · hr_skills_survey · l10n_ph · resource · base_geolocalize · sale · portal

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

Two packages the module needs are not declared

The manifest declares external_dependencies: {'python': ['requests']}, so Odoo checks for requests and reports it properly if absent. geopy and sentry-sdk are not declared, yet both are imported when the module loads — a missing one produces an import traceback and the whole module fails to load, not an "unmet dependency" message.

Install them before the module, into the same environment Odoo runs in:

runtime packages · required
pip install requests geopy sentry-sdk
PackageNeeded forIf missing
requestsLicense validation, BaseUp connectionDeclared — Odoo reports it as an unmet dependency. Odoo 18 requires it anyway
geopyReverse-geocoding work addresses for geofenced check-inUndeclared. Import error at module load — the whole module fails, not just geofencing
sentry-sdkError reporting to BaseUp Labs (§6)Undeclared. Import error at module load
pypdf or PyPDF2BIR Form 2316 PDF fillingImported at module load, with a fallback from pypdf to PyPDF2. Odoo 18's own requirements include PyPDF2, so a standard Odoo install already has it

xlsxwriter and babel are imported too, but both are part of Odoo 18's own requirements and need nothing extra.

Do not pip install -r requirements.txt

The requirements.txt at the repository root is a development file, not a runtime list. Alongside geopy, sentry-sdk and the PDF libraries it carries test-only packages (faker, coverage) and packages the module does not import (PyMuPDF, paramiko, pandas). Use the pip install line above instead.

Server

  • Python and PostgreSQL — whatever your Odoo 18 build requires (Odoo 18 needs Python 3.10 or later); this module adds no constraint of its own.
  • Outbound HTTPS — required, not optional: the license is validated online at install and again during use. Chart.js, error reporting and reverse geocoding also reach out. See §6.
  • Timezone — schedules and every payroll computation localise to Asia/Manila by default.
03

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.

  1. Buy the module and download the archive from your Odoo account's purchases.
  2. 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.
  3. Note the version in baseup_human_resources/__manifest__.py and check it matches what you expect (18.0.0.6 at the time of writing). An 18.0.* version only runs on Odoo 18.
  4. Have the four license values from BaseUp to hand (§5). The install cannot proceed without them.
Not into Odoo's own addons directory

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.

04

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

directory 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/

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.

odoo.conf
[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
ownership
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 {} \;
Check for sync artefacts before deploying

File-sync tools sometimes leave duplicate copies with a space and a number in the name — views 2/, or foo 2.py. A duplicate inside a package Odoo imports is dead weight at best and shadows the real file at worst; either way it should not ship. Sweep for them: find . -name "* 2" -o -name "* 2.py".

05

Install

Set the license parameters first

The module's pre-install hook reads four system parameters and validates them against BaseUp's license server (https://odoo.baseup.co/api/license/validate), sending them with the server's IP address. If any parameter is missing, or the server says no, or it cannot be reached, the install stops with a License Key Required or License Validation Failed message before a single data file loads.

Settings ▸ Technical ▸ System Parameters
baseup_hr.license_key   # your license key
baseup_hr.fingerprint   # fingerprint issued with the license
baseup_hr.module_name   # module name issued with the license
baseup_hr.hostname      # this server's hostname

On a brand-new database, create it with -i base first, then set the parameters from developer mode, or from an Odoo shell:

odoo shell · set the license parameters
sudo -u odoo /opt/odoo/venv/bin/python /opt/odoo/odoo-bin shell \
  -c /etc/odoo/odoo.conf -d <database>

>>> icp = env['ir.config_parameter']
>>> icp.set_param('baseup_hr.license_key', '<key>')
>>> icp.set_param('baseup_hr.fingerprint', '<fingerprint>')
>>> icp.set_param('baseup_hr.module_name', '<module name>')
>>> icp.set_param('baseup_hr.hostname', '<hostname>')
>>> env.cr.commit()

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.

install the module
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

  1. Restart the Odoo service so the new addons path is picked up.
  2. Enable developer mode, set the four license parameters under Settings ▸ Technical ▸ System Parameters, then go to Apps and click Update Apps List. Without this the module will not appear at all.
  3. Remove the Apps filter from the search bar — the module is not flagged as an application — then search Baseup and install Baseup Human Resources.
What happens on install

After the license check, one hundred 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, a six-row annual tax table, 23 overtime rate rows, the ND rate table, leave types, HR case types and the BIR 2316 PDF template — and registers its scheduled jobs. A fresh install is ready to configure, not empty.

Databases that ran the older baseup_hr module

The same hook looks for records of the earlier baseup_hr module. If it finds them it hands the fiscal year and salary journal over to baseup_human_resources, deletes the rest of baseup_hr's external ids and its module record, and fills a missing fiscal year on existing payslips. Back up first.

06

Configure

Four things to settle before handing the database over. The functional setup — periods, schedules, contracts — is covered in the Operator Guide; this is the deployment layer.

The license keeps checking

Validation does not end at install. Every backend page request by a logged-in user checks the license, using a cached result for 24 hours and calling the license server again once that expires. If the server is unreachable, a check that succeeded within the last 48 hours is accepted. Past that, or if the server rejects the license, backend pages return 403 Forbidden with the license message until it validates again.

The result is cached in two system parameters, baseup_hr.license_status and baseup_hr.last_license_check. They are the first place to look when users report a 403.

Outbound network access

HostUsed byIf blocked
odoo.baseup.coLicense validation, at install and every 24 hours of useInstall fails; once the 48-hour grace runs out, the backend returns 403
cdn.jsdelivr.netChart.js, for the HR dashboardDashboard charts do not render
*.ingest.us.sentry.ioError reports to BaseUp LabsNothing visible; errors are not reported
nominatim.openstreetmap.orgReverse-geocoding a work address when it is geolocated, for geofenced check-inGeolocating a work address errors, so geofencing cannot be set up
api.baseuplabs.comOnly if you use Connect to BaseUp in SettingsThe connection cannot be made; nothing else is affected
Error reporting is on by default

On load the module starts the Sentry SDK with a BaseUp Labs project key compiled into the code. Anything logged at error level is sent to Sentry with its traceback, the module version, the server's hostname and the log lines leading up to it. There is no setting to turn it off; the environment tag can be set with the SENTRY_ENV variable or a sentry_environment option in odoo.conf. If the customer's policy does not allow it, block the Sentry host at the firewall.

Air-gapped or CDN-restricted deployments

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. A fully air-gapped deployment is not possible: the license check needs odoo.baseup.co.

Mail and branding

  • SMTP From — set it on the outgoing mail server, or outgoing payslips and notices go out with the wrong sender.
  • System name — the app_system_name parameter 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

Six jobs are created and enabled. Review them against the deployment before go-live, particularly the two biometric jobs, which will try to contact terminals that may not exist yet.

  • Auto Import Biometric Attendance · Download Attendance
  • Leave Allocation: Check Validity
  • Employee: Years in Service · Employee: Compute Age
  • HR Employee Data Expiration
07

Verify

A clean install is not the same as a working one. Seven checks, in this order.

  1. Module state. Apps shows Baseup Human Resources as Installed at 18.0.0.6.
  2. License cached. After opening any backend page, baseup_hr.license_status reads valid in System Parameters.
  3. Menus. Employees, Attendances, Overtime, Leaves, Payroll and Salary Loans all appear for an administrator.
  4. Statutory data loaded. Payroll ▸ Configuration ▸ Premiums and Tax Tables — SSS should hold the activated Circular 2024-006 schedule, the Withholding Tax Table 24 bracket rows and the Annual Tax Table six.
  5. Dashboard renders. Employees ▸ Dashboard. If the counts appear but the charts do not, Chart.js is being blocked — see §6.
  6. BIR report works. Open any employee, then the Print menu ▸ BIR Form 2316. A PDF must come back.
  7. 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.
Faster than reading procedures

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 and the chart of accounts. Run them from developer mode; on a fresh deployment they double as a functional smoke test.

08

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.

Treat the license parameters as credentials

The four baseup_hr.* parameters from §5 identify this deployment to BaseUp's license server. Any user who can open Settings ▸ Technical ▸ System Parameters can read them, so keep administrator rights to the people who need them, and ask BaseUp for new values if the database changes hands.

Decide on error reporting

Errors, with their tracebacks and preceding log lines, go to BaseUp Labs' Sentry project (§6). Log lines can carry record names and other business data. Tell the customer, and block the Sentry host if their data policy requires it.

Standard Odoo hardening

  • Set admin_passwd in odoo.conf and keep the database manager off the public interface — list_db = False, or block /web/database/ at the proxy.
  • Leave /baseup_connect/verify reachable only if you use Connect to BaseUp. It is public by design and answers only during a five-minute connection handshake; otherwise it returns 404.
  • Review each user's groups. A login made with Create User on the employee form gets Employee Own Data, unless the employee is flagged HR Manager or Payroll Master, in which case it gets the HR, leave, contract, recruitment, attendance and payroll manager groups.
  • Serve the instance over HTTPS only, with proxy_mode = True set in odoo.conf.
09

Upgrading

Replace the files and run an update. Take a backup first — payroll data is not reconstructible.

upgrade
# 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
  • No migration scripts — 18.0.0.6 ships no migrations/ directory, so an update reloads views and data and relies on the ORM for schema changes.
  • The install-time license check does not re-run — Odoo runs a pre-install hook only on install. The runtime check in §6 still applies after the upgrade.
  • Staying on Odoo 18 — 18.0.* packages are the Odoo 18 line. The 19.0 package is a separate series for Odoo 19 and is not an upgrade path within Odoo 18.
  • 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.
10

Troubleshooting the install

SymptomCauseFix
Module not in Apps Apps list not refreshed, the Apps filter is still on, or the addons path points one level too high Update Apps List; clear the filter; confirm __manifest__.py is one level below a path entry
License Key Required on install One or more baseup_hr.* parameters missing Set all four in System Parameters — §5
License Validation Failed on install License server unreachable, or it rejected the values Allow outbound HTTPS to odoo.baseup.co; check the values with BaseUp
403 Forbidden on backend pages The runtime license check failed — license no longer valid, or the server unreachable for more than 48 hours Check baseup_hr.license_status and the server log for "License validation failed"; restore access to odoo.baseup.co
Unmet dependency on install Running Community, or Enterprise addons path missing Add the enterprise directory to addons_path; §2 lists the seven Enterprise modules
ImportError for geopy or sentry_sdk Undeclared package not installed; both are imported at module load pip install geopy sentry-sdk 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
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 Miscellaneous journal named Salary or coded SAL for that company Accept the Create Journal prompt, or add the 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