Code Monkey home page Code Monkey logo

installer's Introduction

installer

Quickly install pre-compiled binaries from Github releases.

Installer is an HTTP server which returns shell scripts. The returned script will detect platform OS and architecture, choose from a selection of URLs, download the appropriate file, un(zip|tar|gzip) the file, find the binary (largest file) and optionally move it into your PATH. Useful for installing your favourite pre-compiled programs on hosts using only curl.

GoDev CI

Usage

# install <user>/<repo> from github
curl https://i.jpillora.com/<user>/<repo>@<release>! | bash
# search web for github repo <query>
curl https://i.jpillora.com/<query>! | bash

Or you can use wget -qO- <url> | bash

Path API

  • user Github user (defaults to @jpillora, customisable if you host your own, searches the web to pick most relevant user when repo not found)
  • repo Github repository belonging to user (required)
  • release Github release name (defaults to the latest release)
  • ! When provided, downloads binary directly into /usr/local/bin/ (defaults to working directory)

Query Params

  • ?type= Force the return type to be one of: script or homebrew
    • type is normally detected via User-Agent header
    • type=homebrew is not working at the moment – see Homebrew
  • ?insecure=1 Force curl/wget to skip certificate checks
  • ?as= Force the binary to be named as this parameter value

Security

⚠️ Although I promise my instance of installer is simply a copy of this repo - you're right to be wary of piping shell scripts from unknown servers, so you can host your own server here or just leave off | bash and checkout the script yourself.

Examples

Private repos

You'll have to set GITHUB_TOKEN on both your server (instance of installer) and client (before you run curl https://i.jpillora.com/foobar | bash)

See #31 for how this could improved

Host your own

  • Install installer with installer

    curl -s https://i.jpillora.com/installer | bash
  • Install from source

    go get github.com/jpillora/installer
  • Install on Fly.io

    • Clone this repo
    • Setup the fly CLI tool
    • Create a new app
    • Replace app = "installer" in fly.toml with your app name
    • Run fly deploy

Force a particular user/repo

In some cases, people want an installer server for a single tool

export FORCE_USER=zyedidia
export FORCE_REPO=micro
./installer

Then calls to curl localhost:3000 will return the install script for zyedidia/micro

Homebrew

Currently, installing via Homebrew does not work. Homebrew was intended to be supported with:

#does not work
brew install https://i.jpillora.com/serve

However, homebrew formulas require an SHA1 hash of each binary and currently, the only way to get is to actually download the file. It might be acceptable to download all assets if the resulting .rb file was cached for a long time.

MIT License

Copyright © 2020 Jaime Pillora <[email protected]>

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

installer's People

Contributors

drmikecrowe avatar jpambrun avatar jpillora avatar laverya avatar milahu avatar philipsd6 avatar temoto avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

installer's Issues

Installer generates incorrect script for Linux and Darwin

Running, e.g.:

curl -fsSL https://i.jpillora.com/jesseduffield/[email protected] | bash

fails with Error: No asset for platform linux-amd64 on Linux and Error: No asset for platform darwin-amd64 on Mac.

The reason is lines ~45-47

     case `uname -s` in
     Darwin) OS="darwin";;
     Linux) OS="linux";;

and ~63-96:

    case "${OS}_${ARCH}" in
    "Linux_386") ...
    "Linux_amd64") ...
    "Linux_arm") ...
    "Darwin_386") ...
    "Darwin_amd64") ...

.

The cases must be lowercased as well.

feat: support installing from a specific commit hash

We can use Github Actions to build the program for every commit and store it as an artifact that could later be fetched by the installer. This would be useful for easy testing prior to committing to a release.

Improve architecture to: simplify codebase, serve private binaries, install-by-file-url

I think the architecture should be changed from returning 1 complex shell script into 2 simple shell scripts:

curl <installer ip address>/myuser/myrepo

should return a simple script which fetches all of the OS information it can, and then repeats the call (Protocol + Host + path) except the call has extra fields added:

curl <installer ip address>/myuser/myrepo?os=linux&arch=arm64&tools=unzip,tar,gz

now that it has the minimum info (os arch tools) it can now do the checks in Go, and return a simple script which is effectively 1. curl to /tmp, 2. optional unpack, 3. chmod +x, 4. optionally mv to PATH. all the complex shell logic will move into go. second simple shell script does a minimal download and install. errors are just a one-liner echo "my error..."

