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:
parent
91ea442ce6
commit
459d92cef9
11
CHANGELOG.md
11
CHANGELOG.md
@ -21,10 +21,21 @@ the server will try to use the new mode after updating the plugin.
|
||||
If you don't want the chat server to be active, just uninstall the plugin
|
||||
(settings won't be lost, you just have to download it again).
|
||||
|
||||
### Important Notes
|
||||
|
||||
This version of the plugin comes with a builtin Prosody AppImage.
|
||||
|
||||
If you were using this plugin before this version, and if you had installed Prosody manually,
|
||||
you can safely uninstall Prosody.
|
||||
|
||||
If you were using the custom Peertube docker image that is embedding Prosody, you can switch back to the official
|
||||
Peertube image.
|
||||
|
||||
### New Features
|
||||
|
||||
* Removed deprecated modes, only keeping «Prosody server controlled by Peertube».
|
||||
* BOSH proxy optimization + enabling websocket.
|
||||
* Builtin Prosody AppImage. No more manual installation required.
|
||||
|
||||
### Changes
|
||||
|
||||
|
54
build-prosody.sh
Normal file
54
build-prosody.sh
Normal file
@ -0,0 +1,54 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -euo pipefail
|
||||
set -x
|
||||
|
||||
rootdir="$(pwd)"
|
||||
prosody_build_dir="$rootdir/build/prosody"
|
||||
prosody_destination_dir="$rootdir/dist/server/prosody"
|
||||
|
||||
if [[ ! -d "$prosody_build_dir" ]]; then
|
||||
mkdir -p "$prosody_build_dir"
|
||||
fi
|
||||
|
||||
cd "$prosody_build_dir"
|
||||
|
||||
if [ -f "$prosody_build_dir/livechat-prosody-x86_64.AppImage" ]; then
|
||||
echo "Prosody image already built."
|
||||
else
|
||||
echo "Prosody image must be build..."
|
||||
|
||||
# Prerequisite: you must have python3-venv installed on your system
|
||||
if [[ ! -d "venv" ]]; then
|
||||
echo "Creating the python venv..."
|
||||
python3 -m venv venv
|
||||
fi
|
||||
|
||||
echo "Activating the python venv..."
|
||||
source venv/bin/activate
|
||||
|
||||
echo "Installing appimage-builder..."
|
||||
pip3 install appimage-builder
|
||||
|
||||
echo "Copying appimage source files..."
|
||||
cp "$rootdir/prosody/appimage_x86_64.yml" "$prosody_build_dir/appimage_x86_64.yml"
|
||||
cp "$rootdir/prosody/launcher.lua" "$prosody_build_dir/launcher.lua"
|
||||
|
||||
echo "Building Prosody..."
|
||||
appimage-builder --recipe "$prosody_build_dir/appimage_x86_64.yml"
|
||||
fi
|
||||
|
||||
echo "Copying Prosody dist files..."
|
||||
mkdir -p "$prosody_destination_dir" && cp $prosody_build_dir/livechat-prosody-x86_64.AppImage "$prosody_destination_dir/"
|
||||
|
||||
# For some obscur reason, if we keep AppDir and appimage-build folders,
|
||||
# and if we try to install the plugin using the Peertube CLI,
|
||||
# the installation fails because there are some subfolders that are right protected.
|
||||
# To avoid that, we clean them:
|
||||
echo "Cleaning build folders..."
|
||||
rm -rf "$prosody_build_dir/AppDir"
|
||||
rm -rf "$prosody_build_dir/appimage-build"
|
||||
|
||||
echo "Prosody AppImage OK."
|
||||
|
||||
exit 0
|
@ -88,6 +88,7 @@
|
||||
"clean:light": "rm -rf dist/*",
|
||||
"prepare": "npm run clean && npm run build",
|
||||
"build:converse": "bash conversejs/build-conversejs.sh",
|
||||
"build:prosody": "bash build-prosody.sh",
|
||||
"build:images": "mkdir -p dist/client/images && npx svgo -f public/images/ -o dist/client/images/",
|
||||
"build:avatars": "mkdir -p dist/server/avatars && ./build-avatars.js",
|
||||
"build:webpack": "webpack --mode=production",
|
||||
@ -95,7 +96,7 @@
|
||||
"build:serverconverse": "mkdir -p dist/server/conversejs && cp conversejs/index.html dist/server/conversejs/",
|
||||
"build:prosodymodules": "mkdir -p dist/server/prosody-modules && cp -r prosody-modules/* dist/server/prosody-modules/",
|
||||
"build:styles": "sass assets:dist/assets",
|
||||
"build": "npm-run-all -s clean:light -p build:converse build:images build:avatars build:webpack build:server build:serverconverse build:prosodymodules build:styles",
|
||||
"build": "npm-run-all -s clean:light -p build:converse build:prosody build:images build:avatars build:webpack build:server build:serverconverse build:prosodymodules build:styles",
|
||||
"lint": "npm-run-all -s lint:script lint:styles",
|
||||
"lint:script": "npx eslint --ext .js --ext .ts .",
|
||||
"lint:styles": "stylelint 'conversejs/**/*.scss' 'assets/**/*.css'",
|
||||
|
59
prosody/appimage_x86_64.yml
Normal file
59
prosody/appimage_x86_64.yml
Normal file
@ -0,0 +1,59 @@
|
||||
# This file is meant to be used with appimage-builder: https://appimage-builder.readthedocs.io
|
||||
# See it is use in the build-prosody.sh script.
|
||||
|
||||
version: 1
|
||||
|
||||
script:
|
||||
# Remove any previous build
|
||||
- rm -rf AppDir | true
|
||||
# Make usr dirs
|
||||
- mkdir -p AppDir/usr/bin
|
||||
# Copy the launcher code into the AppDir
|
||||
- cp ./launcher.lua AppDir/usr/bin/
|
||||
|
||||
AppDir:
|
||||
path: ./AppDir
|
||||
|
||||
app_info:
|
||||
id: org.peertube-plugin-livechat.prosody
|
||||
name: prosody
|
||||
icon: utilities-terminal
|
||||
version: 1.0.0
|
||||
exec: usr/bin/lua5.2
|
||||
exec_args: "$APPDIR/usr/bin/launcher.lua $@"
|
||||
|
||||
apt:
|
||||
arch: amd64
|
||||
sources:
|
||||
- sourceline: 'deb [arch=amd64] https://deb.debian.org/debian/ bullseye main contrib'
|
||||
key_url: 'http://keyserver.ubuntu.com/pks/lookup?op=get&search=0x648ACFD622F3D138'
|
||||
- sourceline: 'deb [arch=amd64] https://deb.debian.org/debian/ bullseye-backports main contrib'
|
||||
|
||||
include:
|
||||
- lua5.2
|
||||
- prosody
|
||||
|
||||
files:
|
||||
exclude:
|
||||
- usr/share/man
|
||||
- usr/share/doc/*/README.*
|
||||
- usr/share/doc/*/changelog.*
|
||||
- usr/share/doc/*/NEWS.*
|
||||
- usr/share/doc/*/TODO.*
|
||||
- etc/init.d/*
|
||||
- etc/logrotate.d/*
|
||||
|
||||
runtime:
|
||||
# Here we use the path_mappings to rewrite, on runtime, all paths.
|
||||
# Note: this assume that peertube-plugin-livechat is not in a subdir of one of following mappings.
|
||||
# This seems a reasonable assumption.
|
||||
path_mappings:
|
||||
- /etc/:$APPDIR/etc/
|
||||
- /lib/:$APPDIR/lib/
|
||||
- /lib64/:$APPDIR/lib64/
|
||||
- /runtime/:$APPDIR/runtime/
|
||||
- /usr/:$APPDIR/usr/
|
||||
|
||||
AppImage:
|
||||
arch: x86_64
|
||||
file_name: 'livechat-prosody-x86_64.AppImage'
|
13
prosody/launcher.lua
Normal file
13
prosody/launcher.lua
Normal file
@ -0,0 +1,13 @@
|
||||
#!/usr/bin/env lua
|
||||
|
||||
-- This file is a launcher, that takes the first argument to choose what to launch.
|
||||
|
||||
local what = table.remove(arg, 1);
|
||||
if what == 'prosody' then
|
||||
dofile('/usr/bin/prosody');
|
||||
elseif what == 'prosodyctl' then
|
||||
dofile('/usr/bin/prosodyctl');
|
||||
else
|
||||
print("Unknown command: "..what);
|
||||
os.exit(1);
|
||||
end
|
@ -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))
|
||||
|
Loading…
x
Reference in New Issue
Block a user