Update to 2022-01-26 18:00

This commit is contained in:
Daniel Berteaud 2022-01-26 18:00:05 +01:00
parent 010ec37bf3
commit e293e29bbb
27 changed files with 1015 additions and 0 deletions

View File

@ -0,0 +1,76 @@
---
# Version to deploy
taiga_version: 6.5.0
# Where taiga will be installed
taiga_root_dir: /opt/taiga
# User under which taiga will run (will be created)
taiga_user: taiga
# Archive URL and expected checksum
taiga_archives:
back:
url: https://github.com/kaleidos-ventures/taiga-back/archive/refs/tags/{{ taiga_version }}.tar.gz
sha256: aa68e689a0095a1726869291eb8bcfe82e828d51188ed4a9eb797ed9a664aa0c
front:
url: https://github.com/kaleidos-ventures/taiga-front-dist/archive/refs/tags/{{ taiga_version }}.tar.gz
sha256: 1d2595b32346eeef1796db85d1c5701258e0c038be2bab9e86c0c7d6f99b034b
dir: taiga-front-dist-{{ taiga_version }}
events:
url: https://github.com/kaleidos-ventures/taiga-events/archive/refs/tags/{{ taiga_version }}.tar.gz
sha256: c6307e1246b97a2aa7f53755dbceb98b24256badf8282b37b8a24b51d08b583f
protected:
url: https://github.com/kaleidos-ventures/taiga-protected/archive/refs/tags/{{ taiga_version }}.tar.gz
sha256: 8465eaf078dee7b61f4fd5dbb216db94ea455b3c8d69c19c10ae33ff481e46f0
# Database settings
taiga_db_server: "{{ pg_server | default('localhost') }}"
taiga_db_port: 5432
taiga_db_name: taiga
taiga_db_user: taiga
# If the password is not defined, a random one will be generated and stored under {{ taiga_root_dir }}/meta/ansible_dbpass
# taiga_db_pass: S3cr3t.
# Secret key used by various components
# If not defined, a random one will be created and stored under {{ taiga_root_dir }}/meta/ansible_secret_key
# taiga_secret_key: S3cr3t.
# AMQP settings
taiga_amqp_server: localhost
taiga_amqp_port: 5672
taiga_amqp_user: taiga
taiga_amqp_vhost: taiga
# If the password is not defined, a random one will be create and stored under {{ taiga_root_dir }}/meta/ansible_amqp_pass
# But this is only useful when taiga_amqp_server is localhost. If you use a remote AMQP server, you'll have to define the pass
# taiga_amqp_pass: S3cr3t.
# Ports used by taiga components
# they will only be accessible to localhost and exposed by nginx
# If you want to restrict access at the firewall level (for example, to only allow a reverse proxy), you need to
# set nginx_src_ip to the list of IP (or CIDR network) which will have access to port 80/443
taiga_ports:
back: 8001
protected: 8003
events: 8888
# Public URL to reach taiga
taiga_public_url: https://{{ inventory_hostname }}/
# A default admin user is created during installation
# You can set its password, or a random one will be generated and stored under {{ taiga_root_dir }}/meta/ansible_admin_pass
# taiga_admin_pass: S3cr3t.
# Registration enabled ?
taiga_user_registration: False
# Max upload file size (in MB)
taiga_max_upload_file_size: 20
# Email settings
taiga_email_from: taiga-no-reply@{{ ansible_domain }}
taiga_smtp_server: localhost
taiga_smtp_port: 25
taiga_smtp_tls: "{{ (taiga_smtp_port == 587) | ternary(True, False) }}"
taiga_smtp_ssl: "{{ (taiga_smtp_port == 465) | ternary(True, False) }}"
# If your SMTP server requires an authentication, set the following variables
#taiga_smtp_user: taiga@example.org
#taiga_smtp_pass: p@ssw0rd

View File

@ -0,0 +1,22 @@
module taiga 1.2;
require {
type ldconfig_exec_t;
type etc_t;
type init_t;
type init_tmp_t;
type ldconfig_t;
type amqp_port_t;
type postgresql_port_t;
type usr_t;
class file { append execute_no_trans write map };
class tcp_socket name_connect;
class process2 nnp_transition;
}
allow init_t ldconfig_exec_t:file execute_no_trans;
allow init_t ldconfig_t:process2 nnp_transition;
allow init_t usr_t:file { write append };
allow init_t init_tmp_t:file map;
allow init_t postgresql_port_t:tcp_socket name_connect;
allow init_t amqp_port_t:tcp_socket name_connect;

View File

