Kubernetes Nginx ingress setup for Strapi with x-forwarded headers

If you’re using Strapi and you’re trying to figure out how to setup Nginx Ingress for Kubernetes or you are trying to solve one of the following issues:

Here’s the ingress configuration, and your nginx ingress helm chart value you should be editing:

#1 Provide use-forwarded-headers in your helm chart’s controller config params

# values.yaml
    use-forwarded-headers: "true"

#2 My ingress config

apiVersion: extensions/v1beta1
kind: Ingress
    nginx.ingress.kubernetes.io/use-regex: "true"
    nginx.ingress.kubernetes.io/proxy-body-size: 200m
    nginx.ingress.kubernetes.io/enable-cors: "true"
    nginx.ingress.kubernetes.io/cors-allow-origin: "*"
    nginx.ingress.kubernetes.io/cors-allow-headers: "*"
    nginx.ingress.kubernetes.io/cors-allow-credentials: "true"
    nginx.ingress.kubernetes.io/cors-allow-methods: "*"
    nginx.ingress.kubernetes.io/proxy-connect-timeout: "30s"
    nginx.ingress.kubernetes.io/proxy-read-timeout: "20s"
    nginx.ingress.kubernetes.io/client-body-buffer-size: "50m"
    kubernetes.io/ingress.class: nginx
  name: strapi-ingress
  - host: mydomain.com
      - path: /
          serviceName: angular-ui
          servicePort: 80
      # Depends on the plugins you use
      - path: /(admin|plugins|email|settings-manager|documentation|content-type-builder|upload|users-permissions|users|content-manager|auth)/?.*$
          serviceName: strapi
          servicePort: 1337

#3 Custom nginx ingress installation

You might want to create a custom configmap to us within your nginx ingress installation like the following:

apiVersion: v1
  use-forwarded-headers: "true"
kind: ConfigMap
  name: nginx-configuration

#4 Digital Ocean k8s

or if you are running your k8s in Digital Ocean you need to add few more config params, but I’d suggest you read this full blog post:


#5 Nginx map directive

If you are simply using Nginx as a load balancer, you might want to setup the map directive outside your server block like the solution provided in this comment: https://github.com/strapi/strapi/issues/2424#issuecomment-445964719

CircleCI notifications in RocketChat

There is no official CircleCI integration for RocketChat, therefore this has to be done a little manually.

Below is an example of how I use it.


version: 2
      - image: debian:stretch
        - checkout
        - run: 
            command: apt-get update && apt-get install -y curl
        - run:
            name: Greeting from hello
            command: echo "Hello, world from hello."
        - run:
            name: Notifiation Failed
            command: bash .circleci/notify "failed"
            when: on_fail
        - run:
            name: Notification Sucess
            command: bash ./circleci/notify "success"
            when: on_success
  version: 2
      - build-development
                - develop

Note that on_fail will only execute if one of the above will fail, same with on_success, it only executes if all of the above are successful.


set -euo pipefail

cat <<EOM
    "status": "$1",
    "job": "$CIRCLE_JOB",
    "build_num": "$CIRCLE_BUILD_NUM",
    "project_reponame": "$CIRCLE_PROJECT_REPONAME",
    "branch": "$CIRCLE_BRANCH",
    "build_url": "$CIRCLE_BUILD_URL",
    "compare_url": "$CIRCLE_COMPARE_URL",
    "sha1": "$CIRCLE_SHA1"

curl -X POST -H 'Content-Type: application/json' --data "$payload" https://YOUR-ROCKETCHAT/hooks/INCOMING-WEBHOOK-INTEGRATION-URL

RocketChat Incoming WebHook Integration

