Thursday, December 30, 2021

Edit Postgresql configuration without restart of database

Postgresql common configuration files are the postgresql.conf and pg_hba.conf. In many cases, its possible to edit without the need to restart the database. Here are the 2 options on  Centos Linux;

Use systemctl

# systemctl reload postgresql-11

or

# systemctl reload postgresql

Within Postgresql

Login and and access psql as admin or user postgres then run this sql.

SELECT pg_reload_conf();

Check Postgresql connections

Postgresql database provides 2 main configurations to limit the incoming connections. This is done in the file postgresql.conf

max_connections = 200                   # (change requires restart)
superuser_reserved_connections = 3      # (change requires restart)

Notes here refers to Postgresql version 11.

Following are common sql commands to monitor connections.

List number of connections

SELECT count(distinct(numbackends)) 
  FROM pg_stat_database; 

List connections by database

SELECT datname, numbackends 
  FROM pg_stat_database; 

    datname     | numbackends
----------------+-------------
 postgres      |           1
 template1     |           0
 template0     |           0
 shop01        |           0
 tutorial_php  |           0
 tutorial_linux|           0
 helpdesk      |          27
 telegram      |           6
(8 rows)

List the connections on a specific database

SELECT * FROM pg_stat_activity 
  WHERE datname='helpdesk';


List number of session that is active or idle.

SELECT state, count(*) FROM pg_stat_activity  
  WHERE pid <> pg_backend_pid() 
  GROUP BY 1 
  ORDER BY 1;


        state        | count
---------------------+-------
 active              |    55
 idle                |    38
 idle in transaction |     2
                     |     5
(4 rows)

These will provide data for planning and risk mitigations.

Wednesday, December 29, 2021

Howto clone existing GIT repository

There are many cases where remote git repositories provide a central location to store files such as source codes. The command 'clone' is used to retrieve a remote git repository. Depends on how a user is provided access to the server, by http, ssh or other methods. 

Here is how its done on Centos Linux, where it defaults to create a folder which is the same name as the repository.

cd /var/www

git clone ssh://nicholas@remoteserver:22/repo/tboxmy.git

Another approach is to create in our empty folder myproject

git clone ssh://nicholas@remoteserver:22/repo/tboxmy.git myproject


How to add user to the remote

git remote add newuser ssh://nicholas@remoteserver:22/repo/tboxmy.git

View remote users

git remote -v 

Wednesday, November 24, 2021

Adding standby node to Postgresql replication

 Postgresql database version 11 uses write ahead log (WAL) to ensure data integrity. It contains a log of all activity within the database, and helps with recovery of data. WAL records are saved to a WAL file. The insert position is a log sequence number (LSN) that is a byte offset into the logs, increasing with each new record.

Here, I am provided a Postgresql database that have been configured as a MASTER database. A user has been created on the Linux server and a role within the Postgresql called "replication". Now a new linux server have been provided for purpose of running a standby node, this has the same version of Postgresql database as in the MASTER server.

Installation of Standby

For simplicity the IP of MASTER will be 10.1.1.100, and for STANDBY will be 10.1.1.101.

Following information is provided by the MASTER slave;

Linux username: replication

with password: password

Replication standby server is assigned name: replication

Folder of the installation: /var/lib/pgsql/11/data

Within MASTER, the STANDBY server IP has been added to its pg_hba.conf. 

Lets configure the STANBY server

Step 1: Login as postgres user

sudo su postgres

(enter your password)

cd

Step 2: Replace local data with MASTER data

cd 11

mv data data.original

We will use the option -R to generate the default recovery.conf file.

pg_basebackup -h 10.1.1.100 -U replication -D /var/lib/pgsql/11/data -P --password --slot replication -R

(enter password provided by MASTER)

chmod go-rw data

cd data

Step 3: Start Postgresql server

Ensure firewalld allows the database access.

Review contents of recovery.conf, standby_mode should be 'on'.

sudo systemctl start postgresql-11


Monitoring replication process

STANDBY server.

The latest WAL file, is stored in the folder data/pg_wal. Display current process of startup and which WAL file is being pocessed.

ps -eaf|grep startup

postgres  186454  186452  0 17:51 ?        00:00:02 postgres: startup   recovering 000000010000000C00000024

Display the LSN
ps -eaf|grep receiver

postgres  186460  186452  0 17:51 ?        00:00:06 postgres: walreceiver   streaming C/24C1DA10

Login to psql as postgres user,

SELECT pg_last_wal_receive_lsn();

 pg_last_wal_receive_lsn
-------------------------
 C/24D0B740
(1 row)

SELECT pg_last_wal_replay_lsn();

 pg_last_wal_replay_lsn
------------------------
 C/24D15138
(1 row)

MASTER server

Display the replication connection.
ps -eaf|grep postgres

It should display a line that contains
postgres: walsender replication 10.1.1.101(49840) streaming C/24C90AF8

login the psql,

sudo su postgres
psql

SELECT pg_current_wal_lsn();

 pg_current_wal_lsn
--------------------
 C/24D243A0
(1 row)


SELECT * FROM pg_stat_replication;


