Skip to content

binaries: strip debug symbols on Linux, build cryptography against the bundled OpenSSL - #10346

Merged
ThomasWaldmann merged 1 commit into
borgbackup:masterfrom
ThomasWaldmann:binary-size-10345
Sep 9, 2026
Merged

binaries: strip debug symbols on Linux, build cryptography against the bundled OpenSSL#10346
ThomasWaldmann merged 1 commit into
borgbackup:masterfrom
ThomasWaldmann:binary-size-10345

Conversation

@ThomasWaldmann

@ThomasWaldmann ThomasWaldmann commented Sep 9, 2026

Copy link
Copy Markdown
Member

The first three items of #10345.

Strip the debug symbols on Linux (scripts/borg.exe.spec): pythons built with the default CFLAGS carry -g, and the spec had strip=False everywhere, so about half of the Linux binaries was debug info. PyInstaller's strip now runs on the collected shared libraries (libpython, the extension modules, libcrypto, ...) on Linux only: on macOS it would interfere with code signing, and it is not recommended on Windows. Python tracebacks do not need the symbols, only gdb would.

Measured on the glibc239 x86_64 bundle of the last CI run of #10344 by stripping the shared libraries the same way: 152 -> 78 MiB unpacked, 69.6 -> 43.4 MiB compressed. A stripped bundle was tried on Debian 13 (repo-create with aes256-ocb, create, list, check, extract). This applies to the glibc243 binaries as well, they share the spec.

Build cryptography against the bundled OpenSSL (oldglibc_binary job): cryptography (a paramiko dependency from the sftp extra) comes as a manylinux wheel that statically links its own copy of OpenSSL, so the binary contained two OpenSSLs. The job now builds it from source (OPENSSL_DIR pointing at the OpenSSL built in the job, an rpath via RUSTFLAGS so it loads that one at runtime, same SONAME hazard as for python and borg) - the runner image has the Rust toolchain. Expected saving: a few MiB compressed; the main point is one OpenSSL in the binary, i.e. one thing to update on an OpenSSL CVE.

New checks in the job: the extension links and loads the job's OpenSSL, the bundled one links libcrypto dynamically, no bundled shared library still carries debug info, and the bundle sizes are printed in the log.

Bundle only the botocore service models borg needs (scripts/borg.exe.spec): botocore ships the JSON service models of all ~430 AWS services, 23 MiB, about 14 MiB in the compressed binary. borg only ever creates an s3 client, also for S3-compatible services like MinIO or Backblaze B2 (they just get a different endpoint URL), so the spec now keeps the s3 model, the shared top-level files (endpoints.json, partitions.json, _retry.json, sdk-default-configuration.json) and the models the credential providers may need: sts (assume-role and web-identity profiles), sso and sso-oidc (SSO profiles). The oldglibc_binary job checks that the other models are gone and smoke-tests the frozen binary against a MinIO server (repo-create, create, list, check, extract, repo-delete): the test suite's S3 test runs borg from the venv, not the binary.

🤖 Generated with Claude Code

@codecov

codecov Bot commented Sep 9, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 85.34%. Comparing base (7ae795e) to head (6f9cb88).
⚠️ Report is 1 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff             @@
##           master   #10346      +/-   ##
==========================================
- Coverage   87.88%   85.34%   -2.54%     
==========================================
  Files         103      103              
  Lines       18878    18878              
  Branches     2916     2916              
==========================================
- Hits        16590    16112     -478     
- Misses       1586     2078     +492     
+ Partials      702      688      -14     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

…odels, one OpenSSL

The Linux binaries were about 70 MiB as a single file and unpacked to
152 MiB at every start, see borgbackup#10345. Three changes:

Strip the debug symbols on Linux: pythons built with the default CFLAGS
carry -g, and the spec had strip=False everywhere, so about half of the
Linux binaries was debug info. Enable PyInstaller's strip for the
collected shared libraries on Linux (only there: on macOS it would
interfere with code signing, and it is not recommended on Windows).
Python tracebacks do not need the symbols, only gdb would. Measured on
the glibc239 x86_64 bundle: 152 -> 78 MiB unpacked, 69.6 -> 43.4 MiB
compressed.

Bundle only the botocore service models borg needs: botocore (boto3, s3
extra) ships the JSON service models of all ~430 AWS services, 23 MiB,
about 14 MiB in the compressed binary. borg only ever creates an s3
client - also for S3-compatible services like MinIO or Backblaze B2,
which just get a different endpoint URL - so the spec keeps only the s3
model, the shared top-level files and the models the credential
providers may need (sts, sso, sso-oidc).

In the oldglibc_binary job, build cryptography (a paramiko dependency
from the sftp extra) from source against the OpenSSL built there,
instead of using the manylinux wheel that statically links its own copy
of OpenSSL - the binary contained two OpenSSLs. The runner image has the
Rust toolchain this needs.

The job now checks that the bundled OpenSSL and Python libraries are the
ones built there by their GNU build IDs (the files are stripped now),
that cryptography links and loads that OpenSSL, that no bundled shared
library still carries debug info, that the other botocore models are
gone, prints the bundle sizes, and smoke-tests the frozen binary against
a MinIO server - the test suite's S3 test runs borg from the venv, not
the binary.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@codecov

codecov Bot commented Sep 9, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 87.88%. Comparing base (7ae795e) to head (9f3f692).
⚠️ Report is 1 commits behind head on master.
✅ All tests successful. No failed tests found.

Additional details and impacted files
@@           Coverage Diff           @@
##           master   #10346   +/-   ##
=======================================
  Coverage   87.88%   87.88%           
=======================================
  Files         103      103           
  Lines       18878    18878           
  Branches     2916     2916           
=======================================
  Hits        16590    16590           
  Misses       1586     1586           
  Partials      702      702           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

@ThomasWaldmann
ThomasWaldmann merged commit b375300 into borgbackup:master Sep 9, 2026
22 checks passed
@ThomasWaldmann
ThomasWaldmann deleted the binary-size-10345 branch September 9, 2026 19:47
ThomasWaldmann added a commit that referenced this pull request Sep 9, 2026
…43 Linux binaries

#10346 did this only in the oldglibc_binary job (glibc239 binaries). The
Linux binaries from native_tests (ubuntu-26.04, glibc243) still bundled
two OpenSSLs: the system's libcrypto, which borg's crypto extension uses
and PyInstaller bundles, and the copy statically linked into the
manylinux wheel of cryptography (a paramiko dependency, sftp extra).

Build cryptography from source against the system OpenSSL there, too,
for the Linux "binary" matrix entries - the runner image has the Rust
toolchain. The step checks that the extension links libcrypto
dynamically and loads the same OpenSSL version as the system's openssl
program; the smoke test of the built binary checks that the bundled
extension links the bundled libcrypto, and prints the bundle sizes.

The stripping of the debug symbols and the trimming of the botocore
models from #10346 live in the shared PyInstaller spec, so they already
apply to these binaries. See #10345.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
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