From a287e741842f67d0a04c48276221d85f16079d55 Mon Sep 17 00:00:00 2001 From: Opal <847966@proton.me> Date: Sat, 15 Oct 2022 15:27:41 -0700 Subject: merging code between old emacsconf repo, to sachac's emacsconf repo --- pad-proxy/defaults/main.yml | 1 - pad-proxy/handlers/main.yml | 5 - pad-proxy/tasks/main.yml | 27 - pad-proxy/templates/etherpad.nginx.conf | 33 - pad-proxy/templates/wikimedia.etherpad.nginx.conf | 33 - pad/README.md | 38 -- pad/defaults/main.yml | 9 - pad/tasks/loadtest.yml | 11 - pad/tasks/main.yml | 120 ---- pad/tasks/mariadb.yml | 42 -- pad/templates/etherpad.init.d | 79 --- pad/templates/etherpad.service | 15 - pad/templates/loadtest.settings.json | 632 ----------------- pad/templates/settings.json | 632 ----------------- pad/vars/main.yml | 2 - roles/base/files/keys/bandali | 1 + roles/base/files/keys/cairn | 1 + roles/base/files/keys/dragestil | 1 + roles/base/files/keys/opal | 2 + roles/base/files/keys/sachac | 2 + roles/base/files/keys/zaeph | 1 + roles/base/files/sshd_config | 16 + roles/base/files/sudoers.d/10_ansible | 1 + roles/base/files/sudoers.d/20_admin | 1 + roles/base/files/sudoers.d/30_org_admin | 3 + roles/base/tasks/main.yml | 54 ++ roles/base/vars/main.yml | 55 ++ roles/pad-proxy/defaults/main.yml | 1 + roles/pad-proxy/handlers/main.yml | 5 + roles/pad-proxy/tasks/main.yml | 27 + roles/pad-proxy/templates/etherpad.nginx.conf | 33 + .../templates/wikimedia.etherpad.nginx.conf | 33 + roles/pad/README.md | 38 ++ roles/pad/defaults/main.yml | 9 + roles/pad/tasks/loadtest.yml | 11 + roles/pad/tasks/main.yml | 120 ++++ roles/pad/tasks/mariadb.yml | 42 ++ roles/pad/templates/etherpad.init.d | 79 +++ roles/pad/templates/etherpad.service | 15 + roles/pad/templates/loadtest.settings.json | 632 +++++++++++++++++ roles/pad/templates/settings.json | 632 +++++++++++++++++ roles/pad/vars/main.yml | 2 + roles/wiki-edit/tasks/main.yaml | 55 ++ roles/wiki/tasks/docker.yml | 45 ++ roles/wiki/tasks/main.yml | 57 ++ roles/wiki/templates/Scrubber.pm | 749 +++++++++++++++++++++ roles/wiki/templates/copyright.pm | 60 ++ roles/wiki/templates/emacsconf.setup | 440 ++++++++++++ roles/wiki/templates/htmlscrubber.pm | 132 ++++ roles/wiki/templates/license.pm | 59 ++ wiki-edit/tasks/main.yaml | 55 -- wiki/tasks/docker.yml | 45 -- wiki/tasks/main.yml | 57 -- wiki/templates/Scrubber.pm | 749 --------------------- wiki/templates/copyright.pm | 60 -- wiki/templates/emacsconf.setup | 440 ------------ wiki/templates/htmlscrubber.pm | 132 ---- wiki/templates/license.pm | 59 -- 58 files changed, 3414 insertions(+), 3276 deletions(-) delete mode 100644 pad-proxy/defaults/main.yml delete mode 100644 pad-proxy/handlers/main.yml delete mode 100644 pad-proxy/tasks/main.yml delete mode 100644 pad-proxy/templates/etherpad.nginx.conf delete mode 100644 pad-proxy/templates/wikimedia.etherpad.nginx.conf delete mode 100644 pad/README.md delete mode 100644 pad/defaults/main.yml delete mode 100644 pad/tasks/loadtest.yml delete mode 100644 pad/tasks/main.yml delete mode 100644 pad/tasks/mariadb.yml delete mode 100755 pad/templates/etherpad.init.d delete mode 100644 pad/templates/etherpad.service delete mode 100644 pad/templates/loadtest.settings.json delete mode 100644 pad/templates/settings.json delete mode 100644 pad/vars/main.yml create mode 100644 roles/base/files/keys/bandali create mode 100644 roles/base/files/keys/cairn create mode 100644 roles/base/files/keys/dragestil create mode 100644 roles/base/files/keys/opal create mode 100644 roles/base/files/keys/sachac create mode 100644 roles/base/files/keys/zaeph create mode 100644 roles/base/files/sshd_config create mode 100644 roles/base/files/sudoers.d/10_ansible create mode 100644 roles/base/files/sudoers.d/20_admin create mode 100644 roles/base/files/sudoers.d/30_org_admin create mode 100644 roles/base/tasks/main.yml create mode 100644 roles/base/vars/main.yml create mode 100644 roles/pad-proxy/defaults/main.yml create mode 100644 roles/pad-proxy/handlers/main.yml create mode 100644 roles/pad-proxy/tasks/main.yml create mode 100644 roles/pad-proxy/templates/etherpad.nginx.conf create mode 100644 roles/pad-proxy/templates/wikimedia.etherpad.nginx.conf create mode 100644 roles/pad/README.md create mode 100644 roles/pad/defaults/main.yml create mode 100644 roles/pad/tasks/loadtest.yml create mode 100644 roles/pad/tasks/main.yml create mode 100644 roles/pad/tasks/mariadb.yml create mode 100755 roles/pad/templates/etherpad.init.d create mode 100644 roles/pad/templates/etherpad.service create mode 100644 roles/pad/templates/loadtest.settings.json create mode 100644 roles/pad/templates/settings.json create mode 100644 roles/pad/vars/main.yml create mode 100644 roles/wiki-edit/tasks/main.yaml create mode 100644 roles/wiki/tasks/docker.yml create mode 100644 roles/wiki/tasks/main.yml create mode 100644 roles/wiki/templates/Scrubber.pm create mode 100644 roles/wiki/templates/copyright.pm create mode 100644 roles/wiki/templates/emacsconf.setup create mode 100755 roles/wiki/templates/htmlscrubber.pm create mode 100644 roles/wiki/templates/license.pm delete mode 100644 wiki-edit/tasks/main.yaml delete mode 100644 wiki/tasks/docker.yml delete mode 100644 wiki/tasks/main.yml delete mode 100644 wiki/templates/Scrubber.pm delete mode 100644 wiki/templates/copyright.pm delete mode 100644 wiki/templates/emacsconf.setup delete mode 100755 wiki/templates/htmlscrubber.pm delete mode 100644 wiki/templates/license.pm diff --git a/pad-proxy/defaults/main.yml b/pad-proxy/defaults/main.yml deleted file mode 100644 index c548560..0000000 --- a/pad-proxy/defaults/main.yml +++ /dev/null @@ -1 +0,0 @@ -etherpad_server_name: pad.emacsconf.org diff --git a/pad-proxy/handlers/main.yml b/pad-proxy/handlers/main.yml deleted file mode 100644 index e01a9d0..0000000 --- a/pad-proxy/handlers/main.yml +++ /dev/null @@ -1,5 +0,0 @@ -- name: Restart etherpad - become: true - service: - name: etherpad - state: restarted diff --git a/pad-proxy/tasks/main.yml b/pad-proxy/tasks/main.yml deleted file mode 100644 index d47573a..0000000 --- a/pad-proxy/tasks/main.yml +++ /dev/null @@ -1,27 +0,0 @@ ---- -- name: Set up Nginx as root - become: true - block: - - name: Install Nginx - apt: - name: nginx - state: present - - name: Add proxy configuration - template: - src: etherpad.nginx.conf - dest: /etc/nginx/sites-available/etherpad.conf - when: not use_wikimedia - - name: Add rewrite configuration - template: - src: wikimedia.etherpad.nginx.conf - dest: /etc/nginx/sites-available/etherpad.conf - when: use_wikimedia - - name: Enable site - file: - src: /etc/nginx/sites-available/etherpad.conf - dest: /etc/nginx/sites-enabled/etherpad.conf - state: link - - name: Restart nginx - service: - name: nginx - state: restarted diff --git a/pad-proxy/templates/etherpad.nginx.conf b/pad-proxy/templates/etherpad.nginx.conf deleted file mode 100644 index 92ba974..0000000 --- a/pad-proxy/templates/etherpad.nginx.conf +++ /dev/null @@ -1,33 +0,0 @@ -upstream etherpad_upstream { - server 127.0.0.1:9001; -} - -server { - listen 80; - server_name {{ etherpad_server_name }}; - access_log /var/log/nginx/{{ etherpad_server_name }}.access.log; - location ~ ^/(locales/|locales.json|admin/|static/|pluginfw/|javascripts/|socket.io/|ep/|minified/|api/|ro/|error/|jserror/|favicon.ico|robots.txt) { - proxy_buffering off; - proxy_pass http://etherpad_upstream; - } - location /p/ { - rewrite ^/p/(.*) /$1 redirect; - } - location ~ ^/$ { - proxy_buffering off; - proxy_pass http://etherpad_upstream; - } - location ~ ^/pad-lister($|\/.*) { - proxy_buffering off; - proxy_pass http://etherpad_upstream; - } - location / { - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - proxy_pass http://etherpad_upstream/p/; - proxy_redirect / /p/; - proxy_read_timeout 90; - } -} diff --git a/pad-proxy/templates/wikimedia.etherpad.nginx.conf b/pad-proxy/templates/wikimedia.etherpad.nginx.conf deleted file mode 100644 index 2288c65..0000000 --- a/pad-proxy/templates/wikimedia.etherpad.nginx.conf +++ /dev/null @@ -1,33 +0,0 @@ -upstream etherpad_upstream { - server 127.0.0.1:9001; -} -server { - listen 80; - server_name {{ etherpad_server_name }}; - access_log /var/log/nginx/{{ etherpad_server_name }}.access.log; - location /p/ { - rewrite ^/p/(.*) /$1 redirect; - } - location ~ ^/$ { - return 302 https://etherpad.wikimedia.org/p/emacsconf-2022; - } - location ~ ^/(locales/|locales.json|admin/|static/|pluginfw/|javascripts/|socket.io/|ep/|minified/|api/|ro/|error/|jserror/|favicon.ico|robots.txt) { - proxy_buffering off; - proxy_pass http://etherpad_upstream; - } - location ~ ^/pad-lister($|\/.*) { - proxy_buffering off; - proxy_pass http://etherpad_upstream; - } - location /direct/ { - rewrite /direct/(.*) /$1 break; - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - proxy_pass http://etherpad_upstream/p/; - } - location / { - rewrite /(.*) https://etherpad.wikimedia.org/p/emacsconf-$1 redirect; - } -} diff --git a/pad/README.md b/pad/README.md deleted file mode 100644 index 7ddc2d4..0000000 --- a/pad/README.md +++ /dev/null @@ -1,38 +0,0 @@ -pad -========= - -Set up Etherpad with MySQL. - -Requirements ------------- - -Any pre-requisites that may not be covered by Ansible itself or the role should be mentioned here. For instance, if the role uses the EC2 module, it may be a good idea to mention in this section that the boto package is required. - -Role Variables --------------- - -A description of the settable variables for this role should go here, including any variables that are in defaults/main.yml, vars/main.yml, and any variables that can/should be set via parameters to the role. Any variables that are read from other roles and/or the global scope (ie. hostvars, group vars, etc.) should be mentioned here as well. - -Dependencies ------------- - -A list of other roles hosted on Galaxy should go here, plus any details in regards to parameters that may need to be set for other roles, or variables that are used from other roles. - -Example Playbook ----------------- - -Including an example of how to use your role (for instance, with variables passed in as parameters) is always nice for users too: - - - hosts: servers - roles: - - { role: username.rolename, x: 42 } - -License -------- - -MIT License - -Author Information ------------------- - -Sacha Chua diff --git a/pad/defaults/main.yml b/pad/defaults/main.yml deleted file mode 100644 index 9d2e294..0000000 --- a/pad/defaults/main.yml +++ /dev/null @@ -1,9 +0,0 @@ ---- -# defaults file for pad -etherpad_path: /home/etherpad/etherpad -etherpad_database_name: emacsconf_pad -etherpad_database_user: etherpad -etherpad_user: etherpad -etherpad_group: etherpad -etherpad_base: emacsconf -etherpad_year: 2022 diff --git a/pad/tasks/loadtest.yml b/pad/tasks/loadtest.yml deleted file mode 100644 index 28deefc..0000000 --- a/pad/tasks/loadtest.yml +++ /dev/null @@ -1,11 +0,0 @@ ---- -- name: Install loadtest configuration - become: true - template: - src: loadtest.settings.json - dest: "{{ etherpad_path }}/settings.json" -- name: Restart Etherpad - become: true - service: - name: etherpad - state: restarted diff --git a/pad/tasks/main.yml b/pad/tasks/main.yml deleted file mode 100644 index 01b2da7..0000000 --- a/pad/tasks/main.yml +++ /dev/null @@ -1,120 +0,0 @@ ---- -# tasks file for pad -- name: Set up packages as root - block: - - name: Add GPG - apt: - update_cache: yes - name: - - gpg - - sudo - - name: Add nodesource key - apt_key: - url: https://deb.nodesource.com/gpgkey/nodesource.gpg.key - state: present - - name: Add nodesource repository - ansible.builtin.apt_repository: - repo: deb https://deb.nodesource.com/node_13.x buster main - update_cache: yes - - name: Install packages - apt: - update_cache: yes - name: - - git - - systemd - - sudo - - nodejs - - mariadb-server - - mariadb-client - state: present - - name: Create etherpad user - user: - name: etherpad - home: /home/etherpad - shell: /bin/bash - state: present -- include: mariadb.yml - become: true -- name: Set up etherpad as the etherpad user - tags: etherpad-src - become: true - block: - - name: Install etherpad - git: - repo: https://github.com/ether/etherpad-lite.git - dest: "{{ etherpad_path }}" - depth: 1 - - name: Configure etherpad - template: - src: templates/settings.json - dest: "{{ etherpad_path }}/settings.json" - - name: Install dependencies - shell: cd {{ etherpad_path }}; . src/bin/functions.sh; src/bin/installDeps.sh - # - name: Install etherpad plugins - # npm: - # name: ep_scrolltoanchor - # path: "{{ etherpad_path }}" - - name: Change ownership - file: - dest: /home/etherpad/etherpad - owner: "{{ etherpad_user }}" - group: "{{ etherpad_group }}" - recurse: true - - name: Set etherpad API key - copy: - content: "{{ etherpad_api_key }}" - dest: "{{ etherpad_path }}/APIKEY.txt" - owner: "{{ etherpad_user }}" - mode: "0600" -- name: Install init.d configuration - tags: system - become: true - template: - src: etherpad.init.d - dest: /etc/init.d/etherpad - owner: root - group: root - mode: 0755 - when: use_initd -- name: Install systemd configuration - tags: system - become: true - template: - src: etherpad.service - dest: /etc/systemd/system/etherpad.service - owner: root - group: root - mode: 0755 - when: not use_initd -- name: Restart Etherpad - become: true - service: - name: etherpad - state: restarted -- tags: create-pads - include_vars: - file: talks.json - name: talks -- name: Set slugs - tags: create-pads - set_fact: - slugs: -- name: Wait for OK - tags: create-pads - uri: - url: "http://localhost:9001/api/1/createPad?apikey={{ etherpad_api_key }}&padID={{etherpad_year}}" - register: _result - until: _result.status == 200 - retries: 720 - delay: 5 -- debug: - var: _result - tags: create-pads -- name: Create pads - tags: create-pads - uri: - url: "http://localhost:9001/api/1/createPad?apikey={{ etherpad_api_key }}&padID={{etherpad_year}}-{{ item.slug }}" - loop: "{{ talks | json_query('talks[*]') }}" -- include: loadtest.yml - become: true - when: load_test is defined diff --git a/pad/tasks/mariadb.yml b/pad/tasks/mariadb.yml deleted file mode 100644 index ec81430..0000000 --- a/pad/tasks/mariadb.yml +++ /dev/null @@ -1,42 +0,0 @@ ---- -- name: Install MySQL packages - apt: - name: - - mariadb-server - - mariadb-client - - python3-mysqldb -- name: Ensure mysql is configured to bind only to localhost - ini_file: - dest: /etc/mysql/my.cnf - section: mysqld - option: "bind-address" - value: "127.0.0.1" -- name: Start MariaDB - service: - name: mysql - state: restarted - enabled: yes - runlevel: - - 3 - - 5 -- name: Ensure anonymous users are not in the database - mysql_user: - name: "" - host: "{{ item }}" - state: absent - with_items: - - localhost - - 127.0.0.1 - - ::1 - - "%" -- name: Ensure emacsconf-pad database exists - mysql_db: - name: "{{ etherpad_database_name }}" - collation: utf8mb4_general_ci - state: present -- name: Grant permissions to user - mysql_user: - name: "{{ etherpad_database_user }}" - state: present - priv: "{{ etherpad_database_name }}.*:ALL" - password: "{{ etherpad_database_password }}" diff --git a/pad/templates/etherpad.init.d b/pad/templates/etherpad.init.d deleted file mode 100755 index 420ae27..0000000 --- a/pad/templates/etherpad.init.d +++ /dev/null @@ -1,79 +0,0 @@ -#!/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" -LOGFILE="{{ etherpad_path }}/etherpad-lite.log" -EPLITE_DIR="{{ etherpad_path }}" -EPLITE_BIN="src/bin/safeRun.sh" -USER="{{ etherpad_user }}" -GROUP="{{ etherpad_group }}" -DESC="Etherpad Lite" -NAME="etherpad" - -set -e - -. /lib/lsb/init-functions - -start() { - echo "Starting $DESC... " - - start-stop-daemon --start --chuid "$USER:$GROUP" -d $EPLITE_DIR --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 \ No newline at end of file diff --git a/pad/templates/etherpad.service b/pad/templates/etherpad.service deleted file mode 100644 index f8e947d..0000000 --- a/pad/templates/etherpad.service +++ /dev/null @@ -1,15 +0,0 @@ -[Unit] -Description=Etherpad -After=syslog.target network.target - -[Service] -Type=simple -User={{ etherpad_user }} -Group={{ etherpad_group }} -WorkingDirectory={{ etherpad_path }} -ExecStart=node {{ etherpad_path }}/node_modules/ep_etherpad-lite/node/server.js -Environment=NODE_ENV=production -Restart=always - -[Install] -WantedBy=multi-user.target diff --git a/pad/templates/loadtest.settings.json b/pad/templates/loadtest.settings.json deleted file mode 100644 index 4e64cba..0000000 --- a/pad/templates/loadtest.settings.json +++ /dev/null @@ -1,632 +0,0 @@ -/* - * This file must be valid JSON. But comments are allowed - * - * Please edit settings.json, not settings.json.template - * - * Please note that starting from Etherpad 1.6.0 you can store DB credentials in - * a separate file (credentials.json). - * - * - * ENVIRONMENT VARIABLE SUBSTITUTION - * ================================= - * - * All the configuration values can be read from environment variables using the - * syntax "${ENV_VAR}" or "${ENV_VAR:default_value}". - * - * This is useful, for example, when running in a Docker container. - * - * DETAILED RULES: - * - If the environment variable is set to the string "true" or "false", the - * value becomes Boolean true or false. - * - If the environment variable is set to the string "null", the value - * becomes null. - * - If the environment variable is set to the string "undefined", the setting - * is removed entirely, except when used as the member of an array in which - * case it becomes null. - * - If the environment variable is set to a string representation of a finite - * number, the string is converted to that number. - * - If the environment variable is set to any other string, including the - * empty string, the value is that string. - * - If the environment variable is unset and a default value is provided, the - * value is as if the environment variable was set to the provided default: - * - "${UNSET_VAR:}" becomes the empty string. - * - "${UNSET_VAR:foo}" becomes the string "foo". - * - "${UNSET_VAR:true}" and "${UNSET_VAR:false}" become true and false. - * - "${UNSET_VAR:null}" becomes null. - * - "${UNSET_VAR:undefined}" causes the setting to be removed (or be set - * to null, if used as a member of an array). - * - If the environment variable is unset and no default value is provided, - * the value becomes null. THIS BEHAVIOR MAY CHANGE IN A FUTURE VERSION OF - * ETHERPAD; if you want the default value to be null, you should explicitly - * specify "null" as the default value. - * - * EXAMPLE: - * "port": "${PORT:9001}" - * "minify": "${MINIFY}" - * "skinName": "${SKIN_NAME:colibris}" - * - * Would read the configuration values for those items from the environment - * variables PORT, MINIFY and SKIN_NAME. - * - * If PORT and SKIN_NAME variables were not defined, the default values 9001 and - * "colibris" would be used. - * The configuration value "minify", on the other hand, does not have a - * designated default value. Thus, if the environment variable MINIFY were - * undefined, "minify" would be null. - * - * REMARKS: - * 1) please note that variable substitution always needs to be quoted. - * - * "port": 9001, <-- Literal values. When not using - * "minify": false substitution, only strings must be - * "skinName": "colibris" quoted. Booleans and numbers must not. - * - * "port": "${PORT:9001}" <-- CORRECT: if you want to use a variable - * "minify": "${MINIFY:true}" substitution, put quotes around its name, - * "skinName": "${SKIN_NAME}" even if the required value is a number or - * a boolean. - * Etherpad will take care of rewriting it - * to the proper type if necessary. - * - * "port": ${PORT:9001} <-- ERROR: this is not valid json. Quotes - * "minify": ${MINIFY} around variable names are missing. - * "skinName": ${SKIN_NAME} - * - * 2) Beware of undefined variables and default values: nulls and empty strings - * are different! - * - * This is particularly important for user's passwords (see the relevant - * section): - * - * "password": "${PASSW}" // if PASSW is not defined would result in password === null - * "password": "${PASSW:}" // if PASSW is not defined would result in password === '' - * - * If you want to use an empty value (null) as default value for a variable, - * simply do not set it, without putting any colons: "${ABIWORD}". - * - * 3) if you want to use newlines in the default value of a string parameter, - * use "\n" as usual. - * - * "defaultPadText" : "${DEFAULT_PAD_TEXT}Line 1\nLine 2" - */ -{ - /* - * Name your instance! - */ - "title": "EmacsConf Etherpad", - - /* - * Pathname of the favicon you want to use. If null, the skin's favicon is - * used if one is provided by the skin, otherwise the default Etherpad favicon - * is used. If this is a relative path it is interpreted as relative to the - * Etherpad root directory. - */ - "favicon": null, - - /* - * Skin name. - * - * Its value has to be an existing directory under src/static/skins. - * You can write your own, or use one of the included ones: - * - * - "no-skin": an empty skin (default). This yields the unmodified, - * traditional Etherpad theme. - * - "colibris": the new experimental skin (since Etherpad 1.8), candidate to - * become the default in Etherpad 2.0 - */ - "skinName": "colibris", - - /* - * Skin Variants - * - * Use the UI skin variants builder at /p/test#skinvariantsbuilder - * - * For the colibris skin only, you can choose how to render the three main - * containers: - * - toolbar (top menu with icons) - * - editor (containing the text of the pad) - * - background (area outside of editor, mostly visible when using page style) - * - * For each of the 3 containers you can choose 4 color combinations: - * super-light, light, dark, super-dark. - * - * For example, to make the toolbar dark, you will include "dark-toolbar" into - * skinVariants. - * - * You can provide multiple skin variants separated by spaces. Default - * skinVariant is "super-light-toolbar super-light-editor light-background". - * - * For the editor container, you can also make it full width by adding - * "full-width-editor" variant (by default editor is rendered as a page, with - * a max-width of 900px). - */ - "skinVariants": "super-light-toolbar super-light-editor light-background", - - /* - * IP and port which Etherpad should bind at. - * - * Binding to a Unix socket is also supported: just use an empty string for - * the ip, and put the full path to the socket in the port parameter. - * - * EXAMPLE USING UNIX SOCKET: - * "ip": "", // <-- has to be an empty string - * "port" : "/somepath/etherpad.socket", // <-- path to a Unix socket - */ - "ip": "127.0.0.1", - "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. - * - * - * Database specific settings are dependent on dbType, and go in dbSettings. - * Remember that since Etherpad 1.6.0 you can also store this information in - * credentials.json. - * - * For a complete list of the supported drivers, please refer to: - * https://www.npmjs.com/package/ueberdb2 - */ - - /* - * 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": "{{ etherpad_database_user }}", - "host": "localhost", - "port": 3306, - "password": "{{ etherpad_database_password }}", - "database": "{{ etherpad_database_name }}", - "charset": "utf8mb4" - }, - - /* - * The default text of a pad - */ - "defaultPadText" : "Conference info, how to watch/participate: https://emacsconf.org/2022/\nGuidelines for conduct: https://emacsconf.org/conduct/\nSee end of file for license (CC Attribution-ShareAlike 4.0 + GPLv3 or later)\n----------------------------------------------------------------\nQuestions and discussion go here:\n- \n- \n- \n- \n- \n- \n- \n\n----------------------------------------------------------------\nExcept where otherwise noted, the material on the EmacsConf pad are dual-licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0 International Public License; and the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) an later version. Copies of these two licenses are included in the EmacsConf wiki repository, in the COPYING.GPL and COPYING.CC-BY-SA files (https://emacsconf.org/COPYING/)\n\nBy contributing to this pad, you agree to make your contributions available under the above licenses. You are also promising that you are the author of your changes, or that you copied them from a work in the public domain or a work released under a free license that is compatible with the above two licenses. DO NOT SUBMIT COPYRIGHTED WORK WITHOUT PERMISSION.", - - /* - * Default Pad behavior. - * - * Change them if you want to override. - */ - "padOptions": { - "noColors": false, - "showControls": true, - "showChat": false, - "showLineNumbers": true, - "useMonospaceFont": false, - "userName": null, - "userColor": null, - "rtl": false, - "alwaysShowChat": false, - "chatAndUsers": false, - "lang": null - }, - - /* - * 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": false, - - /* - * 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 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": false, - - /* - * 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. - * - * This is especially necessary when the reverse proxy performs SSL - * termination, otherwise the cookies will not have the "secure" flag. - * - * The other effect will be that the logs will contain the real client's IP, - * instead of the reverse proxy's IP. - */ - "trustProxy": true, - - /* - * Settings controlling the session cookie issued by Etherpad. - */ - "cookie": { - /* - * Value of the SameSite cookie property. "Lax" is recommended unless - * Etherpad will be embedded in an iframe from another site, in which case - * this must be set to "None". Note: "None" will not work (the browser will - * not send the cookie to Etherpad) unless https is used to access Etherpad - * (either directly or via a reverse proxy with "trustProxy" set to true). - * - * "Strict" is not recommended because it has few security benefits but - * significant usability drawbacks vs. "Lax". See - * https://stackoverflow.com/q/41841880 for discussion. - */ - "sameSite": "Lax", - - /* - * How long (in milliseconds) after navigating away from Etherpad before the - * user is required to log in again. (The express_sid cookie is set to - * expire at time now + sessionLifetime when first created, and its - * expiration time is periodically refreshed to a new now + sessionLifetime - * value.) If requireAuthentication is false then this value does not really - * matter. - * - * The "best" value depends on your users' usage patterns and the amount of - * convenience you desire. A long lifetime is more convenient (users won't - * have to log back in as often) but has some drawbacks: - * - It increases the amount of state kept in the database. - * - It might weaken security somewhat: The cookie expiration is refreshed - * indefinitely without consulting authentication or authorization - * hooks, so once a user has accessed a pad, the user can continue to - * use the pad until the user leaves for longer than sessionLifetime. - * - * Session lifetime can be set to infinity (not recommended) by setting this - * to null or 0. Note that if the session does not expire, most browsers - * will delete the cookie when the browser exits, but a session record is - * kept in the database forever. - */ - "sessionLifetime": 864000000, // = 10d * 24h/d * 60m/h * 60s/m * 1000ms/s - - /* - * How long (in milliseconds) before the expiration time of an active user's - * session is refreshed (to now + sessionLifetime). This setting affects the - * following: - * - How often a new session expiration time will be written to the - * database. - * - How often each user's browser will ping the Etherpad server to - * refresh the expiration time of the session cookie. - * - * High values reduce the load on the database and the load from browsers, - * but can shorten the effective session lifetime if Etherpad is restarted - * or the user navigates away. - * - * Automatic session refreshes can be disabled (not recommended) by setting - * this to null. - */ - "sessionRefreshInterval": 86400000 // = 1d * 24h/d * 60m/h * 60s/m * 1000ms/s - }, - - /* - * Privacy: disable IP logging - */ - "disableIPlogging": true, - - /* - * 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 - }, - - /* - * User accounts. These accounts are used by: - * - default HTTP basic authentication if no plugin handles authentication - * - some but not all authentication plugins - * - some but not all authorization plugins - * - * User properties: - * - password: The user's password. Some authentication plugins will ignore - * this. - * - is_admin: true gives access to /admin. Defaults to false. If you do not - * uncomment this, /admin will not be available! - * - readOnly: If true, this user will not be able to create new pads or - * modify existing pads. Defaults to false. - * - canCreate: If this is true and readOnly is false, this user can create - * new pads. Defaults to true. - * - * Authentication and authorization plugins may define additional properties. - * - * 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": { - // 1) "password" can be replaced with "hash" if you install ep_hash_auth - // 2) please note that if password is null, the user will not be created - "password": "changeme1", - "is_admin": true - }, - "user": { - // 1) "password" can be replaced with "hash" if you install ep_hash_auth - // 2) please note that if password is null, the user will not be created - "password": "changeme1", - "is_admin": false - } - }, - */ - - /* - * Restrict socket.io transport methods - */ - "socketTransportProtocols" : ["xhr-polling", "jsonp-polling", "htmlfile"], - - "socketIo": { - /* - * Maximum permitted client message size (in bytes). All messages from - * clients that are larger than this will be rejected. Large values make it - * possible to paste large amounts of text, and plugins may require a larger - * value to work properly, but increasing the value increases susceptibility - * to denial of service attacks (malicious clients can exhaust memory). - */ - "maxHttpBufferSize": 10000 - }, - - /* - * Allow Load Testing tools to hit the Etherpad Instance. - * - * WARNING: this will disable security on the instance. - */ - "loadTest": true, - - /** - * Disable dump of objects preventing a clean exit - */ - "dumpOnUncleanExit": false, - - /* - * Disable indentation on new line when previous line ends with some special - * chars (':', '[', '(', '{') - */ - - /* - "indentationOnNewLine": false, - */ - - /* - * From Etherpad 1.8.3 onwards, import and export of pads is always rate - * limited. - * - * The default is to allow at most 10 requests per IP in a 90 seconds window. - * After that the import/export request is rejected. - * - * See https://github.com/nfriedly/express-rate-limit for more options - */ - "importExportRateLimiting": { - // duration of the rate limit window (milliseconds) - "windowMs": 90000, - - // maximum number of requests per IP to allow during the rate limit window - "max": 10 - }, - - /* - * From Etherpad 1.8.3 onwards, the maximum allowed size for a single imported - * file is always bounded. - * - * File size is specified in bytes. Default is 50 MB. - */ - "importMaxFileSize": 52428800, // 50 * 1024 * 1024 - - /* - * From Etherpad 1.8.5 onwards, when Etherpad is in production mode commits from individual users are rate limited - * - * The default is to allow at most 10 changes per IP in a 1 second window. - * After that the change is rejected. - * - * See https://github.com/animir/node-rate-limiter-flexible/wiki/Overall-example#websocket-single-connection-prevent-flooding for more options - */ - "commitRateLimiting": { - // duration of the rate limit window (seconds) - "duration": 1, - - // maximum number of changes per IP to allow during the rate limit window - "points": 10 - }, - - /* - * 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"] - ] - }, - */ - - /* - * Expose Etherpad version in the web interface and in the Server http header. - * - * Do not enable on production machines. - */ - "exposeVersion": false, - - /* - * The log level we are using. - * - * Valid values: DEBUG, INFO, WARN, ERROR - */ - "loglevel": "INFO", - - /* Override any strings found in locale directories */ - "customLocaleStrings": {}, - - /* Disable Admin UI tests */ - "enableAdminUITests": false -} diff --git a/pad/templates/settings.json b/pad/templates/settings.json deleted file mode 100644 index 08b46dc..0000000 --- a/pad/templates/settings.json +++ /dev/null @@ -1,632 +0,0 @@ -/* - * This file must be valid JSON. But comments are allowed - * - * Please edit settings.json, not settings.json.template - * - * Please note that starting from Etherpad 1.6.0 you can store DB credentials in - * a separate file (credentials.json). - * - * - * ENVIRONMENT VARIABLE SUBSTITUTION - * ================================= - * - * All the configuration values can be read from environment variables using the - * syntax "${ENV_VAR}" or "${ENV_VAR:default_value}". - * - * This is useful, for example, when running in a Docker container. - * - * DETAILED RULES: - * - If the environment variable is set to the string "true" or "false", the - * value becomes Boolean true or false. - * - If the environment variable is set to the string "null", the value - * becomes null. - * - If the environment variable is set to the string "undefined", the setting - * is removed entirely, except when used as the member of an array in which - * case it becomes null. - * - If the environment variable is set to a string representation of a finite - * number, the string is converted to that number. - * - If the environment variable is set to any other string, including the - * empty string, the value is that string. - * - If the environment variable is unset and a default value is provided, the - * value is as if the environment variable was set to the provided default: - * - "${UNSET_VAR:}" becomes the empty string. - * - "${UNSET_VAR:foo}" becomes the string "foo". - * - "${UNSET_VAR:true}" and "${UNSET_VAR:false}" become true and false. - * - "${UNSET_VAR:null}" becomes null. - * - "${UNSET_VAR:undefined}" causes the setting to be removed (or be set - * to null, if used as a member of an array). - * - If the environment variable is unset and no default value is provided, - * the value becomes null. THIS BEHAVIOR MAY CHANGE IN A FUTURE VERSION OF - * ETHERPAD; if you want the default value to be null, you should explicitly - * specify "null" as the default value. - * - * EXAMPLE: - * "port": "${PORT:9001}" - * "minify": "${MINIFY}" - * "skinName": "${SKIN_NAME:colibris}" - * - * Would read the configuration values for those items from the environment - * variables PORT, MINIFY and SKIN_NAME. - * - * If PORT and SKIN_NAME variables were not defined, the default values 9001 and - * "colibris" would be used. - * The configuration value "minify", on the other hand, does not have a - * designated default value. Thus, if the environment variable MINIFY were - * undefined, "minify" would be null. - * - * REMARKS: - * 1) please note that variable substitution always needs to be quoted. - * - * "port": 9001, <-- Literal values. When not using - * "minify": false substitution, only strings must be - * "skinName": "colibris" quoted. Booleans and numbers must not. - * - * "port": "${PORT:9001}" <-- CORRECT: if you want to use a variable - * "minify": "${MINIFY:true}" substitution, put quotes around its name, - * "skinName": "${SKIN_NAME}" even if the required value is a number or - * a boolean. - * Etherpad will take care of rewriting it - * to the proper type if necessary. - * - * "port": ${PORT:9001} <-- ERROR: this is not valid json. Quotes - * "minify": ${MINIFY} around variable names are missing. - * "skinName": ${SKIN_NAME} - * - * 2) Beware of undefined variables and default values: nulls and empty strings - * are different! - * - * This is particularly important for user's passwords (see the relevant - * section): - * - * "password": "${PASSW}" // if PASSW is not defined would result in password === null - * "password": "${PASSW:}" // if PASSW is not defined would result in password === '' - * - * If you want to use an empty value (null) as default value for a variable, - * simply do not set it, without putting any colons: "${ABIWORD}". - * - * 3) if you want to use newlines in the default value of a string parameter, - * use "\n" as usual. - * - * "defaultPadText" : "${DEFAULT_PAD_TEXT}Line 1\nLine 2" - */ -{ - /* - * Name your instance! - */ - "title": "EmacsConf Etherpad", - - /* - * Pathname of the favicon you want to use. If null, the skin's favicon is - * used if one is provided by the skin, otherwise the default Etherpad favicon - * is used. If this is a relative path it is interpreted as relative to the - * Etherpad root directory. - */ - "favicon": null, - - /* - * Skin name. - * - * Its value has to be an existing directory under src/static/skins. - * You can write your own, or use one of the included ones: - * - * - "no-skin": an empty skin (default). This yields the unmodified, - * traditional Etherpad theme. - * - "colibris": the new experimental skin (since Etherpad 1.8), candidate to - * become the default in Etherpad 2.0 - */ - "skinName": "colibris", - - /* - * Skin Variants - * - * Use the UI skin variants builder at /p/test#skinvariantsbuilder - * - * For the colibris skin only, you can choose how to render the three main - * containers: - * - toolbar (top menu with icons) - * - editor (containing the text of the pad) - * - background (area outside of editor, mostly visible when using page style) - * - * For each of the 3 containers you can choose 4 color combinations: - * super-light, light, dark, super-dark. - * - * For example, to make the toolbar dark, you will include "dark-toolbar" into - * skinVariants. - * - * You can provide multiple skin variants separated by spaces. Default - * skinVariant is "super-light-toolbar super-light-editor light-background". - * - * For the editor container, you can also make it full width by adding - * "full-width-editor" variant (by default editor is rendered as a page, with - * a max-width of 900px). - */ - "skinVariants": "super-light-toolbar super-light-editor light-background", - - /* - * IP and port which Etherpad should bind at. - * - * Binding to a Unix socket is also supported: just use an empty string for - * the ip, and put the full path to the socket in the port parameter. - * - * EXAMPLE USING UNIX SOCKET: - * "ip": "", // <-- has to be an empty string - * "port" : "/somepath/etherpad.socket", // <-- path to a Unix socket - */ - "ip": "127.0.0.1", - "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. - * - * - * Database specific settings are dependent on dbType, and go in dbSettings. - * Remember that since Etherpad 1.6.0 you can also store this information in - * credentials.json. - * - * For a complete list of the supported drivers, please refer to: - * https://www.npmjs.com/package/ueberdb2 - */ - - /* - * 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": "{{ etherpad_database_user }}", - "host": "localhost", - "port": 3306, - "password": "{{ etherpad_database_password }}", - "database": "{{ etherpad_database_name }}", - "charset": "utf8mb4" - }, - - /* - * The default text of a pad - */ - "defaultPadText" : "Conference info, how to watch/participate: https://emacsconf.org/2022/\nGuidelines for conduct: https://emacsconf.org/conduct/\nSee end of file for license (CC Attribution-ShareAlike 4.0 + GPLv3 or later)\n----------------------------------------------------------------\nQuestions and discussion go here:\n- \n- \n- \n- \n- \n- \n- \n\n----------------------------------------------------------------\nExcept where otherwise noted, the material on the EmacsConf pad are dual-licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0 International Public License; and the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) an later version. Copies of these two licenses are included in the EmacsConf wiki repository, in the COPYING.GPL and COPYING.CC-BY-SA files (https://emacsconf.org/COPYING/)\n\nBy contributing to this pad, you agree to make your contributions available under the above licenses. You are also promising that you are the author of your changes, or that you copied them from a work in the public domain or a work released under a free license that is compatible with the above two licenses. DO NOT SUBMIT COPYRIGHTED WORK WITHOUT PERMISSION.", - - /* - * Default Pad behavior. - * - * Change them if you want to override. - */ - "padOptions": { - "noColors": false, - "showControls": true, - "showChat": false, - "showLineNumbers": true, - "useMonospaceFont": false, - "userName": null, - "userColor": null, - "rtl": false, - "alwaysShowChat": false, - "chatAndUsers": false, - "lang": null - }, - - /* - * 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": false, - - /* - * 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": true, - - /* - * 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": false, - - /* - * 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. - * - * This is especially necessary when the reverse proxy performs SSL - * termination, otherwise the cookies will not have the "secure" flag. - * - * The other effect will be that the logs will contain the real client's IP, - * instead of the reverse proxy's IP. - */ - "trustProxy": true, - - /* - * Settings controlling the session cookie issued by Etherpad. - */ - "cookie": { - /* - * Value of the SameSite cookie property. "Lax" is recommended unless - * Etherpad will be embedded in an iframe from another site, in which case - * this must be set to "None". Note: "None" will not work (the browser will - * not send the cookie to Etherpad) unless https is used to access Etherpad - * (either directly or via a reverse proxy with "trustProxy" set to true). - * - * "Strict" is not recommended because it has few security benefits but - * significant usability drawbacks vs. "Lax". See - * https://stackoverflow.com/q/41841880 for discussion. - */ - "sameSite": "Lax", - - /* - * How long (in milliseconds) after navigating away from Etherpad before the - * user is required to log in again. (The express_sid cookie is set to - * expire at time now + sessionLifetime when first created, and its - * expiration time is periodically refreshed to a new now + sessionLifetime - * value.) If requireAuthentication is false then this value does not really - * matter. - * - * The "best" value depends on your users' usage patterns and the amount of - * convenience you desire. A long lifetime is more convenient (users won't - * have to log back in as often) but has some drawbacks: - * - It increases the amount of state kept in the database. - * - It might weaken security somewhat: The cookie expiration is refreshed - * indefinitely without consulting authentication or authorization - * hooks, so once a user has accessed a pad, the user can continue to - * use the pad until the user leaves for longer than sessionLifetime. - * - * Session lifetime can be set to infinity (not recommended) by setting this - * to null or 0. Note that if the session does not expire, most browsers - * will delete the cookie when the browser exits, but a session record is - * kept in the database forever. - */ - "sessionLifetime": 864000000, // = 10d * 24h/d * 60m/h * 60s/m * 1000ms/s - - /* - * How long (in milliseconds) before the expiration time of an active user's - * session is refreshed (to now + sessionLifetime). This setting affects the - * following: - * - How often a new session expiration time will be written to the - * database. - * - How often each user's browser will ping the Etherpad server to - * refresh the expiration time of the session cookie. - * - * High values reduce the load on the database and the load from browsers, - * but can shorten the effective session lifetime if Etherpad is restarted - * or the user navigates away. - * - * Automatic session refreshes can be disabled (not recommended) by setting - * this to null. - */ - "sessionRefreshInterval": 86400000 // = 1d * 24h/d * 60m/h * 60s/m * 1000ms/s - }, - - /* - * Privacy: disable IP logging - */ - "disableIPlogging": true, - - /* - * 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 - }, - - /* - * User accounts. These accounts are used by: - * - default HTTP basic authentication if no plugin handles authentication - * - some but not all authentication plugins - * - some but not all authorization plugins - * - * User properties: - * - password: The user's password. Some authentication plugins will ignore - * this. - * - is_admin: true gives access to /admin. Defaults to false. If you do not - * uncomment this, /admin will not be available! - * - readOnly: If true, this user will not be able to create new pads or - * modify existing pads. Defaults to false. - * - canCreate: If this is true and readOnly is false, this user can create - * new pads. Defaults to true. - * - * Authentication and authorization plugins may define additional properties. - * - * 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": { - // 1) "password" can be replaced with "hash" if you install ep_hash_auth - // 2) please note that if password is null, the user will not be created - "password": "changeme1", - "is_admin": true - }, - "user": { - // 1) "password" can be replaced with "hash" if you install ep_hash_auth - // 2) please note that if password is null, the user will not be created - "password": "changeme1", - "is_admin": false - } - }, - */ - - /* - * Restrict socket.io transport methods - */ - "socketTransportProtocols" : ["xhr-polling", "jsonp-polling", "htmlfile"], - - "socketIo": { - /* - * Maximum permitted client message size (in bytes). All messages from - * clients that are larger than this will be rejected. Large values make it - * possible to paste large amounts of text, and plugins may require a larger - * value to work properly, but increasing the value increases susceptibility - * to denial of service attacks (malicious clients can exhaust memory). - */ - "maxHttpBufferSize": 10000 - }, - - /* - * Allow Load Testing tools to hit the Etherpad Instance. - * - * WARNING: this will disable security on the instance. - */ - "loadTest": false, - - /** - * Disable dump of objects preventing a clean exit - */ - "dumpOnUncleanExit": false, - - /* - * Disable indentation on new line when previous line ends with some special - * chars (':', '[', '(', '{') - */ - - /* - "indentationOnNewLine": false, - */ - - /* - * From Etherpad 1.8.3 onwards, import and export of pads is always rate - * limited. - * - * The default is to allow at most 10 requests per IP in a 90 seconds window. - * After that the import/export request is rejected. - * - * See https://github.com/nfriedly/express-rate-limit for more options - */ - "importExportRateLimiting": { - // duration of the rate limit window (milliseconds) - "windowMs": 90000, - - // maximum number of requests per IP to allow during the rate limit window - "max": 10 - }, - - /* - * From Etherpad 1.8.3 onwards, the maximum allowed size for a single imported - * file is always bounded. - * - * File size is specified in bytes. Default is 50 MB. - */ - "importMaxFileSize": 52428800, // 50 * 1024 * 1024 - - /* - * From Etherpad 1.8.5 onwards, when Etherpad is in production mode commits from individual users are rate limited - * - * The default is to allow at most 10 changes per IP in a 1 second window. - * After that the change is rejected. - * - * See https://github.com/animir/node-rate-limiter-flexible/wiki/Overall-example#websocket-single-connection-prevent-flooding for more options - */ - "commitRateLimiting": { - // duration of the rate limit window (seconds) - "duration": 1, - - // maximum number of changes per IP to allow during the rate limit window - "points": 10 - }, - - /* - * 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"] - ] - }, - */ - - /* - * Expose Etherpad version in the web interface and in the Server http header. - * - * Do not enable on production machines. - */ - "exposeVersion": false, - - /* - * The log level we are using. - * - * Valid values: DEBUG, INFO, WARN, ERROR - */ - "loglevel": "INFO", - - /* Override any strings found in locale directories */ - "customLocaleStrings": {}, - - /* Disable Admin UI tests */ - "enableAdminUITests": false -} diff --git a/pad/vars/main.yml b/pad/vars/main.yml deleted file mode 100644 index 981efa9..0000000 --- a/pad/vars/main.yml +++ /dev/null @@ -1,2 +0,0 @@ ---- -# vars file for pad diff --git a/roles/base/files/keys/bandali b/roles/base/files/keys/bandali new file mode 100644 index 0000000..e50d913 --- /dev/null +++ b/roles/base/files/keys/bandali @@ -0,0 +1 @@ +ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIA0St/clKIWYQMvrVwxs2f3bKapNnu6DmsRxitFfsGMN bandali@gnu.org diff --git a/roles/base/files/keys/cairn b/roles/base/files/keys/cairn new file mode 100644 index 0000000..6bd04bd --- /dev/null +++ b/roles/base/files/keys/cairn @@ -0,0 +1 @@ +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDK7g0qqt0yIKwozCc+ogKiTzK5iwA3nXFHnlvhJfiEZUKiCcl9PN0O+50h8+rFrva27NxE8OEhCPCV9Ug+K8+Z4ikVbIYEBbgF4+GOtW6R7Ktota2Y+6c5DZfoq2vFNOI5cL1OkQUrQhVa+fIjb9zh2L9YgJIsBv/850HlYLS4DPMqyWo7SsMNFA2BIm/rL/U/fqjr4IJ/uxGa3cwM6zixqfozQShxULvz6BxVpe+yPp0yj+mau9DJEs18ZNoeC4vqzXq73hsth2RisXq389foWNRKrAMzcajw8EW7MRd4srRnlr6APt2ZH/vQ6EcTBNyWqEv2KJ4KVZLgg0QHyQBb cairn@starfighter diff --git a/roles/base/files/keys/dragestil b/roles/base/files/keys/dragestil new file mode 100644 index 0000000..5bc093f --- /dev/null +++ b/roles/base/files/keys/dragestil @@ -0,0 +1 @@ +ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBvPOtgcm5ptn8l+/YLAJEqVeT801btqFOf9gE9BLGDh yuchen@melb diff --git a/roles/base/files/keys/opal b/roles/base/files/keys/opal new file mode 100644 index 0000000..eeb5e3c --- /dev/null +++ b/roles/base/files/keys/opal @@ -0,0 +1,2 @@ +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQChD6zcTYv5hpl9YRSetz1uQzQfOkzOQZNna0Mvzqt5mzptdthe6ZNHKchto5tpby5iVxwGTPiHcWs0VlnnDG/VX/a5p28qs2595MZizv6McqInr1kLj3w+gbJpPRqaL0GGtlCZhIYyv1MRFhkemdSzLAo4/Noj7z3b+z6tsnsIr/qJvpoUt0tdsrgMlHOHkqZsnQICNah+ugQAOQzCkZCW7E3hSMtal412eNIaX8TiB686N2VigMOOUxg6NNbo/dRFq5IMA48hBNJpzeS4zz1gMXv6hSCRPcBJ5aFt+O6T7VOXdTAlC88+zu6c554kacyhVB/4tWGmnf1ZaK4kD8Un ry@nocry +ecdsa-sha2-nistp521 AAAAE2VjZHNhLXNoYTItbmlzdHA1MjEAAAAIbmlzdHA1MjEAAACFBAGTI8v3jrhi/HS9RIudSrVg7WFBcvCiRj90q3Qa8HuwbbrHAkVSrhrpJKVTYMt2tBGdcM9QgU/dy5F0o07Vb23COQG/sqr/ImX8wSnjIvjW/yDHaKtEcy3sbvtqqRXiI8R8wfMctCPjUnl7OhaDPMWDy8sAefApCs1W5InafT6TYkooCg== ry@apollyon diff --git a/roles/base/files/keys/sachac b/roles/base/files/keys/sachac new file mode 100644 index 0000000..999b59c --- /dev/null +++ b/roles/base/files/keys/sachac @@ -0,0 +1,2 @@ +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDK0Vg112xS0SAuCutincht2LWs+2jC8EWC19Irotv8M0ztzLf6wmXEw0xoB8D78LKzXGC/gFcIvYzsNezHFpU5PmlxYBRJkdOYH2zYfnlWQFpJKmk1OelTrugaRE4HywXurf6q6Sot5hzbzPmCWgOlBZshnkDXMAyPCfYvL+RcwTRJWiaiGwwDHlfHCkebr4cwypRQ7Nl2kKajdp4wZXwbuP64pPNMmftZEMEM910w3zPnzQTil4IuLSiVC8K7TSk6xsnrsk10Y6zfoaHkZ71OD58rqPPFqeHYDj8SAvp6W4hHwakbf+r8nfRfr8Tc+gtCf0B6a4Y050OI5FxHlmjh +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCyMf4V8eCzYNEde8xG4tIJPBv8NwoTzyRG9O5+Bl69osaHV7OZQz81wXil1qZ/xrUu6fc5jMkxq7j5KCCs2MF6gMq12UKe9ESKYe5i+jFL7+V6JNQqcjLcyaEfEFtFCJ95nWCQWpXrMPijvpB3+YxLspFOTz8ZJsGENXU+Rkz5EIdx2VTgHUbddCjE5jndIO58uPKmR4EpMeUWxb20xYLpOwM14aGF/ERVjI++dIwu7mc21kxg42HJjRA/NRV48IxrGl57KKzl7qtMrqwp+ucoLWw4PdqHk4/tApjmrgLiJzLpSZx/4LL3mHTg3I6w9fC5yTgk3k6rJFomb2Jbboxx diff --git a/roles/base/files/keys/zaeph b/roles/base/files/keys/zaeph new file mode 100644 index 0000000..33d3fa4 --- /dev/null +++ b/roles/base/files/keys/zaeph @@ -0,0 +1 @@ +ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJxla020OSOgCfbCekmMMEFNmuUicibIo7eotqONcJDB diff --git a/roles/base/files/sshd_config b/roles/base/files/sshd_config new file mode 100644 index 0000000..0060c33 --- /dev/null +++ b/roles/base/files/sshd_config @@ -0,0 +1,16 @@ +Include /etc/ssh/sshd_config.d/*.conf +Port 46668 + +LoginGraceTime 2m +AllowAgentForwarding yes +X11Forwarding yes +PermitRootLogin prohibit-password +AuthorizedKeysFile .ssh/authorized_keys +PasswordAuthentication no +UsePAM yes +PrintMotd no +AcceptEnv LANG LC_* + +Subsystem sftp /usr/lib/ssh/sftp-server + +AllowUsers opalvaults ansible bandali zaeph sachac dragestil cairn diff --git a/roles/base/files/sudoers.d/10_ansible b/roles/base/files/sudoers.d/10_ansible new file mode 100644 index 0000000..80053e5 --- /dev/null +++ b/roles/base/files/sudoers.d/10_ansible @@ -0,0 +1 @@ +ansible ALL = (ALL) NOPASSWD: ALL diff --git a/roles/base/files/sudoers.d/20_admin b/roles/base/files/sudoers.d/20_admin new file mode 100644 index 0000000..71b74c3 --- /dev/null +++ b/roles/base/files/sudoers.d/20_admin @@ -0,0 +1 @@ +%admin ALL=(ALL) ALL diff --git a/roles/base/files/sudoers.d/30_org_admin b/roles/base/files/sudoers.d/30_org_admin new file mode 100644 index 0000000..f855569 --- /dev/null +++ b/roles/base/files/sudoers.d/30_org_admin @@ -0,0 +1,3 @@ +sachac ALL=(ALL) /usr/bin/apt +zaeph ALL=(ALL) /usr/bin/apt +dragestil ALL=(ALL) /usr/bin/apt diff --git a/roles/base/tasks/main.yml b/roles/base/tasks/main.yml new file mode 100644 index 0000000..8d2280b --- /dev/null +++ b/roles/base/tasks/main.yml @@ -0,0 +1,54 @@ +--- +# User & Group Creation +- name: create groups + group: + name: "{{ item.value.group }}" + state: "{{ item.value.state }}" + loop: "{{ init_users | dict2items }}" + +- name: create users + user: + name: "{{ item.value.name }}" + group: "{{ item.value.group }}" + groups: "{{ item.value.groups }}" + create_home: "{{ item.value.create_home }}" + state: "{{ item.value.state }}" + shell: "{{ item.value.shell }}" + loop: "{{ init_users | dict2items }}" + +# SSH Initial Setup +- name: create .ssh dirs + file: + path: "/home/{{ item.value.name }}/.ssh" + state: directory + mode: 0700 + owner: "{{ item.value.name }}" + group: "{{ item.value.group }}" + loop: "{{ init_users | dict2items }}" + + +- name: Copy keys to users + authorized_key: + user: "{{ item.value.name }}" + state: present + key: "{{ lookup('file', 'keys/{{ item.value.name }}') }}" + loop: "{{ init_users | dict2items }}" + + +- name: Copy custom sshd_config + copy: + src: sshd_config + dest: "/etc/ssh/sshd_config.d/emacsconf_ssh.conf" + mode: 0644 + owner: root + group: root + +# Sudoers +- name: sudoers.d entries + copy: + src: "sudoers.d/" + dest: "/etc/sudoers.d/" + mode: 0440 + owner: root + group: root + force: no diff --git a/roles/base/vars/main.yml b/roles/base/vars/main.yml new file mode 100644 index 0000000..927d641 --- /dev/null +++ b/roles/base/vars/main.yml @@ -0,0 +1,55 @@ +--- +init_users: + opal: + name: opal + group: opal + groups: admin,org-admin + state: present + shell: /bin/bash + create_home: true + bandali: + name: bandali + group: bandali + groups: admin,org-admin + state: present + shell: /bin/bash + create_home: true + sachac: + name: sachac + group: sachac + groups: org-admin + state: present + shell: /bin/bash + create_home: true + zaeph: + name: zaeph + group: zaeph + groups: org-admin + state: present + shell: /bin/bash + create_home: true + cairn: + name: cairn + group: cairn + groups: org-admin + state: present + shell: /bin/bash + create_home: true + dragestil: + name: dragestil + group: dragestil + groups: org-admin + state: present + shell: /bin/bash + create_home: true + +sudoers_files: + - sudoers.d/10_ansible + - sudoers.d/20_org_admin + - sudoers.d/30_admin + +packages: + - git + - vim + - emacs + - nano diff --git a/roles/pad-proxy/defaults/main.yml b/roles/pad-proxy/defaults/main.yml new file mode 100644 index 0000000..c548560 --- /dev/null +++ b/roles/pad-proxy/defaults/main.yml @@ -0,0 +1 @@ +etherpad_server_name: pad.emacsconf.org diff --git a/roles/pad-proxy/handlers/main.yml b/roles/pad-proxy/handlers/main.yml new file mode 100644 index 0000000..e01a9d0 --- /dev/null +++ b/roles/pad-proxy/handlers/main.yml @@ -0,0 +1,5 @@ +- name: Restart etherpad + become: true + service: + name: etherpad + state: restarted diff --git a/roles/pad-proxy/tasks/main.yml b/roles/pad-proxy/tasks/main.yml new file mode 100644 index 0000000..d47573a --- /dev/null +++ b/roles/pad-proxy/tasks/main.yml @@ -0,0 +1,27 @@ +--- +- name: Set up Nginx as root + become: true + block: + - name: Install Nginx + apt: + name: nginx + state: present + - name: Add proxy configuration + template: + src: etherpad.nginx.conf + dest: /etc/nginx/sites-available/etherpad.conf + when: not use_wikimedia + - name: Add rewrite configuration + template: + src: wikimedia.etherpad.nginx.conf + dest: /etc/nginx/sites-available/etherpad.conf + when: use_wikimedia + - name: Enable site + file: + src: /etc/nginx/sites-available/etherpad.conf + dest: /etc/nginx/sites-enabled/etherpad.conf + state: link + - name: Restart nginx + service: + name: nginx + state: restarted diff --git a/roles/pad-proxy/templates/etherpad.nginx.conf b/roles/pad-proxy/templates/etherpad.nginx.conf new file mode 100644 index 0000000..92ba974 --- /dev/null +++ b/roles/pad-proxy/templates/etherpad.nginx.conf @@ -0,0 +1,33 @@ +upstream etherpad_upstream { + server 127.0.0.1:9001; +} + +server { + listen 80; + server_name {{ etherpad_server_name }}; + access_log /var/log/nginx/{{ etherpad_server_name }}.access.log; + location ~ ^/(locales/|locales.json|admin/|static/|pluginfw/|javascripts/|socket.io/|ep/|minified/|api/|ro/|error/|jserror/|favicon.ico|robots.txt) { + proxy_buffering off; + proxy_pass http://etherpad_upstream; + } + location /p/ { + rewrite ^/p/(.*) /$1 redirect; + } + location ~ ^/$ { + proxy_buffering off; + proxy_pass http://etherpad_upstream; + } + location ~ ^/pad-lister($|\/.*) { + proxy_buffering off; + proxy_pass http://etherpad_upstream; + } + location / { + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_pass http://etherpad_upstream/p/; + proxy_redirect / /p/; + proxy_read_timeout 90; + } +} diff --git a/roles/pad-proxy/templates/wikimedia.etherpad.nginx.conf b/roles/pad-proxy/templates/wikimedia.etherpad.nginx.conf new file mode 100644 index 0000000..2288c65 --- /dev/null +++ b/roles/pad-proxy/templates/wikimedia.etherpad.nginx.conf @@ -0,0 +1,33 @@ +upstream etherpad_upstream { + server 127.0.0.1:9001; +} +server { + listen 80; + server_name {{ etherpad_server_name }}; + access_log /var/log/nginx/{{ etherpad_server_name }}.access.log; + location /p/ { + rewrite ^/p/(.*) /$1 redirect; + } + location ~ ^/$ { + return 302 https://etherpad.wikimedia.org/p/emacsconf-2022; + } + location ~ ^/(locales/|locales.json|admin/|static/|pluginfw/|javascripts/|socket.io/|ep/|minified/|api/|ro/|error/|jserror/|favicon.ico|robots.txt) { + proxy_buffering off; + proxy_pass http://etherpad_upstream; + } + location ~ ^/pad-lister($|\/.*) { + proxy_buffering off; + proxy_pass http://etherpad_upstream; + } + location /direct/ { + rewrite /direct/(.*) /$1 break; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_pass http://etherpad_upstream/p/; + } + location / { + rewrite /(.*) https://etherpad.wikimedia.org/p/emacsconf-$1 redirect; + } +} diff --git a/roles/pad/README.md b/roles/pad/README.md new file mode 100644 index 0000000..7ddc2d4 --- /dev/null +++ b/roles/pad/README.md @@ -0,0 +1,38 @@ +pad +========= + +Set up Etherpad with MySQL. + +Requirements +------------ + +Any pre-requisites that may not be covered by Ansible itself or the role should be mentioned here. For instance, if the role uses the EC2 module, it may be a good idea to mention in this section that the boto package is required. + +Role Variables +-------------- + +A description of the settable variables for this role should go here, including any variables that are in defaults/main.yml, vars/main.yml, and any variables that can/should be set via parameters to the role. Any variables that are read from other roles and/or the global scope (ie. hostvars, group vars, etc.) should be mentioned here as well. + +Dependencies +------------ + +A list of other roles hosted on Galaxy should go here, plus any details in regards to parameters that may need to be set for other roles, or variables that are used from other roles. + +Example Playbook +---------------- + +Including an example of how to use your role (for instance, with variables passed in as parameters) is always nice for users too: + + - hosts: servers + roles: + - { role: username.rolename, x: 42 } + +License +------- + +MIT License + +Author Information +------------------ + +Sacha Chua diff --git a/roles/pad/defaults/main.yml b/roles/pad/defaults/main.yml new file mode 100644 index 0000000..9d2e294 --- /dev/null +++ b/roles/pad/defaults/main.yml @@ -0,0 +1,9 @@ +--- +# defaults file for pad +etherpad_path: /home/etherpad/etherpad +etherpad_database_name: emacsconf_pad +etherpad_database_user: etherpad +etherpad_user: etherpad +etherpad_group: etherpad +etherpad_base: emacsconf +etherpad_year: 2022 diff --git a/roles/pad/tasks/loadtest.yml b/roles/pad/tasks/loadtest.yml new file mode 100644 index 0000000..28deefc --- /dev/null +++ b/roles/pad/tasks/loadtest.yml @@ -0,0 +1,11 @@ +--- +- name: Install loadtest configuration + become: true + template: + src: loadtest.settings.json + dest: "{{ etherpad_path }}/settings.json" +- name: Restart Etherpad + become: true + service: + name: etherpad + state: restarted diff --git a/roles/pad/tasks/main.yml b/roles/pad/tasks/main.yml new file mode 100644 index 0000000..01b2da7 --- /dev/null +++ b/roles/pad/tasks/main.yml @@ -0,0 +1,120 @@ +--- +# tasks file for pad +- name: Set up packages as root + block: + - name: Add GPG + apt: + update_cache: yes + name: + - gpg + - sudo + - name: Add nodesource key + apt_key: + url: https://deb.nodesource.com/gpgkey/nodesource.gpg.key + state: present + - name: Add nodesource repository + ansible.builtin.apt_repository: + repo: deb https://deb.nodesource.com/node_13.x buster main + update_cache: yes + - name: Install packages + apt: + update_cache: yes + name: + - git + - systemd + - sudo + - nodejs + - mariadb-server + - mariadb-client + state: present + - name: Create etherpad user + user: + name: etherpad + home: /home/etherpad + shell: /bin/bash + state: present +- include: mariadb.yml + become: true +- name: Set up etherpad as the etherpad user + tags: etherpad-src + become: true + block: + - name: Install etherpad + git: + repo: https://github.com/ether/etherpad-lite.git + dest: "{{ etherpad_path }}" + depth: 1 + - name: Configure etherpad + template: + src: templates/settings.json + dest: "{{ etherpad_path }}/settings.json" + - name: Install dependencies + shell: cd {{ etherpad_path }}; . src/bin/functions.sh; src/bin/installDeps.sh + # - name: Install etherpad plugins + # npm: + # name: ep_scrolltoanchor + # path: "{{ etherpad_path }}" + - name: Change ownership + file: + dest: /home/etherpad/etherpad + owner: "{{ etherpad_user }}" + group: "{{ etherpad_group }}" + recurse: true + - name: Set etherpad API key + copy: + content: "{{ etherpad_api_key }}" + dest: "{{ etherpad_path }}/APIKEY.txt" + owner: "{{ etherpad_user }}" + mode: "0600" +- name: Install init.d configuration + tags: system + become: true + template: + src: etherpad.init.d + dest: /etc/init.d/etherpad + owner: root + group: root + mode: 0755 + when: use_initd +- name: Install systemd configuration + tags: system + become: true + template: + src: etherpad.service + dest: /etc/systemd/system/etherpad.service + owner: root + group: root + mode: 0755 + when: not use_initd +- name: Restart Etherpad + become: true + service: + name: etherpad + state: restarted +- tags: create-pads + include_vars: + file: talks.json + name: talks +- name: Set slugs + tags: create-pads + set_fact: + slugs: +- name: Wait for OK + tags: create-pads + uri: + url: "http://localhost:9001/api/1/createPad?apikey={{ etherpad_api_key }}&padID={{etherpad_year}}" + register: _result + until: _result.status == 200 + retries: 720 + delay: 5 +- debug: + var: _result + tags: create-pads +- name: Create pads + tags: create-pads + uri: + url: "http://localhost:9001/api/1/createPad?apikey={{ etherpad_api_key }}&padID={{etherpad_year}}-{{ item.slug }}" + loop: "{{ talks | json_query('talks[*]') }}" +- include: loadtest.yml + become: true + when: load_test is defined diff --git a/roles/pad/tasks/mariadb.yml b/roles/pad/tasks/mariadb.yml new file mode 100644 index 0000000..ec81430 --- /dev/null +++ b/roles/pad/tasks/mariadb.yml @@ -0,0 +1,42 @@ +--- +- name: Install MySQL packages + apt: + name: + - mariadb-server + - mariadb-client + - python3-mysqldb +- name: Ensure mysql is configured to bind only to localhost + ini_file: + dest: /etc/mysql/my.cnf + section: mysqld + option: "bind-address" + value: "127.0.0.1" +- name: Start MariaDB + service: + name: mysql + state: restarted + enabled: yes + runlevel: + - 3 + - 5 +- name: Ensure anonymous users are not in the database + mysql_user: + name: "" + host: "{{ item }}" + state: absent + with_items: + - localhost + - 127.0.0.1 + - ::1 + - "%" +- name: Ensure emacsconf-pad database exists + mysql_db: + name: "{{ etherpad_database_name }}" + collation: utf8mb4_general_ci + state: present +- name: Grant permissions to user + mysql_user: + name: "{{ etherpad_database_user }}" + state: present + priv: "{{ etherpad_database_name }}.*:ALL" + password: "{{ etherpad_database_password }}" diff --git a/roles/pad/templates/etherpad.init.d b/roles/pad/templates/etherpad.init.d new file mode 100755 index 0000000..420ae27 --- /dev/null +++ b/roles/pad/templates/etherpad.init.d @@ -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" +LOGFILE="{{ etherpad_path }}/etherpad-lite.log" +EPLITE_DIR="{{ etherpad_path }}" +EPLITE_BIN="src/bin/safeRun.sh" +USER="{{ etherpad_user }}" +GROUP="{{ etherpad_group }}" +DESC="Etherpad Lite" +NAME="etherpad" + +set -e + +. /lib/lsb/init-functions + +start() { + echo "Starting $DESC... " + + start-stop-daemon --start --chuid "$USER:$GROUP" -d $EPLITE_DIR --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 \ No newline at end of file diff --git a/roles/pad/templates/etherpad.service b/roles/pad/templates/etherpad.service new file mode 100644 index 0000000..f8e947d --- /dev/null +++ b/roles/pad/templates/etherpad.service @@ -0,0 +1,15 @@ +[Unit] +Description=Etherpad +After=syslog.target network.target + +[Service] +Type=simple +User={{ etherpad_user }} +Group={{ etherpad_group }} +WorkingDirectory={{ etherpad_path }} +ExecStart=node {{ etherpad_path }}/node_modules/ep_etherpad-lite/node/server.js +Environment=NODE_ENV=production +Restart=always + +[Install] +WantedBy=multi-user.target diff --git a/roles/pad/templates/loadtest.settings.json b/roles/pad/templates/loadtest.settings.json new file mode 100644 index 0000000..4e64cba --- /dev/null +++ b/roles/pad/templates/loadtest.settings.json @@ -0,0 +1,632 @@ +/* + * This file must be valid JSON. But comments are allowed + * + * Please edit settings.json, not settings.json.template + * + * Please note that starting from Etherpad 1.6.0 you can store DB credentials in + * a separate file (credentials.json). + * + * + * ENVIRONMENT VARIABLE SUBSTITUTION + * ================================= + * + * All the configuration values can be read from environment variables using the + * syntax "${ENV_VAR}" or "${ENV_VAR:default_value}". + * + * This is useful, for example, when running in a Docker container. + * + * DETAILED RULES: + * - If the environment variable is set to the string "true" or "false", the + * value becomes Boolean true or false. + * - If the environment variable is set to the string "null", the value + * becomes null. + * - If the environment variable is set to the string "undefined", the setting + * is removed entirely, except when used as the member of an array in which + * case it becomes null. + * - If the environment variable is set to a string representation of a finite + * number, the string is converted to that number. + * - If the environment variable is set to any other string, including the + * empty string, the value is that string. + * - If the environment variable is unset and a default value is provided, the + * value is as if the environment variable was set to the provided default: + * - "${UNSET_VAR:}" becomes the empty string. + * - "${UNSET_VAR:foo}" becomes the string "foo". + * - "${UNSET_VAR:true}" and "${UNSET_VAR:false}" become true and false. + * - "${UNSET_VAR:null}" becomes null. + * - "${UNSET_VAR:undefined}" causes the setting to be removed (or be set + * to null, if used as a member of an array). + * - If the environment variable is unset and no default value is provided, + * the value becomes null. THIS BEHAVIOR MAY CHANGE IN A FUTURE VERSION OF + * ETHERPAD; if you want the default value to be null, you should explicitly + * specify "null" as the default value. + * + * EXAMPLE: + * "port": "${PORT:9001}" + * "minify": "${MINIFY}" + * "skinName": "${SKIN_NAME:colibris}" + * + * Would read the configuration values for those items from the environment + * variables PORT, MINIFY and SKIN_NAME. + * + * If PORT and SKIN_NAME variables were not defined, the default values 9001 and + * "colibris" would be used. + * The configuration value "minify", on the other hand, does not have a + * designated default value. Thus, if the environment variable MINIFY were + * undefined, "minify" would be null. + * + * REMARKS: + * 1) please note that variable substitution always needs to be quoted. + * + * "port": 9001, <-- Literal values. When not using + * "minify": false substitution, only strings must be + * "skinName": "colibris" quoted. Booleans and numbers must not. + * + * "port": "${PORT:9001}" <-- CORRECT: if you want to use a variable + * "minify": "${MINIFY:true}" substitution, put quotes around its name, + * "skinName": "${SKIN_NAME}" even if the required value is a number or + * a boolean. + * Etherpad will take care of rewriting it + * to the proper type if necessary. + * + * "port": ${PORT:9001} <-- ERROR: this is not valid json. Quotes + * "minify": ${MINIFY} around variable names are missing. + * "skinName": ${SKIN_NAME} + * + * 2) Beware of undefined variables and default values: nulls and empty strings + * are different! + * + * This is particularly important for user's passwords (see the relevant + * section): + * + * "password": "${PASSW}" // if PASSW is not defined would result in password === null + * "password": "${PASSW:}" // if PASSW is not defined would result in password === '' + * + * If you want to use an empty value (null) as default value for a variable, + * simply do not set it, without putting any colons: "${ABIWORD}". + * + * 3) if you want to use newlines in the default value of a string parameter, + * use "\n" as usual. + * + * "defaultPadText" : "${DEFAULT_PAD_TEXT}Line 1\nLine 2" + */ +{ + /* + * Name your instance! + */ + "title": "EmacsConf Etherpad", + + /* + * Pathname of the favicon you want to use. If null, the skin's favicon is + * used if one is provided by the skin, otherwise the default Etherpad favicon + * is used. If this is a relative path it is interpreted as relative to the + * Etherpad root directory. + */ + "favicon": null, + + /* + * Skin name. + * + * Its value has to be an existing directory under src/static/skins. + * You can write your own, or use one of the included ones: + * + * - "no-skin": an empty skin (default). This yields the unmodified, + * traditional Etherpad theme. + * - "colibris": the new experimental skin (since Etherpad 1.8), candidate to + * become the default in Etherpad 2.0 + */ + "skinName": "colibris", + + /* + * Skin Variants + * + * Use the UI skin variants builder at /p/test#skinvariantsbuilder + * + * For the colibris skin only, you can choose how to render the three main + * containers: + * - toolbar (top menu with icons) + * - editor (containing the text of the pad) + * - background (area outside of editor, mostly visible when using page style) + * + * For each of the 3 containers you can choose 4 color combinations: + * super-light, light, dark, super-dark. + * + * For example, to make the toolbar dark, you will include "dark-toolbar" into + * skinVariants. + * + * You can provide multiple skin variants separated by spaces. Default + * skinVariant is "super-light-toolbar super-light-editor light-background". + * + * For the editor container, you can also make it full width by adding + * "full-width-editor" variant (by default editor is rendered as a page, with + * a max-width of 900px). + */ + "skinVariants": "super-light-toolbar super-light-editor light-background", + + /* + * IP and port which Etherpad should bind at. + * + * Binding to a Unix socket is also supported: just use an empty string for + * the ip, and put the full path to the socket in the port parameter. + * + * EXAMPLE USING UNIX SOCKET: + * "ip": "", // <-- has to be an empty string + * "port" : "/somepath/etherpad.socket", // <-- path to a Unix socket + */ + "ip": "127.0.0.1", + "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. + * + * + * Database specific settings are dependent on dbType, and go in dbSettings. + * Remember that since Etherpad 1.6.0 you can also store this information in + * credentials.json. + * + * For a complete list of the supported drivers, please refer to: + * https://www.npmjs.com/package/ueberdb2 + */ + + /* + * 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": "{{ etherpad_database_user }}", + "host": "localhost", + "port": 3306, + "password": "{{ etherpad_database_password }}", + "database": "{{ etherpad_database_name }}", + "charset": "utf8mb4" + }, + + /* + * The default text of a pad + */ + "defaultPadText" : "Conference info, how to watch/participate: https://emacsconf.org/2022/\nGuidelines for conduct: https://emacsconf.org/conduct/\nSee end of file for license (CC Attribution-ShareAlike 4.0 + GPLv3 or later)\n----------------------------------------------------------------\nQuestions and discussion go here:\n- \n- \n- \n- \n- \n- \n- \n\n----------------------------------------------------------------\nExcept where otherwise noted, the material on the EmacsConf pad are dual-licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0 International Public License; and the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) an later version. Copies of these two licenses are included in the EmacsConf wiki repository, in the COPYING.GPL and COPYING.CC-BY-SA files (https://emacsconf.org/COPYING/)\n\nBy contributing to this pad, you agree to make your contributions available under the above licenses. You are also promising that you are the author of your changes, or that you copied them from a work in the public domain or a work released under a free license that is compatible with the above two licenses. DO NOT SUBMIT COPYRIGHTED WORK WITHOUT PERMISSION.", + + /* + * Default Pad behavior. + * + * Change them if you want to override. + */ + "padOptions": { + "noColors": false, + "showControls": true, + "showChat": false, + "showLineNumbers": true, + "useMonospaceFont": false, + "userName": null, + "userColor": null, + "rtl": false, + "alwaysShowChat": false, + "chatAndUsers": false, + "lang": null + }, + + /* + * 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": false, + + /* + * 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 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": false, + + /* + * 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. + * + * This is especially necessary when the reverse proxy performs SSL + * termination, otherwise the cookies will not have the "secure" flag. + * + * The other effect will be that the logs will contain the real client's IP, + * instead of the reverse proxy's IP. + */ + "trustProxy": true, + + /* + * Settings controlling the session cookie issued by Etherpad. + */ + "cookie": { + /* + * Value of the SameSite cookie property. "Lax" is recommended unless + * Etherpad will be embedded in an iframe from another site, in which case + * this must be set to "None". Note: "None" will not work (the browser will + * not send the cookie to Etherpad) unless https is used to access Etherpad + * (either directly or via a reverse proxy with "trustProxy" set to true). + * + * "Strict" is not recommended because it has few security benefits but + * significant usability drawbacks vs. "Lax". See + * https://stackoverflow.com/q/41841880 for discussion. + */ + "sameSite": "Lax", + + /* + * How long (in milliseconds) after navigating away from Etherpad before the + * user is required to log in again. (The express_sid cookie is set to + * expire at time now + sessionLifetime when first created, and its + * expiration time is periodically refreshed to a new now + sessionLifetime + * value.) If requireAuthentication is false then this value does not really + * matter. + * + * The "best" value depends on your users' usage patterns and the amount of + * convenience you desire. A long lifetime is more convenient (users won't + * have to log back in as often) but has some drawbacks: + * - It increases the amount of state kept in the database. + * - It might weaken security somewhat: The cookie expiration is refreshed + * indefinitely without consulting authentication or authorization + * hooks, so once a user has accessed a pad, the user can continue to + * use the pad until the user leaves for longer than sessionLifetime. + * + * Session lifetime can be set to infinity (not recommended) by setting this + * to null or 0. Note that if the session does not expire, most browsers + * will delete the cookie when the browser exits, but a session record is + * kept in the database forever. + */ + "sessionLifetime": 864000000, // = 10d * 24h/d * 60m/h * 60s/m * 1000ms/s + + /* + * How long (in milliseconds) before the expiration time of an active user's + * session is refreshed (to now + sessionLifetime). This setting affects the + * following: + * - How often a new session expiration time will be written to the + * database. + * - How often each user's browser will ping the Etherpad server to + * refresh the expiration time of the session cookie. + * + * High values reduce the load on the database and the load from browsers, + * but can shorten the effective session lifetime if Etherpad is restarted + * or the user navigates away. + * + * Automatic session refreshes can be disabled (not recommended) by setting + * this to null. + */ + "sessionRefreshInterval": 86400000 // = 1d * 24h/d * 60m/h * 60s/m * 1000ms/s + }, + + /* + * Privacy: disable IP logging + */ + "disableIPlogging": true, + + /* + * 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 + }, + + /* + * User accounts. These accounts are used by: + * - default HTTP basic authentication if no plugin handles authentication + * - some but not all authentication plugins + * - some but not all authorization plugins + * + * User properties: + * - password: The user's password. Some authentication plugins will ignore + * this. + * - is_admin: true gives access to /admin. Defaults to false. If you do not + * uncomment this, /admin will not be available! + * - readOnly: If true, this user will not be able to create new pads or + * modify existing pads. Defaults to false. + * - canCreate: If this is true and readOnly is false, this user can create + * new pads. Defaults to true. + * + * Authentication and authorization plugins may define additional properties. + * + * 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": { + // 1) "password" can be replaced with "hash" if you install ep_hash_auth + // 2) please note that if password is null, the user will not be created + "password": "changeme1", + "is_admin": true + }, + "user": { + // 1) "password" can be replaced with "hash" if you install ep_hash_auth + // 2) please note that if password is null, the user will not be created + "password": "changeme1", + "is_admin": false + } + }, + */ + + /* + * Restrict socket.io transport methods + */ + "socketTransportProtocols" : ["xhr-polling", "jsonp-polling", "htmlfile"], + + "socketIo": { + /* + * Maximum permitted client message size (in bytes). All messages from + * clients that are larger than this will be rejected. Large values make it + * possible to paste large amounts of text, and plugins may require a larger + * value to work properly, but increasing the value increases susceptibility + * to denial of service attacks (malicious clients can exhaust memory). + */ + "maxHttpBufferSize": 10000 + }, + + /* + * Allow Load Testing tools to hit the Etherpad Instance. + * + * WARNING: this will disable security on the instance. + */ + "loadTest": true, + + /** + * Disable dump of objects preventing a clean exit + */ + "dumpOnUncleanExit": false, + + /* + * Disable indentation on new line when previous line ends with some special + * chars (':', '[', '(', '{') + */ + + /* + "indentationOnNewLine": false, + */ + + /* + * From Etherpad 1.8.3 onwards, import and export of pads is always rate + * limited. + * + * The default is to allow at most 10 requests per IP in a 90 seconds window. + * After that the import/export request is rejected. + * + * See https://github.com/nfriedly/express-rate-limit for more options + */ + "importExportRateLimiting": { + // duration of the rate limit window (milliseconds) + "windowMs": 90000, + + // maximum number of requests per IP to allow during the rate limit window + "max": 10 + }, + + /* + * From Etherpad 1.8.3 onwards, the maximum allowed size for a single imported + * file is always bounded. + * + * File size is specified in bytes. Default is 50 MB. + */ + "importMaxFileSize": 52428800, // 50 * 1024 * 1024 + + /* + * From Etherpad 1.8.5 onwards, when Etherpad is in production mode commits from individual users are rate limited + * + * The default is to allow at most 10 changes per IP in a 1 second window. + * After that the change is rejected. + * + * See https://github.com/animir/node-rate-limiter-flexible/wiki/Overall-example#websocket-single-connection-prevent-flooding for more options + */ + "commitRateLimiting": { + // duration of the rate limit window (seconds) + "duration": 1, + + // maximum number of changes per IP to allow during the rate limit window + "points": 10 + }, + + /* + * 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"] + ] + }, + */ + + /* + * Expose Etherpad version in the web interface and in the Server http header. + * + * Do not enable on production machines. + */ + "exposeVersion": false, + + /* + * The log level we are using. + * + * Valid values: DEBUG, INFO, WARN, ERROR + */ + "loglevel": "INFO", + + /* Override any strings found in locale directories */ + "customLocaleStrings": {}, + + /* Disable Admin UI tests */ + "enableAdminUITests": false +} diff --git a/roles/pad/templates/settings.json b/roles/pad/templates/settings.json new file mode 100644 index 0000000..08b46dc --- /dev/null +++ b/roles/pad/templates/settings.json @@ -0,0 +1,632 @@ +/* + * This file must be valid JSON. But comments are allowed + * + * Please edit settings.json, not settings.json.template + * + * Please note that starting from Etherpad 1.6.0 you can store DB credentials in + * a separate file (credentials.json). + * + * + * ENVIRONMENT VARIABLE SUBSTITUTION + * ================================= + * + * All the configuration values can be read from environment variables using the + * syntax "${ENV_VAR}" or "${ENV_VAR:default_value}". + * + * This is useful, for example, when running in a Docker container. + * + * DETAILED RULES: + * - If the environment variable is set to the string "true" or "false", the + * value becomes Boolean true or false. + * - If the environment variable is set to the string "null", the value + * becomes null. + * - If the environment variable is set to the string "undefined", the setting + * is removed entirely, except when used as the member of an array in which + * case it becomes null. + * - If the environment variable is set to a string representation of a finite + * number, the string is converted to that number. + * - If the environment variable is set to any other string, including the + * empty string, the value is that string. + * - If the environment variable is unset and a default value is provided, the + * value is as if the environment variable was set to the provided default: + * - "${UNSET_VAR:}" becomes the empty string. + * - "${UNSET_VAR:foo}" becomes the string "foo". + * - "${UNSET_VAR:true}" and "${UNSET_VAR:false}" become true and false. + * - "${UNSET_VAR:null}" becomes null. + * - "${UNSET_VAR:undefined}" causes the setting to be removed (or be set + * to null, if used as a member of an array). + * - If the environment variable is unset and no default value is provided, + * the value becomes null. THIS BEHAVIOR MAY CHANGE IN A FUTURE VERSION OF + * ETHERPAD; if you want the default value to be null, you should explicitly + * specify "null" as the default value. + * + * EXAMPLE: + * "port": "${PORT:9001}" + * "minify": "${MINIFY}" + * "skinName": "${SKIN_NAME:colibris}" + * + * Would read the configuration values for those items from the environment + * variables PORT, MINIFY and SKIN_NAME. + * + * If PORT and SKIN_NAME variables were not defined, the default values 9001 and + * "colibris" would be used. + * The configuration value "minify", on the other hand, does not have a + * designated default value. Thus, if the environment variable MINIFY were + * undefined, "minify" would be null. + * + * REMARKS: + * 1) please note that variable substitution always needs to be quoted. + * + * "port": 9001, <-- Literal values. When not using + * "minify": false substitution, only strings must be + * "skinName": "colibris" quoted. Booleans and numbers must not. + * + * "port": "${PORT:9001}" <-- CORRECT: if you want to use a variable + * "minify": "${MINIFY:true}" substitution, put quotes around its name, + * "skinName": "${SKIN_NAME}" even if the required value is a number or + * a boolean. + * Etherpad will take care of rewriting it + * to the proper type if necessary. + * + * "port": ${PORT:9001} <-- ERROR: this is not valid json. Quotes + * "minify": ${MINIFY} around variable names are missing. + * "skinName": ${SKIN_NAME} + * + * 2) Beware of undefined variables and default values: nulls and empty strings + * are different! + * + * This is particularly important for user's passwords (see the relevant + * section): + * + * "password": "${PASSW}" // if PASSW is not defined would result in password === null + * "password": "${PASSW:}" // if PASSW is not defined would result in password === '' + * + * If you want to use an empty value (null) as default value for a variable, + * simply do not set it, without putting any colons: "${ABIWORD}". + * + * 3) if you want to use newlines in the default value of a string parameter, + * use "\n" as usual. + * + * "defaultPadText" : "${DEFAULT_PAD_TEXT}Line 1\nLine 2" + */ +{ + /* + * Name your instance! + */ + "title": "EmacsConf Etherpad", + + /* + * Pathname of the favicon you want to use. If null, the skin's favicon is + * used if one is provided by the skin, otherwise the default Etherpad favicon + * is used. If this is a relative path it is interpreted as relative to the + * Etherpad root directory. + */ + "favicon": null, + + /* + * Skin name. + * + * Its value has to be an existing directory under src/static/skins. + * You can write your own, or use one of the included ones: + * + * - "no-skin": an empty skin (default). This yields the unmodified, + * traditional Etherpad theme. + * - "colibris": the new experimental skin (since Etherpad 1.8), candidate to + * become the default in Etherpad 2.0 + */ + "skinName": "colibris", + + /* + * Skin Variants + * + * Use the UI skin variants builder at /p/test#skinvariantsbuilder + * + * For the colibris skin only, you can choose how to render the three main + * containers: + * - toolbar (top menu with icons) + * - editor (containing the text of the pad) + * - background (area outside of editor, mostly visible when using page style) + * + * For each of the 3 containers you can choose 4 color combinations: + * super-light, light, dark, super-dark. + * + * For example, to make the toolbar dark, you will include "dark-toolbar" into + * skinVariants. + * + * You can provide multiple skin variants separated by spaces. Default + * skinVariant is "super-light-toolbar super-light-editor light-background". + * + * For the editor container, you can also make it full width by adding + * "full-width-editor" variant (by default editor is rendered as a page, with + * a max-width of 900px). + */ + "skinVariants": "super-light-toolbar super-light-editor light-background", + + /* + * IP and port which Etherpad should bind at. + * + * Binding to a Unix socket is also supported: just use an empty string for + * the ip, and put the full path to the socket in the port parameter. + * + * EXAMPLE USING UNIX SOCKET: + * "ip": "", // <-- has to be an empty string + * "port" : "/somepath/etherpad.socket", // <-- path to a Unix socket + */ + "ip": "127.0.0.1", + "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. + * + * + * Database specific settings are dependent on dbType, and go in dbSettings. + * Remember that since Etherpad 1.6.0 you can also store this information in + * credentials.json. + * + * For a complete list of the supported drivers, please refer to: + * https://www.npmjs.com/package/ueberdb2 + */ + + /* + * 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": "{{ etherpad_database_user }}", + "host": "localhost", + "port": 3306, + "password": "{{ etherpad_database_password }}", + "database": "{{ etherpad_database_name }}", + "charset": "utf8mb4" + }, + + /* + * The default text of a pad + */ + "defaultPadText" : "Conference info, how to watch/participate: https://emacsconf.org/2022/\nGuidelines for conduct: https://emacsconf.org/conduct/\nSee end of file for license (CC Attribution-ShareAlike 4.0 + GPLv3 or later)\n----------------------------------------------------------------\nQuestions and discussion go here:\n- \n- \n- \n- \n- \n- \n- \n\n----------------------------------------------------------------\nExcept where otherwise noted, the material on the EmacsConf pad are dual-licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0 International Public License; and the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) an later version. Copies of these two licenses are included in the EmacsConf wiki repository, in the COPYING.GPL and COPYING.CC-BY-SA files (https://emacsconf.org/COPYING/)\n\nBy contributing to this pad, you agree to make your contributions available under the above licenses. You are also promising that you are the author of your changes, or that you copied them from a work in the public domain or a work released under a free license that is compatible with the above two licenses. DO NOT SUBMIT COPYRIGHTED WORK WITHOUT PERMISSION.", + + /* + * Default Pad behavior. + * + * Change them if you want to override. + */ + "padOptions": { + "noColors": false, + "showControls": true, + "showChat": false, + "showLineNumbers": true, + "useMonospaceFont": false, + "userName": null, + "userColor": null, + "rtl": false, + "alwaysShowChat": false, + "chatAndUsers": false, + "lang": null + }, + + /* + * 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": false, + + /* + * 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": true, + + /* + * 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": false, + + /* + * 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. + * + * This is especially necessary when the reverse proxy performs SSL + * termination, otherwise the cookies will not have the "secure" flag. + * + * The other effect will be that the logs will contain the real client's IP, + * instead of the reverse proxy's IP. + */ + "trustProxy": true, + + /* + * Settings controlling the session cookie issued by Etherpad. + */ + "cookie": { + /* + * Value of the SameSite cookie property. "Lax" is recommended unless + * Etherpad will be embedded in an iframe from another site, in which case + * this must be set to "None". Note: "None" will not work (the browser will + * not send the cookie to Etherpad) unless https is used to access Etherpad + * (either directly or via a reverse proxy with "trustProxy" set to true). + * + * "Strict" is not recommended because it has few security benefits but + * significant usability drawbacks vs. "Lax". See + * https://stackoverflow.com/q/41841880 for discussion. + */ + "sameSite": "Lax", + + /* + * How long (in milliseconds) after navigating away from Etherpad before the + * user is required to log in again. (The express_sid cookie is set to + * expire at time now + sessionLifetime when first created, and its + * expiration time is periodically refreshed to a new now + sessionLifetime + * value.) If requireAuthentication is false then this value does not really + * matter. + * + * The "best" value depends on your users' usage patterns and the amount of + * convenience you desire. A long lifetime is more convenient (users won't + * have to log back in as often) but has some drawbacks: + * - It increases the amount of state kept in the database. + * - It might weaken security somewhat: The cookie expiration is refreshed + * indefinitely without consulting authentication or authorization + * hooks, so once a user has accessed a pad, the user can continue to + * use the pad until the user leaves for longer than sessionLifetime. + * + * Session lifetime can be set to infinity (not recommended) by setting this + * to null or 0. Note that if the session does not expire, most browsers + * will delete the cookie when the browser exits, but a session record is + * kept in the database forever. + */ + "sessionLifetime": 864000000, // = 10d * 24h/d * 60m/h * 60s/m * 1000ms/s + + /* + * How long (in milliseconds) before the expiration time of an active user's + * session is refreshed (to now + sessionLifetime). This setting affects the + * following: + * - How often a new session expiration time will be written to the + * database. + * - How often each user's browser will ping the Etherpad server to + * refresh the expiration time of the session cookie. + * + * High values reduce the load on the database and the load from browsers, + * but can shorten the effective session lifetime if Etherpad is restarted + * or the user navigates away. + * + * Automatic session refreshes can be disabled (not recommended) by setting + * this to null. + */ + "sessionRefreshInterval": 86400000 // = 1d * 24h/d * 60m/h * 60s/m * 1000ms/s + }, + + /* + * Privacy: disable IP logging + */ + "disableIPlogging": true, + + /* + * 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 + }, + + /* + * User accounts. These accounts are used by: + * - default HTTP basic authentication if no plugin handles authentication + * - some but not all authentication plugins + * - some but not all authorization plugins + * + * User properties: + * - password: The user's password. Some authentication plugins will ignore + * this. + * - is_admin: true gives access to /admin. Defaults to false. If you do not + * uncomment this, /admin will not be available! + * - readOnly: If true, this user will not be able to create new pads or + * modify existing pads. Defaults to false. + * - canCreate: If this is true and readOnly is false, this user can create + * new pads. Defaults to true. + * + * Authentication and authorization plugins may define additional properties. + * + * 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": { + // 1) "password" can be replaced with "hash" if you install ep_hash_auth + // 2) please note that if password is null, the user will not be created + "password": "changeme1", + "is_admin": true + }, + "user": { + // 1) "password" can be replaced with "hash" if you install ep_hash_auth + // 2) please note that if password is null, the user will not be created + "password": "changeme1", + "is_admin": false + } + }, + */ + + /* + * Restrict socket.io transport methods + */ + "socketTransportProtocols" : ["xhr-polling", "jsonp-polling", "htmlfile"], + + "socketIo": { + /* + * Maximum permitted client message size (in bytes). All messages from + * clients that are larger than this will be rejected. Large values make it + * possible to paste large amounts of text, and plugins may require a larger + * value to work properly, but increasing the value increases susceptibility + * to denial of service attacks (malicious clients can exhaust memory). + */ + "maxHttpBufferSize": 10000 + }, + + /* + * Allow Load Testing tools to hit the Etherpad Instance. + * + * WARNING: this will disable security on the instance. + */ + "loadTest": false, + + /** + * Disable dump of objects preventing a clean exit + */ + "dumpOnUncleanExit": false, + + /* + * Disable indentation on new line when previous line ends with some special + * chars (':', '[', '(', '{') + */ + + /* + "indentationOnNewLine": false, + */ + + /* + * From Etherpad 1.8.3 onwards, import and export of pads is always rate + * limited. + * + * The default is to allow at most 10 requests per IP in a 90 seconds window. + * After that the import/export request is rejected. + * + * See https://github.com/nfriedly/express-rate-limit for more options + */ + "importExportRateLimiting": { + // duration of the rate limit window (milliseconds) + "windowMs": 90000, + + // maximum number of requests per IP to allow during the rate limit window + "max": 10 + }, + + /* + * From Etherpad 1.8.3 onwards, the maximum allowed size for a single imported + * file is always bounded. + * + * File size is specified in bytes. Default is 50 MB. + */ + "importMaxFileSize": 52428800, // 50 * 1024 * 1024 + + /* + * From Etherpad 1.8.5 onwards, when Etherpad is in production mode commits from individual users are rate limited + * + * The default is to allow at most 10 changes per IP in a 1 second window. + * After that the change is rejected. + * + * See https://github.com/animir/node-rate-limiter-flexible/wiki/Overall-example#websocket-single-connection-prevent-flooding for more options + */ + "commitRateLimiting": { + // duration of the rate limit window (seconds) + "duration": 1, + + // maximum number of changes per IP to allow during the rate limit window + "points": 10 + }, + + /* + * 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"] + ] + }, + */ + + /* + * Expose Etherpad version in the web interface and in the Server http header. + * + * Do not enable on production machines. + */ + "exposeVersion": false, + + /* + * The log level we are using. + * + * Valid values: DEBUG, INFO, WARN, ERROR + */ + "loglevel": "INFO", + + /* Override any strings found in locale directories */ + "customLocaleStrings": {}, + + /* Disable Admin UI tests */ + "enableAdminUITests": false +} diff --git a/roles/pad/vars/main.yml b/roles/pad/vars/main.yml new file mode 100644 index 0000000..981efa9 --- /dev/null +++ b/roles/pad/vars/main.yml @@ -0,0 +1,2 @@ +--- +# vars file for pad diff --git a/roles/wiki-edit/tasks/main.yaml b/roles/wiki-edit/tasks/main.yaml new file mode 100644 index 0000000..f7eb650 --- /dev/null +++ b/roles/wiki-edit/tasks/main.yaml @@ -0,0 +1,55 @@ +--- +- name: Set up SSH directory + ansible.builtin.file: + path: /home/ikiwiki/.ssh + state: directory + mode: '0700' +- name: Install SSH key for EmacsConf wiki + ansible.builtin.get_url: + url: https://emacsconf.org/id_rsa_anon_git_emacsconf + dest: /home/ikiwiki/.ssh/id_rsa_anon_git_emacsconf + mode: '0600' + owner: 'ikiwiki' +- name: Set up packages + become: yes + block: + - name: Add snapshot repository + ansible.builtin.apt_repository: + repo: deb http://emacs.ganneff.de/ buster main + - name: Remove old package + ansible.builtin.apt: + name: emacs + state: absent + - name: Install Emacs snapshot + ansible.builtin.apt: + name: emacs-snapshot-nox + state: present +- name: Set up or update repositories + tags: publish + block: + - name: Check out wiki repository + ansible.builtin.git: + repo: git://git.emacsconf.org/emacsconf-wiki + dest: ~/emacsconf-wiki + - name: Check out emacsconf-el + ansible.builtin.git: + repo: git@git.emacsconf.org:pub/emacsconf-el + dest: ~/emacsconf-el + register: elisp + - name: Check out emacsconf-2022-private + ansible.builtin.git: + repo: git@git.emacsconf.org:emacsconf-2022-private + dest: ~/emacsconf-2022-private + register: private +- name: Publish + tags: publish + block: + - name: Publish the schedule + command: emacs -l ~/.emacs.d/init.el --batch --exec '(emacsconf-generate-main-schedule)' + when: force_publish or ((private.changed or elisp.changed) and slug is not defined) + - name: Update a specific talk's nav page + tags: publish-talk + command: emacs -l ~/.emacs.d/init.el --batch --exec '(emacsconf-with-talk-heading "{{ slug }}" (emacsconf-update-talk))' + when: slug is defined + - name: Commit the wiki and push + shell: cd ~/emacsconf-wiki; git commit -m 'Update from ansible' -a; git push diff --git a/roles/wiki/tasks/docker.yml b/roles/wiki/tasks/docker.yml new file mode 100644 index 0000000..a5d73e2 --- /dev/null +++ b/roles/wiki/tasks/docker.yml @@ -0,0 +1,45 @@ +- name: Set up docker stuff if on docker + apt: + pkg: + - lighttpd + - supervisor +- name: Create the anon user + user: + name: anon +- name: Set up Ikiwiki setup + template: + src: emacsconf.setup + dest: "{{ ikiwiki_path }}/emacsconf.setup" + owner: www-data + group: www-data +- name: Set up the ikiwiki directories + file: + dest: /var/www/html + state: directory + owner: www-data + group: www-data +- name: Clone the bare git repo + git: + bare: true + repo: "{{ ikiwiki_git_source_mount }}" + dest: "{{ ikiwiki_bare_git_dir }}" + version: "{{ ikiwiki_git_branch }}" +- name: Change owner + file: + dest: "{{ ikiwiki_bare_git_dir }}" + recurse: true + owner: www-data + group: www-data +- name: Clone the working git repo + git: + repo: "{{ ikiwiki_bare_git_dir }}" + dest: "{{ ikiwiki_src_dir }}" + version: "{{ ikiwiki_git_branch }}" +- name: Copy supervisor config + template: + src: supervisord.conf + dest: /etc/supervisor/conf.d/ikiwiki.conf +- name: Start lighttpd + service: + name: lighttpd + state: started diff --git a/roles/wiki/tasks/main.yml b/roles/wiki/tasks/main.yml new file mode 100644 index 0000000..0fa2336 --- /dev/null +++ b/roles/wiki/tasks/main.yml @@ -0,0 +1,57 @@ +--- +- name: Set up packages + ansible.builtin.apt: + update_cache: true + pkg: + - ikiwiki + - git + - openssh-server + - libimage-magick-perl + - libtext-csv-perl + - libxml-writer-perl + - imagemagick + - nginx + - wget + state: present +- name: Create ikiwiki group + group: + name: ikiwiki + state: present +- name: Create ikiwiki user + user: + name: ikiwiki + group: ikiwiki + state: present +- debug: + var: docker +- name: Set up or update repositories + ansible.builtin.git: + repo: git://git.emacsconf.org/emacsconf-wiki + dest: "{{ ikiwiki_src_dir }}" + when: not docker|d(false) +- name: Template the config + ansible.builtin.template: + src: emacsconf.setup + dest: "{{ ikiwiki_path }}/emacsconf.setup" + owner: ikiwiki +- name: Copy Ikiwiki plugins + template: + src: "{{ item }}" + dest: "{{ ikiwiki_plugin_path }}" + loop: + - copyright.pm + - htmlscrubber.pm + - license.pm +- include: docker.yml + when: docker is true +- name: Chown all the files to ikiwiki + file: + dest: "{{ ikiwiki_path }}" + owner: ikiwiki + group: ikiwiki + recurse: true +- name: Regenerate all the files + shell: ikiwiki --setup "{{ ikiwiki_path }}/emacsconf.setup" --rebuild --wrappers + register: output +- debug: + var: output diff --git a/roles/wiki/templates/Scrubber.pm b/roles/wiki/templates/Scrubber.pm new file mode 100644 index 0000000..2efaa10 --- /dev/null +++ b/roles/wiki/templates/Scrubber.pm @@ -0,0 +1,749 @@ +package HTML::Scrubber; + +# ABSTRACT: Perl extension for scrubbing/sanitizing html + + +use 5.008; # enforce minimum perl version of 5.8 +use strict; +use warnings; +use HTML::Parser 3.47 (); +use HTML::Entities; +use Scalar::Util ('weaken'); + +our ( @_scrub, @_scrub_fh ); + +our $VERSION = '0.15'; # VERSION +our $AUTHORITY = 'cpan:NIGELM'; # AUTHORITY + +# my my my my, these here to prevent foolishness like +# http://perlmonks.org/index.pl?node_id=251127#Stealing+Lexicals +(@_scrub) = ( \&_scrub, "self, event, tagname, attr, attrseq, text" ); +(@_scrub_fh) = ( \&_scrub_fh, "self, event, tagname, attr, attrseq, text" ); + +sub new { + my $package = shift; + my $p = HTML::Parser->new( + api_version => 3, + default_h => \@_scrub, + marked_sections => 0, + strict_comment => 0, + unbroken_text => 1, + case_sensitive => 0, + boolean_attribute_value => undef, + empty_element_tags => 1, + ); + + my $self = { + _p => $p, + _rules => { '*' => 0, }, + _comment => 0, + _process => 0, + _r => "", + _optimize => 1, + _script => 0, + _style => 0, + }; + + $p->{"\0_s"} = bless $self, $package; + weaken( $p->{"\0_s"} ); + + return $self unless @_; + + my (%args) = @_; + + for my $f (qw[ default allow deny rules process comment ]) { + next unless exists $args{$f}; + if ( ref $args{$f} ) { + $self->$f( @{ $args{$f} } ); + } + else { + $self->$f( $args{$f} ); + } + } + + return $self; +} + + +sub comment { + return $_[0]->{_comment} + if @_ == 1; + $_[0]->{_comment} = $_[1]; + return; +} + + +sub process { + return $_[0]->{_process} + if @_ == 1; + $_[0]->{_process} = $_[1]; + return; +} + + +sub script { + return $_[0]->{_script} + if @_ == 1; + $_[0]->{_script} = $_[1]; + return; +} + + +sub style { + return $_[0]->{_style} + if @_ == 1; + $_[0]->{_style} = $_[1]; + return; +} + + +sub allow { + my $self = shift; + for my $k (@_) { + $self->{_rules}{ lc $k } = 1; + } + $self->{_optimize} = 1; # each time a rule changes, reoptimize when parse + + return; +} + + +sub deny { + my $self = shift; + + for my $k (@_) { + $self->{_rules}{ lc $k } = 0; + } + + $self->{_optimize} = 1; # each time a rule changes, reoptimize when parse + + return; +} + + +sub rules { + my $self = shift; + my (%rules) = @_; + for my $k ( keys %rules ) { + $self->{_rules}{ lc $k } = $rules{$k}; + } + + $self->{_optimize} = 1; # each time a rule changes, reoptimize when parse + + return; +} + + +sub default { + return $_[0]->{_rules}{'*'} + if @_ == 1; + + $_[0]->{_rules}{'*'} = $_[1] if defined $_[1]; + $_[0]->{_rules}{'_'} = $_[2] if defined $_[2] and ref $_[2]; + $_[0]->{_optimize} = 1; # each time a rule changes, reoptimize when parse + + return; +} + + +sub scrub_file { + if ( @_ > 2 ) { + return unless defined $_[0]->_out( $_[2] ); + } + else { + $_[0]->{_p}->handler( default => @_scrub ); + } + + $_[0]->_optimize(); #if $_[0]->{_optimize}; + + $_[0]->{_p}->parse_file( $_[1] ); + + return delete $_[0]->{_r} unless exists $_[0]->{_out}; + print { $_[0]->{_out} } $_[0]->{_r} if length $_[0]->{_r}; + delete $_[0]->{_out}; + return 1; +} + + +sub scrub { + if ( @_ > 2 ) { + return unless defined $_[0]->_out( $_[2] ); + } + else { + $_[0]->{_p}->handler( default => @_scrub ); + } + + $_[0]->_optimize(); # if $_[0]->{_optimize}; + + $_[0]->{_p}->parse( $_[1] ) if defined( $_[1] ); + $_[0]->{_p}->eof(); + + return delete $_[0]->{_r} unless exists $_[0]->{_out}; + delete $_[0]->{_out}; + return 1; +} + + +sub _out { + my ( $self, $o ) = @_; + + unless ( ref $o and ref \$o ne 'GLOB' ) { + open my $F, '>', $o or return; + binmode $F; + $self->{_out} = $F; + } + else { + $self->{_out} = $o; + } + + $self->{_p}->handler( default => @_scrub_fh ); + + return 1; +} + + +sub _validate { + my ( $s, $t, $r, $a, $as ) = @_; + return "<$t>" unless %$a; + + $r = $s->{_rules}->{$r}; + my %f; + + for my $k ( keys %$a ) { + my $check = exists $r->{$k} ? $r->{$k} : exists $r->{'*'} ? $r->{'*'} : next; + + if ( ref $check eq 'CODE' ) { + my @v = $check->( $s, $t, $k, $a->{$k}, $a, \%f ); + next unless @v; + $f{$k} = shift @v; + } + elsif ( ref $check || length($check) > 1 ) { + $f{$k} = $a->{$k} if $a->{$k} =~ m{$check}; + } + elsif ($check) { + $f{$k} = $a->{$k}; + } + } + + if (%f) { + my %seen; + return "<$t $r>" + if $r = join ' ', map { + defined $f{$_} + ? qq[$_="] . encode_entities( $f{$_} ) . q["] + : $_; # boolean attribute (TODO?) + } grep { exists $f{$_} and !$seen{$_}++; } @$as; + } + + return "<$t>"; +} + + +sub _scrub_str { + my ( $p, $e, $t, $a, $as, $text ) = @_; + + my $s = $p->{"\0_s"}; + my $outstr = ''; + + if ( $e eq 'start' ) { + if ( exists $s->{_rules}->{$t} ) # is there a specific rule + { + if ( ref $s->{_rules}->{$t} ) # is it complicated?(not simple;) + { + $outstr .= $s->_validate( $t, $t, $a, $as ); + } + elsif ( $s->{_rules}->{$t} ) # validate using default attribute rule + { + $outstr .= $s->_validate( $t, '_', $a, $as ); + } + } + elsif ( $s->{_rules}->{'*'} ) # default allow tags + { + $outstr .= $s->_validate( $t, '_', $a, $as ); + } + } + elsif ( $e eq 'end' ) { + my $place = 0; + if ( exists $s->{_rules}->{$t} ) { + $place = 1 if $s->{_rules}->{$t}; + } + elsif ( $s->{_rules}->{'*'} ) { + $place = 1; + } + if ($place) { + if ( length $text ) { + $outstr .= ""; + } + else { + substr $s->{_r}, -1, 0, ' /'; + } + } + } + elsif ( $e eq 'comment' ) { + if ( $s->{_comment} ) { + + # only copy comments through if they are well formed... + $outstr .= $text if ( $text =~ m|^$|ms ); + } + } + elsif ( $e eq 'process' ) { + $outstr .= $text if $s->{_process}; + } + elsif ( $e eq 'text' or $e eq 'default' ) { + $text =~ s//>/g; + + $outstr .= $text; + } + elsif ( $e eq 'start_document' ) { + $outstr = ""; + } + + return $outstr; +} + + +sub _scrub_fh { + my $self = $_[0]->{"\0_s"}; + print { $self->{_out} } $self->{'_r'} if length $self->{_r}; + $self->{'_r'} = _scrub_str(@_); +} + + +sub _scrub { + + $_[0]->{"\0_s"}->{_r} .= _scrub_str(@_); +} + +sub _optimize { + my ($self) = @_; + + my (@ignore_elements) = grep { not $self->{"_$_"} } qw(script style); + $self->{_p}->ignore_elements(@ignore_elements); # if @ is empty, we reset ;) + + return unless $self->{_optimize}; + + #sub allow + # return unless $self->{_optimize}; # till I figure it out (huh) + + if ( $self->{_rules}{'*'} ) { # default allow + $self->{_p}->report_tags(); # so clear it + } + else { + + my (@reports) = + grep { # report only tags we want + $self->{_rules}{$_} + } keys %{ $self->{_rules} }; + + $self->{_p}->report_tags( # default deny, so optimize + @reports + ) if @reports; + } + + # sub deny + # return unless $self->{_optimize}; # till I figure it out (huh) + my (@ignores) = + grep { not $self->{_rules}{$_} } grep { $_ ne '*' } keys %{ $self->{_rules} }; + + $self->{_p}->ignore_tags( # always ignore stuff we don't want + @ignores + ) if @ignores; + + $self->{_optimize} = 0; + return; +} + +1; + +#print sprintf q[ '%-12s => %s,], "$_'", $h{$_} for sort keys %h;# perl! +#perl -ne"chomp;print $_;print qq'\t\t# test ', ++$a if /ok\(/;print $/" test.pl >test2.pl +#perl -ne"chomp;print $_;if( /ok\(/ ){s/\#test \d+$//;print qq'\t\t# test ', ++$a }print $/" test.pl >test2.pl +#perl -ne"chomp;if(/ok\(/){s/# test .*$//;print$_,qq'\t\t# test ',++$a}else{print$_}print$/" test.pl >test2.pl + +__END__ + +=pod + +=for stopwords html cpan callback homepage Perlbrew perltidy respository + +=head1 NAME + +HTML::Scrubber - Perl extension for scrubbing/sanitizing html + +=head1 VERSION + +version 0.15 + +=head1 SYNOPSIS + + use HTML::Scrubber; + + my $scrubber = HTML::Scrubber->new( allow => [ qw[ p b i u hr br ] ] ); + print $scrubber->scrub('

