Ruan Bekker's Blog

From a Curious mind to Posts on Github

Python Script to Decrypt Encrypted Data With AWS KMS

Quick script to decrypt data that was encrypted with your KMS key:

The Script:

The script requires the encrypted scring as an argument:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#!/usr/bin/env python

import boto3
import sys
from base64 import b64decode

try:
    encrypted_value = sys.argv[1]
except IndexError:
    print("Usage: {} {}".format(sys.argv[0], 'the-encrypted-string'))
    exit(1)

session = boto3.Session(
        region_name='eu-west-1',
        profile_name='default'
    )

kms = session.client('kms')

response = kms.decrypt(CiphertextBlob=b64decode(encrypted_value))['Plaintext']
print("Decrypted Value: {}".format(response))

Change the permissions so that the file is executable:

1
$ chmod +x decrypt.py

Usage:

1
2
$ ./decrypt.py asdlaskjdasidausd09q3uoijad09ujd38u309
Decrypted Value: thisIsMyDecryptedValue

Setup Kerberos Server and Client on Ubuntu

Kerberos is a authentication protocol that provides a centralized authentication server, that works with the concepts of tickets that are encrypted.

Today we will setup a Kerberos Server (KDC) and setup and Kerberos Enabled Client, and then testing our setup by obtaining a Kerberos Ticket from our server.

Setup the Server:

Install Kerberos KDC and Admin Server:

1
2
3
$ apt update && apt upgrade -y
$ apt install krb5-kdc krb5-admin-server krb5-config -y
$ krb5_newrealm

You will be prompted for realm, and hostnames, in my case I have setup the following:

  • REALM: LAN.RUANBEKER.COM
  • HOST: localhost
  • ADMIN_SERVER: localhost

Then our master password:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
This script should be run on the master KDC/admin server to initialize
a Kerberos realm.  It will ask you to type in a master key password.
This password will be used to generate a key that is stored in
/etc/krb5kdc/stash.  You should try to remember this password, but it
is much more important that it be a strong password than that it be
remembered.  However, if you lose the password and /etc/krb5kdc/stash,
you cannot decrypt your Kerberos database.
Loading random data
Initializing database '/var/lib/krb5kdc/principal' for realm 'LAN.RUANBEKKER.COM',
master key name 'K/M@LAN.RUANBEKKER.COM'
You will be prompted for the database Master Password.
It is important that you NOT FORGET this password.
Enter KDC database master key:
Re-enter KDC database master key to verify:

The output:

1
2
3
4
5
6
7
8
9
10
11
12
Now that your realm is set up you may wish to create an administrative
principal using the addprinc subcommand of the kadmin.local program.
Then, this principal can be added to /etc/krb5kdc/kadm5.acl so that
you can use the kadmin program on other computers.  Kerberos admin
principals usually belong to a single user and end in /admin.  For
example, if jruser is a Kerberos administrator, then in addition to
the normal jruser principal, a jruser/admin principal should be
created.

Don't forget to set up DNS information so your clients can find your
KDC and admin servers.  Doing so is documented in the administration
guide.

Uncomment the last line which contains admin:

1
$ vi /etc/krb5kdc/kadm5.acl

a Kerberos principal is a unique identity to which Kerberos can assign tickets, lets add our first principal, james:

1
2
3
4
5
6
7
8
9
$ kadmin.local
Authenticating as principal root/admin@LAN.RUANBEKKER.COM with password.
kadmin.local:  addprinc james

WARNING: no policy specified for james@LAN.RUANBEKKER.COM; defaulting to no policy
Enter password for principal "james@LAN.RUANBEKKER.COM":
Re-enter password for principal "james@LAN.RUANBEKKER.COM":
Principal "james@LAN.RUANBEKKER.COM" created.
kadmin.local:  exit

Setup the Client:

Setup a Host Entry:

1
$ echo '10.1.1.1 kdc.lan.ruanbekker.com kdc' >> /etc/hosts

Setup Kerberos Client:

1
2
3
4
$ apt install krb5-user -y
- realm
- hostname
- hostname

Obtain a Ticket from the Server:

1
2
3
4
5
6
7
8
9
10
$ kinit -p james
Password for james@LAN.RUANBEKKER.COM:

$ klist
Ticket cache: FILE:/tmp/krb5cc_0
Default principal: james@LAN.RUANBEKKER.COM

Valid starting     Expires            Service principal
10/18/17 22:13:34  10/19/17 08:13:34  krbtgt/LAN.RUANBEKKER.COM@LAN.RUANBEKKER.COM
  renew until 10/19/17 22:13:30

Resources:

Using Python to Build a Dictionary From Data Eg Sports Per Person

I had to achieve a way to provide data in key-value format, where I wanted to see what sports people like, eg: {"ruan": ["rugby", "cricket"]}

The Idea

So my idea was to have the name as the key, and the sports as the value in a list.

Some Catches

So for this post, I will be setting the data statically in the code, while at the time I was working data that was returned via a API.

I am looping through each occurence, adding the name, and when the name exists, I append the sport to the list of the person.

The catch was that, if there was any duplicated data, the person will only exists once in the dictionary that I am building, but the sport will be appended, so if there were 2 occurences of rugby it will show the sport 2 times. So I had to put some logic into the code to handle that.

The Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
"""|Info:

Printing Sports per Person, by looping through data, appending the sports to a list per person, which gets added to our dictionary.

Variables:
 group {dict} -- "the dictionary that we are building up"
 people {list} -- "list of people with their sport choices"
 for sportman in people: {[for-loop]} -- "iterating through our data, if the sport exists, continue, if not, apeend it to the list"
 print(group) {[dict]} -- "printing the results"
"""

group = {}
people = [
  {
      "name": "ruan",
      "sport": "cricket"
  },
  {
      "name": "stefan",
      "sport": "rugby"
  },
  {
      "name": "stefan",
      "sport": "cricket"
  },
  {
      "name": "james",
      "sport": "rugby"
  },
  {
      "name": "james",
      "sport": "golf"
  },
  {
      "name": "stefan",
      "sport": "rugby"
  },
  {
      "name": "james",
      "sport": "hockey"
  }
]

for sportman in people:
    if sportman['name'] in group:
        if sportman['sport'] not in group[sportman['name']]:
            group[sportman['name']].append(sportman['sport'])
        else:
            pass
    else:
        group[sportman['name']] = []
        group[sportman['name']].append(sportman['sport'])

print(group)

Running the Script:

When running the script results in the following:

1
2
$ python sports.py
{'james': ['rugby', 'golf', 'hockey'], 'ruan': ['cricket'], 'stefan': ['rugby', 'cricket']}

Customize Ubuntu 16 Desktop With Arc Dark Theme

