Modernize Debian and RPM packaging (systemd, dedicated user, CI tests)#663
Open
vharseko wants to merge 4 commits into
Open
Modernize Debian and RPM packaging (systemd, dedicated user, CI tests)#663vharseko wants to merge 4 commits into
vharseko wants to merge 4 commits into
Conversation
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.
91ada0f to
552a762
Compare
…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.
maximthomas
approved these changes
Jun 29, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
The
opendj-deb/opendj-rpmpackaging had drifted from current Linux practice: jdeb 1.3 (2016), SysV-init only with directupdate-rc.d/chkconfigcalls, noStandards-Version, a 2015 changelog, the server running as root, and the install guide never reflecting any of this. CI also built the.deb/.rpmbut never installed or tested them.What changed
Service management
resources/systemd/opendj.service,Type=simple,start-ds --nodetach), SysV init kept as a fallback for non-systemd hosts.deb-systemd-helper/systemctlwith anupdate-rc.d/chkconfigfallback; 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
opendjsystem user/group,chown /opt/opendjto it (migrates root-owned installs on upgrade); runstart-ds/stop-ds/upgrade/the service asopendj.Java discovery (robust to JRE upgrade/reinstall)
_script-util.sh:which java→command -v java(no dependency on thewhichpackage; resolves the stable/usr/bin/java).postinst/ rpm%postpindefault.java-homeinconfig/java.propertiesto a stable symlink./etc/default/opendj(deb, conffile),/etc/sysconfig/opendj(rpm,%config(noreplace)), read by the systemd unit and the init script.Build tooling & metadata
Standards-Version: 4.7.3;Section: net; Debian revision inVersion;Pre-Depends: adduser; JRE fallback throughjava25; rpmRequires: java-headless >= 1:11+Requires(pre): shadow-utils;set -e, fixedexit -1,/run; changelogs regenerated from GitHub Releases.Documentation (
install-guide/)opendjuser, systemd (systemctl) with SysV fallback, JRE installed automatically via the package dependency, runsetupasopendj, override Java via/etc/default|/etc/sysconfig/opendj,CAP_NET_BIND_SERVICEfor privileged ports.CI
test-deb(cleandebian:12container + livesystemctlon the runner) andtest-rpm(rockylinux:9container) jobs: install, assert theopendjuser + ownership,setup, service start/stop,ldapsearchliveness, cleanup.Reviewer notes
chown -R /opt/opendjon upgrade migrates existing root-owned installs.test-debinspects withdpkg-deb.build-docker-alpinefailures on some runs are an unrelated pre-existing flake; and a flaky macOS JMX test (JmxPrivilegeTestCase) can failbuild-mavenand skip thetest-deb/test-rpmdependents — re-run failed jobs if that happens.