How To Install Rust on Ubuntu 26.04 LTS

Install Rust on Ubuntu 26.04

A fresh Ubuntu 26.04 LTS server is easy to set up, and then someone asks for a Rust toolchain. It looks like a two-minute job. Then cargo build stops with “linker cc not found”, or a crate wants OpenSSL headers that aren’t there. The CI runner works, but the production box compiles a different Rust version from the one on your laptop. Each of these problems is small, but together they can eat an afternoon.

Ubuntu 26.04 LTS “Resolute Raccoon” was released on April 23, 2026. It leans on Rust more than any Ubuntu release before it. The default sudo is now sudo-rs, and a large share of the core utilities come from the Rust-based rust-coreutils project. Installing a Rust toolchain on this release is a very normal thing to do.

There are two sensible ways to do it. You can use the compiler packaged by Ubuntu through APT, or you can use rustup, the toolchain manager maintained by the Rust project. They suit different jobs, and mixing them carelessly causes confusing behavior. This guide covers both methods and explains when each fits. It also covers the build dependencies people forget, the PATH and permission problems that catch people out, and the settings that matter on a real server.

The commands below were written for Ubuntu 26.04. Where Debian or AlmaLinux differ, a note says so.

Which Install Method Should You Pick?

The choice depends on what the machine does.

Ubuntu 26.04 ships Rust 1.93.x in its default repositories. LinuxCapable’s install guide confirms that the default APT packages resolve to Rust and Cargo 1.93.x on 26.04. Ubuntu’s own developer documentation lists the same 1.93 version for 26.04. That version is stable and patched by Canonical, and it stays fixed for the life of the release.

The official rustup installer tracks the newest stable release. The Rust project’s own documentation describes it as the recommended way to get Rust, and it installs to ~/.cargo/bin.

Scenario Best method Why
Developer workstation rustup Newest stable, easy beta and nightly switching
CI runner or build server rustup, pinned version Reproducible builds across machines
Building one tool from source APT Quick, no extra files in home directory
Packaging for .deb distribution APT toolchain Matches the distro’s own build environment
Locked-down production host APT, or no compiler at all Smaller attack surface, vendor-patched
Cross-compiling (musl, ARM, WASM) rustup Targets are one command away

My own rule is simple. Production hosts should rarely have a compiler on them at all. Build in CI, ship the binary. A compiler on a public-facing server is a convenience for an attacker and a drift risk for you. Developer boxes and build runners are different, and rustup is the better choice for them.

Prerequisites and System Preparation

Start by checking what you have. The commands are short, and they save time later.

lsb_release -a
uname -m
df -h /home
free -h

You want Ubuntu 26.04 on x86_64 or aarch64. Both are well supported. On disk, a rustup install with the default profile uses somewhere around 1 to 1.5 GB under ~/.rustup. Plan for several more gigabytes if you build large projects, because the target/ directory grows quickly. RAM matters more than people expect. Linking big binaries can spike memory use, so a 1 GB VPS will struggle with heavy crates.

Update the system first

sudo apt update
sudo apt full-upgrade -y

On a server that has been running a while, reboot afterward if the kernel changed. Then confirm sudo works as expected. Ubuntu 26.04 uses sudo-rs by default, and traditional sudo remains available as the sudo.ws package. For installing Rust, the difference rarely matters. It can matter if you have old scripts that depend on unusual sudoers syntax or on sudo -E behavior, so test them.

Install the build dependencies

This is the step most tutorials skip, and it causes most “Rust is broken” complaints. Rust needs a C linker, and many popular crates compile C code or link against system libraries. The Rust book says that Linux users should generally install GCC or Clang, and on Ubuntu that means the build-essential package.

sudo apt install -y build-essential pkg-config libssl-dev curl ca-certificates git

Each package has a job:

  • build-essential provides gcc, g++, make and the linker that rustc calls.
  • pkg-config lets build scripts find system libraries.
  • libssl-dev satisfies the openssl-sys crate, which a surprising number of projects pull in.
  • curl and ca-certificates let you download the installer over verified TLS.
  • git is needed for crates fetched from Git repositories.

On Debian the same command works. On AlmaLinux or Rocky, use this instead:

sudo dnf groupinstall -y "Development Tools"
sudo dnf install -y openssl-devel pkgconf-pkg-config curl git