@ -0,0 +1,9 @@
---
- name: restart taiga
service: name=taiga-{{ item }} state=restarted
loop:
- back
- async
- events
- protected

View File

@ -0,0 +1,9 @@
---
dependencies:
- role: nodejs
- role: rabbitmq_server
when: taiga_amqp_server in ['localhost', '127.0.0.1']
- role: nginx
- role: postgresql_server
when: taiga_db_server in ['localhost', '127.0.0.1']

View File

@ -0,0 +1,10 @@
---
- name: Compress previous version
command: tar cf {{ taiga_root_dir }}/archives/{{ taiga_current_version }}.tar.zst --use-compress-program=zstd ./
args:
chdir: "{{ taiga_root_dir }}/archives/{{ taiga_current_version }}"
warn: False
environment:
ZSTD_CLEVEL: 10
tags: taiga

View File

@ -0,0 +1,38 @@
---
- name: Create the archive dir
file: path={{ taiga_root_dir }}/archives/{{ taiga_current_version }} state=directory
tags: taiga
- name: Install postgresql client
package:
name:
- postgresql14
tags: taiga
- name: Archive previous version
synchronize:
src: "{{ taiga_root_dir }}/{{ item }}"
dest: "{{ taiga_root_dir }}/archives/{{ taiga_current_version }}/"
recursive: True
delete: True
compress: False
loop:
- venv
- app
delegate_to: "{{ inventory_hostname }}"
tags: taiga
- name: Dump the database
command: >
/usr/pgsql-14/bin/pg_dump
--clean
--create
--host={{ taiga_db_server | quote }}
--port={{ taiga_db_port | quote }}
--username={{ taiga_db_user | quote }} {{ taiga_db_name | quote }}
--file="{{ taiga_root_dir }}/archives/{{ taiga_current_version }}/{{ taiga_db_name }}.sql"
environment:
- PGPASSWORD: "{{ taiga_db_pass }}"
tags: taiga

View File

@ -0,0 +1,15 @@
---
- name: Remove tmp and obsolete files
file: path={{ item }} state=absent
loop:
- "{{ taiga_root_dir }}/tmp/taiga-back-{{ taiga_version }}.tar.gz"
- "{{ taiga_root_dir }}/tmp/taiga-back-{{ taiga_version }}"
- "{{ taiga_root_dir }}/tmp/taiga-front-dist-{{ taiga_version }}.tar.gz"
- "{{ taiga_root_dir }}/tmp/taiga-front-dist-{{ taiga_version }}"
- "{{ taiga_root_dir }}/tmp/taiga-events-{{ taiga_version }}.tar.gz"
- "{{ taiga_root_dir }}/tmp/taiga-events-{{ taiga_version }}"
- "{{ taiga_root_dir }}/tmp/taiga-protected-{{ taiga_version }}.tar.gz"
- "{{ taiga_root_dir }}/tmp/taiga-protected-{{ taiga_version }}"
- "{{ taiga_root_dir }}/archives/{{ taiga_current_version }}"
tags: taiga

View File

@ -0,0 +1,88 @@
---
- name: Deploy configuration
template: src={{ item.src }} dest={{ item.dest }} group={{ item.group | default(omit) }} mode={{ item.mode | default(omit) }}
loop:
- src: back/config.py.j2
dest: "{{ taiga_root_dir }}/app/back/settings/config.py"
group: "{{ taiga_user }}"
mode: 640
- src: front/conf.json.j2
dest: "{{ taiga_root_dir }}/app/front/dist/conf.json"
- src: events/env.j2
dest: "{{ taiga_root_dir }}/app/events/.env"
group: "{{ taiga_user }}"
mode: 640
- src: protected/env.j2
dest: "{{ taiga_root_dir }}/app/protected/.env"
group: "{{ taiga_user }}"
mode: 640
notify: restart taiga
tags: taiga
- name: Deploy nginx configuration
template: src=nginx.conf.j2 dest=/etc/nginx/ansible_conf.d/10-taiga.conf
notify: reload nginx
tags: taiga
- name: Create RabbitMQ user and vhost
shell: |
{% if taiga_amqp_user_exists.rc == 0 %}
rabbitmqctl change_password {{ taiga_amqp_user }} {{ taiga_amqp_pass }}
{% else %}
rabbitmqctl add_user {{ taiga_amqp_user }} {{ taiga_amqp_pass }}
{% endif %}
rabbitmqctl add_vhost {{ taiga_amqp_vhost }}
rabbitmqctl set_permissions -p {{ taiga_amqp_vhost }} {{ taiga_amqp_user }} ".*" ".*" ".*"
when: taiga_amqp_server in ['localhost', '127.0.0.1']
tags: taiga
- when: taiga_install_mode != 'none'
block:
- name: Migrate database
django_manage:
command: migrate
app_path: "{{ taiga_root_dir }}/app/back"
virtualenv: "{{ taiga_root_dir }}/venv"
become_user: "{{ taiga_user }}"
- name: Compile messages
django_manage:
command: compilemessages
app_path: "{{ taiga_root_dir }}/app/back"
virtualenv: "{{ taiga_root_dir }}/venv"
- name: Collect static files
django_manage:
command: collectstatic
app_path: "{{ taiga_root_dir }}/app/back"
virtualenv: "{{ taiga_root_dir }}/venv"
environment:
DJANGO_SETTINGS_MODULE: settings.config
CELERY_ENABLED: False
tags: taiga
- when: taiga_install_mode == 'install'
block:
- name: Create admin user
django_manage:
command: createsuperuser --noinput --username admin --email admin@{{ ansible_domain }}
app_path: "{{ taiga_root_dir }}/app/back"
virtualenv: "{{ taiga_root_dir }}/venv"
- name: load initial data
django_manage:
command: loaddata initial_project_templates
app_path: "{{ taiga_root_dir }}/app/back"
virtualenv: "{{ taiga_root_dir }}/venv"
environment:
DJANGO_SUPERUSER_PASSWORD: '{{ taiga_admin_pass }}'
DJANGO_SETTINGS_MODULE: settings.config
CELERY_ENABLED: False
become_user: "{{ taiga_user }}"
when: taiga_install_mode == 'install'
tags: taiga

