本番環境、テスト環境両方ともdnf、yumでパッケージインストールだけで済めば良いのですが、そうでない場合がありますよね?
良くあるパターンとしては、PHPはパッケージでインストールしたOpenSSLを使用して、ApacheだけソースコードからビルドしてインストールしたOpenSSLを使いたい場合です。
PHPは外部にさらすわけではないので、ローカルのOpenSSLにリンクさせ、外部に解放するApacheは最新のOpenSSLにリンクさせたいってニーズがあるかと思います。
よくLD_LIBRARY_PATHやld.so.confにライブラリの検索パスを定義して解決する手法を見ますが、これをやってしまうとシステム全体に影響が出てしまい、ある意味PHPとApacheの住み分けができなくなってしまいます。
そこで理想的な解決手段として取り得るのが、実行バイナリにシェアードライブラリの検索パスを埋め込み、実行時にシェアードライブラリを探しに行くパスを指定してしまうことです。この手法を用いるとPHP用のOpenSSL、Apache用のOpenSSLと言った複数バージョンのOpenSSLを使い分けることが可能となります。ただし、ハードルが少し高く、PHP、Apache両方ともソースコードからビルドする必要があります。
なぜかというと、検索パスの指定、実行バイナリへの埋め込みはバイナリを生成するコンパイル時にしかできないからです。それでは、実際の例を見ていきましょう。
PHPのインストール
周辺ライブラリのインストール
dnf config-manager --set-enabled powertools
dnf install epel-release
dnf install libtool \
gcc-c++ \
gcc-toolset-11-gcc-c++
dnf install wget \
tar \
gcc \
make \
zlib \
zlib-devel \
expat \
expat-devel \
libtool \
pcre \
pcre-devel -y
dnf install readline \
readline-devel -y
dnf install autoconf \
uw-imap \
uw-imap-devel \
libzip \
libzip-devel \
zlib \
zlib-devel \
curl \
libcurl \
libcurl-devel \
libssh \
libssh-config \
libssh-devel \
gd \
gd-devel \
libpng \
libpng-devel \
freetype \
freetype-devel \
fontconfig \
fontconfig-devel \
libjpeg-turbo \
libjpeg-turbo-devel \
libXpm \
libXpm-devel \
libtiff \
libtiff-devel \
libxslt \
libxslt-devel \
re2c \
libxml2 \
libxml2-devel \
libwebp \
libwebp-devel \
oniguruma \
oniguruma-devel \
sqlite-devel
wget https://imagemagick.org/archive/ImageMagick.tar.gz
tar xvfz ImageMagick.tar.gz
cd ImageMagick-7.1.1-43
./configure --prefix=/var/home/lib/imagic
make all
make install
PHPソースコードのダウンロード・展開
./configure \
--prefix=/var/home/ap/php \
--enable-fpm \
--with-config-file-path=/var/home/ap/php/etc \
--enable-libgcc \
--with-openssl \
--with-zlib \
--with-zlib-dir=/usr \
--enable-gd \
--with-freetype \
--with-jpeg \
--with-xpm \
--with-webp \
--enable-bcmath \
--with-bz2 \
--enable-calendar \
--with-curl \
--enable-dba=shared \
--enable-exif \
--with-curl \
--enable-gd-jis-conv \
--with-gettext \
--enable-mbstring \
--with-mysqli=mysqlnd \
--with-pdo-mysql=mysqlnd \
--enable-pcntl \
--with-readline \
--enable-soap \
--enable-sockets \
--with-xsl \
--with-imap \
--with-imap-ssl \
--with-libdir=lib64 \
--with-kerberos \
--enable-opcache \
--enable-shared
make all
make install
各種拡張モジュールのインストール
wget https://pecl.php.net/get/apcu-5.1.22.tgz
※ https://pecl.php.net/package/APCu
tar xvfz apcu-5.1.22.tgz
cd apcu-5.1.22/
/var/home/ap/php/bin/phpize
./configure --enable-apcu --with-php-config=/var/home/ap/php/bin/php-config
make all
make install
Installing shared extensions: /var/home/ap/php/lib/php/extensions/no-debug-non-zts-20210902/
Installing header files: /var/home/ap/php/include/php/
※https://pecl.php.net/package/imagick
wget https://pecl.php.net/get/imagick-3.7.0.tgz
tar xvfz imagick-3.7.0.tgz
cd imagick-3.7.0
/var/home/ap/php/bin/phpize
PKG_CONFIG_PATH=/var/home/lib/imagic/lib/pkgconfig/ \
./configure --prefix=/var/home/ap/php/lib/php/extensions/no-debug-non-zts-20210902 --with-libdir=/var/home/lib/imagic/lib --with-php-config=/var/home/ap/php/bin/php-config
make all
cp modules/imagick.so /var/home/ap/php/lib/php/extensions/no-debug-non-zts-20210902/
シェアードライブラリのリンク先を確認する
cd /var/home/ap/php/bin
ldd ./php
linux-vdso.so.1 (0x00007ffe377dc000)
libcrypt.so.1 => /lib64/libcrypt.so.1 (0x00007fc6452ee000)
libc-client.so.2007 => /lib64/libc-client.so.2007 (0x00007fc644fd8000)
libresolv.so.2 => /lib64/libresolv.so.2 (0x00007fc644dc0000)
libreadline.so.7 => /lib64/libreadline.so.7 (0x00007fc644b71000)
libncurses.so.6 => /lib64/libncurses.so.6 (0x00007fc644946000)
libtinfo.so.6 => /lib64/libtinfo.so.6 (0x00007fc644719000)
librt.so.1 => /lib64/librt.so.1 (0x00007fc644511000)
libbz2.so.1 => /lib64/libbz2.so.1 (0x00007fc644300000)
libutil.so.1 => /lib64/libutil.so.1 (0x00007fc6440fc000)
libm.so.6 => /lib64/libm.so.6 (0x00007fc643d7a000)
libdl.so.2 => /lib64/libdl.so.2 (0x00007fc643b76000)
libxml2.so.2 => /lib64/libxml2.so.2 (0x00007fc64380e000)
libgssapi_krb5.so.2 => /lib64/libgssapi_krb5.so.2 (0x00007fc6435b9000)
libkrb5.so.3 => /lib64/libkrb5.so.3 (0x00007fc6432ce000)
libk5crypto.so.3 => /lib64/libk5crypto.so.3 (0x00007fc6430b7000)
libcom_err.so.2 => /lib64/libcom_err.so.2 (0x00007fc642eb3000)
libssl.so.1.1 => /lib64/libssl.so.1.1 (0x00007fc642c1e000)
libcrypto.so.1.1 => /lib64/libcrypto.so.1.1 (0x00007fc642733000)
libsqlite3.so.0 => /lib64/libsqlite3.so.0 (0x00007fc64241f000)
libz.so.1 => /lib64/libz.so.1 (0x00007fc642207000)
libcurl.so.4 => /lib64/libcurl.so.4 (0x00007fc641f78000)
libpng16.so.16 => /lib64/libpng16.so.16 (0x00007fc641d43000)
libwebp.so.7 => /lib64/libwebp.so.7 (0x00007fc641ad5000)
libjpeg.so.62 => /lib64/libjpeg.so.62 (0x00007fc64186c000)
libXpm.so.4 => /lib64/libXpm.so.4 (0x00007fc641659000)
libX11.so.6 => /lib64/libX11.so.6 (0x00007fc641315000)
libfreetype.so.6 => /lib64/libfreetype.so.6 (0x00007fc641059000)
libonig.so.5 => /lib64/libonig.so.5 (0x00007fc640dd5000)
libxslt.so.1 => /lib64/libxslt.so.1 (0x00007fc640b94000)
libexslt.so.0 => /lib64/libexslt.so.0 (0x00007fc64097d000)
libgcrypt.so.20 => /lib64/libgcrypt.so.20 (0x00007fc64065f000)
libgpg-error.so.0 => /lib64/libgpg-error.so.0 (0x00007fc64043e000)
libc.so.6 => /lib64/libc.so.6 (0x00007fc640068000)
libpam.so.0 => /lib64/libpam.so.0 (0x00007fc63fe58000)
libpthread.so.0 => /lib64/libpthread.so.0 (0x00007fc63fc38000)
/lib64/ld-linux-x86-64.so.2 (0x00007fc645517000)
liblzma.so.5 => /lib64/liblzma.so.5 (0x00007fc63fa11000)
libkrb5support.so.0 => /lib64/libkrb5support.so.0 (0x00007fc63f800000)
libkeyutils.so.1 => /lib64/libkeyutils.so.1 (0x00007fc63f5fc000)
libnghttp2.so.14 => /lib64/libnghttp2.so.14 (0x00007fc63f3d5000)
libidn2.so.0 => /lib64/libidn2.so.0 (0x00007fc63f1b7000)
libssh.so.4 => /lib64/libssh.so.4 (0x00007fc63ef47000)
libpsl.so.5 => /lib64/libpsl.so.5 (0x00007fc63ed36000)
libldap-2.4.so.2 => /lib64/libldap-2.4.so.2 (0x00007fc63eae7000)
liblber-2.4.so.2 => /lib64/liblber-2.4.so.2 (0x00007fc63e8d7000)
libbrotlidec.so.1 => /lib64/libbrotlidec.so.1 (0x00007fc63e6ca000)
libxcb.so.1 => /lib64/libxcb.so.1 (0x00007fc63e4a1000)
libaudit.so.1 => /lib64/libaudit.so.1 (0x00007fc63e270000)
libselinux.so.1 => /lib64/libselinux.so.1 (0x00007fc63e045000)
libunistring.so.2 => /lib64/libunistring.so.2 (0x00007fc63dcc4000)
libsasl2.so.3 => /lib64/libsasl2.so.3 (0x00007fc63daa6000)
libbrotlicommon.so.1 => /lib64/libbrotlicommon.so.1 (0x00007fc63d885000)
libXau.so.6 => /lib64/libXau.so.6 (0x00007fc63d681000)
libcap-ng.so.0 => /lib64/libcap-ng.so.0 (0x00007fc63d47b000)
libpcre2-8.so.0 => /lib64/libpcre2-8.so.0 (0x00007fc63d1f7000)
上記、リンクの情報を見ていただければ、パッケージでインストールしたOpenSSLにリンクしていることが確認できます。
それでは、続いてソースコードからインストールしたOpenSSLにリンクするApacheのインストールを行ってみましょう。
注)OpenSSL3.3.2が/var/home/lib/opensslにインストールされていることを前提とします。
Apacheのインストール
周辺ライブラリのインストール
dnf install jansson \
jansson-devel \
wget \
tar \
gcc \
make \
zlib \
zlib-devel \
expat \
expat-devel \
libtool \
pcre \
pcre-devel -y
wget https://dlcdn.apache.org//apr/apr-1.7.4.tar.gz
tar xvfz apr-1.7.4.tar.gz
cd apr-1.7.4
./configure \
--prefix=/var/home/lib/apr \
--enable-shared \
--enable-threads \
--enable-posix-shm
make all
make install
mv /var/home/lib/apr /var/home/lib/apr1.7.4
ln -s /var/home/lib/apr1.7.4 /var/home/lib/apr
wget https://dlcdn.apache.org//apr/apr-util-1.6.3.tar.gz
tar xvfz apr-util-1.6.3.tar.gz
cd apr-util-1.6.3
./configure \
--prefix=/var/home/lib/apr-util \
--with-apr=/var/home/lib/apr/bin/apr-1-config
make all
make install
mv /var/home/lib/apr-util /var/home/lib/apr-util1.6.3
ln -s /var/home/lib/apr-util1.6.3 /var/home/lib/apr-util
dnf install libxml2 libxml2-devel libev libev-devel jansson jansson-devel c-ares c-ares-devel
wget https://github.com/nghttp2/nghttp2/releases/download/v1.62.1/nghttp2-1.62.1.tar.gz
tar xvfz nghttp2-1.62.1.tar.gz
cd nghttp2-1.62.1
./configure --prefix=/var/home/lib/nghttp2 \
--enable-lib-only
gmake
(約3分かかる)
gmake install
mv /var/home/lib/nghttp2 /var/home/lib/nghttp2-1.62.1
ln -s /var/home/lib/nghttp2-1.62.1 /var/home/lib/nghttp2
Apacheソースコードのダウンロード・展開
wget https://dlcdn.apache.org/httpd/httpd-2.4.62.tar.gz
tar xvfz httpd-2.4.62.tar.gz
Apacheコンパイル・インストール
LDFLAGSに-Wl,-rpathをセットすることでバイナリに検索パスを埋め込むことができます。
cd httpd-2.4.62
LDFLAGS="-Wl,-rpath=/var/home/lib/openssl/lib64" \
./configure \
--prefix=/var/home/ap/apache \
--with-apr=/var/home/lib/apr \
--with-apr-util=/var/home/lib/apr-util \
--enable-ssl \
--enable-so \
--enable-mods-shared=all \
--enable-mpms-shared=all \
--with-ssl=/var/home/lib/openssl \
--with-nghttp2=/var/home/lib/nghttp2
LDFLAGS="-Wl,-rpath=/var/home/lib/openssl/lib64" \
make all
LDFLAGS="-Wl,-rpath=/var/home/lib/openssl/lib64" \
make install
mv /var/home/ap/apache /var/home/ap/apache2.4.62
ln -s /var/home/ap/apache2.4.62 /var/home/ap/apache
シェアードライブラリのリンク先を確認する
cd /var/home/ap/apache/modules
ldd mod_ssl.so
linux-vdso.so.1 (0x00007ffca9539000)
libssl.so.3 => /var/home/lib/openssl/lib64/libssl.so.3 (0x00007f8a30190000)
libcrypto.so.3 => /var/home/lib/openssl/lib64/libcrypto.so.3 (0x00007f8a2fa40000)
libuuid.so.1 => /lib64/libuuid.so.1 (0x00007f8a2f838000)
librt.so.1 => /lib64/librt.so.1 (0x00007f8a2f630000)
libcrypt.so.1 => /lib64/libcrypt.so.1 (0x00007f8a2f407000)
libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f8a2f1e7000)
libdl.so.2 => /lib64/libdl.so.2 (0x00007f8a2efe3000)
libc.so.6 => /lib64/libc.so.6 (0x00007f8a2ec0d000)
libz.so.1 => /lib64/libz.so.1 (0x00007f8a2e9f5000)
/lib64/ld-linux-x86-64.so.2 (0x00007f8a306cf000)
上記を参照いただければわかりますが、ソースコードからインストールしたOpenSSLにリンクしていることがわかります。
ちなみに下記コマンドでmod_ssl.soの中を見ると以下の結果が得られます。
readelf -d mod_ssl.so
Dynamic section at offset 0x3ad10 contains 33 entries:
Tag Type Name/Value
0x0000000000000001 (NEEDED) Shared library: [libssl.so.3]
0x0000000000000001 (NEEDED) Shared library: [libcrypto.so.3]
0x0000000000000001 (NEEDED) Shared library: [libuuid.so.1]
0x0000000000000001 (NEEDED) Shared library: [librt.so.1]
0x0000000000000001 (NEEDED) Shared library: [libcrypt.so.1]
0x0000000000000001 (NEEDED) Shared library: [libpthread.so.0]
0x0000000000000001 (NEEDED) Shared library: [libdl.so.2]
0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
0x000000000000000e (SONAME) Library soname: [mod_ssl.so]
0x000000000000000f (RPATH) Library rpath: [/var/home/lib/openssl/lib64]
0x000000000000000c (INIT) 0xb160
0x000000000000000d (FINI) 0x2b048
0x0000000000000019 (INIT_ARRAY) 0x239e30
0x000000000000001b (INIT_ARRAYSZ) 8 (bytes)
0x000000000000001a (FINI_ARRAY) 0x239e38
0x000000000000001c (FINI_ARRAYSZ) 8 (bytes)
0x000000006ffffef5 (GNU_HASH) 0x1f0
0x0000000000000005 (STRTAB) 0x3518
0x0000000000000006 (SYMTAB) 0x218
0x000000000000000a (STRSZ) 10185 (bytes)
0x000000000000000b (SYMENT) 24 (bytes)
0x0000000000000003 (PLTGOT) 0x23b000
0x0000000000000002 (PLTRELSZ) 12648 (bytes)
0x0000000000000014 (PLTREL) RELA
0x0000000000000017 (JMPREL) 0x7ff8
0x0000000000000007 (RELA) 0x6198
0x0000000000000008 (RELASZ) 7776 (bytes)
0x0000000000000009 (RELAENT) 24 (bytes)
0x000000006ffffffe (VERNEED) 0x6128
0x000000006fffffff (VERNEEDNUM) 3
0x000000006ffffff0 (VERSYM) 0x5ce2
0x000000006ffffff9 (RELACOUNT) 302
0x0000000000000000 (NULL) 0x0
mod_ssl.so内にLibrary rpathが定義されており、ソースコードからインストールしたOpenSSLのディレクトリを検索しに行くようパスが埋め込まれています。
このようにするとシステム上に複数バージョンのOpenSSLを同居させ、それぞれのアプリケーションから使い分けすることができるようになります。
以上となります。お疲れ様でした!