Method 1: Install Rust with rustup (Recommended)

This is the route for most people. It gives you rustc, cargo, rustup and the standard tools in your home directory, with no root access needed beyond the build dependencies.

Step 1: Download and run the installer

curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

The flags are worth understanding. --proto '=https' refuses any redirect to plain HTTP. --tlsv1.2 sets a minimum TLS version. -sSf keeps curl quiet but still shows errors, and it fails on HTTP errors instead of piping an error page into your shell. This is the command the Rust project publishes.

Piping a script straight into sh makes some admins uneasy, and that instinct is healthy. A more careful approach is to download first, read it, then run it:

curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs -o rustup-init.sh
less rustup-init.sh
sh rustup-init.sh

The Arch Wiki recommends the same download, inspect and run pattern. On a regulated server, add a checksum comparison against the standalone rustup-init binaries published by the project.

Step 2: Choose the installation option

The installer shows a menu. You will see options for the default installation, customization, and cancel. Option 1 is right for most people. Choose option 2 when you need something specific:

  • A minimal profile, which skips documentation and saves disk space on CI runners.
  • A specific default toolchain, such as a pinned version.
  • Skipping PATH modification, if you manage shell profiles through configuration management.

A non-interactive install is better for automation:

curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --profile minimal --default-toolchain stable

The -y flag accepts defaults, and --profile minimal installs just rustc, rust-std and cargo. Add clippy and rustfmt later if you want them.

Step 3: Load Cargo into your current shell

The installer appends a line to your shell profile. That change only applies to new sessions, so load it manually this time:

. "$HOME/.cargo/env"

The Arch Wiki makes the same point about sourcing the environment file until you log out and back in. The rustup book also says to open a new shell before checking the version.

Step 4: Verify the installation

rustc --version
cargo --version
rustup --version
rustup show

You should see a stable version number. Rust releases a new stable roughly every six weeks, so what you see depends on the date. Today is October 2, 2026, and the number will be well ahead of the 1.93 that Ubuntu packages.

Step 5: Compile something real

A hello world test proves the whole chain works, linker included.

cargo new hello_rust
cd hello_rust
cargo run

Expected output is Hello, world! after a short compile. If this works, the compiler, Cargo, the linker and the crate registry connection are all fine. Now try a dependency that touches native code. Add reqwest to Cargo.toml and build. If OpenSSL headers are missing, you will find out now instead of during a deploy.

Method 2: Install Rust from Ubuntu’s APT Repository

This approach is simple and conservative. You get a distribution-tested compiler, updated through normal apt upgrade cycles.

sudo apt update
sudo apt install -y rustc cargo
rustc --version
cargo --version

On Ubuntu 26.04 this installs the 1.93 series. A computingforgeeks walkthrough recorded 1.93.1 from the default repositories for this release.

Versioned packages

Ubuntu also offers versioned Rust packages, so you can install a specific toolchain beside the default one. Ubuntu’s availability table lists several available 26.04 versions and a naming scheme like rustc-1.97. Check what exists before assuming a name:

apt-cache search --names-only '^rustc-[0-9]'
apt policy rustc

Versioned packages install binaries such as rustc-1.93 and cargo-1.93. That is useful when a Debian packaging workflow needs a known compiler version.

The rustup package and the snap

Ubuntu 26.04 also packages rustup itself, though the repository version trails the upstream release. Ubuntu additionally offers a rustup snap with stable, beta and nightly channels. They work, but on servers the official script is the most predictable choice, because its behavior is the same on every distribution you manage.

Don’t Mix APT Rust and rustup Rust

This mistake shows up on real machines all the time. Someone installs rustc from APT months ago, then runs the rustup installer. Now /usr/bin/rustc and ~/.cargo/bin/rustc both exist. Which one runs depends on PATH order, and different users, cron jobs and systemd units see different results.

Diagnose it with:

type -a rustc
which -a cargo
echo "$PATH"

If you see two entries, pick one. For a rustup setup, remove the APT packages:

sudo apt remove --purge rustc cargo
sudo apt autoremove -y
hash -r