View File

@ -0,0 +1,34 @@
---
- name: Create needed directories
file: path={{ item.dir }} state=directory owner={{ item.owner | default(omit) }} group={{ item.group | default(omit) }} mode={{ item.mode | default(omit) }}
loop:
- dir: "{{ taiga_root_dir }}"
owner: "{{ taiga_user }}"
group: nginx
mode: 750
- dir: "{{ taiga_root_dir }}/backup"
owner: root
group: root
mode: 700
- dir: "{{ taiga_root_dir }}/meta"
owner: root
group: root
mode: 700
- dir: "{{ taiga_root_dir }}/archives"
owner: root
group: root
mode: 700
- dir: "{{ taiga_root_dir }}/tmp"
owner: "{{ taiga_user }}"
mode: 700
- dir: "{{ taiga_root_dir }}/app"
- dir: "{{ taiga_root_dir }}/app/back"
- dir: "{{ taiga_root_dir }}/app/front"
- dir: "{{ taiga_root_dir }}/app/events"
- dir: "{{ taiga_root_dir }}/app/protected"
- dir: "{{ taiga_root_dir }}/data/media"
owner: "{{ taiga_user }}"
group: "{{ taiga_user }}"
mode: 750
tags: taiga

View File

@ -0,0 +1,65 @@
---
# Load distribution specific variables
- include_vars: "{{ item }}"
with_first_found:
- "{{ role_path }}/vars/{{ ansible_distribution }}-{{ ansible_distribution_major_version }}.yml"
- "{{ role_path }}/vars/{{ ansible_os_family }}-{{ ansible_distribution_major_version }}.yml"
- "{{ role_path }}/vars/{{ ansible_distribution }}.yml"
- "{{ role_path }}/vars/{{ ansible_os_family }}.yml"
tags: taiga
# Detect installed version (if any)
- block:
- import_tasks: ../includes/webapps_set_install_mode.yml
vars:
- root_dir: "{{ taiga_root_dir }}"
- version: "{{ taiga_version }}"
- set_fact: taiga_install_mode={{ (install_mode == 'upgrade' and not taiga_manage_upgrade) | ternary('none',install_mode) }}
- set_fact: taiga_current_version={{ current_version | default('') }}
tags: taiga
# Generate a password for the database if needed
- when: taiga_db_pass is not defined
block:
- import_tasks: ../includes/get_rand_pass.yml
vars:
- pass_file: "{{ taiga_root_dir }}/meta/ansible_dbpass"
- set_fact: taiga_db_pass={{ rand_pass }}
tags: taiga
# Create a random secret key
- when: taiga_secret_key is not defined
block:
- import_tasks: ../includes/get_rand_pass.yml
vars:
- pass_file: "{{ taiga_root_dir }}/meta/ansible_secret_key"
- set_fact: taiga_secret_key={{ rand_pass }}
tags: taiga
# AMQP password
- when: taiga_amqp_pass is not defined
block:
- import_tasks: ../includes/get_rand_pass.yml
vars:
- pass_file: "{{ taiga_root_dir }}/meta/ansible_amqp_pass"
- complex: False
- set_fact: taiga_amqp_pass={{ rand_pass }}
tags: taiga
# Default admin pass
- when: taiga_admin_pass is not defined
block:
- import_tasks: ../includes/get_rand_pass.yml
vars:
- pass_file: "{{ taiga_root_dir }}/meta/ansible_admin_pass"
- complex: False
- set_fact: taiga_admin_pass={{ rand_pass }}
tags: taiga
- name: Check if RabbitMQ user exists
shell: rabbitmqctl list_users | grep -qP '^{{ taiga_amqp_user }}\s+'
register: taiga_amqp_user_exists
failed_when: False
changed_when: False
tags: taiga

