inaugurate is a generic bootstrap script that optionally supports the immediate execution of the application that is being bootstrapped. You can use it from it's 'official' url with either a hosted, or your own, local application description (as explained below):
curl https://inaugurate.sh | bash -s -- <application> <args>
Or you can download it, optionally customize it (change defaults, add your own application to the script as a default), and host it yourself somewhere.
inaugurate also comes with an 'official app store', although that is, for now at least, mostly to demonstrate it's 'app-store' feature. That app-store, of course, can also be customized and self-hosted.
At the moment, inaugurate is mainly useful if you want to (cross-*NIX-platform) bootstrap Python packages (via pip) that have (non-Python) system dependencies, without the need to have root/sudo permissions (which is accomplished by using conda). Admittedly, a rather limited scope for a self-proclaimed 'generic' thing :-) . I reckon it wouldn't be too hard to extend it to support other types of installs/languages though. Ping me if you have suggestions/use-cases.
For more details, check the relevant sections below:
So here's an example on how you 'inaugurate' frecklecute, which comes bundled with freckles and lets you run 'declarative' scripts (basically wrapped ansible playbooks). This is a good example of when it's useful to be able to install and run at the same time, since in some cases you might not ever need to run frecklecute again (for example, if you use it to build a Docker container within a Dockerfile
):
❯ curl https://inaugurate.sh | bash -s -- frecklecute --help
'frecklecute' not found in path, inaugurating...
* checking inaugurate app store for: freckles
...
... < more inaugurate progress output >
...
Usage: frecklecute [OPTIONS] FRECKLECUTABLE [ARGS]...
...
... < more usage information >
...
Here inaugurate executes the application once it's installed (not doing anything useful, only showing usage information). This behavior (among others) can be turned off, if need be, with the help of an environment variable:
❯ curl https://inaugurate.sh | NO_EXEC=true bash -s -- frecklecute
Of course, we can also use wget
if curl
is not available on our system:
❯ wget -O - https://inaugurate.sh | SELF_DESTRUCT=true bash -s -- frecklecute --help
In this last example we also use the SELF_DESTRUCT
environment variable to instruct inaugurate to delete itself and the application it just installed after that application ran. This might be useful, for example, if you build a container, and want the end-product to be as slim as possible.
By default, inaugurate uses conda to bootstrap the desired application into the users home directory, without needing sudo/root permissions. The user can opt to use sudo though, in which case native systems packages will be installed, and Python packages are installed inside a (individually created) virtualenv. This would look like:
❯ curl https://inaugurate.sh | sudo NO_EXEC=true bash -s -- frecklecute
inaugurate...
- lets you install (mainly Python, but potentially also other) applications and run them in the same go
- can (optionally) delete itself and the application it bootstrapped after the command was executed
- supports 'non-root'-permission installs (via conda)
- has no dependencies except for either
curl
orwget
(andbzip2
when using conda) - creates separate environments for each package it installs (either via Python virtualenv or conda)
- has it's own 'official' app_store, or lets you use your own, local one
- can be self-hosted
- is easily customizable, so can be used for your own application for which you want to provide a bootstrap script
- supports Debian-, RedHat- based Linux distros, as well as Mac OS X
- can -- optionally -- also install Mac OS X CommandLineTools for Xcode
inaugurate was written for freckles to enable 'one-line' bootstrap of whole working environments. It turned out to be fairly easy to make it more generic, so it got its own project here. inaugurate (obviously) is not useful for simple cases where you just need to install an application. In 95% of all cases you can do that by just using your system package manager (apt install the-package-you-want
).
Some applications require a bit more effort to install (e.g. ansible using pip, although that is getting easier as well). While still being fairly trivial, you need to install some system dependencies, then, if you want to do it properly, create a virtualenv and pip install
the package into it. Those are the cases where inaugurate is of some use as it can do those things automatically.
The main reason for writing inaugurate was the aforementioned 'one-line' bootstrap though. Admittedly, I have no idea how often this can be of use for the general public, but I figure its a basic enough pattern that I haven't seen implemented elsewhere (yet -- also I might not have looked well enough), at least not in a generic fashion. So I thought I might as well polish it a bit and put it up for other people to have a look. I imagine there are a few situations where it will make sense. You'll know it when you see it, sorta thing.
Here's how the commandline interface looks on a high level:
<curl_or_wget_command> https://inaugurate.sh | ENV_KEY_1=<env_value_1> ENV_KEY_2=<env_value> bash -s -- <application> <app_args>
| | | | | | | |
- download command - ------- url ------- ---------- control behaviour -------------- ---- app execution ---
Or, using sudo
:
<curl_or_wget_command> https://inaugurate.sh | sudo ENV_KEY_1=<env_value_1> ENV_KEY_2=<env_value> bash -s -- <application> <app_args>
| | | | | | | |
- download command - ------- url ------- ---------- control behaviour -------------- ---- app execution ---
- download command
- either
curl
(or usecurl -s
if you don't want to see its progress), orwget -O -
- url
- always
https://inaugurate.sh
(you can also usehttps://freckles.io
if you want, though) - control behaviour
- see the list below for available options
- app execution
- this is the same you'd use if you would execute the application if it was already installed and available in your
PATH
, for example:ansible-playbook --ask-become-pass play.yml
inaugurate uses text files that describe the requirements that are needed to install an application. This is an example for such a description, for the application ansible:
ENV_NAME=ansible
EXECUTABLES_TO_LINK=ansible ansible-playbook ansible-galaxy ansible-vault ansible-console ansible-doc ansible-pull
EXTRA_EXECUTABLES=
# conda
CONDA_PYTHON_VERSION=2.7
CONDA_DEPENDENCIES=pip cryptography pycrypto git
# deb
DEB_DEPENDENCIES=curl build-essential git python-dev python-virtualenv libssl-dev libffi-dev
# rpm
RPM_DEPENDENCIES=epel-release wget git python-virtualenv openssl-devel gcc libffi-devel python-devel
# pip requirements
PIP_DEPENDENCIES=ansible
By default, inaugurate will check whether the first argument is a path to a locally existing file. If it is, this file will be read. If not, a file named after the provided app name (the first argument to the script) in $HOME/.inaugurate/local-store
. If there is, this will be read and the application described therein will be 'inaugurated'. If no such file exists, inaugurate will check whether such a file exists on the official inaugurate app_store.
Here's what the different vars mean:
- ENV_NAME
- the name of the conda or virtualenv that will be created
- EXECUTABLES_TO_LINK
- a list of executables that should be linked ot
$HOME/.local/bin
- EXTRA_EXECUTABLES
- an optional list of secondary executables. this is mainly used within freckles. executables in this list are linked into
$HOME/.local/share/inaugurate/bin
- CONDA_PYTHON_VERSION
- if using conda, this is the python version that is used in the new environment
- CONDA_DEPENDENCIES
- if using conda, those are the packages that will be installed into the new environment
- DEB_DEPENDENCIES
- if using sudo/root-permissions, and running on a Debian-based platform, those are the packages that should be installed using apt
- RPM_DEPENDENCIES
- if using sudo/root-permissions, and running on a RedHat-based platform those are the packages that should be installed using yum
- PIP_DEPENDENCIES
- the python packages to install in the conda or virtualenv environment
As already mentioned, you can either use curl
or wget
to download inaugurate.sh. Actually, any other tool you have at hand that can download files from the internet, and pipe out their content. I focus on curl
and wget
since the likelyhood one of them being installed is highest.
As mentioned above, this is how to invoke inaugurate using curl
:
curl https://inaugurate.sh | bash -s -- <app_name> <app_args>>
And using wget
:
wget -O - https://inaugurate.sh | bash -s -- <app_name> <app_args>
For the following examples I'll always use curl
, but of course you can use wget
interchangeably.
In case the command you are trying to inaugurate requires interactive input, you can use either of those formats:
bash <(wget -O- https://inaugurate.sh) <app_name> <app_args>
or
bash <(curl https://inaugurate.sh) <app_name> <app_args>
I haven't figured out yet how to do that with sudo though.
One of the main features of inaugurate is providing the option to install, whatever you want to install, without having to use root
or sudo
permissions. This only works for applications that are available via conda, or python packages.
The way to tell inaugurate whether to use conda or not is by either calling it via sudo (or as root
user) or as a 'normal' user. In the former case inaugurate will install system packages, in the latter it will install conda (if not already available) and contain all other dependencies within a conda environment.
To call inaugurate using sudo
, potentially/optionally using a environment variable to control its behaviour, you do something like:
curl https://inaugurate.sh | sudo NO_EXEC=true bash -s -- frecklecute --help
Here's a list of environment variables that can be used to change inaugurate's default behaviour, by default all variables are set to false or are empty strings:
- NO_ADD_PATH
- if set to true, inaugurate won't add
$HOME/.local/bin
to the path in the$HOME/.profile
file - NO_EXEC
- if set to true, inaugurate won't execute the inaugurated application after install
- FORCE_CONDA
- if set to true and run as user 'root', inaugurate will use 'conda' (instead of system packages). This doesn't have any effect if used in combination with 'sudo'
- FORCE_SUDO
- if set to true and not run as user 'root' or using 'sudo', inaugurate will not run
- FORCE_NON_SUDO
- if set to true and run using 'sudo', inaugurate will not run
- SELF_DESTRUCT
- if set to true, inaugurate will delete everything it installed in this run (under
$HOME/.local/share/inaugurate
) - INSTALL_BASE_DIR
- if set, inaugurate will install under the specified directory. if not set, default install dir is
$HOME/.local/share/inaugurate
- PIP_INDEX_URL
- if set, a file
$HOME/.pip/pip.conf
will be created, and the provided string will be set as asindex-url
(only ifpip.conf
does not exist already) - CONDA_CHANNEL
- if set, a file
$HOME/.condarc
will be created, and the provided string will be set as the (sole) conda channel (only if.condarc
does not exist yet) - CHINA
- if set to true,
PIP_INDEX_URL
andCONDA_CHANNEL
will be set to urls that are faster when used within China as they are not outside the GFW, also, this will try to set debian mirrors to ones within China (if host machine is Debian, and inaugurate is run with sudo permissions) -- this is really only a convenience setting I used when staying in Beijing, but I imagine it might help users in China -- if there ever will be any - INSTALL_COMMAND_LINE_TOOLS
- if set to true and run with elevated permissions on Mac OS X, inaugurate will make sure that the Mac OS X CommandLineTools are installed. this was required before inaugurate used the get-pip.py script to install pip on Mac
inaugurate is a shell script that, in most cases, will be downloaded via curl
or wget
(obviously you can just download it once and invoke it directly). It's behaviour can be controlled by environment variables (see examples above).
inaugurate touches two things when it is run. It adds a line to $HOME/.profile
, and it creates a folder $HOME/.local/share/inaugurate
where it puts all the application data it installs. In addition, if invoked using root permissions, it will also potentially install dependencies via system packages.
By default, inaugurate adds those lines to your $HOME/.profile
(which will be created if it doesn't exist):
# add inaugurate environment LOCAL_BIN_PATH="$HOME/.local/bin" if [ -d "$LOCAL_BIN_PATH" ]; then PATH="$PATH:$LOCAL_BIN_PATH" fi
Obviously, this won't be in effect after your first inaugurate run, as the .profile
file wasn't read since then. You can 'force' picking up the new PATH
by either logging out and logging in again, or sourcing .profile
:
source $HOME/.profile
Adding the inaugurate path to .profile
can be disabled by specifying the NO_ADD_PATH
environment variable when running inaugurate:
curl https://inaugurate.sh | NO_ADD_PATH=true bash -s -- cookiecutter gh:audreyr/cookiecutter-pypackage
You'll have to figure out a way to manually add your inaugurated applications to your $PATH
, or you always specify the full path (e.g. $HOME/.local/bin/cookiecutter
).
Everything is installed in the users home directory, under $HOME/.local/share/inaugurate
. Each application you 'inaugurate' gets its own environemnt (a python virtualenv in case of a sudo install, or a conda environment otherwise). The executables that are specified in the inaugurate app description (for example: https://github.com/inaugurate/store/blob/master/ansible) will be linked into the folder $HOME/.local/bin
.
Because everything is contained under $HOME/.local/share/inaugurate
, deleting this folder will delete all traces of inaugurate and 'inaugurated' apps (except for the added PATH
in .profile
) and free up all space (except for potentially installed system dependency packages).
As mentioned, if invoked using sudo
(or as user root), inaugurate will try to install dependencies using system packages (and python packages using virtualenv), otherwise conda is used to perform an entirely non-root install. This is the reason why both cases differ slightly in the folders that are created and used:
.local/
├── bin
│ ├── <linked_executable_1>
│ ├── <linked_executable_2>
│ ├── <linked_executable_3>
│ ├── <linked_executable_4>
│ ...
│ ...
│
├── share
└── inaugurate
├── bin
├── logs
├── tmp
└── virtualenvs
├── <one app>
│ └──bin
│ ├── <link_target_1>
│ ├── <link_target_2>
│ ...
│ ...
├── <other app>
│ └──bin
│ ├── <link_target_3>
│ ├── <link_target_4>
│ ...
│ ...
In this case, new application environments are created under .local/share/inaugurate/virtualenvs
. So, for example, if you want to activate one of those virtualenvs (something you usually don't need to do as the executables you probably want are all linked into .local/bin
which is in your PATH
by now), you can do:
source $HOME/.local/share/inaugurate/virtualenvs/<app_name>/bin/activate
deactivate it issuing:
deactivate
.local/
├── bin
│ ├── <linked_executable_1>
│ ├── <linked_executable_2>
│ ├── <linked_executable_3>
│ ├── <linked_executable_4>
│ ...
│ ...
│
├── share
└── inaugurate
├── bin
├── conda
│ ├── bin
│ ├── conda-meta
│ ├── envs
│ │ ├── <one app>
│ │ │ └──bin
│ │ │ ├── <link_target_1>
│ │ │ ├── <link_target_2>
│ │ │ ...
│ │ │ ...
│ │ ├── <other app>
│ │ └──bin
│ │ ├── <link_target_3>
│ │ ├── <link_target_4>
│ │ ...
│ │ ...
│ ├── etc
│ ├── include
│ ├── lib
│ ├── pkgs
│ ├── share
│ └── ssl
└── logs
Conda app environments can be found under .local/share/inaugurate/conda/envs
. In this case, if you'd wanted to activate a specific conda environment (again, usually you don't need to do this), you can do:
source $HOME/.local/share/inaugurate/conda/bin/activate <env_name>
and to deactivate:
source deactivate
What? Downloading and executing a random script from the internet? Duh.
That being said, you can download the inaugurate script and host it yourself on github (or somewhere else). If you then only use app descriptions locally and host your own 'app-store' (or, as those app descriptions are fairly easy to parse and understand, you read the ones the are hosted on the 'official' inaugurate app_store) you have the same sort of control you'd have if you'd do all the things inaugurate does manually.
I'd argue it's slightly better to have one generic, widely-used (not that inaugurate is widely-used at the moment, mind you) and looked upon script, that uses easy to parse configurations for the stuff it installs, than every app out there writing their own bootstrap shell script. inaugurate (possibly in combination with frecklecute to support more advanced setup tasks) could be such a thing, but I'd be happy if someone else writes a better alternative. It's more practical to not have to read a whole bash script every time you want to bootstrap a non-trivial-to-install application, is all I'm saying.
And even if you don't agree with any of this, you could still use a self-hosted inaugurate script for your local or in-house bootstrapping needs. If you have such needs :-)
Since I'm not particularly interested to have the old 'curly bootstrap scripts are evil'-discussion, here are a few links to arguments already made, and fights already fought:
- https://news.ycombinator.com/item?id=12766049
- https://sandstorm.io/news/2015-09-24-is-curl-bash-insecure-pgp-verified-install
I'm certain inaugurate, as it currently is, could be improved upon, esp. in terms of security and trustworthiness. For example add some sort of easy-to-use gpg-signing feature. As this is only one of a few minor side-projects for me, I can't really spend a lot of time on it at the moment. If anybody feels like contributing I'd be more than happy though!
It's as easy as I could possibly make it to adapt the inaugurate shell script for your own application. In order to do this, you need to modify the beginning of the inaugurate script and include the appropriate variable declarations.
If you want to adapt inaugurate for your own application, you can do that by adding the following variables to inaugurate (read the comments in the file to find the best place for them):
DEFAULT_PROFILE="freckles"
# conda
DEFAULT_PROFILE_CONDA_PYTHON_VERSION="2.7"
DEFAULT_PROFILE_CONDA_DEPENDENCIES="pip cryptography pycrypto git virtualenv"
DEFAULT_PROFILE_EXECUTABLES_TO_LINK="freckles frecklecute freckelize freckfreckfreck frankentree inaugurate frocker"
DEFAULT_PROFILE_EXTRA_EXECUTABLES="nsbl nsbl-tasks nsbl-playbook ansible ansible-playbook ansible-galaxy git"
# deb
DEFAULT_PROFILE_DEB_DEPENDENCIES="curl build-essential git python-dev python-pip python-virtualenv virtualenv libssl-dev libffi-dev"
# rpm
DEFAULT_PROFILE_RPM_DEPENDENCIES="wget git python-pip python-virtualenv openssl-devel gcc libffi-devel python-devel"
# pip requirements
DEFAULT_PROFILE_PIP_DEPENDENCIES="freckles"
DEFAULT_PROFILE_ENV_NAME="freckles"
The most important thing to do is to have a DEFAULT_PROFILE
variable set to the name of your package or executable. This indicates to inaugurate that a custom application profile is set. If the executable name that is used by the user in the inaugurate command-line can be found in the DEFAULT_PROFILE_EXECUTABLES_TO_LINK
variable value (which, usually, would probably only contain one executable), it'll use the custom profile. If not, it'll try the local and remote app-stores as described above.
The meaning of the other vars is the same as is described in apps descriptions (with a prepended DEFAULT_PROFILE
).
If you want to prevent the user to change or set one of the available environment variables, you can override those like so, in the top part of the inaugurate file:
NO_EXEC=true
Simple, nothing more to it.
If you want to change the inaugurate defaults for one or some of the available environment variables, add code like this to the inaugurate file:
if [ -z "$NO_EXEC" ]; then NO_EXEC=true fi
Use luci to create a option-url tree
This is not ready yet, will update details once it is.
Those are the platforms I have tested so far, others might very well work too. I did my development mainly on Debian-based systems, so other Linux distributions might not (yet) be up to scratch:
- Linux
- Debian
- Stretch
- Jessie
- Ubuntu
- 17.04
- 16.10
- 16.04
- CentOS
- 7
- Debian
- Mac OS X
- El Capitan
- Sierra
- Windows
- Windows 10 (Ubuntu subsystem) -- not tested/working yet
GNU General Public License v3