Skip to content

fix(macos): bundle OpenSSL so PostgreSQL starts without Homebrew - #42

Open
vadimcomanescu wants to merge 2 commits into
vectorize-io:mainfrom
nadicodeai:fix/macos-portable-openssl
Open

vadimcomanescu wants to merge 2 commits into
vectorize-io:mainfrom
nadicodeai:fix/macos-portable-openssl

Conversation

@vadimcomanescu

Copy link
Copy Markdown

Problem

The theseus-rs macOS PostgreSQL 18.1.0 binaries load OpenSSL from the Homebrew prefix of the machine that built them (theseus-rs/postgresql-binaries#30). On a Mac without Homebrew's openssl@3, PostgreSQL cannot load, so pg0 start fails.

otool -L ~/.pg0/installation/18.1.0/lib/libpq.5.dylib (pg0 0.15.2):

/opt/homebrew/opt/openssl@3/lib/libssl.3.dylib (compatibility version 3.0.0, current version 3.0.0)
/opt/homebrew/opt/openssl@3/lib/libcrypto.3.dylib (compatibility version 3.0.0, current version 3.0.0)

10 Mach-O files in the bundle reference it: bin/postgres, pg_dump, pg_dumpall, pg_restore, pgbench, pg_combinebackup, pg_verifybackup, lib/libpq.5.dylib, lib/pgcrypto.dylib, lib/sslinfo.dylib.

pg0 0.15.2 on a clean macOS 26.6.2 VM (no Homebrew, no Command Line Tools):

Error: PostgreSQL error: Command error: stdout=; stderr=dyld[762]: Library not loaded: /opt/homebrew/opt/openssl@3/lib/libssl.3.dylib
  Referenced from: <...> /Users/admin/.pg0/installation/18.1.0/lib/libpq.5.dylib

Fix

The same approach Postgres.app uses, done in build.rs for the two apple-darwin targets, next to bundle_runtime_libs:

  • libssl.3.dylib and libcrypto.3.dylib come from conda-forge's OpenSSL 3.5.9 package (the 3.5 LTS line), pinned by URL and SHA-256 in versions.env the way the Linux .debs are. conda-forge was chosen because it publishes checksummed builds for both osx-arm64 and osx-64 with a macOS 11 deployment target; Homebrew no longer ships x86_64 macOS bottles.
  • They are copied into the bundle's lib/, with OpenSSL's licence in share/openssl/LICENSE.txt.
  • Every Mach-O that references libssl.3.dylib/libcrypto.3.dylib is rewritten to @loader_path/../lib/... (install_name_tool -change, and -id for the two copied libraries), then re-signed ad hoc (codesign -f -s -), because install_name_tool invalidates the signature.
  • The build fails if any Mach-O still references /opt/homebrew or /usr/local.
  • On macOS, pg0 re-extracts an install that lacks lib/libcrypto.3.dylib, so a broken install left by an earlier pg0 gets repaired on the next pg0 start.

Linux and Windows builds are unchanged. A second commit repins libxml2 for the Linux GNU builds: Ubuntu removed libxml2_2.9.13+dfsg-1ubuntu0.12 from the archive pool (HTTP 404), so those builds were failing on main. The new pin is 0ubuntu0.13 by its Launchpad URL, which keeps every published package, and its bytes are identical to the archive pool's.

Evidence

After the fix, otool -L lib/libpq.5.dylib:

@loader_path/../lib/libssl.3.dylib (compatibility version 3.0.0, current version 3.0.0)
@loader_path/../lib/libcrypto.3.dylib (compatibility version 3.0.0, current version 3.0.0)

For the wheels build-python-wheels.yml built on macos-14 and macos-15-intel, all 127 Mach-O files in the extracted install were scanned, and 0 reference /opt/homebrew or /usr/local. pg0 start and pg0 stop work for both architectures.

On the same clean macOS 26.6.2 arm64 VM, against the broken ~/.pg0 that 0.15.2 left behind, pg0 start re-extracted the install and started PostgreSQL. CREATE EXTENSION vector worked (0.8.5), and SHOW ssl_library returned OpenSSL. vmmap showed postgres loading ~/.pg0/installation/18.1.0/lib/libssl.3.dylib and libcrypto.3.dylib. pg0 stop stopped it, and a second start/stop worked too.

The theseus-rs macOS PostgreSQL binaries load libssl/libcrypto from
/opt/homebrew/opt/openssl@3, so pg0 cannot start PostgreSQL on a Mac
without Homebrew (theseus-rs/postgresql-binaries#30).

For the apple-darwin targets, build.rs now copies libssl.3.dylib and
libcrypto.3.dylib from a pinned, checksummed conda-forge OpenSSL 3.5.9
package into the bundle's lib/, rewrites every reference to
@loader_path/../lib/, re-signs the changed files ad-hoc and fails the
build if any Mach-O still references /opt/homebrew or /usr/local.
An install extracted by an earlier pg0 is re-extracted once.
Linux and Windows builds are unchanged.
Ubuntu removed libxml2_2.9.13+dfsg-1ubuntu0.12 from the archive pool, so
the Linux GNU builds failed with HTTP 404. Pin the current jammy point
release (same bytes as the archive pool) by its Launchpad URL, which keeps
every published package.
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