Task Management using Kanboard on CentOS 7 - rharmonson/richtech GitHub Wiki

Task Management using Kanboard on CentOS 7


2018-Dec-13: revised firewall scripts to not specify interface, i.e. -i ens32


Kanboard is a Kan-ban. Kan-ban is used to manage tasks for an individual or groups. Kan-bans are commonly found in software development or project management software, e.g. Jira, with a bunch of other crud packaged with it. Kanboard is strictly a Kan-ban but extensible with plugins.

More information about Kanboard can be found at

Purpose

The purpose of this article to is to provide instructions on how to install Kanboard on a single CentOS 7 using it's Software Collection Libray for MariaDB, Nginx, and PHP.

Installation Overview

  • Setup Software Collection Libray
  • Install Packages
  • SELinux
  • Firewall
  • MariaDB Configuration
  • Nginx Configuration
  • FPM Configuration
  • Certificates
  • (opcache <-- to add later)
  • (Secure LDAP <-- to add later)

CPU, RAM, etc.

I am assuming your are using server or container virtualization. For small group individuals, one CPU, one gigabyte of RAM, 10 GB of storage should be fine. However, a larger implementation will require more resources. A good starting point is two CPUs, two gigabytes of RAM, and fifteen or twenty gigabytes of storage. Plenty of head-room for growth. Increase CPU and RAM as necessary, but another option is build a second host or container and separate the database and web server. This will also simplify resource management.

Software Collection Library

Recently, I moved to using CentOS' Software Collection Library or SCL versus a variety of other repositories. Use your preferred repository but make sure you have met Kanboard's requirements as described at https://docs.kanboard.org/en/latest/admin_guide/requirements.html.

sudo yum install -y centos-release-scl

Results

================================================================================
 Package                    Arch        Version               Repository   Size
================================================================================
Installing:
 centos-release-scl         noarch      2-2.el7.centos        extras       12 k
Installing for dependencies:
 centos-release-scl-rh      noarch      2-2.el7.centos        extras       12 k

Transaction Summary
================================================================================
Install  1 Package (+1 Dependent package)

Total download size: 24 k
Installed size: 39 k
Is this ok [y/d/N]:

To ease use of SCL packages and their commands from bash, we need to configure either bash directly for the user or use a shell profile for the entire system. This is done by creating a shell script at /etc/profile.d/.

sudo vi /etc/profile.d/enable-scl.sh

copy+paste

source scl_source enable rh-mariadb102 rh-php71 rh-nginx112

To apply changes, start a new bash session. If you opted to use different versions of packages, revise accordingly.

Install Packages

sudo yum install -y iptables-services wget unzip git rh-mariadb102-server rh-nginx112 rh-php71 rh-php71-php-fpm rh-php71-php-mbstring rh-php71-php-pdo rh-php71-php-gd rh-php71-php-opcache rh-php71-php-mysqlnd rh-php71-php-ldap

Results

================================================================================
 Package                        Arch   Version             Repository      Size
================================================================================
Installing:
 git                            x86_64 1.8.3.1-14.el7_5    updates        4.4 M
 iptables-services              x86_64 1.4.21-24.1.el7_5   updates         51 k
 rh-mariadb102                  x86_64 3.0-5.el7           centos-sclo-rh 7.1 k
 rh-nginx112                    x86_64 1.12-3.el7          centos-sclo-rh 2.5 k
 rh-php71                       x86_64 1-1.el7             centos-sclo-rh 4.1 k
 rh-php71-php-fpm               x86_64 7.1.8-1.el7         centos-sclo-rh 1.4 M
 rh-php71-php-gd                x86_64 7.1.8-1.el7         centos-sclo-rh 147 k
 rh-php71-php-ldap              x86_64 7.1.8-1.el7         centos-sclo-rh  57 k
 rh-php71-php-mbstring          x86_64 7.1.8-1.el7         centos-sclo-rh 521 k
 rh-php71-php-mysqlnd           x86_64 7.1.8-1.el7         centos-sclo-rh 165 k
 rh-php71-php-opcache           x86_64 7.1.8-1.el7         centos-sclo-rh 183 k
 rh-php71-php-pdo               x86_64 7.1.8-1.el7         centos-sclo-rh  98 k
 unzip                          x86_64 6.0-19.el7          base           170 k
 wget                           x86_64 1.14-15.el7_4.1     base           547 k
