diff --git a/roles/6-generic-apps/tasks/main.yml b/roles/6-generic-apps/tasks/main.yml index 01fcd7340..b7fe93cc2 100644 --- a/roles/6-generic-apps/tasks/main.yml +++ b/roles/6-generic-apps/tasks/main.yml @@ -27,6 +27,12 @@ when: ejabberd_install tags: ejabberd +- name: LOKOLE + include_role: + name: lokole + when: lokole_install + tags: lokole + - name: NEXTCLOUD include_role: name: nextcloud diff --git a/roles/lokole/README.rst b/roles/lokole/README.rst new file mode 100644 index 000000000..824202d07 --- /dev/null +++ b/roles/lokole/README.rst @@ -0,0 +1,22 @@ +============= +Lokole README +============= + +This Ansible role installs the `Lokole web app `_ within Internet-in-a-Box. Lokole is a project by the Canadian-Congolese non-profit `Ascoderu `_. + +The Lokole is a simple email client that offers functionality like: + +1. Self-service creation of user accounts +2. Read emails sent to the account +3. Write emails including rich formatting +4. Send attachments + +Using It +-------- + +Lokole should be accessible at http://box/lokole + +Known Issues +------------ + +Please see `#1282 `_. diff --git a/roles/lokole/defaults/main.yml b/roles/lokole/defaults/main.yml new file mode 100644 index 000000000..b1272ad1b --- /dev/null +++ b/roles/lokole/defaults/main.yml @@ -0,0 +1,21 @@ +# Info needed to install Lokole +lokole_version: "0.1.24" +lokole_install_path: "{{ content_base }}/lokole" # /library/lokole +lokole_venv: "{{ lokole_install_path }}/venv" # /library/lokole/venv + +# Info needed to run Lokole +lokole_user: lokole +lokole_run_directory: "/home/{{ lokole_user }}/state" + +lokole_install: True +lokole_enabled: True + +lokole_url: /lokole +lokole_full_url: "http://{{ iiab_hostname }}.{{ iiab_domain }}{{ lokole_url }}" # http://box.lan/lokole + +lokole_domain_socket: "{{ lokole_run_directory }}/lokole_gunicorn.sock" + +# Global variables provided by setup-lokole.sh L157-166 +# https://github.com/ascoderu/opwen-webapp/blob/master/setup/setup-lokole.sh#L157 +opwen_server_locale: "{{ default_language }}" +opwen_server_timezone: "{{ local_tz }}" diff --git a/roles/lokole/tasks/install.yml b/roles/lokole/tasks/install.yml new file mode 100644 index 000000000..68f368fdb --- /dev/null +++ b/roles/lokole/tasks/install.yml @@ -0,0 +1,125 @@ +- name: "Install 7 packages for Lokole: python3, python3-pip, python3-venv, python3-dev, libffi-dev, libssl-dev, bcrypt" + apt: + name: + - python3 + - python3-pip + - python3-venv + - python3-dev + - libffi-dev + - libssl-dev + - bcrypt + state: present + tags: + - install + +- name: pip install opwen_email_client (Lokole) {{ lokole_version }} from PyPI to {{ lokole_venv }} + pip: + name: opwen_email_client + version: "{{ lokole_version }}" + virtualenv: "{{ lokole_venv }}" + virtualenv_command: python3 -m venv "{{ lokole_venv }}" + tags: + - install + when: internet_available + +- name: Compile translations + shell: | + python_version=$(python3 -c 'from sys import version_info; print("%s.%s" % (version_info.major, version_info.minor));';) + {{ lokole_venv }}/bin/pybabel compile -d {{ item }}/translations + with_items: + - "{{ lokole_venv }}/lib/python${python_version}/site-packages/opwen_email_client/webapp" + tags: + - install + +- name: Create dir {{ lokole_run_directory }} + file: + path: "{{ lokole_run_directory }}" + state: directory + tags: + - configure + +- name: Install {{ lokole_run_directory }}/webapp_secrets.sh from template, to configure Lokole + template: + src: webapp_secrets.sh.j2 + dest: "{{ lokole_run_directory }}/webapp_secrets.sh" + tags: + - configure + +- name: Install {{ lokole_run_directory }}/webapp.sh from template, to configure Gunicorn + template: + src: webapp.sh.j2 + dest: "{{ lokole_run_directory }}/webapp.sh" + mode: a+x + tags: + - configure + +- name: Install unit file /etc/systemd/system/lokole.service from template + template: + src: lokole.service.j2 + dest: /etc/systemd/system/lokole.service + tags: + - systemd + +- name: Enable & Restart 'lokole' systemd service, with daemon_reload, if lokole_enabled + systemd: + daemon_reload: yes + name: lokole + enabled: yes + state: restarted + when: lokole_enabled + +- name: Disable 'lokole' service, if not lokole_enabled + systemd: + name: lokole + enabled: no + state: stopped + when: not lokole_enabled + +- name: Install /etc/{{ apache_config_dir }}/lokole.conf from template, for http://box/lokole + template: + src: lokole.conf.j2 + dest: "/etc/{{ apache_config_dir }}/lokole.conf" + +- name: Symlink /etc/apache2/sites-enabled/lokole.conf to /etc/{{ apache_config_dir }}/lokole.conf, if lokole_enabled (debuntu) + file: + src: "/etc/{{ apache_config_dir }}/lokole.conf" + path: /etc/apache2/sites-enabled/lokole.conf + state: link + when: lokole_enabled and is_debuntu + +- name: Remove /etc/apache2/sites-enabled/lokole.conf, if not lokole_enabled (debuntu) + file: + path: /etc/apache2/sites-enabled/lokole.conf + state: absent + when: not lokole_enabled and is_debuntu + +- name: Remove /etc/{{ apache_config_dir }}/lokole.conf, if not lokole_enabled (OS's other than debuntu) + file: + path: "/etc/{{ apache_config_dir }}/lokole.conf" + state: absent + when: (not lokole_enabled) and (not is_debuntu) + +- name: Restart Apache ({{ apache_service }}) to enable/disable http://box/lokole + service: + name: "{{ apache_service }}" + state: restarted + +- name: Add 'lokole' variable values to {{ iiab_ini_file }} + ini_file: + path: "{{ iiab_ini_file }}" + section: lokole + option: "{{ item.option }}" + value: "{{ item.value }}" + with_items: + - option: name + value: lokole + - option: description + value: '"Lokole is an email service that works offline, for rural communities."' + - option: lokole_run_directory + value: "{{ lokole_run_directory }}" + - option: lokole_url + value: "{{ lokole_url }}" + - option: lokole_full_url + value: "{{ lokole_full_url }}" + - option: lokole_enabled + value: "{{ lokole_enabled }}" diff --git a/roles/lokole/tasks/main.yml b/roles/lokole/tasks/main.yml new file mode 100644 index 000000000..55a1173c0 --- /dev/null +++ b/roles/lokole/tasks/main.yml @@ -0,0 +1,3 @@ +- name: Run Lokole's install.yml if lokole_install + include_tasks: install.yml + when: lokole_install diff --git a/roles/lokole/templates/lokole.conf.j2 b/roles/lokole/templates/lokole.conf.j2 new file mode 100644 index 000000000..5462444e8 --- /dev/null +++ b/roles/lokole/templates/lokole.conf.j2 @@ -0,0 +1,29 @@ +# Root directory goes to Lokole web server + +RedirectMatch ^{{ lokole_url }}$ {{ lokole_url }}/ + +ProxyRequests off +ProxyPass {{ lokole_url }}/ unix:{{ lokole_domain_socket }}|http://{{ iiab_hostname }}.{{ iiab_domain }}/ + + + ProxyPassReverse / + ProxyHTMLEnable On + ProxyHTMLURLMap / {{ lokole_url }}/ + RequestHeader unset Accept-Encoding + + +# /static directory is stored on filesystem +Alias {{ lokole_url }}/static {{ lokole_install_path }} + + + Options Indexes FollowSymLinks + + # Don't allow modifications in static directory + Require all granted + + Require all denied + + + +# Disable TRACE to prevent cross-site tracing +TraceEnable off diff --git a/roles/lokole/templates/lokole.service.j2 b/roles/lokole/templates/lokole.service.j2 new file mode 100644 index 000000000..29643cabd --- /dev/null +++ b/roles/lokole/templates/lokole.service.j2 @@ -0,0 +1,16 @@ +[Unit] +Description=Provides the Lokole Server +#Requires=lokole.socket +After=network.target + +[Service] +Type=simple +ExecStart=/bin/bash {{ lokole_run_directory }}/webapp.sh +ExecReload=/bin/kill -s HUP $MAINPID +ExecStop=/bin/kill -s TERM $MAINPID +User=root +Group=root +PrivateTmp=true + +[Install] +WantedBy=multi-user.target diff --git a/roles/lokole/templates/webapp.sh.j2 b/roles/lokole/templates/webapp.sh.j2 new file mode 100644 index 000000000..87290925a --- /dev/null +++ b/roles/lokole/templates/webapp.sh.j2 @@ -0,0 +1,9 @@ +#!/usr/bin/env sh +. '{{lokole_run_directory}}/webapp_secrets.sh' + +'{{lokole_venv}}/bin/gunicorn' \ + --timeout='300' \ + --workers='{{ [4, ansible_memtotal_mb / 200] | min | int }}' \ + --bind='unix:{{ lokole_domain_socket }}' \ + --log-level='error' \ + 'opwen_email_client.webapp:app' diff --git a/roles/lokole/templates/webapp_secrets.sh.j2 b/roles/lokole/templates/webapp_secrets.sh.j2 new file mode 100644 index 000000000..44dcfbae6 --- /dev/null +++ b/roles/lokole/templates/webapp_secrets.sh.j2 @@ -0,0 +1,4 @@ +export OPWEN_STATE_DIRECTORY='{{lokole_run_directory}}' +export OPWEN_SESSION_KEY='{{ lookup('password', '/dev/null chars=ascii_letters,digits,_ length=32') }}' +export OPWEN_PASSWORD_SALT='{{ lookup('password', '/dev/null chars=ascii_letters,digits,_ length=16') }}' +export OPWEN_CLIENT_NAME='iiab-{{ iiab_hostname }}' diff --git a/tests/test.yml b/tests/test.yml index 3d858cc75..858e12830 100644 --- a/tests/test.yml +++ b/tests/test.yml @@ -32,6 +32,7 @@ - { role: kalite } - { role: kiwix } - { role: kolibri } + - { role: lokole } - { role: mediawiki } - { role: mongodb } - { role: monit } diff --git a/vars/default_vars.yml b/vars/default_vars.yml index 2bbd8fe7b..067b2f72f 100644 --- a/vars/default_vars.yml +++ b/vars/default_vars.yml @@ -290,6 +290,10 @@ elgg_mysql_password: elgg4kids ejabberd_install: False ejabberd_enabled: False +# Lokole (email) +lokole_install: True +lokole_enabled: False + # Nextcloud nextcloud_install: True nextcloud_enabled: False diff --git a/vars/local_vars_big.yml b/vars/local_vars_big.yml index 5548682bb..2cc707ec2 100644 --- a/vars/local_vars_big.yml +++ b/vars/local_vars_big.yml @@ -170,6 +170,9 @@ elgg_enabled: True ejabberd_install: True ejabberd_enabled: False +lokole_install: True +lokole_enabled: True + nextcloud_install: True nextcloud_enabled: True diff --git a/vars/local_vars_medium.yml b/vars/local_vars_medium.yml index 26e3e3b0d..c024cfe4d 100644 --- a/vars/local_vars_medium.yml +++ b/vars/local_vars_medium.yml @@ -170,6 +170,9 @@ elgg_enabled: True ejabberd_install: False ejabberd_enabled: False +lokole_install: False +lokole_enabled: False + nextcloud_install: True nextcloud_enabled: True diff --git a/vars/local_vars_min.yml b/vars/local_vars_min.yml index 71d10826f..16511c97a 100644 --- a/vars/local_vars_min.yml +++ b/vars/local_vars_min.yml @@ -170,6 +170,9 @@ elgg_enabled: False ejabberd_install: False ejabberd_enabled: False +lokole_install: False +lokole_enabled: False + nextcloud_install: False nextcloud_enabled: False