boot-clj / boot

Build tooling for Clojure.
https://boot-clj.github.io/
Eclipse Public License 1.0
1.75k stars 179 forks source link

Disabling self-update for vendor installs #500

Open kentfredric opened 7 years ago

kentfredric commented 7 years ago

Currently packaging boot to be installed via vendor tooling, which gives sysadmin people better peace of mind than a blind sudo bash curl ... invocation.

Presently doing this via simply provisioning a custom version of boot.sh without all the magic, and deploying the stable boot.jar into /usr/ and having boot.sh load that. ( It still loads all the dependencies and stuff from maven on first run, but this of course happens as a non-priveleged instead of root ).

However, in such situation its desirable to disable self-update mechanics.

Obviously this can be bodged in via re-writing args passing from scratch in the bash wrapper, and then bailing when somebody tries to upgrade, but I figured it might be better to suggest some kind of first-class support for this.

I suspect a JVM Option like -Dboot.vendor_install=1 would be sufficient, or maybe a string like -Dboot.vendor=gentoo which could trip the right paths in boot.

micha commented 7 years ago

@kentfredric You can install boot.sh into eg. /usr/local/bin, that's what the sudo bash curl... business is doing. It just fetches a copy of boot.sh, makes it executable, and moves it there. That's the only part that needs to be done as root. When a normal user uses boot, they will have all the jar files and so on downloaded as their user into their own home directory. (By default boot will refuse to run as root, by the way.)

I don't see how disabling self-update would make anything more secure, can you please explain a little more?

Boot contains the update logic to make it feasible to pin a project to a specific version of boot in the boot.properties file or the BOOT_VERSION environment variable, it knows how to download the jars etc for any specific version of boot. This is useful because it simplifies installation — you can use the latest boot.sh with any released version of boot, all the way back to version 2.0.0 and for all future versions of boot, too. So if your project builds with boot today, all you have to do is add a boot.properties file to the project with the current version of boot and clojure and you will definitely be able to build it 10 years from now (unless the JVM is no longer compatible with clojure).

kentfredric commented 7 years ago

When a normal user uses boot, they will have all the jar files and so on downloaded as their user into their own home directory.

It should be said that this is something that is seen as undesirable from a vendor/sysadmin standpoint and that we're trying to limit how much of this happens.

Obviously maven is a complex beast and its not feasible to eliminate this entirely at present.

But in that vein I didn't use your upstream version of boot.sh ( which I incidentally had trouble working out where you actually stored that in github, because it was invisible in every source tree and was not listed on any release page ), and instead booted into a copy of boot.jar, because it makes for better user clarity to see:

/usr/bin/some/shellscript
/usr/share/path/to/jarfile

where $shellscript calls $jarfile

The alternative with the self-contained binary shell script hybrid was just not something I felt comfortable releasing into our systems.

But as such, the above I believe means we've made boot itself unupgradeable, due to hard-wiring the jar itself ( I don't know if the embedded jar in the .sh and the boot.jar on the releases page are the same or not, but I assumed they were ), and was just seeking for a way to make that clearer to the user that "self upgrade does not work because you're using a vendor version, use your vendor tools"

However, I now realise this may be undesirable for developers who need specific versions of boot in their runtime, so I may have to think of a different strategy.

waffling


To help understand my motives, it should also be said that in the ultra-long-term we desire to be able to build as much from source as possible, and we also want a way to subvert the "download things from maven automatically", because Gentoo is a source based distribution, and people prefer to build things from their sources where possible a lot of the time.

This is clearly not going to happen in the next month, or the next year, but one thing I'd hope to see eventually is being able to invoke boot inside boot based projects in a sterile, network-free environment and use boot to compile those packages from source trees to jar binaries for the user to use. ( I've kinda got a way to bodge around part of the problem by working out how to construct a .m2 layout without maven, but its messy )

Because the end result is of course we want to be able to ship java/clojure based applications, where the users don't have to know how the Java ecosystem works to "just use" these applications, and emerge AppName should "work", and assuming they fetched the requisite dependencies via emerge, then booting the application as ~user should happen without any subsequent steps involving an internet connection. ( That is, we're trying to discourage people downloading an executing arbitrary applications from the internet and running them, this is what linux is good at after all )

But yeah, all very very long term goals, so I'm not panicking if we have to make short term compromises :)

telent commented 7 years ago

I would very much welcome something like this in order to be able to use boot for building packages in NixOS. Nix package builds are run by an unprivileged user with no network access and no write permission in their home directory: initially it looked like boot's with-cp task was going to make this awesomely simpler than having to download half of the maven repo and a third of the clojars repo just so that leiningen could resolve all the jars that my project needs, but I'm having immense difficulty even persuading boot to run

(The current packaging of boot in NixOS is, as far as I can determine, not adequate for this use case)