scCAFM / start_server.sh
Catchxu
Fix GPU visibility in JupyterLab
b06d7d0
Raw
History Blame Contribute Delete
6.04 kB
#!/bin/bash
set -euo pipefail
if [[ "$(id -u)" -ne 0 ]]; then
echo "start_server.sh must run as root to prepare the read-only workspace." >&2
exit 1
fi
JUPYTER_TOKEN="${JUPYTER_TOKEN:-huggingface}"
SCCAFM_SOURCE_URL="${SCCAFM_SOURCE_URL:-https://github.com/Catchxu/scCAFM.git}"
SCCAFM_SOURCE_REVISION="${SCCAFM_SOURCE_REVISION:-main}"
SCCAFM_MODEL_ID="${SCCAFM_MODEL_ID:-kaichenxu/scCAFM}"
SCCAFM_MODEL_REVISION="${SCCAFM_MODEL_REVISION:-main}"
SCCAFM_DATASET_ID="${SCCAFM_DATASET_ID:-kaichenxu/scCAFM-data}"
SCCAFM_DATASET_REVISION="${SCCAFM_DATASET_REVISION:-main}"
readonly SCCAFM_WORKSPACE="/workspace/scCAFM"
readonly NOTEBOOK_DIR="$SCCAFM_WORKSPACE"
SCCAFM_ASSETS_DIR="$SCCAFM_WORKSPACE/assets"
SCCAFM_DATA_DIR="$SCCAFM_WORKSPACE/tutorial_data"
JUPYTER_RUNTIME_ROOT="$(mktemp -d /tmp/sccafm-jupyter.XXXXXX)"
resolve_hf_revision() {
local repo_type="$1"
local repo_id="$2"
local revision="$3"
/home/user/miniconda/bin/python -c '
import sys
from huggingface_hub import HfApi
repo_type, repo_id, revision = sys.argv[1:]
api = HfApi()
if repo_type == "model":
info = api.model_info(repo_id, revision=revision)
elif repo_type == "dataset":
info = api.dataset_info(repo_id, revision=revision)
else:
raise ValueError(f"Unsupported repository type: {repo_type}")
print(info.sha)
' "$repo_type" "$repo_id" "$revision"
}
require_commit_sha() {
local name="$1"
local revision="$2"
if [[ ! "$revision" =~ ^[0-9a-f]{40}$ ]]; then
echo "Could not resolve $name to a 40-character commit SHA: $revision" >&2
exit 1
fi
}
mkdir -p "$(dirname "$SCCAFM_WORKSPACE")"
if [[ ! -d "$SCCAFM_WORKSPACE/.git" ]]; then
if [[ -e "$SCCAFM_WORKSPACE" ]] && [[ -n "$(ls -A "$SCCAFM_WORKSPACE")" ]]; then
echo "Cannot prepare scCAFM: $SCCAFM_WORKSPACE exists and is not an empty Git checkout." >&2
exit 1
fi
git clone "$SCCAFM_SOURCE_URL" "$SCCAFM_WORKSPACE"
fi
git -C "$SCCAFM_WORKSPACE" fetch --depth 1 origin "$SCCAFM_SOURCE_REVISION"
git -C "$SCCAFM_WORKSPACE" checkout --detach FETCH_HEAD
SCCAFM_SOURCE_RESOLVED_REVISION="$(git -C "$SCCAFM_WORKSPACE" rev-parse HEAD)"
require_commit_sha "scCAFM source" "$SCCAFM_SOURCE_RESOLVED_REVISION"
pip install --no-deps "$SCCAFM_WORKSPACE"
SCCAFM_MODEL_RESOLVED_REVISION="$(resolve_hf_revision model "$SCCAFM_MODEL_ID" "$SCCAFM_MODEL_REVISION")"
require_commit_sha "scCAFM model" "$SCCAFM_MODEL_RESOLVED_REVISION"
mkdir -p "$SCCAFM_ASSETS_DIR"
hf download "$SCCAFM_MODEL_ID" \
--repo-type model \
--revision "$SCCAFM_MODEL_RESOLVED_REVISION" \
--local-dir "$SCCAFM_ASSETS_DIR"
SCCAFM_DATASET_RESOLVED_REVISION="$(resolve_hf_revision dataset "$SCCAFM_DATASET_ID" "$SCCAFM_DATASET_REVISION")"
require_commit_sha "scCAFM dataset" "$SCCAFM_DATASET_RESOLVED_REVISION"
mkdir -p "$SCCAFM_DATA_DIR"
hf download "$SCCAFM_DATASET_ID" \
--repo-type dataset \
--revision "$SCCAFM_DATASET_RESOLVED_REVISION" \
--local-dir "$SCCAFM_DATA_DIR"
cp /home/user/app/README.md "$SCCAFM_WORKSPACE/SPACE_README.md"
{
printf 'component\trepository\tselector\tresolved_revision\n'
printf 'source\t%s\t%s\t%s\n' "$SCCAFM_SOURCE_URL" "$SCCAFM_SOURCE_REVISION" "$SCCAFM_SOURCE_RESOLVED_REVISION"
printf 'model\t%s\t%s\t%s\n' "$SCCAFM_MODEL_ID" "$SCCAFM_MODEL_REVISION" "$SCCAFM_MODEL_RESOLVED_REVISION"
printf 'dataset\t%s\t%s\t%s\n' "$SCCAFM_DATASET_ID" "$SCCAFM_DATASET_REVISION" "$SCCAFM_DATASET_RESOLVED_REVISION"
} > "$SCCAFM_WORKSPACE/SPACE_VERSIONS.tsv"
echo "Resolved source revision: $SCCAFM_SOURCE_RESOLVED_REVISION"
echo "Resolved model revision: $SCCAFM_MODEL_RESOLVED_REVISION"
echo "Resolved dataset revision: $SCCAFM_DATASET_RESOLVED_REVISION"
jupyter labextension disable "@jupyterlab/apputils-extension:announcements"
chown user:user "$JUPYTER_RUNTIME_ROOT"
chmod 0700 "$JUPYTER_RUNTIME_ROOT"
install -d -o user -g user -m 0700 \
"$JUPYTER_RUNTIME_ROOT/cache" \
"$JUPYTER_RUNTIME_ROOT/config" \
"$JUPYTER_RUNTIME_ROOT/data" \
"$JUPYTER_RUNTIME_ROOT/ipython" \
"$JUPYTER_RUNTIME_ROOT/runtime"
chown -R root:root "$SCCAFM_WORKSPACE" /home/user /data/huggingface
chmod -R a-w "$SCCAFM_WORKSPACE" /home/user /data/huggingface
chmod 0755 /tmp /var/tmp
if ! runuser -u user -- test -w "$JUPYTER_RUNTIME_ROOT/runtime"; then
echo "Refusing to start: the Jupyter runtime directory is not writable by the Jupyter user." >&2
exit 1
fi
if runuser -u user -- test -w "$SCCAFM_WORKSPACE"; then
echo "Refusing to start: the scCAFM workspace is still writable by the Jupyter user." >&2
exit 1
fi
echo "Read-only workspace verified at $SCCAFM_WORKSPACE"
exec runuser -u user -- env -i \
HOME=/home/user \
PATH=/home/user/miniconda/bin:/usr/local/bin:/usr/bin:/bin \
PYTHONPATH=/home/user/app \
PYTHONDONTWRITEBYTECODE=1 \
LANG=C.UTF-8 \
LC_ALL=C.UTF-8 \
LD_LIBRARY_PATH="${LD_LIBRARY_PATH:-}" \
NVIDIA_VISIBLE_DEVICES="${NVIDIA_VISIBLE_DEVICES:-}" \
NVIDIA_DRIVER_CAPABILITIES="${NVIDIA_DRIVER_CAPABILITIES:-}" \
HF_HOME="$JUPYTER_RUNTIME_ROOT/cache/huggingface" \
HF_HUB_DISABLE_TELEMETRY=1 \
XDG_CACHE_HOME="$JUPYTER_RUNTIME_ROOT/cache" \
JUPYTER_CONFIG_DIR="$JUPYTER_RUNTIME_ROOT/config" \
JUPYTER_DATA_DIR="$JUPYTER_RUNTIME_ROOT/data" \
JUPYTER_RUNTIME_DIR="$JUPYTER_RUNTIME_ROOT/runtime" \
IPYTHONDIR="$JUPYTER_RUNTIME_ROOT/ipython" \
TMPDIR="$JUPYTER_RUNTIME_ROOT" \
/home/user/miniconda/bin/jupyter-lab \
--ip 0.0.0.0 \
--port 7860 \
--no-browser \
--ServerApp.token="$JUPYTER_TOKEN" \
--ServerApp.contents_manager_class=readonly_contents.ReadOnlyContentsManager \
--ServerApp.terminals_enabled=False \
--ServerApp.tornado_settings="{'headers': {'Content-Security-Policy': 'frame-ancestors *'}}" \
--ServerApp.cookie_options="{'SameSite': 'None', 'Secure': True}" \
--ServerApp.disable_check_xsrf=True \
--LabApp.news_url=None \
--LabApp.check_for_updates_class="jupyterlab.NeverCheckForUpdate" \
--notebook-dir="$NOTEBOOK_DIR"