Installing for dependencies:
 audit-libs-python              x86_64 2.8.1-3.el7_5.1     updates         75 k
 checkpolicy                    x86_64 2.5-6.el7           base           294 k
 fontconfig                     x86_64 2.10.95-11.el7      base           229 k
 fontpackages-filesystem        noarch 1.44-8.el7          base           9.9 k
 gd                             x86_64 2.0.35-26.el7       base           146 k
 libX11                         x86_64 1.6.5-1.el7         base           606 k
 libX11-common                  noarch 1.6.5-1.el7         base           164 k
 libXau                         x86_64 1.0.8-2.1.el7       base            29 k
 libXpm                         x86_64 3.5.12-1.el7        base            55 k
 libcgroup                      x86_64 0.41-15.el7         base            65 k
 libgnome-keyring               x86_64 3.12.0-1.el7        base           109 k
 libjpeg-turbo                  x86_64 1.2.90-5.el7        base           134 k
 libpng                         x86_64 2:1.5.13-7.el7_2    base           213 k
 libsemanage-python             x86_64 2.5-11.el7          base           112 k
 libwebp                        x86_64 0.3.0-7.el7         base           170 k
 libxcb                         x86_64 1.12-1.el7          base           211 k
 libxslt                        x86_64 1.1.28-5.el7        base           242 k
 lsof                           x86_64 4.87-5.el7          base           331 k
 net-tools                      x86_64 2.0-0.22.20131004git.el7
                                                           base           305 k
 perl                           x86_64 4:5.16.3-292.el7    base           8.0 M
 perl-Carp                      noarch 1.26-244.el7        base            19 k
 perl-Compress-Raw-Bzip2        x86_64 2.061-3.el7         base            32 k
 perl-Compress-Raw-Zlib         x86_64 1:2.061-4.el7       base            57 k
 perl-DBD-MySQL                 x86_64 4.023-6.el7         base           140 k
 perl-DBI                       x86_64 1.627-4.el7         base           802 k
 perl-Data-Dumper               x86_64 2.145-3.el7         base            47 k
 perl-Encode                    x86_64 2.51-7.el7          base           1.5 M
 perl-Error                     noarch 1:0.17020-2.el7     base            32 k
 perl-Exporter                  noarch 5.68-3.el7          base            28 k
 perl-File-Path                 noarch 2.09-2.el7          base            26 k
 perl-File-Temp                 noarch 0.23.01-3.el7       base            56 k
 perl-Filter                    x86_64 1.49-3.el7          base            76 k
 perl-Getopt-Long               noarch 2.40-3.el7          base            56 k
 perl-Git                       noarch 1.8.3.1-14.el7_5    updates         54 k
 perl-HTTP-Tiny                 noarch 0.033-3.el7         base            38 k
 perl-IO-Compress               noarch 2.061-2.el7         base           260 k
 perl-Net-Daemon                noarch 0.48-5.el7          base            51 k
 perl-PathTools                 x86_64 3.40-5.el7          base            82 k
 perl-PlRPC                     noarch 0.2020-14.el7       base            36 k
 perl-Pod-Escapes               noarch 1:1.04-292.el7      base            51 k
 perl-Pod-Perldoc               noarch 3.20-4.el7          base            87 k
 perl-Pod-Simple                noarch 1:3.28-4.el7        base           216 k
 perl-Pod-Usage                 noarch 1.63-3.el7          base            27 k
 perl-Scalar-List-Utils         x86_64 1.27-248.el7        base            36 k
 perl-Socket                    x86_64 2.010-4.el7         base            49 k
 perl-Storable                  x86_64 2.45-3.el7          base            77 k
 perl-TermReadKey               x86_64 2.30-20.el7         base            31 k
 perl-Text-ParseWords           noarch 3.29-4.el7          base            14 k
 perl-Time-HiRes                x86_64 4:1.9725-3.el7      base            45 k
 perl-Time-Local                noarch 1.2300-2.el7        base            24 k
 perl-constant                  noarch 1.27-2.el7          base            19 k
 perl-libs                      x86_64 4:5.16.3-292.el7    base           688 k
 perl-macros                    x86_64 4:5.16.3-292.el7    base            43 k
 perl-parent                    noarch 1:0.225-244.el7     base            12 k
 perl-podlators                 noarch 2.5.1-3.el7         base           112 k
 perl-threads                   x86_64 1.87-4.el7          base            49 k
 perl-threads-shared            x86_64 1.43-6.el7          base            39 k
 policycoreutils-python         x86_64 2.5-22.el7          base           454 k
 psmisc                         x86_64 22.20-15.el7        base           141 k
 python-IPy                     noarch 0.75-6.el7          base            32 k
 rh-mariadb102-mariadb          x86_64 1:10.2.8-5.el7      centos-sclo-rh 6.6 M
 rh-mariadb102-mariadb-common   x86_64 1:10.2.8-5.el7      centos-sclo-rh  74 k
 rh-mariadb102-mariadb-config   x86_64 1:10.2.8-5.el7      centos-sclo-rh  28 k
 rh-mariadb102-mariadb-errmsg   x86_64 1:10.2.8-5.el7      centos-sclo-rh 216 k
 rh-mariadb102-mariadb-server   x86_64 1:10.2.8-5.el7      centos-sclo-rh  17 M
 rh-mariadb102-mariadb-server-utils
                                x86_64 1:10.2.8-5.el7      centos-sclo-rh 2.0 M
 rh-mariadb102-runtime          x86_64 3.0-5.el7           centos-sclo-rh 1.2 M
 rh-nginx112-nginx              x86_64 1:1.12.1-2.el7      centos-sclo-rh 515 k
 rh-nginx112-runtime            x86_64 1.12-3.el7          centos-sclo-rh  26 k
 rh-php71-php-cli               x86_64 7.1.8-1.el7         centos-sclo-rh 2.7 M
 rh-php71-php-common            x86_64 7.1.8-1.el7         centos-sclo-rh 648 k
 rh-php71-php-json              x86_64 7.1.8-1.el7         centos-sclo-rh  52 k
 rh-php71-php-pear              noarch 1:1.10.4-1.el7      centos-sclo-rh 356 k
 rh-php71-php-process           x86_64 7.1.8-1.el7         centos-sclo-rh  61 k
 rh-php71-php-xml               x86_64 7.1.8-1.el7         centos-sclo-rh 159 k
 rh-php71-php-zip               x86_64 7.1.8-1.el7         centos-sclo-rh  89 k
 rh-php71-runtime               x86_64 1-1.el7             centos-sclo-rh 1.1 M
 rsync                          x86_64 3.1.2-4.el7         base           403 k
 scl-utils                      x86_64 20130529-18.el7_4   base            24 k
 setools-libs                   x86_64 3.3.8-2.el7         base           619 k
 stix-fonts                     noarch 1.1.0-5.el7         base           1.3 M

