A one-command installer for the apt-based ROS 2 path

I’d like ROS 2 to be installable with one command on Ubuntu:

curl -fsSL https://ros.org/install.sh | sh
source /opt/ros/lyrical/setup.bash

Today it’s a sequence — enable universe, look up the latest ros-apt-source
release, download the .deb, dpkg -i, apt update, apt install - from Installation

Those steps end up copied into Dockerfiles, CI configs and tutorials, and
whenever the apt setup changes, all of those copies break separately. If the
project hosted a single script, that’s one place to fix instead.

There are already community scripts doing this, for example
GitHub - Tiryoh/ros2_setup_scripts_ubuntu: 🔧 unofficial ROS 2 install/setup scripts for Ubuntu · GitHub , so this doesn’t need to
start from zero. I’m happy to write a first version and set up a CI matrix.

What I’d like to know is whether the project would want to host something like
this, and what it would take — a docs change, or something more formal.

4 Likes

curl ... | bash is fundamentally an anti-pattern.
I do not think that such an installation method should be offered.

and really, the entire process takes what, like 5 minutes?

and if something goes wrong during the script, how is recovery handled? if someone is doing it manually and they encounter an error, they know at which step the error occurred and then can search up how to fix it.
if an error happens in the script, it is now more obfuscated from the user.

how many times has this happened in the past? have you encountered such an issue?

this is precisely why it is a bad idea.

2 Likes

@solonovamax
Thanks for the pushback — these are the right questions to ask.

Two things on this.

First, I agree it’s an anti-pattern as a general rule. But look at what the current instructions already do: query api.github.com for a version string, download a .deb from GitHub Releases, and sudo dpkg -i it. That .deb is not verified by apt — it is the thing that installs the key. So the trust boundary today is “whatever HTTPS gives you from a project-controlled URL, run as root.” A script served from the same kind of URL doesn’t widen that. The only difference is whether the thing you fetch is a package or a script you can read before running.

Second, it matters what the script would actually do. Every ROS package would still come through apt, signed and verified. The script only automates the one step that is already outside apt today — fetching the .deb that configures the repository. Nothing moves out of the package manager.

The part of the anti-pattern argument I do agree with is the habit: teaching newcomers to pipe URLs into their shell as if that’s the normal way to install things. I’d want this presented not as “the” way to install ROS, but as the reference implementation of the documented steps, kept in sync with them.

For someone who has done it a few times on their own machine, sure, it’s not a big deal.

It’s a different story for beginners and for people maintaining Docker images or CI.

For beginners, the current procedure includes spells like $(. /etc/os-release && echo ${UBUNTU_CODENAME:-${VERSION_CODENAME}}). These are the people who copy a command from a migration guide, miss one sudo, and end up with a broken system.

For Docker and CI it’s worse. Because there is no guarantee the procedure stays the same, everyone writes their own script that automates the same steps, and that script gets copied into every new CI config from then on. When the procedure changes, I doubt finding and updating all of those takes five minutes.

That’s a fair concern, but it’s a matter of script quality, not a reason to have no script. A script that stops on the first error and says which step failed — something like could not fetch ros2-apt-source release: <url> — is easier to debug than a raw apt error halfway through a manual sequence.

Last year’s migration thread has a concrete example of the manual version. The URL in the docs was pinned to 1.0.0, the package moved to 1.1.0 the next day, and two people following the official instructions hit a 404 and had to ask what was wrong (here and here). Following the steps by hand didn’t tell them which step was broken.

You may have seen some of these already, but counting only changes to the apt setup procedure itself:

  • 2019: key rotation after a security incident
  • 2021-04: docs moved from apt-key add to signed-by= keyrings
  • 2021-05-29: key expired; 42 replies, official Docker images and ros-tooling/setup-ros broken over a holiday weekend
  • 2025-06-01: key expired again, ros-apt-source introduced; the PMC announcement itself opens with “we are again upon the brink”

