Skip to content

Installing

Plugins are Python distributions. A gateway app loads the plugins that are installed in its environment and listed in its configuration (FOCA's plugins.available; see FOCA's plugins page): installed is not enabled. Installing a whole group and enabling two plugins is valid; security-conscious operators install only what they enable, to keep dependencies (and scanner findings) out of their images.

Experimental plugins only

The plugins released so far, generic.routing.random and tes.routing.distance (0.1.3 each), are experimental; the latest release train is foca-plugins 0.3.0. Distributions named below that don't exist yet are examples of the naming scheme.

Release trains: the meta distribution

The meta distribution foca-plugins has no code, only extras that pin plugins of this repository to exact versions. Each release of it is a release train (a semantic version, set by the changes of its pins; see Releasing): plugins tested together against the FOCA versions that it declares.

Extra Installs Now
foca-plugins[<group>] (generic, tes, wes) the stable and experimental plugins of a group [generic]: generic.routing.random; [tes]: tes.routing.distance; [wes]: empty
foca-plugins[<group>-<subgroup>], e.g., [tes-routing] those of a subgroup [generic-routing], [tes-routing] (a subgroup's extra is added with its first plugin)
foca-plugins[all] all stable plugins empty
foca-plugins[experimental] all experimental plugins both plugins

For example:

pip install "foca-plugins[tes-routing]==0.3.0"

The example plugin generic.example.noop is never published, so it is in no extra.

Single distributions

Install plugins directly to choose versions yourself, or to combine plugins of this repository with those of others, e.g. (the second name is an example):

pip install "foca-plugin-tes-routing-distance==0.1.3" "org-example-cost-routing==<version>"

Each plugin declares the FOCA versions that it supports (foca>=X,<Y) and its plugin API version; FOCA refuses plugins of another API version at startup.

Add plugins to a gateway app by building an image derived from the app's image. This is explicit, reviewable and hash-pinned, and works for plugins of any repository. proTES documents its image and configuration in its repository; the same recipe applies to every gateway app:

# uv, by digest; not copied into the image
FROM ghcr.io/astral-sh/uv:<version>@sha256:<digest> AS uv

# The app's release image, by digest
FROM docker.io/elixircloud/protes:<version>@sha256:<digest>
USER root
RUN --mount=from=uv,source=/uv,target=/usr/local/bin/uv \
    --mount=type=bind,source=plugins.txt,target=/tmp/plugins.txt \
    UV_NO_CACHE=1 uv pip install --system --require-hashes --only-binary :all: \
        --no-deps --compile-bytecode -r /tmp/plugins.txt \
    && uv pip check --system
USER <user of the app's image>

Images on FOCA 0.20 or later have no pip, so install with uv, as above. Set the last USER to the user that the app's image runs as (e.g., 1000 for proTES).

plugins.txt lists the plugins and their dependencies that the app's image doesn't have, each pinned with hashes, e.g., generated with uv pip compile --generate-hashes against the app's own requirements:

foca-plugin-tes-routing-distance==<version> \
    --hash=sha256:<hash of the wheel>

Then enable the plugins in the app's configuration, e.g., in a Helm values file of the app's chart, which selects the derived image (image.repository, image.tag) and renders the plugins section; the chart never installs code. Scan and sign the derived image as you do the app's image.

Not recommended: installing plugins at container start (e.g., in an init container): it is unpinned and unreviewed, and breaks read-only root file systems.

Verifying distributions

Every wheel and sdist is published with PEP 740 attestations (Sigstore) by the release workflow of this repository, and with GitHub artifact attestations (SLSA build provenance). pip does not verify attestations yet; verify them before building an image, e.g.:

gh attestation verify foca_plugin_tes_routing_distance-<version>-py3-none-any.whl \
  --repo elixir-cloud-aai/foca-plugins