class Script {
  process_incoming_request({ request }) {
    var alertColor = "warning";
    let status = request.content.status;
    let job = request.content.job;
    let build_num = request.content.build_num;
    let project_reponame = request.content.project_reponame;
    let branch = request.content.branch;
    let build_url = request.content.build_url;
    let sha1 = request.content.sha1;
    if (status == "success") {
    	alertColor = "good";
    } else if (status == "failed") {
    	alertColor = "danger";

    let textMessage = (status == "failed" ? "@all\n" : "");
    let title = status == "failed" ? " build failed!" : " was built successfully!"
    textMessage = textMessage + "*Build no*: " + build_num + "\n*Project*: " + project_reponame + "\n*Branch*: " + branch + "\n*Commit*: " + sha1

    return {
    	content: {
	    username: "CircleCI",
            attachments: [{
		text: textMessage,
                color: alertColor,
                title: job + title,
                title_link: build_url

    return {
    	error: {
        	success: false

Upgrade postgresql 9.2 to 9.6 in CentOS 7 (bold steps)

Install postgresql 9.6

wget https://yum.postgresql.org/9.6/redhat/rhel-7.4-x86_64/pgdg-centos96-9.6-3.noarch.rpm
rpm -i pgdg-centos96-9.6-3.noarch.rpm

yum install postgresql96-server postgresql96-contrib
/usr/pgsql-9.6/bin/postgresql96-setup initdb

mv /usr/bin/pg_ctl{,-orig}
echo '#!/bin/bash' > /usr/bin/pg_ctl
echo '"$0"-orig "${@/unix_socket_directory/unix_socket_directories}"' >> /usr/bin/pg_ctl
chmod +x /usr/bin/pg_ctl

Start importing/upgrading data to new server

systemctl stop postgresql
# At this point both servers are stoped

# As Postgres user
su postgres
cd ~
/usr/pgsql-9.6/bin/pg_upgrade -v -b /usr/bin/ -B /usr/pgsql-9.6/bin/ -d /var/lib/pgsql/data/ -D /var/lib/pgsql/9.6/data/

# Back to root user
# Rollback pg_ctl
mv -f /usr/bin/pg_ctl{-orig,}

#### APPLY OLD postgresql config params to postgresql-9.6 (pg_hba.conf, postgresql.conf) (manually), maybe use pgtune for postgresql.conf...


systemctl start postgresql-9.6
systemctl enable postgresql-9.6
systemctl disable postgresql

# temporary
ln -s /usr/pgsql-9.6/bin/psql /usr/bin/psql --force
ln -s /usr/pgsql-9.6/bin/pg_dump /usr/bin/pg_dump --force

# Postgres user
su postgres
cd ~

# back as root
# remove old postgresql
yum remove postgresql

# Export new path
echo 'export PATH=$PATH:/usr/pgsql-9.6/bin' >> /etc/bashrc

exit, SSH back to host and check if new path is ok for postgres commands

Finally decide if you want to remove the old postgres cluster (data folder)

MemcacheD php client for development purpose on Laravel 5

This class simulates the real Memcached PHP extension (which doesn’t exit) on windows (php_memcached.dll) – Note the “d”.
I forked and modified this repository so that it works with few basic methods of laravel 5… Please don’t use this class in production, use it only for development purposes.

Github repo: https://github.com/altinukshini/memcached-client

Configuration in Windows machine

Before you do anything else, make sure you have Memcached server installed. Here’s a blog that shows how to do that (follow step A): https://commaster.net/content/installing-memcached-windows

Assuming you have Memcached server installed, proceed with the following.

Place memcached.php file in C:\xampp\php\pear folder

In your laravel 5 installation, edit AppServiceProvider.php and place the code below inside the boot() method.

if (!class_exists('Memcached')) {
    include ("memcached.php");

so it should look something like:

public function boot(Kernel $kernel)
    if (!class_exists('Memcached')) {
        include ("memcached.php");

…you should be good to go!

Building Hackerspace CRM

Hackerspace CRM (Community Relationship Management) is a web application built with Laravel that helps communities around the world to run and manage their Hackerspaces/Makerspaces.
Github: https://github.com/altinukshini/hackerspacecrm

My friends and I run Prishtina Hackerspace (a hackerspace in Kosovo), and since the beginning of it we always struggled finding the best solution to manage members, payments, keys, etc. I’m not trying to reinvent the wheel, we tried many different applications but I think we need a better solutions for this. I think that many hackerspaces face the same problem when dealing with 30+ members. I know all hackerspaces have different structures, but we could maybe boil down to something common and useful for all of us.

There are many open source CRM software out there like CiviCRM and such (paid ones as well) that actually do have more functionality in them but are hard to use because of their complexity.

Hackerspace CRM tends to be more user friendly and come to use only to Hackerspaces. The idea is to have most of the application parameters configurable via the administrator panel. The application should be modular so that other hackerspaces around the world can write their own specific functionalities. Anyone can write a theme for it or even localize the CRM for use in their own language.


So far, I’ve thought of couple of features, most of which I liked in Seltzer CRM, and some that I thought might be useful based on my experience with Prishtina Hackerspace and some local hackerspaces in Balkans. But, in order for this CRM to be as good as it can (and obviously better than the existing solutions), I need your help to let me know what do you struggle with, and what would you need to have in such application? How do you process this kind of stuff, what services you use and what would be the easiest way to complete your hackerspace administrative tasks via this CRM. Continue reading “Building Hackerspace CRM”

Restrict RoundCube login username to one domain

Roundcube is a client software to access IMAP mailboxes. If you already came to this post, then I’m sure you’ve figured out that RoundCube does not restrict domains in the login form, which means that as long as your username and password are OK, you can basically use any domain you like in your username field. Exc: @gmail.com, @yahoo.com etc.

This is not something that Roundcube deals with, because it should be taken care of on your IMAP server configuration, and if the IMAP server does not check for your full username (domain included), and allows access with any other domain, you get access :). However, even if it’s taken care of on your IMAP server, handling this in RoundCube will prevent an unnecessary request to your IMAP server.

One of the configuration options in Roundcube helps you append the domain to a clean username login.
Exc: if in your username field you type only the username “username” without the “@domain.com” then roundcube can help  you by appending the “@domain.com”. This is helpful only for IMAP servers that require full e-mail addresses for login. You can specify this by editing $rcmail_config[‘username_domain’] variable in config/defaults.inc.php

By default that variable is blank as below:

$config['username_domain'] = '';

Above that variable, you’ll find a short description on what options can be set to this variable, one of which you might assume it is:

%d - domain (http hostname $_SERVER['HTTP_HOST'] without the first part)

But in cases when your roundcube installation is in a different host/domain server than your original domain that is needed to authenticate in your IMAP server, that will not help, therefore use your domain as follows:

$config['username_domain'] = 'yourdomain.com';

Now if you type “username” (without the domain) in the username field, roundcube will append “@yourdomain.com” and the request to your IMAP server will have your username sent as “username@yourdomain.com”, otherwise if you already specify the domain in your username field, it will make the login request with the specified domain which in this case can be anything (@gmail.com, @yahoo.com etc). Continue reading “Restrict RoundCube login username to one domain”