diff --git a/Makefile b/Makefile index b085be4..cbf9c7b 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ FORCE_REBUILD ?= 0 JITSI_RELEASE ?= stable JITSI_BUILD ?= latest JITSI_REPO ?= jitsi -JITSI_SERVICES ?= base base-java web prosody jicofo jvb jigasi +JITSI_SERVICES ?= base base-java web prosody jicofo jvb jigasi etherpad ifeq ($(FORCE_REBUILD), 1) BUILD_ARGS = "--no-cache" diff --git a/README.md b/README.md index a48c8cc..a2a1eb6 100644 --- a/README.md +++ b/README.md @@ -35,7 +35,10 @@ follow these steps: a different port, in case you edited the compose file). If you want to use jigasi too, first configure your env file with SIP credentials -and then run Docker Compose as follows: ``docker-compose -f docker-compose.yml -f jigasi.yml up -d`` +and then run Docker Compose as follows: ``docker-compose -f docker-compose.yml -f jigasi.yml up`` + +If you want to enable document sharing via [Etherpad], configure it and run Docker Compose as +follows: ``docker-compose -f docker-compose.yml -f etherpad.yml up`` ## Architecture @@ -199,6 +202,17 @@ This can be tested using the [jwt.io] debugger. Use the following samople payloa } ``` +### Shared document editing using Etherpad + +You can collaboratively edit a document via [Etherpad]. In order to enable it, set the config options bellow and run +Docker Compose with the additional config file `etherpad.yml`. + +Here are the required options: + +Variable | Description | Example +--- | --- | --- +`ETHERPAD_URL_BASE` | Set etherpad-lite URL | http://etherpad.meet.jitsi:9001 + ### Advanced configuration These configuration options are already set and generally don't need to be changed. @@ -270,4 +284,5 @@ option. [ICE]: https://en.wikipedia.org/wiki/Interactive_Connectivity_Establishment [STUN]: https://en.wikipedia.org/wiki/STUN [jwt.io]: https://jwt.io/#debugger-io +[Etherpad]: https://github.com/ether/etherpad-lite diff --git a/docker-compose.yml b/docker-compose.yml index 42337f9..7092ad8 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -24,6 +24,7 @@ services: - XMPP_BOSH_URL_BASE - XMPP_GUEST_DOMAIN - XMPP_MUC_DOMAIN + - ETHERPAD_URL_BASE - TZ networks: meet.jitsi: diff --git a/env.example b/env.example index fbf4387..32c5ec1 100644 --- a/env.example +++ b/env.example @@ -33,6 +33,14 @@ TZ=Europe/Amsterdam #LETSENCRYPT_EMAIL=alice@atlanta.net +# +# Etherpad integration (for document sharing) +# + +# Set etherpad-lite URL (uncomment to enable). +#ETHERPAD_URL_BASE=http://etherpad.meet.jitsi:9001 + + # # Basic Jigasi configuration options (needed for SIP gateway support) # diff --git a/etherpad.yml b/etherpad.yml new file mode 100644 index 0000000..e033a99 --- /dev/null +++ b/etherpad.yml @@ -0,0 +1,10 @@ +version: '3' + +services: + # Etherpad: real-time collaborative document editing + etherpad: + image: jitsi/etherpad + networks: + meet.jitsi: + aliases: + - etherpad.meet.jitsi diff --git a/etherpad/Dockerfile b/etherpad/Dockerfile new file mode 100644 index 0000000..c74e99b --- /dev/null +++ b/etherpad/Dockerfile @@ -0,0 +1,5 @@ +FROM etherpad/etherpad + +ADD ./rootfs/defaults/settings.json /opt/etherpad-lite/settings.json + +EXPOSE 9001 diff --git a/etherpad/Makefile b/etherpad/Makefile new file mode 100644 index 0000000..06eb689 --- /dev/null +++ b/etherpad/Makefile @@ -0,0 +1,4 @@ +build: + docker build $(BUILD_ARGS) -t jitsi/etherpad . + +.PHONY: build diff --git a/etherpad/rootfs/defaults/settings.json b/etherpad/rootfs/defaults/settings.json new file mode 100644 index 0000000..f01f619 --- /dev/null +++ b/etherpad/rootfs/defaults/settings.json @@ -0,0 +1,418 @@ +/* + * This file must be valid JSON. But comments are allowed + * + * Please edit settings.json, not settings.json.template + * + * Please note that since Etherpad 1.6.0 you can store DB credentials in a + * separate file (credentials.json). + */ +{ + /* + * Name your instance! + */ + "title": "Video Chat", + + /* + * favicon default name + * alternatively, set up a fully specified Url to your own favicon + */ + "favicon": "favicon.ico", + + /* + * IP and port which etherpad should bind at + */ + "ip": "0.0.0.0", + "port" : 9001, + + /* + * Option to hide/show the settings.json in admin page. + * + * Default option is set to true + */ + "showSettingsInAdminPage" : true, + + /* + * Node native SSL support + * + * This is disabled by default. + * Make sure to have the minimum and correct file access permissions set so + * that the Etherpad server can access them + */ + + /* + "ssl" : { + "key" : "/path-to-your/epl-server.key", + "cert" : "/path-to-your/epl-server.crt", + "ca": ["/path-to-your/epl-intermediate-cert1.crt", "/path-to-your/epl-intermediate-cert2.crt"] + }, + */ + + /* + * The type of the database. + * + * You can choose between many DB drivers, for example: dirty, postgres, + * sqlite, mysql. + * + * You shouldn't use "dirty" for for anything else than testing or + * development. + * + * For a complete list of the supported drivers, please consult: + * https://www.npmjs.com/package/ueberdb2 + */ + + "dbType" : "dirty", + + /* + * Database specific settings (dependent on dbType). + * + * Remember that since Etherpad 1.6.0 you can also store these informations in + * credentials.json. + */ + "dbSettings" : { + "filename" : "var/dirty.db" + }, + + /* + * An Example of MySQL Configuration (commented out). + * + * See: https://github.com/ether/etherpad-lite/wiki/How-to-use-Etherpad-Lite-with-MySQL + */ + + /* + "dbType" : "mysql", + "dbSettings" : { + "user" : "etherpaduser", + "host" : "localhost", + "port" : 3306, + "password": "PASSWORD", + "database": "etherpad_lite_db", + "charset" : "utf8mb4" + }, + */ + + /* + * The default text of a pad + */ + "defaultPadText" : "Welcome to Web Chat!\n\n", + + /* + * Default Pad behavior. + * + * Change them if you want to override. + */ + "padOptions": { + "noColors": false, + "showControls": true, + "showChat": true, + "showLineNumbers": true, + "useMonospaceFont": false, + "userName": false, + "userColor": false, + "rtl": false, + "alwaysShowChat": false, + "chatAndUsers": false, + "lang": "en-gb" + }, + + /* + * Pad Shortcut Keys + */ + "padShortcutEnabled" : { + "altF9" : true, /* focus on the File Menu and/or editbar */ + "altC" : true, /* focus on the Chat window */ + "cmdShift2" : true, /* shows a gritter popup showing a line author */ + "delete" : true, + "return" : true, + "esc" : true, /* in mozilla versions 14-19 avoid reconnecting pad */ + "cmdS" : true, /* save a revision */ + "tab" : true, /* indent */ + "cmdZ" : true, /* undo/redo */ + "cmdY" : true, /* redo */ + "cmdI" : true, /* italic */ + "cmdB" : true, /* bold */ + "cmdU" : true, /* underline */ + "cmd5" : true, /* strike through */ + "cmdShiftL" : true, /* unordered list */ + "cmdShiftN" : true, /* ordered list */ + "cmdShift1" : true, /* ordered list */ + "cmdShiftC" : true, /* clear authorship */ + "cmdH" : true, /* backspace */ + "ctrlHome" : true, /* scroll to top of pad */ + "pageUp" : true, + "pageDown" : true + }, + + /* + * Should we suppress errors from being visible in the default Pad Text? + */ + "suppressErrorsInPadText" : true, + + /* + * If this option is enabled, a user must have a session to access pads. + * This effectively allows only group pads to be accessed. + */ + "requireSession" : false, + + /* + * Users may edit pads but not create new ones. + * + * Pad creation is only via the API. + * This applies both to group pads and regular pads. + */ + "editOnly" : false, + + /* + * If set to true, those users who have a valid session will automatically be + * granted access to password protected pads. + */ + "sessionNoPassword" : false, + + /* + * If true, all css & js will be minified before sending to the client. + * + * This will improve the loading performance massively, but makes it difficult + * to debug the javascript/css + */ + "minify" : true, + + /* + * How long may clients use served javascript code (in seconds)? + * + * Not setting this may cause problems during deployment. + * Set to 0 to disable caching. + */ + "maxAge" : 21600, // 60 * 60 * 6 = 6 hours + + /* + * Absolute path to the Abiword executable. + * + * Abiword is needed to get advanced import/export features of pads. Setting + * it to null disables Abiword and will only allow plain text and HTML + * import/exports. + */ + "abiword" : null, + + /* + * This is the absolute path to the soffice executable. + * + * LibreOffice can be used in lieu of Abiword to export pads. + * Setting it to null disables LibreOffice exporting. + */ + "soffice" : null, + + /* + * Path to the Tidy executable. + * + * Tidy is used to improve the quality of exported pads. + * Setting it to null disables Tidy. + */ + "tidyHtml" : null, + + /* + * Allow import of file types other than the supported ones: + * txt, doc, docx, rtf, odt, html & htm + */ + "allowUnknownFileEnds" : true, + + /* + * This setting is used if you require authentication of all users. + * + * Note: "/admin" always requires authentication. + */ + "requireAuthentication" : false, + + /* + * Require authorization by a module, or a user with is_admin set, see below. + */ + "requireAuthorization" : false, + + /* + * When you use NGINX or another proxy/load-balancer set this to true. + */ + "trustProxy" : false, + + /* + * Privacy: disable IP logging + */ + "disableIPlogging" : false, + + /* + * Time (in seconds) to automatically reconnect pad when a "Force reconnect" + * message is shown to user. + * + * Set to 0 to disable automatic reconnection. + */ + "automaticReconnectionTimeout" : 0, + + /* + * By default, when caret is moved out of viewport, it scrolls the minimum + * height needed to make this line visible. + */ + "scrollWhenFocusLineIsOutOfViewport": { + + /* + * Percentage of viewport height to be additionally scrolled. + * + * E.g.: use "percentage.editionAboveViewport": 0.5, to place caret line in + * the middle of viewport, when user edits a line above of the + * viewport + * + * Set to 0 to disable extra scrolling + */ + "percentage": { + "editionAboveViewport": 0, + "editionBelowViewport": 0 + }, + + /* + * Time (in milliseconds) used to animate the scroll transition. + * Set to 0 to disable animation + */ + "duration": 0, + + /* + * Flag to control if it should scroll when user places the caret in the + * last line of the viewport + */ + "scrollWhenCaretIsInTheLastLineOfViewport": false, + + /* + * Percentage of viewport height to be additionally scrolled when user + * presses arrow up in the line of the top of the viewport. + * + * Set to 0 to let the scroll to be handled as default by Etherpad + */ + "percentageToScrollWhenUserPressesArrowUp": 0 + }, + + /* + * Users for basic authentication. + * + * is_admin = true gives access to /admin. + * If you do not uncomment this, /admin will not be available! + * + * WARNING: passwords should not be stored in plaintext in this file. + * If you want to mitigate this, please install ep_hash_auth and + * follow the section "secure your installation" in README.md + */ + + /* + "users": { + "admin": { + // "password" can be replaced with "hash" if you install ep_hash_auth + "password": "changeme1", + "is_admin": true + }, + "user": { + // "password" can be replaced with "hash" if you install ep_hash_auth + "password": "changeme1", + "is_admin": false + } + }, + */ + + /* + * Restrict socket.io transport methods + */ + "socketTransportProtocols" : ["xhr-polling", "jsonp-polling", "htmlfile"], + + /* + * Allow Load Testing tools to hit the Etherpad Instance. + * + * WARNING: this will disable security on the instance. + */ + "loadTest": false, + + /* + * Disable indentation on new line when previous line ends with some special + * chars (':', '[', '(', '{') + */ + + /* + "indentationOnNewLine": false, + */ + + /* + * Toolbar buttons configuration. + * + * Uncomment to customize. + */ + + /* + "toolbar": { + "left": [ + ["bold", "italic", "underline", "strikethrough"], + ["orderedlist", "unorderedlist", "indent", "outdent"], + ["undo", "redo"], + ["clearauthorship"] + ], + "right": [ + ["importexport", "timeslider", "savedrevision"], + ["settings", "embed"], + ["showusers"] + ], + "timeslider": [ + ["timeslider_export", "timeslider_returnToPad"] + ] + }, + */ + + /* + * The log level we are using. + * + * Valid values: DEBUG, INFO, WARN, ERROR + */ + "loglevel": "INFO", + + /* + * Logging configuration. See log4js documentation for further information: + * https://github.com/nomiddlename/log4js-node + * + * You can add as many appenders as you want here. + */ + "logconfig" : + { "appenders": [ + { "type": "console" + //, "category": "access"// only logs pad access + } + + /* + , { "type": "file" + , "filename": "your-log-file-here.log" + , "maxLogSize": 1024 + , "backups": 3 // how many log files there're gonna be at max + //, "category": "test" // only log a specific category + } + */ + + /* + , { "type": "logLevelFilter" + , "level": "warn" // filters out all log messages that have a lower level than "error" + , "appender": + { Use whatever appender you want here } + } + */ + + /* + , { "type": "logLevelFilter" + , "level": "error" // filters out all log messages that have a lower level than "error" + , "appender": + { "type": "smtp" + , "subject": "An error occurred in your EPL instance!" + , "recipients": "bar@blurdybloop.com, baz@blurdybloop.com" + , "sendInterval": 300 // 60 * 5 = 5 minutes -- will buffer log messages; set to 0 to send a mail for every message + , "transport": "SMTP", "SMTP": { // see https://github.com/andris9/Nodemailer#possible-transport-methods + "host": "smtp.example.com", "port": 465, + "secureConnection": true, + "auth": { + "user": "foo@example.com", + "pass": "bar_foo" + } + } + } + } + */ + + ] + } // logconfig +} diff --git a/web/rootfs/defaults/meet.conf b/web/rootfs/defaults/meet.conf index 876325d..c8331ed 100644 --- a/web/rootfs/defaults/meet.conf +++ b/web/rootfs/defaults/meet.conf @@ -32,3 +32,19 @@ location /http-bind { proxy_set_header X-Forwarded-For $remote_addr; proxy_set_header Host {{ .Env.XMPP_DOMAIN }}; } + +{{ if .Env.ETHERPAD_URL_BASE }} +# Etherpad-lite +location /etherpad/ { + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection 'upgrade'; + proxy_set_header Host $host; + proxy_cache_bypass $http_upgrade; + + proxy_pass {{ .Env.ETHERPAD_URL_BASE }}/; + proxy_set_header X-Forwarded-For $remote_addr; + proxy_buffering off; + proxy_set_header Host {{ .Env.XMPP_DOMAIN }}; +} +{{ end }} diff --git a/web/rootfs/etc/cont-init.d/10-config b/web/rootfs/etc/cont-init.d/10-config index 326c778..26053e0 100644 --- a/web/rootfs/etc/cont-init.d/10-config +++ b/web/rootfs/etc/cont-init.d/10-config @@ -72,6 +72,12 @@ if [[ ! -f /config/config.js ]]; then -e "s#// authdomain:.*#authdomain: '${XMPP_DOMAIN}',#" \ /config/config.js fi + + if [[ ! -z "${ETHERPAD_URL_BASE}" && -z "$(grep -om1 'etherpad_base:' /config/config.js)" ]]; then + sed -i \ + -e "/enableWelcomePage/a\ etherpad_base: '/etherpad/p/'," \ + /config/config.js + fi fi if [[ ! -f /config/interface_config.js ]]; then