homebridge-config-ui-x
Version:
A web based management, configuration and control platform for Homebridge.
250 lines • 10.7 kB
JavaScript
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.FreeBSDInstaller = void 0;
const node_child_process_1 = require("node:child_process");
const node_os_1 = require("node:os");
const node_path_1 = require("node:path");
const node_process_1 = __importDefault(require("node:process"));
const fs_extra_1 = require("fs-extra");
const base_platform_1 = require("../base-platform");
class FreeBSDInstaller extends base_platform_1.BasePlatform {
get rcServiceName() {
return this.hbService.serviceName.toLowerCase();
}
get rcServicePath() {
return (0, node_path_1.resolve)('/usr/local/etc/rc.d', this.rcServiceName);
}
async install() {
this.checkForRoot();
await this.checkUser();
this.setupSudo();
await this.hbService.portCheck();
await this.hbService.storagePathCheck();
await this.hbService.configCheck();
try {
await this.createRCService();
await this.enableService();
await this.start();
await this.hbService.printPostInstallInstructions();
}
catch (e) {
console.error(e.toString());
this.hbService.logger('ERROR: Failed Operation', 'fail');
}
}
async uninstall() {
this.checkForRoot();
await this.stop();
await this.disableService();
try {
if ((0, fs_extra_1.existsSync)(this.rcServicePath)) {
this.hbService.logger(`Removed ${this.rcServiceName} Service`, 'succeed');
(0, fs_extra_1.unlinkSync)(this.rcServicePath);
}
else {
this.hbService.logger(`Could not find installed ${this.rcServiceName} Service.`, 'fail');
}
}
catch (e) {
console.error(e.toString());
this.hbService.logger('ERROR: Failed Operation', 'fail');
}
}
async start() {
this.checkForRoot();
try {
this.hbService.logger(`Starting ${this.rcServiceName} Service...`);
(0, node_child_process_1.execSync)(`service ${this.rcServiceName} start`, { stdio: 'inherit' });
this.hbService.logger(`${this.rcServiceName} Started`, 'succeed');
}
catch (e) {
this.hbService.logger(`Failed to start ${this.rcServiceName}`, 'fail');
}
}
async stop() {
this.checkForRoot();
try {
this.hbService.logger(`Stopping ${this.rcServiceName} Service...`);
(0, node_child_process_1.execSync)(`service ${this.rcServiceName} stop`, { stdio: 'inherit' });
this.hbService.logger(`${this.rcServiceName} Stopped`, 'succeed');
}
catch (e) {
this.hbService.logger(`Failed to stop ${this.rcServiceName}`, 'fail');
}
}
async restart() {
this.checkForRoot();
try {
this.hbService.logger(`Restarting ${this.rcServiceName} Service...`);
(0, node_child_process_1.execSync)(`service ${this.rcServiceName} restart`, { stdio: 'inherit' });
this.hbService.logger(`${this.rcServiceName} Restarted`, 'succeed');
}
catch (e) {
this.hbService.logger(`Failed to restart ${this.rcServiceName}`, 'fail');
}
}
async rebuild(all = false) {
try {
this.checkForRoot();
const npmGlobalPath = (0, node_child_process_1.execSync)('/bin/echo -n "$(npm -g prefix)/lib/node_modules"', {
env: Object.assign({
npm_config_loglevel: 'silent',
npm_update_notifier: 'false',
}, node_process_1.default.env),
}).toString('utf8');
const targetNodeVersion = (0, node_child_process_1.execSync)('node -v').toString('utf8').trim();
(0, node_child_process_1.execSync)('npm rebuild --unsafe-perm', {
cwd: node_process_1.default.env.UIX_BASE_PATH,
stdio: 'inherit',
});
if (all === true) {
try {
(0, node_child_process_1.execSync)('npm rebuild --unsafe-perm', {
cwd: npmGlobalPath,
stdio: 'inherit',
});
}
catch (e) {
this.hbService.logger('Could not rebuild all modules - check Homebridge logs.', 'warn');
}
}
this.hbService.logger(`Rebuilt modules in ${node_process_1.default.env.UIX_BASE_PATH} for Node.js ${targetNodeVersion}.`, 'succeed');
}
catch (e) {
console.error(e.toString());
this.hbService.logger('ERROR: Failed Operation', 'fail');
}
}
async getId() {
if ((node_process_1.default.getuid() === 0 && this.hbService.asUser) || node_process_1.default.env.SUDO_USER) {
const uid = (0, node_child_process_1.execSync)(`id -u ${this.hbService.asUser || node_process_1.default.env.SUDO_USER}`).toString('utf8');
const gid = (0, node_child_process_1.execSync)(`id -g ${this.hbService.asUser || node_process_1.default.env.SUDO_USER}`).toString('utf8');
return {
uid: Number.parseInt(uid, 10),
gid: Number.parseInt(gid, 10),
};
}
else {
return {
uid: (0, node_os_1.userInfo)().uid,
gid: (0, node_os_1.userInfo)().gid,
};
}
}
getPidOfPort(port) {
try {
return (0, node_child_process_1.execSync)(`sockstat -P tcp -p ${port} -l -q 2> /dev/null | awk '{print $3}' | head -n 1`).toString('utf8').trim();
}
catch (e) {
return null;
}
}
async enableService() {
try {
(0, node_child_process_1.execSync)(`sysrc ${this.rcServiceName}_enable="YES" 2> /dev/null`);
}
catch (e) {
this.hbService.logger(`WARNING: failed to run "sysrc ${this.rcServiceName}_enable=\"YES\"`, 'warn');
}
}
async disableService() {
try {
(0, node_child_process_1.execSync)(`sysrc ${this.rcServiceName}_enable="NO" 2> /dev/null`);
}
catch (e) {
this.hbService.logger(`WARNING: failed to run "sysrc ${this.rcServiceName}_enable=\"NO\"`, 'warn');
}
}
checkForRoot() {
if (node_process_1.default.getuid() !== 0) {
this.hbService.logger('ERROR: This command must be executed using sudo on FreeBSD', 'fail');
this.hbService.logger(`EXAMPLE: sudo hb-service ${this.hbService.action}`, 'fail');
node_process_1.default.exit(1);
}
if (this.hbService.action === 'install' && !node_process_1.default.env.SUDO_USER && !this.hbService.asUser) {
this.hbService.logger('ERROR: Could not detect user. Pass in the user you want to run Homebridge as using the --user flag eg.', 'fail');
this.hbService.logger(`EXAMPLE: sudo hb-service ${this.hbService.action} --user your-user`, 'fail');
node_process_1.default.exit(1);
}
}
async checkUser() {
try {
(0, node_child_process_1.execSync)(`id ${this.hbService.asUser} 2> /dev/null`);
}
catch (e) {
(0, node_child_process_1.execSync)(`pw useradd -q -n ${this.hbService.asUser} -s /usr/sbin/nologin 2> /dev/null`);
this.hbService.logger(`Created service user: ${this.hbService.asUser}`, 'info');
}
}
setupSudo() {
try {
const npmPath = (0, node_child_process_1.execSync)('which npm').toString('utf8').trim();
const sudoersEntry = `${this.hbService.asUser} ALL=(ALL) NOPASSWD:SETENV: ${npmPath}, /usr/local/bin/npm`;
const sudoers = (0, fs_extra_1.readFileSync)('/usr/local/etc/sudoers', 'utf-8');
if (sudoers.includes(sudoersEntry)) {
return;
}
(0, node_child_process_1.execSync)(`echo '${sudoersEntry}' | sudo EDITOR='tee -a' visudo`);
}
catch (e) {
this.hbService.logger('WARNING: Failed to setup /etc/sudoers, you may not be able to shutdown/restart your server from the Homebridge UI.', 'warn');
}
}
async updateNodejs(job) {
this.hbService.logger('Update Node.js using pkg manually.', 'fail');
node_process_1.default.exit(1);
}
async createRCService() {
const rcFileContents = [
'#!/bin/sh',
'#',
`# PROVIDE: ${this.rcServiceName}`,
'# REQUIRE: NETWORKING SYSLOG',
'# KEYWORD: shutdown',
'#',
`# Add the following lines to /etc/rc.conf to enable ${this.rcServiceName}:`,
'#',
`#${this.rcServiceName}_enable="YES"`,
'',
'. /etc/rc.subr',
'',
`name="${this.rcServiceName}"`,
`rcvar="${this.rcServiceName}_enable"`,
'',
'load_rc_config $name',
'',
`: \${${this.rcServiceName}_user:="${this.hbService.asUser}"}`,
`: \${${this.rcServiceName}_enable:="NO"}`,
`: \${${this.rcServiceName}_facility:="daemon"}`,
`: \${${this.rcServiceName}_priority:="debug"}`,
`: \${${this.rcServiceName}_storage_path:="${this.hbService.storagePath}"}`,
'',
'export HOME="$(eval echo ~${homebridge_user})"',
'export PATH=/usr/local/bin:${PATH}',
'export HOMEBRIDGE_CONFIG_UI_TERMINAL=1',
'export UIX_STORAGE_PATH="${homebridge_storage_path}"',
'',
'pidfile="/var/run/${name}.pid"',
'command="/usr/sbin/daemon"',
'procname="daemon"',
`command_args=" -c -f -R 3 -P \${pidfile} ${this.hbService.selfPath} run -U \${homebridge_storage_path}"`,
'start_precmd="homebridge_precmd"',
'',
'homebridge_precmd()',
'{',
' sleep 10',
' chown -R ${homebridge_user}: ${homebridge_storage_path}',
' install -o ${homebridge_user} /dev/null ${pidfile}',
'}',
'',
'run_rc_command "$1"',
].filter(x => x).join('\n');
await (0, fs_extra_1.outputFile)(this.rcServicePath, rcFileContents);
await (0, fs_extra_1.chmod)(this.rcServicePath, '755');
}
}
exports.FreeBSDInstaller = FreeBSDInstaller;
//# sourceMappingURL=freebsd.js.map
;