Skip to content

Commit

Permalink
fix(main): add --no-sandbox option to optionally disable sandboxing o…
Browse files Browse the repository at this point in the history
…n linux

When root user has to be used and system sandboxing is not possible on Linux platforms, Chrome
should be executed with the `--no-sandbox` argument for Puppeteer to run.
  • Loading branch information
onderceylan committed Nov 30, 2020
1 parent 91ae0a9 commit 79444d2
Show file tree
Hide file tree
Showing 8 changed files with 65 additions and 10 deletions.
8 changes: 5 additions & 3 deletions README.md
Expand Up @@ -97,6 +97,7 @@ $ pwa-asset-generator --help
-u --single-quotes Generate HTML meta tags with single quotes [default: false]
-x --xhtml Generate HTML meta tags by self-closing the tags [default: false]
-g --log Logs the steps of the library process [default: true]
-n --no-sandbox Disable sandbox on bundled Chromium on Linux platforms - not recommended [default: false]
Examples
$ pwa-asset-generator logo.html
Expand Down Expand Up @@ -278,7 +279,8 @@ pwa-asset-generator depends on Puppeteer and it's screenshot API for image gener

However, you can use one of the lossless / lossy compression libraries - like [pngquant](https://pngquant.org/) to compress the generated PNG images.

## Troubleshooting
### Running the CLI command on CI server causes Puppeteer error: "Running as root without --no-sandbox is not supported". How can I disable sandboxing?

### "No usable sandbox!" error on Linux
In case of getting "No usable sandbox!" error on Linux, you need to enable [system sandboxing](https://github.com/GoogleChrome/puppeteer/blob/master/docs/troubleshooting.md#setting-up-chrome-linux-sandbox).
When root user has to be used and system sandboxing is not possible on Linux platforms, Chrome should be executed with the `--no-sandbox` [argument for Puppeteer to run](https://github.com/GoogleChrome/puppeteer/blob/master/docs/troubleshooting.md#setting-up-chrome-linux-sandbox).

PAG provides users the `--no-sandbox` option to tackle this issue. Note that there are limitations for this option; it can only be used on Linux platforms and HTML inputs are disabled for security purposes.
1 change: 1 addition & 0 deletions src/cli.ts
Expand Up @@ -34,6 +34,7 @@ $ pwa-asset-generator --help
-u --single-quotes Generate HTML meta tags with single quotes [default: false]
-x --xhtml Generate HTML meta tags by self-closing the tags [default: false]
-g --log Logs the steps of the library process [default: true]
-n --no-sandbox Disable sandbox on bundled Chromium on Linux platforms - not recommended [default: false]
Examples
$ pwa-asset-generator logo.html
Expand Down
5 changes: 5 additions & 0 deletions src/config/constants.ts
Expand Up @@ -134,6 +134,11 @@ export default {
alias: 'd',
default: false,
},
noSandbox: {
type: 'boolean',
alias: 'n',
default: false,
},
},

CHROME_LAUNCH_ARGS: [
Expand Down
9 changes: 6 additions & 3 deletions src/helpers/browser.ts
Expand Up @@ -48,7 +48,8 @@ const getLocalRevisionInfo = async (): Promise<RevisionInfo | undefined> => {
};

const getLocalBrowserInstance = async (
launchArgs?: LaunchOptions,
launchArgs: LaunchOptions,
noSandbox: boolean,
): Promise<Browser> => {
let revisionInfo: RevisionInfo;
const localRevisionInfo = await getLocalRevisionInfo();
Expand All @@ -61,6 +62,7 @@ const getLocalBrowserInstance = async (

return puppeteer.launch({
...launchArgs,
...(noSandbox && { args: ['--no-sandbox', '--disable-setuid-sandbox'] }),
executablePath: revisionInfo.executablePath,
});
};
Expand Down Expand Up @@ -107,7 +109,8 @@ const getSystemBrowserInstance = async (
};

const getBrowserInstance = async (
launchArgs?: LaunchOptions,
launchArgs: LaunchOptions,
noSandbox: boolean,
): Promise<{ chrome: LaunchedChrome | undefined; browser: Browser }> => {
const LAUNCHER_CONNECTION_REFUSED_ERROR_CODE = 'ECONNREFUSED';
const LAUNCHER_NOT_INSTALLED_ERROR_CODE = 'ERR_LAUNCHER_NOT_INSTALLED';
Expand Down Expand Up @@ -139,7 +142,7 @@ const getBrowserInstance = async (
logger.warn('Looks like Chrome is not installed on your system');
}

browser = await getLocalBrowserInstance(launchArgs);
browser = await getLocalBrowserInstance(launchArgs, noSandbox);
}

return { browser, chrome };
Expand Down
27 changes: 26 additions & 1 deletion src/helpers/flags.ts
@@ -1,3 +1,4 @@
import os from 'os';
import constants from '../config/constants';
import { CLIOptions, Options } from '../models/options';
import { LoggerFunction } from '../models/logger';
Expand Down Expand Up @@ -52,4 +53,28 @@ const getDefaultOptions = (): Options => {
}, {} as Options);
};

export default { normalizeOnlyFlagPairs, normalizeOutput, getDefaultOptions };
const normalizeSandboxOption = (
noSandbox: boolean | undefined,
logger: LoggerFunction,
): Partial<Options> => {
let sandboxDisabled = false;
if (noSandbox) {
if (os.platform() !== 'linux') {
logger.warn(
'Disabling sandbox is only relevant on Linux platforms, request declined!',
);
} else {
sandboxDisabled = true;
}
}
return {
noSandbox: sandboxDisabled,
};
};

export default {
normalizeOnlyFlagPairs,
normalizeOutput,
getDefaultOptions,
normalizeSandboxOption,
};
17 changes: 14 additions & 3 deletions src/helpers/puppets.ts
Expand Up @@ -240,9 +240,20 @@ const generateImages = async (
options: Options,
): Promise<SavedImage[]> => {
const logger = preLogger(generateImages.name, options);
const { browser, chrome } = await browserHelper.getBrowserInstance({
timeout: constants.BROWSER_TIMEOUT,
});
const isHtmlInput = canNavigateTo(source);

if (isHtmlInput) {
logger.warn(
'noSandbox option is disabled for HTML inputs, use an image input instead',
);
}

const { browser, chrome } = await browserHelper.getBrowserInstance(
{
timeout: constants.BROWSER_TIMEOUT,
},
isHtmlInput ? false : options.noSandbox,
);

let splashScreenMetaData;

Expand Down
1 change: 1 addition & 0 deletions src/main.ts
Expand Up @@ -63,6 +63,7 @@ async function generateImages(
options,
logger,
),
...flags.normalizeSandboxOption(options.noSandbox, logger),
};
} else {
modOptions = {
Expand Down
7 changes: 7 additions & 0 deletions src/models/options.ts
Expand Up @@ -149,6 +149,13 @@ export interface Options {
@default false
*/
readonly mstile: boolean;

/**
Disable sandbox on bundled Chromium on Linux platforms - not recommended
@default false
*/
readonly noSandbox: boolean;
}

export type CLIOptions = Partial<Options>;

0 comments on commit 79444d2

Please sign in to comment.