Spaces:
Paused
Paused
Commit History
-
feat: tao-shen user with sudo, hostname=huggingrun, ttyd login
- Create tao-shen user (sudo NOPASSWD) instead of generic 'user' - Set hostname to 'huggingrun' for clean prompt - ttyd uses 'login -f tao-shen' for proper login shell - Copy root's authorized_keys to tao-shen on restore Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>ca96613 -
fix: split Dockerfile apt-get calls (match proven build pattern)
Use openssl passwd instead of chpasswd, split apt-get into two separate calls matching the old Dockerfile that built successfully. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>8e73dda -
v2: complete redesign — single entrypoint, tar.zst persistence
Replace 13 scripts with 3 files (+ Dockerfile): - entrypoint.py: single Python PID 1 (init, sync, services, log streamer) - nginx.conf: reverse proxy (7860 → ttyd, ssh, logs) - ws_ssh_bridge.py: WebSocket-to-SSH bridge (unchanged) Key changes: - Persistence: tar.zst of /home + /root via upload_file (not folder sync) - No more rsync permission corruption (tar -p preserves modes) - No more .cache path rejections (single archive file) - No more upload_large_folder hangs (upload_file is fast) - Log streamer runs as thread (not separate process) - Sync runs as thread (not separate daemon) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>52013b5 -
fix: restore original logging pattern + fix sync hanging
Root cause analysis: 1. sync daemon log() changed from stderr to stdout (broke HF log capture) 2. stdbuf -oL -eL removed from RUN_CMD (broke line buffering) 3. start-server.sh used exec > >(tee >&2) instead of direct echo >&2 4. upload_large_folder hangs for hours on 1.8GB rootfs Fixes: - Restore log() to use file=sys.stderr (original design from ea21d45) - Restore stdbuf -oL -eL in Dockerfile RUN_CMD - Simplify start-server.sh to direct echo >&2 + logfile write - Switch from upload_large_folder to upload_folder (doesn't hang) - Restore exec nginx (original PID 1 = nginx, not bash+wait) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>ea03e2a
-
fix: move ALL app scripts to /scripts/ (outside PERSIST_DIRS)
Dataset restore overwrites files in /opt/ and /etc/ with stale versions from the dataset. Move all Docker image scripts to /scripts/ which is NOT in PERSIST_DIRS, so they survive restore. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>6adea9c -
fix: copy nginx.conf to /scripts/ AFTER COPY scripts (dir replace)
COPY scripts /scripts replaces the entire directory, deleting any files previously copied there. Move nginx.conf copy after it. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>bdc0fe0 -
fix: store nginx.conf outside PERSIST_DIRS, restore before nginx start
Dataset restore overwrites /etc/nginx/nginx.conf with stale version. Fix: keep canonical config at /scripts/nginx.conf (not in PERSIST_DIRS), copy it to /etc/nginx/ before starting nginx. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>e081bc5 -
fix: start nginx LAST so startup logs appear in HF SSE
HF's runtime SSE only captures container output during STARTING state (before port 7860 responds). Move nginx from first to last service so all boot info + service status appears in the SSE stream. Also: - Rename /logs → /api/logs (HF intercepts /logs path) - Revert to bash entrypoint (Python wrapper didn't help) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>f18461b -
fix: use Python PID 1 wrapper to capture all output for HF SSE
HF's runtime log SSE captures stdout from PID 1. Gradio (Python) apps work because Python is PID 1. Bash entrypoints don't seem to work. This Python wrapper becomes PID 1, runs entrypoint.sh as a subprocess, and forwards all output to stdout with flush. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>9c66a5d -
fix: remove reference to deleted entrypoint_wrapper.py in chmod
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>22382b6 -
feat: add /logs/stream SSE endpoint for real-time log streaming
HF's runtime log API doesn't capture Docker SDK container output (confirmed: stdout, stderr, /proc/1/fd/*, Python PID 1 all fail). Added our own SSE streamer at /logs/stream that mimics HF's format: curl -N https://tao-shen-huggingrun.hf.space/logs/stream Also available as static file: curl .../logs Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>efe59e5 -
feat: Python PID 1 wrapper for HF runtime log API compatibility
HF's log API doesn't capture bash stdout/stderr from Docker containers. Use a Python process as PID 1 that tails /var/log/huggingrun.log and prints to stdout/stderr. All scripts write to the logfile, Python PID 1 echoes them for HF to capture. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>a1676f7 -
fix: use stderr for all logs (HF Spaces captures stderr, not stdout)
HF Spaces log API only captures stderr from Docker containers. Changed all scripts to redirect stdout→stderr (exec 1>&2) and Python to print to sys.stderr. Added PYTHONUNBUFFERED=1, removed stdbuf wrapper. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>955df2f -
fix: dataset = exact disk mirror, minimal excludes, subcommand daemon
- Minimize rsync excludes to only /proc /sys /dev /data (technically impossible) - Add --no-specials --no-devices to rsync (git can't store sockets/devices) - Split daemon into init/sync-loop/save subcommands (fix thread dying) - entrypoint.sh runs init then starts sync-loop as background process Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>29460a0 -
feat: git_sync_daemon — gitfs-like auto-sync without FUSE
FUSE/gitfs not available in HF Spaces (no CAP_MKNOD). Implements same behavior via pure git: - git clone dataset → /data on startup - rsync / → /data/rootfs/ periodically - git add/commit/push automatically (like gitfs current/) - Dataset mirrors filesystem at actual paths - Configurable sync interval (default 120s) Simplified start-server.sh: only starts services (sshd, ws-bridge, ttyd, nginx). All persistence handled by git_sync_daemon. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>08f77cf -
fix: use upload_large_folder, fix permission errors, exclude locks
- upload_sync.py: uses upload_large_folder for reliable large uploads - Exclude *.lock, *.pid, *.sock from rsync (permission issues) - chmod -R a+r rootfs before upload - Source /etc/huggingrun.env in save_system() Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>94a1b4c -
fix: install Claude Code globally via npm, fix root password
- npm install -g for global /usr/local/bin/claude access - Use openssl passwd consistently for root (chpasswd fails in Docker) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>7cc82b5 -
fix: create /run/sshd, fix websockets API deprecation, root password
- mkdir -p /run/sshd in Dockerfile and start-server.sh (sshd needs it) - Use websockets.asyncio.server.serve with fallback for compatibility - Set root password for SSH login as root Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>9c608e0 -
fix: use openssl passwd instead of chpasswd for user creation
chpasswd fails with PAM error in Docker build. Use useradd -p with openssl passwd -6 to set password directly. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>0c15a92 -
feat: single-port SSH-over-WebSocket + full OS persistence
- nginx multiplexes port 7860: / → ttyd, /ssh → ws-ssh-bridge → sshd - WebSocket-to-TCP bridge enables SSH through HF's single port - Full system persistence: /usr/local, /home, /opt, /root, /etc + apt packages - Dataset stores at root level (no subfolder) - Client helper: scripts/ssh_connect.sh using websocat Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>2a081e2 -
feat: Ubuntu Server with ttyd web terminal + SSH + Claude Code + persistence stress test
- Dockerfile: switch from Desktop (XFCE/noVNC) to Server (ttyd web terminal) - Install Node.js 20, Claude Code, openssh, ttyd, tmux, htop, vim - ubuntu-server/start-server.sh: ttyd on 7860, sshd on 2222, persistent /data/home - monitor_and_test.py: add persistence stress test (concurrent file I/O, checksums, large file writes, read-write under load) - test_local.sh: updated for server (ttyd instead of noVNC) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>ed449d2 -
feat: SSH access + stress test for Ubuntu desktop; always start sshd
- Dockerfile: pre-generate SSH host key at build time - start-desktop.sh: sshd always starts (key-auth or password-less); configurable SSH_LISTEN (0.0.0.0 for local, 127.0.0.1 for HF) - monitor_and_test.py: add --ssh-test with connect, command exec, stress (concurrent sessions), and brute-force ramp-up tests - scripts/test_local.sh: full local Docker integration test - scripts/verify_overnight.sh: multi-round overnight verification Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>3cf6b15 -
stderr echo + stdbuf for log visibility; trace x11vnc/noVNC
Made-with: Cursor401dec8 -
fix: usermod -d use user not EXISTING; add scripts/curl_logs.sh for Bearer curl
Made-with: Cursor82529e3 -
feat: sshd + reverse SSH for local SSH into HF Ubuntu; docs/SSH_ACCESS.md
Made-with: Cursor62248a5 -
fix: useradd UID 1000 already exists in base; poll once then show logs immediately on error
Made-with: Cursor261341c -
deploy: Ubuntu desktop as root Dockerfile; add push-debug workflow doc; generic monitor retries and sync retry
Made-with: Cursor5cd111e -
HuggingRun: Run anything on Hugging Face — generic Docker + persistence
Made-with: Cursora3bfafd