Skip to content

Installer v7.6 robustness: resume preflight + safer extension failure flow - #582

Open
nicdavidson wants to merge 20 commits into
developfrom
installer/v7.6-robustness-overhaul
Open

Installer v7.6 robustness: resume preflight + safer extension failure flow#582
nicdavidson wants to merge 20 commits into
developfrom
installer/v7.6-robustness-overhaul

Conversation

@nicdavidson

@nicdavidson nicdavidson commented Jun 1, 2026

Copy link
Copy Markdown
Contributor

Summary

  • harden the Linux installer for the PHP 8.5 target
  • add resumable installer phase state and repair/resume controls
  • improve non-interactive install defaults for recommended installs
  • stabilize package-manager handling across Ubuntu, Debian, Fedora, and RHEL-family installers
  • pin PECL extension versions where current upstream releases are required
  • switch RHEL-family PHP/module installation to Remi PHP 8.5 packages where available
  • add an EL9 OpenSSL preflight so stale RHEL/EUS systems fail early with a readable message instead of DNF dependency noise
  • normalize DreamFactory runtime permissions before final Laravel migration/cache operations

RHEL support note

The PHP 8.5 installer path requires EL9 systems with OpenSSL 3.2 symbols available in /usr/lib64/libcrypto.so.3.

  • RHEL 9.6+ / compatible current EL9 systems are the supported PHP 8.5 target.
  • AlmaLinux 9.8 validates cleanly as the RHEL-family path.
  • RHEL 9.3 is intentionally rejected because it lacks OPENSSL_3.2.0, which Remi PHP 8.5 requires.
  • Older RHEL/EUS customers should use a PHP 8.3 installer path rather than having this installer force system crypto upgrades.