So I was running ApricityOS for quite some time, which is a Arch Distibution. But a couple of hours before PyConZa I was trying to do a update and found that their repositories were reporting 404 errors, and turns out they have stopped their project :( . I quite liked ApricityOS, as it’s what you will expect when installing Arch with the basic applications and the numix icon/theme pack.

So I decided to use Ubuntu for a change.

Customizations:

For the Operating System, I am Ubuntu 16:

For my theme I am using Arc Dark:

Moka Icon pack for my Icons:

Terminator for my terminal of choice:

And my config:

~/.config/terminator/config
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
[global_config]
  enabled_plugins = LaunchpadCodeURLHandler, APTURLHandler, LaunchpadBugURLHandler
  sticky = True
  window_state = maximise
[keybindings]
[layouts]
  [[default]]
    [[[child1]]]
      parent = window0
      profile = default
      type = Terminal
    [[[window0]]]
      parent = ""
      type = Window
  [[multi]]
    foreground_color = "#ffffff"
    palette = "#62b9d6:#cc0000:#4e9a06:#c4a000:#3465a4:#75507b:#06989a:#d3d7cf:#77c529:#ef2929:#8ae234:#fce94f:#729fcf:#ad7fa8:#34e2e2:#eeeeec"
    [[[child0]]]
      order = 0
      parent = ""
      position = 0:25
      size = 1366, 768
      type = Window
    [[[child1]]]
      order = 0
      parent = child0
      position = 632
      type = HPaned
    [[[child2]]]
      order = 0
      parent = child1
      position = 354
      type = VPaned
    [[[child5]]]
      order = 1
      parent = child1
      position = 354
      type = VPaned
    [[[terminal3]]]
      command = top; bash
      order = 0
      parent = child2
      profile = default
      type = Terminal
    [[[terminal4]]]
      command = uptime; bash
      order = 1
      parent = child2
      profile = default
      type = Terminal
    [[[terminal6]]]
      command = cd ~/workspace; bash
      order = 0
      parent = child5
      profile = default
      type = Terminal
    [[[terminal7]]]
      command = cd ~/workspace; bash
      order = 1
      parent = child5
      profile = default
      type = Terminal
  [[simples]]
    [[[child0]]]
      order = 0
      parent = ""
      position = 0:25
      size = 715, 694
      type = Window
    [[[child1]]]
      order = 0
      parent = child0
      position = 348
      type = VPaned
    [[[terminal2]]]
      command = cd ~/workspace; bash
      order = 0
      parent = child1
      profile = default
      type = Terminal
    [[[terminal3]]]
      command = cd ~/workspace; bash
      order = 1
      parent = child1
      profile = default
      type = Terminal
[plugins]
[profiles]
  [[default]]
    background_image = None
    icon_bell = False
    scrollback_infinite = True

And to force color prompts:

~/.bashrc
1
force_color_prompt=yes

And my Wallpaper:

Other Preferred Applications:

I will update this page as I’m getting new apps or modifications

Display PHP Content Through HTML Files

While I was working with a root index page which is in HTML that had PHP content in, it did not render all of the PHP and some content was displayed as text, instead of rendered.

The Issue:

Some PHP content not rendered, as I am seeing this at the top of the page as plain text:

1
; somePhpFunction(); ?>

My Nginx Config:

nginx.conf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
http {
    include                     /etc/nginx/mime.types;
    default_type                application/octet-stream;
    sendfile                    on;
    access_log                  /var/log/nginx/access.log;
    keepalive_timeout           3000;

    proxy_cache_path /var/cache/nginx/ levels=1:2 keys_zone=nginx_cache:10m max_size=16m inactive=60m;

    server {
        listen                  80;
        root                    /www;
        index                   index.php index.html index.htm;
        server_name             _;
        client_max_body_size    32m;
        error_page              500 502 503 504  /50x.html;
        proxy_cache       nginx_cache;
        add_header        X-Proxy-Cache "public";

        location = /50x.html {
              root              /var/lib/nginx/html;
        }

        location ~ \.php$ {
              fastcgi_pass      127.0.0.1:9000;
              fastcgi_index     index.php;
              include           fastcgi.conf;
        }
    }
}

The Fix:

a .htaccess had to be placed in my root directory of the website:

.htaccess
1
AddType application/x-httpd-php .html .htm

After that was in place, all of the PHP was rendered

Sending Mail With SSMTP on Alpine Linux

Quick Post on how to use ssmtp on Alpine Linux to Send Mail:

Update and Install SSMTP

1
2
$ apk update
$ apk add ssmtp

Configure SSMTP

1
2
3
4
5
6
$ cat > /etc/ssmtp/ssmtp.conf << EOF
root=postmaster
mailhub=mail.domain.com:25
hostname=`hostname`
FromLineOverride=YES
EOF

Create the Mail Content

1
2
3
4
5
6
7
$ cat > mail.txt << EOF
To: recipient@domain.com
From: sender@domain.com
Subject: Mail with SSMTP

Hello, this is a test mail.
EOF

Testing Mail Delivery

1
$ ssmtp recipient@domain.com < file.txt

Related:

Backup and Restore Mutliple Collections From a Database With MongoDB

From a previous post we’ve Setup a MongoDB Cluster, and in this post we will go through the steps of backing up a database and restoring it to another mongodb cluster.

MLab offers a free Shared MongoDB Hosted Service with a limitation of 500MB, which I will be using to restore my data from my own hosted cluster to the free MLab service.

Create the MongoDB Backup

First we will need to create our backup path, and then backup our database, in my case, I am backing up my rocketchat database:

1
2
$ mkdir -p /opt/backups/mongodb
$ mongodump --host mongodb.example.com --port 27017 -u <mongouser> --authenticationDatabase <authdb> --db rocketchat --out /opt/backups/mongodb/

Change into the backup directory:

1
$ cd /opt/backups/mongodb/rocketchat/

You will find the bson and json metadata files for each collection:

1
2
3
4
5
6
7
8
9
10
$ ls -l | awk '{print $9}' | head -9
custom_emoji.chunks.bson
custom_emoji.chunks.metadata.json
custom_emoji.files.bson
custom_emoji.files.metadata.json
instances.bson
instances.metadata.json
meteor_accounts_loginServiceConfiguration.bson
meteor_accounts_loginServiceConfiguration.metadata.json
...

Restore MongoDB Database

We will need to restore all the collections to our new mongodb service, I have created a bash script (restore-mongodb.sh) that will restore each collection to our rocketchat database:

1
2
3
4
5
6
7
8
9
10
11
12
13
#!/usr/bin/env bash

mongo_user=<mongouser>
mongo_pass=<mongopass>

for file in `ls | grep bson`
  do
    for collection in `echo $file | sed 's/.bson//g'`
  do
    mongorestore --host mymongoid.mlab.com --port 12345 -u $mongo_user -p $mongo_pass -d rocketchat -c $collection $file
    sleep 2
  done
done

Change the permissions of your script to make it executable and execute the script:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
$ chmod +x restore-mongodb.sh
$ ./restore-mongodb.sh

2017-10-03T22:05:39.138+0200    checking for collection data in custom_emoji.chunks.bson
2017-10-03T22:05:39.159+0200    reading metadata for rocketchat.custom_emoji.chunks from custom_emoji.chunks.metadata.json
2017-10-03T22:05:39.211+0200    restoring rocketchat.custom_emoji.chunks from custom_emoji.chunks.bson
2017-10-03T22:05:39.900+0200    restoring indexes for collection rocketchat.custom_emoji.chunks from metadata
2017-10-03T22:05:39.922+0200    finished restoring rocketchat.custom_emoji.chunks (20 documents)
2017-10-03T22:05:39.922+0200    done
2017-10-03T22:05:42.188+0200    checking for collection data in custom_emoji.files.bson
2017-10-03T22:05:42.231+0200    reading metadata for rocketchat.custom_emoji.files from custom_emoji.files.metadata.json
2017-10-03T22:05:42.252+0200    restoring rocketchat.custom_emoji.files from custom_emoji.files.bson
2017-10-03T22:05:42.623+0200    restoring indexes for collection rocketchat.custom_emoji.files from metadata
2017-10-03T22:05:42.645+0200    finished restoring rocketchat.custom_emoji.files (20 documents)
2017-10-03T22:05:42.645+0200    done
...

Checkout the New MongoDB Database:

Once the restore has been done, logon to your new mongodb database and have a look at the collections in the database:

1
2
3
4
5
6
7
8
9
10
11
12
$ mongo mymongoid.mlab.com:12345/rocketchat -u <mongouser> -p
MongoDB shell version v3.4.7
Enter password:
connecting to: mongodb://mymongoid.mlab.com:12345/rocketchat
MongoDB server version: 3.4.9

rs-mymongoid:PRIMARY> show collections
_raix_push_app_tokens
_raix_push_notifications
custom_emoji.chunks
custom_emoji.files
instances

Resources:

Creating a Nodejs Hostname App With Docker Stacks on Swarm

Create a Nodejs Application that responds GET requests with its Hostname.

Our nodejs application will sit beind a HAProxy Load Balancer, we are mounting the docker.sock from the host to the container, so as we scale our web application, our load balancer is aware of the changes, and scales as we scale our web application.

Creating the Application:

Our nodejs application:

app.js
1
2
3
4
5
6
var http = require('http');
var os = require('os');
http.createServer(function (req, res) {
    res.writeHead(200, {'Content-Type': 'text/html'});
    res.end(`My Hostname: ${os.hostname()}\n`);
}).listen(8080);

Our Dockerfile:

Dockerfile
1
2
3
FROM node:alpine
ADD app.js /app.js
CMD ["node", "/app.js"]

Build and Push to your registry, or you could use my image on Dockerhub: hub.docker.com/r/rbekker87/node-containername

Build and Push
1
2
3
$ docker login
$ docker build -t <username>/<repo>:<tag> .
$ docker push  <username>/<repo>:<tag>

Creating the Compose file

Create the compose file that will define our services:

docker-compose.yml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
version: '3'

services:
  node-app:
    image: rbekker87/node-containername
    networks:
      - nodenet
    environment:
      - SERVICE_PORTS=8080
    deploy:
      replicas: 20
      update_config:
        parallelism: 5
        delay: 10s
      restart_policy:
        condition: on-failure
        max_attempts: 3
        window: 120s

  loadbalancer:
    image: dockercloud/haproxy:latest
    depends_on:
      - node-app
    environment:
      - BALANCE=leastconn
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    ports:
      - 80:80
    networks:
      - nodenet
    deploy:
      placement:
        constraints: [node.role == manager]

networks:
  nodenet:
    driver: overlay

Create the Stack:

Deploy the Stack by specifying the compose file and name of our stack:

Deploy our Stack
1
$ docker stack deploy -c docker-compose.yml node

List the Services in the Stack:

List Services in our Stack
1
2
3
$ docker stack ls
NAME                SERVICES
node                2

List the Tasks in the Stack:

Tasks in our Stack
1
2
3
4
5
6
7
8
$ docker stack ps node
ID                  NAME                  IMAGE                                 NODE     DESIRED STATE       CURRENT STATE            ERROR               PORTS
l5ryfaedzzaq        node_loadbalancer.1   dockercloud/haproxy:latest            dsm-01   Running             Running 40 minutes ago
c8nrrcvek79h        node_node-app.5       rbekker87/node-containername:latest   dsm-01   Running             Running 40 minutes ago
dqii18b2q5nn        node_node-app.10      rbekker87/node-containername:latest   dsm-01   Running             Running 40 minutes ago
vkpw2rugy0ah        node_node-app.11      rbekker87/node-containername:latest   dsm-01   Running             Running 40 minutes ago
mm88nvnvy5lg        node_node-app.12      rbekker87/node-containername:latest   dsm-01   Running             Running 40 minutes ago
oyx8rfqc1xl2        node_node-app.16      rbekker87/node-containername:latest   dsm-01   Running             Running 41 minutes ago

Test out our Application

Test out the Service:

GET Requests
1
2
3
4
5
6
7
8
$ curl -XGET http://127.0.0.1/
My Hostname: a6e34246e73b

$ curl -XGET http://127.0.0.1/
My Hostname: 5de71278be38

$ curl -XGET http://127.0.0.1/
My Hostname: e0b7316fdd51

Scaling Out:

Scale our Application out to 30 replica’s

Scaling Up
1
$ docker service scale node-app=30

Scale our Application down to 10 replica’s

Scaling Down
1
$ docker service scale node-app=10

Cleanup

Remove the Stack:

Delete the Stack
1
2
3
4
$ docker stack rm node
Removing service node_loadbalancer
Removing service node_node-app
Removing network node_nodenet

Resources:

Create a 3 Node Elasticsearch Stack With HAProxy on Docker Swarm

Tried out creating a 3 node elasticsearch stack on docker swarm using docker-compose, that sits behind a haproxy service.

Environment:

Images:

Stack:

  • 1 x haproxy
  • 1 x elasticsearch master (haproxy wont send requests to this one)
  • 2 x elasticsearch master/data
  • 1 x esnet overlay network

Defining our Stack

First we will create our compose file, which we will call es-compose.yml:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
version: '3'

services:
  es-master:
    image: rbekker87/elasticsearch:master-5.6-alpine
    networks:
      - esnet
    deploy:
      replicas: 1

  es-data-1:
    image: rbekker87/elasticsearch:master-5.6-alpine
    environment:
     - SERVICE_PORTS=9200
    networks:
      - esnet
    deploy:
      replicas: 2

  es-data-2:
    image: rbekker87/elasticsearch:master-5.6-alpine
    environment:
     - SERVICE_PORTS=9200
    networks:
      - esnet
    deploy:
      replicas: 2

  loadbalancer:
    image: dockercloud/haproxy:latest
    depends_on:
      - es-data-1
      - es-data-2
    environment:
      - BALANCE=leastconn
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    ports:
      - 9200:80
    networks:
      - esnet
    deploy:
      placement:
        constraints: [node.role == manager]

networks:
  esnet:
    driver: overlay

The above compose file defines that we want a overlay network, which we will associate with all our services, 3 elasticsearch services, haproxy service which will expose port 9200, then from haproxy it has a container port of 80, which sends to the backend SERVICE_PORTS of each elasticsearch service.

We have only defined SERVICE_PORTS=9200 on our es-data services, as I just want to proxy client connections to them.

Creating our Elasticsearch Stack

Now that we have our compose file ready, let’s create our stack using docker stack deploy:

Create the Stack
1
2
3
4
5
6
7
$ docker stack deploy -c es-compose.yml analytics

Creating network analytics_esnet
Creating service analytics_loadbalancer
Creating service analytics_es-master
Creating service analytics_es-data-1
Creating service analytics_es-data-2

Let’s have a look at our stack:

Docker Stack Status
1
2
3
4
5
6
$ docker stack ps analytics
ID                  NAME                       IMAGE                                       NODE                  DESIRED STATE       CURRENT STATE            ERROR               PORTS
4t3ukxl2kch3        analytics_loadbalancer.1   dockercloud/haproxy:latest                  scw-swarm-master-01   Running             Running 27 seconds ago
jgbxtgqkg9jp        analytics_es-data-2.1      rbekker87/elasticsearch:master-5.6-alpine   scw-swarm-master-01   Running             Running 33 seconds ago
x5cq6pm7u7mn        analytics_es-data-1.1      rbekker87/elasticsearch:master-5.6-alpine   scw-swarm-master-01   Running             Running 36 seconds ago
5v22w1hvtdvm        analytics_es-master.1      rbekker87/elasticsearch:master-5.6-alpine   scw-swarm-master-01   Running             Running 38 seconds ago

View the logs of our haproxy service:

HAProxy Service Logs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
$ docker service logs -f analytics_loadbalancer
analytics_loadbalancer.1.lcpgiz0ooeas@scw-swarm-master-01    | INFO:haproxy:dockercloud/haproxy 1.6.7 is running outside Docker Cloud
analytics_loadbalancer.1.lcpgiz0ooeas@scw-swarm-master-01    | INFO:haproxy:Haproxy is running in SwarmMode, loading HAProxy definition through docker api
analytics_loadbalancer.1.lcpgiz0ooeas@scw-swarm-master-01    | INFO:haproxy:dockercloud/haproxy PID: 7
analytics_loadbalancer.1.lcpgiz0ooeas@scw-swarm-master-01    | INFO:haproxy:=> Add task: Initial start - Swarm Mode
analytics_loadbalancer.1.lcpgiz0ooeas@scw-swarm-master-01    | INFO:haproxy:=> Executing task: Initial start - Swarm Mode
analytics_loadbalancer.1.lcpgiz0ooeas@scw-swarm-master-01    | INFO:haproxy:==========BEGIN==========
analytics_loadbalancer.1.lcpgiz0ooeas@scw-swarm-master-01    | INFO:haproxy:Linked service: analytics_es-data-1, analytics_es-data-2, analytics_es-master
analytics_loadbalancer.1.lcpgiz0ooeas@scw-swarm-master-01    | INFO:haproxy:Linked container: analytics_es-data-1.1.u641c5bq5vkjklk8sb1scnnlc, analytics_es-data-2.1.ic9an6bzj6aejs0lx0vzfpia6, analytics_es-master.1.h4erlgwzit509p0zehzmozy3u
analytics_loadbalancer.1.lcpgiz0ooeas@scw-swarm-master-01    | INFO:haproxy:HAProxy configuration:
analytics_loadbalancer.1.lcpgiz0ooeas@scw-swarm-master-01    | global
analytics_loadbalancer.1.lcpgiz0ooeas@scw-swarm-master-01    |   log 127.0.0.1 local0
analytics_loadbalancer.1.lcpgiz0ooeas@scw-swarm-master-01    |   log 127.0.0.1 local1 notice
analytics_loadbalancer.1.lcpgiz0ooeas@scw-swarm-master-01    |   log-send-hostname
analytics_loadbalancer.1.lcpgiz0ooeas@scw-swarm-master-01    |   maxconn 4096
analytics_loadbalancer.1.lcpgiz0ooeas@scw-swarm-master-01    |   pidfile /var/run/haproxy.pid
analytics_loadbalancer.1.lcpgiz0ooeas@scw-swarm-master-01    |   user haproxy
analytics_loadbalancer.1.lcpgiz0ooeas@scw-swarm-master-01    |   group haproxy
analytics_loadbalancer.1.lcpgiz0ooeas@scw-swarm-master-01    |   daemon
analytics_loadbalancer.1.lcpgiz0ooeas@scw-swarm-master-01    |   stats socket /var/run/haproxy.stats level admin
analytics_loadbalancer.1.lcpgiz0ooeas@scw-swarm-master-01    |   ssl-default-bind-options no-sslv3
analytics_loadbalancer.1.lcpgiz0ooeas@scw-swarm-master-01    |   ssl-default-bind-ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:AES128-GCM-SHA256:AES128-SHA256:AES128-SHA:AES256-GCM-SHA384:AES256-SHA256:AES256-SHA:DHE-DSS-AES128-SHA:DES-CBC3-SHA
analytics_loadbalancer.1.lcpgiz0ooeas@scw-swarm-master-01    | defaults
analytics_loadbalancer.1.lcpgiz0ooeas@scw-swarm-master-01    |   balance leastconn
analytics_loadbalancer.1.lcpgiz0ooeas@scw-swarm-master-01    |   log global
analytics_loadbalancer.1.lcpgiz0ooeas@scw-swarm-master-01    |   mode http
analytics_loadbalancer.1.lcpgiz0ooeas@scw-swarm-master-01    |   option redispatch
analytics_loadbalancer.1.lcpgiz0ooeas@scw-swarm-master-01    |   option httplog
analytics_loadbalancer.1.lcpgiz0ooeas@scw-swarm-master-01    |   option dontlognull
analytics_loadbalancer.1.lcpgiz0ooeas@scw-swarm-master-01    |   option forwardfor
analytics_loadbalancer.1.lcpgiz0ooeas@scw-swarm-master-01    |   timeout connect 5000
analytics_loadbalancer.1.lcpgiz0ooeas@scw-swarm-master-01    |   timeout client 50000
analytics_loadbalancer.1.lcpgiz0ooeas@scw-swarm-master-01    |   timeout server 50000
analytics_loadbalancer.1.lcpgiz0ooeas@scw-swarm-master-01    | listen stats
analytics_loadbalancer.1.lcpgiz0ooeas@scw-swarm-master-01    |   bind :1936
analytics_loadbalancer.1.lcpgiz0ooeas@scw-swarm-master-01    |   mode http
analytics_loadbalancer.1.lcpgiz0ooeas@scw-swarm-master-01    |   stats enable
analytics_loadbalancer.1.lcpgiz0ooeas@scw-swarm-master-01    |   timeout connect 10s
analytics_loadbalancer.1.lcpgiz0ooeas@scw-swarm-master-01    |   timeout client 1m
analytics_loadbalancer.1.lcpgiz0ooeas@scw-swarm-master-01    |   timeout server 1m
analytics_loadbalancer.1.lcpgiz0ooeas@scw-swarm-master-01    |   stats hide-version
analytics_loadbalancer.1.lcpgiz0ooeas@scw-swarm-master-01    |   stats realm Haproxy\ Statistics
analytics_loadbalancer.1.lcpgiz0ooeas@scw-swarm-master-01    |   stats uri /
analytics_loadbalancer.1.lcpgiz0ooeas@scw-swarm-master-01    |   stats auth stats:stats
analytics_loadbalancer.1.lcpgiz0ooeas@scw-swarm-master-01    | frontend default_port_80
analytics_loadbalancer.1.lcpgiz0ooeas@scw-swarm-master-01    |   bind :80
analytics_loadbalancer.1.lcpgiz0ooeas@scw-swarm-master-01    |   reqadd X-Forwarded-Proto:\ http
analytics_loadbalancer.1.lcpgiz0ooeas@scw-swarm-master-01    |   maxconn 4096
analytics_loadbalancer.1.lcpgiz0ooeas@scw-swarm-master-01    |   default_backend default_service
analytics_loadbalancer.1.lcpgiz0ooeas@scw-swarm-master-01    | backend default_service
analytics_loadbalancer.1.lcpgiz0ooeas@scw-swarm-master-01    |   server analytics_es-data-1.1.u641c5bq5vkjklk8sb1scnnlc 10.0.7.5:9200 check inter 2000 rise 2 fall 3
analytics_loadbalancer.1.lcpgiz0ooeas@scw-swarm-master-01    |   server analytics_es-data-2.1.ic9an6bzj6aejs0lx0vzfpia6 10.0.7.7:9200 check inter 2000 rise 2 fall 3
analytics_loadbalancer.1.lcpgiz0ooeas@scw-swarm-master-01    | INFO:haproxy:Launching HAProxy
analytics_loadbalancer.1.lcpgiz0ooeas@scw-swarm-master-01    | INFO:haproxy:HAProxy has been launched(PID: 10)
analytics_loadbalancer.1.lcpgiz0ooeas@scw-swarm-master-01    | INFO:haproxy:===========END===========

Testing Elasticsearch:

Do a GET request on our HAProxy’s Expose port: 9200

Test Elasticsearch on port 9200
1
2
3
4
5
6
7
8
9
10
11
12
13
14
$ curl -XGET http://127.0.0.1:9200
{
  "name" : "5306a0c2ee24",
  "cluster_name" : "es-cluster",
  "cluster_uuid" : "FUJmMekFQVq6zXofPCin2A",
  "version" : {
    "number" : "5.6.0",
    "build_hash" : "781a835",
    "build_date" : "2017-09-07T03:09:58.087Z",
    "build_snapshot" : false,
    "lucene_version" : "6.6.0"
  },
  "tagline" : "You Know, for Search"
}

Have a look at the /_cat/nodes API:

Get the Node Info
1
2
3
4
5
$  curl -XGET http://127.0.0.1:9200/_cat/nodes?v
ip       heap.percent ram.percent cpu load_1m load_5m load_15m node.role master name
10.0.7.6           28          84  14    3.09    2.28     1.49 mdi       -      56c1b0aebc5f
10.0.7.2           27          84  15    3.09    2.28     1.49 mdi       *      572c68bca904
10.0.7.4           29          84  15    3.09    2.28     1.49 mdi       -      5306a0c2ee24

Simple Program With C Language on Linux

Today the idea popped up on how to write a Simple “Hello World” Application using C Programming Language, as I just wanted to see how it works.

Requirements:

You will need the gcc package to compile the program:

RHEL
1
$ yum install gcc -y
Debian
1
$ apt install gcc -y

Writing our first Program:

We will create a app that just prints out a static defined value:

Create any file with a .c extension, in my case it will be app.c:

app.c
1
2
3
4
5
6
#include <stdio.h>

int main(){
    printf("Hello, World\n");
    return 0;
}

Now compile app.c with gcc and specify the output path of your app with -o <app-name>

app.c
1
$ gcc -o app app.c

Testing our App:

You will see that there is a executable file with the name that you have specified as the output:

app.c
1
2
$ ./app
Hello, World

Really basic, but quite cool.