Knowing exactly which Ubuntu version a server runs sounds like a question with one answer — but Linux gives you at least five commands that report it, and each one tells you something slightly different. This guide covers the ones worth knowing, when each is the right tool, and the cross-distro version that works regardless of what distribution you're actually on.
The fastest answer
If you just want the version and you're on Ubuntu (or any modern Debian-based system):
lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 24.04.1 LTS
Release: 24.04
Codename: noble
That's the canonical answer. Description gives you the marketing name (Ubuntu 24.04.1 LTS), Release gives you the numeric version you'd write in a Dockerfile (24.04), and Codename gives you the adjective-animal name Ubuntu releases get (noble, jammy, focal).
If lsb_release: command not found, install the package — on Ubuntu Server minimal installs it's not preinstalled:
sudo apt-get install -y lsb-release
The cross-distro answer: /etc/os-release
Every distribution that uses systemd ships an /etc/os-release file with standardised fields. It's the right command to reach for in any script that might run across multiple distros (Ubuntu, Debian, AlmaLinux, Rocky, Fedora, Amazon Linux, Alpine):
cat /etc/os-release
PRETTY_NAME="Ubuntu 24.04.1 LTS"
NAME="Ubuntu"
VERSION_ID="24.04"
VERSION="24.04.1 LTS (Noble Numbat)"
VERSION_CODENAME=noble
ID=ubuntu
ID_LIKE=debian
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
To extract just one field — useful in shell scripts:
. /etc/os-release # source it as shell variables
echo "$ID $VERSION_ID" # ubuntu 24.04
echo "$VERSION_CODENAME" # noble
ID is the lowercase distribution identifier (ubuntu, debian, almalinux, rocky, rhel, amzn, alpine), and VERSION_ID is the major version. Those two are the right pair to branch on in a portable deploy script — see the Linux distros for deployment guide for context on which IDs your servers might actually report.
hostnamectl — systemd's built-in
hostnamectl was designed for setting the hostname, but it also dumps OS metadata as a side effect:
hostnamectl
Static hostname: web-prod-01
Icon name: computer-vm
Chassis: vm
Machine ID: 7c3d8a9e2f1b4c6d8e0f1a2b3c4d5e6f
Boot ID: a1b2c3d4e5f60718293a4b5c6d7e8f90
Virtualization: kvm
Operating System: Ubuntu 24.04.1 LTS
Kernel: Linux 6.8.0-31-generic
Architecture: x86-64
It's the most informative single command — it tells you the distro version and the kernel and whether you're running in a VM. On any systemd system it works without extra packages installed.
uname — kernel, not distro
uname reports the kernel, which is not the same thing as the distribution. Treating it as a distro check is one of the most common mistakes:
uname -a
Linux web-prod-01 6.8.0-31-generic #31-Ubuntu SMP PREEMPT_DYNAMIC Thu May 30 21:00:00 UTC 2024 x86_64 x86_64 x86_64 GNU/Linux
The output mentions Ubuntu
, but that's part of the Ubuntu-specific kernel build identifier. On an Amazon Linux box running a Red Hat-flavoured kernel you'd see .el9.x86_64 instead. uname -r alone gives you the kernel version (6.8.0-31-generic), which matters when you're checking module compatibility, but it doesn't tell you whether the distro is Ubuntu 22.04 or 24.04.
Use uname for kernel-related decisions, not distribution-version decisions.
/etc/issue and /etc/issue.net — the legacy options
Some older guides recommend these:
cat /etc/issue
Ubuntu 24.04.1 LTS \n \l
The \n and \l are escape sequences expanded at login time (hostname and tty line). /etc/issue is what gets shown above the login prompt on a serial console. It's editable as a free-form file, so on hardened or customised systems it might contain a banner instead of the OS version. Don't rely on it in scripts — /etc/os-release is the right substitute.
Cross-distro examples — what you'll see on each
The output of /etc/os-release on the other distros covered earlier:
Debian 12:
PRETTY_NAME="Debian GNU/Linux 12 (bookworm)"
NAME="Debian GNU/Linux"
VERSION_ID="12"
VERSION="12 (bookworm)"
VERSION_CODENAME=bookworm
ID=debian
AlmaLinux 9:
NAME="AlmaLinux"
VERSION="9.4 (Seafoam Ocelot)"
ID="almalinux"
ID_LIKE="rhel centos fedora"
VERSION_ID="9.4"
PLATFORM_ID="platform:el9"
PRETTY_NAME="AlmaLinux 9.4 (Seafoam Ocelot)"
Amazon Linux 2023:
NAME="Amazon Linux"
VERSION="2023"
ID="amzn"
ID_LIKE="fedora"
VERSION_ID="2023"
PRETTY_NAME="Amazon Linux 2023.5.20240805"
PLATFORM_ID="platform:al2023"
Alpine 3.20:
NAME="Alpine Linux"
ID=alpine
VERSION_ID=3.20.3
PRETTY_NAME="Alpine Linux v3.20"
HOME_URL="https://alpinelinux.org/"
Notice that AlmaLinux and Amazon Linux both set ID_LIKE to fedora / rhel — that's the field to branch on when you want anything in the RHEL family
rather than a specific distro. Debian-derivatives (Ubuntu, Mint) set ID_LIKE=debian.
Scripting version checks in CI
A common pattern in deploy scripts: gate a step on the distro and version. The portable version:
#!/usr/bin/env bash
set -euo pipefail
. /etc/os-release
case "$ID" in
ubuntu|debian)
sudo apt-get update
sudo apt-get install -y nginx
;;
almalinux|rocky|rhel|fedora|amzn)
sudo dnf install -y nginx
;;
*)
echo "Unsupported distro: $ID" >&2
exit 1
;;
esac
For an exact-version check (some deploy steps only support specific versions):
. /etc/os-release
if [[ "$ID" == "ubuntu" && "$VERSION_ID" == "24.04" ]]; then
echo "Detected Ubuntu 24.04 — using the noble apt source"
fi
The [[ ... ]] test treats VERSION_ID as a string, which is what you want — 24.04 is a label, not a number. (Bash float arithmetic would interpret 24.04 and 24.10 as 24.04 and 24.1 respectively, which is exactly the wrong thing.)
For richer version comparisons (greater-than-or-equal), use dpkg --compare-versions on Debian-family or rpm -q --qf on RHEL-family rather than rolling your own.
Container-specific: how cat /etc/os-release behaves inside containers
Inside a Docker container, cat /etc/os-release reports the image's distro, not the host's. A Debian-slim container running on an Amazon Linux host:
docker run --rm debian:12-slim cat /etc/os-release
PRETTY_NAME="Debian GNU/Linux 12 (bookworm)"
ID=debian
That's usually what you want — the script inside the container should see the container's filesystem. But it does mean what distro is this server?
gives different answers depending on whether you're asking the host or a container. The host answer comes from cat /etc/os-release on the bare metal; the container answer comes from inside docker exec.
For Kubernetes nodes, the right place to check the host OS is via the kubelet's nodeInfo field (kubectl get nodes -o wide) or by ssh'ing into the node directly.
Related deploys
Knowing your distro version unlocks the rest of the server-ops command set:
- Essential Linux server commands for deployment — disk space, memory, process and log inspection that come up every release.
- Deploying WordPress on a VPS — distro-version-specific install steps for the most common LAMP stack.
- Installing cPanel on Ubuntu 22.04 — Ubuntu version specificity matters here because cPanel only supports specific point releases.
- Installing Keycloak on a VPS — Ubuntu-targeted but the version-check pattern carries.
For deploys themselves, DeployHQ is distro-agnostic — the build pipelines feature runs your build inside a container, and the deploy lands on whichever Linux distribution your target servers happen to run. Start a free trial to wire any of these distros into a Git-driven deploy workflow.
Need help? Email support@deployhq.com or follow @deployhq on X.