Skip to content

Commit

Permalink
docs(troubleshooting): update on sandboxing (#3531)
Browse files Browse the repository at this point in the history
  • Loading branch information
aslushnikov committed Nov 13, 2018
1 parent eb7bd9d commit 766a951
Showing 1 changed file with 75 additions and 15 deletions.
90 changes: 75 additions & 15 deletions docs/troubleshooting.md
Expand Up @@ -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
```
</details>

<details>
Expand Down Expand Up @@ -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

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!`.

- 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!**)
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']});
```
## Running Puppeteer on Travis CI

To run headless Chrome on Travis, you *must* call `launch()` with flags to disable Chrome's sandbox, like so:
> **NOTE**: Running without a sandbox is **strongly discouraged**. Consider configuring a sandbox instead.
```js
const browser = await puppeteer.launch({args: ['--no-sandbox']});
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
```

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:
### [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 <project-dir-path>/node_modules/puppeteer/.local-chromium/linux-<revision>/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

> 👋 We run our tests for Puppeteer on Travis CI - see our [`.travis.yml`](https://github.com/GoogleChrome/puppeteer/blob/master/.travis.yml) for reference.
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)

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.
Expand Down

0 comments on commit 766a951

Please sign in to comment.