Solr installer internals (solr.sh.inc)

lib/functions/solr.sh.inc (478 LOC) is the Barracuda-side, install-time dispatcher for every Solr backend BOA ships: Solr 4 (under Jetty 9), Solr 7, Solr 9. It lays down the daemon, its data tree, its sysvinit service, and the JDK-pinned env file — everything the Search-API vhost traffic eventually reaches. It is not the runtime core manager (/var/xdrago/manage_solr_config.sh); it runs only on a barracuda UPGRADE pass — never on a first-time INIT/install — and never touches per-site cores.

solr is one of the thirteen libraries BARRACUDA sources on entry (BARRACUDA.sh.txt:275). The single entry point is _if_install_upgrade_solr, called from the _ALLOW_HEAVY_REBUILDS=YES add-on block, which is itself nested inside if [ "${_STATUS}" = "UPGRADE" ] — so this dispatcher fires on an UPGRADE pass only, never on a fresh INIT/install (a load-bearing condition for "why didn't Solr install on a new box"). The call is further guarded by the absence of the opt-out flag file:

[ ! -e "/root/.deny.java.cnf" ] && _if_install_upgrade_solr

Drop /root/.deny.java.cnf on a box and the whole Solr/Java subsystem is skipped, regardless of _XTRAS_LIST.

Dispatch: _if_install_upgrade_solr (:447)

The dispatcher runs two setup helpers, then gates each version independently on OS, an SRn token, an existing-install marker, or the hosted-system flag.

_if_to_do_fix          # system.sh.inc:337 — sets _xSrl serial + fix state
_if_hosted_sys         # helper.sh.inc:4  — _hostedSys=YES on *.aegir.cc / .host8.cnf

if [ "${_OS_CODE}" != "excalibur" ]; then
  # Solr 4 (Jetty 9) — needs java11
  [[ "${_XTRAS_LIST}" =~ "SR4" ]] || [ -e "/opt/solr4/solr.xml" ] \
    || [ "${_hostedSys}" = "YES" ]  →  [ -e /usr/bin/java11 ] && _if_solr_four
  # Solr 7 — needs java11
  [[ "${_XTRAS_LIST}" =~ "SR7" ]] || [ -e "/var/solr7/logs/solr.log" ] \
    || [ "${_hostedSys}" = "YES" ]  →  [ -e /usr/bin/java11 ] && _if_solr_seven
fi
# Solr 9 — needs java17 OR java21; runs on ALL OSes incl. excalibur
[[ "${_XTRAS_LIST}" =~ "SR9" ]] || [ ! -e "/var/solr9/logs/solr.log" ] \
  || [ "${_hostedSys}" = "YES" ]  →  ([ -e /usr/bin/java17 ] || [ -e /usr/bin/java21 ]) && _if_solr_nine

Two gate mechanics matter when reading this:

  • Solr 4 + 7 are wrapped in [ "${_OS_CODE}" != "excalibur" ] (:454). On Devuan Excalibur only Solr 9 is reachable; the SR4/SR7 tokens are not stripped from _XTRAS_LIST, they just never reach _if_solr_four / _if_solr_seven.
  • The SRn token is only one of three OR-triggers. An already-installed Solr (/opt/solr4/solr.xml, /var/solr7/logs/solr.log), or _hostedSys=YES, each independently re-enters the per-version function on every upgrade — that is how an existing install keeps getting version-bumped without SRn in the list. Note the Solr 9 trigger is [ ! -e "/var/solr9/logs/solr.log" ] (absent log), so a box with no Solr 9 yet always enters _if_solr_nine on a heavy rebuild; the per-version prompt then decides.

The final gate is the Java binary, not the token

Each version is only entered if its JDK symlink exists: java11 for Solr 4/7, java17 or java21 for Solr 9. The JDK set is laid down earlier in the run by system.sh.inc per _OS_CODE. The install-reachability matrix is therefore:

OS (_OS_CODE) JDKs present Solr 4 Solr 7 Solr 9
beowulf java11 only yes yes no (no java17/21)
chimaera java11, java17 yes yes yes (via Java 17)
daedalus java11, java17, java21 yes yes yes
excalibur java11, java17, java21 no (:454 gate) no (:454 gate) yes (via Java 21)