The hash -r command clears bash’s cached command locations. Without it, your shell may keep looking for the deleted binary. This matters for scripts too. A deploy script that runs under a non-login shell will not read ~/.bashrc, so it may not find ~/.cargo/bin at all. Set the PATH explicitly in such scripts:

export PATH="$HOME/.cargo/bin:$PATH"

Managing Toolchains, Components and Targets

Installing Rust is the easy part. Running it well over months is where rustup earns its place.

Update and switch channels

rustup update
rustup self update
rustup toolchain list
rustup default stable
rustup toolchain install nightly
rustup toolchain install 1.93.0

rustup update refreshes installed toolchains. The Rust documentation points to it for getting the latest version. rustup self update upgrades rustup itself, which is a separate step.

Pin a version per project

Teams with more than one developer should commit a rust-toolchain.toml file at the project root:

[toolchain]
channel = "1.93.0"
components = ["rustfmt", "clippy"]
targets = ["x86_64-unknown-linux-musl"]
profile = "minimal"

When someone runs cargo build in that directory, rustup fetches the right toolchain automatically. This removes the classic “works on my machine” problem. It also keeps CI and production builds identical, which is the whole point of reproducibility.

Add components

rustup component add rustfmt clippy rust-analyzer
rustup component list --installed

rustfmt formats code, clippy is the linter, and rust-analyzer powers editor features. On a headless build runner, clippy and rustfmt are usually all you need.

Cross-compilation targets

rustup target add x86_64-unknown-linux-musl
rustup target add aarch64-unknown-linux-gnu
rustup target add wasm32-unknown-unknown

The musl target produces statically linked binaries that run on nearly any Linux distribution, which makes deployment much simpler. You may also need a musl cross compiler:

sudo apt install -y musl-tools
cargo build --release --target x86_64-unknown-linux-musl

For ARM targets, install the cross linker (gcc-aarch64-linux-gnu) and point Cargo at it in ~/.cargo/config.toml:

[target.aarch64-unknown-linux-gnu]
linker = "aarch64-linux-gnu-gcc"

Performance Tuning for Rust Builds

Rust compiles slowly compared with many languages, and the cost grows with project size. A few adjustments make a large difference.

CPU

Cargo uses all cores by default. On shared hosts, cap it with -j or the CARGO_BUILD_JOBS variable. For release builds, link-time optimization produces smaller, faster binaries but takes longer. Tune it in Cargo.toml:

[profile.release]
opt-level = 3
lto = "thin"
codegen-units = 16
strip = true

Lowering codegen-units to 1 gives the best runtime performance and the slowest build. For everyday work, thin LTO with the default units is a reasonable middle ground.

Linker

The default linker can be the slowest phase on big projects. Faster linkers such as lld or mold cut link times noticeably. Install one and tell Cargo to use it:

sudo apt install -y lld clang
[target.x86_64-unknown-linux-gnu]
linker = "clang"
rustflags = ["-C", "link-arg=-fuse-ld=lld"]

Put that in ~/.cargo/config.toml or the project’s .cargo/config.toml. Test that it works before rolling it out to a team, since a few crates behave badly with alternative linkers.

RAM and swap

A linker plus several rustc processes can use several gigabytes at once. On small VPS instances, the out-of-memory killer ends builds with a cryptic “signal: 9, SIGKILL” message. Reduce parallelism with -j 1, or add swap:

sudo fallocate -l 4G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile

Swap is a safety net, not a performance feature. Builds that depend on it will be slow, but they will finish.

Disk I/O

The target/ directory generates a huge number of small files. Put it on fast storage, ideally NVMe. On a machine with a slow disk, you can point Cargo at a tmpfs directory for throwaway builds:

export CARGO_TARGET_DIR=/dev/shm/target

Remember that tmpfs lives in RAM and disappears on reboot. For long-term hygiene, install cargo-sweep or periodically run cargo clean on old projects. A forgotten target/ folder can fill a disk without warning.

Compile caching

sccache caches compiler output and helps most on CI systems:

cargo install sccache --locked
export RUSTC_WRAPPER=sccache
sccache --show-stats

Installing it with cargo install compiles it from source, which takes a few minutes the first time.

Network

Cargo downloads crates from the registry over HTTPS. Behind a corporate proxy, set HTTPS_PROXY. On flaky connections, raise retries in ~/.cargo/config.toml:

[net]
retry = 5