-[ RECORD 1 ]----+------------------------------
pid              | 2322396
usesysid         | 98654
usename          | replication
application_name | walreceiver
client_addr      | 10.1.1.101
client_hostname  |
client_port      | 49840
backend_start    | 2021-11-24 17:51:54.164144+08
backend_xmin     |
state            | streaming
sent_lsn         | C/24D88B18
write_lsn        | C/24D88B18
flush_lsn        | C/24D88B18
replay_lsn       | C/24D88B18
write_lag        | 00:00:00.000447
flush_lag        | 00:00:00.001416
replay_lag       | 00:00:00.001419
sync_priority    | 0
sync_state       | async


Determine if STANDBY is lagging.

On the STANDBY server, run these in psql.

SELECT CASE WHEN pg_last_wal_receive_lsn() = pg_last_wal_replay_lsn()
THEN 0
ELSE EXTRACT (EPOCH FROM now() - pg_last_xact_replay_timestamp())
END AS log_delay;

It should result in a value of 0 if everything is in sync.

Display the last last records written.
select pg_is_in_recovery(),pg_is_wal_replay_paused(), pg_last_wal_receive_lsn(), pg_last_wal_replay_lsn(), pg_last_xact_replay_timestamp();

-[ RECORD 1 ]-----------------+------------------------------
pg_is_in_recovery             | t
pg_is_wal_replay_paused       | f
pg_last_wal_receive_lsn       | C/24DF6580
pg_last_wal_replay_lsn        | C/24DF6580
pg_last_xact_replay_timestamp | 2021-11-24 17:52:29.764273+08


Troubleshooting

Error Canceling statement due to conflict with recovery

This is due to standby server getting updates/deletes in the WAL stream that will invalidate data currently being accessed by a running query. Usually occurs when queries are time consuming.

Solution:
Edit data/postgresql.conf to increase max_standby_streaming_delay, which allows the standby server to intentionally increase replication lag to allow queries to finish. Case where write of archives are taking a longer time than expected, then increase max_standby_archive_delay.

Note: Posting this ahead of time, for comments on understandability of information.

Tuesday, November 23, 2021

Howto: Find and kill a hanging query in Postgresql

 In normal case of a query to Postgresql database, it would take a very small amount of time to be processed. However, when query takes a long time to process then it will be a problem as resources such as connection, CPU and RAM will be locked to process that query.

Problem queries may lead to more queries in waiting until the database maximum connection is reached. Default Postgresql is set to maximum 100 connections. This will cause users to fail when trying to login to the application or trying to access the database. These 2 are common examples of when you will need to kill queries.

Lets see break this to 2 parts. 

Part 1, list max connection, and the current settings. Part 2, find the problem query, then to end it.

Part 1

Identify is the maximum connection to database has been reached.

Step 1: list the current maximum connection settings and where it is configured.

Login to postgresql terminal as admin (postgres) and use the commands.

SELECT name, setting, sourcefile FROM pg_settings WHERE name LIKE 'max_connections';



Step 2: List connections used

SELECT count(*) used FROM pg_stat_activity;

Compare values, to determine if this is an issue.

Part 2


Step 1: List query that is currently active

SELECT datid, pid, usename, client_addr, backend_start FROM pg_stat_activity WHERE state = 'active';


Step 2: Kill the query

SELECT pg_cancel_backend(PID);

Where PID is the value identified in Step 1 above.


Part 3

