Spaces:
Paused
Paused
Upload 10 files
Browse files- .dockerignore +7 -0
- Dockerfile +42 -27
- README.md +202 -5
- nginx.conf +62 -0
- scripts/launch-browser.sh +16 -0
- scripts/launch-nginx.sh +7 -0
- scripts/launch-openbox.sh +6 -0
- scripts/launch-x11vnc.sh +14 -0
- start.sh +50 -0
- supervisord.conf +83 -0
.dockerignore
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
.git/
|
| 2 |
+
.env
|
| 3 |
+
*.log
|
| 4 |
+
__pycache__/
|
| 5 |
+
.browser.htpasswd
|
| 6 |
+
chromium-profile/
|
| 7 |
+
browser-data/
|
Dockerfile
CHANGED
|
@@ -1,34 +1,49 @@
|
|
| 1 |
-
|
| 2 |
-
|
| 3 |
-
|
| 4 |
-
|
| 5 |
-
|
| 6 |
-
|
| 7 |
-
|
| 8 |
-
|
| 9 |
-
|
| 10 |
-
|
| 11 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 12 |
&& rm -rf /var/lib/apt/lists/*
|
| 13 |
|
| 14 |
-
|
| 15 |
-
|
| 16 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 17 |
|
| 18 |
-
# 3. 設定全域變數 (這樣 Chromium 絕對不會找不到 DISPLAY)
|
| 19 |
-
ENV DISPLAY=:1
|
| 20 |
-
ENV HOME=/home/user
|
| 21 |
-
RUN useradd -m -u 1000 user
|
| 22 |
USER user
|
| 23 |
-
WORKDIR /home/user
|
| 24 |
|
| 25 |
EXPOSE 7860
|
| 26 |
|
| 27 |
-
|
| 28 |
-
CMD
|
| 29 |
-
sleep 3 && \
|
| 30 |
-
openbox & \
|
| 31 |
-
x11vnc -display :1 -nopw -forever -shared -rfbport 5900 & \
|
| 32 |
-
/usr/share/novnc/utils/launch.sh --vnc localhost:5900 --listen 7860 & \
|
| 33 |
-
sleep 3 && \
|
| 34 |
-
chromium --no-sandbox --disable-gpu --disable-dev-shm-usage --start-maximized --no-first-run
|
|
|
|
| 1 |
+
# syntax=docker/dockerfile:1.7
|
| 2 |
+
|
| 3 |
+
FROM debian:bookworm-slim
|
| 4 |
+
|
| 5 |
+
ARG DEBIAN_FRONTEND=noninteractive
|
| 6 |
+
|
| 7 |
+
ENV DISPLAY=:99 \
|
| 8 |
+
HOME=/home/user \
|
| 9 |
+
BROWSER_WIDTH=1920 \
|
| 10 |
+
BROWSER_HEIGHT=1080 \
|
| 11 |
+
START_URL=https://arena.ai/text/direct
|
| 12 |
+
|
| 13 |
+
RUN apt-get update && apt-get install -y --no-install-recommends \
|
| 14 |
+
apache2-utils \
|
| 15 |
+
ca-certificates \
|
| 16 |
+
chromium \
|
| 17 |
+
dbus-x11 \
|
| 18 |
+
fonts-liberation \
|
| 19 |
+
fonts-noto-cjk \
|
| 20 |
+
fonts-noto-color-emoji \
|
| 21 |
+
nginx \
|
| 22 |
+
novnc \
|
| 23 |
+
openbox \
|
| 24 |
+
supervisor \
|
| 25 |
+
tini \
|
| 26 |
+
websockify \
|
| 27 |
+
x11-utils \
|
| 28 |
+
x11vnc \
|
| 29 |
+
xvfb \
|
| 30 |
&& rm -rf /var/lib/apt/lists/*
|
| 31 |
|
| 32 |
+
RUN useradd --create-home --uid 1000 --shell /bin/bash user \
|
| 33 |
+
&& mkdir -p /home/user/app /home/user/nginx /home/user/browser-data \
|
| 34 |
+
&& chown -R user:user /home/user/app /home/user/nginx /home/user/browser-data
|
| 35 |
+
|
| 36 |
+
WORKDIR /home/user/app
|
| 37 |
+
|
| 38 |
+
COPY --chown=user:user nginx.conf supervisord.conf start.sh ./
|
| 39 |
+
COPY --chown=user:user scripts ./scripts
|
| 40 |
+
COPY --chown=user:user README.md ./README.md
|
| 41 |
+
|
| 42 |
+
RUN chmod 0755 /home/user/app/start.sh /home/user/app/scripts/*.sh
|
| 43 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 44 |
USER user
|
|
|
|
| 45 |
|
| 46 |
EXPOSE 7860
|
| 47 |
|
| 48 |
+
ENTRYPOINT ["/usr/bin/tini", "--"]
|
| 49 |
+
CMD ["/home/user/app/start.sh"]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
README.md
CHANGED
|
@@ -1,10 +1,207 @@
|
|
| 1 |
---
|
| 2 |
-
title:
|
| 3 |
-
emoji:
|
| 4 |
-
colorFrom:
|
| 5 |
-
colorTo:
|
| 6 |
sdk: docker
|
|
|
|
| 7 |
pinned: false
|
| 8 |
---
|
| 9 |
|
| 10 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
---
|
| 2 |
+
title: Private Manual Browser
|
| 3 |
+
emoji: 🖥️
|
| 4 |
+
colorFrom: gray
|
| 5 |
+
colorTo: blue
|
| 6 |
sdk: docker
|
| 7 |
+
app_port: 7860
|
| 8 |
pinned: false
|
| 9 |
---
|
| 10 |
|
| 11 |
+
# Private Manual Browser — Hugging Face Docker Space
|
| 12 |
+
|
| 13 |
+
這是一個只供帳號本人操作的瀏覽器 Space:
|
| 14 |
+
|
| 15 |
+
```text
|
| 16 |
+
Chromium → Xvfb → x11vnc → websockify/noVNC → Nginx :7860
|
| 17 |
+
```
|
| 18 |
+
|
| 19 |
+
用途是讓使用者透過瀏覽器開啟 Hugging Face Space,手動操作遠端 Chromium。它不會自動解 CAPTCHA、不會自動接受條款,也不包含 OpenAI API Bridge。
|
| 20 |
+
|
| 21 |
+
## 必要 Secrets
|
| 22 |
+
|
| 23 |
+
在 **Space → Settings → Variables and secrets → Secrets** 建立:
|
| 24 |
+
|
| 25 |
+
| Secret | 說明 |
|
| 26 |
+
|---|---|
|
| 27 |
+
| `BROWSER_USERNAME` | noVNC 網頁的 HTTP Basic Auth 使用者名稱。 |
|
| 28 |
+
| `BROWSER_PASSWORD` | 強隨機密碼,建議至少 24 個字元。 |
|
| 29 |
+
|
| 30 |
+
產生密碼:
|
| 31 |
+
|
| 32 |
+
```bash
|
| 33 |
+
python -c "import secrets; print(secrets.token_urlsafe(32))"
|
| 34 |
+
```
|
| 35 |
+
|
| 36 |
+
不要把 Google、Arena 或其他網站密碼設定為 `BROWSER_PASSWORD`。
|
| 37 |
+
|
| 38 |
+
## 建議 Variables
|
| 39 |
+
|
| 40 |
+
| Variable | 預設值 | 說明 |
|
| 41 |
+
|---|---:|---|
|
| 42 |
+
| `BROWSER_WIDTH` | `1920` | 虛擬桌面寬度,640–3840。 |
|
| 43 |
+
| `BROWSER_HEIGHT` | `1080` | 虛擬桌面高度,640–2160。 |
|
| 44 |
+
| `START_URL` | `https://arena.ai/text/direct` | Chromium 啟動頁面。 |
|
| 45 |
+
|
| 46 |
+
資源較少時可使用:
|
| 47 |
+
|
| 48 |
+
```text
|
| 49 |
+
BROWSER_WIDTH=1366
|
| 50 |
+
BROWSER_HEIGHT=768
|
| 51 |
+
```
|
| 52 |
+
|
| 53 |
+
## 部署
|
| 54 |
+
|
| 55 |
+
Space repository 根目錄:
|
| 56 |
+
|
| 57 |
+
```text
|
| 58 |
+
Dockerfile
|
| 59 |
+
README.md
|
| 60 |
+
nginx.conf
|
| 61 |
+
supervisord.conf
|
| 62 |
+
start.sh
|
| 63 |
+
scripts/
|
| 64 |
+
launch-browser.sh
|
| 65 |
+
launch-nginx.sh
|
| 66 |
+
launch-openbox.sh
|
| 67 |
+
launch-x11vnc.sh
|
| 68 |
+
```
|
| 69 |
+
|
| 70 |
+
建立 Docker Space、上傳檔案、設定兩個必要 Secrets,然後 Factory Rebuild。
|
| 71 |
+
|
| 72 |
+
## 開啟瀏覽器
|
| 73 |
+
|
| 74 |
+
造訪 Space 的直接網址:
|
| 75 |
+
|
| 76 |
+
```text
|
| 77 |
+
https://YOUR-SPACE.hf.space/
|
| 78 |
+
```
|
| 79 |
+
|
| 80 |
+
瀏覽器會要求 HTTP Basic Auth:
|
| 81 |
+
|
| 82 |
+
```text
|
| 83 |
+
Username: BROWSER_USERNAME
|
| 84 |
+
Password: BROWSER_PASSWORD
|
| 85 |
+
```
|
| 86 |
+
|
| 87 |
+
成功後會進入 noVNC,並自動連接遠端桌面。可使用 noVNC 左側控制列調整縮放、全螢幕及剪貼簿。
|
| 88 |
+
|
| 89 |
+
## 持久化 Chrome Profile
|
| 90 |
+
|
| 91 |
+
如果 Space 已附加 Hugging Face Persistent Storage,程式會使用:
|
| 92 |
+
|
| 93 |
+
```text
|
| 94 |
+
/data/manual-browser/chromium-profile
|
| 95 |
+
```
|
| 96 |
+
|
| 97 |
+
其中包含:
|
| 98 |
+
|
| 99 |
+
- Cookies
|
| 100 |
+
- Local Storage
|
| 101 |
+
- 登入 Session
|
| 102 |
+
- 瀏覽器設定
|
| 103 |
+
- 網站權限
|
| 104 |
+
- 歷史紀錄
|
| 105 |
+
|
| 106 |
+
如果 `/data` 不存在,會改用:
|
| 107 |
+
|
| 108 |
+
```text
|
| 109 |
+
/home/user/browser-data/chromium-profile
|
| 110 |
+
```
|
| 111 |
+
|
| 112 |
+
並在 Logs 顯示 profile 是暫存的;容器重啟後可能遺失。
|
| 113 |
+
|
| 114 |
+
## 安全要求
|
| 115 |
+
|
| 116 |
+
1. **強烈建議使用 Private Space。** Basic Auth 是第二層保護,不應取代 Hugging Face 存取控制。
|
| 117 |
+
2. 使用獨立、強隨機的 `BROWSER_PASSWORD`。
|
| 118 |
+
3. 不要分享 Space URL 或密碼。
|
| 119 |
+
4. `/data` 內的 Chromium profile 等同登入憑證,不能公開或下載分享。
|
| 120 |
+
5. 不要在多人共用 Space 中登入私人 Google 帳號。
|
| 121 |
+
6. 不使用時應 Pause Space;需要撤銷所有 Session 時,刪除 `/data/manual-browser/chromium-profile`。
|
| 122 |
+
7. `x11vnc` 與 `websockify` 只監聽容器內的 `127.0.0.1`,外部只能經過 Nginx Basic Auth。
|
| 123 |
+
8. Chromium 在容器中使用 `--no-sandbox`,因此只能在受控的 Private Space 中操作可信網站。
|
| 124 |
+
|
| 125 |
+
## Google 登入
|
| 126 |
+
|
| 127 |
+
這是由使用者本人操作的可見 Chromium,不是自動輸入帳密的腳本。但 Google 仍可能因資料中心 IP、新裝置、Chromium 環境或帳號政策要求:
|
| 128 |
+
|
| 129 |
+
- MFA/2FA
|
| 130 |
+
- 裝置確認
|
| 131 |
+
- CAPTCHA
|
| 132 |
+
- 拒絕登入
|
| 133 |
+
|
| 134 |
+
請由帳號本人處理;本專案不會繞過 Google 安全驗證。如果 Google 拒絕此環境,請改用自己電腦的一般 Chrome 建立 Arena Storage State。
|
| 135 |
+
|
| 136 |
+
## Health Check
|
| 137 |
+
|
| 138 |
+
不需認證的程序存活端點:
|
| 139 |
+
|
| 140 |
+
```text
|
| 141 |
+
https://YOUR-SPACE.hf.space/healthz
|
| 142 |
+
```
|
| 143 |
+
|
| 144 |
+
回傳:
|
| 145 |
+
|
| 146 |
+
```json
|
| 147 |
+
{"status":"alive"}
|
| 148 |
+
```
|
| 149 |
+
|
| 150 |
+
它只表示 Nginx 存活,不代表 Chromium 已登入任何網站。
|
| 151 |
+
|
| 152 |
+
## Cronitor
|
| 153 |
+
|
| 154 |
+
可監控:
|
| 155 |
+
|
| 156 |
+
```text
|
| 157 |
+
GET https://YOUR-SPACE.hf.space/healthz
|
| 158 |
+
```
|
| 159 |
+
|
| 160 |
+
Assertions:
|
| 161 |
+
|
| 162 |
+
```text
|
| 163 |
+
response.code = 200
|
| 164 |
+
response.body contains "alive"
|
| 165 |
+
```
|
| 166 |
+
|
| 167 |
+
監控請求可能喚醒 Space,但不能保證 Hugging Face 免費 Space 永不休眠。
|
| 168 |
+
|
| 169 |
+
## 常見問題
|
| 170 |
+
|
| 171 |
+
### 401 Unauthorized
|
| 172 |
+
|
| 173 |
+
確認 `BROWSER_USERNAME`、`BROWSER_PASSWORD` 是 Secrets,修改後 Restart/Factory Rebuild。
|
| 174 |
+
|
| 175 |
+
### 黑畫面
|
| 176 |
+
|
| 177 |
+
等待 10–20 秒後重新整理;檢查 Logs 中 Xvfb、Openbox、Chromium、x11vnc 是否都進入 RUNNING。
|
| 178 |
+
|
| 179 |
+
### noVNC 顯示 WebSocket disconnected
|
| 180 |
+
|
| 181 |
+
確認 Nginx、websockify、x11vnc 都在運行,並使用根網址自動產生的 `path=websockify`。
|
| 182 |
+
|
| 183 |
+
### 重啟後登出
|
| 184 |
+
|
| 185 |
+
確認 Space 已附加 Persistent Storage,Logs 應顯示:
|
| 186 |
+
|
| 187 |
+
```text
|
| 188 |
+
Browser profile: persistent /data/manual-browser/chromium-profile
|
| 189 |
+
```
|
| 190 |
+
|
| 191 |
+
### 清除所有登入狀態
|
| 192 |
+
|
| 193 |
+
在 Space 停止後刪除:
|
| 194 |
+
|
| 195 |
+
```text
|
| 196 |
+
/data/manual-browser/chromium-profile
|
| 197 |
+
```
|
| 198 |
+
|
| 199 |
+
再重新啟動。這會登出所有網站並清除瀏覽器資料。
|
| 200 |
+
|
| 201 |
+
## 限��
|
| 202 |
+
|
| 203 |
+
- 這是互動式遠端瀏覽器,不是高效能桌面。
|
| 204 |
+
- 音訊、視訊、WebGL 與硬體加速可能受限。
|
| 205 |
+
- 免費 Space 可能休眠。
|
| 206 |
+
- Persistent Storage 需要 Hugging Face 支援的儲存方案。
|
| 207 |
+
- 本專案不會自動化 CAPTCHA、MFA、OAuth 或法律條款同意。
|
nginx.conf
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
worker_processes 1;
|
| 2 |
+
pid /tmp/nginx.pid;
|
| 3 |
+
error_log /dev/stderr info;
|
| 4 |
+
|
| 5 |
+
events {
|
| 6 |
+
worker_connections 512;
|
| 7 |
+
}
|
| 8 |
+
|
| 9 |
+
http {
|
| 10 |
+
include /etc/nginx/mime.types;
|
| 11 |
+
default_type application/octet-stream;
|
| 12 |
+
access_log /dev/stdout;
|
| 13 |
+
sendfile on;
|
| 14 |
+
keepalive_timeout 65;
|
| 15 |
+
|
| 16 |
+
client_body_temp_path /tmp/nginx-client;
|
| 17 |
+
proxy_temp_path /tmp/nginx-proxy;
|
| 18 |
+
|
| 19 |
+
map $http_upgrade $connection_upgrade {
|
| 20 |
+
default upgrade;
|
| 21 |
+
'' close;
|
| 22 |
+
}
|
| 23 |
+
|
| 24 |
+
server {
|
| 25 |
+
listen 7860;
|
| 26 |
+
server_name _;
|
| 27 |
+
server_tokens off;
|
| 28 |
+
|
| 29 |
+
auth_basic "Private browser";
|
| 30 |
+
auth_basic_user_file /home/user/.browser.htpasswd;
|
| 31 |
+
|
| 32 |
+
add_header X-Content-Type-Options nosniff always;
|
| 33 |
+
add_header Referrer-Policy no-referrer always;
|
| 34 |
+
add_header Cache-Control "no-store" always;
|
| 35 |
+
|
| 36 |
+
location = /healthz {
|
| 37 |
+
auth_basic off;
|
| 38 |
+
default_type application/json;
|
| 39 |
+
return 200 '{"status":"alive"}';
|
| 40 |
+
}
|
| 41 |
+
|
| 42 |
+
location = / {
|
| 43 |
+
return 302 /vnc.html?autoconnect=true&resize=scale&path=websockify;
|
| 44 |
+
}
|
| 45 |
+
|
| 46 |
+
location = /websockify {
|
| 47 |
+
proxy_pass http://127.0.0.1:6080;
|
| 48 |
+
proxy_http_version 1.1;
|
| 49 |
+
proxy_set_header Upgrade $http_upgrade;
|
| 50 |
+
proxy_set_header Connection $connection_upgrade;
|
| 51 |
+
proxy_set_header Host $host;
|
| 52 |
+
proxy_read_timeout 86400s;
|
| 53 |
+
proxy_send_timeout 86400s;
|
| 54 |
+
proxy_buffering off;
|
| 55 |
+
}
|
| 56 |
+
|
| 57 |
+
location / {
|
| 58 |
+
root /usr/share/novnc;
|
| 59 |
+
try_files $uri $uri/ =404;
|
| 60 |
+
}
|
| 61 |
+
}
|
| 62 |
+
}
|
scripts/launch-browser.sh
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/bin/sh
|
| 2 |
+
set -eu
|
| 3 |
+
until xdpyinfo -display "${DISPLAY:-:99}" >/dev/null 2>&1; do
|
| 4 |
+
sleep 0.25
|
| 5 |
+
done
|
| 6 |
+
|
| 7 |
+
exec /usr/bin/chromium \
|
| 8 |
+
--no-sandbox \
|
| 9 |
+
--disable-dev-shm-usage \
|
| 10 |
+
--no-first-run \
|
| 11 |
+
--no-default-browser-check \
|
| 12 |
+
--password-store=basic \
|
| 13 |
+
--user-data-dir="${BROWSER_PROFILE}" \
|
| 14 |
+
--window-size="${BROWSER_WIDTH},${BROWSER_HEIGHT}" \
|
| 15 |
+
--start-maximized \
|
| 16 |
+
"${START_URL}"
|
scripts/launch-nginx.sh
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/bin/sh
|
| 2 |
+
set -eu
|
| 3 |
+
mkdir -p /tmp/nginx-client /tmp/nginx-proxy
|
| 4 |
+
exec /usr/sbin/nginx \
|
| 5 |
+
-p /home/user/nginx \
|
| 6 |
+
-c /home/user/app/nginx.conf \
|
| 7 |
+
-g 'daemon off;'
|
scripts/launch-openbox.sh
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/bin/sh
|
| 2 |
+
set -eu
|
| 3 |
+
until xdpyinfo -display "${DISPLAY:-:99}" >/dev/null 2>&1; do
|
| 4 |
+
sleep 0.25
|
| 5 |
+
done
|
| 6 |
+
exec openbox-session
|
scripts/launch-x11vnc.sh
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/bin/sh
|
| 2 |
+
set -eu
|
| 3 |
+
until xdpyinfo -display "${DISPLAY:-:99}" >/dev/null 2>&1; do
|
| 4 |
+
sleep 0.25
|
| 5 |
+
done
|
| 6 |
+
exec /usr/bin/x11vnc \
|
| 7 |
+
-display "${DISPLAY:-:99}" \
|
| 8 |
+
-localhost \
|
| 9 |
+
-nopw \
|
| 10 |
+
-forever \
|
| 11 |
+
-shared \
|
| 12 |
+
-repeat \
|
| 13 |
+
-noxdamage \
|
| 14 |
+
-rfbport 5900
|
start.sh
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/bin/sh
|
| 2 |
+
set -eu
|
| 3 |
+
|
| 4 |
+
: "${BROWSER_USERNAME:?Set BROWSER_USERNAME as a Hugging Face Space Secret}"
|
| 5 |
+
: "${BROWSER_PASSWORD:?Set BROWSER_PASSWORD as a Hugging Face Space Secret}"
|
| 6 |
+
|
| 7 |
+
case "${BROWSER_WIDTH:-1920}" in
|
| 8 |
+
''|*[!0-9]*) echo "BROWSER_WIDTH must be numeric" >&2; exit 64 ;;
|
| 9 |
+
esac
|
| 10 |
+
case "${BROWSER_HEIGHT:-1080}" in
|
| 11 |
+
''|*[!0-9]*) echo "BROWSER_HEIGHT must be numeric" >&2; exit 64 ;;
|
| 12 |
+
esac
|
| 13 |
+
|
| 14 |
+
if [ "${BROWSER_WIDTH}" -lt 640 ] || [ "${BROWSER_WIDTH}" -gt 3840 ]; then
|
| 15 |
+
echo "BROWSER_WIDTH must be between 640 and 3840" >&2
|
| 16 |
+
exit 64
|
| 17 |
+
fi
|
| 18 |
+
if [ "${BROWSER_HEIGHT}" -lt 640 ] || [ "${BROWSER_HEIGHT}" -gt 2160 ]; then
|
| 19 |
+
echo "BROWSER_HEIGHT must be between 640 and 2160" >&2
|
| 20 |
+
exit 64
|
| 21 |
+
fi
|
| 22 |
+
|
| 23 |
+
# Use paid Hugging Face persistent storage when /data is writable; otherwise
|
| 24 |
+
# fall back to ephemeral container storage and warn clearly.
|
| 25 |
+
if [ -d /data ] && [ -w /data ]; then
|
| 26 |
+
BROWSER_PROFILE=/data/manual-browser/chromium-profile
|
| 27 |
+
mkdir -p /data/manual-browser "$BROWSER_PROFILE"
|
| 28 |
+
chmod 700 /data/manual-browser "$BROWSER_PROFILE" 2>/dev/null || true
|
| 29 |
+
echo "Browser profile: persistent /data/manual-browser/chromium-profile"
|
| 30 |
+
else
|
| 31 |
+
BROWSER_PROFILE=/home/user/browser-data/chromium-profile
|
| 32 |
+
mkdir -p "$BROWSER_PROFILE"
|
| 33 |
+
chmod 700 "$BROWSER_PROFILE"
|
| 34 |
+
echo "WARNING: /data is unavailable; browser profile is ephemeral."
|
| 35 |
+
fi
|
| 36 |
+
|
| 37 |
+
export BROWSER_PROFILE
|
| 38 |
+
export START_URL="${START_URL:-https://arena.ai/text/direct}"
|
| 39 |
+
export XDG_RUNTIME_DIR=/tmp/runtime-user
|
| 40 |
+
mkdir -p "$XDG_RUNTIME_DIR"
|
| 41 |
+
chmod 700 "$XDG_RUNTIME_DIR"
|
| 42 |
+
|
| 43 |
+
# Read the password through stdin so it is not exposed in the htpasswd process argv.
|
| 44 |
+
printf '%s\n' "$BROWSER_PASSWORD" | htpasswd -iBc /home/user/.browser.htpasswd "$BROWSER_USERNAME" >/dev/null
|
| 45 |
+
chmod 600 /home/user/.browser.htpasswd
|
| 46 |
+
|
| 47 |
+
# Do not pass credentials to Chromium, noVNC, or other child processes.
|
| 48 |
+
unset BROWSER_PASSWORD BROWSER_USERNAME
|
| 49 |
+
|
| 50 |
+
exec /usr/bin/supervisord -n -c /home/user/app/supervisord.conf
|
supervisord.conf
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
[supervisord]
|
| 2 |
+
nodaemon=true
|
| 3 |
+
logfile=/dev/null
|
| 4 |
+
pidfile=/tmp/supervisord.pid
|
| 5 |
+
childlogdir=/tmp
|
| 6 |
+
|
| 7 |
+
[program:xvfb]
|
| 8 |
+
command=/usr/bin/Xvfb :99 -screen 0 %(ENV_BROWSER_WIDTH)sx%(ENV_BROWSER_HEIGHT)sx24 -ac -nolisten tcp
|
| 9 |
+
autostart=true
|
| 10 |
+
autorestart=true
|
| 11 |
+
priority=10
|
| 12 |
+
startsecs=1
|
| 13 |
+
stopasgroup=true
|
| 14 |
+
killasgroup=true
|
| 15 |
+
stdout_logfile=/dev/fd/1
|
| 16 |
+
stdout_logfile_maxbytes=0
|
| 17 |
+
stderr_logfile=/dev/fd/2
|
| 18 |
+
stderr_logfile_maxbytes=0
|
| 19 |
+
|
| 20 |
+
[program:openbox]
|
| 21 |
+
command=/home/user/app/scripts/launch-openbox.sh
|
| 22 |
+
autostart=true
|
| 23 |
+
autorestart=true
|
| 24 |
+
priority=20
|
| 25 |
+
startsecs=1
|
| 26 |
+
stopasgroup=true
|
| 27 |
+
killasgroup=true
|
| 28 |
+
stdout_logfile=/dev/fd/1
|
| 29 |
+
stdout_logfile_maxbytes=0
|
| 30 |
+
stderr_logfile=/dev/fd/2
|
| 31 |
+
stderr_logfile_maxbytes=0
|
| 32 |
+
|
| 33 |
+
[program:chromium]
|
| 34 |
+
command=/home/user/app/scripts/launch-browser.sh
|
| 35 |
+
autostart=true
|
| 36 |
+
autorestart=true
|
| 37 |
+
priority=30
|
| 38 |
+
startsecs=3
|
| 39 |
+
stopasgroup=true
|
| 40 |
+
killasgroup=true
|
| 41 |
+
stdout_logfile=/dev/fd/1
|
| 42 |
+
stdout_logfile_maxbytes=0
|
| 43 |
+
stderr_logfile=/dev/fd/2
|
| 44 |
+
stderr_logfile_maxbytes=0
|
| 45 |
+
|
| 46 |
+
[program:x11vnc]
|
| 47 |
+
command=/home/user/app/scripts/launch-x11vnc.sh
|
| 48 |
+
autostart=true
|
| 49 |
+
autorestart=true
|
| 50 |
+
priority=40
|
| 51 |
+
startsecs=1
|
| 52 |
+
stopasgroup=true
|
| 53 |
+
killasgroup=true
|
| 54 |
+
stdout_logfile=/dev/fd/1
|
| 55 |
+
stdout_logfile_maxbytes=0
|
| 56 |
+
stderr_logfile=/dev/fd/2
|
| 57 |
+
stderr_logfile_maxbytes=0
|
| 58 |
+
|
| 59 |
+
[program:websockify]
|
| 60 |
+
command=/usr/bin/websockify 127.0.0.1:6080 127.0.0.1:5900
|
| 61 |
+
autostart=true
|
| 62 |
+
autorestart=true
|
| 63 |
+
priority=50
|
| 64 |
+
startsecs=1
|
| 65 |
+
stopasgroup=true
|
| 66 |
+
killasgroup=true
|
| 67 |
+
stdout_logfile=/dev/fd/1
|
| 68 |
+
stdout_logfile_maxbytes=0
|
| 69 |
+
stderr_logfile=/dev/fd/2
|
| 70 |
+
stderr_logfile_maxbytes=0
|
| 71 |
+
|
| 72 |
+
[program:nginx]
|
| 73 |
+
command=/home/user/app/scripts/launch-nginx.sh
|
| 74 |
+
autostart=true
|
| 75 |
+
autorestart=true
|
| 76 |
+
priority=60
|
| 77 |
+
startsecs=1
|
| 78 |
+
stopasgroup=true
|
| 79 |
+
killasgroup=true
|
| 80 |
+
stdout_logfile=/dev/fd/1
|
| 81 |
+
stdout_logfile_maxbytes=0
|
| 82 |
+
stderr_logfile=/dev/fd/2
|
| 83 |
+
stderr_logfile_maxbytes=0
|