View File

@ -0,0 +1,135 @@
---
- name: Install packages
package: name={{ taiga_packages }}
tags: taiga
- name: Stop services during upgrade
service: name={{ item }} state=stopped
loop:
- taiga-back
- taiga-async
- taiga-events
- taiga-protected
when: taiga_install_mode == 'upgrade'
tags: taiga
- when: taiga_install_mode != 'none'
block:
- name: Download components
get_url:
url: "{{ taiga_archives[item].url }}"
dest: "{{ taiga_root_dir }}/tmp"
checksum: sha256:{{ taiga_archives[item].sha256 }}
loop: "{{ taiga_archives.keys() | list }}"
- name: Extract archives
unarchive:
src: "{{ taiga_root_dir }}/tmp/{{ taiga_archives[item].dir | default('taiga-' ~ item ~ '-' ~ taiga_version) }}.tar.gz"
dest: "{{ taiga_root_dir }}/tmp"
remote_src: True
loop: "{{ taiga_archives.keys() | list }}"
- name: Move components to their final dir
synchronize:
src: "{{ taiga_root_dir }}/tmp/{{ taiga_archives[item].dir | default('taiga-' ~ item ~ '-' ~ taiga_version) }}/"
dest: "{{ taiga_root_dir }}/app/{{ item }}/"
delete: True
compress: False
loop: "{{ taiga_archives.keys() | list }}"
delegate_to: "{{ inventory_hostname }}"
- name: Create the virtualenv
pip:
name:
- pip
- wheel
virtualenv: "{{ taiga_root_dir }}/venv"
virtualenv_command: /bin/python3.9 -m venv
- name: Install taiga-back dependencies
pip:
requirements: "{{ taiga_root_dir }}/app/back/requirements.txt"
state: "{{ (taiga_install_mode == 'upgrade') | ternary('latest', 'present') }}"
virtualenv: "{{ taiga_root_dir }}/venv"
virtualenv_command: /bin/python3.9 -m venv
#environment:
# PATH: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/usr/pgsql-14/bin/
- name: Install the contrib-protected plugin
pip:
name: git+https://github.com/kaleidos-ventures/taiga-contrib-protected.git@stable#egg=taiga-contrib-protected
virtualenv: "{{ taiga_root_dir }}/venv"
virtualenv_command: /bin/python3.9 -m venv
- name: Install dependencies for taiga-events
npm:
path: "{{ taiga_root_dir }}/app/events/"
- name: Install requirements for taiga-protected
pip:
requirements: "{{ taiga_root_dir }}/app/protected/requirements.txt"
state: "{{ (taiga_install_mode == 'upgrade') | ternary('latest', 'present') }}"
virtualenv: "{{ taiga_root_dir }}/venv"
virtualenv_command: /bin/python3.9 -m venv
tags: taiga
- block:
- name: Create the PostgreSQL role
postgresql_user:
db: postgres
name: "{{ taiga_db_user }}"
password: "{{ taiga_db_pass }}"
login_host: "{{ taiga_db_server }}"
login_user: sqladmin
login_password: "{{ pg_admin_pass }}"
- name: Create the PostgreSQL database
postgresql_db:
name: "{{ taiga_db_name }}"
encoding: UTF-8
template: template0
owner: "{{ taiga_db_user }}"
login_host: "{{ taiga_db_server }}"
login_user: sqladmin
login_password: "{{ pg_admin_pass }}"
tags: taiga
- name: Install service units
template: src={{ item }}.j2 dest=/etc/systemd/system/{{ item }}
loop:
- taiga-back.service
- taiga-async.service
- taiga-events.service
- taiga-protected.service
register: taiga_units
tags: taiga
- name: Reload systemd
systemd: daemon_reload=True
when: taiga_units.results | selectattr('changed','equalto',True) | list | length > 0
tags: taiga
- name: Install backup hooks
template: src={{ item }}-backup.j2 dest=/etc/backup/{{ item }}.d/taiga mode=700
loop:
- pre
- post
tags: taiga
- name: Copy SELinux policy
copy: src=taiga.te dest=/etc/selinux/targeted/local/
register: taiga_selinux_policy
tags: taiga
- name: Compile and load SELinux policy
shell: |
cd /etc/selinux/targeted/local/
checkmodule -M -m -o taiga.mod taiga.te
semodule_package -o taiga.pp -m taiga.mod
semodule -i /etc/selinux/targeted/local/taiga.pp
when: ansible_selinux.status == 'enabled' and taiga_selinux_policy.changed
tags: taiga

