mirror of
https://github.com/kemalai/FreeCrawl-SEO-Tool.git
synced 2026-10-18 00:39:38 +02:00
85 lines
3.8 KiB
JavaScript
85 lines
3.8 KiB
JavaScript
// electron-builder `afterPack` hook, wired up in electron-builder.yml.
|
|
//
|
|
// Linux AppImage only: puts a small shell launcher in front of the Electron
|
|
// binary that adds `--no-sandbox` on systems where Chromium's sandbox cannot
|
|
// work, and leaves the sandbox on everywhere else.
|
|
//
|
|
// Why a launcher and not app code: Chromium's sandbox needs unprivileged user
|
|
// namespaces. Ubuntu 23.10+ denies them to every process that has no AppArmor
|
|
// profile (kernel.apparmor_restrict_unprivileged_userns=1), Chromium then
|
|
// falls back to the setuid `chrome-sandbox` helper, and that helper can never
|
|
// be setuid inside an AppImage (the FUSE mount is nosuid). The check runs in
|
|
// content's ContentMainRunnerImpl::Initialize, before the main process has
|
|
// executed a single line of JavaScript, so `app.commandLine.appendSwitch(
|
|
// 'no-sandbox')` is too late; the flag has to come from whatever execs the
|
|
// binary. electron-builder's own AppRun just execs `$APPDIR/<executableName>`
|
|
// with the user's arguments, so a script at that path is the one place that
|
|
// can decide.
|
|
//
|
|
// The .deb/.rpm are deliberately not wrapped: electron-builder's after-install
|
|
// script installs an AppArmor profile (Ubuntu 24.04+) and chmods
|
|
// chrome-sandbox 4755 where user namespaces are unavailable, so the sandbox
|
|
// keeps working there. That is why `build:linux` runs the AppImage in its own
|
|
// electron-builder invocation and this hook refuses mixed target lists.
|
|
import { chmodSync, renameSync, writeFileSync } from 'node:fs';
|
|
import path from 'node:path';
|
|
|
|
const REAL_SUFFIX = '.bin';
|
|
|
|
function launcherScript(exe) {
|
|
// Written with LF regardless of this file's own line endings: a CRLF shebang
|
|
// is "bad interpreter" on Linux.
|
|
return `#!/bin/sh
|
|
# FreeCrawl SEO AppImage launcher (generated by scripts/after-pack.mjs).
|
|
#
|
|
# Chromium's sandbox needs unprivileged user namespaces. When the kernel denies
|
|
# them to ordinary processes, Chromium falls back to a setuid chrome-sandbox
|
|
# helper that cannot exist inside an AppImage, and aborts with "No usable
|
|
# sandbox!" before the app starts. On such systems start with --no-sandbox;
|
|
# everywhere else the sandbox stays on.
|
|
here=$(dirname "$(readlink -f "$0")")
|
|
bin="$here/${exe}${REAL_SUFFIX}"
|
|
|
|
sysctl_is() {
|
|
[ -r "$1" ] && [ "$(cat "$1" 2>/dev/null)" = "$2" ]
|
|
}
|
|
|
|
for arg in "$@"; do
|
|
case "$arg" in
|
|
--no-sandbox) exec "$bin" "$@" ;;
|
|
esac
|
|
done
|
|
|
|
# Ubuntu 23.10+ (AppArmor), Debian/Arch style kernels, RHEL 7 style kernels.
|
|
if sysctl_is /proc/sys/kernel/apparmor_restrict_unprivileged_userns 1 \\
|
|
|| sysctl_is /proc/sys/kernel/unprivileged_userns_clone 0 \\
|
|
|| sysctl_is /proc/sys/user/max_user_namespaces 0; then
|
|
echo "FreeCrawl SEO: this system restricts unprivileged user namespaces; starting with --no-sandbox." >&2
|
|
exec "$bin" --no-sandbox "$@"
|
|
fi
|
|
|
|
exec "$bin" "$@"
|
|
`.replace(/\r\n/g, '\n');
|
|
}
|
|
|
|
export default async function afterPack(context) {
|
|
if (context.electronPlatformName !== 'linux') return;
|
|
const targets = context.targets.map((t) => t.name);
|
|
if (!targets.includes('appImage')) return;
|
|
const others = targets.filter((t) => t !== 'appImage');
|
|
if (others.length > 0) {
|
|
throw new Error(
|
|
`after-pack: the AppImage must be built in its own electron-builder run ` +
|
|
`(got targets: ${targets.join(', ')}). The launcher must not end up in the ` +
|
|
`.deb/.rpm; see build:linux in apps/desktop/package.json.`,
|
|
);
|
|
}
|
|
const exe = context.packager.executableName;
|
|
const binPath = path.join(context.appOutDir, exe);
|
|
const realPath = binPath + REAL_SUFFIX;
|
|
renameSync(binPath, realPath);
|
|
writeFileSync(binPath, launcherScript(exe), { mode: 0o755 });
|
|
chmodSync(binPath, 0o755); // the mode in writeFileSync is subject to umask
|
|
console.log(` • after-pack: AppImage launcher installed as ${exe}, Electron binary is now ${exe}${REAL_SUFFIX}`);
|
|
}
|