Transaction Summary
================================================================================
Install  14 Packages (+81 Dependent packages)

Total download size: 59 M
Installed size: 241 M
Is this ok [y/d/N]:

Base Configuration

SELinux

Advise setting SELinux to permissive during installation and configure SELinux, later, to permit Kanboard operation. SELinux configuration beyond setting to permissive is not in scope of this article.

sed -i 's/=enforcing/=permissive/g' /etc/selinux/config

IPv4 Tables

I do not use firewalld. In fact, I give instructions below on how to remove it and use iptables directly with iptables-services package.

If you use firewalld, review the policies below and apply using firewalld-cmd.

Create an IPv4 script.

vi ~/ip4-kanboard.fw

copy+paste

#!/bin/bash

#Flush current policies
iptables -F

# Set default chain policies
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT

# Allow established sessions to receive traffic
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

# Accept on localhost
iptables -A INPUT -i lo -j ACCEPT

#ICMP Echo (OPTIONAL)
iptables -A INPUT -p icmp --icmp-type echo-request -j ACCEPT
iptables -A INPUT -j REJECT --reject-with icmp-host-prohibited

# Accept incoming SSH
iptables -I INPUT -p tcp -m conntrack --ctstate NEW -m tcp --dport 22 -j ACCEPT
iptables -I INPUT -p tcp -m conntrack --ctstate NEW -m tcp --dport 80 -j ACCEPT
iptables -I INPUT -p tcp -m conntrack --ctstate NEW -m tcp --dport 443 -j ACCEPT

