Installing Major Python Versions on Debian Trixie
Very, very often you have to deal with the need to use a certain version of Python, for example, for torch, or for something specific.
Using conda or Docker with nvidia-container-toolkit and then setting up images like nvidia/cuda:13.0.1-runtime-ubuntu22.04 feels counterintuitive to me, even though I’ve done it many times.
And an additional packages have to be installed in the container.
But easier and more convenient to compile everything on the host system, and at the same time prevent contamination of the entire system with third-party libraries and executable files.
The following is an example of building multiple Python versions for the verpy group only, which is a bit more convenient than installing for just one user.
ai- an arbitrary user from whom the compilation is performed.verpy- the group that will be allowed to use these versions.
1 2 3 4 | apt install \ build-essential libssl-dev zlib1g-dev libbz2-dev libreadline-dev libsqlite3-dev \ wget curl llvm libncurses5-dev libncursesw5-dev xz-utils tk-dev libffi-dev \ liblzma-dev libgdbm-dev libnsl-dev libgdbm-compat-dev |
mkdir /opt/openssl
mkdir /opt/python
groupadd --gid 42398 verpy
usermod -aG verpy ai
Provide write access for the installation
chown ai:verpy /opt/openssl /opt/python
chmod u=rwX,g=rX,o-rwXx /opt/openssl /opt/python
Switch to the user from whom the build and installation will be performed
/usr/bin/sudo-rs --login --user ai /bin/bash
mkdir -p $HOME/src/openssl
cd $HOME/src/openssl
Installing the required versions of openssl
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 | # 1.0.2u > python 3.7 wget https://github.com/openssl/openssl/releases/download/OpenSSL_1_0_2u/openssl-1.0.2u.tar.gz wget https://github.com/openssl/openssl/releases/download/OpenSSL_1_0_2u/openssl-1.0.2u.tar.gz.asc wget https://github.com/openssl/openssl/releases/download/OpenSSL_1_0_2u/openssl-1.0.2u.tar.gz.sha256 gpg --keyserver keys.gnupg.net --recv-keys 8657ABB260F056B1E5190839D9C4D26D0E604491 gpg --verify openssl-1.0.2u.tar.gz.asc tar zxf openssl-1.0.2u.tar.gz && cd openssl-1.0.2u ./config --prefix=/opt/openssl/1.0.2u --openssldir=/opt/openssl/1.0.2u/ssl make -j8 make install_sw # exec bash - reinitializes and resets any environment variables that may remain from a previous installation exec bash cd $HOME/src/openssl # 1.1.1w > python 3.9 wget https://github.com/openssl/openssl/releases/download/OpenSSL_1_1_1w/openssl-1.1.1w.tar.gz wget https://github.com/openssl/openssl/releases/download/OpenSSL_1_1_1w/openssl-1.1.1w.tar.gz.asc wget https://github.com/openssl/openssl/releases/download/OpenSSL_1_1_1w/openssl-1.1.1w.tar.gz.sha256 gpg --keyserver keys.gnupg.net --recv-keys EFC0A467D613CB83C7ED6D30D894E2CE8B3D79F5 gpg --verify openssl-1.1.1w.tar.gz.asc tar zxf openssl-1.1.1w.tar.gz && cd openssl-1.1.1w ./config --prefix=/opt/openssl/1.1.1w --openssldir=/opt/openssl/1.1.1w/ssl make -j8 make install_sw exec bash cd $HOME/src/openssl # 3.0.17 > python 3.10 ; 3.11 wget https://github.com/openssl/openssl/releases/download/openssl-3.0.17/openssl-3.0.17.tar.gz wget https://github.com/openssl/openssl/releases/download/openssl-3.0.17/openssl-3.0.17.tar.gz.asc wget https://github.com/openssl/openssl/releases/download/openssl-3.0.17/openssl-3.0.17.tar.gz.sha256 gpg --keyserver keys.gnupg.net --recv-keys BA5473A2B0587B07FB27CF2D216094DFD0CB81EF gpg --verify openssl-3.0.17.tar.gz.asc tar zxf openssl-3.0.17.tar.gz && cd openssl-3.0.17 ./config --prefix=/opt/openssl/3.0.17 --openssldir=/opt/openssl/3.0.17/ssl make -j8 make install_sw exec bash cd $HOME/src/openssl # 3.5.4 > python 3.12 wget https://github.com/openssl/openssl/releases/download/openssl-3.5.4/openssl-3.5.4.tar.gz wget https://github.com/openssl/openssl/releases/download/openssl-3.5.4/openssl-3.5.4.tar.gz.asc wget https://github.com/openssl/openssl/releases/download/openssl-3.5.4/openssl-3.5.4.tar.gz.sha256 gpg --keyserver keys.gnupg.net --recv-keys BA5473A2B0587B07FB27CF2D216094DFD0CB81EF gpg --verify openssl-3.5.4.tar.gz.asc tar zxf openssl-3.5.4.tar.gz && cd openssl-3.5.4 ./config --prefix=/opt/openssl/3.5.4 --openssldir=/opt/openssl/3.5.4/ssl make -j8 make install_sw exec bash cd $HOME/src |
Installing Python
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 | mkdir -p $HOME/src/python cd $HOME/src/python # python 3.7.17 wget https://www.python.org/ftp/python/3.7.17/Python-3.7.17.tar.xz wget https://www.python.org/ftp/python/3.7.17/Python-3.7.17.tar.xz.asc gpg --keyserver keys.gnupg.net --search-keys 0D96DF4D4110E5C43FBFB17F2D347EA6AA65421D gpg --verify Python-3.7.17.tar.xz.asc tar xvf Python-3.7.17.tar.xz && cd Python-3.7.17 LDFLAGS="${LDFLAGS} -Wl,-rpath=/opt/openssl/1.1.1w/lib" ./configure --prefix=/opt/python/3.7.17 --enable-optimizations --with-openssl=/opt/openssl/1.1.1w --with-lto --with-computed-gotos --with-system-ffi make -j8 make test make install exec bash cd $HOME/src/python # python 3.9.19 wget https://www.python.org/ftp/python/3.9.19/Python-3.9.19.tar.xz wget https://www.python.org/ftp/python/3.9.19/Python-3.9.19.tar.xz.asc gpg --keyserver keys.gnupg.net --search-keys E3FF2839C048B25C084DEBE9B26995E310250568 gpg --verify Python-3.9.19.tar.xz.asc tar xvf Python-3.9.19.tar.xz && cd Python-3.9.19 LDFLAGS="${LDFLAGS} -Wl,-rpath=/opt/openssl/1.1.1w/lib" ./configure --prefix=/opt/python/3.9.19 --enable-optimizations --with-openssl=/opt/openssl/1.1.1w --with-lto --with-computed-gotos --with-system-ffi make -j8 make test make install exec bash cd $HOME/src/python # python 3.9.25 wget https://www.python.org/ftp/python/3.9.25/Python-3.9.25.tar.xz wget https://www.python.org/ftp/python/3.9.25/Python-3.9.25.tar.xz.asc gpg --keyserver keys.gnupg.net --search-keys E3FF2839C048B25C084DEBE9B26995E310250568 gpg --verify Python-3.9.25.tar.xz.asc tar xvf Python-3.9.25.tar.xz && cd Python-3.9.25 LDFLAGS="${LDFLAGS} -Wl,-rpath=/opt/openssl/1.1.1w/lib" ./configure --prefix=/opt/python/3.9.25 --enable-optimizations --with-openssl=/opt/openssl/1.1.1w --with-lto --with-computed-gotos --with-system-ffi make -j8 make test make install exec bash cd $HOME/src/python # python 3.10.19 wget https://www.python.org/ftp/python/3.10.19/Python-3.10.19.tar.xz wget https://www.python.org/ftp/python/3.10.19/Python-3.10.19.tar.xz.asc gpg --keyserver keys.gnupg.net --search-keys CFDCA245B1043CF2A5F97865FFE87404168BD847 gpg --verify Python-3.10.19.tar.xz.asc tar xvf Python-3.10.19.tar.xz && cd Python-3.10.19 LDFLAGS="${LDFLAGS} -Wl,-rpath=/opt/openssl/3.0.17/lib" ./configure --prefix=/opt/python/3.10.19 --enable-optimizations --with-openssl=/opt/openssl/3.0.17 --with-lto --with-computed-gotos --with-system-ffi make -j8 make test make install exec bash cd $HOME/src/python # python 3.11.14 wget https://www.python.org/ftp/python/3.11.14/Python-3.11.14.tar.xz wget https://www.python.org/ftp/python/3.11.14/Python-3.11.14.tar.xz.asc gpg --keyserver keys.gnupg.net --search-keys CFDCA245B1043CF2A5F97865FFE87404168BD847 gpg --verify Python-3.11.14.tar.xz.asc tar xvf Python-3.11.14.tar.xz && cd Python-3.11.14 LDFLAGS="${LDFLAGS} -Wl,-rpath=/opt/openssl/3.0.17/lib" ./configure --prefix=/opt/python/3.11.14 --enable-optimizations --with-openssl=/opt/openssl/3.0.17 --with-lto --with-computed-gotos --with-system-ffi make -j8 make test make install exec bash cd $HOME/src/python # python 3.12.12 wget https://www.python.org/ftp/python/3.12.12/Python-3.12.12.tar.xz wget https://www.python.org/ftp/python/3.12.12/Python-3.12.12.tar.xz.asc gpg --keyserver keys.gnupg.net --search-keys 7169605F62C751356D054A26A821E680E5FA6305 gpg --verify Python-3.12.12.tar.xz.asc tar xvf Python-3.12.12.tar.xz && cd Python-3.12.12 LDFLAGS="${LDFLAGS} -Wl,-rpath=/opt/openssl/3.5.4/lib" ./configure --prefix=/opt/python/3.12.12 --enable-optimizations --with-openssl=/opt/openssl/3.5.4 --with-lto --with-computed-gotos make -j8 make test make install exec bash |
strip - it’s up to you
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | # [ --strip-all | --strip-unneeded ] strip --strip-unneeded /opt/python/3.10.19/bin/python3.10 strip --strip-unneeded /opt/python/3.11.14/bin/python3.11 strip --strip-unneeded /opt/python/3.12.12/bin/python3.12 strip --strip-unneeded /opt/python/3.7.17/bin/python3.7 strip --strip-unneeded /opt/python/3.7.17/bin/python3.7m strip --strip-unneeded /opt/python/3.9.19/bin/python3.9 strip --strip-unneeded /opt/python/3.9.25/bin/python3.9 strip --strip-unneeded /opt/openssl/1.0.2u/bin/openssl strip --strip-unneeded /opt/openssl/1.1.1w/bin/openssl strip --strip-unneeded /opt/openssl/3.0.17/bin/openssl strip --strip-unneeded /opt/openssl/3.5.4/bin/openssl exit |
Now let’s take away the write access
That’s it, OpenSSL and Python are installed, write access may must be removed.
Read, write, and execute permissions only for the verpy group.
All other users will not interact with these packages in any way, this is not FrankenDebian.
chown -R nobody:verpy /opt/openssl /opt/python
chmod -R u=r,g=rXx,o-rwXx /opt/openssl /opt/python
Linking all versions of Python
Run the following script as the ai user:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | #!/bin/bash if [[ ! -d "$HOME/.local/bin" ]]; then mkdir -p $HOME/.local/bin fi declare -A dirs=( ["3.7.17"]="2to3-3.7 easy_install-3.7 idle3.7 pip3.7 pydoc3.7 python3.7 python3.7m pyvenv-3.7 python3.7m-config" ["3.9.25"]="2to3-3.9 idle3.9 pip3.9 pydoc3.9 python3.9 python3.9-config" ["3.10.19"]="2to3-3.10 idle3.10 pip3.10 pydoc3.10 python3.10 python3.10-config" ["3.11.14"]="2to3-3.11 idle3.11 pip3.11 pydoc3.11 python3.11 python3.11-config" ["3.12.12"]="2to3-3.12 idle3.12 pip3.12 pydoc3.12 python3.12 python3.12-config" ) for dir in "${!dirs[@]}"; do printf '%s\n' "$dir" bins="${dirs[$dir]}" for bin in ${bins}; do printf '/opt/python/%s/bin/%s > ~/.local/bin/%s\n' "${dir}" "$bin" "$bin" ln -sf /opt/python/${dir}/bin/${bin} $HOME/.local/bin/${bin} done bins='' done |
Some tests
import ssl
ssl.OPENSSL_VERSION
import sys
print(sys.executable)
python3.7
1 2 3 4 5 6 7 8 9 | Python 3.7.17 (default, Dec 22 2025, 10:58:22) [GCC 14.2.0] on linux Type "help", "copyright", "credits" or "license" for more information. >>> import ssl >>> ssl.OPENSSL_VERSION 'OpenSSL 1.1.1w 11 Sep 2023' >>> import sys >>> print(sys.executable) /home/ai/.local/bin/python3.7 |
python3.12
1 2 3 4 5 | Python 3.12.12 (main, Dec 22 2025, 12:33:21) [GCC 14.2.0] on linux Type "help", "copyright", "credits" or "license" for more information. >>> import ssl >>> ssl.OPENSSL_VERSION 'OpenSSL 3.5.4 30 Sep 2025' |
Install torch with python 3.10
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | mkdir ~/.torch_env/ python3.10 -m venv ~/.torch_env/ source ~/.torch_env/bin/activate which pip3 # /home/ai/.torch_env/bin/pip3 which python3.10 # /home/ai/.torch_env/bin/python3.10 python3.10 -m pip install --upgrade pip pip3 install torch numpy python3.10 from torch import cuda print(cuda.get_device_name(cuda.current_device())) |
1 2 3 4 5 6 | python3.10 Python 3.10.19 (main, Dec 22 2025, 11:39:18) [GCC 14.2.0] on linux Type "help", "copyright", "credits" or "license" for more information. >>> from torch import cuda >>> print(cuda.get_device_name(cuda.current_device())) NVIDIA RTX A3000 Laptop GPU |
If some tests fail
You can continue the installation and then pass the same test under the tested version of Python:
1 2 | 1 test failed:
test_urllib2
|
cd ~/src/python/Python-3.7.17/Lib
1 2 3 | /opt/python/3.7.17/bin/python3.7 -m test test_ssl /opt/python/3.7.17/bin/python3.7 -m test test_urllib2 == Tests result: SUCCESS == |
Original post on SecOps.it Blog • Installing Major Python Versions on Debian Trixie