diff --git a/extensions/linux/index.js b/extensions/linux/index.js index 08791ba4f..8529b0701 100644 --- a/extensions/linux/index.js +++ b/extensions/linux/index.js @@ -1,5 +1,6 @@ 'use strict'; +const fs = require('fs'); const os = require('os'); const execa = require('execa'); const path = require('path'); @@ -51,6 +52,52 @@ class LinuxExtension extends cli.Extension { // we need to remove it manually here via sudo return this.ui.sudo(`rm -rf ${path.join(instance.dir, 'content')}`); } + + run(argv, instance) { + if (os.platform() !== 'linux') { + // platform isn't linux, we don't need to to anything + return Promise.resolve(); + } + + let ghostuid, ghostgid; + + try { + ghostuid = execa.shellSync('id -u ghost').stdout; + ghostgid = execa.shellSync('id -g ghost').stdout; + } catch (e) { + if (!e.message.match(/no such user/)) { + return Promise.reject(new cli.errors.ProcessError(e)); + } + + // Ghost user doesn't exist, skip + return Promise.resolve(); + } + + ghostuid = parseInt(ghostuid); + ghostgid = parseInt(ghostgid); + + let stats = fs.lstatSync(path.join(instance.dir, 'content')); + + if (stats.uid !== ghostuid && stats.gid !== ghostgid) { + // folder isn't owned by ghost user, skip additional behavior + return Promise.resolve(); + } + + let currentuid = process.getuid(); + + if (currentuid === ghostuid) { + // current user is ghost, continue + return Promise.resolve(); + } + + if (currentuid !== 0) { + // we need to be sudo in order to run setuid below + return Promise.reject(new cli.errors.SystemError('Because Ghost-CLI has set up a "ghost" system user for this instance, you must run `sudo ghost run` instead.')); + } + + process.setgid(ghostgid); + process.setuid(ghostuid); + } } module.exports = LinuxExtension; diff --git a/lib/commands/run.js b/lib/commands/run.js index 26dfff5d1..336cf6703 100644 --- a/lib/commands/run.js +++ b/lib/commands/run.js @@ -4,7 +4,7 @@ const spawn = require('child_process').spawn; const Command = require('../command'); class RunCommand extends Command { - run() { + run(argv) { // If the user is running this command directly, output a little note // telling them they're likely looking for `ghost start` if (process.stdin.isTTY) { @@ -16,23 +16,25 @@ class RunCommand extends Command { process.env.paths__contentPath = path.join(process.cwd(), 'content'); - this.child = spawn(process.execPath, ['current/index.js'], { - cwd: process.cwd(), - stdio: [0, 1, 2, 'ipc'] - }); - - this.child.on('error', (error) => { - this.ui.fail(error); - process.exit(1); - }); - - this.child.on('message', (message) => { - if (message.started) { - instance.process.success(); - return; - } - - instance.process.error(message.error); + return this.system.hook('run', argv, instance).then(() => { + this.child = spawn(process.execPath, ['current/index.js'], { + cwd: process.cwd(), + stdio: [0, 1, 2, 'ipc'] + }); + + this.child.on('error', (error) => { + this.ui.fail(error); + process.exit(1); + }); + + this.child.on('message', (message) => { + if (message.started) { + instance.process.success(); + return; + } + + instance.process.error(message.error); + }); }); }