subsequent improvements:

  • uses trap to better cleanup and show errors
  • for private installations, you can set a GH_TOKEN on your server and securely serve private binaries. this second script now knows exactly which file you need, and can get the presigned download URL: https://objects.githubusercontent.com/github-production-release-asset-2e65be/725845012/814abb0e-fc45-4965-be3b-24a0d6df38be?X-Amz-Algorithm=AWS4-HMAC-SHA256.....
    • this would not be feasible in the previous architecture as it would require installer to get the presigned URLs for all files, and there could be hundreds
  • second script should also allow the user to provide the asset url directly url=https://github... to installer to skip the asset discovery step (api.github.com calls). this would essentially just do the final GET + unarchive + move into PATH steps.
  • second script could support optional caching, through a Put / Get interface. which could support caching to disk, to s3, to artifactory, etc. user fetches URL x, and installer checks if x is cached, if not installer quickly downloads and caches it, and returns an installer download link instead of a GitHub content link

caveat:

  • this may break a small portion of users who go via a dumb proxy. if user goes server-a.com -> installer.internal, and server-a changes the user's request setting Host: installer.internal then the second script would incorrectly have installer.internal when it should have server-a.com

Installer M1 Macbook support

Darwin_arm64 is missing from the arch detection case switch. /usr/local/bin has migrated to /bin on darwin_arm64 This breaks all installs that try to write to the non existent directory /usr/local/bin, instead of writing to the correct install dir /bin. I would be happy to create a PR with the changes needed if that direction is approved.

The GitHub CLI gets installed as cli instead of gh

The GitHub CLI repo is cli/cli so we run the curl command:

curl -s "https://i.jpillora.com/cli/cli!!" | bash -x

and see that it installs gh as cli:

+ echo 'mv with sudo...'
+ sudo mv ./gh_2.19.0_linux_amd64/bin/gh /usr/local/bin/cli
+ echo 'Installed at /usr/local/bin/cli'

Is there any way to ensure the binary is installed as gh? It seems to me that the script could just do this instead:

+ sudo mv ./gh_2.19.0_linux_amd64/bin/gh /usr/local/bin/

i.e. move into the target directory instead of to a target file, but I'm not sure if that would adversely affect different repo's releases. My current workaround is to follow up with a sudo mv /usr/local/bin/{cli,gh}.

Segmentation fault on RPi OS 64

Expected Behavior

Tried installing Installer on my Raspberry Pi 4 and got an error when trying to run it.

Current Behavior

Get an error when trying to run Installer

$ curl -s https://i.jpillora.com/installer | bash
Downloading jpillora/installer v0.2.7.....
######################################################################## 100.0%#=#=-#  #                ######################################################################## 100.0%
Downloaded to /home/pi/installer
$ ./installer 
qemu: uncaught target signal 11 (Segmentation fault) - core dumped
Segmentation fault

Possible Solution

Detect the correct architecture.

Manually downloading and running installer_0.2.7_linux_arm64.gz works.

Steps to Reproduce

  1. $ curl -s https://i.jpillora.com/installer | bash
  2. $ ./installer

Context (Environment)

Hardware: Raspberry Pi 4

$ cat /etc/os-release
PRETTY_NAME="Debian GNU/Linux 10 (buster)"
NAME="Debian GNU/Linux"
VERSION_ID="10"
VERSION="10 (buster)"
VERSION_CODENAME=buster
ID=debian
HOME_URL="https://www.debian.org/"
SUPPORT_URL="https://www.debian.org/support"
BUG_REPORT_URL="https://bugs.debian.org/"
$ uname -a
Linux pi-04 5.4.72-v8+ #1356 SMP PREEMPT Thu Oct 22 13:58:52 BST 2020 aarch64 GNU/Linux
$ md5sum installer
2d365aab917f3844cb021ba7b1634e90  installer

Support M1 Macs

M1 Macs are darwin/arm64. The install script should support this os/arch pair.

M1 Macs also have Rosetta 2 which means its safe to fallback to darwin/amd64

wrong parsed arch on casey/just

>> uname -a
Linux jpambrun-rancher 3.10.0-1160.83.1.el7.x86_64 #1 SMP Wed Jan 25 16:41:43 UTC 2023 x86_64 x86_64 x86_64 GNU/Linux

>> curl -s https://i.jpillora.com/casey/just! | bash
Installing casey/just 1.13.0 (linux/amd64).....
######################################################################## 100.0%
mv with sudo...
Installed at /usr/local/bin/just

>> file /usr/local/bin/just
/usr/local/bin/just: ELF 64-bit LSB executable, ARM aarch64, version 1 (SYSV), statically linked, BuildID[sha1]=5dd31aa9ff55b6b00d45dc70e07bac6d376f90f9, not stripped

Should have got x86_64, but got aarch64.

installer --version outputs to stderr.

When running installer --version, the output is directed to stderr instead of stdout. Also, a return character needs to be added to the end.

Referencing this article.

Expected behavior.

