# Putting catalog SIFs into an Eureka deployment

Eureka does **not** download containers when someone clicks Launch.
The catalog is a public library. A deployment copies the SIFs it wants
onto **shared POSIX** (vault / OrangeFS / NFS) that login and compute
already mount. Admin Apps `filePath` is that POSIX path.

This is a deploy-time (or “enable this app”) step, not a session step.

## Rule

| Place | Role |
| --- | --- |
| https://containers.projecteureka.ai/`<name>`/`<version>`/image.sif | Public catalog. Pin a version. |
| Shared POSIX (vault) | What Apptainer actually execs |
| Admin Apps `filePath` | Vault path, **not** the HTTPS URL |
| `container_args` / `connectUrl` | From that version’s `container-program.json` |

`image/apps/container/start.sh` waits until `filePath` is readable, then
`apptainer exec`. An `https://…` `filePath` is rejected on purpose.

Do not pull from Docker Hub or the catalog at Connect time. Multi-GB
over the session path is slow and races the Connect button.

## Which containers

Copy **only the apps this Eureka should offer**. Four HTTP SIFs are
published today (~4 GiB total). A teaching lab that only wants VS Code
copies that one object.

See [APPS.md](APPS.md) for what is published and what is worth adding.

## Where they go

Prefer **one site-wide copy** on the shared filesystem every compute
personality can read:

```
/vault/containers/<name>/<version>/image.sif
```

Example:

```
/vault/containers/jupyter-datascience/2026.08/image.sif
/vault/containers/codeserver/4.96.4/image.sif
```

Use a **project** path (`/vault/projects/<project>/containers/…`) only
for a custom or unlisted SIF that should not be global.

`/software/containers/` on the VM image is the old cloudjump layout.
Do not bake catalog SIFs into the image going forward.

The directory must exist on the shared FS **before** the first Launch.
`container/start.sh` will not create it from the catalog.

## How to copy

Any of these is fine. Compute only needs the file to be POSIX-readable.

### curl (from a login node that can write vault)

```sh
VER=2026.08
DEST=/vault/containers/jupyter-datascience/${VER}
mkdir -p "${DEST}"
curl -fsSL -o "${DEST}/image.sif" \
  "https://containers.projecteureka.ai/jupyter-datascience/${VER}/image.sif"
curl -fsSL -o "${DEST}/image.sif.sha256" \
  "https://containers.projecteureka.ai/jupyter-datascience/${VER}/image.sif.sha256"
test "$(tr -d ' \n' < "${DEST}/image.sif.sha256" | awk '{print $1}')" = "$(sha256sum "${DEST}/image.sif" | awk '{print $1}')"
# Eureka Admin Apps Download does this once and writes image.sif.verified.
```

### gsutil / gcloud (same objects)

```sh
gcloud storage cp --recursive \
  gs://containers.projecteureka.ai/jupyter-datascience/2026.08 \
  /vault/containers/jupyter-datascience/2026.08
```

The catalog bucket is public-read. No GCP key is required to **download**.
Writing to vault is a normal Unix permission on the shared FS.

### Storage Manager

Add `containers.projecteureka.ai` as a public GCS bucket (read-only),
then copy `image.sif` into project or site POSIX. Same outcome: a file
compute can `open()`.

## Register the app

1. Copy the SIF (above).
2. Admin Apps → New App, using that version’s `container-program.json`
   **except** `filePath`:

   | Field | Example |
   | --- | --- |
   | Display name | Jupyter Data Science |
   | FilePath | `/vault/containers/jupyter-datascience/2026.08/image.sif` |
   | Connect path | `/login` |
   | Arguments | `jupyter lab --core-mode --config=$CONFIG_FILE` |

   Published JSON still has the HTTPS catalog URL in `filePath` as
   documentation. Replace it with the vault path.

3. Add a project launcher that selects that ContainerProgram.
4. Launch once. Connect is the same as the old InstanceProgram for that
   app (`/node/…/login` or `rnode:…`).

Repeat per app you want on this Eureka. Skip the rest.

## Versions

Pin `<name>/<version>/` in the vault path and in Admin Apps. Do not
install a floating `latest`. Publishing a new catalog version does not
change running deployments until someone copies the new object and
updates `filePath`.

## Do not

- Set `filePath` to `https://containers.projecteureka.ai/…`
- `apptainer pull docker://…` on the compute node at session start
- Put `.sif` files in git
- Copy every catalog object “just in case” (they are large)
- Duplicate the same app under two names (one RStudio HTTP SIF)
