Table of Contents
How to Install Taiga on Ubuntu 16.04
Standard Server Initialization
Add a standard user for installing packages and for ssh login. Later the taiga user will be added.
$ sudo adduser lain
Add user to the sudo group
$ sudo usermod -aG sudo lain
Update repositories and upgrade packages
$ sudo apt update;apt upgrade
Reboot to ensure any kernel changes are fully installed
$ sudo reboot
Prerequisites
Taiga consists of three modules and each of them require different packages and third-party packages. This sections collects the required packages for a successful Taiga installation and configuration. In this section we will install all dependencies for all modules, including the optional modules and services. Essential packages:
$ sudo apt-get update $ sudo apt-get install -y build-essential binutils-doc autoconf flex bison libjpeg-dev $ sudo apt-get install -y libfreetype6-dev zlib1g-dev libzmq3-dev libgdbm-dev libncurses5-dev $ sudo apt-get install -y automake libtool libffi-dev curl git tmux gettext $ sudo apt-get install -y nginx $ sudo apt-get install -y rabbitmq-server redis-server $ sudo apt-get install -y circus
The component taiga-back uses postgresql (>= 9.4) as database:
$ sudo apt-get install -y postgresql-9.5 postgresql-contrib-9.5 $ sudo apt-get install -y postgresql-doc-9.5 postgresql-server-dev-9.5
Python (3.5) and virtualenvwrapper must be installed along with a few third-party libraries:
$ sudo apt-get install -y python3 python3-pip python-dev python3-dev python-pip virtualenvwrapper $ sudo apt-get install -y libxml2-dev libxslt-dev $ sudo apt-get install -y libssl-dev libffi-dev
virtualenvwrapper helps keeping the system clean of third party libraries, installed with the language package manager by installing these packages in an isolated virtual environment.
Restart the shell or run bash to reload the bash environment with the new virtualenvwrapper variables and functions.
This step is mandatory before continuing the installation! Create a user named taiga, and give it root permissions
$ sudo adduser taiga $ sudo adduser taiga sudo $ sudo su taiga $ cd ~
Do not change to root user. The installation must be done with the taiga user.
Configuring Dependencies
Configure postgresql with the initial user and database:
$ sudo -u postgres createuser taiga $ sudo -u postgres createdb taiga -O taiga --encoding='utf-8' --locale=en_US.utf8 --template=template0
Generate an alpha numeric password for PASSWORD_FOR_EVENTS. I had an issue with creating a password with symbols, if you do, you can place the password in single or double quotations, and this MAY work. I created an alphanumeric password so there was no issue when submitting the command. Create a user named taiga, and a virtualhost for RabbitMQ (taiga-events)
$ sudo rabbitmqctl add_user taiga PASSWORD_FOR_EVENTS $ sudo rabbitmqctl add_vhost taiga $ sudo rabbitmqctl set_permissions -p taiga taiga ".*" ".*" ".*"
Create the logs folder (mandatory)
$ mkdir -p ~/logs
Backend configuration
This section helps configuring the backend (api) Taiga service and its dependencies. Download the code
$ cd ~ $ git clone https://github.com/taigaio/taiga-back.git taiga-back $ cd taiga-back $ git checkout stable
Create new virtualenv named taiga
$ mkvirtualenv -p /usr/bin/python3.5 taiga
Install dependencies
$ pip install -r requirements.txt
Populate the database with initial basic data
$ python manage.py migrate --noinput $ python manage.py loaddata initial_user $ python manage.py loaddata initial_project_templates $ python manage.py compilemessages $ python manage.py collectstatic --noinput
This creates the administrator account. The login credentials are admin with password 123123.
To finish the setup of taiga-back, create the intial configuration file for proper static/media file resolution, optionally with email sending support:
Copy-paste the following config into ~/taiga-back/settings/local.py and update it with your own details (FQDN, theveryultratopsecretkey, PASSWORD_FOR_EVENTS):
from .common import * MEDIA_URL = "https://example.com/media/" STATIC_URL = "https://example.com/static/" SITES["front"]["scheme"] = "https" SITES["front"]["domain"] = "example.com" SECRET_KEY = "theveryultratopsecretkey" 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:PASSWORD_FOR_EVENTS@localhost:5672/taiga"} # Uncomment and populate with proper connection parameters # for enable email sending. EMAIL_HOST_USER should end by @domain.tld #EMAIL_BACKEND = "django.core.mail.backends.smtp.EmailBackend" #EMAIL_USE_TLS = False #EMAIL_HOST = "localhost" #EMAIL_HOST_USER = "" #EMAIL_HOST_PASSWORD = "" #EMAIL_PORT = 25 # Uncomment and populate with proper connection parameters # for enable github login/singin. #GITHUB_API_CLIENT_ID = "yourgithubclientid" #GITHUB_API_CLIENT_SECRET = "yourgithubclientsecret"
Frontend installation
Download the code from Github: Download the code
$ cd ~ $ git clone https://github.com/taigaio/taiga-front-dist.git taiga-front-dist $ cd taiga-front-dist $ git checkout stable
Copy the example config file:
$ cp ~/taiga-front-dist/dist/conf.example.json ~/taiga-front-dist/dist/conf.json
Edit the example configuration following the pattern below (replace with your own details):
{ "api": "https://example.com/api/v1/", "eventsUrl": "wss://example.com/events", "debug": "true", "publicRegisterEnabled": true, "feedbackEnabled": true, "privacyPolicyUrl": null, "termsOfServiceUrl": null, "GDPRUrl": null, "maxUploadFileSize": null, "contribPlugins": [] }
Be careful using copy-paste from browser to avoidhttpduplication.
Having taiga-front-dist downloaded and configured is insufficient. The next step is to expose the code (in dist directory) under a static file web server. In this tutorial We use nginx as a static file web server and reverse-proxy. The configuration of nginx is explained later.
Events installation
This step is optional and can be skipped
Taiga-events is the Taiga websocket server, it allows taiga-front to show realtime changes in the backlog, taskboard, kanban and issues listing. Taiga-events use rabbitmq (the message broker).
Download taiga-events from Github and install its dependencies: Download the code
$ cd ~ $ git clone https://github.com/taigaio/taiga-events.git taiga-events $ cd taiga-events
Install nodejs
$ curl -sL https://deb.nodesource.com/setup_6.x | sudo -E bash - $ sudo apt-get install -y nodejs
Install the javascript dependencies needed
$ npm install $ sudo npm install -g coffee-script
Copy and edit the config.json file. Update with your rabbitmq uri and the secret key.
$ cp config.example.json config.json
Your config.json should be like:
{ "url": "amqp://taiga:PASSWORD_FOR_EVENTS@localhost:5672/taiga", "secret": "theveryultratopsecretkey", "webSocketServer": { "port": 8888 } }
The 'secret' in config.json must be the same as the “SECRET_KEY” in ~/taiga-back/settings/local.py
Add taiga-events to circus configuration.
Copy-paste the code below into /etc/circus/conf.d/taiga-events.ini
[watcher:taiga-events] working_dir = /home/taiga/taiga-events cmd = /usr/bin/coffee args = index.coffee uid = taiga numprocesses = 1 autostart = true send_hup = true stdout_stream.class = FileStream stdout_stream.filename = /home/taiga/logs/taigaevents.stdout.log stdout_stream.max_bytes = 10485760 stdout_stream.backup_count = 12 stderr_stream.class = FileStream stderr_stream.filename = /home/taiga/logs/taigaevents.stderr.log stderr_stream.max_bytes = 10485760 stderr_stream.backup_count = 12
Reload the circusd configurations:
$ sudo service circusd restart $ sudo service circusd status
Start and Expose Taiga
Before moving further, make sure you installed taiga-back and taiga-front-dist, however, having installed them is insufficient to run Taiga.
taiga-back should run under an application server, which in turn, should be executed and monitored by a process manager. For this task we will use gunicorn and circus respectively.
Both taiga-front-dist and taiga-back must be exposed to the outside using a proxy/static-file web server. For this purpose, Taiga uses nginx.
Circus and gunicorn
Circus is a process manager written by Mozilla and Taiga uses it to execute gunicorn. Circus is not only for executing processes, but it also has utils for monitoring them, collecting logs, and restarting processes if something goes wrong, and also for starting processes on system boot.
Initial Taiga configuration for circus in /etc/circus/conf.d/taiga.ini
[watcher:taiga] working_dir = /home/taiga/taiga-back cmd = gunicorn args = -w 3 -t 60 --pythonpath=. -b 127.0.0.1:8001 taiga.wsgi uid = taiga numprocesses = 1 autostart = true send_hup = true stdout_stream.class = FileStream stdout_stream.filename = /home/taiga/logs/gunicorn.stdout.log stdout_stream.max_bytes = 10485760 stdout_stream.backup_count = 4 stderr_stream.class = FileStream stderr_stream.filename = /home/taiga/logs/gunicorn.stderr.log stderr_stream.max_bytes = 10485760 stderr_stream.backup_count = 4 [env:taiga] PATH = /home/taiga/.virtualenvs/taiga/bin:$PATH TERM=rxvt-256color SHELL=/bin/bash USER=taiga LANG=en_US.UTF-8 HOME=/home/taiga PYTHONPATH=/home/taiga/.virtualenvs/taiga/lib/python3.5/site-packages
Circus stats can generate a high cpu usage without any load you can set statsd in /etc/circus/circusd.conf to false if you don’t need them.
Taiga stores logs on the user home, making them available and immediately accessible when you enter a machine. To make everything work, make sure you have the logs directory created.
Final step is restarting circus:
$ sudo service circusd restart
To verify that the services are running, issue:
$ circusctl status
Nginx
Nginx is used as a static file web server to serve taiga-front-dist and send proxy requests to taiga-back.
Let's Encrypt
For SSL add the EFF's PPA for the Let's Encrypt certbot.
$ sudo add-apt-repository ppa:certbot/certbot $ sudo apt update; sudo apt upgrade $ sudo apt install python-certbot-nginx $ sudo certbot --nginx certonly
Cert and Key locations:
/etc/letsencrypt/live/domain.tld/fullchain.pem
/etc/letsencrypt/live/domain.tld/privkey.pem
By default, a generic DH key is used which weakens the key exchange. Generate a non-generic Diffie-Hellman key with OpenSSL, the line in the Nginx configuration file has already been added in the config below.
$ sudo openssl dhparam -dsaparam -out /etc/ssl/dhparam.pem 4096
Remove the default nginx config file to avoid collision with Taiga:
$ sudo rm /etc/nginx/sites-enabled/default
Nginx config
To create a new nginx virtualhost for Taiga, create and edit the /etc/nginx/conf.d/taiga.conf file, as follows:
Don’t forget to change server_name from “_” to the FQDM!
server {
listen 80 default_server;
server_name _;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl default_server;
server_name _;
large_client_header_buffers 4 32k;
client_max_body_size 50M;
charset utf-8;
index index.html;
# Frontend
location / {
root /home/taiga/taiga-front-dist/dist/;
try_files $uri $uri/ /index.html;
}
# Backend
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:8001/api;
proxy_redirect off;
}
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:8001$request_uri;
proxy_redirect off;
}
# Static files
location /static {
alias /home/taiga/taiga-back/static;
}
# Media files
location /media {
alias /home/taiga/taiga-back/media;
}
add_header Strict-Transport-Security "max-age=63072000; includeSubdomains; preload";
add_header Public-Key-Pins 'pin-sha256="klO23nT2ehFDXCfx3eHTDRESMz3asj1muO+4aIdjiuY="; pin-sha256="633lt352PKRXbOwf4xSEa1M517scpD3l5f79xMD9r9Q="; max-age=2592000; includeSubDomains';
ssl on;
ssl_certificate /etc/nginx/ssl/example.com/ssl-bundle.crt;
ssl_certificate_key /etc/nginx/ssl/example.com/example_com.key;
ssl_session_timeout 5m;
ssl_protocols TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!3DES:!MD5:!PSK';
ssl_session_cache shared:SSL:10m;
ssl_dhparam /etc/ssl/dhparam.pem;
ssl_stapling on;
ssl_stapling_verify on;
# Taiga-events
location /events {
proxy_pass http://127.0.0.1:8888/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;
}
}
Public Key Pinning
Public key pinning increases the security and effectiveness of SSL. If you open the console on a web browser on a site that does not have the correct key in their web server configuration file, it will produce an error. The following command is used to derive the correct key string for PKP to function properly for the site specified.
$ sudo openssl s_client -servername domain.tld -connect domain.tld:443 | openssl x509 -pubkey -noout | openssl pkey -pubin -outform der | openssl dgst -sha256 -binary | openssl enc -base64
This will output some text. Example:
ubin -outform der | openssl dgst -sha256 -binary | openssl enc -base64m:443 | openssl x509 -pubkey -noout | openssl pkey -pu depth=2 C = US, O = DigiCert Inc, OU = www.digicert.com, CN = DigiCert High Assurance EV Root CA verify return:1 depth=1 C = US, O = DigiCert Inc, OU = www.digicert.com, CN = DigiCert SHA2 High Assurance Server CA verify return:1 depth=0 C = US, ST = California, L = Los Angeles, O = Internet Corporation for Assigned Names and Numbers, OU = Technology, CN = www.example.org verify return:1 xmvvalwaPni4IBbhPzFPPMX6JbHlKqua257FmJsWWto=
The last line is a key string that you need to replace in the nginx config at line: add_header Public-Key-Pins 'pin-sha256=”<insert string here>”
Finalization
This documentation differs from the official documentation, where it initially checks that nginx will start without SSL. Instead it leads taiga to coming up with working SSL upon first exposure of nginx to the internet. One last command:
$ sudo reboot
Backups
To backup data from your server you just need to store a copy of the database and attachments files. That is, You just need to make a dump of the database and a copy of taiga-back/media directory.
Create dump:
$ pg_dump taiga > taiga.sql
Copy media to a <dest>:
$ cp -r taiga-back/media <dest>
Then You can restore the backup creating a new database to load the dump and copying the media directory:
$ createdb taiga $ psql taiga < taiga.sql $ cp -r <dest> taiga-back/media
Upgrading
Management
User management on Taiga is not built in, instead you have the option of managing users via the REST API or from the internal django interface. This section only includes the most basic of functions required to manage users.
Django
Django is web framework for python projects. You can edit everything about a project using the Django Admin Interface. This is run manually on localhost port 8000. There are a few things that are required to allow for it to work. You need a user who is admin and superuser, you will have to edit an existing user to give them these credentials. You will also need to start the Django Admin Interface manually in order to access it. The all requires that you have access to a web browser on the server which means you need to run a desktop environment as well.
Change to the proper directory for interacting with django and launch a shell within the django project environment.
$ cd ~/taiga-back $ workon taiga $ python manage.py shell
Copy and paste the following commands one line at a time. If everything works correctly you will get no output from any of the commands.1)
>>> from django.contrib.auth import get_user_model >>> User = get_user_model() >>> user = User.objects.get(username="myname") >>> user.is_admin = True >>> user.is_superuser = True >>> user.save() >>> exit()
Now you can start the Django Admin Interface. The server will run in the current terminal session until you Ctrl-C to stop it.
$ python manage.py runserver
Reset password for any user
$ cd ~/taiga-back $ workon taiga $ python manage.py changepassword <user>
Enable/Disable public signup
Set publicRegisterEnabled to false,
$ vim /home/taiga/taiga-front-dist/dist/conf.json
Set PUBLIC_REGISTER_ENABLED to False
$ vim /home/taiga/taiga-back/settings/local.py
To disable API access, add these lines to the nginx config:
location /api/v1/auth/register {
response 405;
}