Embedding Prosody using AppImage:
Thanks to this commit, there is no more need to manually install Prosody on the server. The plugin now build and embed an AppImage of Prosody. In this commit: * building and using a Prosody AppImage. * Adding a launcher in the AppImage: the first command argument tells if we want to run prosody or prosodyctl * prosodyCtl functions now uses the AppImage. * Prosody AppImage: extract once at the startup, then run the squashfs
This commit is contained in:
@ -33,6 +33,8 @@ export async function diagProsody (test: string, options: RegisterServerOptions)
|
||||
|
||||
result.messages.push(`Prosody will use ${wantedConfig.baseApiUrl} as base uri from api calls`)
|
||||
|
||||
result.messages.push(`Prosody path will be '${wantedConfig.paths.exec}'`)
|
||||
|
||||
result.messages.push(`Prosody modules path will be '${wantedConfig.paths.modules}'`)
|
||||
|
||||
result.messages.push(`Prosody rooms will be grouped by '${wantedConfig.roomType}'.`)
|
||||
|
@ -54,6 +54,24 @@ async function getProsodyFilePaths (options: RegisterServerOptions): Promise<Pro
|
||||
logger.debug('Calling getProsodyFilePaths')
|
||||
|
||||
const dir = await getWorkingDir(options)
|
||||
const settings = await options.settingsManager.getSettings(['use-system-prosody'])
|
||||
let exec
|
||||
let execArgs: string[]
|
||||
let execCtl
|
||||
let execCtlArgs: string[]
|
||||
let appImageToExtract
|
||||
if (settings['use-system-prosody']) {
|
||||
exec = 'prosody'
|
||||
execArgs = []
|
||||
execCtl = 'prosodyctl'
|
||||
execCtlArgs = []
|
||||
} else {
|
||||
appImageToExtract = path.resolve(__dirname, '../../prosody/livechat-prosody-x86_64.AppImage')
|
||||
exec = path.resolve(dir, 'squashfs-root/AppRun') // the AppImage will be extracted in the working dir
|
||||
execArgs = ['prosody']
|
||||
execCtl = exec
|
||||
execCtlArgs = ['prosodyctl']
|
||||
}
|
||||
return {
|
||||
dir: dir,
|
||||
pid: path.resolve(dir, 'prosody.pid'),
|
||||
@ -62,7 +80,12 @@ async function getProsodyFilePaths (options: RegisterServerOptions): Promise<Pro
|
||||
config: path.resolve(dir, 'prosody.cfg.lua'),
|
||||
data: path.resolve(dir, 'data'),
|
||||
modules: path.resolve(__dirname, '../../prosody-modules'),
|
||||
avatars: path.resolve(__dirname, '../../avatars')
|
||||
avatars: path.resolve(__dirname, '../../avatars'),
|
||||
exec,
|
||||
execArgs,
|
||||
execCtl,
|
||||
execCtlArgs,
|
||||
appImageToExtract
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -7,6 +7,11 @@ interface ProsodyFilePaths {
|
||||
data: string
|
||||
modules: string
|
||||
avatars: string
|
||||
exec: string
|
||||
execArgs: string[]
|
||||
execCtl: string
|
||||
execCtlArgs: string[]
|
||||
appImageToExtract?: string
|
||||
}
|
||||
|
||||
export {
|
||||
|
@ -5,6 +5,38 @@ import { disableProxyRoute, enableProxyRoute } from '../routers/webchat'
|
||||
import * as fs from 'fs'
|
||||
import * as child_process from 'child_process'
|
||||
|
||||
/**
|
||||
* This function prepares the binaries for the embeded Prosody (if needed).
|
||||
* @param options
|
||||
*/
|
||||
async function prepareProsody (options: RegisterServerOptions): Promise<void> {
|
||||
const logger = options.peertubeHelpers.logger
|
||||
const filePaths = await getProsodyFilePaths(options)
|
||||
const appImageToExtract = filePaths.appImageToExtract
|
||||
if (!appImageToExtract) {
|
||||
return
|
||||
}
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
const spawned = child_process.spawn(appImageToExtract, ['--appimage-extract'], {
|
||||
cwd: filePaths.dir,
|
||||
env: {
|
||||
...process.env
|
||||
}
|
||||
})
|
||||
spawned.stdout.on('data', (data) => {
|
||||
logger.debug(`AppImage extract printed: ${data as string}`)
|
||||
})
|
||||
spawned.stderr.on('data', (data) => {
|
||||
logger.error(`AppImage extract has errors: ${data as string}`)
|
||||
})
|
||||
spawned.on('error', reject)
|
||||
spawned.on('close', (_code) => { // 'close' and not 'exit', to be sure it is finished.
|
||||
resolve()
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
interface ProsodyCtlResult {
|
||||
code: number | null
|
||||
stdout: string
|
||||
@ -23,11 +55,13 @@ async function prosodyCtl (options: RegisterServerOptions, command: string): Pro
|
||||
let d: string = ''
|
||||
let e: string = ''
|
||||
let m: string = ''
|
||||
const spawned = child_process.spawn('prosodyctl', [
|
||||
const cmdArgs = [
|
||||
...filePaths.execCtlArgs,
|
||||
'--config',
|
||||
filePaths.config,
|
||||
command
|
||||
], {
|
||||
]
|
||||
const spawned = child_process.spawn(filePaths.execCtl, cmdArgs, {
|
||||
cwd: filePaths.dir,
|
||||
env: {
|
||||
...process.env,
|
||||
@ -44,7 +78,10 @@ async function prosodyCtl (options: RegisterServerOptions, command: string): Pro
|
||||
m += data as string
|
||||
})
|
||||
spawned.on('error', reject)
|
||||
spawned.on('exit', (code) => {
|
||||
|
||||
// on 'close' and not 'exit', to be sure everything is done
|
||||
// (else it can cause trouble by cleaning AppImage extract too soon)
|
||||
spawned.on('close', (code) => {
|
||||
resolve({
|
||||
code: code,
|
||||
stdout: d,
|
||||
@ -163,8 +200,9 @@ async function ensureProsodyRunning (options: RegisterServerOptions): Promise<vo
|
||||
const filePaths = config.paths
|
||||
|
||||
// launch prosody
|
||||
logger.info('Going to launch prosody')
|
||||
const prosody = child_process.exec('prosody', {
|
||||
const execCmd = filePaths.exec + (filePaths.execArgs.length ? ' ' + filePaths.execArgs.join(' ') : '')
|
||||
logger.info('Going to launch prosody (' + execCmd + ')')
|
||||
const prosody = child_process.exec(execCmd, {
|
||||
cwd: filePaths.dir,
|
||||
env: {
|
||||
...process.env,
|
||||
@ -248,6 +286,7 @@ export {
|
||||
getProsodyAbout,
|
||||
testProsodyRunning,
|
||||
testProsodyCorrectlyRunning,
|
||||
prepareProsody,
|
||||
ensureProsodyRunning,
|
||||
ensureProsodyNotRunning
|
||||
}
|
||||
|
@ -27,11 +27,11 @@ function initSettings (options: RegisterServerOptions): void {
|
||||
(if this button is not opening a new window, please try to refresh the page).`
|
||||
})
|
||||
|
||||
// ********** Chat Mode
|
||||
// ********** Chat Server
|
||||
registerSetting({
|
||||
type: 'html',
|
||||
private: true,
|
||||
descriptionHTML: '<h3>Chat mode</h3>'
|
||||
descriptionHTML: '<h3>Chat Server</h3>'
|
||||
})
|
||||
registerSetting({
|
||||
name: 'chat-help-builtin-prosody',
|
||||
@ -39,14 +39,22 @@ function initSettings (options: RegisterServerOptions): void {
|
||||
label: 'Prosody server',
|
||||
descriptionHTML: `This plugin uses the Prosody XMPP server to handle chat rooms.<br>
|
||||
The Peertube server will control this Prosody server.<br>
|
||||
Important Note: you have to install Prosody on your server.
|
||||
Please read the <a
|
||||
href="https://github.com/JohnXLivingston/peertube-plugin-livechat/blob/main/documentation/prosody.md"
|
||||
target="_blank"
|
||||
>documentation</a>.`,
|
||||
By default, this plugin comes with a Prosody AppImage.`,
|
||||
private: true
|
||||
})
|
||||
registerSetting({
|
||||
name: 'use-system-prosody',
|
||||
type: 'input-checkbox',
|
||||
label: 'Use system Prosody',
|
||||
descriptionHTML: `Warning: don't check this settings if you are not sure of what you are doing.<br>
|
||||
By checking this settings, your Peertube will use the Prosody server that comes with your system,
|
||||
and not the embeded AppImage.<br>
|
||||
Only use this if you encounter problems with the embedded Prosody.`,
|
||||
private: true,
|
||||
default: false
|
||||
})
|
||||
|
||||
// TODO: fix the settings order. Since there is no more multiple chat-mode, the order is not good.
|
||||
registerSetting({
|
||||
name: 'prosody-list-rooms',
|
||||
label: 'List existing rooms',
|
||||
|
@ -3,7 +3,7 @@ import { migrateSettings } from './lib/migration/settings'
|
||||
import { initSettings } from './lib/settings'
|
||||
import { initCustomFields } from './lib/custom-fields'
|
||||
import { initRouters } from './lib/routers/index'
|
||||
import { ensureProsodyRunning, ensureProsodyNotRunning } from './lib/prosody/ctl'
|
||||
import { prepareProsody, ensureProsodyRunning, ensureProsodyNotRunning } from './lib/prosody/ctl'
|
||||
import decache from 'decache'
|
||||
|
||||
// FIXME: Peertube unregister don't have any parameter.
|
||||
@ -25,6 +25,7 @@ async function register (options: RegisterServerOptions): Promise<any> {
|
||||
await initRouters(options)
|
||||
|
||||
try {
|
||||
await prepareProsody(options)
|
||||
await ensureProsodyRunning(options)
|
||||
} catch (error) {
|
||||
options.peertubeHelpers.logger.error('Error when launching Prosody: ' + (error as string))
|
||||
|
Reference in New Issue
Block a user