Skip to content

Modernize Debian and RPM packaging (systemd, dedicated user, CI tests)#663

Open
vharseko wants to merge 4 commits into
OpenIdentityPlatform:masterfrom
vharseko:features/linux-distribution
Open

Modernize Debian and RPM packaging (systemd, dedicated user, CI tests)#663
vharseko wants to merge 4 commits into
OpenIdentityPlatform:masterfrom
vharseko:features/linux-distribution

Conversation

@vharseko

@vharseko vharseko commented Jun 26, 2026

Copy link
Copy Markdown
Member

Why

The opendj-deb/opendj-rpm packaging had drifted from current Linux practice: jdeb 1.3 (2016), SysV-init only with direct update-rc.d/chkconfig calls, no Standards-Version, a 2015 changelog, the server running as root, and the install guide never reflecting any of this. CI also built the .deb/.rpm but never installed or tested them.

What changed

Service management

  • Native systemd unit (resources/systemd/opendj.service, Type=simple, start-ds --nodetach), SysV init kept as a fallback for non-systemd hosts.
  • Register/enable/start via deb-systemd-helper / systemctl with an update-rc.d / chkconfig fallback; stop on removal.
  • AmbientCapabilities=CAP_NET_BIND_SERVICE (+ CapabilityBoundingSet) so the non-root service can still bind privileged ports (LDAP 389, LDAPS 636) without running as root.

Dedicated service account

  • Create an opendj system user/group, chown /opt/opendj to it (migrates root-owned installs on upgrade); run start-ds/stop-ds/upgrade/the service as opendj.

Java discovery (robust to JRE upgrade/reinstall)

  • _script-util.sh: which javacommand -v java (no dependency on the which package; resolves the stable /usr/bin/java).
  • deb postinst / rpm %post pin default.java-home in config/java.properties to a stable symlink.
  • EnvironmentFile for admin overrides: /etc/default/opendj (deb, conffile), /etc/sysconfig/opendj (rpm, %config(noreplace)), read by the systemd unit and the init script.

Build tooling & metadata

  • jdeb 1.3 → 1.14; Standards-Version: 4.7.3; Section: net; Debian revision in Version; Pre-Depends: adduser; JRE fallback through java25; rpm Requires: java-headless >= 1:11 + Requires(pre): shadow-utils; set -e, fixed exit -1, /run; changelogs regenerated from GitHub Releases.

Documentation (install-guide/)

  • Updated the Debian and RPM install/upgrade/uninstall sections to match: dedicated opendj user, systemd (systemctl) with SysV fallback, JRE installed automatically via the package dependency, run setup as opendj, override Java via /etc/default|/etc/sysconfig/opendj, CAP_NET_BIND_SERVICE for privileged ports.

CI

  • New test-deb (clean debian:12 container + live systemctl on the runner) and test-rpm (rockylinux:9 container) jobs: install, assert the opendj user + ownership, setup, service start/stop, ldapsearch liveness, cleanup.

Reviewer notes

  • Dedicated user + chown -R /opt/opendj on upgrade migrates existing root-owned installs.
  • jdeb 1.14 may differ from 1.3 in compression/permissions — test-deb inspects with dpkg-deb.
  • build-docker-alpine failures on some runs are an unrelated pre-existing flake; and a flaky macOS JMX test (JmxPrivilegeTestCase) can fail build-maven and skip the test-deb/test-rpm dependents — re-run failed jobs if that happens.

Bring the opendj-deb/opendj-rpm packages up to current Linux packaging
practice. The packaging had drifted from the ForgeRock era: jdeb 1.3
(2016), SysV-init only with direct update-rc.d/chkconfig calls, no
Standards-Version, a 2015 changelog, and the server running as root.

Service management:
- Ship a native systemd unit (resources/systemd/opendj.service,
  Type=simple, start-ds --nodetach), kept alongside the SysV init script
  as a fallback for non-systemd hosts.
- Register/enable/start via deb-systemd-helper / systemctl with an
  update-rc.d / chkconfig fallback; stop the service on removal.

Dedicated service account:
- Create an "opendj" system user/group and chown /opt/opendj to it; this
  also migrates previously root-owned installs on upgrade.
- Run start-ds/stop-ds/upgrade as "opendj" from systemd, the maintainer
  scripts, and the SysV init script (new run_as helper, falls back to the
  current user when the account is absent).