View File

@ -0,0 +1,14 @@
---
- include: user.yml
- include: directories.yml
- include: facts.yml
- include: archive_pre.yml
when: taiga_install_mode == 'upgrade'
- include: install.yml
- include: conf.yml
- include: services.yml
- include: write_version.yml
- include: archive_post.yml
when: taiga_install_mode == 'upgrade'
- include: cleanup.yml

View File

@ -0,0 +1,10 @@
---
- name: Start and enable services
service: name={{ item }} state=started enabled=True
loop:
- taiga-back
- taiga-async
- taiga-events
- taiga-protected
tags: taiga

View File

@ -0,0 +1,9 @@
---
- name: Create user
user:
name: "{{ taiga_user }}"
home: "{{ taiga_root_dir }}"
system: True
shell: /sbin/nologin
tags: taiga

View File

@ -0,0 +1,5 @@
---
- name: Write installed version
copy: content={{ taiga_version }} dest={{ taiga_root_dir }}/meta/ansible_version
tags: taiga

View File

@ -0,0 +1,220 @@
# -*- coding: utf-8 -*-
import os
from .common import *
#########################################
## GENERIC
#########################################
DEBUG = False
#ADMINS = (
# ("Admin", "example@example.com"),
#)
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': '{{ taiga_db_name }}',
'USER': '{{ taiga_db_user }}',
'PASSWORD': '{{ taiga_db_pass }}',
'HOST': '{{ taiga_db_server }}',
'PORT': '{{ taiga_db_port }}',
}
}
SECRET_KEY = "{{ taiga_secret_key }}"
TAIGA_SITES_SCHEME = "{{ taiga_public_url | urlsplit('scheme') }}"
TAIGA_SITES_DOMAIN = "{{ taiga_public_url | urlsplit('hostname') }}"
FORCE_SCRIPT_NAME = "{{ (taiga_public_url | urlsplit('path') == '/') | ternary('', taiga_public_url | urlsplit('path')) }}"
TAIGA_URL = f"{ TAIGA_SITES_SCHEME }://{ TAIGA_SITES_DOMAIN }{ FORCE_SCRIPT_NAME }"
SITES = {
"api": { "name": "api", "scheme": TAIGA_SITES_SCHEME, "domain": TAIGA_SITES_DOMAIN },
"front": { "name": "front", "scheme": TAIGA_SITES_SCHEME, "domain": f"{ TAIGA_SITES_DOMAIN }{ FORCE_SCRIPT_NAME }" }
}
# Setting DEFAULT_PROJECT_SLUG_PREFIX to false
# removes the username from project slug
DEFAULT_PROJECT_SLUG_PREFIX = False
#########################################
## MEDIA AND STATIC
#########################################
MEDIA_ROOT = '{{ taiga_root_dir }}/data/media/'
MEDIA_URL = f"{ TAIGA_URL }/media/"
DEFAULT_FILE_STORAGE = "taiga_contrib_protected.storage.ProtectedFileSystemStorage"
THUMBNAIL_DEFAULT_STORAGE = DEFAULT_FILE_STORAGE
# STATIC_ROOT = '/home/taiga/static'
STATIC_URL = f"{ TAIGA_URL }/static/"
#########################################
## EMAIL
#########################################
# https://docs.djangoproject.com/en/3.1/topics/email/
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
CHANGE_NOTIFICATIONS_MIN_INTERVAL = 120 # seconds
DEFAULT_FROM_EMAIL = '{{ taiga_email_from }}'
EMAIL_USE_TLS = {{ taiga_smtp_tls | ternary('True', 'False') }}
EMAIL_USE_SSL = {{ taiga_smtp_ssl | ternary('True', 'False') }}
EMAIL_HOST = '{{ taiga_smtp_server }}'
EMAIL_PORT = {{ taiga_smtp_port }}
{% if taiga_smtp_user is defined and taiga_smtp_pass is defined %}
EMAIL_HOST_USER = '{{ taiga_smtp_user }}'
EMAIL_HOST_PASSWORD = '{{ taiga_smtp_pass }}'
{% endif %}
#########################################
## EVENTS
#########################################
EVENTS_PUSH_BACKEND = "taiga.events.backends.rabbitmq.EventsPushBackend"
EVENTS_PUSH_BACKEND_OPTIONS = {
"url": "amqp://{{ taiga_amqp_user }}:{{ taiga_amqp_pass }}@{{ taiga_amqp_server }}:{{ taiga_amqp_port }}/{{ taiga_amqp_vhost }}"
}
#########################################
## TAIGA ASYNC
#########################################
CELERY_ENABLED = os.getenv('CELERY_ENABLED', 'True') == 'True'
from kombu import Queue # noqa
CELERY_BROKER_URL = "amqp://{{ taiga_amqp_user }}:{{ taiga_amqp_pass }}@{{ taiga_amqp_server }}:{{ taiga_amqp_port }}/{{ taiga_amqp_vhost }}"
CELERY_RESULT_BACKEND = None # for a general installation, we don't need to store the results
CELERY_ACCEPT_CONTENT = ['pickle', ] # Values are 'pickle', 'json', 'msgpack' and 'yaml'
CELERY_TASK_SERIALIZER = "pickle"
CELERY_RESULT_SERIALIZER = "pickle"
CELERY_TIMEZONE = "{{ system_tz | default('Europe/Paris') }}"
CELERY_TASK_DEFAULT_QUEUE = 'tasks'
CELERY_QUEUES = (
Queue('tasks', routing_key='task.#'),
Queue('transient', routing_key='transient.#', delivery_mode=1)
)
CELERY_TASK_DEFAULT_EXCHANGE = 'tasks'
CELERY_TASK_DEFAULT_EXCHANGE_TYPE = 'topic'
CELERY_TASK_DEFAULT_ROUTING_KEY = 'task.default'
#########################################
## CONTRIBS
#########################################
# INSTALLED_APPS += [
# "taiga_contrib_slack",
# "taiga_contrib_github_auth",
# "taiga_contrib_gitlab_auth"
# ]
#
# GITHUB_API_CLIENT_ID = "changeme"
# GITHUB_API_CLIENT_SECRET = "changeme"
#
# GITLAB_API_CLIENT_ID = "changeme"
# GITLAB_API_CLIENT_SECRET = "changeme"
# GITLAB_URL = "changeme"
#########################################
## TELEMETRY
#########################################
ENABLE_TELEMETRY = False
#########################################
## REGISTRATION
#########################################
PUBLIC_REGISTER_ENABLED = False
#########################################
## THROTTLING
#########################################
#REST_FRAMEWORK["DEFAULT_THROTTLE_RATES"] = {
# "anon-write": "20/min",
# "user-write": None,
# "anon-read": None,
# "user-read": None,
# "import-mode": None,
# "import-dump-mode": "1/minute",
# "create-memberships": None,
# "login-fail": None,
# "register-success": None,
# "user-detail": None,
# "user-update": None,
#}
# This list should contain:
# - Taiga users IDs
# - Valid clients IP addresses (X-Forwarded-For header)
#REST_FRAMEWORK["DEFAULT_THROTTLE_WHITELIST"] = []
# LIMIT ALLOWED DOMAINS FOR REGISTER AND INVITE
# None or [] values in USER_EMAIL_ALLOWED_DOMAINS means allow any domain
#USER_EMAIL_ALLOWED_DOMAINS = None
# PUCLIC OR PRIVATE NUMBER OF PROJECT PER USER
#MAX_PRIVATE_PROJECTS_PER_USER = None # None == no limit
#MAX_PUBLIC_PROJECTS_PER_USER = None # None == no limit
#MAX_MEMBERSHIPS_PRIVATE_PROJECTS = None # None == no limit
#MAX_MEMBERSHIPS_PUBLIC_PROJECTS = None # None == no limit
#########################################
## SITEMAP
#########################################
# If is True /front/sitemap.xml show a valid sitemap of taiga-front client
#FRONT_SITEMAP_ENABLED = False
#FRONT_SITEMAP_CACHE_TIMEOUT = 24*60*60 # In second
#########################################
## FEEDBACK
#########################################
# Note: See config in taiga-front too
FEEDBACK_ENABLED = False
#FEEDBACK_EMAIL = "support@taiga.io"
#########################################
## STATS
#########################################
#STATS_ENABLED = False
#STATS_CACHE_TIMEOUT = 60*60 # In second
#########################################
## IMPORTERS
#########################################
# Configuration for the GitHub importer
# Remember to enable it in the front client too.
#IMPORTERS["github"] = {
# "active": True,
# "client_id": "XXXXXX_get_a_valid_client_id_from_github_XXXXXX",
# "client_secret": "XXXXXX_get_a_valid_client_secret_from_github_XXXXXX"
#}
# Configuration for the Trello importer
# Remember to enable it in the front client too.
#IMPORTERS["trello"] = {
# "active": True, # Enable or disable the importer
# "api_key": "XXXXXX_get_a_valid_api_key_from_trello_XXXXXX",
# "secret_key": "XXXXXX_get_a_valid_secret_key_from_trello_XXXXXX"
#}
# Configuration for the Jira importer
# Remember to enable it in the front client too.
#IMPORTERS["jira"] = {
# "active": True, # Enable or disable the importer
# "consumer_key": "XXXXXX_get_a_valid_consumer_key_from_jira_XXXXXX",
# "cert": "XXXXXX_get_a_valid_cert_from_jira_XXXXXX",
# "pub_cert": "XXXXXX_get_a_valid_pub_cert_from_jira_XXXXXX"
#}