Beowulf can host at most Solr 4 + Solr 7; the Solr 9 java gate (:473-474) skips it. Chimaera reaches Solr 9 through Java 17 (the _useJava selector at :77-81 picks 17 when java-21-openjdk-amd64 is absent) — it does not get Java 21.

Version pins live in BARRACUDA.sh.txt

Every version string the installer fetches and stamps is a top-level variable in BARRACUDA.sh.txt — this is the single edit point for a version bump:

Component Variable Source line Value
Solr 9 _SOLR_9_VRN :137 9.10.1
Solr 7 _SOLR_7_VRN :136 7.7.3
Solr 4 _SOLR_4_VRN :135 4.9.1
Jetty 9 (hosts Solr 4) _JETTY_9_VRN :65 9.2.16.v20160414
SLF4J (Jetty 9 lib) _SLF4J_VRN :132 1.7.21
log4j (Jetty 9 lib) _LOGJ4_VRN :70 1.2.17

_SOLR_1_VRN/_SOLR_3_VRN and _JETTY_7_VRN/_JETTY_8_VRN are also pinned but no longer wired into solr.sh.inc — dead pins retained for reference.

The functions read these variables into the fetch name, the tarball path, and the per-version idempotency marker, so bumping the variable changes all three consistently. Archives are pulled by _get_dev_arch (helper.sh.inc:225, from the dev mirror ${_urlDev}, 10 retries) and Drupal contrib by _get_dev_contrib (helper.sh.inc:327, from ${_urlDev}/${_tRee}/contrib/).

Ports, paths, service model

Solr Function Install root Data tree Listen Service Env file
9 _if_solr_nine (:33) /opt/solr9 /var/solr9/data 127.0.0.1:9099 /etc/init.d/solr9 /etc/default/solr9.in.sh
7 _if_solr_seven (:141) /opt/solr7 /var/solr7/data 127.0.0.1:9077 /etc/init.d/solr7 /etc/default/solr7.in.sh
4 _if_solr_four (:228) /opt/solr4 /opt/solr4/core{0..9}/data 127.0.0.1:8099 /etc/init.d/jetty9 /etc/default/jetty9

Solr 7/9 install via Solr's own install_solr_service.sh (-i /opt -d /var/solrN -u solrN -s solrN -p <port>, :62/:169), which drops the sysvinit script and creates the solrN system user (BOA pre-creates it with adduser --system --group

  • usermod -aG users). Solr 4 has no solr4 service: the WAR (solr-<VRN>.war) is deployed into a Jetty 9 distribution and the daemon is jetty9. The jetty9 init script is copied from the BOA-shipped template ${_locCnf}/solr4/jetty9 (= <build>/aegir/conf/solr4/jetty9) when present, else symlinked to /opt/jetty9/bin/jetty.sh, then update-rc.d jetty9 defaults (:341-351).

Per-version walkthrough

_if_solr_nine (:33)

  1. Symlink-host repair (:38-41). If /var/solr9 is a symlink onto a mount and /var/solr9/data exists, run _if_fix_solr9_permissions + _if_fix_solr9_mod up front.
  2. Fresh install (:48-74). Only when /var/solr9/data is absent. Prompts (_prompt_yes_no), wipes /var/opt/solr*, fetches solr-${_SOLR_9_VRN}.tgz (kept), runs install_solr_service.sh on port 9099, writes the marker /var/solr9/solr-${_SOLR_9_VRN}-version.txt, then re-runs the perms + module fix.
  3. Env-file reconcile (:76-113). When /etc/default/solr9.in.sh exists, it checks three grep sentinels — the JDK-path comment BOA ${_xSrl} Path to Java ${_useJava} on ${_OS_CODE}, SOLR_MODULES="analysis-extras,clustering,extraction,langid,ltr", and SOLR_STOP_PORT=19099. If all match, _DO_NOTHING=YES; otherwise it strips the old SOLR_STOP_*/SOLR_JAVA_HOME/SOLR_MODULES/LOG4J_* lines and re-appends them, selecting SOLR_JAVA_HOME=/usr/lib/jvm/java-21-openjdk (Excalibur, or when java-21-openjdk-amd64 is executable) or .../java-17-openjdk otherwise. LOG4J_FORMAT_MSG_NO_LOOKUPS=true is always set (Log4Shell mitigation).
  4. Version-bump upgrade (:114-132). Guarded by the absence of the _SOLR_9_VRN-stamped marker file — a version bump renames the marker, which re-triggers install_solr_service.sh against the new tarball, then re-stamps.
  5. JDK-upgrade restart (:134-138). When _UP_JDK=YES and the service exists, _mrun "service solr9 restart".

