Tuesday, February 6, 2018

PostgreSQL Replication using SSL


Ohohohoh!!! I can set up the replication using SSL That's Cool. 
Let's Do it then what we are waiting for ??????


What is SSL and why it is used?

SSL stands for Secure Sockets Layer and, in short, it's the standard technology for keeping a connection secure and protecting any sensitive data that is being sent between two servers, preventing criminals from reading and modifying any information transferred.
The two systems can be a server and a client or server to server.
Installed PostgreSQL-9.6 from the pgdg repo on Centos7.

First, create the certificates on the Master.

Create Directory for SSL

mkdir /var/lib/pgsql/9.6/data/ssl
cd /var/lib/pgsql/9.6/data/ssl

openssl req -new -text -out server.req
openssl rsa -in privkey.pem -out server.key
rm privkey.pem
openssl req -x509 -in server.req -text -key server.key -out server.crt
chmod og-rwx server.key
chown -R postgres  /var/lib/pgsql/9.6/data/ssl

Always it is recommended to create replication user for replication.

psql -c "create role replica with login replication password 'replication';"

Now set parameters in postgresql.conf and add replication entry in pg_hba.conf on Master.

postgresql.conf :

ssl = on
ssl_cert_file = '/var/lib/pgsql/9.6/data/ssl/server.crt'
ssl_key_file = '/var/lib/pgsql/9.6/data/ssl/server.key'
wal_level = hot_standby 
archive_mode='on'
archive_command='cp %p /var/lib/pgsql/9.6/archive/%f'
max_wal_senders = 5 
wal_keep_segments = 150
hot_standby_feedback = on
hot_standby = on           #this parameter will not effect on Master. It is for standby server.

pg_hba.conf

hostssl replication     replica        192.168.56.102/32          md5

Now restart the Master and take pg_basebackup to setup the replication.

systemctl restart postgresql-9.6

Backup :

pg_basebackup -D /var/lib/pgsql/9.6/replica -U replica -v -h 192.168.56.102 -R -xP

Start the replica cluster.

pg_ctl -D /var/lib/pgsql/9.6/replica/ start

recovery.conf  of replica cluster

standby_mode = 'on'
primary_conninfo = 'user=replica password=replication host=192.168.56.102 port=5432 sslmode=prefer sslcompression=1 krbsrvname=postgres'
restore_command='cp /var/lib/pgsql/9.6/archive/%f %p'

Here is the status of replicaion :


-[ RECORD 1 ]----+------------------------------
pid              | 8054
usesysid         | 16449
usename          | replica
application_name | walreceiver
client_addr      | 192.168.56.102
client_hostname  |
client_port      | 59200
backend_start    | 2018-02-01 00:30:16.148848-05
backend_xmin     |
state            | streaming
sent_location    | 0/5013A98
write_location   | 0/5013A98
flush_location   | 0/5013A98
replay_location  | 0/5013A98
sync_priority    | 0
sync_state       | async


Now let's try to connect to Master using replica user and check if certificates are been used or not?

Create extension sslinfo; 

postgres=# create extension sslinfo ;
CREATE EXTENSION
postgres=# \dx+ sslinfo
   Objects in extension "sslinfo"
         Object Description
------------------------------------
 function ssl_cipher()
 function ssl_client_cert_present()
 function ssl_client_dn()
 function ssl_client_dn_field(text)
 function ssl_client_serial()
 function ssl_extension_info()
 function ssl_issuer_dn()
 function ssl_issuer_field(text)
 function ssl_is_used()
 function ssl_version()
(10 rows)

Now connect using replica user over SSL.

psql (9.6.6)
SSL connection (protocol: TLSv1.2, cipher: ECDHE-RSA-AES256-GCM-SHA384, bits: 256, compression: off)
Type "help" for help.

postgres=> select ssl_is_used();
 ssl_is_used
-------------
 t
(1 row)

postgres=> \q



WOW!!!! Great Replicaion setup is ready and it is Secure .....!!


Thursday, December 21, 2017

Cascaded Replication using pglogical on different version of PostgreSQL

I am going to show you how to configure cascaded pglogical replication on a different version of PostgreSQL.

I have installed three version of PostgreSQL (i.e 9.5,9.6,10)
Les install pglogical for all the version of PostgreSQL.

I did set up on CENTOS 7.2.

Here is the link to Download and install pglogical:

yum install http://packages.2ndquadrant.com/pglogical/yum-repo-rpms/pglogical-rhel-1.0-3.noarch.rpm
PostgreSQL 9.5: yum install postgresql95-pglogical
PostgreSQL 9.6: yum install postgresql96-pglogical
PostgreSQL 10 : yum install postgresql10-pglogical

Here  PostgreSQL 9.5 is on 5432 port,9.6 is on 5433,port,10 is on 5434 port.
Add below parameters in postgresql.conf for all versions of PostgreSQL and add replication entry for servers(I am doing it on Local).

