diff --git a/backend/Dockerfile b/backend/Dockerfile index 0d810ed..e59aa13 100644 --- a/backend/Dockerfile +++ b/backend/Dockerfile @@ -7,6 +7,7 @@ RUN apt-get update && apt-get install -y \ libpq-dev \ postgresql-client \ curl \ + xvfb \ && rm -rf /var/lib/apt/lists/* COPY requirements.txt . @@ -19,4 +20,6 @@ COPY . . EXPOSE 8000 -CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"] +ENV DISPLAY=:99 + +CMD ["sh", "-c", "Xvfb :99 -screen 0 1280x720x24 -nolisten tcp & sleep 1 && uvicorn main:app --host 0.0.0.0 --port 8000"] diff --git a/backend/services/scraper_backends/playwright_local.py b/backend/services/scraper_backends/playwright_local.py index cb54fc7..4ed99ea 100644 --- a/backend/services/scraper_backends/playwright_local.py +++ b/backend/services/scraper_backends/playwright_local.py @@ -56,8 +56,8 @@ class PlaywrightLocalBackend(ScraperBackend): Local Playwright backend using Chromium. Stealth measures: - - Runs headful (via xvfb in the container) — headless leaks SwiftShader - WebGL, empty plugins, missing chrome.runtime + - Runs headful (via Xvfb in the container) — headless leaks SwiftShader + WebGL, empty plugins, missing chrome.runtime; Xvfb needs shm_size 256m - playwright-stealth patches navigator.webdriver, plugins, WebGL vendor - ONE consistent modern-Chrome identity: UA + matching sec-ch-ua client hints + platform (a mismatched UA is worse than none) @@ -159,17 +159,13 @@ class PlaywrightLocalBackend(ScraperBackend): if self._playwright is None: self._playwright = await async_playwright().start() launch_kwargs = dict( - # Headless — stealth patches + residential proxy + session - # cookies cover the fingerprint; headed+xvfb is unreliable - # in Proxmox LXC kernels where Xvfb exits immediately. - headless=True, + headless=False, args=[ '--disable-blink-features=AutomationControlled', '--no-sandbox', '--disable-dev-shm-usage', '--disable-features=IsolateOrigins,site-per-process', - '--disable-gpu', - '--enable-unsafe-swiftshader', + '--start-maximized', ], ) # Proxy is set at launch (Chromium binds the sticky session, which diff --git a/docker-compose.yml b/docker-compose.yml index 19d0130..c981fe0 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -3,6 +3,7 @@ services: build: ./backend security_opt: - apparmor=unconfined + shm_size: '256m' environment: - DATABASE_URL=${DATABASE_URL} - CENTRAL_AUTH_SECRET=${CENTRAL_AUTH_SECRET}