Faveo Helpdesk K8s

Deploying Faveo Helpdesk on managed Kubernetes Cluster

drawing

Introduction

In this article, we’ll be deploying Faveo Helpdesk app on top of Kubernetes. But first, you may be wondering why we’re using Kubernetes and Docker for the deployment of our Faveo Helpdesk application. Kubernetes allows us to derive maximum utility from containers and build cloud-native applications that can run anywhere, independent of cloud-specific requirements. With Kubernetes, we can automatically deploy, scale, and manage our application. We will go through the steps one by one required in deploying Faveo Helpdesk app.

Prerequisites

  • A Managed Kubernetes 1.28+ cluster with your connection configuration set as the kubectl default on the local machine from which you access the cluster. You can read more about installing kubectl in the official documentation.
  • The Helm 3 package manager installed on your local machine. You can follow the official guide here to install Helm 3.
  • A Managed Mysql 8.0+ or MariaDB 10.6+ database in the same region as of the Cluster.
  • A Managed Redis database in the same region as of the Cluster.
  • Spaces bucket in the same region. (We recommend to have all this requirements in the same region as of the cluster for better performance and good connectivity among them)
  • A fully registered domain name with an available A record.You can use the domain registrar of your choice. Don’t worry about associating your domain’s A record with an IP at this time. Once you deploy Nginx ingress controller and your Load balancer is attached to your cluster, you will connect your_domain to the proper IP.

Before beginning the installation take a look at the simplified Architectural Diagram of Faveo Helpdesk on kubernetes. This will help you understand the different components used and how they are inter connected to make Faveo Helpdesk work.

Note: Digital Ocean allows you to install some of the resources or addons via one-click installers. But we recommend to follow the steps in this guide, which uses the Offcial documentaion of that addons to install them, as you will have complete control over there versions.

Step 1: Configuring and Deploying Faveo Helpdesk

In this step, you’ll create a Kubernetes object description file, also known as a manifest, for a deployment. This manifest will contain all of the configuration details needed to deploy your Faveo app to your cluster.

First, you’ll need a directory to store all your YAML configuration files. Create a new directory of your choice and create and open deploy-faveo.yaml. Add the below configurations, making sure to replace order-no and license-key with your order number and license in the CURL Api. Leave the commented lines as it is. The reason for commenting certain lines here will be explained later in Step 6.

apiVersion: v1
kind: Service
metadata:
  name: faveo-svc
  namespace: faveo
spec:
  type: ClusterIP
  ports:
  - port: 80
    targetPort: 80
  selector:
    app: faveo-pods
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: faveo-deploy
  namespace: faveo
spec:
  replicas: 1
  selector:
    matchLabels:
      app: faveo-pods
  template:
    metadata:
      labels:
        app: faveo-pods
    spec:
      containers:
      - name: faveo-apache
        image: ladybird/faveo-k8s:apache-8.2.25
        resources:
          limits:
            memory: 700Mi
            cpu: 1
          requests:
            memory: 600Mi
            cpu: 800m
        livenessProbe:
          httpGet:
            path: /probe.php
            port: 80
          initialDelaySeconds: 5
          timeoutSeconds: 5
          periodSeconds: 10
          failureThreshold: 1
        readinessProbe:
          httpGet:
            path: /probe.php
            port: 80
          initialDelaySeconds: 5
          timeoutSeconds: 5
          periodSeconds: 10
          failureThreshold: 1
        volumeMounts:
        - name: volume-data
          mountPath: /var/www/html
#        - name: cm
#          mountPath: /var/www/html/.env
#          subPath: .env
#        - name: ca-certificates
#          mountPath: /usr/local/share/ca-certificates/faveorootCA.crt
#          subPath: faveorootCA.crt
      initContainers:
      - name: fetch
        image: ladybird/faveo-k8s:fetcher-v9.2.2
        command: ['sh','-c','apt update;apt install git -y; curl https://billing.faveohelpdesk.com/download/faveo\?order_number\=order-no\&serial_key\=license-key --output faveo.zip; unzip faveo.zip -d html;chown -R www-data:www-data /html']
        volumeMounts:
        - name: volume-data
          mountPath: /html
      volumes:
      - name: volume-data
        emptyDir: {}
#      - name: cm-
#        configMap:
#          name: faveo-env
#      - name: ca-certificates
#        configMap:
#          name: faveo-ca-certificates

Save and close the file.

Create a namespace for faveo

kubectl create ns faveo 

Set the Current Context

kubectl config set-context --current --namespace=faveo

Next, apply your new deployment with the following command:

kubectl apply -f deploy-faveo.yaml

This will create a service and deployment for Faveo helpdesk pods.You can confirm by executing below commands.

kubectl get pods
kubectl get svc

Now that we have the Faveo app running but it is still not accessible externally. For this we need to route the external traffic to faveo-svc service which we created by applying deploy-faveo.yaml to the cluster.

You’ve created deployment of the Faveo helpdesk app with accompanying Service.In the next step, you’ll install the Nginx Ingress Controller which will enable external traffic to route to appropriate backed service.

Step 2: Configuring Nginx Ingress Controller