Validation

  • git diff --check
  • bash -n installers/source/*.sh
  • rebuilt installers/dfsetup.run
  • final artifact MD5: aa364039de12094e3245a41489f930d6

VM matrix:

  • Ubuntu 24.04: PHP 8.5.7, modules igbinary, mongodb, pdo_sqlsrv, sqlsrv, HTTP 302, PHASE_FINAL_VERIFY="done"
  • Debian 12: PHP 8.5.7, modules igbinary, mongodb, pdo_sqlsrv, sqlsrv, HTTP 302, PHASE_FINAL_VERIFY="done"
  • AlmaLinux 9.8: PHP 8.5.7, modules igbinary, mongodb, pdo_sqlsrv, sqlsrv, HTTP 302, PHASE_FINAL_VERIFY="done"
  • RHEL 9.3: rebuilt packaged installer guard rejects early with the OpenSSL 3.2/RHEL 9.6+ message

@nicdavidson

Copy link
Copy Markdown
Contributor Author

Added follow-up hardening commit: \n\nWhat it fixes:\n- now kills the actual spinner PID () instead of \n- INT trap now safely kills spinner PID with stderr suppressed\n- command invocation uses quoted function name call ()\n\nExtra verification run:\n- \n- \n- focused runtime harness confirmed no orphan spinner child processes after success/failure paths ()\n\nRemaining for full sign-off: distro VM matrix (Ubuntu/Debian/RHEL families with induced failure + resume).

@nicdavidson

Copy link
Copy Markdown
Contributor Author

Follow-up hardening commit pushed: 48f2779

What it fixes:

  • run_process now kills the actual spinner PID ($BGPID) instead of kill $!
  • INT trap now safely kills spinner PID with stderr suppressed
  • command invocation uses quoted function name call ("$2")

Extra verification run:

  • bash -n installer.sh
  • for f in installers/source/*.sh; do bash -n "$f"; done
  • focused runtime harness confirmed no orphan spinner child processes after success/failure paths (child_sleep_count=0)

Remaining for full sign-off: distro VM matrix (Ubuntu/Debian/RHEL families with induced failure + resume).

- Guard PECL installs (mongodb/sqlsrv/pdo_sqlsrv) with pecl-list checks so
  reruns no longer re-trigger compiles on resume
- Bump mcrypt to 1.0.9; feed full prompt input to non-interactive pecl
- Add fix_php_extension_permissions helper (setup.sh) and apply after each
  extension install across ubuntu/debian/centos/fedora
- Rewrite SQL Server/msodbcsql repo setup to use the official
  packages-microsoft-prod.deb, version-driven via CURRENT_OS
- Version-drive Microsoft/remi/CRB repo selection by CURRENT_OS
- Regenerate dfsetup.run bundle to match source
Non-interactive installs no longer fall back to a hardcoded
admin@dreamfactory.com / DreamFactory123! pair (flagged by secret
scanners; also a weak, publicly-known default on every unattended
install). DF_ADMIN_EMAIL is now required for unattended installs so
real install emails are captured; DF_ADMIN_PASSWORD is randomly
generated when unset and saved to /opt/dreamfactory/.admin_credentials
(chmod 600). Regenerate dfsetup.run to match.
…ENSE_KEY env)

The final-verify step ran 'php artisan migrate --seed' without --force, so
under APP_ENV=production it prompted for confirmation and stalled/consumed
stdin on non-interactive installs -- cancelling migrations (missing core
tables -> API 500) and leaving the license-key prompt to loop on EOF. This
path only runs for commercial/license installs, so OSS installs were
unaffected.

- migrate --seed --force (no production prompt)
- license-key prompt now takes DF_LICENSE_KEY from the environment when set
  or when stdin is not a TTY, mirroring the DF_ADMIN_* non-interactive flow
- regenerate dfsetup.run

Validated end-to-end: clean gold install on Debian 12 with commercial
composer + license key -> GOLD tier, df-sqlsrv connector, live SQL Server
2022 query through the DreamFactory API.
Ubuntu's run_composer_install only passed --ignore-platform-req=ext-oci8,
so commercial/gold composer sets that bundle connectors needing other
optional extensions (df-ibmdb2/ext-ibm_db2, df-cassandra, etc.) would fail
composer install on a default Ubuntu box. Debian/centos/fedora already use
the full --ignore-platform-reqs; align ubuntu to match.

Validated: gold install on fresh Ubuntu 24.04 -> composer install pulls
df-sqlsrv + df-oracledb (no ext-oci8 present), GOLD tier, live SQL Server
2022 query through the DreamFactory API.
…dening

Validated end-to-end on a fresh Oracle Linux 9.7 box, fully unattended, with
the State of Vermont deployment profile (Gold license + SQL Server connector +
MCP daemon, under SELinux enforcing). Seven fixes:

1. OS detection: add `ol|oracle` to both CURRENT_KERNEL case statements so
   Oracle Linux (ID=ol) routes through centos.sh instead of "unsupported, exiting".
2. SELinux booleans: set httpd_can_network_connect_db + httpd_can_network_connect
   in fix_dreamfactory_runtime_permissions (RHEL family). Without the DB boolean
   php-fpm cannot reach the system DB -> SQLSTATE 2002, masked as a generic 500.
3. SELinux file context: semanage fcontext + restorecon storage/ & bootstrap/cache
   to httpd_sys_rw_content_t (they inherit usr_t under /opt). dontaudit hides the
   AVC, so this silently 500s every request until relabeled. Adds
   policycoreutils-python-utils to system deps for semanage.
4. install_composer (centos): early-return when composer is already on PATH
   (EPEL provides it); the manual getcomposer bootstrap was fragile.
5. run_composer_install: drop the hardcoded /usr/local/bin/composer (does not
   exist when composer comes from EPEL at /usr/bin) -> PATH-resolved, all 4 distros.
6. MCP daemon: install Node 20 (was 14) and gate it on the MCP option (10), build
   the daemon as the runtime user, and install a persistent df-mcp.service systemd
   unit instead of the fire-and-forget `start-daemon.sh &` that died with the shell.
7. INSTALLER_TUI_MODE: honor a pre-set env value instead of always read-ing stdin,
   so unattended installs can pick the profile via env (a piped stdin was silently
   dropping the selection). Consistent with DF_ADMIN_EMAIL/DF_LICENSE_KEY/LICENSE_*.

ubuntu.sh/debian.sh/fedora.sh get the composer-path fix; ubuntu.sh also Node 14->20.
Cosmetic + minor robustness, no functional change to a successful install:
- assert_php85_active: retry resolving php (5x/3s) before warning, so the
  "active php is missing" red warning no longer fires on the normal case where
  the CLI just takes a moment to settle after the Remi package swap.
- dnf_module_enable_remi_php85: `|| true` — Remi ships 8.5 non-modular so the
  module enable is expected to fail; the direct package install handles 8.5.
- mcrypt: reword the PHP 8.5 skip from red "error" to a magenta informational
  note (install_mcrypt already returns 0 on 8.5; the post-check message was the
  only thing making it look like a failure). mcrypt is not required by DF.
…n fatals

The "active php is missing" warning still fired on a fresh OL9 install even with
the retry loop: mid-install, an extension .ini can reference a .so not built until
a later step, so a normal `php -r` FATALs and returns empty — for the whole retry
window — though the 8.5 core is fine and the API works post-install.

Use `php -n` (ignore ini files) in assert_php85_active and install_mcrypt's version
detection so they report the real core version regardless of half-configured
extensions. Extensions are still validated by their own install steps.
…e README OS list

The self-extracting dfsetup.run bundle was a stale snapshot of source/ from before
the robustness work, so `sudo ./dfsetup.run` (the documented install path) would have
shipped the un-fixed installer. Regenerated it from the current source via
update-installers.sh; verified the bundle contains all fixes (ol|oracle detection,
SELinux booleans+fcontext, MCP systemd setup, composer-path, node20, php -n, TUI env).

README: correct the supported-OS list to what the installer actually gates on
(RHEL/CentOS/Oracle/Alma/Rocky 8 & 9, Debian 12/13, Fedora 39+, Ubuntu 22/24).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant