diff --git a/roles/etherpad/.gitignore b/roles/etherpad/.gitignore new file mode 100644 index 0000000..0c7f9f6 --- /dev/null +++ b/roles/etherpad/.gitignore @@ -0,0 +1,3 @@ +.molecule +.tox +molecule/*/.molecule diff --git a/roles/etherpad/.travis.yml b/roles/etherpad/.travis.yml new file mode 100644 index 0000000..68c34a5 --- /dev/null +++ b/roles/etherpad/.travis.yml @@ -0,0 +1,19 @@ +--- +language: python +cache: pip + +env: + - MOLECULE_DISTRO=debian10 + - MOLECULE_DISTRO=debian9 + - MOLECULE_DISTRO=ubuntu1804 + - MOLECULE_DISTRO=ubuntu1604 + +install: + # Install test dependencies. + - pip install molecule docker ansible-lint yamllint + +script: + - molecule test -s docker + +notifications: + webhooks: https://galaxy.ansible.com/api/v1/notifications/ diff --git a/roles/etherpad/.yamllint b/roles/etherpad/.yamllint new file mode 100644 index 0000000..c5ae64b --- /dev/null +++ b/roles/etherpad/.yamllint @@ -0,0 +1,12 @@ +--- +extends: default + +rules: + braces: + max-spaces-inside: 1 + level: error + brackets: + max-spaces-inside: 1 + level: error + line-length: disable + truthy: disable diff --git a/roles/etherpad/defaults/main.yml b/roles/etherpad/defaults/main.yml new file mode 100644 index 0000000..41a9373 --- /dev/null +++ b/roles/etherpad/defaults/main.yml @@ -0,0 +1,99 @@ +--- +etherpad: + title: "Etherpad" + favicon: "favicon.ico" + ip: 0.0.0.0 + port: 9001 + users: [] + # - + # name: admin + # password: "" + # is_admin: "true" + default_text: '"Welcome to Etherpad!\\n\\nThis pad text is synchronized as you type, so that everyone viewing this page sees the same text. This allows you to collaborate seamlessly on documents!\\n\\nGet involved with Etherpad at http:\\/\\/etherpad.org\\n"' + pad_options_no_colors: "false" + pad_options_show_controls: "true" + pad_options_show_chat: "true" + pad_options_show_line_numbers: "true" + pad_options_use_monospace_font: "false" + pad_options_user_name: "false" + pad_options_user_color: "false" + pad_options_rtl: "false" + pad_options_always_show_chat: "false" + pad_options_chat_and_users: "false" + pad_options_lang: "en-gb" + pad_shortcut_alt_f9: "true" + pad_shortcut_alt_c: "true" + pad_shortcut_cmd_shft_2: "true" + pad_shortcut_delete: "true" + pad_shortcut_return: "true" + pad_shortcut_esc: "true" + pad_shortcut_cmd_s: "true" + pad_shortcut_tab: "true" + pad_shortcut_cmd_z: "true" + pad_shortcut_cmd_y: "true" + pad_shortcut_cmd_i: "true" + pad_shortcut_cmd_b: "true" + pad_shortcut_cmd_u: "true" + pad_shortcut_cmd_5: "true" + pad_shortcut_cmd_shift_l: "true" + pad_shortcut_cmd_shift_n: "true" + pad_shortcut_cmd_shift_1: "true" + pad_shortcut_cmd_shift_c: "true" + pad_shortcut_cmd_h: "true" + pad_shortcut_ctrl_home: "true" + pad_shortcut_page_up: "true" + pad_shortcut_page_down: "true" + suppress_errors_in_pad_text: "false" + require_session: "false" + edit_only: "false" + session_no_password: "false" + minify: "true" + max_age: 21600 + abiword: "null" + soffice: "null" + tidyhtml: "null" + allow_unknown_file_ends: "true" + require_authentication: "false" + require_authorization: "false" + trust_proxy: "false" + socket_transport_protocols: ["xhr-polling", "jsonp-polling", "htmlfile"] + load_test: "false" + indentation_on_new_line: "false" + automatic_reconnection_timeout: 0 + expose_version: "false" + 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"] + log_level: "INFO" + abiword_enabled: False + console_enabled: False + monit_enabled: False + # list of etherpad plugins to be installed + plugins: [] + plugins_state: present + + mysql_database_host: /var/run/postgresql + mysql_database_name: etherpad + mysql_database_user: etherpad + mysql_database_password: etherpad + mysql_database_port: 3306 + + # Recommendation for large setups is MyISAM + mysql_database_engine: InnoDB + mysql_database_collation: utf8mb4_bin + mysql_database_charset: utf8mb4 + + # Settings for plugin 'ep_table_of_contents' + toc_disable: "true" + + # Settings for plugin 'ep_auth_author' + # auth_author_prefix: diff --git a/roles/etherpad/handlers/main.yml b/roles/etherpad/handlers/main.yml new file mode 100644 index 0000000..17f31a4 --- /dev/null +++ b/roles/etherpad/handlers/main.yml @@ -0,0 +1,5 @@ +--- +- name: restart etherpad-lite + service: + name: etherpad-lite + state: restarted diff --git a/roles/etherpad/tasks/abiword.yml b/roles/etherpad/tasks/abiword.yml new file mode 100644 index 0000000..310ef13 --- /dev/null +++ b/roles/etherpad/tasks/abiword.yml @@ -0,0 +1,6 @@ +--- + +- name: Ensure abiword package is installed + apt: + pkg: abiword + state: present diff --git a/roles/etherpad/tasks/main.yml b/roles/etherpad/tasks/main.yml new file mode 100644 index 0000000..58f147d --- /dev/null +++ b/roles/etherpad/tasks/main.yml @@ -0,0 +1,43 @@ +--- +- include: postgresql.yml + +- name: ensure etherpad user is present + user: + name: "etherpad" + home: "/srv/etherpad" + shell: "/bin/bash" + state: present + +- name: ensure etherpad is latest + git: + repo: "https://github.com/ether/etherpad-lite" + dest: "/srv/etherpad/etherpad" + version: "master" + become: true + become_user: "etherpad" + register: repository + +- name: ensure etherpad systemd unit is latest + template: + src: etherpad-lite.service.j2 + dest: /etc/systemd/system/etherpad-lite.service + owner: root + group: root + mode: 0644 + +- name: ensure etherpad will start after system is booted + service: + name: etherpad-lite + enabled: yes + +- name: install etherpad plugins + npm: + name: "{{ item }}" + path: "{{ etherpad.path }}" + state: "{{ etherpad.plugins_state }}" + become: true + become_user: etherpad + with_items: "{{ etherpad.plugins|d() }}" + notify: restart etherpad-lite + +- include: abiword.yml diff --git a/roles/etherpad/tasks/postgresql.yml b/roles/etherpad/tasks/postgresql.yml new file mode 100644 index 0000000..f269e17 --- /dev/null +++ b/roles/etherpad/tasks/postgresql.yml @@ -0,0 +1,21 @@ +--- +- name: Install postgresql + apt: + pkg: + - postgresql + - python3-psycopg2 +- name: Create etherpad postgresql db + become: yes + become_user: postgres + postgresql_db: + name: etherpad + +- name: Create etherpad postgresql user + become: yes + become_user: postgres + postgresql_user: + db: etherpad + name: etherpad + password: etherpad + + diff --git a/roles/etherpad/templates/etherpad-lite.service.j2 b/roles/etherpad/templates/etherpad-lite.service.j2 new file mode 100644 index 0000000..d309b0b --- /dev/null +++ b/roles/etherpad/templates/etherpad-lite.service.j2 @@ -0,0 +1,15 @@ +[Unit] +Description=Etherpad-lite, the collaborative editor. +After=syslog.target network.target + +[Service] +Type=simple +User=etherpad +Group=etherpad +WorkingDirectory=/srv/etherpad/etherpad +ExecStart=/usr/bin/nodejs /srv/etherpad/etherpad/node_modules/ep_etherpad-lite/node/server.js +Environment=NODE_ENV=production +Restart=always + +[Install] +WantedBy=multi-user.target diff --git a/roles/etherpad/templates/etherpad-lite.sysvinit.j2 b/roles/etherpad/templates/etherpad-lite.sysvinit.j2 new file mode 100644 index 0000000..4a440cf --- /dev/null +++ b/roles/etherpad/templates/etherpad-lite.sysvinit.j2 @@ -0,0 +1,79 @@ +#!/bin/sh + +### BEGIN INIT INFO +# Provides: etherpad-lite +# Required-Start: $local_fs $remote_fs $network $syslog +# Required-Stop: $local_fs $remote_fs $network $syslog +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: starts etherpad lite +# Description: starts etherpad lite using start-stop-daemon +### END INIT INFO + +PATH="/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/opt/node/bin" +LOGFILE="/var/log/etherpad-lite/etherpad-lite.log" +EPLITE_DIR="{{ etherpad_path }}" +EPLITE_BIN="bin/safeRun.sh" +USER="{{ etherpad_user }}" +GROUP="{{ etherpad_group }}" +DESC="Etherpad Lite" +NAME="etherpad-lite" + +set -e + +. /lib/lsb/init-functions + +start() { + echo "Starting $DESC... " + + start-stop-daemon --start --chuid "$USER:$GROUP" --background --make-pidfile --pidfile /var/run/$NAME.pid --exec $EPLITE_DIR/$EPLITE_BIN -- $LOGFILE || true + echo "done" +} + +#We need this function to ensure the whole process tree will be killed +killtree() { + local _pid=$1 + local _sig=${2-TERM} + for _child in $(ps -o pid --no-headers --ppid ${_pid}); do + killtree ${_child} ${_sig} + done + kill -${_sig} ${_pid} +} + +stop() { + echo "Stopping $DESC... " + if test -f /var/run/$NAME.pid; then + while test -d /proc/$(cat /var/run/$NAME.pid); do + killtree $(cat /var/run/$NAME.pid) 15 + sleep 0.5 + done + rm /var/run/$NAME.pid + fi + echo "done" +} + +status() { + status_of_proc -p /var/run/$NAME.pid "" "etherpad-lite" && exit 0 || exit $? +} + +case "$1" in + start) + start + ;; + stop) + stop + ;; + restart) + stop + start + ;; + status) + status + ;; + *) + echo "Usage: $NAME {start|stop|restart|status}" >&2 + exit 1 + ;; +esac + +exit 0 diff --git a/roles/etherpad/templates/settings.json.j2 b/roles/etherpad/templates/settings.json.j2 new file mode 100644 index 0000000..0f8e524 --- /dev/null +++ b/roles/etherpad/templates/settings.json.j2 @@ -0,0 +1,109 @@ +#jinja2: lstrip_blocks: True +{ + "title": "{{ etherpad.title }}", + "favicon": "{{ etherpad.favicon }}", + "ip": "{{ etherpad.ip }}", + "port" : {{ etherpad.port }}, + "showSettingsInAdminPage": false, + "sessionKey": "{{ etherpad.session_key }}", + "skinName": "colibris", + "dbType": "mysql", + "dbSettings" : { + "user" : "{{ etherpad.mysql_database_user }}", + "host" : "{{ etherpad.mysql_database_host }}", + "port" : {{ etherpad.mysql_database_port }}, + "password": "{{ etherpad.mysql_database_password }}", + "database": "{{ etherpad.mysql_database_name }}", + "charset" : "{{ etherpad.mysql_database_charset }}" + }, + "defaultPadText": {{ etherpad.default_text }}, + "padOptions": { + "noColors": {{ etherpad.pad_options_no_colors }}, + "showControls": {{ etherpad.pad_options_show_controls }}, + "showChat": {{ etherpad.pad_options_show_chat }}, + "showLineNumbers": {{ etherpad.pad_options_show_line_numbers }}, + "useMonospaceFont": {{ etherpad.pad_options_use_monospace_font }}, + "userName": {{ etherpad.pad_options_user_name }}, + "userColor": {{ etherpad.pad_options_user_color }}, + "rtl": {{ etherpad.pad_options_rtl }}, + "alwaysShowChat": {{ etherpad.pad_options_always_show_chat }}, + "chatAndUsers": {{ etherpad.pad_options_chat_and_users }}, + "lang": "{{ etherpad.pad_options_lang }}" + }, + "padShortcutEnabled" : { + "altF9": {{ etherpad.pad_shortcut_alt_f9 }}, + "altC": {{ etherpad.pad_shortcut_alt_c }}, + "cmdShift2": {{ etherpad.pad_shortcut_cmd_shft_2 }}, + "delete": {{ etherpad.pad_shortcut_delete }}, + "return": {{ etherpad.pad_shortcut_return }}, + "esc": {{ etherpad.pad_shortcut_esc }}, + "cmdS": {{ etherpad.pad_shortcut_cmd_s }}, + "tab": {{ etherpad.pad_shortcut_tab }}, + "cmdZ": {{ etherpad.pad_shortcut_cmd_z }}, + "cmdY": {{ etherpad.pad_shortcut_cmd_y }}, + "cmdI": {{ etherpad.pad_shortcut_cmd_i }}, + "cmdB": {{ etherpad.pad_shortcut_cmd_b }}, + "cmdU": {{ etherpad.pad_shortcut_cmd_u }}, + "cmd5": {{ etherpad.pad_shortcut_cmd_5 }}, + "cmdShiftL": {{ etherpad.pad_shortcut_cmd_shift_l }}, + "cmdShiftN": {{ etherpad.pad_shortcut_cmd_shift_n }}, + "cmdShift1": {{ etherpad.pad_shortcut_cmd_shift_1 }}, + "cmdShiftC": {{ etherpad.pad_shortcut_cmd_shift_c }}, + "cmdH": {{ etherpad.pad_shortcut_cmd_h }}, + "ctrlHome": {{ etherpad.pad_shortcut_ctrl_home }}, + "pageUp": {{ etherpad.pad_shortcut_page_up }}, + "pageDown": {{ etherpad.pad_shortcut_page_down }} + }, + "suppressErrorsInPadText": {{ etherpad.suppress_errors_in_pad_text }}, + "requireSession": {{ etherpad.require_session }}, + "editOnly": {{ etherpad.edit_only }}, + "sessionNoPassword": {{ etherpad.session_no_password }}, + "minify": {{ etherpad.minify }}, + "maxAge": {{ etherpad.max_age }}, + "abiword": {{ etherpad.abiword }}, + "soffice": {{ etherpad.soffice }}, + "tidyHtml": {{ etherpad.tidyhtml }}, + "allowUnknownFileEnds": {{ etherpad.allow_unknown_file_ends }}, + "requireAuthentication": {{ etherpad.require_authentication }}, + "requireAuthorization": {{ etherpad.require_authorization }}, + "trustProxy": {{ etherpad.trust_proxy }}, + "disableIPlogging": {{ etherpad.disable_ip_logging }}, + "automaticReconnectionTimeout": {{ etherpad.automatic_reconnection_timeout }}, + "scrollWhenFocusLineIsOutOfViewport": { + "percentage": { + "editionAboveViewport": 0, + "editionBelowViewport": 0 + }, + "duration": 0, + "scrollWhenCaretIsInTheLastLineOfViewport": false, + "percentageToScrollWhenUserPressesArrowUp": 0 + }, +{% if 'ep_table_of_contents' in etherpad.plugins %} + "ep_toc": { + "disable_by_default": {{ etherpad.toc_disable }} + }, +{% endif %} +{% if 'ep_auth_author' in etherpad.plugins and etherpad.auth_author_prefix is defined %} + "ep_auth_author": { + "prefix": "{{ etherpad.auth_author_prefix }}" + }, +{% endif %} + "users": { +{% for user in etherpad.users %} + "{% if user.auth_author is defined and user.auth_author %}{{ etherpad.auth_author_prefix }}{% endif %}{{ user.name }}": { + "password": "{{ user.password }}", +{% if user.auth_author is defined and user.auth_author %} + "author_name": "{{ user.name }}", +{% endif %} + "is_admin": {{ user.is_admin }} + }{% if not loop.last %},{% endif %} + +{% endfor %} + }, + "socketTransportProtocols": {{ etherpad.socket_transport_protocols|to_json }}, + "loadTest": false, + "indentationOnNewLine": {{ etherpad.indentation_on_new_line }}, + "toolbar": {{ etherpad.toolbar|to_json }}, + "exposeVersion": false, + "loglevel": "{{ etherpad.log_level }}", +}