# Save Changes
service iptables save

# Service
systemctl restart iptables
systemctl status iptables

IPv6 Tables

Create an IPv6 script, but note I do not use IPv6 within my network--ignorant app developers do thus the IPv6 loopback. If you need it, revise it to meet your requirements.

vi ~/ip6-kanboard.fw

copy+paste

#!/bin/bash

#Flush current policies
ip6tables -F

# Set default chain policies
ip6tables -P INPUT DROP
ip6tables -P FORWARD DROP
ip6tables -P OUTPUT ACCEPT

# Allow established sessions to receive traffic
ip6tables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

# Accept on localhost
ip6tables -A INPUT -i lo -j ACCEPT
#ip6tables -A OUTPUT -o lo -j ACCEPT

# Save Changes
service ip6tables save

# Service
systemctl restart ip6tables
systemctl status ip6tables

Firewall

Remove firewalld, enable and start iptables-services we installed earlier, execute the firewall scripts, and review the changes. Either su to root or use sudo.

systemctl disable firewalld
systemctl enable iptables
systemctl enable ip6tables
systemctl start iptables
systemctl start iptables
bash < ip4-kb.fw
bash < ip6-kb.fw
service iptables save
service ip6tables save

Using iptables -L and ip6tables -L review the changes then reboot if satisfied with results.

MariaDB

Enable and start mariadb.

sudo systemctl enable rh-mariadb102-mariadb
sudo systemctl start rh-mariadb102-mariadb

Secure mariadb by setting mariadb's root password, 'root_PASSWORDHERE', and responding 'y' to each question.

mysql_secure_installation

Create database and user using mysql command. Arg '-p' prompts for root's password.

$ mysql -uroot -p
MariaDB [(none)]> CREATE DATABASE kanboard CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
MariaDB [(none)]> GRANT ALTER, CREATE, DELETE, DROP, INDEX, INSERT, REFERENCES, SELECT, UPDATE ON kanboard.* TO 'kbuser'@'localhost' IDENTIFIED BY 'kbuser_PASSWORDHERE';
MariaDB [(none)]> FLUSH PRIVILEGES;
MariaDB [(none)]> quit;

Test kbuser's account and password using mysql -ukbuser -p.

nginx

Enable and start nginx.

sudo systemctl enable rh-nginx112-nginx
sudo systemctl start rh-nginx112-nginx

Verify operation by opening an Internet browser and enter the URL http://[ip_address] which should result with Red Hat's default nginx page.

Also, note the default document root and nginx.conf locations.

  • /opt/rh/rh-nginx112/root/usr/share/nginx/html/
  • /etc/opt/rh/rh-nginx112/nginx/nginx.conf

php-fpm

Update php-fpm default settings from apache to nginx.

sudo vi /etc/opt/rh/rh-php71/php-fpm.d/www.conf 

From

; RPM: apache user chosen to provide access to the same directories as httpd
user = apache
; RPM: Keep a group allowed to write in log dir.
group = apache

to

; RPM: apache user chosen to provide access to the same directories as httpd
user = nginx
; RPM: Keep a group allowed to write in log dir.
group = nginx

Enable and start php-fpm.

sudo systemctl enable rh-php71-php-fpm
sudo systemctl start rh-php71-php-fpm

Kanboard

Kanboard is written in PHP and it's code repository is on Github. Download the source code for Kanboard and the stgray theme as follows:

If behind a reverse proxy, use of git -c http.sslVerify=false clone [repository]. This is used when SSL decryption results with the error given below after a SSL check is done.

Peer's certificate issuer has been marked as not trusted by the user.

Clone Kanboard & stgray Theme

The stgray Theme is optional. It may, also, be simpler to not clone stgray until after operation of Kanboard has been established to simplify troubleshooting.