View File

@ -0,0 +1,4 @@
RABBITMQ_URL="amqp://{{ taiga_amqp_user }}:{{ taiga_amqp_pass }}@{{ taiga_amqp_server }}:{{ taiga_amqp_port }}/{{ taiga_amqp_vhost }}"
SECRET="{{ taiga_secret_key }}"
WEB_SOCKET_SERVER_PORT={{ taiga_ports['events'] }}
APP_PORT=3023

View File

@ -0,0 +1,29 @@
{
"api": "{{ taiga_public_url }}/api/v1/",
"eventsUrl": "{{ taiga_public_url | regex_replace('^http','ws') }}/events",
"baseHref": "{{ (taiga_public_url | urlsplit('path') == '') | ternary('/', taiga_public_url | urlsplit('path')) }}",
"eventsMaxMissedHeartbeats": 5,
"eventsHeartbeatIntervalTime": 60000,
"eventsReconnectTryInterval": 10000,
"debug": false,
"debugInfo": false,
"defaultLanguage": "en",
"themes": ["taiga"],
"defaultTheme": "taiga",
"defaultLoginEnabled": true,
"publicRegisterEnabled": {{ taiga_user_registration | ternary('true', 'false') }},
"feedbackEnabled": true,
"supportUrl": "https://resources.taiga.io",
"privacyPolicyUrl": null,
"termsOfServiceUrl": null,
"maxUploadFileSize": {{ taiga_max_upload_file_size }},
"contribPlugins": [],
"tagManager": { "accountId": null },
"tribeHost": null,
"enableAsanaImporter": false,
"enableGithubImporter": false,
"enableJiraImporter": false,
"enableTrelloImporter": false,
"gravatar": false,
"rtlLanguages": ["ar", "fa", "he"]
}

