From 766a9516b026b2a79d7f0b2a37af77063f78fddb Mon Sep 17 00:00:00 2001 From: Andrey Lushnikov Date: Tue, 13 Nov 2018 15:31:13 -0800 Subject: [PATCH] docs(troubleshooting): update on sandboxing (#3531) --- docs/troubleshooting.md | 90 ++++++++++++++++++++++++++++++++++------- 1 file changed, 75 insertions(+), 15 deletions(-) diff --git a/docs/troubleshooting.md b/docs/troubleshooting.md index fa1fa625..3f3a1edc 100644 --- a/docs/troubleshooting.md +++ b/docs/troubleshooting.md @@ -49,10 +49,6 @@ lsb-release xdg-utils wget ``` -Also enable `kernel.unprivileged_userns_clone` for server `sysctl`. See [comment](https://github.com/GoogleChrome/puppeteer/issues/290#issuecomment-403876758) -```bash -sudo sysctl -w kernel.unprivileged_userns_clone=1 -```
@@ -88,33 +84,97 @@ xorg-x11-fonts-misc - [#391](https://github.com/GoogleChrome/puppeteer/issues/391) - CentOS troubleshooting - [#379](https://github.com/GoogleChrome/puppeteer/issues/379) - Alpine troubleshooting -## Chrome Headless fails due to sandbox issues +## Setting Up Chrome Linux Sandbox -- Make sure kernel version is up-to-date. -- Read about linux sandbox here: https://chromium.googlesource.com/chromium/src/+/master/docs/linux_suid_sandbox_development.md -- Try running without the sandbox (**Note: running without the sandbox is not recommended due to security reasons!**) +In order to protect the host environment from untrusted web content, Chrome uses [multiple layers of sandboxing](https://chromium.googlesource.com/chromium/src/+/HEAD/docs/linux_sandboxing.md). For this to work properly, +the host should be configured first. If there's no good sandbox for Chrome to use, it will crash +with the error `No usable sandbox!`. + +If you **absolutely trust** the content you open in Chrome, you can launch Chrome +with the `--no-sandbox` argument: ```js const browser = await puppeteer.launch({args: ['--no-sandbox', '--disable-setuid-sandbox']}); ``` + +> **NOTE**: Running without a sandbox is **strongly discouraged**. Consider configuring a sandbox instead. + +There are 2 ways to configure a sandbox in Chromium. + +### [recommended] Enable [user namespace cloning](http://man7.org/linux/man-pages/man7/user_namespaces.7.html) + +User namespace cloning is only supported by modern kernels. Unprivileged user namespaces are generally fine to enable, +but in some cases they open up more kernel attack surface for (unsandboxed) non-root processes to elevate to +kernel privileges. + +```bash +sudo sysctl -w kernel.unprivileged_userns_clone=1 +``` + +### [alternative] Setup [setuid sandbox](https://chromium.googlesource.com/chromium/src/+/HEAD/docs/linux_suid_sandbox_development.md) + +The setuid sandbox comes as a standalone executable and is located next to the Chromium that Puppeteer downloads. It is +fine to re-use the same sandbox executable for different Chromium versions, so the following could be +done only once per host environment: + +```bash +# cd to the downloaded instance +cd /node_modules/puppeteer/.local-chromium/linux-/chrome-linux/ +sudo chown root:root chrome_sandbox +sudo chmod 4755 chrome_sandbox +# copy sandbox executable to a shared location +sudo cp chrome_sandbox /usr/local/sbin/chrome-devel-sandbox +# export CHROME_DEVEL_SANDBOX env variable +export CHROME_DEVEL_SANDBOX=/usr/local/sbin/chrome-devel-sandbox +``` + +You might want to export the `CHROME_DEVEL_SANDBOX` env variable by default. In this case, add the following to the `~/.bashrc` +or `.zshenv`: + +```bash +export CHROME_DEVEL_SANDBOX=/usr/local/sbin/chrome-devel-sandbox +``` + + ## Running Puppeteer on Travis CI -To run headless Chrome on Travis, you *must* call `launch()` with flags to disable Chrome's sandbox, like so: +> 👋 We run our tests for Puppeteer on Travis CI - see our [`.travis.yml`](https://github.com/GoogleChrome/puppeteer/blob/master/.travis.yml) for reference. -```js -const browser = await puppeteer.launch({args: ['--no-sandbox']}); -``` +Tips-n-tricks: +- The `libnss3` package must be installed in order to run Chromium on Ubuntu Trusty +- [user namespace cloning](http://man7.org/linux/man-pages/man7/user_namespaces.7.html) should be enabled to support + proper sandboxing +- [xvfb](https://en.wikipedia.org/wiki/Xvfb) should be launched in order to run Chromium in non-headless mode (e.g. to test Chrome Extensions) -Some Puppeteer functionality (like Chrome extensions) requires non-headless mode. Running Puppeteer in non-headless mode on Travis CI can be done using an [Xvfb](https://en.wikipedia.org/wiki/Xvfb) server: +To sum up, your `.travis.yml` might look like this: ```yml +language: node_js +dist: trusty +addons: + apt: + packages: + # This is required to run new chrome on old trusty + - libnss3 +notifications: + email: false +cache: + directories: + - node_modules +# allow headful tests before_install: - - export DISPLAY=:99.0 - - sh -e /etc/init.d/xvfb start + # Enable user namespace cloning + - "sysctl kernel.unprivileged_userns_clone=1" + # Launch XVFB + - "export DISPLAY=:99.0" + - "sh -e /etc/init.d/xvfb start" ``` + ## Running Puppeteer in Docker +> 👋 We use [Cirrus Ci](https://cirrus-ci.org/) to run our tests for Puppeteer in a Docker container - see our [`Dockerfile.linux`](https://github.com/GoogleChrome/puppeteer/blob/master/.ci/node8/Dockerfile.linux) for reference. + Getting headless Chrome up and running in Docker can be tricky. The bundled Chromium that Puppeteer installs is missing the necessary shared library dependencies.