_useJava (:77-81) is 21 on Excalibur or when java-21-openjdk-amd64 is executable, else 17. The env-file JDK block is only written for excalibur|daedalus|chimaera (:103-105).

_if_solr_seven (:141)

Same five-phase shape as Solr 9 but simpler: no module set, single JDK (Java 11), port 9077, stop-port 19077, marker /var/solr7/solr-${_SOLR_7_VRN}-version.txt. The env-file reconcile checks two sentinels (BOA ${_xSrl} Path to Java 11 and SOLR_STOP_PORT=19077) and always writes SOLR_JAVA_HOME="/usr/lib/jvm/java-11-openjdk" (:200). Symlink-host repair calls _if_fix_solr7_permissions (:22).

_if_solr_four (:228) — legacy, Jetty-hosted

The heaviest path. Solr 4.9.1 is not a standalone Solr — its WAR runs inside a Jetty 9 distribution:

  • Fresh install (:244-357), only when /opt/solr4 is absent. Fetches jetty-distribution-${_JETTY_9_VRN}.tar.gz/opt/jetty9, drops solr-${_SOLR_4_VRN}.war into /opt/jetty9/webapps/solr.war, seeds ten cores /opt/solr4/core{0..9}/{conf,data} from the Solr example, and (first time only) builds the Tika stack (_get_dev_contrib apachesolr_attachments-7.x-1.x-dev, patches solrconfig.tika.patch, downloads tika-app-{1.8,1.9,1.10,1.11,1.12,1.13,1.20}.jar).
  • search_api_solr core config (:293-304), seeded once from search_api_solr-7.x-1.17 solr-conf/4.x/*, with 8983→8099 rewritten in solrcore.properties.
  • Logging jars (:305-315): SLF4J (_SLF4J_VRN) + log4j (_LOGJ4_VRN) copied into /opt/jetty9/lib/ext.
  • Env file /etc/default/jetty9 (:319-331): pins JAVA=/usr/bin/java11, JAVA_HOME=/usr/lib/jvm/java-11-openjdk-amd64, JETTY_HOST=127.0.0.1, JETTY_PORT=8099, JETTY_USER=jetty9, and a JAVA_OPTIONS line carrying -Dsolr.solr.home=/opt/solr4. Port 8080→8099 is rewritten across start.d/http.ini, start.ini, and bin/jetty.sh.
  • Upgrade path (:366-444), keyed on /opt/jetty9/VERSION.txt plus a set of seven marker/jar-presence checks (_PORT_CTRL, the SLF4J jar, .fixed.start.ini.txt, tika-app-1.8.jar, log4j-1.2.17.jar, _JETTY_CTRL, _SOLR_CTRL). If any is missing it re-lays Jetty, re-deploys the WAR, re-fetches Tika/SLF4J/log4j. The old tree is archived to ${_vBs}/jetty9-…-${_NOW}, not deleted.
  • JDK-upgrade restart (:359-364): _UP_JDK=YES triggers pkill -9 -f jetty9 + service jetty9 start.

Markers: /opt/jetty9/jetty-ctrl-${_JETTY_9_VRN}-${_SOLR_4_VRN}-version.txt (_JETTY_CTRL) and /opt/jetty9/solr-${_SOLR_4_VRN}-version.txt (_SOLR_CTRL).

The fix helpers

Function Line Effect
_if_fix_solr9_mod :2 Seed /opt/solr9/server/modules/ from ${_bldPth}/aegir/conf/solr9/*only when ltr.mod is absent; then chown root:root + chmod 644 on the module files.
_if_fix_solr9_permissions :11 mkdir -p /var/solr9 if absent; chown -R solr9:solr9 + chmod 750 (follows a symlinked /var/solr9 onto /mnt/*/var/solr9).
_if_fix_solr7_permissions :22 Same shape for solr7:solr7 on /var/solr7.

