Installation¶
Requirements¶
Linux (x86_64 or arm64) or macOS (Apple Silicon / arm64 only). Intel Macs (x86_64) are no longer supported. On Windows, consider using Ubuntu for WSL. BusyBox is not supported.
POSIX-compliant login shell (bash, zsh, dash, ksh93), fish, elvish, nushell, or powershell. csh and tcsh have minimal support (
PATHand environment variables only).Python 3.12, which will be bootstrap installed into
~/.local/share/koopa-bootstrapautomatically when necessary.Core utilities:
curl,git,grep,mkdir,mktemp,rm,sed,tar.
macOS¶
Xcode Command Line Tools are required.
xcode-select --install
The command line tools will install into /Library/Developer/CommandLineTools.
Debian / Ubuntu¶
if [ "$(id -u)" -eq 0 ]
then
apt-get update
apt-get --quiet --yes install sudo
fi
sudo apt-get update
sudo apt-get \
--no-install-recommends \
--quiet \
--yes \
install \
bash \
build-essential \
ca-certificates \
coreutils \
curl \
findutils \
git \
locales \
lsb-release \
procps \
python3 \
unzip
Fedora / RHEL¶
if [ "$(id -u)" -eq 0 ]
then
dnf -y install sudo
fi
sudo dnf -y install \
automake \
bash \
coreutils \
curl \
findutils \
gcc \
git \
make \
procps \
python3 \
unzip
Install koopa¶
The install script will prompt to determine whether you want a shared install for all users, or for the current local user only. It will also ask about dotfile configuration and whether your shell profile configuration file should be modified.
sh -c "$(curl -LSs https://koopa.acidgenomics.com/install)"
Alternatively, download the install script as a temporary file and then execute.
install="$(mktemp)"
curl -LSs -o "$install" https://koopa.acidgenomics.com/install
chmod +x "$install"
"$install"
Here’s how to install koopa non-interactively, which is intended primarily for building Docker images.
curl -LSs https://koopa.acidgenomics.com/install \
| sh -s -- --non-interactive
Offline / pinned install (restricted networks)¶
The install script above fetches and executes code from
koopa.acidgenomics.com in one step. On a corporate build that requires every
artifact to be reviewed and sourced from an approved host before it runs,
install from a pinned release tarball instead.
What this secures: ingress. The artifact is pinned to a specific tag (an
immutable commit, not a moving branch), mirrorable through an internal proxy,
and reviewable before it ever runs, unlike curl | sh, which fetches and
executes in the same step.
What this does not secure: the ~500 third-party apps koopa can install
(compilers, language runtimes, CLI tools). Those are downloaded and, in many
cases, compiled at koopa install time from their own upstream hosts. Use the
internal mirror below, with
pull_priority set to "vendor_only", to route those through the same
review gate.
# Fetch a specific tagged release (or pull the same tarball from an internal
# mirror that proxies GitHub tag archives). GitHub's codeload URLs are
# content-addressed by tag, so re-fetching the same tag always returns the
# same bytes -- this is what makes the artifact reviewable ahead of use.
version=0.25.0
curl -LSs -o "koopa-${version}.tar.gz" \
"https://github.com/acidgenomics/koopa/archive/refs/tags/v${version}.tar.gz"
# Extract into the standard koopa data directory.
data_home="${XDG_DATA_HOME:-$HOME/.local/share}"
mkdir -p "$data_home"
tar -xzf "koopa-${version}.tar.gz" -C "$data_home"
mv "${data_home}/koopa-${version}" "${data_home}/koopa"
# Activate, e.g. by adding this line to the shell profile.
. "${data_home}/koopa/activate.sh"
This is a pinned, non-git release: koopa install/uninstall/configure
work normally against it, but koopa update recognizes the tree as a pinned
release and reports as much instead of attempting a git pull. To update,
fetch and extract the next tagged release the same way.
The first koopa invocation needs an interpreter matching the version pinned
in .python-version (currently 3.12) to run its own CLI. It looks for one at
/usr/bin/python3 first, then the .python-version-derived name (e.g.
python3.12) and python3 as resolved on PATH; if none matches, it runs
bootstrap.sh. bootstrap.sh reads the same vendor.json
described in Internal mirror below,
so a vendor_only network routes the bootstrap Python build through the
mirror too, the same as every other app install.
Two things to know before relying on that for a fully offline bootstrap:
Parsing
vendor.jsonneeds a JSON parser.bootstrap.shuses whicheverpython3it finds (any version; this is unrelated to the 3.12 pin) and falls back to ased-based parse of the flat HTTP fields when nopython3exists at all. That fallback cannot read the nestedremotesmap below, so it only supports a pre-populatedsrc_repomirror, not the remote-proxy rewrite.The fast path (a prebuilt CPython via
uv, seconds instead of a ~10 minute compile) needsuvalready onPATH;bootstrap.shnever fetches theuvbinary itself from the mirror. Whenuvis present, it can still fetch its CPython build through a mirror-derivedUV_PYTHON_INSTALL_MIRROR(see below), butuvcannot present the mirror’s Bearer token, so an auth-required repo fails the fast path –bootstrap.shthen falls through to the source build automatically, which does authenticate.
Internal mirror (restricted networks)¶
Installing apps normally downloads source tarballs and prebuilt binaries from
upstream hosts (GitHub, GNU/Savannah mirrors, koopa.acidgenomics.com/src, and
similar) directly. On a network that restricts outbound traffic to an approved
allowlist, or where every artifact must be reviewed before it reaches a host,
route these downloads through an internal mirror instead: a generic HTTP(S)
repository or an S3 bucket that you control and populate.
Copy the example config into ${XDG_CONFIG_HOME:-~/.config}/koopa/vendor.json
and edit it in place. This location is recommended over etc/koopa/vendor.json
inside the checkout (see precedence note below):
mkdir -p "${XDG_CONFIG_HOME:-$HOME/.config}/koopa"
cp etc/koopa/vendor.json.example "${XDG_CONFIG_HOME:-$HOME/.config}/koopa/vendor.json"
{
"enabled": true,
"backend": "http",
"http": {
"base_url": "https://artifacts.example.com",
"src_repo": "generic-team-koopa-src",
"binary_repo": "generic-team-koopa-binaries",
"token_env_var": "HTTP_ACCESS_TOKEN",
"remotes": {
"koopa.acidgenomics.com": "koopa-remote",
"github.com": "github-remote",
"www.python.org": "python-org-remote",
".gnu.org": "gnu-remote"
}
},
"pull_priority": "vendor_only"
}
Fields:
backend:"http"or"s3". Only one backend section (httpors3) is read, matchingbackend.http.base_url: the URL prefix that repository names hang off. koopa only ever appends/<repo>/...to it, so if your server serves repositories under a path prefix rather than at the domain root, include that prefix here.http.token_env_var: the name of an environment variable holding a Bearer token, read at request time. Never put the token itself invendor.json— anonymous read access needs no token at all.http.remotes: an optional host -> repository map for remote repositories that proxy an upstream host and cache on first fetch (as opposed tosrc_repo, a local repository you populate yourself; see below). A request tohttps://github.com/...is rewritten to{base_url}/{remotes["github.com"]}/..., preserving everything after the host. Keys starting with.match as a hostname suffix, so".gnu.org"coversftpmirror.gnu.org,ftp.gnu.org, and any other GNU mirror host koopa tries. Every upstream URL koopa would otherwise contact is tried through a matching remote before falling back to the direct public host (or not at all, undervendor_only).s3.profile: a named AWS CLI profile used foraws s3 cp/aws s3api head-objectcalls. Requires theawsCLI onPATH. Thes3backend has no equivalent toremotes.pull_priority:"vendor_first"(the default) tries the mirror before falling back to the public host, useful while the mirror is still being populated."vendor_only"never contacts a public host: onlysrc_repoandremotesare tried, and the install fails outright if an artifact is missing from both — this is what a genuinely airgapped or allowlisted network needs.
vendor.json is checked in order, first existing file wins (the two are never
merged): ${XDG_CONFIG_HOME:-~/.config}/koopa/vendor.json, then
etc/koopa/vendor.json relative to the koopa prefix. The etc/koopa/ location
is gitignored either way; it is not something you commit alongside the koopa
checkout. The XDG_CONFIG_HOME location is preferred because it lives outside
the koopa tree entirely: a pinned-release re-extract or a git clean in the
checkout can never destroy it, so the mirror config the host depends on to
install anything survives independently. Populating src_repo with the app
versions your team needs is an operational task outside koopa itself —
koopa develop push-app-build <name>
uploads a locally built app to the configured backend once credentials are
present. A remotes entry needs no such per-app population step: point one
remote repository at koopa.acidgenomics.com and it covers every source
tarball koopa already mirrors there, including the ones bootstrap.sh itself
needs (see above) — a single
entry gets a vendor_only network most of the way to a fully offline install
with zero pre-population.
If you are behind a corporate proxy rather than (or in addition to) a vendor
mirror, see Troubleshooting for the http_proxy
variable koopa and its bootstrap dependencies honor.