[registries.crates-io]
protocol = "sparse"

Sparse is already the default in recent Cargo, so the second entry is only a safeguard for older setups. For offline or air-gapped hosts, use cargo vendor to bundle dependencies into the repository.

Security Considerations

A toolchain executes arbitrary code at build time. Every crate can run a build.rs script with your privileges. That is the main risk, so treat it as one.

Do not build as root

Never run cargo build or rustup as root unless you have a specific reason. Create a dedicated user for builds:

sudo adduser --disabled-password --gecos "" builder

Running as an unprivileged user limits the damage from a malicious or buggy build script.

Audit your dependencies

cargo install cargo-audit --locked
cargo audit
cargo install cargo-deny --locked
cargo deny check

cargo-audit checks your lock file against the RustSec advisory database. cargo-deny adds license and source policies. Run both in CI. Commit Cargo.lock for applications so builds use the same versions every time, and use --locked in build commands to fail when the lock file is out of date.

Firewall and network exposure

A build box rarely needs inbound access beyond SSH. Keep UFW tight:

sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow OpenSSH
sudo ufw enable
sudo ufw status verbose

Outbound access is needed for static.rust-lang.org and the crates registry. If you restrict egress, allow those hosts. Keep the OS patched with unattended-upgrades, and keep Rust updated as well, since compiler and standard library fixes ship regularly.

File permissions

chmod 700 ~/.cargo
chmod 600 ~/.cargo/credentials.toml 2>/dev/null

The credentials.toml file holds registry API tokens if you publish crates. Treat it like an SSH key. Never commit it, and never bake it into container images. Use short-lived CI secrets instead.

Troubleshooting Common Errors

These are the problems that show up most often on Ubuntu servers, with the fix for each.

error: linker `cc` not found

The C toolchain is missing. Install it:

sudo apt install -y build-essential

failed to run custom build command for `openssl-sys`

OpenSSL development headers or pkg-config are absent:

sudo apt install -y libssl-dev pkg-config

If you would rather avoid system OpenSSL, many crates offer a rustls feature. Switching to it removes the dependency completely and simplifies static builds.

cargo: command not found

PATH does not include ~/.cargo/bin. Run . "$HOME/.cargo/env" or open a new shell. For cron and systemd, set PATH explicitly. In a systemd unit:

[Service]
Environment="PATH=/home/builder/.cargo/bin:/usr/local/bin:/usr/bin:/bin"

curl: (60) SSL certificate problem

The CA bundle is missing or the clock is wrong. Fix both:

sudo apt install -y ca-certificates
sudo update-ca-certificates
timedatectl status

On a minimal container, missing certificates are the usual cause. Do not “fix” it with curl -k, because that disables verification.

error: could not compile … signal: 9, SIGKILL

The kernel’s out-of-memory killer ended the process. Confirm it:

dmesg | grep -i -E 'killed process|out of memory'

Then reduce -j, add swap, or use a bigger instance.

Two different rustc versions

See the earlier section on mixing APT and rustup. Run type -a rustc, remove the one you do not want, and clear the shell hash.

rustup: unable to write to the home directory, or permission denied on ~/.cargo

This often happens after someone ran sudo cargo or sudo rustup once, leaving root-owned files in a user’s directory:

sudo chown -R "$USER":"$USER" ~/.cargo ~/.rustup

Slow or stalled crate downloads

Try a different network path, check DNS, and raise net.retry. If your provider throttles connections, a local mirror or vendored dependencies will make builds more reliable.

sudo behaves differently than expected

Since Ubuntu 26.04 uses sudo-rs by default, some old environment-handling habits may not carry over exactly. If a legacy script breaks, check the Ubuntu Server documentation on sudo-rs, which notes that sudo.ws remains available as an alternative provider. Cases like this are rare for Rust installs, but they are worth knowing about when you run automation on a new LTS.

r00t is an experienced Linux enthusiast and technical writer with a passion for open-source software. With years of hands-on experience in various Linux distributions, r00t has developed a deep understanding of the Linux ecosystem and its powerful tools. He holds certifications in SCE and has contributed to several open-source projects. r00t is dedicated to sharing her knowledge and expertise through well-researched and informative articles, helping others navigate the world of Linux with confidence.

Related Posts