# Node 20 slim base FROM node:20-slim # Reduce interactive prompts in apt ENV DEBIAN_FRONTEND=noninteractive # System deps needed to build node-pty (node-gyp toolchain). # - build-essential: compilers and headers required by native addons (node-pty) # - python3, pip, venv: provide Python 3.11 and tooling for scripts/venvs executed via the web terminal # - python-is-python3: makes the `python` command invoke Python 3 (quality-of-life) RUN apt-get update && \ apt-get -o Acquire::Retries=3 -o Acquire::http::Timeout=30 install -y --no-install-recommends \ bash git python3 python3-pip python3-venv python-is-python3 build-essential \ tmux ncurses-term rclone rsync nano ssh python3-dev curl wget gpg htop libicu-dev libcurl4-openssl-dev libedit-dev libsqlite3-dev libncurses-dev libxml2-dev pkg-config uuid-dev && \ rm -rf /var/lib/apt/lists/* # Container-friendly Python defaults: # - PYTHONUNBUFFERED=1: log output is unbuffered so you see real-time logs in HF Spaces. # - PYTHONDONTWRITEBYTECODE=1: avoid writing .pyc files; fewer disk writes in ephemeral containers. # - PIP_DISABLE_PIP_VERSION_CHECK=1: skip online version check to reduce network calls and noise. ENV PYTHONUNBUFFERED=1 \ PYTHONDONTWRITEBYTECODE=1 \ PIP_DISABLE_PIP_VERSION_CHECK=1 # Convenience symlinks for common typos so `pyhon`/`ptyhon` also run Python 3. # This helps when quickly executing scripts in the web terminal. RUN ln -sf /usr/bin/python3 /usr/local/bin/pyhon && \ ln -sf /usr/bin/python3 /usr/local/bin/ptyhon # Optional: install Claude Code CLI globally so you can run `claude` in the web terminal # Network hiccups can cause builds to fail; keep this optional and non-fatal. RUN npm install -g @anthropic-ai/claude-code # App setup WORKDIR /app # Preinstall Python packages used in the terminal. We use `|| true` so # transient PyPI/network issues don’t fail the whole image build. Remove # `|| true` if you prefer strict builds. COPY requirements.txt ./ # Add timeout to pip to avoid long hangs when PyPI is slow/unreachable RUN pip install --no-cache-dir --break-system-packages --timeout=60 -r requirements.txt || true COPY package.json ./ RUN npm install --production COPY server.js ./ COPY scripts ./scripts COPY public ./public # Cloudflare RUN wget https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64.deb RUN dpkg -i cloudflared-linux-amd64.deb # Make backup scripts available on PATH COPY scripts/download_claude_backup.sh /usr/local/bin/download_claude_backup.sh COPY scripts/upload_claude_backup.sh /usr/local/bin/upload_claude_backup.sh RUN chmod +x /usr/local/bin/download_claude_backup.sh /usr/local/bin/upload_claude_backup.sh ENV PATH=${HOME}/.local/share/swiftly/bin:${PATH} ENV PORT=7860 \ NODE_ENV=production EXPOSE 7860 # Write SSH keys from env vars at runtime, then exec the app COPY scripts/ssh-setup.sh /usr/local/bin/ssh-setup.sh COPY scripts/install_swift.sh /usr/local/bin/install_swift.sh COPY scripts/setup.sh /usr/local/bin/setup.sh COPY scripts/download_claude_backup.sh /app/scripts/. COPY scripts/upload_claude_backup.sh /app/scripts/. RUN chmod 777 /usr/local/bin/ssh-setup.sh RUN chmod 777 /usr/local/bin/setup.sh RUN chmod 777 /usr/local/bin/install_swift.sh RUN chmod 777 /app/scripts/download_claude_backup.sh RUN chmod 777 /app/scripts/upload_claude_backup.sh RUN chmod 777 /app/scripts/hearbeat.sh CMD ["sh", "-c", "/usr/local/bin/setup.sh"]