postgresql.conf

wal_level = 'logical'
max_worker_processes = 10   # one per database needed on provider node
                            # one per node needed on subscriber node
max_replication_slots = 10  # one per node needed on provider node
max_wal_senders = 10        # one per node needed on provider node
shared_preload_libraries = 'pglogical'

pg_hba.conf

local   replication     postgres                                trust
host    replication     postgres        127.0.0.1/32            trust

Now Let's create a pglogical database and in it create a pglogical extension on all versions.

create database pglogical;
\c pglogical
create extension pglogical;

5432 port will be the acting as provider node to 5433.

pglogical:provider :5432

select pglogical.create_node 
( 
    node_name := 'provider', 
    dsn := 'host=127.0.0.1 port=5432 dbname=pglogical' 
); 


ex: 

pglogical=# select pglogical.create_node 
pglogical-# ( 
pglogical(#     node_name := 'provider', 
pglogical(#     dsn := 'host=127.0.0.1 port=5432 dbname=pglogical' 
pglogical(# ); 
 create_node 
-------------
  3171898924
(1 row)

Now add the all tables from public schema to replication set. If you have sequences then you can add those as well to the same replication set.
Note: there should be pk on tables otherwise it won't allow the user to create replication set.

select pglogical.replication_set_add_all_tables('default', array['public']); 

ex:

pglogical=# select pglogical.replication_set_add_all_tables('default', array['public']); 
 replication_set_add_all_tables 
--------------------------------
 t
(1 row)

pglogical:subscriber and provider:5433

select pglogical.create_node( 
    node_name := 'subscriber', 
    dsn := 'host=127.0.0.1 port=5433 dbname=pglogical' 
); 

ex:

pglogical=# select pglogical.create_node( 
pglogical(#     node_name := 'subscriber', 
pglogical(#     dsn := 'host=127.0.0.1 port=5433 dbname=pglogical' 
pglogical(# ); 
 create_node 
-------------
  2941155235
(1 row)

Here on 5433, you have to create replication set same as 5432 because 5433 is also acting as a provider to 5434.

select pglogical.replication_set_add_all_tables('default', array['public']);

ex: 

pglogical=# select pglogical.replication_set_add_all_tables('default', array['public']); 
 replication_set_add_all_tables 
--------------------------------
 t
(1 row)


As 5433 is subscriber there should be subscription between 5432 and 5433. 


SELECT pglogical.create_subscription(
    subscription_name := 'subscription',
    provider_dsn := 'host=127.0.0.1 port=5432 dbname=pglogical');

ex:

 pglogical=# SELECT pglogical.create_subscription(
    subscription_name := 'subscription',
    provider_dsn := 'host=127.0.0.1 port=5432 dbname=pglogical');
 create_subscription 
---------------------
          2875150205
(1 row)

Lets check the data in 5432,5433,5434 .

On 5432: 

pglogical=# show port;
 port 
------
 5432
(1 row)

pglogical=# insert into test1 values (generate_series(1,15),'cascade');
INSERT 0 15
pglogical=# 
pglogical=# 
pglogical=# select count(*) from test1 ;
 count 
-------
    15
(1 row)

On 5433 :

pglogical=# show port;
 port 
------
 5433
(1 row)

pglogical=# select count(*) from test1 ;
 count 
-------
    15
(1 row)

pglogical=# 

On 5434:

pglogical=# show port;
 port 
------
 5434
(1 row)

pglogical=# select count(*) from test1 ;
 count 
-------
     0
(1 row)


On 5434 no data because of replication not yet setup between 5433 and 5434.


5434 port will be the acting as a subscriber to 5433.

pglogical:only subscriber:5434

select pglogical.create_node( 
    node_name := 'subscriber1', 
    dsn := 'host=127.0.0.1 port=5434 dbname=pglogical' 
); 

ex: 

pglogical=# select pglogical.create_node( 
pglogical(#     node_name := 'subscriber1', 
pglogical(#     dsn := 'host=127.0.0.1 port=5434 dbname=pglogical' 
pglogical(# ); 
 create_node 
-------------
   330520249
(1 row)

SELECT pglogical.create_subscription(
    subscription_name := 'subscription2',
    provider_dsn := 'host=127.0.0.1 port=5433 dbname=pglogical');

ex: 

pglogical=# SELECT pglogical.create_subscription(
    subscription_name := 'subscription2',
    provider_dsn := 'host=127.0.0.1 port=5433 dbname=pglogical');
 create_subscription 
---------------------
          1871150101
(1 row)


Now let's check the count on 5434 whether 15 records got replicated or not?

On 5434 :

pglogical=# show port ;
 port 
------
 5434
(1 row)

pglogical=# select count(*) from test1 ;
 count 
-------
    15
(1 row)


There are various options in pglogical like you can do a table, column, row level replication.

Sunday, March 13, 2016

Backup and Incremental Backup from Slave Server using pgbarman

>>pgespresso <<

pgespresso extension (https://github.com/2ndquadrant-it/pgespresso) is used for enabling stop and start backup mode with pgespresso_start_backup and pgespresso_stop_backup on Slave server.This is extra module or extension which has to be create on master and slave.
pgespresso_start_backup (label, fast)
pgespresso_start_backup is used to start taking a concurrent backup. It returns a backup label file that the user is responsible for placing in the $PGDATA of the backup AFTER the backup has been taken. The label file must not be written to the data directory of the server from which the backup is taken because this type of backup presumes and allows that more than one backup may be in progress at any one time. The label file contains the user-supplied label string (typically this would be used to tell where the backup dump will be stored) and the starting time and starting WAL location for the dump.

pgespresso_stop_backup (label_content)
pgespresso_stop_backup is used to stop a concurrent backup. It returns the XLOG filename containing end of backup location, combining both the TLI and the end location.

pgespresso_abort_backup ()
pgespresso_abort_backup aborts a running concurrent backup.


Step1:Install and configure Postgresql9.5 and pgespresso

PostgreSQL 9.4 link : https://ftp.postgresql.org/pub/source/v9.4.0/postgresql-9.4.0.tar.bz2
pgespresso link         : https://github.com/2ndquadrant-it/pgespresso


Export pg env variables and the start the Setup of pgespresso.

[root@localhost tmp]# unzip master
[root@localhost tmp]# cd pgespresso-master/
[root@localhost pgespresso-master]# make
make: Nothing to be done for `all'.
[root@localhost pgespresso-master]# make install
/bin/mkdir -p '/opt/Postgres94/share/postgresql/extension'
/bin/mkdir -p '/opt/Postgres94/share/postgresql/extension'
/bin/mkdir -p '/opt/Postgres94/lib/postgresql'
/usr/bin/install -c -m 644 pgespresso.control '/opt/Postgres94/share/postgresql/extension/'
/usr/bin/install -c -m 644 pgespresso--1.0.sql '/opt/Postgres94/share/postgresql/extension/'
/usr/bin/install -c -m 755  pgespresso.so '/opt/Postgres94/lib/postgresql/'

Step2:Install prerequisite before installing pgbarman below are necessary prerequisite.

Python 2.6 or 2.7
Python modules:
argcomplete
argh >= 0.21.2
psycopg2
python-dateutil < 2.0 (since version 2.0 requires python3)
distribute (optional)
PostgreSQL >= 8.3
rsync >= 3.0.4

 then configure and install pgbarman

pgbarman link  :  https://sourceforge.net/projects/pgbarman/files/1.5.1/barman-1.5.1.tar.gz/download

Step3: Set the parameters in barman.conf and provide conninfo of slave server (In example slave is running on 5433 port) as shown below

[barman]
barman_home = /home/barman
barman_user = barman
log_file = /home/barman/barman.log
compression = gzip
reuse_backup = link
retention_policy = REDUNDANCY 4
bandwidth_limit = 4000
network_compression = true
backup_options = concurrent_backup
last_backup_maximum_age = 1 DAY
[main]
description =  "PostgreSQL Database Hot Standby"
ssh_command = ssh postgres@127.0.0.1
conninfo = host=127.0.0.1 user=postgres port=5433   --Slave details
minimum_redundancy = 1

Step4:Make passwordless authentication between master,slave,barman servers.

Step5:Set the parametes in postgresql.conf on master as given below

archive_mode = on
wal_level = hot_standby
archive_command = 'rsync -a %p barman@127.0.0.1:/home/barman/main/incoming/%f'

then restart the master , setup streaming replication(slave is on port 5433) and created extension pgespresso on master.

Step6: Now Check wether barman can connect to postgres or not .

[barman@localhost ~]$ barman check main
Server main:
PostgreSQL: OK
wal_level: OK
directories: OK
retention policy settings: OK
backup maximum age: OK (no last_backup_maximum_age provided)
compression settings: OK
failed backups: OK (there are 0 failed backups)
minimum redundancy requirements: FAILED (have 0 backups, expected at least 1)
ssh: OK (PostgreSQL server)
pgespresso extension: OK
archive_mode: OK
archive_command: OK
continuous archiving: OK
archiver errors: OK

Note : here 'main' is name for slave "postgres instance" which is declared in barman.conf.


Step7 : Below command gives the information of the postgres server

 [barman@localhost ~]$ barman show-server  main
Server main:
active: True
archive_command: rsync -a %p barman@127.0.0.1:/home/barman/main/incoming/%f
archive_mode: on
archived_count: 0
archiver: True
backup_directory: /home/barman/main
backup_method: rsync
backup_options: BackupOptions(['concurrent_backup'])
bandwidth_limit: 4000
basebackup_retry_sleep: 30
basebackup_retry_times: 1
basebackups_directory: /home/barman/main/base
compression: gzip
config_file: /home/postgres/data2/postgresql.conf
conninfo: host=127.0.0.1 user=postgres dbname=postgres port=5433
current_archived_wals_per_second: 0.0
current_size: 828503628
current_xlog: None
custom_compression_filter: None
custom_decompression_filter: None
data_directory: /home/postgres/data2
description: Main PostgreSQL Database
disabled: False
errors_directory: /home/barman/main/errors


Step8 :  Take first full backup of main using barman

[barman@localhost ~]$ barman backup main
Starting backup for server main in /home/barman/main/base/20160227T171537
Backup start at xlog location: 0/8F0000C8 (00000001000000000000008F, 000000C8)
This is the first backup for server main
Copying files.
Copy done.
Asking PostgreSQL server to finalize the backup.
Backup size: 790.2 MiB. Actual size on disk: 790.2 MiB (-0.00% deduplication ratio).
Backup end at xlog location: 0/90000000 (00000001000000000000008F, 00000000)
Backup completed
Processing xlog segments from file archival for main
00000001000000000000008E


Step9: Create database and use pgbench to load data then take  incremental backup of main using barman.

Adding data to postgres :
postgres=# create database test;
CREATE DATABASE
postgres=# \q
[postgres@localhost ~]$ pgbench -i -d test
NOTICE:  table "pgbench_history" does not exist, skipping
NOTICE:  table "pgbench_tellers" does not exist, skipping
NOTICE:  table "pgbench_accounts" does not exist, skipping
NOTICE:  table "pgbench_branches" does not exist, skipping
creating tables...
100000 of 100000 tuples (100%) done (elapsed 0.24 s, remaining 0.00 s).
vacuum...
set primary keys...
done.
[postgres@localhost ~]$ psql -d test
psql (9.4.6)
Type "help" for help.

test=# \dt
              List of relations
 Schema |       Name       | Type  |  Owner  
--------+------------------+-------+----------
 public | pgbench_accounts | table | postgres
 public | pgbench_branches | table | postgres
 public | pgbench_history  | table | postgres
 public | pgbench_tellers  | table | postgres
(4 rows)

test=#


Now take incremental backup using barman :

[barman@localhost ~]$ barman backup --reuse=link main
Starting backup for server main in /home/barman/main/base/20160227T172458
Backup start at xlog location: 0/8F012DE8 (00000001000000000000008F, 00012DE8)
Copying files.
Copy done.
Asking PostgreSQL server to finalize the backup.
Backup size: 42.4 MiB. Actual size on disk: 1.3 MiB (-96.94% deduplication ratio).
Backup end at xlog location: 0/90000000 (00000001000000000000008F, 00000000)
Backup completed

Note :  --reuse= link is used to link the main full backup . This will backup only modified or changed files from main(postgres) .

Step10: To list out the backus follow below command

[barman@localhost ~]$ barman list-backup main
main 20160227T172458 - Sat Feb 27 17:25:02 2016 - Size: 42.4 MiB - WAL Size: 0 B
main 20160227T171537 - Sat Feb 27 17:19:04 2016 - Size: 790.2 MiB - WAL Size: 0 B

There are 2 backups listed .

Step11: Now lets recover from backup

[barman@localhost ~]$ barman recover main 20160227T172458 /tmp/recover
Processing xlog segments from file archival for main
000000010000000000000093
000000010000000000000094
000000010000000000000095
000000010000000000000096
000000010000000000000097
000000010000000000000098
000000010000000000000099
Starting local restore for server main using backup 20160227T172458
Destination directory: /tmp/recover
Copying the base backup.
Copying required WAL segments.
Generating archive status files
Identify dangerous settings in destination directory.

IMPORTANT
These settings have been modified to prevent data losses
postgresql.conf line 207: archive_command = false
Your PostgreSQL server has been successfully prepared for recovery!

Backup is restored at location /tmp/recover and while recovering user have to give latest backup ID
"barman recover main latest_Backup_ID /tmp/recover"

Step12: Change owner of recover instance from barman to postgres.

[root@localhost ~]# chown -R postgres:postgres /tmp/recover
[root@localhost ~]# ll /tmp/recover/
total 152
-rw-rw-r--. 1 postgres postgres   218 Feb 27 17:25 backup_label
-rw-------. 1 postgres postgres   206 Feb 27 14:06 backup_label.old
drwx------. 6 postgres postgres  4096 Feb 27 16:21 base
drwx------. 2 postgres postgres  4096 Feb 27 17:24 global
drwx------. 2 postgres postgres  4096 Feb 27 14:06 pg_clog
drwx------. 2 postgres postgres  4096 Feb 27 14:06 pg_dynshmem
-rw-------. 1 postgres postgres  4465 Feb 27 14:06 pg_hba.conf
-rw-------. 1 postgres postgres  1636 Feb 27 14:06 pg_ident.conf
drwx------. 2 postgres postgres  4096 Feb 27 17:11 pg_log
drwx------. 4 postgres postgres  4096 Feb 27 14:06 pg_logical
drwx------. 4 postgres postgres  4096 Feb 27 14:06 pg_multixact
drwx------. 2 postgres postgres  4096 Feb 27 17:11 pg_notify
drwx------. 2 postgres postgres  4096 Feb 27 14:06 pg_replslot
drwx------. 2 postgres postgres  4096 Feb 27 14:06 pg_serial
drwx------. 2 postgres postgres  4096 Feb 27 14:06 pg_snapshots
drwx------. 2 postgres postgres  4096 Feb 27 17:11 pg_stat
drwx------. 2 postgres postgres  4096 Feb 27 17:24 pg_stat_tmp
drwx------. 2 postgres postgres  4096 Feb 27 14:06 pg_subtrans
drwx------. 2 postgres postgres  4096 Feb 27 14:06 pg_tblspc
drwx------. 2 postgres postgres  4096 Feb 27 14:06 pg_twophase
-rw-------. 1 postgres postgres     4 Feb 27 14:06 PG_VERSION
drwx------. 3 postgres postgres  4096 Feb 27 17:27 pg_xlog
-rw-------. 1 postgres postgres    88 Feb 27 17:27 postgresql.auto.conf
-rw-------. 1 postgres postgres    88 Feb 27 14:06 postgresql.auto.conf.origin
-rw-------. 1 postgres postgres 21384 Feb 27 17:27 postgresql.conf
-rw-------. 1 postgres postgres 21351 Feb 27 17:10 postgresql.conf.origin
-rw-------. 1 postgres postgres    35 Feb 27 17:11 postmaster.opts


Step13: start recovered cluster using pg_ctl

[postgres@localhost ~]$ psql -p 5434
psql (9.4.6)
Type "help" for help.

postgres=# show data_directory ;
 data_directory
----------------
 /tmp/recover
(1 row)

postgres=# \c test
You are now connected to database "test" as user "postgres".
test=# \dt
              List of relations
 Schema |       Name       | Type  |  Owner  
--------+------------------+-------+----------
 public | pgbench_accounts | table | postgres
 public | pgbench_branches | table | postgres
 public | pgbench_history  | table | postgres
 public | pgbench_tellers  | table | postgres
(4 rows)

test=#


              *************************************


Observed activity on slave and found that barman was taking backup from slave below is evidence :

postgres=# show port;
 port
------
 5433
(1 row)

postgres=# select pg_is_in_recovery();
 pg_is_in_recovery
-------------------
 t
(1 row)

postgres=# select * from pg_stat_activity ;
 datid | datname  |  pid  | usesysid | usename  | application_name | client_addr | client_hostname | client_port |          backend_start           |            xact_start      
    |           query_start            |           state_change           | waiting | state  | backend_xid | backend_xmin |                                       query          
                         
-------+----------+-------+----------+----------+------------------+-------------+-----------------+-------------+----------------------------------+------------------------------
----+----------------------------------+----------------------------------+---------+--------+-------------+--------------+--------------------------------------------------------
---------------------------
 13003 | postgres | 97373 |       10 | postgres |                  | 127.0.0.1   |                 |       41877 | 2016-02-27 16:32:41.54456+05:30  | 2016-02-27 16:32:42.064071+05
:30 | 2016-02-27 16:32:42.064123+05:30 | 2016-02-27 16:32:42.064124+05:30 | f       | active |             |         1919 | SELECT pgespresso_start_backup('Barman backup main 2016
0227T163242',false), now()
 13003 | postgres | 95772 |       10 | postgres | psql             |             |                 |          -1 | 2016-02-27 16:28:57.001512+05:30 | 2016-02-27 16:32:47.167849+05
:30 | 2016-02-27 16:32:47.167849+05:30 | 2016-02-27 16:32:47.167853+05:30 | f       | active |             |         1919 | select * from pg_stat_activity ;
(2 rows)

postgres=# select * from pg_stat_activity ;
 datid | datname  |  pid  | usesysid | usename  | application_name | client_addr | client_hostname | client_port |          backend_start           |            xact_start      
    |           query_start            |           state_change           | waiting | state  | backend_xid | backend_xmin |                                       query          
                         
-------+----------+-------+----------+----------+------------------+-------------+-----------------+-------------+----------------------------------+------------------------------
----+----------------------------------+----------------------------------+---------+--------+-------------+--------------+--------------------------------------------------------
---------------------------
 13003 | postgres | 97373 |       10 | postgres |                  | 127.0.0.1   |                 |       41877 | 2016-02-27 16:32:41.54456+05:30  | 2016-02-27 16:32:42.064071+05
:30 | 2016-02-27 16:32:42.064123+05:30 | 2016-02-27 16:32:42.064124+05:30 | f       | active |             |         1919 | SELECT pgespresso_start_backup('Barman backup main 2016
0227T163242',false), now()
 13003 | postgres | 95772 |       10 | postgres | psql             |             |                 |          -1 | 2016-02-27 16:28:57.001512+05:30 | 2016-02-27 16:32:49.423868+05
:30 | 2016-02-27 16:32:49.423868+05:30 | 2016-02-27 16:32:49.423872+05:30 | f       | active |             |         1919 | select * from pg_stat_activity ;
(2 rows)




****************************

Thursday, March 10, 2016

Barman Installation and configuration


Barman (backup and recovery manager) is an administration tool for disaster recovery of PostgreSQL servers written in Python. Barman can perform remote backups of multiple servers in business critical environments, and helps DBAs during the recovery phase.
Barman’s most wanted features include: backup catalogues, incremental backup, retention policies, remote recovery, archiving and compression of WAL files and of backups.

Steps To Setup pgbarman:

Step 1 : Install PostgreSQL-9.4 or 9.5.

Download PostgreSQL from below link

https://ftp.postgresql.org/pub/source/v9.5.1/postgresql-9.5.1.tar.bz2

Step 2 : Download pgbarman from below link.

https://sourceforge.net/projects/pgbarman/files/1.5.1/barman-1.5.1.tar.gz/download

Step3: Install prerequisite before installing pgbarman below are necessary prerequisite.
  • Python 2.6 or 2.7
  • Python modules:
    • argcomplete
    • argh >= 0.21.2
    • psycopg2
    • python-dateutil < 2.0 (since version 2.0 requires python3)
    • distribute (optional)
  • PostgreSQL >= 8.3
  • rsync >= 3.0.4
Step4: untar the pgbarman file and install it as given below

    [root@localhost ~] tar -xvf barman-1.5.1.tar.gz
    [root@localhost ~] cd barman-1.5.1
    [root@localhost barman-1.5.1] python2.6 setup.py build
    [root@localhost barman-1.5.1] python2.6 setup.py install
Step5: copy barman.conf from doc to /etc/
    [root@localhost barman-1.5.1] cp doc/barman.conf /etc/
Step6: create user barman and change the owner of /etc/barman.conf
    [root@localhost barman-1.5.1]# chown -R barman:barman /etc/barman.conf
Step7: Make password less authentication between barman server and postgres server .
    [barman@localhost ~]$ ssh-keygen
    [barman@localhost ~]$ ssh-copy-id -i .ssh/id_rsa.pub postgres@127.0.0.1
Repeat above steps for postgres user.
    [root@localhost barman-1.5.1]# su - postgres
    [postgres@localhost ~]$ ssh-keygen
    [postgres@localhost ~]$ ssh-copy-id -i .ssh/id_rsa.pub barman@127.0.0.1
Step8: Edit barman.conf and edit below parameters in config file
    [barman]
    barman_home = /home/barman
    barman_user = barman
    log_file = /home/barman/barman.log
    compression = gzip
    reuse_backup = link
    minimum_redundancy = 1
    [main-db-server]
    description = "Main DB Server"
    ssh_command = ssh postgres@127.0.0.1
    conninfo = host=127.0.0.1 user=postgres

Step9: Edit the postgresql.conf and enable the archiving .

There is one last configuration to be made on the main, to switch on backup (or archive) mode. First, we need to locate the value of the incoming backup directory from the barman, switch to the user barman:
             
             su - barman

Run below command to locate the incoming backup directory:
     barman show-server main | grep incoming_wals_directory  
    incoming_wals_directory: /home/barman/main/incoming
    Note down the value of incoming_wals_directory in my setup it's /home/barman/main/incoming
Now switch to the user postgres on postgres server.
    Open the postgresql.conf and make the following changes to the file:
    Uncomment the wal_level parameter and set its value to archive.
    Uncomment the archive_mode parameter and set its value to on.
    Uncomment the archive_command parameter and set its value to 'rsync -a %p barman@127.0.0.1:/home/barman/main/incoming/%f'.
    Use the IP address of the Barman server. If you got a different value for incoming_wals_directory.

Step10: Restart postgres server or instance .

    pg_ctl -D /home/postgres/master restart

Step11: Now loging to the barman (su – barman) and check wether barman can connect to postgres or not .
    Barman check main
Note : here 'main' is name for postgres instance which is declared in barman.conf.

    [barman@localhost ~]$ barman check main
    Server main:
    PostgreSQL: OK
    archive_mode: OK
    wal_level: OK
    archive_command: OK
    continuous archiving: OK
    directories: OK
    retention policy settings: OK
    backup maximum age: OK (no last_backup_maximum_age provided)
    compression settings: OK
    minimum redundancy requirements: FAILED (have 0 backups, expected at least 1)
    ssh: OK (PostgreSQL server)
    not in recovery: OK
Step12 : Below command gives the information of the postgres server
    [barman@localhost ~]$ barman show-server main
    Server main:
    active: True
    archive_command: false
    archive_mode: on
    archived_count: 0
    backup_directory: /home/barman/main
    backup_options: BackupOptions(['exclusive_backup'])
    bandwidth_limit: None
    basebackup_retry_sleep: 30
    basebackup_retry_times: 0
    basebackups_directory: /home/barman/main/base
    compression: None
    config_file: /home/postgres/data/postgresql.conf
    conninfo: host=127.0.0.1 user=postgres port=5432
    copy_method: rsync
    current_archived_wals_per_second: 0.0
    current_xlog: 000000010000000000000043
    custom_compression_filter: None
    custom_decompression_filter: None
    data_directory: /home/postgres/data
    description: Main PostgreSQL Database
    disabled: False
    failed_count: 0
Step13 : Take first full backup of main using barman
    [barman@localhost ~]$ barman backup main
    Starting backup for server main in /home/barman/main/base/20160226T134115
    Backup start at xlog location: 0/48000028 (000000010000000000000048, 00000028)
    Copying files.
    Copy done.
    Asking PostgreSQL server to finalize the backup.
    Backup size: 480.8 MiB. Actual size on disk: 480.8 MiB (-0.00% deduplication ratio).
    Backup end at xlog location: 0/480000C0 (000000010000000000000048, 000000C0)
    Backup completed
    Processing xlog segments for main
    Older than first backup. Trashing file 000000010000000000000047 from server main
    000000010000000000000048
    000000010000000000000048.00000028.backup

Step14 : login to postgres and create database and tables, insert data into tables then take incremental backup of main using barman(login to barman).

Adding data to postgres :
    [postgres@localhost ~]$ psql
    psql (9.5.1)
    Type "help" for help.
    postgres=# \dt
    List of relations
    Schema | Name | Type | Owner
    --------+------------------+-------+----------
    public | pgbench_accounts | table | postgres
    public | pgbench_branches | table | postgres
    public | pgbench_history | table | postgres
    public | pgbench_tellers | table | postgres
    public | test | table | postgres
    public | test1 | table | postgres
    public | test2 | table | postgres
    public | test4 | table | postgres
    public | test5 | table | postgres
    public | test6 | table | postgres
    (10 rows)
    postgres=# create database test;
    CREATE DATABASE
    postgres=# \c test
    You are now connected to database "test" as user "postgres".
    test=# create table test1(i int);
    CREATE TABLE
    test=# create table test2(i int);
    CREATE TABLE
    test=# insert into test1 values (generate_series(1,1000));
    INSERT 0 1000
    test=# insert into test2 values (generate_series(1,1000));
    INSERT 0 1000
    test=# \q
Now take incremental backup using barman :
    [barman@localhost ~]$ barman backup --reuse=link main
    Starting backup for server main in /home/barman/main/base/20160226T134400
    Backup start at xlog location: 0/4A000028 (00000001000000000000004A, 00000028)
    Copying files.
    Copy done.
    Asking PostgreSQL server to finalize the backup.
    Backup size: 488.0 MiB. Actual size on disk: 7.3 MiB (-98.50% deduplication ratio).
    Backup end at xlog location: 0/4A0000C0 (00000001000000000000004A, 000000C0)
    Backup completed
    Processing xlog segments for main
    000000010000000000000049
    00000001000000000000004A
    00000001000000000000004A.00000028.backup
Note : --reuse= link is used to link the main full backup . This will backup only modified or changed files from main(postgres) .

Step15: To list out the backus follow below command

    [barman@localhost ~]$ barman list-backup main
    main 20160226T134400 - Fri Feb 26 13:44:07 2016 - Size: 504.0 MiB - WAL Size: 0 B
    main 20160226T134115 - Fri Feb 26 13:41:29 2016 - Size: 496.8 MiB - WAL Size: 32.0 MiB
    There are two backups listed 20160226T134400 is incremental backup and 20160226T134115 is full backup.
Step16: Now lets recover from backup
    [barman@localhost ~]$ barman recover main 20160226T134400 /tmp/data
    Starting local restore for server main using backup 20160226T134400
    Destination directory: /tmp/data
    Copying the base backup.
    Copying required WAL segments.
    Generating archive status files
    Identify dangerous settings in destination directory.
    IMPORTANT
    These settings have been modified to prevent data losses
    postgresql.conf line 209: archive_command = false
    Your PostgreSQL server has been successfully prepared for recovery!
Backup is restored at location /tmp/data and while recovering user have to give latest backup ID
    barman recover main latest /tmp/data
Step17: Now change owner of /tmp/data as 'postgres' and start the recovered instance.
    [root@localhost tmp]# chown -R postgres:postgres data
    [root@localhost data]# ls -lrth
    total 156K
    drwx------. 2 postgres postgres 4.0K Feb 26 08:11 pg_twophase
    drwx------. 2 postgres postgres 4.0K Feb 26 08:11 pg_tblspc
    drwx------. 2 postgres postgres 4.0K Feb 26 08:11 pg_snapshots
    drwx------. 2 postgres postgres 4.0K Feb 26 08:11 pg_serial
    drwx------. 2 postgres postgres 4.0K Feb 26 08:11 pg_replslot
    drwx------. 4 postgres postgres 4.0K Feb 26 08:11 pg_multixact
    drwx------. 4 postgres postgres 4.0K Feb 26 08:11 pg_logical
    drwx------. 2 postgres postgres 4.0K Feb 26 08:11 pg_dynshmem
    drwx------. 2 postgres postgres 4.0K Feb 26 08:11 pg_commit_ts
    -rw-------. 1 postgres postgres 4 Feb 26 08:11 PG_VERSION
    -rw-------. 1 postgres postgres 88 Feb 26 08:11 postgresql.auto.conf.origin
    drwx------. 2 postgres postgres 4.0K Feb 26 08:11 pg_subtrans
    -rw-------. 1 postgres postgres 1.6K Feb 26 08:11 pg_ident.conf
    drwx------. 2 postgres postgres 4.0K Feb 26 08:11 pg_clog
    -rw-------. 1 postgres postgres 4.4K Feb 26 08:27 pg_hba.conf
    -rw-------. 1 postgres postgres 22K Feb 26 13:40 postgresql.conf.origin
    drwx------. 2 postgres postgres 4.0K Feb 26 13:40 pg_stat
    drwx------. 7 postgres postgres 4.0K Feb 26 13:42 base
    -rw-------. 1 postgres postgres 224 Feb 26 13:44 backup_label.old
    -rw-------. 1 postgres postgres 22K Feb 26 13:45 postgresql.conf
    -rw-------. 1 postgres postgres 88 Feb 26 13:45 postgresql.auto.conf
    -rw-------. 1 postgres postgres 58 Feb 26 13:46 postmaster.pid
    drwx------. 2 postgres postgres 4.0K Feb 26 13:46 pg_notify
    -rw-------. 1 postgres postgres 40 Feb 26 13:46 postmaster.opts
    drwx------. 2 postgres postgres 4.0K Feb 26 13:46 pg_log
    drwx------. 3 postgres postgres 4.0K Feb 26 13:46 pg_xlog
    drwx------. 2 postgres postgres 4.0K Feb 26 13:46 global
    drwx------. 2 postgres postgres 4.0K Feb 26 13:53 pg_stat_tmp
    [root@localhost tmp]# su - postgres
    [postgres@localhost ~]$ pg_ctl -D master/ stop
    waiting for server to shut down.... done
    server stopped
    [postgres@localhost ~]$ pg_ctl -D /tmp/data/ start
    server starting
    [postgres@localhost ~]$ LOG: redirecting log output to logging collector process
    HINT: Future log output will appear in directory "pg_log".
psql to new instance which is recovered using barman at location /tmp/data.
    [postgres@localhost ~]$ psql
    psql (9.5.1)
    Type "help" for help.
    postgres=# \dt
    List of relations
    Schema | Name | Type | Owner
    --------+------------------+-------+----------
    public | pgbench_accounts | table | postgres
    public | pgbench_branches | table | postgres
    public | pgbench_history | table | postgres
    public | pgbench_tellers | table | postgres
    public | test | table | postgres
    public | test1 | table | postgres
    public | test2 | table | postgres
    public | test4 | table | postgres
    public | test5 | table | postgres
    public | test6 | table | postgres
    (10 rows)
    postgres=# \l+
    List of databases
    Name | Owner | Encoding | Collate | Ctype | Access privileges | Size | Tablespace |                Description
    -----------+----------+----------+-------------+-------------+-----------------------+---------+------------+--------------------------------------------
    postgres | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 | | 466 MB | pg_default | default administrative connection database
    template0 | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 | =c/postgres +| 7129 kB | pg_default | unmodifiable empty database
    | | | | | postgres=CTc/postgres | | |
    template1 | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 | =c/postgres +| 7129 kB | pg_default | default template for new databases
    | | | | | postgres=CTc/postgres | | |
    test | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 | | 7265 kB | pg_default |
    (4 rows)
    postgres=# \c test
    You are now connected to database "test" as user "postgres".
    test=# \dt
    List of relations
    Schema | Name | Type | Owner
    --------+-------+-------+----------
    public | test1 | table | postgres
    public | test2 | table | postgres
    (2 rows)
    test=# select count(*) from test1;
    count
    -------
    1000
    (1 row)
    test=# show data_directory ;
    data_directory
    ----------------
    /tmp/data
    (1 row)
    test=#
*******




Predefined roles introduced in PostgreSQL 14 reduced my responsibilities

  User management is a crucial role in the database, and the DBA should assign suitable permissions to users. For example, some users requir...