The Nginx Ingress Controller consists of a Pod and a Service. The Pod runs the Controller, which constantly polls the /ingresses endpoint on the API server of your cluster for updates to available Ingress Resources. The Service is of type LoadBalancer, the cluster will automatically create a Load Balancer on your cloud provider, through which all external traffic will flow to the Controller. The Controller will then route the traffic to appropriate Services, as defined in Ingress Resources.

Only the LoadBalancer Service knows the IP address of the automatically created Load Balancer. To install the Nginx Ingress Controller to your cluster, you’ll first need to add its repository to Helm by running:

helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx

Update your local Helm chart repository cache:

helm repo update

Create a namespace for Ingress Nginx:

kubectl create ns ingress-nginx

Finally, run the following command to install the Nginx ingress:

helm install ingress-nginx ingress-nginx/ingress-nginx --namespace=ingress-nginx

The above command installs the Nginx Ingress Controller from the stable charts repository and deploys a LoadBalancer. You can watch the LoadBalancer become availble by running.

kubectl --namespace ingress-nginx get services -o wide -w ingress-nginx-controller

At this point once the External IP is availble copy that and set the A record for your domain in your registrar.

You’ve installed the Nginx Ingress maintained by the Kubernetes community. It will route HTTP and HTTPS traffic from the Load Balancer to appropriate back-end Services, configured in Ingress Resources. In the next step, you’ll expose the Faveo Helpdesk app deployments using an Ingress Resource.

Step 3: Securing the Ingress Using SSL

Secure Sockets Layer (SSL) is a standard security technology that creates an encrypted connection between a server and a client. SSL is essential for protecting data transmitted over networks, especially for applications like Faveo, which require HTTPS to function correctly with the latest versions.

Step 4: Faveo Helpdesk Web UI installtion

At this point if the domain name is propagated properly with your server’s IP you can open Faveo in browser just by entering your domainname. You can also check the Propagation update by Visiting this site www.whatsmydns.net.

Now you can install Faveo via GUI Wizard

Step 5: Creating and Configuring ConfigMap for .env

After completing Step 4 you have generated .env file under the faveo root directory. Faveo Helpdesk is laravel based Web Application which solely relies on .env file for functionality. The .env file stores all the sensitive information such as Database credentials, Redis, S3 etc which is later used by the code base.

If you take a look at deploy-faveo.yaml which you created in Step 1, the replicas and part of volume definitions will be commented out. So creating that deploy-faveo.yaml manifest will result in creating only one pod which contains the Faveo code base where we generated the .env file after completing the Step 5.

ConfigMaps allow us to keep configurations separate from application images. Such separation is useful when other alternatives are not a good fit. ConfigMap takes a configuration from a source and mounts it into running containers as a volume. This was we can achieve the configuration of the .env file to be shared across multiple pods and nodes. We are literally achieving persistent volume.

After injecting configmap as volume, we can achieve multiple replicas of pods, auto scalling of pods.

First let’s retrive the content of .env by getting inside the running container. Execute the below command to get the pod name.

kubectl get pod

Copy and replace the pod name from the previous output

kubectl exec -ti your_pod_name -- bash

This is will give you access to the bash shell inside the container. Use cat or nano to get the content of the .env file.

cat .env

or

nano .env

Copy those values and save it somewhere on you machine to be used later.

Now, create a file named configmap.yaml. Add the following lines and place all the content of .env you copied previously under “.env

We need to add the details of redis cluster, space keys like the below.

apiVersion: v1
kind: ConfigMap
metadata:
  name: faveo-env
  namespace: faveo
data:
  .env: |
#    ---- Replace your content here ----
    APP_NAME=Faveo:xxxxxxxxxxxxxxxxxxxxxxxx
    APP_DEBUG=false
    APP_BUGSNAG=true
    APP_URL=https://your_domain_name
    APP_KEY=base64:xxxxxxxxxxxxxxxxxxxxxxxx
    DB_TYPE=mysql
    DB_WRITE_HOST=
    DB_READ_HOST=
    DB_HOST="xxxxxxxxxxxxxxxxxxxxxxxx"
    DB_PORT="xxxxx"
    DB_DATABASE="xxxxx"
    DB_USERNAME="xxxxx"
    DB_PASSWORD="xxxxxxxxxxxxxxxxxxxxxxxx"
    DB_ENGINE=InnoDB
    MAIL_MAILER=smtp
    MAIL_HOST=mailtrap.io
    MAIL_PORT=2525
    MAIL_USERNAME=null
    MAIL_PASSWORD=null
    CACHE_DRIVER=file
    SESSION_DRIVER=file
    SESSION_COOKIE_NAME=faveo_3557
    QUEUE_DRIVER=sync
    FCM_SERVER_KEY=xxxxxxxxxxxxxxxxxxxxxxxx
    FCM_SENDER_ID=xxxxxxxxxxxxxxxxxxxxxxxx
    PROBE_PASS_PHRASE=xxxxxxxxxxxxxxxxxxxxxxxx
    REDIS_DATABASE=0
    BROADCAST_DRIVER=pusher
    LARAVEL_WEBSOCKETS_ENABLED=false
    LARAVEL_WEBSOCKETS_PORT=6001
    LARAVEL_WEBSOCKETS_HOST=127.0.0.1
    LARAVEL_WEBSOCKETS_SCHEME=http
    PUSHER_APP_ID=xxxxxxxxxxxxxxxxxxxxxxxx
    PUSHER_APP_KEY=xxxxxxxxxxxxxxxxxxxxxxxx
    PUSHER_APP_SECRET=xxxxxxxxxxxxxxxxxxxxxxxx
    PUSHER_APP_CLUSTER=mt1
    MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
    MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"
    SOCKET_CLIENT_SSL_ENFORCEMENT=false
    LARAVEL_WEBSOCKETS_SSL_LOCAL_CERT=null
    LARAVEL_WEBSOCKETS_SSL_LOCAL_PK=null
    LARAVEL_WEBSOCKETS_SSL_PASSPHRASE=null
    DB_SSL_KEY=
    DB_SSL_CERT=
    DB_SSL_CA=
    DB_SSL_VERIFY_PEER_CERT=false
    SCOUT_DRIVER=database
    MEILISEARCH_HOST=
    MEILISEARCH_KEY=
    ALGOLIA_APP_ID=
    ALGOLIA_SECRET=
    DB_INSTALL=1
    APP_ENV=production
    JWT_SECRET=xxxxxxxxxxxxxxxxxxxxxxxx