_if_fix_solr9_mod is not run on every upgrade. It fires from exactly three conditional sites: the symlink-host repair (:40), a fresh install (:66), and a version-bump upgrade (:127). On a standard non-symlink host already at the current Solr 9 version, none fire during a routine barracuda pass, so the root:root/644 reset is not reapplied each run. The module seed itself is a one-shot: ltr.mod present ⇒ the cp -af is skipped.

JVM heap is set elsewhere

solr.sh.inc writes the JDK path, ports, and module list into the env files but not the heap. SOLR_JAVA_MEM (Solr 7/9) and JAVA_OPTIONS -Xmx (Jetty 9) are RAM-derived in the host-tuning pass in system.sh.inc on every run — RAM/6 for Solr 7/9, RAM/8 for Jetty 9 — so manual heap edits do not survive. That tuning belongs to the tuning subsystem, not this installer.

Editing the source to bump a version

The installer is edit-in-source: bump the pin in BARRACUDA.sh.txt, land the new archive on the dev mirror, and let the marker mechanic re-trigger the upgrade path.

  1. Edit the pin in BARRACUDA.sh.txt_SOLR_9_VRN / _SOLR_7_VRN / _SOLR_4_VRN / _JETTY_9_VRN (and, for Solr 4, _SLF4J_VRN / _LOGJ4_VRN if their bundled jars change). Do not hardcode a version inside solr.sh.inc; every consumer reads the variable.
  2. Publish the archive as solr-<VRN>.tgz (Solr 7/9) or jetty-distribution-<VRN>.tar.gz (Jetty 9) on the dev mirror _get_dev_arch pulls from. The marker filename embeds <VRN>, so a new version string means a missing marker on every box ⇒ the upgrade branch fetches and re-stamps. No state reset is needed.
  3. Solr 4 core config comes from the pinned search_api_solr-7.x-1.17 contrib tarball and the apachesolr_attachments patch — changing the Solr 4 schema means bumping those fetches in _if_solr_four and re-testing the 8983→8099 port rewrite in solrcore.properties.
  4. Sentinels are serial-scoped. The env-file JDK comment carries ${_xSrl} (the run serial from _if_to_do_fix), so a serial bump makes the grep sentinel miss and forces a one-time env-file rewrite on the next pass. That is the intended lever to push a corrected SOLR_JAVA_HOME / module set to the fleet.
  5. Edit the source repo, never the deployed copy. The running installer is a build-tree copy under /opt/tmp/boa/lib/functions/solr.sh.inc, overwritten on every upgrade — changes there are lost.

Solr installs are sticky: removing SRn from _XTRAS_LIST does not auto-uninstall (the existing-install OR-triggers keep re-entering the function). Teardown is operator-manual — stop the service, rm -rf /opt/solrN /var/solrN, update-rc.d -f solrN remove — matching BOA's general no-auto-uninstall pattern.

Related

  • Web & search stack internals — the topic chapter: where solr.sh.inc sits relative to the Provision Nginx vhost/settings generators the Search-API traffic passes through.
  • Install & staged-setup internals — how the build tree (/opt/tmp/boa, _bldPth) and _ALLOW_HEAVY_REBUILDS gate that hosts this dispatcher get onto the box.
  • Aegir backend APIs — the Provision/Drush hook surface the Search-API integration wires into on the Drupal side.

Reference

  • Variables_SOLR_*, _JETTY_*, _XTRAS_LIST, _OS_CODE, _ALLOW_HEAVY_REBUILDS, _UP_JDK consolidated.
  • Commands — the barracuda verbs that drive a heavy rebuild.
  • Discontinued features — retired Solr/Jetty generations (_SOLR_1_VRN/_SOLR_3_VRN, _JETTY_7_VRN/_JETTY_8_VRN) live here.