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
- https://kanboard.org/
- https://github.com/kanboard/kanboard
- https://docs.kanboard.org/en/latest/index.html
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