View File

@ -0,0 +1,76 @@
server {
listen 443 ssl http2;
server_name {{ taiga_public_url | urlsplit('hostname') }};
large_client_header_buffers 4 32k;
client_max_body_size {{ taiga_max_upload_file_size }}M;
charset utf-8;
# Frontend
location / {
alias {{ taiga_root_dir }}/app/front/dist/;
index index.html;
try_files $uri $uri/ index.html =404;
}
# API
location /api/ {
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Scheme $scheme;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://127.0.0.1:{{ taiga_ports['back'] }}/api/;
proxy_redirect off;
}
# Admin
location /admin/ {
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Scheme $scheme;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://127.0.0.1:{{ taiga_ports['back'] }}/admin/;
proxy_redirect off;
}
# Static files
location /static/ {
alias {{ taiga_root_dir }}/app/back/static/;
}
# Media
location /_protected/ {
internal;
alias {{ taiga_root_dir }}/data/media/;
add_header Content-disposition "attachment";
}
# Unprotected section
location /media/exports/ {
alias {{ taiga_root_dir }}/data/media/exports/;
add_header Content-disposition "attachment";
}
location /media/ {
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Scheme $scheme;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://127.0.0.1:{{ taiga_ports['protected'] }}/;
proxy_redirect off;
}
# Events
location /events {
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_connect_timeout 7d;
proxy_send_timeout 7d;
proxy_read_timeout 7d;
proxy_pass http://127.0.0.1:{{ taiga_ports['events'] }}/events;
}
}

View File