$ ./installer --version
0.2.9
$ ./installer --version 1> out.txt 2> error.txt && cat out.txt
0.2.9
$ ./installer --version 1> out.txt 2> error.txt && cat error.txt
null

Actual behavior.

$ ./installer --version
0.2.9$
$ ./installer --version 1> out.txt 2> error.txt && cat out.txt
null
$ ./installer --version 1> out.txt 2> error.txt && cat error.txt
0.2.9$

Environment

$ cat /etc/*-release
NAME="Ubuntu"
VERSION="20.10 (Groovy Gorilla)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 20.10"
VERSION_ID="20.10"
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
VERSION_CODENAME=groovy
UBUNTU_CODENAME=groovy

Ability only allow a specific repository

Great work! When self-hosting, users will likely want to only support one repository for security reasons (e.g. not allowing third-party or bad-party to install binaries through their domains). Also, I believe the documentation and support for self-hosting should be improved (e.g. parameters, docker image, helm, etc.).

Some versions are not parsing properly

There are some versions which are removed the hyphen char

$ curl -s 'https://i.jpillora.com/GoogleContainerTools/[email protected]!!'
echo 'release tag v1.0.0beta.24 not found'
$ curl -s https://api.github.com/repos/GoogleContainerTools/kpt/releases | grep '"tag_name": "v1.0.0-beta.24",'
    "tag_name": "v1.0.0-beta.24",

So apparently this conditional fails, maybe splitHalf method is modifying the value

Update

It works without sudo move option.

curl -s 'https://i.jpillora.com/GoogleContainerTools/[email protected]!' | bash

Switch from statik to go1.16 embed

I had a couple of issues hosting:

  • I was able to deploy my own version and update the .go files w/o an issue
  • When I tried to update the install script, I could not determine how to update scripts/install.sh and include.
  • I installed and was able run statik -dest=.. -f -p=scripts -src=../scripts -include=*.sh manually
  • Could not determine how to deploy to my heroku instance. Once I updated scripts/statik.go, I started getting 500 errors in heroku.

Installer gets confused by aarch64-linux

Hey @jpillora, I was trying to use installer with zoxide, but it seems to be downloading the aarch64 binary instead of amd64 on Linux.

Here's the case statement generated by curl 'https://i.jpillora.com/ajeetdsouza/zoxide!':

case "${OS}_${ARCH}" in
"linux_amd64")
	URL="https://github.com/ajeetdsouza/zoxide/releases/download/v0.7.0/zoxide-aarch64-unknown-linux-musl.tar.gz"
	FTYPE=".tar.gz"
	;;
"linux_arm")
	URL="https://github.com/ajeetdsouza/zoxide/releases/download/v0.7.0/zoxide-armv7-unknown-linux-musleabihf.tar.gz"
	FTYPE=".tar.gz"
	;;
"darwin_amd64")
	URL="https://github.com/ajeetdsouza/zoxide/releases/download/v0.7.0/zoxide-x86_64-apple-darwin.tar.gz"
	FTYPE=".tar.gz"
	;;
*) fail "No asset for platform ${OS}-${ARCH}";;
esac

installed 32bits instead of 64bits

Hello,
My first try with https://github.com/sharkdp/bat showed that installer detected the correct architecture for my test VM (linux/amd64), retrieved a artifact and put into /usr/local/bin as expected.
Bash errored with /usr/local/bin/bat: No such file or directory although the file was there.
A "file /usr/local/bin/bat" showed :
/usr/local/bin/bat: ELF 32-bit LSB pie executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=0c2142c993195cf49a9b711d45efbc3cf3e201e5, stripped

Installer worked for other projects but choked also on https://github.com/sharkdp/fd or https://github.com/bootandy/dust.
Any idea to resolve these issues ?
(I looked at the release assets of the projects and everyone is following... its own convention...)

Match prefix?

Would it be possible to add a query parameter like prefix=foo/ to match releases by prefix and then obtain the latest? I have a mono repo that uses tags like foo/0.1.0 and bar/0.2.0.

Filter release artifacts

I have a use-case with siderolabs/[email protected] (release). I would like to only grab the talosctl artifact from these releases. Right now it only pulls talos which is not what I want.

Maybe there can be a filter arg like ?filter=talosctl&as=tctl that wraps a glob around the filter ?

Licensing!

Would it be possible to have a license added to the repository? It makes the lawyers happy.

Add support for passing headers

Add support for passing headers to the download command in the script.

Our use case is GitHub CI pipelines downloading the binary from GitHub. If we do it more than 60 times/minute, we get rate limited.

This is the header we need for ours to work in curl:

--header 'authorization: Bearer ${{ secrets.GITHUB_TOKEN }}'

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.