Both incident threads are full of people fixing their own copies: CI pipelines, GitHub Actions, Ansible roles, and the broken-system case above. Yes, my own CI was among the things that went red on June 1st.

I may be repeating myself, but that single point of failure already exists. packages.ros.org, the signing key, and the ros-apt-source package are all managed by the Infrastructure PMC, and when any of them changes, every Dockerfile and CI pipeline in the community breaks at the same time. 2021 and 2025 showed exactly that. The only question is whether the fix then lands upstream once, or in every copy separately.

That said, I don’t think curl | sh is the ideal shape either. What I want is a single, maintained entry point that the docs, Dockerfiles and CI can all point at — one where it’s clear who owns the procedure. Some shapes that would do that:

  • A stable, versionless URL for the ros2-apt-source .deb. @peci1 has already asked for this. That alone removes the api.github.com dependency and the version-pinned 404s, and gets the manual path down to curl -LO <url> && sudo dpkg -i followed by apt install.
  • Getting ros2-apt-source into the Ubuntu archive itself, so the whole thing becomes sudo apt install ros2-apt-source. The cleanest answer, and the most work.
  • A script hosted under the ros2 or ros-infrastructure org, documented as “download, read, run” and never as a one-liner. Same maintenance benefit, without teaching the habit.

Where I agree with you: a script that isn’t kept in sync with the docs would be worse than nothing. That’s exactly why I’m asking in this thread whether the PMC would be willing to own something like this.

5 Likes

I’m not so sure. Takumi joined 9 years ago. He doesn’t strike me as someone who comes here to wall-post with AI. And his response seems to be a combination of AI-polished/authored points and human authored points – maybe just using AI to help with the English. Also, instead of being vulgar, you can also just say “ai;dr” – I certainly share your disdain for AI-generated posts.

2 Likes

I gave it a read and it is a good reply. I suggest you give it a try too.

I’m half-split on the curl | sh topic. Beginners love it. Pros don’t. It can help with the “ROS is difficult to install” sentiment I’m constantly hearing.

5 Likes

Thank you.

To be honest, I used an LLM to help with the English and to search through and summarize the past threads — my own English is nowhere near that polished, as this post probably shows. The position and what to argue were my own.

4 Likes

Actually this idea came up in ROS Japan Developer Meeting in person. I think that this is useful to the beginners and I sometimes need a fresh start to set up that build environment, this can be useful.

I can see some objections that are not really fundamental points, we can trap the process in the shell script and print what exactly went wrong for the user with documentation URL. What is the difference against the manual operation?

Besides, many famous tools are using this style like rust, k8s and so on.

After all, I am not sure why this is anti pattern…

1 Like

I think this issue should be discussed by separating the target environment from the way the installer is delivered.

A. Production servers, CI, and public container image builds

B. Personal machines used for learning and disposable test containers

For A, from the perspectives of auditability and reproducibility, it is not appropriate to implicitly track the latest versions without pinning them. The issue is not that it is a one-liner, but that the versions are not pinned.

For B, I support making curl | sh available as an option. There are risks, such as the difficulty of reviewing the script before execution and the possibility of a supply-chain attack if the official hosting infrastructure or CDN is compromised. However, some users may reasonably prefer convenience while accepting those risks. A single command is particularly valuable when repeatedly rebuilding ROS environments or helping beginners get started.

I am the author of the setup script mentioned in this thread. At one point, I was rebuilding my test environment multiple times a day, so I created it to avoid having to run the same sequence of commands each time.

If the script handles errors properly and reports the failed step along with a relevant documentation link, it can still provide useful diagnostics. This is separate from pre-execution reviewability; a script is not necessarily harder to troubleshoot.

This is not a proposal to recommend curl | sh to everyone. The proposal is to retain the manual, inspectable procedure while also providing an officially maintained one-command entry point for users who prioritize convenience.

2 Likes

Didn’t the pixi guys show off last year by running rviz on a showroom-computer on the airport?

Took them 3 commands or so :smiley:

1 Like