bold missing

'); + # output is:

bold

+ + # more complex input + my $html = q[ + + +
+ a => link + br =>
+ b => bold + u => UNDERLINE + ]; + + print $scrubber->scrub($html); + + $scrubber->deny( qw[ p b i u hr br ] ); + + print $scrubber->scrub($html); + +=head1 DESCRIPTION + +If you want to "scrub" or "sanitize" html input in a reliable and flexible +fashion, then this module is for you. + +I wasn't satisfied with HTML::Sanitizer because it is based on +HTML::TreeBuilder, so I thought I'd write something similar that works directly +with HTML::Parser. + +=head1 METHODS + +First a note on documentation: just study the L below. It's +all the documentation you could need + +Also, be sure to read all the comments as well as L. + +If you're new to perl, good luck to you. + +=head2 comment + + warn "comments are ", $p->comment ? 'allowed' : 'not allowed'; + $p->comment(0); # off by default + +=head2 process + + warn "process instructions are ", $p->process ? 'allowed' : 'not allowed'; + $p->process(0); # off by default + +=head2 script + + warn "script tags (and everything in between) are supressed" + if $p->script; # off by default + $p->script( 0 || 1 ); + +B<**> Please note that this is implemented using HTML::Parser's ignore_elements +function, so if C -
- a => link - br =>
- b => bold - u => UNDERLINE - ]; - - print $scrubber->scrub($html); - - $scrubber->deny( qw[ p b i u hr br ] ); - - print $scrubber->scrub($html); - -=head1 DESCRIPTION - -If you want to "scrub" or "sanitize" html input in a reliable and flexible -fashion, then this module is for you. - -I wasn't satisfied with HTML::Sanitizer because it is based on -HTML::TreeBuilder, so I thought I'd write something similar that works directly -with HTML::Parser. - -=head1 METHODS - -First a note on documentation: just study the L below. It's -all the documentation you could need - -Also, be sure to read all the comments as well as L. - -If you're new to perl, good luck to you. - -=head2 comment - - warn "comments are ", $p->comment ? 'allowed' : 'not allowed'; - $p->comment(0); # off by default - -=head2 process - - warn "process instructions are ", $p->process ? 'allowed' : 'not allowed'; - $p->process(0); # off by default - -=head2 script - - warn "script tags (and everything in between) are supressed" - if $p->script; # off by default - $p->script( 0 || 1 ); - -B<**> Please note that this is implemented using HTML::Parser's ignore_elements -function, so if C