cd /opt/rh/rh-nginx112/root/usr/share/nginx/html/
sudo rm -f *
sudo git -c http.sslVerify=false clone https://github.com/kanboard/kanboard.git .
sudo cp config.default.php config.php
cd plugins
sudo git -c http.sslVerify=false clone https://github.com/rharmonson/kb-themeplus-stgray.git Themeplus
cd /opt/rh/rh-nginx112/root/usr/share/nginx/
sudo chown -R nginx:nginx html

Update /opt/rh/rh-nginx112/root/usr/share/nginx/html/config.php.

sudo vi /opt/rh/rh-nginx112/root/usr/share/nginx/html/config.php

Update

// Database driver: sqlite, mysql or postgres (sqlite by default)
define('DB_DRIVER', 'mysql');

// Mysql/Postgres username
define('DB_USERNAME', 'kbuser');

// Mysql/Postgres password
define('DB_PASSWORD', 'kbuser_PASSWORDHERE');

// Mysql/Postgres hostname
define('DB_HOSTNAME', 'localhost');

// Mysql/Postgres database name
define('DB_NAME', 'kanboard');

URL Rewrite (optional)

To enable pretty URLs update the Kanboard config.php.

define('ENABLE_URL_REWRITE', true);

nginx.conf

Backup or move the default nginx.conf.

sudo cp /etc/opt/rh/rh-nginx112/nginx/nginx.conf /etc/opt/rh/rh-nginx112/nginx/nginx.conf.bak

Create a new nginx.conf

sudo vi /etc/opt/rh/rh-nginx112/nginx/nginx.conf

copy+paste

user nginx;
worker_processes auto;
error_log /var/opt/rh/rh-nginx112/log/nginx/error.log;
pid /var/opt/rh/rh-nginx112/run/nginx/nginx.pid;

