Which Python to Install on Ubuntu Server
Ubuntu's own tools run on /usr/bin/python3, so never replace it. Run a newer Python beside it with uv, the deadsnakes PPA or Docker. Here is which to pick.
Which Python should you install on Ubuntu Server?
Which Python to install on Ubuntu Server has a short answer: keep the Python that Ubuntu ships, and install any other version beside it. You do not update or replace the system interpreter. Ubuntu's own tools run on /usr/bin/python3, so changing what that path points to breaks package hooks and security updates. A second interpreter in its own path gives you the version your app needs, and the system never sees it.
This guide shows what each LTS (long-term support) release ships and why that interpreter must stay where it is. Then it compares three ways to run a second version: interpreters managed by uv, the deadsnakes PPA (personal package archive), and the official python container image. It ends with one recommendation per use case.
What does python3 --version print on Ubuntu 24.04 and 26.04?
Check the interpreter before you install anything.
python3 --version
ls -l /usr/bin/python3On Ubuntu 24.04 (noble) the first command prints Python 3.12.3, and the symlink points to python3.12. On Ubuntu 26.04 (resolute) it prints Python 3.14.4, and the symlink points to python3.14. These values come from the Ubuntu package archive as of October 2026. Noble ships the python3.12 package at upstream version 3.12.3, and resolute ships python3.14 at upstream version 3.14.4.
Do not trust a version number quoted from memory, including the ones above. Run the command on your own server. There is also a common mix-up here. The python3 package has its own version number (3.14.3-0ubuntu2 on resolute), and that number is not the interpreter version. Some guides quote the package version by mistake.
Ubuntu keeps one Python minor version for the life of a release, but it does not promise to keep the same upstream patch release. Many security fixes are backported into the version a release shipped with, so often only the package revision changes. On noble the python3.12 package was at 3.12.3-1ubuntu0.17 when this was checked on 13 October 2026, and python3 --version still prints Python 3.12.3. That is one case, not the rule. On Ubuntu 22.04 (jammy) the python3.10 package was released at upstream 3.10.4 and is now at 3.10.12 in the security and updates pockets. Either way, a scanner that reads only the version string can report CVEs (common vulnerabilities and exposures) that are already fixed. Read apt changelog python3.12 to see which fixes you have. For a wider check, see how to check an Ubuntu server for known CVEs.
A fresh server also has no python command. Typing python returns Command 'python' not found (or python: command not found on a minimal image). The python-is-python3 package adds /usr/bin/python as a link to the system Python 3. That is the one extra link Ubuntu supports, because it points to the same interpreter.
Why you must not replace /usr/bin/python3
apt-cache rdepends --installed python3
head -n 1 /usr/bin/unattended-upgrade /usr/bin/cloud-initThe first command lists every installed package that depends on python3. Read the list on your own server. On a stock cloud image it includes cloud-init and unattended-upgrades, and usually several more. The second command prints the first line of two of those programs. Both print #!/usr/bin/python3, which means they run with whatever interpreter that path points to.
These programs also import compiled modules that Ubuntu built for one Python version only. The python3-apt package is the clearest case. Its apt_pkg module is compiled for the system version, so the import fails under any other interpreter. Point /usr/bin/python3 at a different version, with update-alternatives or with ln -sf, and you will see this during apt update or add-apt-repository:
ModuleNotFoundError: No module named 'apt_pkg'The visible error is the mild case. unattended-upgrades runs from a systemd timer, so when it breaks there is no prompt on screen. Your security updates simply stop, and the traceback only appears in journalctl -u apt-daily-upgrade. If you depend on automatic patching, unattended-upgrades on Ubuntu explains how to confirm it still runs. cloud-init runs on every boot, and on a VPS it is the part that applies your network and user settings. Read cloud-init on a new VPS before you change anything it relies on.
If you already relinked it, put it back. On either release:
sudo update-alternatives --remove-all python3
sudo apt install --reinstall python3-minimal
python3 --versionThe python3-minimal package owns the /usr/bin/python3 link, so reinstalling it restores the link to the release's own version. If update-alternatives reports that no alternatives exist for python3, the link was changed by hand, and the reinstall alone fixes it.
The same protection shows up from the other side. On 24.04 and 26.04, pip install against the system interpreter stops with error: externally-managed-environment. The system is telling you to install packages into a virtual environment. Do not delete the marker file that causes the message. Package isolation is its own topic, covered in venv vs pipx vs uv on a server.
Three ways to run a second Python beside the system one
Each method below installs a different interpreter in a different path. None of them changes /usr/bin/python3. They differ in who builds the interpreter and in how it gets security fixes.
Option 1: interpreters managed by uv
uv is a Python package and project manager from Astral. It downloads prebuilt CPython builds from the python-build-standalone project and keeps them under your home directory. Nothing is written to /usr/bin. Pin the uv release, so every server you build gets the same tool. As of 13 October 2026 the current release is 0.13.0, published on 9 October 2026.
The installer is a third-party download. Run it yourself, as the user who will own the app, not as root:
curl -LsSf https://astral.sh/uv/0.13.0/install.sh | shThe installer puts uv in ~/.local/bin and adds that directory to your shell profile. Open a new shell, then install an interpreter:
uv --version
uv python install 3.13
uv python list --only-installed
python3.13 --version
python3 --versionuv --version should print uv 0.13.0. uv python install 3.13 puts a versioned python3.13 command in ~/.local/bin, and the files themselves go under ~/.local/share/uv/python/. The last command still prints the system version. That is the result you want. By default uv installs only a versioned command, so python3 still resolves to /usr/bin/python3.
Always name the version. When no version is requested or pinned, uv installs its default stable Python, and uv 0.13.0 changed that default from 3.14 to 3.15. A bare uv python install on two servers set up with different uv releases can give you two different interpreters.
Do not add --default to uv python install. That option also creates python and python3 commands in ~/.local/bin. On Ubuntu that directory comes early in your PATH, so your shell, and every script you start with #!/usr/bin/env python3, would switch interpreter. System tools keep working because they use the absolute path /usr/bin/python3. Your own scripts would run on a different interpreter without any warning.
In practice you rarely call python3.13 directly. You let uv choose it for a project, with uv venv --python 3.13 or uv run --python 3.13 app.py. uv-managed interpreters are not apt packages, so unattended-upgrades never patches them. Run uv python upgrade 3.13 to move to the newest 3.13 patch release, and add that step to the routine you already use to deploy the app.
Option 2: the deadsnakes PPA
The deadsnakes PPA is a community archive on Launchpad that builds other CPython versions as .deb packages. It is not run by Canonical or by the Python core developers. Its own description says there is no guarantee of timely security updates, and that production use is at your own risk.
As of October 2026 it publishes for Ubuntu 22.04, 24.04 and 26.04. It skips the version each release already ships, so there is no 3.12 for noble and no 3.14 for resolute. Check the PPA page before you rely on it, because the list of series changes as Ubuntu releases start and end support.
Adding a PPA is your decision to make, since it gives a third party the right to ship packages to your server. If you accept that, run:
sudo add-apt-repository ppa:deadsnakes/ppa
sudo apt update
sudo apt install python3.13 python3.13-venv
python3.13 --version
python3 --versionThis installs /usr/bin/python3.13, and python3 still prints the system version. Install python3.13-venv together with the interpreter. Without it, python3.13 -m venv .venv stops with The virtual environment was not created successfully because ensurepip is not available. That happens because Debian and Ubuntu split the ensurepip module into that separate package.
Updates need attention. The default unattended-upgrades configuration only accepts Ubuntu's own origins, so deadsnakes updates wait for a manual sudo apt upgrade unless you add the PPA's origin to the allowed list. A release upgrade also disables third-party sources. After you upgrade Ubuntu 24.04 to 26.04, the PPA stays off until you enable it again for the new series.
Option 3: the official python container image
The python image on Docker Hub is a Docker Official Image. It is built on Debian, not Ubuntu. As of October 2026 the default tags use Debian 13 (trixie). The interpreter lives inside the container, so the host's Python does not matter at all.
docker run --rm python:3.13-slim python --versionThis should print Python 3.13 followed by the newest patch number in that tag. For anything you deploy, pin the full tag, for example python:3.13.16-slim-trixie. Then a rebuild cannot change the interpreter or the Debian release without you noticing.
Docker Hub recommends the default (non-slim) tag unless image size matters. The slim tag leaves out compilers and many libraries, so a package with no prebuilt wheel fails to build inside it. The Alpine tags use a different C library, musl instead of glibc, and many prebuilt wheels do not support musl. If you are new to running services this way, start with Docker Compose basics on a VPS. Updates come from pulling a newer image and recreating the container, not from apt.
Which method should you use for each job?
- A script or cron job that runs on the system version: use
/usr/bin/python3with a virtual environment. Install nothing. - A web app or web service that needs a newer Python than the release ships: use uv-managed interpreters. They live under the app user's home, survive release upgrades, and need no third-party apt source. If the app is Django, deploying Django with Gunicorn and Nginx covers the service side.
- A service you already ship as containers: use the official image, pinned to a full tag. The host's Python then no longer matters.
- A tool that expects a
.debinterpreter at/usr/bin/python3.X, such as a build against system-devheaders: use deadsnakes, and write down that you accept the community security caveat. - You want a newer system Python for everything: move the server to a newer release. Read LTS vs interim Ubuntu releases on a server first, because interim releases have a short support window.
What happens to the second Python when you upgrade Ubuntu?
A release upgrade changes the system interpreter. Going from 24.04 to 26.04 moves /usr/bin/python3 from 3.12 to 3.14. Virtual environments built on the system interpreter record version 3.12 in pyvenv.cfg and keep their packages under lib/python3.12/. After the upgrade those packages are not found, so the app fails with ModuleNotFoundError. Recreate those environments after the upgrade.
The other methods behave differently. uv-managed interpreters sit in your home directory, so the release upgrade does not touch them, and environments built on them keep working. Deadsnakes packages from the old series stay installed, but they get no updates until you enable the PPA again. A container image is not affected at all. If an upgrade stops halfway, recovering a failed Ubuntu release upgrade covers the repair steps.
FAQ
Can I upgrade the system Python on Ubuntu to a newer version?
No. Ubuntu keeps one Python minor version for the life of a release, and tools such as unattended-upgrades and cloud-init run on it through /usr/bin/python3. Install the newer version beside it with uv, the deadsnakes PPA or a container image. Or upgrade to a newer Ubuntu release that ships a newer system Python.
Why does apt print "No module named 'apt_pkg'"?
/usr/bin/python3 points to a different Python version than the one Ubuntu built python3-apt for, so the compiled apt_pkg module cannot load. This almost always follows an update-alternatives or ln -sf change. Run sudo update-alternatives --remove-all python3, then sudo apt install --reinstall python3-minimal, and check that python3 --version prints the release's own version again.
Is the deadsnakes PPA safe for a production server?
It is a community archive, not an official Ubuntu or Python source. Its maintainers state that there is no guarantee of timely security updates and that production use is at your own risk. Its updates also fall outside the default unattended-upgrades origins. For a production web app, uv-managed interpreters or the official python container image are the safer default.
Why does pip say "externally-managed-environment" on Ubuntu?
Ubuntu marks the system interpreter as managed by apt, so pip install refuses to write into it. This stops pip from replacing files that apt-installed tools depend on. Create a virtual environment and install packages there, or use uv or pipx for command-line tools. Do not delete the marker file to silence the error.
Which Python version does Ubuntu 26.04 ship?
As of October 2026 the archive's python3.14 package is at upstream version 3.14.4, so python3 --version on a 26.04 server prints Python 3.14.4. The python3 package has a separate version number (3.14.3-0ubuntu2), which is easy to mistake for the interpreter version. Run python3 --version on your own server to see the real value.