# HuggingRun v2 — Ubuntu Server on HuggingFace Spaces # Single port 7860: nginx → ttyd (web terminal) + SSH-over-WebSocket # Persistence: tar.zst archive of /home + /root → HF Dataset FROM ubuntu:24.04 ENV DEBIAN_FRONTEND=noninteractive # Core: Python + git-lfs + huggingface_hub RUN apt-get update && apt-get install -y --no-install-recommends \ ca-certificates curl wget python3 python3-pip python3-venv git git-lfs \ && pip3 install --no-cache-dir --break-system-packages huggingface_hub websockets \ && git lfs install \ && rm -rf /var/lib/apt/lists/* # Server: SSH + nginx + ttyd + tools RUN apt-get update && apt-get install -y --no-install-recommends \ openssh-server openssh-client \ nginx \ ttyd \ procps htop vim nano less tmux \ build-essential rsync zstd \ && rm -rf /var/lib/apt/lists/* # Node.js 20 LTS (for Claude Code) RUN curl -fsSL https://deb.nodesource.com/setup_20.x | bash - \ && apt-get install -y nodejs \ && rm -rf /var/lib/apt/lists/* # Claude Code (install globally so all users can access) RUN npm install -g @anthropic-ai/claude-code 2>/dev/null \ || (curl -fsSL https://claude.ai/install.sh | bash && \ cp /root/.local/bin/claude /usr/local/bin/claude 2>/dev/null || true) # Snapshot base package list (to detect user-added packages later) RUN dpkg-query -W -f='${Package}\n' | sort > /etc/base-packages.list # SSH: host keys + privilege separation directory RUN ssh-keygen -A && mkdir -p /run/sshd # User account (for SSH login); container runs as root for system persistence RUN useradd -m -u 1000 -s /bin/bash -p "$(openssl passwd -6 huggingrun)" tao-shen 2>/dev/null || true \ && apt-get update && apt-get install -y --no-install-recommends sudo \ && echo "tao-shen ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/tao-shen \ && chmod 440 /etc/sudoers.d/tao-shen \ && rm -rf /var/lib/apt/lists/* # Root password for SSH login as root RUN usermod -p "$(openssl passwd -6 huggingrun)" root RUN mkdir -p /data # v2: only 3 files (entrypoint + nginx + ws-bridge) COPY entrypoint.py /entrypoint.py COPY nginx.conf /etc/nginx/nginx.conf COPY ws_ssh_bridge.py /ws_ssh_bridge.py ENV PERSIST_PATH=/data ENV PYTHONUNBUFFERED=1 # Run as root (needed for: apt install persistence, bind mounts, sshd) EXPOSE 7860 ENTRYPOINT ["python3", "-u", "/entrypoint.py"]