# Load dynamic modules. See /opt/rh/rh-nginx112/root/usr/share/doc/README.dynamic.
include /opt/rh/rh-nginx112/root/usr/share/nginx/modules/*.conf;

events {
    worker_connections  1024;
}

http {
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/opt/rh/rh-nginx112/log/nginx/access.log  main;

    sendfile        on;
    tcp_nopush      on;
    tcp_nodelay     on;
    keepalive_timeout  65;
    types_hash_max_size 2048;

    include       /etc/opt/rh/rh-nginx112/nginx/mime.types;
    default_type  application/octet-stream;

    # Load modular configuration files from the /etc/nginx/conf.d directory.
    # See http://nginx.org/en/docs/ngx_core_module.html#include
    # for more information.
    include /etc/opt/rh/rh-nginx112/nginx/conf.d/*.conf;

    server {
        listen       80 default_server;
        listen       [::]:80 default_server;
        server_name  _;
        root         /opt/rh/rh-nginx112/root/usr/share/nginx/html;

        index index.php;

        location / {
            try_files $uri $uri/ /index.php$is_args$args;
        }

		location = /favicon.ico { access_log off; log_not_found off; }
		location = /robots.txt  { access_log off; log_not_found off; }
		
        location ~ \.php$ {
            try_files $uri =404;
            fastcgi_split_path_info ^(.+\.php)(/.+)$;
            fastcgi_pass   127.0.0.1:9000;
            fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
            fastcgi_index index.php;
            include fastcgi_params;
        }

        # Deny access to the directory data
        location ~* /data {
            deny all;
            return 404;
        }

        # Deny access to .htaccess
        location ~ /\.ht {
            deny all;
            return 404;
        }
    }
}

Verify operation by restarting nginx and using an Internet browser to the hosts IP address.

sudo systemctl restart rh-nginx112-nginx

Certificates

The instructions for obtaining certificates will differ based on if you manage your own PKI or if you are purchasing them from a third party. Once obtained, the complete the section below.

nginx

Create a directory for storing certificates.

$ sudo mkdir /etc/opt/rh/rh-nginx112/nginx/ssl

Copy the private key, iskb.key, from your working directory that you created when creating the private key and certificate signing request.

$ sudo cp iskb.key /etc/opt/rh/rh-nginx112/nginx/ssl/

Create a public chain certificate. This is accomplished by using β€œcat” to write the public certificates to a single file. Assuming we have kanboard.crt, subordinate_ca.crt, and root_ca.crt, the process is as follows:

$ sudo cp kanboard.crt /etc/opt/rh/rh-nginx112/nginx/ssl/chain.crt
$ sudo cat subordinate_ca.crt >> /etc/opt/rh/rh-nginx112/nginx/ssl/chain.crt
$ sudo cat root_ca.crt >> /etc/opt/rh/rh-nginx112/nginx/ssl/chain.crt

Using sudo cat /etc/nginx/ssl/chain.crt will show three stanzas beginning with β€œ-----BEGIN CERTIFICATE-----β€œ and ending with β€œ-----END CERTIFICATE-----.”

Set ownership and permissions.

$ sudo chown -R nginx:nginx /etc/opt/rh/rh-nginx112/nginx/ssl
$ sudo chmod -R 1600 /etc/opt/rh/rh-nginx112/nginx/ssl

Update nginx.conf to reflect the following.

user nginx;
worker_processes auto;
error_log /var/opt/rh/rh-nginx112/log/nginx/error.log;
pid /var/opt/rh/rh-nginx112/run/nginx/nginx.pid;

# Load dynamic modules. See /opt/rh/rh-nginx112/root/usr/share/doc/README.dynamic.
include /opt/rh/rh-nginx112/root/usr/share/nginx/modules/*.conf;

events {
    worker_connections  1024;
}

http {
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/opt/rh/rh-nginx112/log/nginx/access.log  main;

    sendfile        on;
    tcp_nopush      on;
    tcp_nodelay     on;
    keepalive_timeout  65;
    types_hash_max_size 2048;

    include       /etc/opt/rh/rh-nginx112/nginx/mime.types;
    default_type  application/octet-stream;

    # Load modular configuration files from the /etc/nginx/conf.d directory.
    # See http://nginx.org/en/docs/ngx_core_module.html#include
    # for more information.
    include /etc/opt/rh/rh-nginx112/nginx/conf.d/*.conf;

	server {
        listen       80;
        listen       [::]:80 default_server;
        server_name  kanboard.yourdomain.com;
        return 301   https://kanboard.yourdomain.com$request_uri;
    }

	
    server {
        listen       443 ssl http2;
        listen       [::]:443 ssl http2;
        server_name  kanboard.yourdomain.com;
        root         /opt/rh/rh-nginx112/root/usr/share/nginx/html;

        index index.php;
		
        ssl    on;
        ssl_certificate    /etc/opt/rh/rh-nginx112/nginx/ssl/iskb-chain.crt;
        ssl_certificate_key    /etc/opt/rh/rh-nginx112/nginx/ssl/iskb.key;
        # Use only TLS
        ssl_protocols TLSv1.1 TLSv1.2;
        # Tell client which ciphers are available
        ssl_prefer_server_ciphers on;
        ssl_ciphers ECDH+AESGCM:ECDH+AES256:ECDH+AES128:DH+3DES:!ADH:!AECDH:!MD5;
        # Enable HSTS
        add_header Strict-Transport-Security "max-age=31536000" always;
        # Optimize session cache
        ssl_session_cache   shared:SSL:40m;
        ssl_session_timeout 4h;
        # Enable session tickets
        ssl_session_tickets on;

        # Remove version number on errors
        server_tokens off;

        location / {
            try_files $uri $uri/ /index.php$is_args$args;
        }

        location ~ \.php$ {
            try_files $uri =404;
            fastcgi_split_path_info ^(.+\.php)(/.+)$;
            #fastcgi_pass unix:/var/run/php5-fpm.sock;
            fastcgi_pass   127.0.0.1:9000;
            fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
            fastcgi_index index.php;
            include fastcgi_params;
        }

        # Deny access to the directory data
        location ~* /data {
            deny all;
            return 404;
        }

        # Deny access to .htaccess
        location ~ /\.ht {
            deny all;
            return 404;
        }
    }
}

Done!?

  • Use opcache to enhance performance
  • Use Secure LDAP with Active Directory