diff --git a/roles/taiga/defaults/main.yml b/roles/taiga/defaults/main.yml
new file mode 100644
index 0000000..4e08f7d
--- /dev/null
+++ b/roles/taiga/defaults/main.yml
@@ -0,0 +1,2 @@
+taiga_media_url: /media/
+taiga_static_url: /static/
diff --git a/roles/taiga/files/taiga-back.sh b/roles/taiga/files/taiga-back.sh
new file mode 100644
index 0000000..bee6589
--- /dev/null
+++ b/roles/taiga/files/taiga-back.sh
@@ -0,0 +1,7 @@
+#!/bin/sh
+export PYTHONUNBUFFERED=1
+cd /usr/local/lib/taiga/taiga-back
+exec /usr/local/lib/taiga/venv/bin/gunicorn \
+ --workers 4 \
+ -b [::1]:8001 \
+ taiga.wsgi
diff --git a/roles/taiga/files/taiga-events.service b/roles/taiga/files/taiga-events.service
new file mode 100644
index 0000000..e771e0a
--- /dev/null
+++ b/roles/taiga/files/taiga-events.service
@@ -0,0 +1,13 @@
+# vim: set ft=systemd :
+[Unit]
+Description=Taiga Events Server
+
+[Service]
+Type=simple
+WorkingDirectory=/usr/local/lib/taiga/taiga-events
+ExecStart=/usr/local/lib/taiga/taiga-events/node_modules/coffeescript/bin/coffee \
+ index.coffee
+User=taiga
+
+[Install]
+WantedBy=multi-user.target
diff --git a/roles/taiga/files/taiga.httpd.conf b/roles/taiga/files/taiga.httpd.conf
new file mode 100644
index 0000000..ca8a9be
--- /dev/null
+++ b/roles/taiga/files/taiga.httpd.conf
@@ -0,0 +1,33 @@
+# vim: set ft=apache :
+ProxyRequests off
+ProxyPreserveHost on
+
+ProxyPass /api http://localhost:8001/api
+ProxyPassReverse /api http://localhost:8001/api
+ProxyPass /admin http://localhost:8001/admin
+ProxyPassReverse /admin http://localhost:8001/admin
+ProxyPass /events ws://localhost:8888/events
+
+Alias /static /usr/local/lib/taiga/taiga-back/static
+
+ Require all granted
+
+
+Alias /media /usr/local/lib/taiga/taiga-back/media
+
+ Require all granted
+
+
+DocumentRoot /usr/local/lib/taiga/taiga-front-dist/dist
+
+ Require all granted
+
+ RewriteEngine On
+
+ RewriteCond %{HTTPS} !on
+ RewriteRule /.* https://%{SERVER_NAME}$0
+
+ RewriteCond %{REQUEST_FILENAME} !-d
+ RewriteCond %{REQUEST_FILENAME} !-f
+ RewriteRule ^ index.html [L]
+
diff --git a/roles/taiga/files/taiga.service b/roles/taiga/files/taiga.service
new file mode 100644
index 0000000..836ad46
--- /dev/null
+++ b/roles/taiga/files/taiga.service
@@ -0,0 +1,11 @@
+# vim: set ft=systemd :
+[Unit]
+Description=Taiga Backend Server
+
+[Service]
+Type=simple
+User=taiga
+ExecStart=/usr/local/libexec/taiga-back.sh
+
+[Install]
+WantedBy=multi-user.target
diff --git a/roles/taiga/handlers/main.yml b/roles/taiga/handlers/main.yml
new file mode 100644
index 0000000..aedf0f1
--- /dev/null
+++ b/roles/taiga/handlers/main.yml
@@ -0,0 +1,34 @@
+- name: reload systemd
+ command: systemctl daemon-reload
+
+- name: migrate taiga data
+ become: true
+ become_user: taiga
+ command:
+ /usr/local/lib/taiga/venv/bin/python manage.py migrate
+ chdir=/usr/local/lib/taiga/taiga-back
+- name: compile taiga messages
+# become: true
+# become_user: taiga
+ command:
+ /usr/local/lib/taiga/venv/bin/python manage.py compilemessages
+ chdir=/usr/local/lib/taiga/taiga-back
+- name: collect taiga static data
+# become: true
+# become_user: taiga
+ command:
+ /usr/local/lib/taiga/venv/bin/python manage.py collectstatic --noinput
+ chdir=/usr/local/lib/taiga/taiga-back
+
+- name: reload httpd
+ service:
+ name: httpd
+ state: reloaded
+- name: restart taiga-events
+ service:
+ name: taiga-events
+ state: restarted
+- name: restart taiga
+ service:
+ name: taiga
+ state: restarted
diff --git a/roles/taiga/tasks/main.yml b/roles/taiga/tasks/main.yml
new file mode 100644
index 0000000..5a2bba7
--- /dev/null
+++ b/roles/taiga/tasks/main.yml
@@ -0,0 +1,19 @@
+- import_tasks: postgresql.yml
+- import_tasks: rabbitmq.yml
+
+- import_tasks: taiga-back.yml
+- import_tasks: taiga-front.yml
+- import_tasks: taiga-events.yml
+
+- name: ensure apache is configured to serve taiga
+ copy:
+ src: taiga.httpd.conf
+ dest: /etc/httpd/conf.d/taiga.conf
+ mode: '0644'
+ notify:
+ - reload httpd
+- name: ensure selinux allows apache to proxy for taiga
+ seboolean:
+ name: httpd_can_network_connect
+ state: true
+ persistent: true
diff --git a/roles/taiga/tasks/postgresql.yml b/roles/taiga/tasks/postgresql.yml
new file mode 100644
index 0000000..a013f21
--- /dev/null
+++ b/roles/taiga/tasks/postgresql.yml
@@ -0,0 +1,19 @@
+- name: ensure taiga postgresql user exists
+ become: true
+ become_user: postgres
+ postgresql_user:
+ name=taiga
+ state=present
+
+- name: ensure taiga postgresql database exists
+ become: true
+ become_user: postgres
+ postgresql_db:
+ name=taiga
+ owner=taiga
+ encoding=utf-8
+ lc_collate=en_US.UTF-8
+ lc_ctype=en_US.UTF-8
+ state=present
+ notify:
+ - migrate taiga data
diff --git a/roles/taiga/tasks/rabbitmq.yml b/roles/taiga/tasks/rabbitmq.yml
new file mode 100644
index 0000000..4a3cd44
--- /dev/null
+++ b/roles/taiga/tasks/rabbitmq.yml
@@ -0,0 +1,14 @@
+- name: ensure taiga rabbitmq vhost exists
+ rabbitmq_vhost:
+ name=taiga
+ state=present
+- name: ensure taiga rabbitmq user exists
+ rabbitmq_user:
+ name: taiga
+ password: '{{ taiga_events_password }}'
+ permissions:
+ - vhost: taiga
+ configure_priv: .*
+ read_priv: .*
+ write_priv: .*
+ state: present
diff --git a/roles/taiga/tasks/taiga-back.yml b/roles/taiga/tasks/taiga-back.yml
new file mode 100644
index 0000000..c654e8d
--- /dev/null
+++ b/roles/taiga/tasks/taiga-back.yml
@@ -0,0 +1,73 @@
+- name: ensure system dependencies are installed
+ package:
+ name:
+ - gzip
+ - libjpeg
+ - python3-psycopg2
+ - '{{ taiga_python_package }}'
+ - sudo
+ - tar
+ - zlib
+ state: present
+ tags:
+ - install
+
+- name: ensure taiga user exists
+ user:
+ name: taiga
+ system: yes
+ home: /var/lib/taiga
+ state: present
+
+- name: ensure taiga dependencies are installed
+ environment:
+ PIP_NO_INDEX: t
+ PIP_FIND_LINKS: '{{ taiga_pip_url }}'
+ PIP_TRUSTED_HOST: '{{ taiga_pip_url|urlsplit("hostname") }}'
+ pip:
+ requirements: '{{ taiga_pip_url }}/requirements.txt'
+ virtualenv: /usr/local/lib/taiga/venv
+ virtualenv_command: '{{ taiga_python_exe }} -m venv'
+ state: present
+- name: ensure taiga-back is installed
+ unarchive:
+ src: '{{ taiga_back_url }}'
+ dest: /usr/local/lib/taiga/
+ remote_src: true
+ notify:
+ - migrate taiga data
+ - compile taiga messages
+ - collect taiga static data
+
+- name: ensure taiga media directory exists
+ file:
+ path: /usr/local/lib/taiga/taiga-back/media
+ owner: taiga
+ group: taiga
+ mode: '0755'
+ state: directory
+
+- name: ensure taiga-back is configured
+ template:
+ src: settings.py.j2
+ dest: /usr/local/lib/taiga/taiga-back/settings/local.py
+
+- name: ensure taiga-back entry point script is installed
+ copy:
+ src: taiga-back.sh
+ dest: /usr/local/libexec/taiga-back.sh
+ mode: '0755'
+ notify:
+ - restart taiga
+- name: ensure taiga systemd unit is installed
+ copy:
+ src: taiga.service
+ dest: /etc/systemd/system/taiga.service
+ mode: '0644'
+ notify:
+ - reload systemd
+ - restart taiga
+- name: ensure taiga starts at boot
+ service:
+ name: taiga
+ enabled: yes
diff --git a/roles/taiga/tasks/taiga-events.yml b/roles/taiga/tasks/taiga-events.yml
new file mode 100644
index 0000000..426622d
--- /dev/null
+++ b/roles/taiga/tasks/taiga-events.yml
@@ -0,0 +1,52 @@
+- name: ensure nodejs is installed
+ package:
+ name:
+ - nodejs
+ - npm
+ state: present
+ tags:
+ - install
+
+- name: ensure taiga-events directory exists
+ file:
+ path: /usr/local/lib/taiga/taiga-events
+ owner: taiga
+ group: taiga
+ mode: '0755'
+ state: directory
+- name: ensure taiga-events is installed
+ become: true
+ become_user: taiga
+ unarchive:
+ src: '{{ taiga_events_url }}'
+ dest: /usr/local/lib/taiga/
+ remote_src: true
+
+- name: ensure taiga-events dependencies are installed
+ become: true
+ become_user: taiga
+ npm:
+ path: /usr/local/lib/taiga/taiga-events
+
+- name: ensure taiga-events is configured
+ template:
+ src: taiga-events.config.json.j2
+ dest: /usr/local/lib/taiga/taiga-events/config.json
+ owner: root
+ group: taiga
+ mode: '0750'
+ notify:
+ - restart taiga-events
+
+- name: ensure taiga-events systemd unit is installed
+ copy:
+ src: taiga-events.service
+ dest: /etc/systemd/system/taiga-events.service
+ mode: '0644'
+ notify:
+ - reload systemd
+ - restart taiga-events
+- name: ensure taiga-events starts at boot
+ service:
+ name: taiga-events
+ enabled: yes
diff --git a/roles/taiga/tasks/taiga-front.yml b/roles/taiga/tasks/taiga-front.yml
new file mode 100644
index 0000000..fd00a1a
--- /dev/null
+++ b/roles/taiga/tasks/taiga-front.yml
@@ -0,0 +1,11 @@
+- name: ensure taiga-front is installed
+ unarchive:
+ src: '{{ taiga_front_url }}'
+ dest: /usr/local/lib/taiga/
+ remote_src: true
+
+- name: ensure taiga-front is configured
+ template:
+ src: taiga-front.conf.json.j2
+ dest: /usr/local/lib/taiga/taiga-front-dist/dist/conf.json
+ mode: '0644'
diff --git a/roles/taiga/templates/settings.py.j2 b/roles/taiga/templates/settings.py.j2
new file mode 100644
index 0000000..be00580
--- /dev/null
+++ b/roles/taiga/templates/settings.py.j2
@@ -0,0 +1,26 @@
+from .common import *
+
+MEDIA_URL = "{{ taiga_media_url }}"
+STATIC_URL = "{{ taiga_static_url }}"
+SITES["front"]["scheme"] = "http"
+SITES["front"]["domain"] = "example.com"
+
+SECRET_KEY = "{{ taiga_back_secret_key }}"
+
+DEBUG = False
+PUBLIC_REGISTER_ENABLED = True
+
+DEFAULT_FROM_EMAIL = "no-reply@example.com"
+SERVER_EMAIL = DEFAULT_FROM_EMAIL
+
+#CELERY_ENABLED = True
+
+EVENTS_PUSH_BACKEND = "taiga.events.backends.rabbitmq.EventsPushBackend"
+EVENTS_PUSH_BACKEND_OPTIONS = {"url": "amqp://taiga:{{ taiga_events_password }}@localhost:5672/taiga"}
+
+EMAIL_BACKEND = "django.core.mail.backends.smtp.EmailBackend"
+EMAIL_USE_TLS = False
+EMAIL_HOST = "{{ taiga_email_host }}"
+#EMAIL_HOST_USER = ""
+#EMAIL_HOST_PASSWORD = ""
+#EMAIL_PORT = 25
diff --git a/roles/taiga/templates/taiga-events.config.json.j2 b/roles/taiga/templates/taiga-events.config.json.j2
new file mode 100644
index 0000000..c818787
--- /dev/null
+++ b/roles/taiga/templates/taiga-events.config.json.j2
@@ -0,0 +1,7 @@
+{
+ "url": "amqp://taiga:{{ taiga_events_password }}",
+ "Secret": "{{ taiga_back_secret_key }}",
+ "webSocketServer": {
+ "port": 8888
+ }
+}
diff --git a/roles/taiga/templates/taiga-front.conf.json.j2 b/roles/taiga/templates/taiga-front.conf.json.j2
new file mode 100644
index 0000000..1cdf0c3
--- /dev/null
+++ b/roles/taiga/templates/taiga-front.conf.json.j2
@@ -0,0 +1,10 @@
+{
+ "api": "/api/v1/",
+ "publicRegisterEnabled": false,
+ "feedbackEnabled": false,
+ "privacyPolicyUrl": null,
+ "termsOfServiceUrl": null,
+ "GDPRUrl": null,
+ "maxUploadFileSize": null,
+ "contribPlugins": []
+}
diff --git a/roles/taiga/vars/main.yml b/roles/taiga/vars/main.yml
new file mode 100644
index 0000000..c47ef8d
--- /dev/null
+++ b/roles/taiga/vars/main.yml
@@ -0,0 +1,3 @@
+taiga_python_version: 3.6
+taiga_python_exe: /usr/bin/python{{ taiga_python_version }}
+taiga_python_package: python{{ taiga_python_version|replace('.', '') }}