Skip to content

Powered by Grav

SELFUPGRADE reference

SELFUPGRADE reference

SELFUPGRADE is BOA's cron-driven upgrade scheduler. You set _AUTO_UP_* variables in /root/.barracuda.cnf; autoupboa reads them, refreshes the meta-installers, and (re)writes the upgrade cron lines into /etc/crontab. Two flavours run from the same configuration:

  • Weekly system-onlybarracuda up-<tier> system every week on a chosen weekday, through the autoupboa weekly-system wrapper.
  • One-time full upgrade — full barracuda up-<tier> plus octopus up-<tier> all force on a chosen month/day.

Pair this with SKYNET (the tag-driven auto-update, left on by default) for a hands-off production host: SKYNET handles security urgency between windows; SELFUPGRADE handles the predictable cadence. SKYNET's hourly urgency is not paranoia — it was built in direct response to Drupageddon (SA-CORE-2014-005, October 2014), when unpatched Drupal sites were treated as compromised within about seven hours of disclosure; the design goal is that a critical core fix reaches every opted-in box within the hour. The fuller story is under Security history.

Enabling: the three primary variables

In /root/.barracuda.cnf:

INI
# All three must be set, or no auto-upgrade cron is written.
_AUTO_UP_WEEKLY=    # Day of week (1-7) for the weekly system upgrade
_AUTO_UP_MONTH=     # Month (1-12) for the one-time full upgrade
_AUTO_UP_DAY=       # Day (1-31) for the one-time full upgrade

# Optional — defaults shown in "Default timing" below.
_AUTO_VER=          # BOA tier passed to up-: lts | pro | dev (default: this host's tier)
_AUTO_PHP=          # PHP scope token: php-min | php-max | php-all

# Optional schedule tuning (fall back to BOA defaults if unset).
_AUTO_UP_HOUR=      # Hour (0-23) for the barracuda pass
_AUTO_UP_MINUTE=    # Minute (0-59) for the barracuda pass
_AUTO_OCT_UP_HOUR=  # Hour (0-23) for the octopus pass
_AUTO_OCT_UP_MINUTE=# Minute (0-59) for the octopus pass

Validate the ranges yourself. Out-of-range values are interpolated verbatim into the cron expression (_AUTO_UP_WEEKLY=8 writes a day-of-week field of 8). BOA does not reject them; an invalid field produces a cron line that never fires — or, worse, breaks subsequent scheduled jobs.

_AUTO_VER — the tier token

_AUTO_VER is interpolated literally into the command autoupboa emits (up-${_AUTO_VER} …), so it must be a tier barracuda/octopus accept: lts, pro or dev. There is no head value — up-head is rejected by both meta-installers.

When _AUTO_VER is unset, autoupboa falls back to this host's own tier (${_tRee}), so on an LTS host the default is lts; set it explicitly only to override.

INI
_AUTO_VER=pro      # or: dev  (dev follows the development tip — not for production)

_AUTO_PHP — the PHP scope

_AUTO_PHP accepts three values, each passed straight through as the PHP token of the upgrade command:

INI
_AUTO_PHP=php-min   # recommended set: PHP 8.5, 8.4, 8.3 (8.4 default)
# _AUTO_PHP=php-all # same recommended set (synonym of php-min in this path)
# _AUTO_PHP=php-max # every supported PHP version

php-min and php-all resolve to the same recommended set; php-max is the only value that rebuilds every supported version.

Left empty, the upgrade runs with no explicit PHP token (BOA's own default scope). Setting php-min/php-all re-installs the recommended versions on each scheduled window — handy if you prune aggressively and want the standard set rebuilt automatically.

Common schedule patterns

Weekly system-only (typical production)

System upgrade every Wednesday shortly after midnight, no Octopus touch:

INI
_AUTO_UP_WEEKLY=3
_AUTO_UP_MONTH=2     # placeholder — required to enable, no full run lands on it unless the day matches
_AUTO_UP_DAY=29      # placeholder
_AUTO_VER=lts

The weekly line runs only barracuda up-<tier> system — fast, narrow, no Octopus instances touched.

One-time full upgrade

Full barracuda up-<tier> + octopus up-<tier> all force on a specific date:

INI
_AUTO_UP_WEEKLY=    # empty — no weekly line
_AUTO_UP_MONTH=10   # October
_AUTO_UP_DAY=15     # 15th
_AUTO_UP_HOUR=0     # set explicitly — the 00:15/01:15 defaults apply
_AUTO_UP_MINUTE=15  # only when _AUTO_UP_WEEKLY is also set
_AUTO_OCT_UP_HOUR=1
_AUTO_OCT_UP_MINUTE=15
_AUTO_VER=lts

Without explicit hour/minute values in this weekly-less shape the schedule fields stay empty and autoupboa skips writing the lines entirely (an empty field would shift the cron columns and produce a line cron rejects).

Default timing

When the three primary variables are set and the optional time variables are empty, BOA applies:

  • Weekly system upgrades start at 00:15 on the chosen weekday.
  • Full one-time upgrades start at 00:15 for system + Master and 01:15 for Octopus instances.

BOA-hosted boxes (_hostedSys=YES) carry their own hardcoded internal schedule — 03:10 / 04:10 — set automatically and not relevant to ordinary operator hosts.

Override per-host with _AUTO_UP_HOUR / _AUTO_UP_MINUTE / _AUTO_OCT_UP_HOUR / _AUTO_OCT_UP_MINUTE; staggering windows across many hosts avoids them all hitting the mirror at once.

The cron lines autoupboa writes

autoupboa emits up to three lines into /etc/crontab, and the weekly line is deliberately not the same shape as the full lines:

  • Weekly system line — through the wrapper: bash /opt/local/bin/autoupboa weekly-system up-<tier> system [php-*] noscreen. The weekly-system wrapper performs the ICU 7.4 intl self-heal (below) and only ever calls barracuda as a leaf process — it never re-enters itself.
  • One-time full lines — direct to the meta-installers: bash /opt/local/bin/barracuda up-<tier> log [php-*] noscreen and bash /opt/local/bin/octopus up-<tier> all force log noscreen.

The noscreen token marks these as silent, non-interactive scheduled runs (no screen session). Note the directionality: autoupboa invokes barracuda and octopus, never the reverse — barracuda is always a leaf call, so there is no self-recursion loop.

ICU 7.4 intl auto-heal on the weekly run

Where auto-updates are enabled, the weekly-system wrapper guards a specific regression: a system ICU bump to 76 can rebuild PHP 7.4 without intl. On each weekly run the wrapper checks php -m for PHP 7.4 and, only if intl is missing, transparently:

  1. pins ICU to 73-1 (writes _ICU_FORCE_VRN="73-1" to /root/.barracuda.cnf),
  2. rebuilds 7.4 with intl against ICU 73,
  3. unpins so the 8.x versions return to OS-default ICU 76 while 7.4 keeps its ICU-73 intl.

It is self-limiting — once 7.4 carries intl, detection is false and the plain weekly upgrade runs.

Mind the scope: the self-heal runs only where the weekly upgrade cron line was actually written — auto-updates configured, and the box not flagged as a development/scratch server via /root/.dev.server.cnf (the flag is independent of which BOA branch the box tracks). A box outside that set never runs the wrapper, so it falls to the manual procedure below.

A resume marker (/var/log/boa/.php74_intl_bootstrap.active) makes it interrupt-safe: a leftover marker means a prior run pinned but did not unpin, so the next run clears the pin before deciding.

Manual pin on hosts without auto-updates

On hosts without auto-updates the ICU pin is the operator's responsibility: run the same pin → rebuild → unpin → rebuild cycle by hand. Substitute your tier verb (up-lts, up-pro or up-dev):

BASH
# 1. Pin ICU to 73 and rebuild: 7.4 gains intl on ICU 73 (8.x rebuild onto 73 too, temporarily)
echo '_ICU_FORCE_VRN="73-1"' >> /root/.barracuda.cnf
barracuda up-<tier> system

# 2. Unpin and rebuild: 8.x return to OS-default ICU 76; 7.4 keeps its ICU-73 intl
sed -i '/^_ICU_FORCE_VRN=/d' /root/.barracuda.cnf
barracuda up-<tier> system

Verify the end state — PHP 7.4 on ICU 73 with intl, PHP 8.x back on ICU 76:

BASH
readlink /usr/local/lib/icu/current            # -> /usr/local/lib/icu/76.1 after the unpin
/opt/php74/bin/php -m | grep -i intl           # -> intl
/opt/php74/bin/php -i | grep -i 'ICU version'  # -> ICU version => 73.1
ldd /opt/php74/bin/php | grep -i icu           # -> libicu*.so.73 all resolve (no "not found")
/opt/php83/bin/php -i | grep -i 'ICU version'  # -> ICU version => 76.1

The _ICU_FORCE_VRN variable is catalogued in the barracuda.cnf reference.

Both passes rebuild PHP: the pin pass rebuilds every active version onto ICU 73, and the unpin pass rebuilds the 8.x versions back onto ICU 76 — so 8.x are rebuilt twice. The pin pass always compiles from sources (a pinned ICU is a customised build shape, so the prebuilt PHP packages don't apply); the unpin pass can take the prebuilt-package path again. Either way it is a one-time transition cost, but real per-rebuild downtime.

Durability — the pin is transient, but 7.4's intl is not automatically durable. PHP 7.4 keeps its ICU-73 intl only as long as it is not rebuilt while unpinned: the build adds --enable-intl for 7.4 only when _ICU_FORCE_VRN is set, so any forced 7.4 rebuild with the pin off — an OpenSSL change, a php-min/php-max run, a version bump — silently drops intl again. A 7.4 left untouched survives later ICU upgrades unharmed, but re-pin before deliberately rebuilding 7.4.

Do not manually purge old ICU libraries. The transient pin is durable only because ICU runtime libraries are version-suffixed (libicuuc.so.73, libicuuc.so.76, …) and coexist — installing ICU 76 never removes the ICU 73 libraries that 7.4's intl links against. Deleting the so.73 set breaks 7.4 intl even though nothing else on the box still references it.

Unattended reboot after a kernel upgrade

A scheduled OS pass can leave a new kernel pending. By default an ordinary (non-hosted) box does not reboot itself — it prints a notice on the final upgrade stage and leaves the reboot to you:

TXT
NOTE: Your OS kernel has been upgraded
NOTE: Please reboot this server to activate the new kernel
NOTE: Use 'boa reboot' command for optimized reboot

To opt into unattended reboots, create the marker:

SH
touch /root/.allow.auto.reboot.cnf

On every autoupboa pass, when the host is BOA-hosted (_hostedSys=YES) or this marker exists, autoupboa runs _if_new_kernel_reboot. It treats a kernel as pending when either signal fires:

  • /run/reboot-required.pkgs lists a linux package, or
  • boa info reports a Next (pending) kernel line — printed only when the running and next kernel differ.

If a kernel is pending it triggers BOA's accelerated reboot in the background (nohup /opt/local/bin/boa reboot) and exits — but only inside the silent night maintenance window (04:00–04:59 server time). At any other hour the pass just notes that the reboot is pending and waits for the window, so an apt security run staging a kernel mid-day can never reboot a box mid-day.

The window is additionally skipped for the whole day when any active /etc/crontab entry schedules a barracuda or octopus upgrade (directly or via the autoupboa weekly-system wrapper) for today's date — the reboot must never land near or inside an upgrade run, so the staged kernel waits for the next free night instead. Date fields are parsed with crontab(5) semantics (*, numbers, ranges, steps, lists, names; dom/dow combine as OR when both are restricted), and an unparseable entry counts as scheduled — fail-closed for a destructive action.

Before firing, the reboot is announced: an entry is appended to /var/log/boa/kernel-reboot.log (timestamp, the kernel running until now, the pending packages) and, when an admin email address is configured, the same lines are sent as an email alert — so an overnight restart is never a mystery. Hosted boxes always report to the platform address.

The check is skipped during a protected run — when _is_protected_run detects a concurrent autoinit/automini/barracuda/boa/octopus process or one of the octopus_install_run.pid / boa_run.pid / boa_wait.pid run-locks — so it never reboots mid-upgrade.

Behaviour-changing. An opted-in box reboots itself unattended after a kernel bump. The marker stays in /root (it is not relocated to /etc/boa).

Service teardown on every pass

autoupboa is not only the scheduler. Every plain pass also runs _if_disable_not_used_services, a janitor that stands unwanted services down. On a normally configured box that is roughly every five minutes: the */5 root cron entry runs /var/xdrago/clear.sh, which calls autoupboa whenever no /run/boa_run.pid lock is held.

Two conditions gate the whole function:

  • _SKYNET_MODE=OFF in /root/.barracuda.cnf makes autoupboa exit long before the janitor is reached, so every marker in this section becomes inert.
  • The weekly-system wrapper invocation returns first, so the janitor runs only on the plain, cron-driven pass — never on the weekly upgrade line.

None of the markers below is created or removed by BOA. They are operator files that survive upgrades and reboots until you delete them, and none of them is touched by the hosted normalisation block.

The deny family — Jetty 9, Solr 7, Solr 9

Three markers in /etc/boa/ each stand one search-stack service down:

Marker Deregisters Init script moved to Also killed
.deny.jetty9.cnf jetty9 /var/backups/jetty9.initd jetty9, avahi-daemon
.deny.solr7.cnf solr7 /var/backups/solr7.initd solr7, avahi-daemon
.deny.solr9.cnf solr9 /var/backups/solr9.initd solr9, avahi-daemon

Each arm is inner-guarded on its /etc/init.d/<service> still being present. When it is, BOA runs update-rc.d -f <service> remove, moves the init script into /var/backups, then pkill -9s the daemon and avahi-daemon with it. A marker dropped on a box that never had the service is a no-op.

The teardown is not permanent, but nothing in the janitor undoes it. Clearing the switch — deleting the marker and leaving the variable at NO — stops the arm firing, and that pass puts nothing back. What restores the service is the Solr installer, which is gated on /root/.deny.java.cnf / _DENY_JAVA alone and never on these three markers, so a later barracuda up-<tier> UPGRADE pass with _ALLOW_HEAVY_REBUILDS=YES re-lays the init script and runs update-rc.d again: straight away for Jetty 9, whose arm rewrites /etc/init.d/jetty9 whenever it is missing, and on the next version bump for Solr 7 and Solr 9, whose init scripts come back with install_solr_service.sh. The one thing that never returns on its own is the copy parked in /var/backups — it stays behind as a stale duplicate, so tidy it up yourself.

/root/.deny.java.cnf is the superset of all three: one arm tears down solr9, solr7 and jetty9 together and adds pkill -9 -f java, and the same switch also stops Barracuda installing or upgrading Solr at all. _DENY_JAVA=YES in /root/.barracuda.cnf is the supported switch; the marker file stays honoured for one release, and while it exists it wins, so switching back off means setting _DENY_JAVA=NO and removing the file. It is documented with the Solr installer internals.

ClamAV — the missing allow file is the active state

/root/.allow.clamav.cnf and /root/.deny.clamav.cnf are a pair, and their polarity is the opposite of the deny family above. The teardown arm is negated:

SH
if { [ ! -e "/root/.allow.clamav.cnf" ] \
  && ! grep -qiE "^[[:space:]]*(export[[:space:]]+)?_ALLOW_CLAMAV=[\"' ]*YES" /root/.barracuda.cnf 2>/dev/null; } \
  || [ -e "/root/.deny.clamav.cnf" ] \
  || grep -qiE "^[[:space:]]*(export[[:space:]]+)?_DENY_CLAMAV=[\"' ]*YES" /root/.barracuda.cnf 2>/dev/null; then

The braces are load-bearing: they keep the allow-file test and its variable arm as one negated unit, so either form of the opt-in satisfies it, while either form of the deny still overrides.

So a box carrying neither form of the opt-in is torn down on every pass — that is the default. BOA still installs clamav, clamav-base, clamav-daemon and clamdscan on a fresh install and on every full upgrade pass, so the daemons are present but parked: both init scripts are deregistered and moved into /var/backups, clamd and freshclam are killed, and /run/clamav/* is cleared.

To keep ClamAV running, set _ALLOW_CLAMAV=YES in /root/.barracuda.cnf (the /root/.allow.clamav.cnf marker stays honoured for one release); _DENY_CLAMAV=YES or the deny marker overrides it wherever it appears. On its own the deny changes nothing, because the absence of the allow already denies. The marker file wins while it exists, so switching the opt-in back off means setting _ALLOW_CLAMAV=NO and removing /root/.allow.clamav.cnf. Both keys belong in the system cnf only — a same-named line in an Octopus cnf is unsupported.

Through this transition, keep the marker file alongside the variable. The two slow-cycle OS-upgrade drivers, autochimaera and autodaedalus, are refreshed only through the release-latched tool update, so they learn the variable when the next release serial reaches them. Until the release after this one, pair _ALLOW_CLAMAV=YES with touch /root/.allow.clamav.cnf: a major OS upgrade driven by a still-stale driver would tear ClamAV down on a variable-only box.

The same negated test is repeated in six places, so the pair is honoured well beyond autoupboa. The four codename upgrade drivers — autobeowulf, autochimaera, autodaedalus, autoexcalibur — deregister the two init scripts under it while standing the box down for a major OS upgrade, though they do not move the files aside. /etc/init.d/clean-boa-env does the same on its stop path, and skips that whole block while a major-OS-upgrade reboot marker is still pending.

There is exactly one positive reader. The system monitor's _clamav_health_check_fix restarts clamav-daemon or clamav-freshclam when it finds them down, but only when all of these hold: the allow is set in either form, neither deny form is set, /data/u exists, and both init scripts are still in /etc/init.d. It also returns early whenever /run/max_load.pid or /run/critical_load.pid exists, and the monitor as a whole exits on a box that is not fully installed. The /data/u condition means the auto-restart never fires on a host without the Octopus disk layout.

Neither file has a BOA writer. The one write that mentions the deny file — inside the freeze branch below — is [ -e … ] && touch, which only refreshes the timestamp of a file you already created. The upgrade pass that mirrors a marker into its variable writes the cnf, never the marker.

Freezing a development-tree VM

/etc/boa/.ice.vm.cnf is the first and by far the most destructive arm of the same function, and it is doubly gated: the marker must exist and the deployed autoupboa must carry the dev delivery-tree stamp (_tRee=dev, set at the top of the tool itself — /root/.barracuda.cnf never overrides it). On a pro or lts box the branch never runs.

Where it does run, it re-runs on every pass and:

  • truncates six scripts to a blank line — /var/xdrago/move_sql.sh, proc_num_ctrl.pl, runner.sh, monitor/check/nginx.sh, monitor/check/mysql.sh and mysql_backup.sh;
  • deletes the aegir crontab (/var/spool/cron/crontabs/aegir);
  • kills pure-ftpd and newrelic-daemon;
  • stops nginx, MySQL, Valkey and Redis wherever their run files exist, and kills every php-fpm process when /run/php83-fpm.pid is there;
  • refreshes the timestamp of /root/.deny.clamav.cnf and /root/.deny.java.cnf if you already created them — it never creates either. The refresh touches the marker files and nothing else: it never sets _DENY_CLAMAV or _DENY_JAVA, so a box that opted in by variable alone has nothing refreshed here.

One-way. Nothing reverses the freeze. Removing the marker stops further passes, but it restarts no daemon, restores neither the aegir crontab nor the blanked scripts, and leaves whatever the ClamAV and Java arms did in place. Treat it as a deliberate, manually recoverable shutdown of a development VM, never as a pause switch.

Any arm that actually did something sets an internal flag, and the janitor finishes by dropping the kernel page cache — but only when RAM usage is already above 90%.

Logs and notifications

Auto-upgrade output lands in:

  • /var/backups/reports/up/barracuda/* — per-run barracuda log
  • /var/backups/reports/up/octopus/* — per-run octopus log
  • /var/log/boa/ — BOA operational log (includes auto-upgrade events)

Both the system and Octopus reports are emailed to _MY_EMAIL from /root/.barracuda.cnf (default [email protected]; forced to <tool>@omega8.cc on a BOA-hosted box). There is no _EMAIL_USER_ADM variable.

Requesting a full status report

/etc/boa/.run.example.report.cnf is a one-shot request for a complete status report. On the pass that lands on the top of the hour, _send_boa_system_report runs boa info report both, mails the output and deletes its temporary body file. (The test is _TIME equal to 1200 or _MINUTE equal to 00; since 12:00 already has minute 00, the effective window is the top of every hour — one pass in twelve.)

Two current limits matter before you rely on it:

  • It only ever sends on a BOA-hosted box. The recipient and BCC addresses ([email protected], with [email protected] in BCC) are set inside the _hostedSys=YES branch and nowhere else, and the send is skipped while either is empty. On an ordinary operator host the marker is inert — it produces no report and no error.
  • On a hosted box the marker is erased roughly every five minutes. The hosted normalisation block, later in the same run, removes it unconditionally, and the reader never removes it after a send. A request created at any other minute of the hour is therefore wiped before the send window arrives, and the report is silently dropped. Within a single top-of-the-hour pass the send happens first and the wipe second, so a marker that is already in place when the hour rolls over does get its one report.

Like the teardown markers above, the whole path is inert while _SKYNET_MODE=OFF, because autoupboa exits before it.

Disabling SELFUPGRADE

Blank any of the three primary variables:

INI
_AUTO_UP_WEEKLY=
_AUTO_UP_MONTH=
_AUTO_UP_DAY=

Auto-upgrade stops on the next BOA cron pickup (within an hour). This does not disable SKYNET — that is a separate tag-driven mechanism with its own supported switch, _SKYNET_MODE=OFF in /root/.barracuda.cnf — and even that switch keeps the critical tools updating, as the next section explains.

How the fleet updates its own tools

SELFUPGRADE schedules the meta-installers; the tools themselves — barracuda, octopus, boa, autoupboa and the rest of /opt/local/bin — are kept current by the BOA.sh.txt agent, the same script that the bootstrap one-liner (wget -qO- https://files.boa.io/BOA.sh.txt | bash) executes and the SKYNET cron re-fetches. Two updater tiers live inside it:

  • _update_boa_tools — runs on every path and tier. On the normal bootstrap path it runs from _boa_setup. With _SKYNET_MODE=OFF in /root/.barracuda.cnf it still runs: an interactive (SSH TTY) run prints STATUS: BOA Skynet Agent is Inactive! and NOTE: Critically important BOA tools will be still updated, refreshes the key tools (via _if_update_boa_key_tools_only, which calls _update_boa_tools), and exits before anything else; a non-interactive (cron) run does the same refresh silently and exits. This is why the section above says blanking the _AUTO_* variables does not disable SKYNET — and why even SKYNET's own off-switch does not stop core-tool updates. _SKYNET_MODE is catalogued in the barracuda.cnf reference.
  • _update_agents — Skynet-active boxes only. Refreshes the cron agents, the monitor/night scripts, and a few bin tools scoped to installed Skynet-active boxes; the core tool set itself is fetched only by _update_boa_tools.

Per-file versioned fetches

Since BOA-5.10.3 both tiers fetch every tool per-file through a shared helper, _fetch_versioned. A file counts as current only when its stamp /var/log/boa/<name>.ctrl.<serial>.<tree>.<xSrl>.pid exists and the file on disk is non-empty (and its managed symlink is intact, where one is used). Around every fetch:

  • a --guard pgrep check refuses to overwrite a currently-running tool (The <name> is running!);
  • the download lands in a private temp file and only replaces the live copy via an atomic mv after it passes validation — curl reported success, the body is non-empty, it is not the mirror's HTML "Under Construction" stub, and (for sentinel-protected files such as websh) it carries the required token near its end;
  • the stamp is written only after a successful, validated fetch, and even a current stamp is re-checked against the mirror once it ages past the revalidation window (24 h default), so stale bytes self-heal.

The design intent: a lagging mirror or a transient failure leaves no stamp, so the fetch is retried on the next run, and a partial or wrong download can never destroy a working tool.

(The pre-5.10.3 bulk loop tested -e rather than -s and stamped a one-shot marker even on failure, so a partial fetch was never retried until the next release.)

The privileged root helpers in /usr/local/bin are fetched the same per-file way:

  • fix-drupal-platform-permissions.sh
  • fix-drupal-site-permissions.sh
  • fix-drupal-platform-ownership.sh
  • fix-drupal-site-ownership.sh
  • lock-local-drush-permissions.sh
  • fix-drupal-site-symlinks.sh

Serial conventions (read-only plumbing)

None of these are barracuda.cnf variables — they ship inside the agent and are never set by the operator:

  • Per-tool fNN serials count DOWN from f99. A forced refresh of a tool is a decrement (f99f98), never a value the tool already used.
  • The old _bTs function latch is retired. _update_boa_tools used to run once per release behind a updateBOAtools.<_bTs>.ctrl.… stamp; it now runs on every pass and every path, each tool line self-gating on its own fNN stamp — so a bumped tool serial reaches every box (including _SKYNET_MODE=OFF boxes) on the next tick, with no release involved.
  • _xSrl / _rLsn identify the release train the stamps belong to.

One core-tool list, one owner

Each tool has exactly one fetch line. The core tool set lives only in _update_boa_tools, which runs before BOA is even installed and is the only updater left under _SKYNET_MODE=OFF, so every class of box gets it; _update_agents fetches only the monitors, system scripts and the few extra tools that exist solely on installed Skynet-active boxes. (Historically the core list was duplicated into _update_agents to work around the once-per-release latch; that duplication — and its bump-both-together serial discipline — is gone.)

© 2026 BOA Documentation. All rights reserved.