Implement gitlab-runner helper concrete image variant
Create a new "concrete" base image that has a portable git distribution.
Problem
We need a git binary that runs on any Linux distribution — from minimal busybox/scratch containers to FIPS-mandated enterprise environments like RHEL 8/9. The challenges:
- No guaranteed system dependencies — target environments may have no shell, no package manager, no shared libraries at all
- FIPS compliance — on regulated systems, we must use the host's FIPS-validated OpenSSL rather than shipping our own
- OpenSSL ABI split — OpenSSL 1.1 and 3.x are binary-incompatible (different sonames), and both are actively deployed (RHEL 8 ships 1.1, RHEL 9+ ships 3.x)
- Multi-architecture — must support amd64, arm, arm64, s390x, ppc64le, and riscv64
Approach
We build git once and bundle everything it needs to run, with runtime detection to adapt to the host environment.
Bundled glibc and dependencies
Rather than statically linking (which prevents using host OpenSSL) or depending on the host's libc (which varies across distros), we ship our own glibc, libcurl, libz, libpcre2, etc. alongside git. A bundled ld-linux dynamic linker loads these via --library-path, making the installation fully relocatable.
Single git binary, two libcurls
Git itself never touches OpenSSL directly. The dependency chain is git → git-remote-https → libcurl → libssl. Since only libcurl has a direct OpenSSL dependency, we ship two copies of libcurl.so.4: one linked against OpenSSL 3.x (from the system package) and one built from source against OpenSSL 1.1. Everything else is shared.
Static Go wrapper
Each git ELF binary is renamed to git.real and replaced by a small, fully static Go binary (no libc dependency at all). At runtime, the wrapper:
- Checks
/etc/ld.so.cacheand common library paths to detect the host's OpenSSL version - Selects the appropriate
--library-pathto load the right libcurl - Sets
GIT_EXEC_PATHandGIT_TEMPLATE_DIRrelative to its own location - Invokes the bundled
ld-linuxwith--argv0to preserve multicall dispatch
Runtime behavior
| Host environment | libcurl used | OpenSSL used | FIPS? |
|---|---|---|---|
| Has OpenSSL 3.x | Bundled (ossl3) | Host's libssl.so.3 | Yes, if host is FIPS |
| Has OpenSSL 1.1 | Bundled (ossl1) | Host's libssl.so.1.1 | Yes, if host is FIPS |
| No OpenSSL | Bundled (ossl3) | Bundled libssl.so.3 | No |
Size optimizations
- All ELF binaries and shared libraries are stripped
- Git built with
NO_PERL,NO_PYTHON,NO_GITWEB,NO_GETTEXT,NO_TCLTK - Duplicate binaries in
libexec/git-core/(git's multicall pattern) are symlinked rather than copied - Unnecessary templates, hooks, and mergetools removed
Git LFS
Included as a pre-built static binary from the official releases. No wrapper needed since it has zero runtime dependencies.
Future: dropping OpenSSL 1.1 support
When RHEL 8 reaches EOL (2029) or is no longer a target, removing 1.1 support is a clean cut:
- Delete
lib/ossl1-curl/from the distribution - Remove the OpenSSL 1.1 and curl-from-source build steps from the Dockerfile
- Remove the
"1.1"case from the Go wrapper
No git rebuild required.
Relates to gitlab-org/gitlab-runner#39286 (closed)