# Install apps for a cluster ## Goal Stand up PlayMolecule so multiple users on a shared SLURM or HPC site can run apps against a single, centrally managed installation — without each user having to download images, log into Google Cloud, or manage their own license file. This is the admin recipe. For the end-user setup, see [Installation](../installation.md). ## What you'll have at the end - Apptainer installed on every compute node. - A shared license file (or floating-license server) reachable from every node. - A **shared SIF cache** on shared storage holding every app's container image — pulled once, used by everyone. - An environment script users source to pick up the right `PM_*` variables. ## Prerequisites - Acellera-issued **license file** (or coordinates for a floating-license server). - Acellera-issued **service-account JSON** (or another way to authenticate `gcloud`) for the GCloud Artifact Registry that holds the app images. - Shared filesystem mounted at the same path on every compute node (e.g., `/shared`). - Root (or `sudo`) on every compute node where users will run jobs — Apptainer has to be installed on each worker. - `gcloud` CLI installed for the admin user. ## Step 1 — Install Apptainer on every compute node PlayMolecule pulls Docker images and converts them to plain SIF files on first use, so the only requirement is a working Apptainer: ```bash # Debian/Ubuntu sudo apt-get install apptainer # RHEL/Fedora (EPEL) sudo dnf install apptainer ``` Verify: ```bash apptainer --version ``` Modern kernels let Apptainer run fully unprivileged via user namespaces. If your kernel doesn't have user namespaces enabled, install the `apptainer-suid` variant too — it ships a setuid helper as a fallback. Official install docs: . ## Step 2 — Set up the license Two options: **Single machine**: drop the license file somewhere readable by every user: ```bash sudo install -m 0644 acellera.lic /etc/acellera/acellera.lic ``` **Multi-node cluster**: run an Acellera floating-license server. Instructions: ## Step 3 — Authenticate to Acellera's Docker registry ```bash gcloud auth login # admin user gcloud auth activate-service-account --key-file=/etc/playmolecule/sa.json gcloud auth configure-docker europe-southwest1-docker.pkg.dev ``` This stores Docker-format credentials that `apptainer pull docker://...` will pick up automatically. ## Step 4 — Create a shared SIF cache This is the heart of the cluster install. Every app's container image gets pulled into this directory once; every user on every node reads it from there. ```bash sudo mkdir -p /shared/playmolecule/apptainer sudo chmod a+rwx /shared/playmolecule/apptainer ``` The path can be anywhere on shared storage; pick whatever your site convention is. ## Step 5 — Pull the app images Tell PlayMolecule to use Apptainer and point it at the shared cache, then pull everything: ```bash export PM_RUNTIME=apptainer export PM_SIF_CACHE_DIR=/shared/playmolecule/apptainer ``` ```python from playmolecule import update_apps update_apps(pull_new=True, interactive=True) ``` The default `PM_REGISTRIES` (Acellera's GCloud Docker registry) is exactly what you want here — no need to set it. `interactive=True` prints a numbered list of every available app. Type `all` to pull everything, or pick specific apps. Each one converts to a SIF in `/shared/playmolecule/apptainer/`. ## Step 6 — Write an environment script Drop something like this into `/etc/profile.d/playmolecule.sh` (or your site's equivalent module file): ```bash # PlayMolecule shared install export PM_RUNTIME=apptainer export PM_SIF_CACHE_DIR=/shared/playmolecule/apptainer export ACELLERA_LICENCE_SERVER=27000@license.example.com # floating-license server ``` Users who source this need only `pip install playmolecule` and they're ready to go — they pick up Acellera's default Docker registry, the shared SIF cache, and the licence automatically. ## Step 7 — Smoke-test As any non-admin user: ```python from playmolecule import describe_apps from playmolecule.apps import proteinprepare describe_apps() # should list every installed app proteinprepare.tests.simple.run() # should complete with 🎉 ``` If {py:func}`~playmolecule.describe_apps` is empty, the user can't reach the Docker registry — check `gcloud auth configure-docker` and the user's Docker credentials store. If `tests.simple.run()` fails before producing outputs, the most likely cause is the license file path or Apptainer being misconfigured (no `apptainer-suid` on a kernel without user namespaces). ## Refresh later Re-run from the admin account whenever Acellera publishes updates: ```python from playmolecule import update_apps update_apps(pull_new=True) ``` Cron it nightly if you want automatic updates: ```text 0 3 * * * PM_RUNTIME=apptainer PM_SIF_CACHE_DIR=/shared/playmolecule/apptainer \ /opt/playmolecule/.venv/bin/python -c \ "from playmolecule import update_apps; update_apps(pull_new=True)" ``` ## Gotchas - A floating-license server is required if more than one machine will run apps at the same time. Otherwise you'll hit license conflicts. - If `apptainer pull docker://...` fails on a hardened node, the kernel may not have user namespaces enabled. The fix is either to enable them or to install the `apptainer-suid` package as a fallback. - The `$PM_SIF_CACHE_DIR` directory grows. Several GB per app is normal. Reclaim by removing old `*.sif` files; they'll be re-fetched on next use. - The `gcloud auth configure-docker` step has to be reachable by *every user* who'll run jobs — either by having each user run it themselves, or (cleaner) by sharing a `~/.docker/config.json` site-wide. Without it users will see "unauthorized" when the first job tries to pull a SIF. ## See also - [Update installed apps](update-installed-apps.md) - [Switch between Docker and Apptainer](switch-between-docker-and-apptainer.md) - [Environment variables](../reference/environment-variables.md)