#   ---- Add the details of redis cluster, space ----
    AWS_SECRET_ACCESS_KEY=xxxxxxxxxxxxxxxxxxxxxxxx
    AWS_ACCESS_KEY_ID=xxxxxxxxxxxxxxxxxxxxxxxx
    AWS_DEFAULT_REGION=us-east-1
    AWS_BUCKET=xxxxxxxxxxxxxxxxxxxxxxxx
    AWS_ENDPOINT=xxxxxxxxxxxxxxxxxxxxxxxx
    FILESYSTEM_DISK=s3
    REDIS_HOST=xxxxxxxxxxxxxxxxxxxxxxxx
    REDIS_PORT= xxxxx
    REDIS_PASSWORD=xxxxxxxxxxxxxxxxxxxxxxxx
    REDIS_SCHEME=tls

Make sure you replaced all the content of your .env under the “.env |”. Roll it out with kubectl:

kubectl apply -f configmap.yaml

Verfify its running:

kubectl get cm

Now, Let’s modify the deployment to mount configmap inside and also lets increase the number of replicas.

Open deploy-faveo.yaml and uncomment all the faveo-env commented lines. It should now look like this.

---
        - name: cm
          mountPath: /var/www/html/.env
          subPath: .env

---
      - name: cm
        configMap:
          name: faveo-env

Save and close the file. Lets inject this updated definition to kube api:

kubectl apply -f deploy-faveo.yaml

Now the single pod which was running before will be terminating and new 3 pods will be created with updated definition. You can give your desired number of replicas. You can also use Horizontal Pod scaling along with metrics server for autoscaling and descaling. Verify the new pods running by executing the below command:

kubectl get pods

Now that you have created a configmap out of .env and configured it in the deployment which will mount the .env inside all the pods that it creates. The configmap not only will be used by faveo deployment pods but aslo by the supervisor deployment which you will create in next step.

Step 6: Configuring and Deploying Supervisor

Faveo Helpdesk requires certain set of command to be executed to have the Emails sending/receiving, reports generating and recurring. To achieve this we will be spinng a supervisor pod with .env mounted inside it via configmap, which then does the job or us.

Create and open file supervisor.yaml and copy the following lines inside it. Make sure to replace order-no and license-key with your order number and license in the CURL Api.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: supervior-deploy
  namespace: faveo
spec:
  replicas: 1
  selector:
    matchLabels:
      app: supervisor-pods
  template:
    metadata:
      labels:
        app: supervisor-pods
    spec:
      containers:
      - name: faveo-supervisor
        image: ladybird/faveo-k8s:supervisor-8.2.25
        resources:
          limits:
            memory: 1024Mi
            cpu: 1
          requests:
            memory: 900Mi
            cpu: 900m
        volumeMounts:
        - name: volume-data
          mountPath: /var/www/html
        - name: cm
          mountPath: /var/www/html/.env
          subPath: .env
      initContainers:
      - name: fetch
        image: ladybird/fetcher-v9.2.2
       command: ['sh','-c','apt update;apt install git -y; curl https://billing.faveohelpdesk.com/download/faveo\?order_number\=order-no\&serial_key\=license-key --output faveo.zip; unzip faveo.zip -d html;chown -R www-data:www-data /html']
        volumeMounts:
        - name: volume-data
          mountPath: /html
      volumes:
      - name: volume-data
        emptyDir: {}
      - name: cm
        configMap:
          name: faveo-env

Save and close the file.

Next, apply your new deployment with the following command:

kubetctl apply -f supervisor.yaml

This will create a supervisor deployment .You can confirm by executing below commands.

kubectl get pods

Now you should see supervisor pod running along with Faveo Helpdesk pods.

The supervisor pod will use the configuration from .env which is mounted via configmap to perform all the operations.

Updated: