If you're coming from the Wild West of servers, you may have the occasional old/unmaintained/13 year uptime server living fine and well in your management. You know you desperately need to wipe the server and reinstall a modern OS, but alas, there is no time for that and you need to add new software on top of old servers.
Well, strap in, it's going to be a long journey.
So - the goal is to install https://www.borgbackup.org/ on a server that is so old that it doesn't even know how to connect to https sites anymore, because its openssl uses TLS 1.0. The server comes with perl-5.8.8, openssl 0.9.8b, python 2.5.1 and we need to install a python3 program that requires openssl 1.1.
$ wget https://github.com/borgbackup/borg/releases/download/1.1.10/borg-linux64
--11:52:45-- https://github.com/borgbackup/borg/releases/download/1.1.10/borg-linux64
=> `borg-linux64'
Resolving github.com... 140.82.121.4
Connecting to github.com|140.82.121.4|:443... connected.
OpenSSL: error:1407742E:SSL routines:SSL23_GET_SERVER_HELLO:tlsv1 alert protocol version
Unable to establish SSL connection.
That is why we will consider that this old server is on an isolated network and can't connect to the internet.
Challenge accepted!
So - why can't I just take a precompiled borg binary (that bundles python3.5) from the borg backup release page, like this (https://github.com/borgbackup/borg/releases/download/1.1.10/borg-linux64)? Here's why:
$ /usr/local/bin/borg-linux64
Error loading Python lib '/tmp/_MEIhppGHJ/libpython3.5m.so.1.0': /lib64/libc.so.6: version `GLIBC_2.9' not found (required by /tmp/_MEIhppGHJ/libpython3.5m.so.1.0)
My glibc version is too old and doesn't have the required functions needed by the precompiled binary:
$ /lib/libc.so.6 | head -1
GNU C Library stable release version 2.7, by Roland McGrath et al.
The plan
So - we need to:
- compile perl 5.34 locally (needed to compile openssl)
- compile openssl 1.1 locally
- compile python 3.9 locally
- transfer borgbackup package and install locally
- profit!
Compiling Perl
To install perl from source you can easily follow the steps outlined here: http://www.cpan.org/src/. You will need to have gcc and make installed in your local Linux distro. I used gcc 4.1.2 and it worked fine. You will probably need to download the source on a computer that can speak HTTPS and transfer it (e.g. scp) to your destination server.
$ wget https://www.cpan.org/src/5.0/perl-5.34.0.tar.gz $ tar -xzf perl-5.34.0.tar.gz $ cd perl-5.34.0
$ ./Configure -des -Dprefix=/opt/perl5/
$ make
$ make test
$ make install
The make test step will take a while. Once it finishes, you should have a working perl in /opt/perl5. You can test it with:
$ /opt/perl5/bin/perl --version
This is perl 5, version 34, subversion 0 (v5.34.0) built for x86_64-linux
Copyright 1987-2021, Larry Wall
Perl may be copied only under the terms of either the Artistic License or the
GNU General Public License, which may be found in the Perl 5 source kit.
Complete documentation for Perl, including FAQ lists, should be found on
this system using "man perl" or "perldoc perl". If you have access to the
Internet, point your browser at http://www.perl.org/, the Perl Home Page.
Compiling openssl
You can get openssl-1.1.1k from here: https://www.openssl.org/source/openssl-1.1.1k.tar.gz
$ wget https://www.openssl.org/source/openssl-1.1.1k.tar.gz
$ tar zxvf openssl-1.1.1k.tar.gz
$ cd openssl-1.1.1k
$ PATH=/opt/perl5/bin:$PATH
$ ./config --prefix=/opt/openssl11 --openssldir=/opt/openssl11/ssl
$ make
$ sudo make install
# ln -s /opt/openssl11/ /usr/local/openssl
Note, this openssl version does not override your system openssl, because that may break things.
Compiling Python3
Python needs some nonstandard linux packages in order to be compiled. You'll need to track down and install the following:
* libffi
* libffi-devel
* zlib
* zlib-devel
$ wget https://www.python.org/ftp/python/3.9.5/Python-3.9.5.tgz
$ tar zxvf Python-3.9.5.tgz
$ cd Python-3.9.5
$ ./configure --prefix=/opt/python3 --enable-unicode=ucs4 --enable-shared LDFLAGS="-Wl,-rpath /usr/local/lib"
$ make
$ make install
In order to run python you'll need to tell the loader where it can load the python library:
$ cat /etc/ld.so.conf.d/python-3.9.5.conf
/opt/python2/lib
$ sudo ldconfig
Now, you should be able to run python3:
$ /opt/python3/bin/python3 --version
Python 3.9.5
Compiling borg backup
In addition to all this build environment that we've set up, borg backup also needs:
* gcc-c++
* libattr
* libattr-devel
* libacl
* libacl-devel
So you'll need to track down those packages for your distribution and install them. In my case I had to force downgrade some of them because I had libacl installed and could only find a slightly older libacl-devel:
$ sudo rpm -Uvh --oldpackage libacl-2.2.39-10.fc8.x86_64.rpm
Now comes the tricky part. You'll need to download borg backup and its dependencies from PyPy, but since you don't have connectivity (python3 was not bound to the new openssl) you'll need to do it on a different system. The problem is, on the intermediary system you'll need to run the same python version as the target, so that it downloads the correct wheels. So - you might need to rerun the python3 installation steps on the intermediary system before you proceed.
To download borg backup + dependencies, on an intermediary system, do:
$ mkdir to-transfer
$ cd to-transfer
$ /opt/python3/bin/pip3 download borgbackup
$ /opt/python3/bin/pip3 download "setuptools_scm>=1.7"
$ /opt/python3/bin/pip3 download "setuptools==57"
Transfer the downloaded files to the target server and install them:
$ sudo /opt/python3/bin/python3 -m pip install setuptools-57.0.0-py3-none-any.whl
$ sudo /opt/python3/bin/python3 -m pip install setuptools_scm-6.0.1-py3-none-any.whl
$ tar zxvf borgbackup-1.1.16.tar.gz
$ cd borgbackup-1.1.16
$ sudo /opt/python3/bin/python3 -m pip install .
Once the installation finishes correctly you should have /opt/python3/bin/borg you can play with:
$ /opt/python3/bin/borg -v
Traceback (most recent call last):
File "/opt/python3/lib/python3.9/site-packages/borg/archiver.py", line 38, in <module>
from . import helpers
File "/opt/python3/lib/python3.9/site-packages/borg/helpers.py", line 76, in <module>
import borg.crypto.low_level
ImportError: libcrypto.so.1.1: cannot open shared object file: No such file or directory
But to make it run, you'll need to prefix it with the correct path to openssl:
$ LD_LIBRARY_PATH=/opt/openssl11/lib:$LD_LIBRARY_PATH /opt/python3/bin/borg -V
borg 1.1.16
In order to make that nice and quick to remember, let's make a simple shell script:
$ cat /usr/local/bin/borg
#!/bin/bash
LD_LIBRARY_PATH=/opt/openssl11/lib:$LD_LIBRARY_PATH /opt/python3/bin/borg "$@"
Moral of the story? Old servers can be a pain to maintain, but there's little reason they can't run more modern software...
Comments