Build tooling and metadata:
- jdeb 1.3 -> 1.14; ship the systemd unit from both deb and rpm.
- control: add Standards-Version 4.7.3, Section net, a Debian revision in
  Version, Pre-Depends: adduser, and a newest-first JRE fallback list
  (default-jre-headless | ... | java25 | java21 | java17 | java11).
- rpm: add Requires java-headless >= 1:11 and Requires(pre) shadow-utils.
- Maintainer scripts hardened: set -e, fix invalid "exit -1", /var/run
  -> /run, idempotent guards.

Changelog:
- Generate the deb and rpm changelogs from the GitHub Releases via a new
  release-time helper (resources/generate-changelog.sh); committed output
  keeps the Maven build offline and reproducible.

CI:
- Add test-deb and test-rpm jobs (needs: build-maven) that install the
  built package, assert the opendj user and ownership, run setup, and
  start/stop the service (systemd on the runner; SysV in a Rocky Linux 9
  container) with an ldapsearch liveness check.
@vharseko vharseko requested a review from maximthomas June 26, 2026 17:21
@vharseko vharseko added build CI java Pull requests that update java code labels Jun 26, 2026
@vharseko vharseko marked this pull request as draft June 26, 2026 19:03
@vharseko vharseko force-pushed the features/linux-distribution branch from 91ada0f to 552a762 Compare June 26, 2026 19:52
vharseko added 3 commits June 28, 2026 10:24
…e CI

The dedicated `opendj` service user (PR OpenIdentityPlatform#663) runs setup/start-ds/stop-ds with
a clean environment: no inherited JAVA_HOME, and `which` may be absent (e.g.
minimal containers). OpenDJ's Java lookup then fell through to an error, because
the package shipped config/java.properties with an unsubstituted placeholder
(`default.java-home=$JAVA_HOME`) and the PATH fallback relied on the external
`which`. Result: setup/start as `opendj` could not find Java.

Fix Java discovery at the package level, using STABLE references so a JRE
upgrade/reinstall does not break the service:

- _script-util.sh: replace `which java` with `command -v java` (POSIX builtin,
  no dependency on the `which` package; resolves the stable /usr/bin/java
  alternatives symlink). This is the root-cause fix for the PATH fallback.
- deb postinst / rpm %post: substitute `default.java-home` in
  config/java.properties with a stable symlink (/usr/lib/jvm/default-java, else
  the grandparent of `command -v java`, typically /usr) -- never a version-
  specific readlink path. Only the shipped placeholder is touched, so admin
  edits are preserved.
- Ship an EnvironmentFile for admin overrides (OPENDJ_JAVA_HOME / OPENDJ_JAVA_BIN
  / OPENDJ_JAVA_ARGS): /etc/default/opendj on deb (conffile), /etc/sysconfig/
  opendj on rpm (%config(noreplace)). The systemd unit reads it via
  EnvironmentFile=, and the SysV init script sources and exports it so the
  values survive the runuser switch to the service account.

CI (.github/workflows/build.yml):
- test-deb: run in a clean debian:12 container (install + SysV start/stop) plus
  a live `systemctl enable --now` on the runner. The container has no JAVA_HOME
  and no `which`, so it actually verifies the package configures Java itself.
- test-rpm: drop the OPENDJ_JAVA_HOME band-aid; Java now comes from the package.
…privileged ports

The service runs as the dedicated opendj user and so cannot bind privileged ports (LDAP 389, LDAPS 636) by default. Grant CAP_NET_BIND_SERVICE via AmbientCapabilities (and restrict CapabilityBoundingSet to it) so the non-root service can listen on those ports without running as root or applying setcap to the java binary.
…d opendj user

The install guide described the old behavior (init.d, root-owned files, setup as root). Update the Debian and RPM sections to match the current packages: dedicated opendj system user, systemd service (systemctl) with a SysV fallback, JRE installed automatically via the package dependency, run setup as the opendj user, override Java via /etc/default or /etc/sysconfig/opendj, and CAP_NET_BIND_SERVICE for privileged ports.
@vharseko vharseko marked this pull request as ready for review June 28, 2026 20:40
@vharseko vharseko added this to the 5.2.0 milestone Jun 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

build CI java Pull requests that update java code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants