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.

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_VER=lts

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.

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 compile twice. 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.

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).

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.

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 the same core tools, but runs only when SKYNET is active on an installed box.

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 old copy is moved to <file>.old before the download and restored if the fetch comes back empty;
  • the stamp is written only after a successful, non-empty fetch.

The design intent: a lagging mirror or a transient failure leaves no stamp, so the fetch is retried on the next run, and a zero-byte 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 an increment.
  • _bTs (format 5103vNN, counting UP within a release) gates the whole _update_boa_tools pass once per value, via /var/log/boa/updateBOAtools.<_bTs>.ctrl.<tree>.<xSrl>.pid — so any behaviour change to that function ships together with a _bTs bump.
  • _xSrl / _rLsn identify the release train the stamps belong to.

One core-tool list, two owners — by design

The core-tool list is intentionally duplicated between _update_boa_tools and _update_agents. _update_boa_tools must fetch the core tools independently because it runs before BOA is even installed and is the only updater left under _SKYNET_MODE=OFF.

A tool present in both lists shares one stamp name, so by design its serial must be bumped in both functions together — a divergent serial would make each run wipe the other's stamp and refetch every cycle.

The two functions are not a deduplication candidate.

© 2026 BOA Documentation. All rights reserved.