Identify long running queries can be done with a popular query mentioned in (https://wiki.postgresql.org/wiki/Lock_Monitoring)

SELECT a.datname,
         l.relation::regclass,
         l.transactionid,
         l.mode,
         l.GRANTED,
         a.usename,
         a.query,
         a.query_start,
         age(now(), a.query_start) AS "age",
         a.pid
FROM pg_stat_activity a
JOIN pg_locks l ON l.pid = a.pid
ORDER BY a.query_start desc;

This concludes how to troubleshoot basic connection and hanging queries.

Monday, November 22, 2021

Add read only user in Postgresql

How to access to Postgresql where only reading of data is required?

Lets create a new user called "reader" and password as "password" who will be given access to the database mydatabase with READ only access. The following sign denotes the sql prompt, which you do not need to type.

=#

The steps listed here are rather generic on PostgreSQL 11 onwards. There are other considerations for security and more complex database designs that you should look into in the future.

Step 1

Connect to the database as administrator.

psql -U postgres -H localhost

=# \c mydatabase


Step 2

Create the new user

=# CREATE USER reader WITH encrypted PASSWORD 'password';

=# GRANT CONNECT ON DATABASE mydatabase TO reader;

=# GRANT SELECT ON ALL TABLES IN SCHEMA public TO reader;

Determine the user exist with the following command

=# \du


Step 3

Verify this by login as that user. Additionally, the user access can be shown through the commands.

=# \l 
=# \l mydatabase

Connect to the selected database and list that user's privileges.

=# \c mydatabase

=# SELECT table_catalog, table_name from information_schema.role_table_grants WHERE grantee = "reader";

=# SELECT table_catalog, table_schema, table_name from information_schema.table_privileges WHERE grantee = "reader";


Managing user privileges

In the case where that user is no longer required, it is only prudent to remove that user from access to the database. It is common to maintain that user within the system, in case they need to assign the user to another database access.

=# REVOKE ALL ON DATABASE mydatabase FROM reader;

Adding user to an existing READ only role would allow faster management of users.

=# CREATE ROLE reader

=# CREATE USER dave IN ROLE reader

Exercise:

Document your steps for this intermediate exercise.

Create a new user with login access name "dave" and password "exercise". 

Create a database name "bookstore" with a table called "users". You are free to assign the field type to a sensible type. 

users(
id, 
name, 
email, 
options, 
created_at, 
updated_at)

Fill this table "users" with 2 rows of data.

Assign user "dave" to be able to connect to this database and read contents of any table in this database.

Connect as user "dave" and verify if the user can only read data, without being able to update its data.


Friday, November 19, 2021

Installing Nodejs and NPM on MS Windows 10

What is NodeJS?

Its what is known as a runtime environment, where programmes written in JavaScript can run.

What is Python?

Python in a programming language. 

What is NPM?

Its a node package manager, which is an application and repository for developing and sharing JavaScript code. Many developers write applications and allow the NPM access to their programmes.

What is Chocolatey?

Its a package manager for windows that runs in Windows PowerShell. Which means, when installing a programme, and there are other dependencies, it will go search and download for you.

How to install Nodejs and NPM?

Download the executable for your version of Windows, at https://nodejs.org/en/download/ 

Example, download and Save the Windows Installaer (.msi) for 64-bit.

Run the installer. Make sure to CHECK box to Automatically install the necessary tools. This will add to path the Node.js and npm programmes.

At end of installation, a Windows prompt will appear. This runs several scripts, press "Space" and follow the instructions which will lead you to the Windows PowerShell prompt.

Test installation

Open a command prompt and type the following;

npm -version

node -v


My output was

8.1.0

v16.13.0

Run Hello World

Lets use an available helloworld package. At the windows terminal;

npm init hello-world helloworld

cd helloworld

npm run start


Use a web browser with the URL that is displayed at the terminal to see the results. In my case, the URL is http://localhost:3000

Issues

The Windows PowerShell waits for a long time with the last message, and task manager show lots of memory+disk activity+Ethernet. 

Created a UnelevatedInstallerTelemetryDecorator

Could it be a slow PC with slow network connectivity? If there are no errors in windows logs, just wait until its done processing and the text appears. My PC took almost 30 mins.

Press Enter to exit.

Thursday, November 18, 2021

Centos 8 insufficient memory for the Java Runtime Environment to continue

On Linux Centos 8, with Apache Tomcat that would start but almost immediately fail. There is 4 Gb of Ram assigned, and without any load, the service kept crashing. It was really strange.

The Java installed was Openjdk version "1.8.0_312", and Apache Tomcat version 9.0.46.

What was the issue?

Each attempt to start Tomcat, it fails then from the logs:

OpenJDK 64-Bit Server VM warning: INFO: os::commit_memory(0x00007f32cd0a7000, 262144, 0) failed; error='Cannot allocate memory' (errno=12)
#
# There is insufficient memory for the Java Runtime Environment to continue.
# Native memory allocation (mmap) failed to map 262144 bytes for committing reserved memory.
# An error report file with more information is saved as:
# /tmp/hs_err_pid49973.log

How can this be? There is 4Gb assigned to the server, with lots of free memory. As can be seen in the configuration, the maximum memory of 1024Mb is assigned to Tomcat. The configuration file is  <TOMCAT>/bin/setenv.sh

export CATALINA_OPTS="-server -Xms1024M -Xmx1024M"

JAVA_OPTS="$JAVA_OPTS -XX:+UnlockExperimentalVMOptions -XX:+UseTLAB -XX:+UseG1GC -XX:G1MaxNewSizePercent=30 -XX:InitiatingHeapOccupancyPercent=40 -XX:G1NewSizePercent=25 -XX:ConcGCThreads=2 -XX:ParallelGCThreads=2 -Dfile.encoding=UTF8 -XX:+PrintGCTimeStamps -XX:+PrintGCDetails -Xloggc:tomcat_gc.log"

export JAVA_OPTS

Here is the result of command free, hardly any memory is in use (less than 80% for sure) when tomcat is NOT running


Why?

Some how Linux was assigning memory usage not in the way I was expecting. Lets check values for memory overcommit with command

sysctl -a |grep overcommit


Or only display how memory is assigned

cat /proc/sys/vm/overcommit_memory


An explanation of this setting

vm.overcommit_memory=0 setting means that the allocated virtual memory is unlimited. Having unlimited virtual memory is important for database servers, which retain extra unused virtual memory allocations for dynamic memory management. Unreferenced allocated memory is not backed by RAM or paging space on Linux systems. 

vm.overcommit_memory=1 setting where the kernel performs no memory overcommit handling. This increases the possibility of memory overload, but improves performance for memory-intensive tasks. 

vm.overcommit_memory=2, setting limits the total amount of virtual memory that can be allocated, which can result in unexpected errors.

How was this resolved?

What worked for me is to set vm.overcommit_memory=1 and ensure Tomcat starts with memory size to use the free space. This is done by updating the variable vm.overcommit_memory to 1, then in tomcat configuration as mentioned earlier, set the CATALINA_OPTS="-server -Xms1024M -Xmx1024M". Once it was working, I gradually increase the memory allocation.

Start with the following command (without reboot). Suggest before applying commands below, to stop any HTTP, PHP-FPM, NGIX and Tomcat services if running.

echo 1 | sudo tee /proc/sys/vm/overcommit_memory
sysctl -p

Restart the Tomcat application and watch Tomcat running smoothly. If all works, then this can be applied permanently by editing the file in /etc/sysctl.d

Now, 

When Tomcat is running with 1024Mb memory assigned.


When Tomcat is running with 2048Mb memory assigned.



These are just overly simplified notes, which might help. Best to still refer to the experts that is managing the server, as each case might be different.

Friday, November 5, 2021

Building Vue Single Page Application (part 2)

 Creating a Vue component. 

This is a continuation of Tutorial from Part 1.

Part 1:

  • This will build a Vue project with a component called Helloworld.
  • Identify basic folder and files
  • Know how to instantiate a Vue application
  • Know the basic flow
  • Know a basic Vue shorthand
  • Be able to create string variable
  • Be able to create custom function
Part 2:
  • Know what is a component
  • Be able to create a new component
  • Be able to create an array variable
  • Know how to display variables in a table format
  • Know what is Bootstrap
  • Be able to add Bootstrap
  • Be able to create a Bootstrap navbar, navbar-brand, navbar-nav and form within navbar


1. Add and test a new component named Products

Create the file src/components/Products.vue and add the contents

<template>
  <div class="products">
      <h1>{{ msg }}</h1>
  </div>
</template>
<script>
export default {
  name: 'Products',

  props: {
    msg: String
  }
}
</script>

Update the App.vue template with data and methods to be used in the component.

Replace <HelloWorld msg="

with 

<Products msg="

Replace import HelloWorld from './components/HelloWorld.vue'

with 

import Products from './components/Products.vue'

Apply changes and run


Add data and for loop

Edit <SCRIPT> content in src/components/Products.vue

export default {
  name: 'Products',
  props: {
    msg: String,
    products: Array,
  }
}

Edit <TEMPLATE> content in src/components/Products.vue

  <div class="products">

      <h1>{{ msg }}</h1>

      <table border=1>

      <thead>

        <tr>

          <th>Name</th>

          <th>Description</th>

          <th>Cost</th>

        </tr>

      </thead>

      <tbody>

        <tr v-for="product in products" :key="product.id">

          <td>{{ product.name }}</td>

          <td>{{ product.description }}</td>

          <td>{{ product.cost }}</td>

        </tr>

        </tbody>

    </table>

  </div>


Edit conponents data in src/App.vue

  data(){
    return {
      message: 'My Products',

      products: [
        {
          id: 1,
          name: "Leather shield",
          description: "Tough leather",
          cost: 120 },
        { id:2,
          name: "Heavy Leather shield",
          description: "Double leather layers",
          cost: 150 },
        ],
    }

Compile and run

2. Add Bootstrap support

Current Vue 3, will cause Bootstrap 5 to be installed.

npm install --save @popperjs/core bootstrap

Edit the file src/main.js to import the installed bootstrap.

import "bootstrap";

import "bootstrap/dist/css/bootstrap.min.css";

3. Create a navigation bar component

Lets use the example code from bootstrap. Create a new file src/components/Navigation.vue

Then add the following code

<template>
<div class="row">
<div class="NavbarPage hold-transition sidebar-mini layout-fixed">
    <nav class="navbar navbar-expand-lg navbar-light bg-light">
        <div class="container-fluid">
            <a class="navbar-brand" href="#">Navbar</a>
            <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
            <span class="navbar-toggler-icon"></span>
            </button>
            <div class="collapse navbar-collapse" id="navbarSupportedContent">
            <ul class="navbar-nav me-auto mb-2 mb-lg-0">
                <li class="nav-item">
                <a class="nav-link active" aria-current="page" href="#">Home</a>
                </li>
                <li class="nav-item">
                <a class="nav-link" href="#">Link</a>
                </li>
                <li class="nav-item dropdown">
                <a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-bs-toggle="dropdown" aria-expanded="false">
                    Dropdown
                </a>
                <ul class="dropdown-menu" aria-labelledby="navbarDropdown">
                    <li><a class="dropdown-item" href="#">Action</a></li>
                    <li><a class="dropdown-item" href="#">Another action</a></li>
                    <li><hr class="dropdown-divider"></li>
                    <li><a class="dropdown-item" href="#">Something else here</a></li>
                </ul>
                </li>
                <li class="nav-item">
                <a class="nav-link disabled" href="#" tabindex="-1" aria-disabled="true">Disabled</a>
                </li>
            </ul>
            <form class="d-flex">
                <input class="form-control me-2" type="search" placeholder="Search" aria-label="Search">
                <button class="btn btn-outline-success" type="submit">Search</button>
            </form>
            </div>
        </div>
        </nav>
</div>
</div>
</template>

<script>
</script>

Next, edit src/App.vue can replave the DIV with ID=app to the following

<div id="app" class="container-fluid">  

  <NavbarRow />


Within the tag <script>, add this new component

import NavbarRow from './components/Navigation.vue'


Add this to the components list

components: {

     Products, NavbarRow,

  },


Compile and run.


Exercise:

1. Create a new component called Footer.vue and like its name, setup within App.vue to display your name and email as the page footer.

2. Describe how each of the modules are loaded through a drawing. 

3. Edit the menu item "Link" in the navigation bar to load a website of your preference.


Building Vue Single Page Application (part 1)

Following is an introduction tutorial to building a Vue application. It works on MS Windows 10 and Centos Linux 7/8.



Part 1:

  • This will build a Vue project with a component called Helloworld.
  • Identify basic folder and files
  • Know how to instantiate a Vue application
  • Know the basic flow
  • Know a basic Vue shorthand
  • Be able to create string variable
  • Be able to create custom function
Part 2:
  • Know what is a component
  • Be able to create a new component
  • Be able to create an array variable
  • Know how to display variables in a table format
  • Know what is Bootstrap
  • Be able to add Bootstrap
  • Be able to create a Bootstrap navbar, navbar-brand, navbar-nav and form within navbar


Pre-requisite: 

Nodejs version 12.x

NPM version 6.14.x


Most of the commands will  be at the command line, 

Install VUE

npm install -g @vue/cli

vue --version
@vue/cli 4.5.15

vue create helloworld

Select Vue 3, using arrow keys.


Run server for VUE

cd helloworld

npm run serve

Test the new site by opening a web browser and pointing to URL http://localhost:8080/

Press Ctrl-c to stop the server


Parts of Vue

Following are basic files and folders of interest;

src/main.js : root Vue instance is declared and configured.

src/App.vue : contains root Vue components. Notice the page title is defined here in the value "msg".

public/index.html : Rendering page of target "app" or should Vue instance fail.

src/components/HelloWorld.vue : Codes for the initial page that root Vue has declared.


This concludes creating a default Vue project. In each of the exercise below, view the results with

npm run serve


Exercise:

1. Update variable msg string

Replace the page welcome message with your own in the file src/App.vue


2. Update string using component data

In Vue, there are short hand notations. One of this is ":msg" which is shorthand for our variable msg in "v-bind:msg".

In the file src/App.vue edit the components

  components: {
    HelloWorld
  },
  data(){
    return {
      message: 'This is my custom title!'
    }
  }

Replace HelloWorld place holder with

<HelloWorld :msg="message"/>


3. User input to display variable in popup window

Edit file src/App.vue, add after the line <HelloWorld .....

<input type="text" v-model="message" />
<button @click="alertMessage">Ok</button>


Add another component methods, for the function alertMessage to be called

  data(){
    return {
      message: 'Hello World!'
    }
  },

  methods: {
    alertMessage(){
      alert(this.message)
    }
  }


Thursday, October 28, 2021

Kerberos on Centos 8 - notes

Basics on Kerberos on Centos Linux 8.

A user or service is defined as a principal. E.g. a user dev, a service postgres and postgres/TBOX.SITE

An instance is used to manage principals. 

E.g. root/admin, where

root = principal

/admin = instance

A Key Distribution Center (KDC) contains database of all principals and

  • Authentication Server (AS)
  • Ticket Granting Server (TGS)
Keytab is a binary file that where the encryption key is extracted from a service or host.

Following are among the admin console commands

Admin console

sudo kadmin.local

List principals

listprincs

Add principals

addprinc -randkey HTTP/10.8.8.186@TBOX.SITE
addprinc -randkey postgres/10.8.8.186@TBOX.SITE

Delete principal

delprinc dev@TBOX.SITE

Install and configure kerberos server

sudo dnf install krb5-server 
sudo vi /etc/krb5.conf

[libdefaults] default_realm = TBOX.SITE [realms] TBOX.SITE = { kdc = 10.8.8.186 admin_server = 10.8.8.186 } [domain_realm] pg.tbox.com = TBOX.SITE .pg.tbox.com = CTBOX.SITE

Create a Realm

To create realm called TBOX.SITE. This will initialise a database at /var/kerberos/krb5kdc/principal

sudo kdb5_util create -r TBOX.SITE -s

Loading random data Initializing database '/var/kerberos/krb5kdc/principal' for realm 'TBOX.SITE', master key name 'K/M@TBOX.SITE' 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:

Assign administration access rights to the kerberos database;
sudo vi /var/kerberos/krb5kdc/kadm5.acl

*/admin@TBOX.SITE     *

Restart kerberos service

sudo systemctl restart krb5kdc

Destroy a kerberos database (optional)

sudo kdb5_util -r TBOX.SITE destroy


Initial Principal Admin setup in kadmin

sudo kadmin.local
kadmin.local: addprinc root/admin
kadmin.local: q

Add additional users to specific realm with random key

addprinc -randkey daniel@TBOX.SITE

Add additional users to specific realm with password and default realm

addprinc dev

Credential list

List credentials

klist
Ticket cache: KCM:1001:31655
Default principal: dev@TBOX.SITE

Valid starting       Expires              Service principal
10/27/2021 18:29:48  10/28/2021 18:29:48  krbtgt/TBOX.SITE@TBOX.SITE
        renew until 10/27/2021 18:29:48

Create credentials

kinit root/admin
kinit dev

Delete credentials (optional)

kdestroy -A

Keytab management


ktutil

Load keytab data
rkt /tmp/postgres.keytab

List cached
list

Remove entry
delent {slot_number}


Create keytab for use in remote server (to be confirmed)

addprinc -randkey HTTP/www.mydomain.org@MYDOMAIN.ORG
ktadd -k /tmp/http.keytab HTTP/www.mydomain.org@MYDOMAIN.ORG

Copy /tmp/http.keytab to the site

Thursday, October 21, 2021

Reduce image size on Linux

ImageMagick provide tools on Linux to manipulate images such as those of the  JPEG, TIFF, PNM, GIF and Photo CD image formats. Default installation includes special effects that can be applied to the images.

Using other Linux scripts and commands, there are many uses to the tool provided by ImageMagick.

Install on Centos 

sudo yum install ImageMagick

Or

sudo dnf install ImageMagick


Resize images

convert original_apple.jpg -resize 1024 new_apple.jpg


Search files larger than 2Mb size in a directory and convert image to max width 2048 while preserving image ratio.

find directory_name -type f  -size +2M -exec convert {} -resize 2048 {} \;


Other actions by ImageMagick

Change image compression (value between 1 and 100)

convert original_apple.jpg -quality 95 new_apple.jpg


Resize image by height 

convert original_apple.jpg -resize x200 new_apple.jpg


Rotate an image

convert original_apple.jpg -rotate 180 new_apple.jpg


Convert PNG format to JPEG

convert original_apple.png original_apple.jpg

This will remove any transparency in PNG.


Apply an image effect.

convert original_apple.png -swirl 45 original_apple.jpg

Following are effects available:

-annotate geometry text

-charcoal radius

-enhance

-implode amount

-monochrome

-sketch geometry

-swirl degrees

-transpose

-transverse

Friday, September 3, 2021

Howto compare 2 GIT branch

 The benefits of GIT is being able to work in different branches from the master codebase. Commonly a new feature being developed would be published to a new branch for review before being merged to the master branch. Once it is merged to the master branch, the new branch would be removed from the remote site.

Before merge to the master branch, it is possible to compare between the 2 branches. This will allow a check on files changes and where are the code changes. Here, lets see how to retrieve the new branch from remote, then compare changes made. The git command format in general would be;

git option <arguments>

Assumptions:

  • code base is in the branch master
  • remote name is origin
  • new remote branch is FEATURE
  • git version 1.8 and 2.19

Retrieve a remote branch

This section is more of a recap where the remote branch does not exist on your local machine. The option branch can use -b or -t depending on your needs. There is the example with -t where it creates the required branch locally and fetch its contents from remote.

git branch -t origin/FEATURE

git checkout FEATURE


View latest commit in the branch

git log

git log --oneline

Compare difference between branch

git diff master..FEATURE

View only the files that changed

git diff --name-status master..FEATURE

This describes use with TWO dots in the diff option. There is a THREE dots with the diff, but display results that compares the common between the 2 branches. More commonly, in cases that feature is already merged to master, it will produce no results.

Compare difference between commits

Displaying differences in commit between branches is ideal to identify developer notes in the commit between branches at level of commits.

git log master..FEATURE

There are many options to display log difference. Here is one example

git log --oneline --graph --decorate --abbrev-commit master..FEATURE

Compare difference in a file

When working to identify where a specific file has changed between two branches, just mention the relative path of the file

git diff master..FEATURE -- public/js/app.js


Compare with difftool

Here is an option to launch external editors to view the diff results. 

git difftool master..FEATURE

If required, a full directory diff can be done by adding the argument -d. This works fine on our linux systems, but on a GUI environment, the graphical code editors can be configured and activated with the argument -g.


Thats the basics to compare two branches using the diff and log options. Comparing existing branch or commits can be done with shorthand notations, which is much easier and I did not mention them here. This will help to ensure a smoother management of source codes.




Tuesday, July 20, 2021

Disable "your organization requires you to change your password" in Windows 10

 This might not be part of the open source, but its just a thing to blog.

Recently a windows 10 Home, login screen after successfully entering the PIN popup the message "your organization requires you to change your password" and forced users to change the pin before proceeding. Those who were not aware, changed it, but did not remember this new PIN the next time they needed to login.

I am trying out this method, but can't say it works as I have not done more test. Its just for my record


Steps

In Windows 10, press Win+r and type regedit

Scroll through Registry Editor, explorer like navigation as follow

Computer\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Policies\PassportForWork

Look for the item within that sub-folder named Policies\PINComplexity where it contain several value. Change the value named "Expiration". Double click and choose decimal. In Value data put in the number of days before the PIN expires. 

I can't say whats the correct value to disable, but for now I am using the Value data=600 (in decimal). Expecting the PIN to last 600 days. Maybe Windows 11 would be out by then.


Monday, July 12, 2021

KVM virtual machine on Centos 8 - Change name and Create snapshots

 Virtualisation provide a more efficient use of memory, disk and all CPU on a server. Separate servers can be managed within a single server. Centos 8 provide virtual machine (VM) management through KVM (kernel virtual machine).

 Each VM is given a domain name. Common practice before upgrading a server operating system, is to create a backup the current VM, or as its known here, a snapshot. Default format in use is qcow2, where tools for snapshot will work. Through Virtual Machine Manager and Cockpit, virtual machines can be created and managed. 

Centos 8 Cockpit view of VM administration

 Creating of virtual machines is not covered in here as its quite straight forward. Mostly it depends on the organisation practise and best practises.

Pre-requisite:
  • Centos 8 is installed with virtual machine manager.
  • A virtual machine is already added with the name "Centos7_php"

 Let's work with an existing VM named "Centos7_php". This virtual machine is installed with the operating system Centos Linux 8 and all the other packages required as a PHP development server. This requires the VM to be shutdown (and there are no snapshots)

Display available running VM

Syntax: 

virsh list


Shutdown VM

Syntax:
virsh shutdown {domain}
virsh shutdown Centos7_php

Rename VM

Syntax: 
virsh domrename {domain} {new_name}

virsh domrename Centos7_php php_development

Startup VM

Note: The following will continue to use the initial VM name of Centos7_php.

Syntax: 
virsh start {domain}

virsh start Centos7_php

Retrieve VM configuration

Syntax: 
virsh dumpxml {domain}

List available snapshots for a domain

Syntax:
virsh snapshot-list --domain {domain}

Create a snapshot

Snapshots can be created while a VM is running. Best practise would be to stop the VM, where possible. The reason why double-quotes are used here, is that its common to have snapshot name with spaces. But no so for the domain name.
Syntax:
virsh snapshot-create-as --domain {domain} --name "{snapshot_name}"


View details of a snapshot with syntax:
virsh snapshot-info --domain {domain} --name "{snapshot_name}"

Example of creating a snapshot, then showing its details

virsh snapshot-create-as --domain Centos7_php \ 
  --name "2021July" --description "Snapshot initial stages"
virsh snapshot-list --domain Centos7_php
virsh snapshot-info --domain Centos7_php --name "2021July" 

Revert to a specific snapshot

Ensure the VM is shutdown before switching to a snapshot. Here is the syntax and an example.
Syntax:
virsh --snapshot-revert --domain {domain} --snapshotname "{snapshot_name}"

Example to switch to a snapshot known and initial.

virsh shutdown Centos7_php
virsh --snapshot-revert --domain Centos7_php \
     --snapshotname "2021July"
virsh start Centos7_php 

Delete a snapshot

Each snapshot takes up disk space, and these can be removed when not in use anymore.

Syntax:
virsh --snapshot-delete --domain {domain} --snapshotname "{snapshot_name}"

Example to delete a snapshot

virsh --snapshot-delete --domain Centos7_php --snapshotname "2021July" 


Saturday, July 3, 2021

Howto check Centos 7 and 8 common services

In Centos 7 and earlier, SysV manage Linux services. To list such services, 

config --list


Centos 7 and 8 uses Systemd to manage Linux services. The syntax for this command is

systemctl [OPTIONS...] COMMAND [UNIT...]

Centos 7 was a transition phase towards the newer Systemd, and it maintained a mix of service types.


Here are a list of common command to check Linux services.

List active systemd services

systemctl 



List all systemd services

systemctl -a

List only SysV services (centos 7 and older)

systemctl list-unit-files


List by service types

systemctl list-units --type service

systemctl list-units --type mount

Where

LOAD   = Reflects whether the unit definition was properly loaded.

ACTIVE = The high-level unit activation state, i.e. generalization of SUB.

SUB    = The low-level unit activation state, values depend on unit type.


Check status of a service

systemctl status sshd.service

sudo systemctl status nfs-server.service


To stop or start or restart a service

sudo systemctl stop nfs-server.service

sudo systemctl start nfs-server.service

sudo systemctl restart nfs-server.service


To determine service is active or enabled the following will return 0 (active) and non zero (disabled)

systemctl is-active sshd

systemctl is-enabled sshd

systemctl is-active nfs-server

systemctl is-enabled nfs-server


To list a service and its dependencies;

 systemctl list-dependencies nfs-server


List services and their number of running task, CPU percentage, memory usage and I/O continuously

systemd-cgtop


List services as above once

systemd-cgtop -n 1


To sort, use the following based on the column titles

systemd-cgtop -t 

systemd-cgtop -c

systemd-cgtop -m

systemd-cgtop -i


List services and their open ports

netstat -a

List services that use TCP and UDP and their open ports

netstat -tulpn


Display which user is used for a filename

fuser . -v


Display running service

top


Display running services in pretty formatting and enable F1-F10 commands.

htop






Monday, June 28, 2021

Pagination within Laravel

One of the most common operations in Laravel involves the index.blade.php file. It displays a list of all the contents that an object retrieves from the database. In situations where there are thousand of rows of data, the view would best display it across many pages.

In Laravel, Pagination by default is compatible with Tailwind CSS framework and Bootstrap 4. When the number of rows are huge, its essential that the database column where the "whereby" clause is used, is index. 

Lets see 2 methods to apply pagination in a Laravel project using Bootstrap 4. 

Edit file App\Providers\AppServiceProvider.php

public function boot(){
  Paginator::useBootstrap();
}

Lets consider ArticleController that retrieves Article objects from the database through the function index(). This will display all the articles through a View called index.blade.php. For simplicity, only a total of 3 items will be displayed per page. 


Method 1: Using Paginate

Users will be able to view pagination with page numbers.

Pagination display


Edit app\Http\Controllers\ArticleController.php

public function index()
{
   $itemsPerPage = 3;
   $notes = Note::latest()->paginate($itemsPerPage);
   return view('notes.index', compact('notes'));
}

Edit resources\views\articles\index.blade.php and below the displayed date listing add the pagination.

<div>
{!! $notes->links() !!}
</div>

Additional functions available to use with Paginator

  • Number of items in current page $notes->count()
  • Current page number $notes->currentPage() 
  • Last page available $notes->lastPage()


Method 2: Using Cursor

Users will be able to view pagination with only the previous, and next navigation.

Cursor pagination


Edit app\Http\Controllers\ArticleController.php

public function index()
{
   $itemsPerPage = 3;
   $notes = Note::latest()->cursorPaginate($itemsPerPage);
   return view('notes.index', compact('notes'));
}

Edit resources\views\articles\index.blade.php and below the displayed date listing add the pagination.

<div>
{!! $notes->links() !!}
</div>


Additional functions available to use with Cursor

  • Number of items in current page, $notes->count()
  • Determine if cursor is on the first page, $notes->onFirstPage() 
  • Returns value of 1 if there are more pages to be split, $notes->hasMorePages()

Customise Pagination

This can be done by generating the required pagination files for customisation.

php artisan vendor:publish

Then select laravel-pagination and press enter. Find the files in the folder vendor/pagination in the project's view folder. Edit default.blade.php for a custom pagination layout. Here is an example of a customised Paginate.




Friday, May 28, 2021

How to clone a git branch

These notes are for Centos Linux version 7 (git 1.8) and 8 (git 2.7). 

Git is used as a repository to maintain source codes. Its advantage is in being able to manage source codes and files in a distributed way. This allow each one author to have the history and control of the source codes and files that are in their own access. 

A repository is commonly stored at a server and is accessed commonly through secure shell (SSH) or web (HTTP, HTTPS). Programmers, testers and others may clone (make a copy) of the repository OR a branch of the repository to their local machine.

Example of the command to clone by SSH where the username is git, the server URL is github.com 

git clone git@github.com:tboxmy/laraveljsonapi.git

When a repository is created, it is common to have the default branch name "master". From there, source code for development or testing is created in a new branch. 
git branch listing


Example it can be name by functionality "customer-feature". From that branch, another new branch can even be created, for example "customer-view".

git checkout -b customer-feature
git checkout -b customer-view

To switch between branches, use the command checkout

git checkout customer-feature

Then this new branch can be added to the repository with the option "-u".

git push -u origin customer-feature

Further changes to the branch can be easily added to the repository with the command

git push origin customer-feature


Most of the commands listed here should require administration rights.

Installation

yum install git
OR
dnf install git

Clone the whole repository

git clone git@github.com:tboxmy/laraveljsonapi.git

cd laraveljsonapi

Then list the branches in local and at remote server.

git branch -a

View activity at remote branch

git remote show origin

Clone a branch from repository

Start from a directory where the branch should be created.

git clone -b customer-feature git@github.com:tboxmy/laraveljsonapi.git

cd customer-feature

View log activity of that branch

git log

Thursday, March 11, 2021

Backup Postgresql Database

Here are the basic steps to backup and restore Postgresql database. At this point of writing, I am using Postgresql 10 and 11 on Centos Linux 8. 

In this article, backup database is inventory_system and restore of the backup is to another database that I will call cupboard.

Singles Database

Step 1: Login as postgres user

su - postgres

or 

sudo su postgres -

Step 2: Dump the database content to a file using the tool pg_dump

pg_dump inventory_system >  inventory_system-20210312.bak

or when database is located at IP 10.1.1.123 with port 5432

pg_dump -h 10.1.1.123 -p 5432 inventory_system >  inventory_system-20210312.bak

Step 3: Create the new database

createdb cupboard

Step 4: Restore the database file with psql

psql cupboard <  inventory_system-20210312.bak


On MS Windows 10 prompt that is provided through Laragon, the postgres user login is required

pg_dump -U postgres cm2020_1 > test.bak


Schedule backup

Cron job is suitable to automate the backup process mentioned above. To schedule a cron job, use the command

crontab -e

Then save the following instruction to run at midnight of every Saturday

0 0 * * 6 pg_dump -U postgres inventory_system > ~/postgres/backups/inventory_system-20210312.bak

Save and exit from the text editor.


Refer to Cron activities in the file /var/log/cron

For automated backup, there is a good note with the scripts at Postgresql wiki.

Sunday, February 28, 2021

Raspberry Pi display problems

Having successfully installed a new Raspberry Pi with Raspbian OS, it is common that the next reboot the screen display just leaves a blank screen. You just know its the display setting run when at the boot screen the system messages can be seen.

Firstly, the most important file you must know is the /boot/config.txt

This contains many configuration, that require the file to be save and RPi to be restarted. 

If your display is working, but the resolution is wrong, then access the start menu And look for Configuration, or directly access the resolution setting, type 

raspi-config


When the display is a touch screen, it would be a good idea to install a virtual keyboard. Do this by

sudo apt install florence

Back to troubleshooting a display that's not showing. Always check your display is powered, and that system messages appear at boot before proceeding here.


Step 1.

Ensure RPi is connected to your local network, then SSH to your RPi. On MS Windows there is a software named Putty. 


Step 2. 

Determine your device supported resolutions. Use either of following commands;

tvservice -m CEA

tvservice -m DMT

Depending on whether you are connected to a TV (CEA) or computer monitor (DMT). Generally, a TV with VGA cable will use CEA. 


Step 3.

Edit the file /boot/config.txt

Use the settings identified in Step 2. If you are using CEA then the value of hdmi_group=1,

if its DMT then hdmi_group=2. 


Eg 1. when connected to a monitor with resolution 1280×720 and frequency 60Hz, these are the settings;

hdmi_safe=1

hdmi_group=2

hdmi_mode=85

Eg 2. when connected to a TV through HDMI with resolution 640x480 and frequency 60Hz. Since the TV have a standard HDMI connector, hdmi_safe will be commented out. These are the settings;

#hdmi_safe=1

hdmi_group=2

hdmi_mode=4


Reference: Raspberry site

Blog Archive