From a99548e16ebf18c96347c953e70ae55c23e5d7ca Mon Sep 17 00:00:00 2001 From: "Khoa.vo" Date: Fri, 19 Dec 2025 16:50:54 +0700 Subject: [PATCH] Migrate to KasmVNC 1.3.1 (fixed deps) --- Dockerfile | 56 ++++++++++++++++++++++++++---------- frontend/src/pages/Login.tsx | 12 ++++---- supervisord.conf | 20 ++++--------- 3 files changed, 53 insertions(+), 35 deletions(-) diff --git a/Dockerfile b/Dockerfile index fba4d75..aa5c2e3 100644 --- a/Dockerfile +++ b/Dockerfile @@ -9,13 +9,15 @@ RUN npm run build # Production stage FROM python:3.11-slim -# Install system dependencies for Playwright, VNC, and noVNC +# Install system dependencies +# Combined list for Playwright, KasmVNC, and general utilities RUN apt-get update && apt-get install -y --no-install-recommends \ wget \ curl \ gnupg \ ca-certificates \ ffmpeg \ + openbox \ # Playwright dependencies libnss3 \ libnspr4 \ @@ -35,27 +37,49 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ libatspi2.0-0 \ libgtk-3-0 \ fonts-liberation \ - # VNC and display - xvfb \ - xauth \ - x11vnc \ + # KasmVNC dependencies + libjpeg62-turbo \ + libpng16-16 \ + libx11-6 \ + libxcursor1 \ + libxext6 \ + libxi6 \ + libxinerama1 \ + libxrender1 \ + libxtst6 \ + zlib1g \ + libssl3 \ + adduser \ + libfontconfig1 \ + libgl1 \ + libpixman-1-0 \ + libxfont2 \ + libxkbfile1 \ + xfonts-base \ + xfonts-75dpi \ + xfonts-100dpi \ + python3-yaml \ supervisor \ - # noVNC dependencies - python3-numpy \ && rm -rf /var/lib/apt/lists/* -# Install noVNC -RUN mkdir -p /opt/noVNC/utils/websockify \ - && wget -qO- https://github.com/novnc/noVNC/archive/refs/tags/v1.4.0.tar.gz | tar xz --strip 1 -C /opt/noVNC \ - && wget -qO- https://github.com/novnc/websockify/archive/refs/tags/v0.11.0.tar.gz | tar xz --strip 1 -C /opt/noVNC/utils/websockify \ - && ln -s /opt/noVNC/vnc.html /opt/noVNC/index.html +# Install KasmVNC (Debian Bookworm) +RUN wget -q https://github.com/kasmtech/KasmVNC/releases/download/v1.3.1/kasmvncserver_bookworm_1.3.1_amd64.deb -O /tmp/kasmvnc.deb \ + && apt-get update \ + && apt-get install -y --no-install-recommends /tmp/kasmvnc.deb \ + && rm /tmp/kasmvnc.deb \ + && rm -rf /var/lib/apt/lists/* + +# Setup KasmVNC user +# KasmVNC requires a non-root user for security best practices, but we run as root in this simple container. +# We will run vncserver as root (not recommended but easiest for migration) or create a user. +# Let's try running as root first with specific flags. WORKDIR /app # Copy backend requirements and install COPY backend/requirements.txt ./ RUN pip install --no-cache-dir -r requirements.txt -# Install Playwright browsers with retries +# Install Playwright browsers RUN mkdir -p /root/.cache/ms-playwright && \ for i in 1 2 3; do \ playwright install chromium && break || \ @@ -78,16 +102,18 @@ COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf ENV PYTHONUNBUFFERED=1 ENV CACHE_DIR=/app/cache ENV DISPLAY=:99 +# KasmVNC envs +ENV KASM_VNC_ARGS="-httpport 6080 -FrameRate 60 -sslOnly 0" # Set working directory to backend for correct imports WORKDIR /app/backend -# Expose ports (8002 = app, 6080 = noVNC) +# Expose ports (8002 = app, 6080 = KasmVNC) EXPOSE 8002 6080 # Health check HEALTHCHECK --interval=30s --timeout=10s --start-period=60s --retries=3 \ CMD curl -f http://localhost:8002/health || exit 1 -# Start services using supervisor +# Start services CMD ["/usr/bin/supervisord", "-c", "/etc/supervisor/conf.d/supervisord.conf"] diff --git a/frontend/src/pages/Login.tsx b/frontend/src/pages/Login.tsx index f309f05..2b92370 100644 --- a/frontend/src/pages/Login.tsx +++ b/frontend/src/pages/Login.tsx @@ -35,8 +35,8 @@ export const Login: React.FC = () => { const getVncUrl = () => { const host = window.location.hostname; - // autoconnect=true, resize=scale to fit, quality=9 for clear text - return `http://${host}:6080/vnc.html?autoconnect=true&resize=scale&quality=9`; + // KasmVNC params: autoconnect=1, resize=scale (fit to screen), negotiate items + return `http://${host}:6080/vnc.html?autoconnect=1&resize=scale&encrypt=0`; }; const handleVncLogin = async () => { @@ -180,8 +180,8 @@ export const Login: React.FC = () => { onClick={handleVncLogin} disabled={isLoading} className={`w-full py-4 rounded-2xl font-bold text-base flex items-center justify-center gap-3 transition-all ${isLoading - ? 'bg-gray-700 text-gray-400 cursor-not-allowed' - : 'bg-gradient-to-r from-pink-500 to-orange-500 text-white shadow-lg shadow-pink-500/25 hover:shadow-pink-500/40 active:scale-[0.98]' + ? 'bg-gray-700 text-gray-400 cursor-not-allowed' + : 'bg-gradient-to-r from-pink-500 to-orange-500 text-white shadow-lg shadow-pink-500/25 hover:shadow-pink-500/40 active:scale-[0.98]' }`} > {isLoading ? ( @@ -224,8 +224,8 @@ export const Login: React.FC = () => { onClick={handleManualLogin} disabled={!sessionId.trim() || isLoading} className={`w-full py-2.5 rounded-lg font-medium text-sm transition-all ${sessionId.trim() && !isLoading - ? 'bg-white/10 hover:bg-white/20 text-white' - : 'bg-white/5 text-gray-600 cursor-not-allowed' + ? 'bg-white/10 hover:bg-white/20 text-white' + : 'bg-white/5 text-gray-600 cursor-not-allowed' }`} > Connect diff --git a/supervisord.conf b/supervisord.conf index e07e8c2..40fde7c 100644 --- a/supervisord.conf +++ b/supervisord.conf @@ -4,8 +4,8 @@ logfile=/dev/stdout logfile_maxbytes=0 loglevel=info -[program:xvfb] -command=Xvfb :99 -screen 0 1920x1080x24 +[program:kasmvnc] +command=/usr/bin/vncserver -fg :99 -select-de -http-port 6080 -FrameRate 60 -SecurityTypes None -sslOnly 0 -geometry 1920x1080 autorestart=true priority=100 stdout_logfile=/dev/stdout @@ -13,8 +13,9 @@ stdout_logfile_maxbytes=0 stderr_logfile=/dev/stderr stderr_logfile_maxbytes=0 -[program:x11vnc] -command=x11vnc -display :99 -forever -shared -rfbport 5900 -nopw -xkb +[program:openbox] +command=openbox +environment=DISPLAY=":99" autorestart=true priority=200 stdout_logfile=/dev/stdout @@ -22,21 +23,12 @@ stdout_logfile_maxbytes=0 stderr_logfile=/dev/stderr stderr_logfile_maxbytes=0 -[program:novnc] -command=/opt/noVNC/utils/novnc_proxy --vnc localhost:5900 --listen 6080 -autorestart=true -priority=300 -stdout_logfile=/dev/stdout -stdout_logfile_maxbytes=0 -stderr_logfile=/dev/stderr -stderr_logfile_maxbytes=0 - [program:app] command=python -m uvicorn main:app --host 0.0.0.0 --port 8002 directory=/app/backend environment=DISPLAY=":99",PYTHONUNBUFFERED="1" autorestart=true -priority=400 +priority=300 stdout_logfile=/dev/stdout stdout_logfile_maxbytes=0 stderr_logfile=/dev/stderr