@ -0,0 +1,5 @@
#!/bin/sh
set -eo pipefail
rm -f {{ taiga_root_dir }}/backup/*

View File

@ -0,0 +1,13 @@
#!/bin/sh
set -eo pipefail
PGPASSWORD='{{ taiga_db_pass }}' /usr/pgsql-14/bin/pg_dump \
--clean \
--create \
--username={{ taiga_db_user | quote }} \
--host={{ taiga_db_server | quote }} \
--port={{ taiga_db_port }} \
{{ taiga_db_name | quote }} | \
zstd -c > {{ taiga_root_dir }}/backup/{{ taiga_db_name | quote }}.sql.zst

View File

@ -0,0 +1,3 @@
SECRET_KEY={{ taiga_secret_key }}
MAX_AGE=300
TAIGA_SUBPATH={{ taiga_public_url | urlsplit('path') }}

View File

@ -0,0 +1,25 @@
[Unit]
Description=Taiga async
After=network.target rabbitmq-server.service
[Service]
User={{ taiga_user }}
Group={{ taiga_user }}
Environment=PYTHONUNBUFFERED=true
Environment=DJANGO_SETTINGS_MODULE=settings.config
WorkingDirectory={{ taiga_root_dir }}/app/back
ExecStart={{ taiga_root_dir }}/venv/bin/celery -A taiga.celery worker -B --concurrency 4 -l INFO --schedule={{ taiga_root_dir }}/data/celerybeat-schedule
PrivateTmp=yes
PrivateDevices=yes
ProtectSystem=full
ProtectHome=yes
NoNewPrivileges=yes
MemoryLimit=1024M
SyslogIdentifier=taiga-async
Restart=on-failure
StartLimitInterval=0
RestartSec=30
[Install]
WantedBy=multi-user.target

View File

@ -0,0 +1,24 @@
[Unit]
Description=Taiga backend
After=network.target rabbitmq-server.service
[Service]
User={{ taiga_user }}
Group={{ taiga_user }}
Environment=PYTHONUNBUFFERED=true
Environment=DJANGO_SETTINGS_MODULE=settings.config
WorkingDirectory={{ taiga_root_dir }}/app/back
ExecStart={{ taiga_root_dir }}/venv/bin/gunicorn --workers 4 --timeout 60 --log-level=info --access-logfile - --bind 127.0.0.1:{{ taiga_ports['back'] }} taiga.wsgi
PrivateTmp=yes
PrivateDevices=yes
ProtectSystem=full
ProtectHome=yes
NoNewPrivileges=yes
MemoryLimit=1024M
SyslogIdentifier=taiga-back
Restart=on-failure
StartLimitInterval=0
RestartSec=30
[Install]
WantedBy=multi-user.target

View File

@ -0,0 +1,23 @@
[Unit]
Description=Taiga events
After=network.target rabbitmq-server.service
[Service]
User={{ taiga_user }}
Group={{ taiga_user }}
WorkingDirectory={{ taiga_root_dir }}/app/events
ExecStart=/bin/npm run start:production
PrivateTmp=yes
PrivateDevices=yes
ProtectSystem=full
ProtectHome=yes
NoNewPrivileges=yes
MemoryLimit=512M
SyslogIdentifier=taiga-events
Restart=on-failure
StartLimitInterval=0
RestartSec=30
[Install]
WantedBy=multi-user.target

View File

@ -0,0 +1,23 @@
[Unit]
Description=Taiga protected
After=network.target rabbitmq-server.service
[Service]
User={{ taiga_user }}
Group={{ taiga_user }}
Environment=PYTHONUNBUFFERED=true
WorkingDirectory={{ taiga_root_dir }}/app/protected
ExecStart={{ taiga_root_dir }}/venv/bin/gunicorn --workers 4 --timeout 60 --log-level=info --access-logfile - --bind 127.0.0.1:{{ taiga_ports['protected'] }} server:app
PrivateTmp=yes
PrivateDevices=yes
ProtectSystem=full
ProtectHome=yes
NoNewPrivileges=yes
MemoryLimit=512M
SyslogIdentifier=taiga-protected
Restart=on-failure
StartLimitInterval=0
RestartSec=30
[Install]
WantedBy=multi-user.target

View File

@ -0,0 +1,31 @@
---
taiga_packages:
- git
- tar
- zstd
- python39-pip
- python39-devel
- python39-wheel
- autoconf
- flex
- bison
- libjpeg-turbo-devel
- freetype-devel
- zlib-devel
- cppzmq-devel
- gdbm-devel
- ncurses-devel
- automake
- libtool
- curl
- tmux
- gettext
- postgresql14
- postgresql-devel
- libpq-devel
- libxml2-devel
- libxslt-devel
- openssl-devel
- libffi-devel
- policycoreutils