diff --git a/hosts.yaml b/hosts.yaml index 85622b6..a7ce13e 100644 --- a/hosts.yaml +++ b/hosts.yaml @@ -11,6 +11,9 @@ all: git: hosts: git.bitlair.nl: + pad: + hosts: + pad.bitlair.nl: lights: hosts: lights.bitlair.nl: diff --git a/pad.yaml b/pad.yaml new file mode 100644 index 0000000..63d91b1 --- /dev/null +++ b/pad.yaml @@ -0,0 +1,9 @@ +--- +- hosts: pad + vars: + acme_san_domains: + - [ pad.bitlair.nl ] + roles: + - common + - acme + - etherpad diff --git a/roles/etherpad/defaults/main.yaml b/roles/etherpad/defaults/main.yaml new file mode 100644 index 0000000..ed6395f --- /dev/null +++ b/roles/etherpad/defaults/main.yaml @@ -0,0 +1,4 @@ +nodejs_version: node_18.x +etherpad_db_user: etherpad +etherpad_db_password: "{{ lookup('password', '/tmp/etherpad_db_password length=32') }}" +etherpad_db_name: etherpad diff --git a/roles/etherpad/handlers/main.yaml b/roles/etherpad/handlers/main.yaml new file mode 100644 index 0000000..39fb4d8 --- /dev/null +++ b/roles/etherpad/handlers/main.yaml @@ -0,0 +1,8 @@ +--- +- import_tasks: ../../common/handlers/main.yaml + +- name: restart etherpad + systemd: + name: etherpad + state: restarted + daemon_reload: true diff --git a/roles/etherpad/tasks/main.yaml b/roles/etherpad/tasks/main.yaml new file mode 100644 index 0000000..b80c15b --- /dev/null +++ b/roles/etherpad/tasks/main.yaml @@ -0,0 +1,124 @@ +--- +- tags: etherpad + block: + - name: Install dependencies + apt: + name: [ gpg, nginx, postgresql, python3-psycopg2 ] + + - name: Import nodesource signing key + apt_key: + url: https://deb.nodesource.com/gpgkey/nodesource.gpg.key + notify: apt update + + - name: Install nodesource source list + template: + src: nodesource.list + dest: /etc/apt/sources.list.d/nodesource.list + owner: root + group: root + mode: 0644 + notify: apt update + + - meta: flush_handlers + + - name: Install nodejs + apt: + name: nodejs + + - name: Add database user + become: true + become_method: su + become_user: postgres + no_log: yes + postgresql_user: + name: etherpad + password: "{{ etherpad_db_password }}" + + - name: Add database + become: true + become_method: su + become_user: postgres + postgresql_db: + name: "{{ etherpad_db_name }}" + owner: "{{ etherpad_db_user }}" + + - name: Add etherpad user + user: + name: etherpad + home: /var/lib/etherpad + + - name: Create log file + file: + path: /var/log/etherpad.log + state: touch + owner: etherpad + group: etherpad + mode: 0644 + + - name: Create source directory + file: + path: /opt/etherpad + state: directory + owner: etherpad + group: etherpad + mode: 0755 + + - name: Clone etherpad source + become: yes + become_method: su + become_user: etherpad + git: + repo: https://github.com/ether/etherpad-lite.git + version: master + dest: /opt/etherpad + accept_hostkey: yes + notify: restart etherpad + + - name: Install etherpad config + template: + src: settings.json + dest: /opt/etherpad/settings.json + owner: root + group: root + mode: 0644 + notify: restart etherpad + + - name: Install etherpad service + template: + src: etherpad.service + dest: /etc/systemd/system/etherpad.service + owner: root + group: root + mode: 0644 + notify: restart etherpad + + - name: Clear default nginx site + file: + state: absent + path: /etc/nginx/sites-enabled/default + notify: reload nginx + + - name: Install nginx config + template: + src: nginx-site.conf + dest: /etc/nginx/sites-enabled/etherpad + owner: root + group: root + mode: 0644 + notify: reload nginx + + - name: Allow HTTP and HTTPS + iptables: + chain: INPUT + protocol: tcp + destination_port: "{{ item.port }}" + ctstate: NEW + jump: ACCEPT + ip_version: "{{ item.ip }}" + action: insert + with_items: + - { ip: ipv4, port: 80 } + - { ip: ipv4, port: 443 } + - { ip: ipv6, port: 80 } + - { ip: ipv6, port: 443 } + notify: persist iptables diff --git a/roles/etherpad/templates/etherpad.service b/roles/etherpad/templates/etherpad.service new file mode 100644 index 0000000..ae128af --- /dev/null +++ b/roles/etherpad/templates/etherpad.service @@ -0,0 +1,16 @@ +# Managed by Ansible + +[Unit] +Description=Etherpad +After=network.target + +[Service] +Type=simple +Restart=always +RestartSec=10s +ExecStart=/opt/etherpad/src/bin/run.sh /var/log/etherpad.log +User=etherpad + +[Install] +WantedBy=multi-user.target + diff --git a/roles/etherpad/templates/nginx-site.conf b/roles/etherpad/templates/nginx-site.conf new file mode 100644 index 0000000..9910a4d --- /dev/null +++ b/roles/etherpad/templates/nginx-site.conf @@ -0,0 +1,33 @@ +server { + listen 443 ssl http2 default_server; + listen [::]:443 ssl http2 default_server; + server_name {{ etherpad_domain }}; + + {% if acme_bootstrap_certs %} + include "snippets/snakeoil.conf"; + {% else %} + ssl_certificate "/var/lib/dehydrated/certs/{{ etherpad_domain }}/fullchain.pem"; + ssl_certificate_key "/var/lib/dehydrated/certs/{{ etherpad_domain }}/privkey.pem"; + {% endif %} + + location / { + proxy_pass http://127.0.0.1:9001/; + include proxy_params; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + } + + include "snippets/acme.conf"; +} + +server { + listen 80 default_server; + listen [::]:80 default_server; + server_name {{ etherpad_domain }}; + + location / { + rewrite ^/(.*) https://$server_name$request_uri? redirect; + } + + include "snippets/acme.conf"; +} diff --git a/roles/etherpad/templates/nodesource.list b/roles/etherpad/templates/nodesource.list new file mode 100644 index 0000000..1d17937 --- /dev/null +++ b/roles/etherpad/templates/nodesource.list @@ -0,0 +1,4 @@ +# Managed by Ansible + +deb https://deb.nodesource.com/{{ nodejs_version }} {{ ansible_facts.distribution_release }} main +deb-src https://deb.nodesource.com/{{ nodejs_version }} {{ ansible_facts.distribution_release }} main diff --git a/roles/etherpad/templates/settings.json b/roles/etherpad/templates/settings.json new file mode 100644 index 0000000..c73cdee --- /dev/null +++ b/roles/etherpad/templates/settings.json @@ -0,0 +1,113 @@ +// Managed by Ansible + +{ + "title": "Bitlair Etherpad", + "favicon": null, + "skinName": "colibris", + "skinVariants": "super-light-toolbar super-light-editor light-background", + "ip": "127.0.0.1", + "port": "9001", + "showSettingsInAdminPage": true, + + "dbType" : "postgres", + "dbSettings" : { + "host": "localhost", + "user": "{{ etherpad_db_user }}", + "password": "{{ etherpad_db_password }}", + "database": "{{ etherpad_db_name }}" + }, + + "defaultPadText" : "Welkom op Bitlair's Etherpad!\n\nPer 2022-10-30 is deze opnieuw geïnstalleerd. Je oude notities zijn tot 2022-12-01 terug te vinden op pad-oud.bitlair.nl", + + "padOptions": { + "noColors": false, + "showControls": true, + "showChat": true, + "showLineNumbers": true, + "useMonospaceFont": false, + "userName": false, + "userColor": false, + "rtl": false, + "alwaysShowChat": false, + "chatAndUsers": false, + "lang": "en-gb" + }, + + "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 + }, + + "suppressErrorsInPadText": false, + "requireSession": false, + "editOnly": false, + "minify": true, + "maxAge": 21600, // 60 * 60 * 6 = 6 hours + "abiword": null, + "soffice": null, + "tidyHtml": null, + "allowUnknownFileEnds": true, + "requireAuthentication": false, + "requireAuthorization": false, + "trustProxy": false, + "cookie": { + "sameSite": "Lax" + }, + "disableIPlogging": false, + "automaticReconnectionTimeout": 0, + "scrollWhenFocusLineIsOutOfViewport": { + "percentage": { + "editionAboveViewport": 0, + "editionBelowViewport": 0 + }, + "duration": 0, + "scrollWhenCaretIsInTheLastLineOfViewport": false, + "percentageToScrollWhenUserPressesArrowUp": 0 + }, + + + "socketTransportProtocols" : ["xhr-polling", "jsonp-polling", "htmlfile"], + "socketIo": { + "maxHttpBufferSize": 10000 + }, + + "loadTest": false, + "dumpOnUncleanExit": false, + "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 + }, + "importMaxFileSize": 52428800, // 50 * 1024 * 1024 + "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 + }, + "exposeVersion": false, + "loglevel": "INFO", + "customLocaleStrings": {}, + "enableAdminUITests": false +}