mirror of
https://github.com/edumeet/edumeet.git
synced 2026-01-23 02:34:58 +00:00
using new server config in compose environment
This commit is contained in:
parent
d3557b8133
commit
1107faa73b
6 changed files with 43 additions and 385 deletions
|
|
@ -53,351 +53,6 @@ function getListenIps() {
|
|||
|
||||
module.exports =
|
||||
{
|
||||
|
||||
// Auth conf
|
||||
/*
|
||||
auth :
|
||||
{
|
||||
// Always enabled if configured
|
||||
lti :
|
||||
{
|
||||
consumerKey : 'key',
|
||||
consumerSecret : 'secret'
|
||||
},
|
||||
|
||||
// Auth strategy to use (default oidc)
|
||||
strategy : 'oidc',
|
||||
oidc :
|
||||
{
|
||||
// The issuer URL for OpenID Connect discovery
|
||||
// The OpenID Provider Configuration Document
|
||||
// could be discovered on:
|
||||
// issuerURL + '/.well-known/openid-configuration'
|
||||
|
||||
// e.g. google OIDC config
|
||||
// Follow this guide to get credential:
|
||||
// https://developers.google.com/identity/protocols/oauth2/openid-connect
|
||||
// use this issuerURL
|
||||
// issuerURL : 'https://accounts.google.com/',
|
||||
|
||||
issuerURL : 'https://example.com',
|
||||
clientOptions :
|
||||
{
|
||||
client_id : '',
|
||||
client_secret : '',
|
||||
scope : 'openid email profile',
|
||||
// where client.example.com is your edumeet server
|
||||
redirect_uri : 'https://client.example.com/auth/callback'
|
||||
}
|
||||
|
||||
},
|
||||
saml :
|
||||
{
|
||||
// where edumeet.example.com is your edumeet server
|
||||
callbackUrl : 'https://edumeet.example.com/auth/callback',
|
||||
issuer : 'https://edumeet.example.com',
|
||||
entryPoint : 'https://openidp.feide.no/simplesaml/saml2/idp/SSOService.php',
|
||||
privateCert : fs.readFileSync('config/saml_privkey.pem', 'utf-8'),
|
||||
signingCert : fs.readFileSync('config/saml_cert.pem', 'utf-8'),
|
||||
decryptionPvk : fs.readFileSync('config/saml_privkey.pem', 'utf-8'),
|
||||
decryptionCert : fs.readFileSync('config/saml_cert.pem', 'utf-8'),
|
||||
// Federation cert
|
||||
cert : fs.readFileSync('config/federation_cert.pem', 'utf-8')
|
||||
},
|
||||
|
||||
// to create password hash use: node server/utils/password_encode.js cleartextpassword
|
||||
local :
|
||||
{
|
||||
users : [
|
||||
{
|
||||
id : 1,
|
||||
username : 'alice',
|
||||
passwordHash : '$2b$10$PAXXw.6cL3zJLd7ZX.AnL.sFg2nxjQPDmMmGSOQYIJSa0TrZ9azG6',
|
||||
displayName : 'Alice',
|
||||
emails : [ { value: 'alice@atlanta.com' } ]
|
||||
},
|
||||
{
|
||||
id : 2,
|
||||
username : 'bob',
|
||||
passwordHash : '$2b$10$BzAkXcZ54JxhHTqCQcFn8.H6klY/G48t4jDBeTE2d2lZJk/.tvv0G',
|
||||
displayName : 'Bob',
|
||||
emails : [ { value: 'bob@biloxi.com' } ]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
*/
|
||||
// URI and key for requesting geoip-based TURN server closest to the client
|
||||
//turnAPIKey : 'examplekey',
|
||||
//turnAPIURI : 'https://example.com/api/turn',
|
||||
//turnAPIparams : {
|
||||
// 'uri_schema' : 'turn',
|
||||
// 'transport' : 'tcp',
|
||||
// 'ip_ver' : 'ipv4',
|
||||
// 'servercount' : '2'
|
||||
//},
|
||||
//turnAPITimeout : 2 * 1000,
|
||||
// Backup turnservers if REST fails or is not configured
|
||||
//backupTurnServers : [
|
||||
// {
|
||||
// urls : [
|
||||
// 'turn:turn.example.com:443?transport=tcp'
|
||||
// ],
|
||||
// username : 'example',
|
||||
// credential : 'example'
|
||||
// }
|
||||
//],
|
||||
// bittorrent tracker
|
||||
fileTracker : 'wss://tracker.lab.vvc.niif.hu:443',
|
||||
// redis server options
|
||||
redisOptions : {
|
||||
host: 'redis',
|
||||
port: 6379
|
||||
},
|
||||
// session cookie secret
|
||||
cookieSecret : 'T0P-S3cR3t_cook!e',
|
||||
cookieName : 'edumeet.sid',
|
||||
// if you use encrypted private key the set the passphrase
|
||||
tls :
|
||||
{
|
||||
cert : `${__dirname}/../certs/mediasoup-demo.localhost.cert.pem`,
|
||||
// passphrase: 'key_password'
|
||||
key : `${__dirname}/../certs/mediasoup-demo.localhost.key.pem`
|
||||
},
|
||||
// listening Host or IP
|
||||
// If omitted listens on every IP. ("0.0.0.0" and "::")
|
||||
// listeningHost: 'localhost',
|
||||
// Listening port for https server.
|
||||
listeningPort : 3443,
|
||||
// Any http request is redirected to https.
|
||||
// Listening port for http server.
|
||||
listeningRedirectPort : 8080,
|
||||
// Listens only on http, only on listeningPort
|
||||
// listeningRedirectPort disabled
|
||||
// use case: loadbalancer backend
|
||||
httpOnly : false,
|
||||
// WebServer/Express trust proxy config for httpOnly mode
|
||||
// You can find more info:
|
||||
// - https://expressjs.com/en/guide/behind-proxies.html
|
||||
// - https://www.npmjs.com/package/proxy-addr
|
||||
// use case: loadbalancer backend
|
||||
trustProxy : '',
|
||||
// This logger class will have the log function
|
||||
// called every time there is a room created or destroyed,
|
||||
// or peer created or destroyed. This would then be able
|
||||
// to log to a file or external service.
|
||||
/* StatusLogger : class
|
||||
{
|
||||
constructor()
|
||||
{
|
||||
this._queue = new AwaitQueue();
|
||||
}
|
||||
|
||||
// rooms: rooms object
|
||||
// peers: peers object
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
async log({ rooms, peers })
|
||||
{
|
||||
this._queue.push(async () =>
|
||||
{
|
||||
// Do your logging in here, use queue to keep correct order
|
||||
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('Number of rooms: ', rooms.size);
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('Number of peers: ', peers.size);
|
||||
})
|
||||
.catch((error) =>
|
||||
{
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('error in log', error);
|
||||
});
|
||||
}
|
||||
}, */
|
||||
// This function will be called on successful login through oidc.
|
||||
// Use this function to map your oidc userinfo to the Peer object.
|
||||
// The roomId is equal to the room name.
|
||||
// See examples below.
|
||||
// Examples:
|
||||
/*
|
||||
// All authenicated users will be MODERATOR and AUTHENTICATED
|
||||
userMapping : async ({ peer, room, roomId, userinfo }) =>
|
||||
{
|
||||
peer.addRole(userRoles.MODERATOR);
|
||||
peer.addRole(userRoles.AUTHENTICATED);
|
||||
},
|
||||
// All authenicated users will be AUTHENTICATED,
|
||||
// and those with the moderator role set in the userinfo
|
||||
// will also be MODERATOR
|
||||
userMapping : async ({ peer, room, roomId, userinfo }) =>
|
||||
{
|
||||
if (
|
||||
Array.isArray(userinfo.meet_roles) &&
|
||||
userinfo.meet_roles.includes('moderator')
|
||||
)
|
||||
{
|
||||
peer.addRole(userRoles.MODERATOR);
|
||||
}
|
||||
|
||||
if (
|
||||
Array.isArray(userinfo.meet_roles) &&
|
||||
userinfo.meet_roles.includes('meetingadmin')
|
||||
)
|
||||
{
|
||||
peer.addRole(userRoles.ADMIN);
|
||||
}
|
||||
|
||||
peer.addRole(userRoles.AUTHENTICATED);
|
||||
},
|
||||
// First authenticated user will be moderator,
|
||||
// all others will be AUTHENTICATED
|
||||
userMapping : async ({ peer, room, roomId, userinfo }) =>
|
||||
{
|
||||
if (room)
|
||||
{
|
||||
const peers = room.getJoinedPeers();
|
||||
|
||||
if (peers.some((_peer) => _peer.authenticated))
|
||||
peer.addRole(userRoles.AUTHENTICATED);
|
||||
else
|
||||
{
|
||||
peer.addRole(userRoles.MODERATOR);
|
||||
peer.addRole(userRoles.AUTHENTICATED);
|
||||
}
|
||||
}
|
||||
},
|
||||
// All authenicated users will be AUTHENTICATED,
|
||||
// and those with email ending with @example.com
|
||||
// will also be MODERATOR
|
||||
userMapping : async ({ peer, room, roomId, userinfo }) =>
|
||||
{
|
||||
if (userinfo.email && userinfo.email.endsWith('@example.com'))
|
||||
{
|
||||
peer.addRole(userRoles.MODERATOR);
|
||||
}
|
||||
|
||||
peer.addRole(userRoles.AUTHENTICATED);
|
||||
},
|
||||
// All authenicated users will be AUTHENTICATED,
|
||||
// and those with email ending with @example.com
|
||||
// will also be MODERATOR
|
||||
userMapping : async ({ peer, room, roomId, userinfo }) =>
|
||||
{
|
||||
if (userinfo.email && userinfo.email.endsWith('@example.com'))
|
||||
{
|
||||
peer.addRole(userRoles.MODERATOR);
|
||||
}
|
||||
|
||||
peer.addRole(userRoles.AUTHENTICATED);
|
||||
},
|
||||
*/
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
userMapping : async ({ peer, room, roomId, userinfo }) =>
|
||||
{
|
||||
if (userinfo.picture != null)
|
||||
{
|
||||
if (!userinfo.picture.match(/^http/g))
|
||||
{
|
||||
peer.picture = `data:image/jpeg;base64, ${userinfo.picture}`;
|
||||
}
|
||||
else
|
||||
{
|
||||
peer.picture = userinfo.picture;
|
||||
}
|
||||
}
|
||||
if (userinfo['urn:oid:0.9.2342.19200300.100.1.60'] != null)
|
||||
{
|
||||
peer.picture = `data:image/jpeg;base64, ${userinfo['urn:oid:0.9.2342.19200300.100.1.60']}`;
|
||||
}
|
||||
|
||||
if (userinfo.nickname != null)
|
||||
{
|
||||
peer.displayName = userinfo.nickname;
|
||||
}
|
||||
|
||||
if (userinfo.name != null)
|
||||
{
|
||||
peer.displayName = userinfo.name;
|
||||
}
|
||||
|
||||
if (userinfo.displayName != null)
|
||||
{
|
||||
peer.displayName = userinfo.displayName;
|
||||
}
|
||||
|
||||
if (userinfo['urn:oid:2.16.840.1.113730.3.1.241'] != null)
|
||||
{
|
||||
peer.displayName = userinfo['urn:oid:2.16.840.1.113730.3.1.241'];
|
||||
}
|
||||
|
||||
if (userinfo.email != null)
|
||||
{
|
||||
peer.email = userinfo.email;
|
||||
}
|
||||
},
|
||||
// All users have the role "NORMAL" by default. Other roles need to be
|
||||
// added in the "userMapping" function. The following accesses and
|
||||
// permissions are arrays of roles. Roles can be changed in userRoles.js
|
||||
//
|
||||
// Example:
|
||||
// [ userRoles.MODERATOR, userRoles.AUTHENTICATED ]
|
||||
accessFromRoles : {
|
||||
// The role(s) will gain access to the room
|
||||
// even if it is locked (!)
|
||||
[BYPASS_ROOM_LOCK] : [ userRoles.ADMIN ],
|
||||
// The role(s) will gain access to the room without
|
||||
// going into the lobby. If you want to restrict access to your
|
||||
// server to only directly allow authenticated users, you could
|
||||
// add the userRoles.AUTHENTICATED to the user in the userMapping
|
||||
// function, and change to BYPASS_LOBBY : [ userRoles.AUTHENTICATED ]
|
||||
[BYPASS_LOBBY] : [ userRoles.NORMAL ]
|
||||
},
|
||||
permissionsFromRoles : {
|
||||
// The role(s) have permission to lock/unlock a room
|
||||
[CHANGE_ROOM_LOCK] : [ userRoles.MODERATOR ],
|
||||
// The role(s) have permission to promote a peer from the lobby
|
||||
[PROMOTE_PEER] : [ userRoles.NORMAL ],
|
||||
// The role(s) have permission to give/remove other peers roles
|
||||
[MODIFY_ROLE] : [ userRoles.NORMAL ],
|
||||
// The role(s) have permission to send chat messages
|
||||
[SEND_CHAT] : [ userRoles.NORMAL ],
|
||||
// The role(s) have permission to moderate chat
|
||||
[MODERATE_CHAT] : [ userRoles.MODERATOR ],
|
||||
// The role(s) have permission to share audio
|
||||
[SHARE_AUDIO] : [ userRoles.NORMAL ],
|
||||
// The role(s) have permission to share video
|
||||
[SHARE_VIDEO] : [ userRoles.NORMAL ],
|
||||
// The role(s) have permission to share screen
|
||||
[SHARE_SCREEN] : [ userRoles.NORMAL ],
|
||||
// The role(s) have permission to produce extra video
|
||||
[EXTRA_VIDEO] : [ userRoles.NORMAL ],
|
||||
// The role(s) have permission to share files
|
||||
[SHARE_FILE] : [ userRoles.NORMAL ],
|
||||
// The role(s) have permission to moderate files
|
||||
[MODERATE_FILES] : [ userRoles.MODERATOR ],
|
||||
// The role(s) have permission to moderate room (e.g. kick user)
|
||||
[MODERATE_ROOM] : [ userRoles.MODERATOR ]
|
||||
},
|
||||
// Array of permissions. If no peer with the permission in question
|
||||
// is in the room, all peers are permitted to do the action. The peers
|
||||
// that are allowed because of this rule will not be able to do this
|
||||
// action as soon as a peer with the permission joins. In this example
|
||||
// everyone will be able to lock/unlock room until a MODERATOR joins.
|
||||
allowWhenRoleMissing : [ CHANGE_ROOM_LOCK ],
|
||||
// When truthy, the room will be open to all users when as long as there
|
||||
// are allready users in the room
|
||||
activateOnHostJoin : true,
|
||||
// When set, maxUsersPerRoom defines how many users can join
|
||||
// a single room. If not set, there is no limit.
|
||||
// maxUsersPerRoom : 20,
|
||||
// Room size before spreading to new router
|
||||
routerScaleSize : 40,
|
||||
// Socket timout value
|
||||
requestTimeout : 20000,
|
||||
// Socket retries when timeout
|
||||
requestRetries : 3,
|
||||
// If > 0, sets a cache-control max-age (in seconds) to static files responses.
|
||||
staticFilesCachePeriod : 0,
|
||||
// Mediasoup settings
|
||||
mediasoup :
|
||||
{
|
||||
|
|
@ -479,32 +134,6 @@ module.exports =
|
|||
webRtcTransport :
|
||||
{
|
||||
listenIps : getListenIps(),
|
||||
/*[
|
||||
// change 192.0.2.1 IPv4 to your server's IPv4 address!!
|
||||
//{ ip: '192.0.2.1', announcedIp: null }
|
||||
// Can have multiple listening interfaces
|
||||
// change 2001:DB8::1 IPv6 to your server's IPv6 address!!
|
||||
// { ip: '2001:DB8::1', announcedIp: null }
|
||||
],*/
|
||||
initialAvailableOutgoingBitrate : 1000000,
|
||||
minimumAvailableOutgoingBitrate : 600000,
|
||||
// Additional options that are not part of WebRtcTransportOptions.
|
||||
maxIncomingBitrate : 1500000
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
,
|
||||
// Prometheus exporter
|
||||
prometheus : {
|
||||
deidentify : false, // deidentify IP addresses
|
||||
// listen : 'localhost', // exporter listens on this address
|
||||
numeric : true, // show numeric IP addresses
|
||||
port : 8889, // allocated port
|
||||
quiet : false, // include fewer labels
|
||||
// aggregated metrics options
|
||||
period : 15, // update period (seconds)
|
||||
secret : null // if set, checks the authorization header: `Bearer <secret>`
|
||||
}
|
||||
|
||||
};
|
||||
|
|
|
|||
8
compose/config/edumeet-server-config.yaml
Normal file
8
compose/config/edumeet-server-config.yaml
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
redisOptions:
|
||||
host: redis
|
||||
port: 6379
|
||||
|
||||
listeningPort: 3443
|
||||
listeningRedirectPort: 8080
|
||||
httpOnly: false
|
||||
trustProxy: ''
|
||||
|
|
@ -18,6 +18,7 @@ services:
|
|||
volumes:
|
||||
- ${PWD}/..:/edumeet
|
||||
- ${PWD}/config/edumeet-server-config.js:/edumeet/server/config/config.js:ro
|
||||
- ${PWD}/config/edumeet-server-config.yaml:/edumeet/server/config/config.yaml:ro
|
||||
- ${PWD}/config/edumeet-app-config.js:/edumeet/app/public/config/config.js:ro
|
||||
network_mode: "host"
|
||||
extra_hosts:
|
||||
|
|
|
|||
|
|
@ -395,7 +395,7 @@ class Room extends EventEmitter
|
|||
else if (this._hasAccess(peer, BYPASS_ROOM_LOCK))
|
||||
this._peerJoining(peer);
|
||||
else if (
|
||||
'maxUsersPerRoom' in config &&
|
||||
config.maxUsersPerRoom &&
|
||||
(
|
||||
Object.keys(this._peers).length +
|
||||
this._lobby.peerList().length
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ const configSchema = convict({
|
|||
turnAPIURI :
|
||||
{
|
||||
doc : 'TURN server URL for requesting a geoip-based TURN server closest to the client.',
|
||||
format : 'url',
|
||||
format : String,
|
||||
default : ''
|
||||
},
|
||||
turnAPIparams :
|
||||
|
|
@ -94,9 +94,21 @@ const configSchema = convict({
|
|||
default : 'wss://tracker.lab.vvc.niif.hu:443'
|
||||
},
|
||||
redisOptions : {
|
||||
doc : 'Redis server options.',
|
||||
format : Object,
|
||||
default : {}
|
||||
host : {
|
||||
doc : 'Redis server host.',
|
||||
format : String,
|
||||
default : 'localhost'
|
||||
},
|
||||
port : {
|
||||
doc : 'Redis server port.',
|
||||
format : 'port',
|
||||
default : 6379
|
||||
},
|
||||
password : {
|
||||
doc : 'Redis server password.',
|
||||
format : String,
|
||||
default : ''
|
||||
}
|
||||
},
|
||||
cookieSecret : {
|
||||
doc : 'Session cookie secret.',
|
||||
|
|
@ -123,7 +135,7 @@ const configSchema = convict({
|
|||
listeningHost : {
|
||||
doc : 'The listening Host or IP address. If omitted listens on every IP. ("0.0.0.0" and "::").',
|
||||
format : String,
|
||||
default : null
|
||||
default : ''
|
||||
},
|
||||
listeningPort : {
|
||||
doc : 'The HTTPS listening port.',
|
||||
|
|
@ -153,12 +165,12 @@ const configSchema = convict({
|
|||
roomsUnlocked : {
|
||||
doc : 'An array of rooms users can enter without waiting in the lobby.',
|
||||
format : Array,
|
||||
default : null
|
||||
default : []
|
||||
},
|
||||
maxUsersPerRoom : {
|
||||
doc : 'It defines how many users can join a single room. If not set, no limit is applied.',
|
||||
format : 'nat',
|
||||
default : null
|
||||
default : 0
|
||||
},
|
||||
routerScaleSize : {
|
||||
doc : 'Room size before spreading to a new router.',
|
||||
|
|
@ -219,7 +231,7 @@ const configSchema = convict({
|
|||
// Router media codecs.
|
||||
mediaCodecs : {
|
||||
doc : 'The Mediasoup codecs settings.',
|
||||
format : Object,
|
||||
format : '*',
|
||||
default :
|
||||
[
|
||||
{
|
||||
|
|
@ -332,7 +344,7 @@ const configSchema = convict({
|
|||
secret : {
|
||||
doc : 'The Prometheus exporter authorization header: `Bearer <secret>` required to allow scraping.',
|
||||
format : String,
|
||||
default : null
|
||||
default : ''
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
@ -376,7 +388,7 @@ let config: any = {};
|
|||
let configError = '';
|
||||
let configLoaded = false;
|
||||
|
||||
// Load config from window object
|
||||
// Load config from file
|
||||
for (const format of [ 'json', 'json5', 'yaml', 'yml', 'toml' ]) // eslint-disable-line no-restricted-syntax
|
||||
{
|
||||
const filepath = `./config/config.${format}`;
|
||||
|
|
@ -430,7 +442,7 @@ if (fs.existsSync(`${__dirname}/../config/config.js`))
|
|||
}
|
||||
|
||||
// eslint-disable-next-line
|
||||
logger.info('Using config:', config);
|
||||
// logger.debug('Using config:', config);
|
||||
|
||||
//
|
||||
export {
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ const {
|
|||
loginHelper,
|
||||
logoutHelper
|
||||
} = require('./httpHelper');
|
||||
const { config } = require('./lib/config');
|
||||
const { config, configError } = require('./lib/config');
|
||||
const interactiveServer = require('./lib/interactiveServer');
|
||||
const promExporter = require('./lib/promExporter');
|
||||
|
||||
|
|
@ -33,13 +33,21 @@ const imsLti = require('ims-lti');
|
|||
const SAMLStrategy = require('passport-saml').Strategy;
|
||||
const LocalStrategy = require('passport-local').Strategy;
|
||||
const redis = require('redis');
|
||||
const redisClient = redis.createClient(config.redisOptions);
|
||||
const { Issuer, Strategy } = require('openid-client');
|
||||
const expressSession = require('express-session');
|
||||
const RedisStore = require('connect-redis')(expressSession);
|
||||
const sharedSession = require('express-socket.io-session');
|
||||
const { v4: uuidv4 } = require('uuid');
|
||||
|
||||
if (configError)
|
||||
{
|
||||
/* eslint-disable no-console */
|
||||
console.error(`Invalid config file: ${configError}`);
|
||||
process.exit(-1);
|
||||
}
|
||||
|
||||
const redisClient = redis.createClient(config.redisOptions);
|
||||
|
||||
/* eslint-disable no-console */
|
||||
console.log('- process.env.DEBUG:', process.env.DEBUG);
|
||||
console.log('- config.mediasoup.worker.logLevel:', config.mediasoup.worker.logLevel);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue