VPS-ல் Headless Browser இயக்குவது எப்படி?
VPS-ல் Headless Chromium இயக்கும்போது ஏற்படும் /dev/shm பிழைகள், sandbox flags மற்றும் missing fonts சிக்கல்களைத் தவிர்க்கத் தேவையான கட்டமைப்பு முறைகளை இந்த வழிகாட்டி விளக்குகிறது.
நீங்கள் இயக்குவது என்ன
VPS-ல் உள்ள headless browser என்பது விண்டோ இல்லாத Chromium ஆகும்; இது மனிதருக்குப் பதிலாக உங்கள் குறியீட்டின் மூலம் இயக்கப்படுகிறது. சர்வரில் இது ஒரு நீண்ட காலம் இயங்கும் process tree ஆகும்; உங்கள் ஏஜென்ட் இதனுடன் local socket வழியாகத் தொடர்பு கொள்கிறது. இதை நிறுவுவதற்கு ஒரு கட்டளை மட்டுமே தேவை. அதன் பிறகு செய்யும் வேலைகளே முக்கியமானவை. பிரவுசர் கணினியிலிருந்து எவ்வளவு வளங்களைப் பயன்படுத்தலாம் என்பதை நீங்கள் கட்டுப்படுத்த வேண்டும், மேலும் அதன் control endpoint-ஐ பொது இணையத்திலிருந்து மறைத்து வைக்க வேண்டும்.
இந்த வழிகாட்டி, நீங்கள் ஏற்கனவே ஒரு கருவியைத் தேர்ந்தெடுத்துவிட்டீர்கள் என்றும், இப்போது அதை இயக்க வேண்டும் என்றும் கருதுகிறது. நீங்கள் இன்னும் crawlers மற்றும் extractors-களை ஒப்பிட்டுக்கொண்டிருந்தால், self-hosted Firecrawl மாற்றுகள் என்பதைப் பார்த்துவிட்டு மீண்டும் இங்கே வரவும். கீழே உள்ள அனைத்தும் Playwright-ன் Chromium-ஐப் பயன்படுத்துகின்றன. ஏனெனில் Playwright தனது சொந்த பிரவுசர் build மற்றும் dependency installer-ஐக் கொண்டுள்ளது. எனவே, bare Ubuntu VPS மற்றும் container ஆகிய இரண்டிலும் ஒரே கட்டளைகள் வேலை செய்யும். ஆகஸ்ட் 2026 நிலவரப்படி பதிப்புகள் தற்போதைய நிலையில் உள்ளன.
Chromium-ஐ dependencies பற்றி கவலைப்படாமல் நிறுவுதல்
npm i -D playwright@1.62.0
npx playwright install --with-deps chromium--with-deps, Chromium-க்குத் தேவையான shared libraries மற்றும் fonts-க்காக apt-ஐ இயக்குகிறது, மேலும் தேவைப்படும்போது root அனுமதியைக் கேட்கிறது. Browser build-ஆனது கட்டளையை இயக்கும் பயனருக்காக ~/.cache/ms-playwright-ல் பதிவிறக்கம் செய்யப்படுகிறது. இது ஒரு server-ல் முக்கியமானது, ஏனெனில் service user என்பது பொதுவாக நீங்கள் login செய்யும் பயனர் அல்ல. sudo npx playwright install-deps chromium-ஐப் பயன்படுத்தி ஒருமுறை நிர்வாகியாக system packages-ஐ நிறுவவும், பின்னர் install கட்டளை மற்றும் service unit ஆகிய இரண்டிலும் PLAYWRIGHT_BROWSERS_PATH=/opt/pw-browsers-ஐ அமைக்கவும், இதன் மூலம் ஒரு நகல் பகிரப்படும். Browser-ஐ அணுக முடியாத ஒரு service, அது தேடிய பாதையைக் குறிப்பிட்டு பிழைச் செய்தியுடன் தொடக்கத்திலேயே தோல்வியடையும்.
Playwright version-ஐ pin செய்யவும். ஒவ்வொரு release-ம் ஒரு குறிப்பிட்ட browser build-உடன் இணைக்கப்பட்டிருக்கும், எனவே pin செய்யப்படாத npm update, இயங்கிக்கொண்டிருக்கும் service-ல் browser-ஐ மாற்றக்கூடும். ஆகஸ்ட் 2026 நிலவரப்படி Playwright 1.62 தற்போதைய பதிப்பாகும்.
இரண்டு Chromium builds உள்ளன, அவை ஒரே நிரல் அல்ல. இயல்புநிலை பதிவிறக்கம் என்பது headless shell ஆகும், இது headless முறையில் மட்டுமே இயங்கக்கூடிய சிறிய binary ஆகும், மேலும் npx playwright install --with-deps --only-shell அதை மட்டும் நிறுவுகிறது. chromium channel மூலம் நீங்கள் முழுமையான browser-ஐப் பெறலாம், இதை Playwright-ன் browser ஆவணங்கள் "உண்மையான Chrome browser, எனவே இது அதிக நம்பகத்தன்மை கொண்டது, துல்லியமானது மற்றும் கூடுதல் அம்சங்களை வழங்குகிறது" என்று குறிப்பிடுகின்றன. மொத்தமாகத் தரவுகளைப் பெற (bulk fetching) shell-ஐப் பயன்படுத்தவும். ஒரு தளம் வித்தியாசமாகச் செயல்படும்போது, அதற்கான காரணத்தைக் கண்டறிய முழுமையான browser-ஐப் பயன்படுத்தவும்.
headless browser ஏன் container-ல் செயலிழக்கிறது
Docker ஒவ்வொரு container-க்கும் 64 MB /dev/shm-ஐ வழங்குகிறது. Docker ஆவணங்கள் இதைத் தெளிவாகக் குறிப்பிடுகின்றன: "நீங்கள் அளவை குறிப்பிடவில்லை என்றால், கணினி 64m-ஐப் பயன்படுத்தும்". Chromium தனது process-களுக்கு இடையே உள்ள rendered content-ஐ அந்தப் பகிரப்பட்ட நினைவகப் பகுதி வழியாகவே பரிமாறிக் கொள்கிறது, எனவே ஒரு கனமான பக்கம் அதை எளிதில் நிரப்பிவிடும். இதனால் renderer செயலிழந்து, உங்கள் laptop-ல் சரியாக இயங்கும் பக்கம், உங்கள் client-ல் crashed target என்று காட்டும். எதையும் மாற்றும் முன் container-க்குள் இருந்து அந்த அளவை உறுதிப்படுத்தவும்.
df -h /dev/shmஇதற்கு இரண்டு உண்மையான தீர்வுகள் உள்ளன, இவை ஒன்றையொன்று மாற்றாகப் பயன்படுத்தக்கூடியவை, ஒன்றாகப் பயன்படுத்த வேண்டியவை அல்ல. --ipc=host, container-ஐ host-ன் IPC namespace-க்குள் வைக்கிறது, எனவே அது host-ன் /dev/shm-ஐப் பயன்படுத்தும், இது பொதுவாக RAM-ன் பாதியளவு இருக்கும். Playwright-ன் Docker வழிகாட்டி இதைப் பரிந்துரைக்கிறது, ஏனெனில் இது இல்லையெனில் "Chromium நினைவகம் தீர்ந்து செயலிழக்கக்கூடும்". இதன் விலை என்னவென்றால், container மற்றும் host-க்கு இடையிலான IPC தனிமைப்படுத்தலை (isolation) நீங்கள் இழக்கிறீர்கள். --shm-size=1g, private namespace-ஐ அப்படியே வைத்துக்கொண்டு, mount அளவை மட்டும் அதிகரிக்கிறது.
docker run --rm -it --init --ipc=host --user pwuser mcr.microsoft.com/playwright:v1.62.0-noble /bin/bash--disable-dev-shm-usage என்ற flag பெரும்பாலான தேடல் முடிவுகளில் காணப்படும் தீர்வாகும், ஆனால் அது வேறு ஒன்றைச் செய்கிறது: அது அந்த files-ஐ /dev/shm-லிருந்து ஒரு தற்காலிக directory-க்கு நகர்த்துகிறது. /tmp வட்டில் (disk) இருந்தால், நீங்கள் செயலிழப்பைத் தவிர்த்துவிட்டு, மெதுவான rendering மற்றும் disk write-களைப் பெறுகிறீர்கள். /tmp ஒரு tmpfs ஆக இருந்தால், தரவு மீண்டும் RAM-க்குச் சென்றுவிடும், அங்கு அளவு வரம்பு இருக்காது; இது ஒரு browser சிறிய VPS-ஐ முழுவதுமாக ஆக்கிரமிக்க ஒரு வழியாகும். அதற்குப் பதிலாக /dev/shm-ஐச் சரியாக அளவு நிர்ணயம் செய்யவும்.
--no-sandbox என்பதன் உண்மையான விளைவுகள்
Chromium ஒவ்வொரு renderer-ஐயும் Linux user namespaces-ஐ அடிப்படையாகக் கொண்ட ஒரு sandbox-க்குள் தனிமைப்படுத்துகிறது. அந்த sandbox தான் ஒரு ஆபத்தான இணையப்பக்கத்திற்கும் உங்கள் server-க்கும் இடையிலான பாதுகாப்பு எல்லை. அது தொடங்கத் தவறும்போது, Chromium இயங்க மறுத்துவிடும், மேலும் log-ல் இது போன்ற ஒரு வரி இடம்பெறும்:
Failed to move to new namespace: PID namespaces supported, Network namespace supported, but failed: errno = Operation not permittedஇதற்கு வழக்கமாக வழங்கப்படும் அறிவுரை --no-sandbox ஆகும். Chromium-ன் சொந்த பாதுகாப்பு ஆவணங்கள் இதன் விளைவை வெளிப்படையாகக் கூறுகின்றன: இந்த flag "Chromium-ன் முக்கியமான பாதுகாப்பு அம்சங்களை முடக்குகிறது, எனவே பொது இணையத்தில் உலாவும்போது இதை ஒருபோதும் பயன்படுத்தக்கூடாது". ஒரு link-ஐப் பின்தொடரும் agent, வரையறைப்படி பொது இணையத்தில் தான் உலாவுகிறது. எனவே, உண்மையான காரணத்தைக் கண்டறியவும்.
பெரும்பாலான சந்தர்ப்பங்களில் இரண்டு காரணங்களே இதற்குப் பொறுப்பாகின்றன. browser-ஐ root பயனர் மூலம் இயக்குவது sandbox-ஐ முடக்குகிறது, ஏனெனில் ஏற்கனவே உள்ள அதிகாரங்களை (privileges) அதனால் குறைக்க முடியாது. இதனால்தான் Playwright-ன் image pwuser என்ற சாதாரண பயனரை உள்ளடக்கியுள்ளது. Ubuntu 24.04 மற்றும் அதற்குப் பிந்தைய பதிப்புகளில், AppArmor unprivileged user namespaces-ஐக் கட்டுப்படுத்துகிறது. எந்தவொரு profile-லும் சேர்க்கப்படாத பாதையில் உள்ள Chromium binary-ஐ அது தடுக்கிறது. ~/.cache/ms-playwright-ன் கீழ் Playwright பதிவிறக்கம் செய்யும் பாதை இது போன்றதுதான். இரண்டையும் சரிபார்க்கவும்:
id -u
sysctl kernel.apparmor_restrict_unprivileged_userns
sudo dmesg | grep -i userns_createsysctl-லிருந்து கிடைக்கும் 1 மற்றும் apparmor="DENIED" operation="userns_create"-ஐக் கொண்ட kernel வரி ஆகியவை இரண்டாவது காரணத்தை உறுதிப்படுத்துகின்றன. அந்த ஒரு binary-ஐ மட்டும் /etc/apparmor.d/pw-chromium-ல் அனுமதிக்கவும், இது server-ல் உள்ள மற்ற அனைத்திற்கும் கட்டுப்பாட்டைத் தொடர்ந்து வைத்திருக்கும்:
abi <abi/4.0>,
include <tunables/global>
profile pw-chromium /home/*/.cache/ms-playwright/*/chrome-linux/{chrome,headless_shell} flags=(unconfined) {
userns,
}இதை sudo apparmor_parser -r /etc/apparmor.d/pw-chromium மூலம் ஏற்றவும். அந்தப் பாதையில் browser-ன் பதிப்பு எண் இருப்பதால், ஒவ்வொரு Playwright மேம்படுத்தலின் போதும் அது மாறும். மேலே உள்ள globs அந்த மாற்றத்தைத் தாங்கி நிற்கும். ஒரு குறிப்பிட்ட பாதையை மட்டும் வைத்து எழுதப்படும் profile, மேம்படுத்தலுக்குப் பிறகு பொருந்தாமல் போகும், இதனால் தொடர்பில்லாதது போல் தோன்றும் ஒரு update-க்குப் பிறகு browser மீண்டும் இயங்கத் தவறும்.
ஸ்கிரீன்ஷாட்கள் ஏன் காலியாகவோ அல்லது கட்டங்களாகவோ வருகின்றன
ஒரு ஸ்கிரீன்ஷாட் காலியாகவோ அல்லது முழுவதுமாக காலியான செவ்வகக் கட்டங்களாகவோ இருந்தால், அது பெரும்பாலும் ரெண்டரிங் பிழையை விட எழுத்துரு (font) தொடர்பான சிக்கலாகும். install-deps ஒரு அடிப்படை தொகுப்பை வழங்குகிறது: fonts-liberation, fonts-freefont-ttf, fonts-noto-color-emoji, fonts-unifont, fonts-ipafont-gothic (ஜப்பானிய மொழிக்கு), fonts-wqy-zenhei (சீன மொழிக்கு), fonts-tlwg-loma-otf (தாய் மொழிக்கு). இந்த தொகுப்பில் Noto CJK இல்லாததால், கொரிய மொழி மற்றும் பிற எழுத்துருக்கள் fontconfig கண்டறியும் ஏதேனும் ஒரு எழுத்துருவிற்கு மாறிவிடும். நீங்களாக ஊகிப்பதற்குப் பதிலாக fontconfig-ஐக் கேட்டு உறுதிப்படுத்தவும்:
fc-match "sans-serif:lang=ko"
fc-match "sans-serif:lang=ar"
fc-list | wc -lநீங்கள் பயன்படுத்தும் மொழி unifont அல்லது முறையான குறியீடுகள் (glyphs) இல்லாத ஒரு எழுத்துருவிற்கு மாறினால், fonts-noto-core மற்றும் fonts-noto-cjk ஆகியவற்றை நிறுவிவிட்டு, மீண்டும் சோதனையை இயக்கவும். Fontconfig தனது முடிவுகளை cache-ல் வைத்திருக்கும் என்பதால், எழுத்துருக்களை நிறுவிய பின் browser-ஐ மறுதொடக்கம் செய்யவும். எழுத்துருக்கள் ஏதுமில்லாத ஒரு stripped image, தொடக்கத்தின் போது Fontconfig error: Cannot load default config file என்று லாக் செய்யும் மற்றும் ஒவ்வொரு பக்கத்தையும் காலியாகவே காட்டும்.
Locale மற்றும் time zone ஆகியவை எழுத்துருக்களிலிருந்து வேறுபட்டவை; இவை பக்கத்தின் தோற்றத்தை மட்டுமல்லாமல், அதில் உள்ள தகவலையும் மாற்றும். ஒரு container-ல் பொதுவாக LANG அமைக்கப்படாமலும், TZ UTC-யிலும் இருக்கும். இதனால் தளங்கள் ஆங்கிலத்தில் தகவல்களை வழங்கும் மற்றும் UTC நேர முத்திரைகளை (timestamps) அச்சிடும். இதன் விளைவாக, அந்தந்த நாடுகளில் உள்ளவர்கள் பார்க்கும் நேரத்திலிருந்து உங்கள் agent காட்டும் நேரம் மாறுபடும். இவற்றை machine-க்கு அமைப்பதற்குப் பதிலாக, ஒவ்வொரு browser சூழலுக்கும் தனித்தனியாக அமைக்கவும். இதன் மூலம் ஒரே browser-ஐ வெவ்வேறு பிராந்தியங்களுக்கான பணிகளுக்குப் பயன்படுத்த முடியும்.
const context = await browser.newContext({
locale: 'en-GB',
timezoneId: 'Europe/Paris',
});Browser processes கசிவு ஏன் server-ல் swap-ஐ ஏற்படுத்துகிறது
"Zombie" என்ற பெயர் இரண்டு வெவ்வேறு சிக்கல்களைக் குறிக்கிறது. ஒரு உண்மையான zombie என்பது, அதன் parent process wait()-ஐ அழைக்காததால் முடிவடைந்த ஒரு process ஆகும். இது ஒரு PID entry-ஐ மட்டுமே வைத்திருக்கும், எனவே இது memory-ஐப் பயன்படுத்தாது. Browser-ஐ ஒரு container-ல் PID 1 ஆக இயக்கும்போது இவை உருவாகின்றன, ஏனெனில் PID 1-க்கு இயல்பான reaper கிடையாது. Docker-ன் --init flag, "signals-ஐ forward செய்து process-களை reap செய்யும்" ஒரு சிறிய init-ஐ இயக்குவதன் மூலம் இந்தச் சிக்கலைச் சரிசெய்கிறது. Compose-ல் இதையே init: true மூலம் செய்யலாம்.
உங்கள் server-ல் swap-ஐ ஏற்படுத்தும் கசிவு வேறுபட்டது: இவை யாரும் மூடாத, இயங்கிக்கொண்டிருக்கும் Chromium process-கள். newContext() மற்றும் close()-க்கு இடையே ஒரு task தோல்வியடையும்போதோ, அல்லது controlling script கொல்லப்பட்டு அதன் browser tree அனாதையாக விடப்படும்போதோ இது நிகழ்கிறது. ஒவ்வொரு request-க்கும் ஒரு புதிய browser-ஐத் தொடங்கும் குறியீடு (code) மிகவும் மோசமானது. அவற்றை எண்ணிப் பாருங்கள்:
pgrep -c -f 'headless_shell|chrome'
ps -eo pid,ppid,rss,etime,comm --sort=-rss | head -20ஒவ்வொரு task-க்கும் இடையில் அந்த எண்ணிக்கை அதன் idle மதிப்பிற்குத் திரும்ப வேண்டும். ஒரு நாள் முழுவதும் அது அதிகரித்துக் கொண்டே இருந்தால், அதற்கான தீர்வு launch flags-ல் இல்லை, உங்கள் குறியீட்டில்தான் உள்ளது: ஒரு finally block-ல் context-ஐ மூடுங்கள், SIGTERM-ல் browser-ஐ மூடுங்கள், மேலும் ஒரு மாதத்திற்கு இயக்குவதற்குப் பதிலாக, குறிப்பிட்ட எண்ணிக்கையிலான task-களுக்குப் பிறகு browser-ஐ recycle செய்யுங்கள். systemd-ன் கீழ், ஒரு stop அல்லது restart அந்த unit-ன் cgroup-ல் உள்ள அனைத்தையும் கொன்றுவிடும், எனவே sudo systemctl restart browser.service ஒரு நம்பகமான reset ஆகும். terminal multiplexer-க்குள் கைமுறையாகத் தொடங்கப்பட்ட browser-க்கு இத்தகைய உத்தரவாதம் இல்லை, அதன் அனாதை process-கள் session முடிந்த பிறகும் இயங்கிக்கொண்டிருக்கும்.
ஒரு browser context-க்கு எவ்வளவு RAM தேவைப்படுகிறது
"ஒரு browser" என்பது ஒரே ஒரு process அல்ல என்பதால், இந்தக் கேள்வியை துல்லியமாகக் கேட்க வேண்டும். Chromium ஒரு browser process, ஒரு GPU process, utility processes மற்றும் ஒவ்வொரு தளத்திற்கும் ஒரு renderer process ஆகியவற்றை இயக்குகிறது. Site isolation வசதியால், cross-site iframe-களுக்குத் தனித்தனி renderer-கள் ஒதுக்கப்படுகின்றன. ஒரு BrowserContext என்பது அதே மர அமைப்பிற்குள் இருக்கும் தனித்தனி cookie jar மற்றும் storage பகுதி என்பதால், இரண்டாவது context-க்கு மிகக் குறைந்த அளவே RAM தேவைப்படும். ஆனால், இரண்டாவது பக்கம் (page) என்பது அத்தனை எளிதானது அல்ல; ஏனெனில் அது புதிய renderer process-களைத் தொடங்கும், விளம்பரங்கள் நிறைந்த பக்கம் பல process-களை உருவாக்கும்.
எனவே, உங்கள் பணிச்சுமையின் கீழ் முழு மர அமைப்பிற்கும் தேவைப்படும் உச்சகட்ட (peak) நினைவக அளவைத்தான் நீங்கள் கணக்கிட வேண்டும். மற்றவர்களின் வலைப்பதிவில் உள்ள புள்ளிவிவரங்கள் இதற்கு உதவாது, ஏனெனில் உங்கள் agent எந்தெந்தப் பக்கங்களைத் திறக்கிறதோ, அதைப் பொறுத்தே இந்த அளவு அமையும். நீங்கள் பயன்படுத்தப்போகும் machine-ல், நீங்கள் அணுகப்போகும் தளங்களை வைத்து அளவீடு செய்யுங்கள்:
sudo systemd-run --unit=browser-probe -p MemoryMax=2G -p MemorySwapMax=0 -p WorkingDirectory=/srv/agent /usr/bin/node worker.js
systemctl status browser-probeUbuntu 24.04-ல், அந்த output-ல் உள்ள Memory: வரி, அந்த unit-ன் தற்போதைய மற்றும் உச்சகட்ட பயன்பாடு ஆகிய இரண்டையும் காட்டும். ஒரு நேரத்தில் ஒரு பக்கத்தை மட்டும் வைத்து worker-ஐ இயக்கவும், உச்சகட்ட அளவைக் குறித்துக்கொள்ளவும். பிறகு, இரண்டு பக்கங்களைத் திறந்து வைத்து, இரண்டாவது பக்கத்திற்கு உண்மையில் எவ்வளவு செலவாகிறது என்று பார்க்கவும். Concurrency-ஐக் கணக்கிடுவது எளிது: மொத்த RAM-ல், அந்த machine-ன் பிற தேவைகளுக்குத் தேவையானதைக் கழித்துவிட்டு, சில நூறு MB-ஐ உபரியாக வைத்துக்கொண்டு, மீதியை ஒரு worker-க்கான உச்சகட்ட அளவால் வகுக்கவும். இதற்கான machine-ஐத் தேர்வு செய்ய, agent VPS-க்கு எவ்வளவு RAM மற்றும் CPU தேவை என்பதைப் பார்க்கவும்.
இந்த அளவை இரண்டு இடங்களில் அமல்படுத்தவும். உங்கள் code-ல், fixed worker pool அல்லது semaphore-ஐப் பயன்படுத்தவும்; இதன் மூலம் agent கோரிக்கைகள் அதிகமாக வரும்போது, அவை வரிசைப்படுத்தப்படும் (queue), மாறாகப் புதிய browser-கள் திறக்கப்படாது. OS மட்டத்தில், cgroup limit-ஐப் பயன்படுத்தவும்; இதனால் queue-ல் ஏதேனும் பிழை ஏற்பட்டாலும், அது முழு machine-ஐயும் முடக்காது:
[Service]
MemoryMax=2G
MemorySwapMax=0
TasksMax=512
Restart=alwaysMemorySwapMax=0 என்பது பார்ப்பதை விட முக்கியமானது. இது இல்லையென்றால், limit-ஐ அடையும்போது cgroup பக்கங்களை swap-க்குத் தள்ளும். இதனால் machine இயங்கிக்கொண்டிருக்கும், ஆனால் ஒவ்வொரு கோரிக்கையும் மிக மெதுவாகச் செயல்படும்; இது ஒரு முழுமையான தோல்வியை விடக் கண்டறிவதற்கு கடினமானது. இதைச் சரியாக அமைத்தால், kernel அந்த cgroup-க்குள் இருக்கும் browser மரத்தை நிறுத்திவிடும், systemd அந்த unit-ஐ மீண்டும் தொடங்கும், மேலும் sshd தடையின்றி இயங்கும். Compose-ல் இதற்கான கட்டுப்பாடுகள் mem_limit, shm_size மற்றும் init ஆகும்; இவை Docker Compose-ல் memory limits அமைத்தல் பகுதியில் விளக்கப்பட்டுள்ளன.
Browser endpoint-ஐ பொது இணையத்திலிருந்து விலக்கி வைத்தல்
Playwright-ஐ ஒரு server-ஆக இயக்கி, உங்கள் agent-க்கு ஒரு WebSocket URL-ஐ வழங்க முடியும்:
const { chromium } = require('playwright');
const server = await chromium.launchServer({ port: 3000 });
console.log(server.wsEndpoint());அந்த endpoint-க்கு login வசதி கிடையாது. Playwright-ன் API ஆவணங்கள் இதைத் தெளிவாகக் குறிப்பிடுகின்றன: "wsPath-ஐ அறிந்த எந்தவொரு process அல்லது web page-ம் (Playwright-ல் இயங்குபவை உட்பட) OS user-ன் கட்டுப்பாட்டைப் பெற முடியும்." இயல்பான host localhost ஆகும், இது "loopback interface-லிருந்து வரும் இணைப்புகளை மட்டுமே ஏற்கும்". 0.0.0.0 போன்ற ஒரு குறிப்பிட்ட முகவரியைக் குறிப்பிடுவது, "listening port-ஐ அணுகக்கூடிய எவருக்கும் browser RPC-ஐ வெளிப்படுத்திவிடும்" என்று ஆவணங்கள் எச்சரிக்கின்றன. Chrome-ன் சொந்த --remote-debugging-port இன்னும் மோசமானது. DevTools protocol-ல் எந்தவிதமான அங்கீகாரமும் (authentication) இல்லை; இது முழுமையாக loopback-ல் இணைக்கப்பட்டிருப்பதை மட்டுமே நம்பியுள்ளது.
நீங்கள் எதை public-ஆக வெளியிட்டுள்ளீர்கள் என்பதைச் சரிபார்க்கவும். இதை உங்கள் VPS-லிருந்து மட்டுமல்லாமல், மற்றொரு கணினியிலிருந்தும் சரிபார்க்கவும்:
ss -ltnp0.0.0.0-ல் இணைக்கப்பட்டிருக்கும் எந்தவொரு browser port-ம் ஒரு பாதுகாப்பு குறைபாடாகும் (finding). பெரும்பாலான சேவை வழங்குநர்கள் தங்கள் control panel-ல் தனிப்பட்ட network firewall-ஐ இயக்குகிறார்கள் என்பதை நினைவில் கொள்க. உங்கள் ufw விதிகள் இதைப் பற்றி அறியாது. அதற்குப் பதிலாக, SSH tunnel அல்லது private VPN வழியாக மற்றொரு கணினியிலிருந்து அந்த endpoint-ஐ அணுகவும்:
ssh -N -L 3000:127.0.0.1:3000 you@your-vpsஇங்குள்ள ஆபத்து, browser-ன் நேரத்தைத் திருடுவதை விடப் பெரியது. நீங்கள் இயக்கக்கூடிய ஒரு browser, உங்கள் network-க்குள் இருக்கும் ஒரு request-forgery கருவியாகும். அந்த socket-ஐ அணுகும் எவரும், அதைக்கொண்டு http://127.0.0.1:8080, உங்கள் database admin பக்கம் அல்லது 169.254.169.254-ல் உள்ள cloud metadata முகவரியை fetch செய்து, அந்தப் பக்கத்திலிருந்து பதிலை வாசிக்க முடியும். உங்கள் firewall, அந்த request VPS-லிருந்தே வருவதாகக் கருதும், எனவே அது அனுமதிக்கப்படும். அந்த control endpoint-ஐ, அந்த box-ல் shell access பெற்றதற்குச் சமமாகக் கருதவும்.
MCP server-களும் இதே தன்மையைக் கொண்டவை. npx @playwright/mcp@latest --headless --port 8931, localhost-ல் HTTP வழியாகச் செயல்படுகிறது. --host 0.0.0.0 என்பது ஒரு local tool-ஐ public tool-ஆக மாற்றும் flag ஆகும். Playwright MCP "ஒரு பாதுகாப்பு எல்லை (security boundary) அல்ல" என்று அந்தத் திட்டத்தின் README தெளிவாகக் கூறுகிறது. அந்த port-ஐ loopback-லேயே வைத்திருக்கவும், அதே tunnel வழியாக agent-ஐ அதை அணுக அனுமதிக்கவும்.
உங்கள் agent படிக்கும் பக்கங்கள் நம்பகத்தன்மையற்ற உள்ளீடுகள்
திறந்த இணையத்தில் உலாவரும் ஒரு agent, அந்நியர்கள் எழுதிய உரையை உங்கள் அறிவுறுத்தல்கள் இருக்கும் அதே model-க்கு உள்ளீடாக வழங்குகிறது. ஒரு இணையப்பக்கம் அந்த model-ஐக் குறிவைத்து, கொடுக்கப்பட்ட பணியைக் கைவிடச் சொல்லியோ, ஒரு கருவியை (tool) இயக்கச் சொல்லியோ அல்லது ஒரு URL-க்குத் தரவுகளை அனுப்பச் சொல்லியோ கட்டளைகளைக் கொண்டிருக்கலாம். Model இவை இரண்டையும் உரையாகவே பெறுவதால், பக்கத்தில் உள்ள சொற்களுக்கும் உங்களுடைய அறிவுறுத்தல்களுக்கும் இடையே உள்ள வேறுபாட்டை அதனால் நம்பகத்தன்மையுடன் கண்டறிய முடியாது. எனவே, ஒரு தீங்கிழைக்கும் பக்கம் செயல்பட முடியாதபடி உங்கள் அமைப்பை வடிவமைக்கவும்.
- Browser-ஐ அதற்கென பிரத்யேகமான OS user-ன் கீழ் இயக்கவும்; அதன் சூழலில் SSH keys அல்லது cloud credentials எதையும் வைத்திருக்க வேண்டாம்.
- ஒவ்வொரு பணிக்கும் புதிய context-ஐப் பயன்படுத்தவும், மேலும்
--isolated-ஐ Playwright MCP உடன் பயன்படுத்தவும். இதன் மூலம் ஒரு தளத்தில் உள்ள session அடுத்த பக்கத்திற்கு கிடைக்காது. - பணி அனுமதிக்கும் இடங்களில் origin allowlist-ஐப் பராமரிக்கவும். Playwright MCP,
--allowed-originsமற்றும்--blocked-originsஆகியவற்றை அரைப்புள்ளி (semicolon) மூலம் பிரிக்கப்பட்ட பட்டியல்களாக ஏற்றுக்கொள்கிறது. - மின்னஞ்சல் அனுப்புதல் அல்லது பணம் செலவழித்தல் போன்ற, நிலையை மாற்றும் எந்தவொரு செயலுக்கும் முன்னதாக மனிதரின் ஒப்புதலைக் கட்டாயமாக்கவும்.
இதைவிடச் சிறந்தது, முழு browser-ஐயும் நீங்கள் அழித்துவிட்டு மீண்டும் உருவாக்கக்கூடிய ஒரு machine-ல் வைத்திருப்பதாகும். இது coding agents-ஐ disposable VM-ல் இயக்குவது போன்ற அதே தர்க்கம்தான். Agent-ன் உண்மையான பணி பொதுவான உலாவல் அல்லாமல் தேடல் மட்டுமே என்றால், முழுமையான browser-ஐ விடக் குறுகிய செயல்பாடுகளைக் கொண்ட கருவியே பாதுகாப்பானது: உங்கள் சொந்த SearXNG மூலம் இயங்கும் தேடல் திறன், தீங்கிழைக்கும் பக்கங்களை ஏற்றாமலேயே முடிவுகளை வழங்கும்.
FAQ
Chromium ஏன் Docker-ல் செயலிழக்கிறது, ஆனால் அதே VPS-ல் நேரடியாக இயங்கும்போது சரியாக வேலை செய்கிறது?
ஏனெனில், container இயல்பாகவே 64 MB /dev/shm-ஐ மட்டுமே பெறுகிறது, ஆனால் host கணினியில் இது மிக அதிகமாக இருக்கும். Chromium தான் உருவாக்கும் உள்ளடக்கத்தை அந்த shared memory பகுதி வழியாகவே அனுப்புகிறது, எனவே ஒரு கனமான பக்கம் அதை நிரப்பிவிடும்போது renderer செயலிழந்துவிடும். இதை உறுதிப்படுத்த container-க்குள் df -h /dev/shm-ஐ இயக்கவும். பிறகு, host-ன் shared memory-ஐப் பயன்படுத்தும் --ipc=host அல்லது container-ன் சொந்த நினைவகத்தை அதிகரிக்கும் --shm-size=1g ஆகிய இரண்டில் ஒன்றைப் பயன்படுத்தித் தொடங்கவும். --disable-dev-shm-usage என்பது சிக்கலை /tmp-க்கு மாற்றுவது மட்டுமே.
VPS-ல் வேறு எந்தப் பணியும் நடக்கவில்லை என்றால் --no-sandbox பாதுகாப்பானதா?
இல்லை. ஒரு தீங்கிழைக்கும் பக்கம் கணினியின் பிற பகுதிகளுக்குப் பரவாமல் தடுப்பதே sandbox ஆகும். Chromium ஆவணங்களின்படி, இந்த flag "Chromium-ன் முக்கியமான பாதுகாப்பு அம்சங்களை முடக்குகிறது, எனவே இணையத்தில் உலாவும்போது இதைப் பயன்படுத்தவே கூடாது". இணைப்புகளைப் பின்தொடரும் ஒரு agent இணையத்தில் உலாவிக் கொண்டிருக்கிறது என்றுதான் அர்த்தம். அதற்குப் பதிலாகக் காரணத்தைச் சரிசெய்யவும்: browser-ஐ root பயனர் மூலம் இயக்க வேண்டாம். Ubuntu 24.04-ல், browser binary பாதைக்கு userns,-ஐக் கொண்ட ஒரு AppArmor profile-ஐச் சேர்க்கவும்; இதன் மூலம் அந்த ஒரு நிரலுக்கு மட்டும் unprivileged user namespaces அனுமதிக்கப்படும்.
ஒரு சிறிய VPS-ல் எத்தனை browser-களை என்னால் இயக்க முடியும்?
ஒரு குறிப்பிட்ட எண்ணிக்கையை மனப்பாடம் செய்யாமல், நீங்களே அளந்து பாருங்கள். Chromium ஒவ்வொரு தளத்திற்கும் ஒரு renderer process-ஐத் தொடங்குகிறது, எனவே நீங்கள் திறக்கும் பக்கங்களைப் பொறுத்தே எண்ணிக்கை அமையும். MemoryMax அமைக்கப்பட்ட நிலையில் systemd-run-ன் கீழ் ஒரு worker-ஐ இயக்கவும். systemctl status-ல் உள்ள Memory: வரியிலிருந்து அதிகபட்ச பயன்பாட்டை (peak) கண்டறியவும். பிறகு, உங்கள் கணினியில் உள்ள இலவச RAM-ஐ அந்த peak மதிப்பால் வகுத்து, சிறிது கூடுதல் இடத்தையும் (headroom) ஒதுக்கவும். உங்கள் code-ல் ஒரு queue-வையும், unit file-ல் ஒரு MemoryMax-ஐயும் அமைப்பதன் மூலம் இந்த முடிவை உறுதிப்படுத்தவும்; இதனால் அதிகப்படியான கோரிக்கைகள் வரும்போது கணினி swap ஆகாமல், வரிசையில் காத்திருக்கும்.
எனது agent மற்றொரு கணினியிலிருந்து browser-உடன் இணைய முடியுமா?
ஆம், ஆனால் port-ஐ ஒருபோதும் 0.0.0.0-ல் bind செய்ய வேண்டாம். Playwright server endpoint மற்றும் Chrome DevTools port ஆகிய இரண்டும், தங்களை அணுகும் எந்த client-ஐயும் கடவுச்சொல் இன்றி அனுமதிக்கும். listener-ஐ 127.0.0.1-ல் வைத்து, SSH tunnel அல்லது private VPN வழியாக இணைப்பை ஏற்படுத்தவும். server-ல் ss -ltnp மூலமும், வெளியிலிருந்து port check மூலமும் இதைச் சரிபார்க்கவும். உங்கள் service provider-ன் தனிப்பட்ட network firewall-ஐயும் கவனிக்கவும்.
பக்கம் சரியாக load ஆகியும், எனது screenshots ஏன் காலியாக உள்ளன?
Fonts இல்லாததே காரணம். பக்கத்தின் script-க்குத் தேவையான font இல்லாதபோது, உரை காலியான பெட்டிகளாகவோ அல்லது தெரியாமலோ போய்விடும், இதனால் படம் போன்ற பக்கங்கள் காலியாகத் தோன்றும். நீங்கள் scrape செய்யும் ஒவ்வொரு மொழிக்கும் fc-match "sans-serif:lang=ko"-ஐ இயக்கவும். பொதுவான fallback தேவைப்படும்போது fonts-noto-core மற்றும் fonts-noto-cjk-ஐ நிறுவவும். fontconfig அதன் cache-ஐ மீண்டும் ஏற்றிக்கொள்ள browser-ஐ restart செய்யவும். fonts இல்லாத ஒரு container தொடங்கும்போதே Fontconfig error: Cannot load default config file-ஐ log-ல் காட்டும்.