PostgreSQLサーバの構築

#構築環境
Iaas：AWS EC2
OS：RHEL-7.6_HVM_GA-20190128-x86_64-0-Hourly2-GP2（コミュニティ AMI）
DB：PostgreSQL 11.5

#構築方針について
PostgreSQLをインストールする方法はyumコマンドやソースからインストール等、複数の方法があります。
今回はバージョンの選択が容易なソースからのインストールを実施します。

#サーバ構築に必要なソフトウェアパッケージをインストール
ソースからのインストールする場合、CコンパイラやGNU Readlineライブラリなどが必要になるのでインストールしていきます。
インストールされていない場合、後続で行うconfigureスクリプトの実行でエラーになります。

###１．gccをインストール
Cコンパイラが無い場合、gccをインストールします。

```
$ sudo yum install gcc -y
```

###２．readline-develをインストール
readlineライブラリが無い場合、readline-develをインストールします。

```
$ sudo yum install readline-devel -y
```

###３．zlib-develをインストール
zlibライブラリが無い場合、zlib-develをインストールします。

```
$ sudo yum install zlib-devel -y
```

###4．systemd-develをインストール（任意）
SystemdのユニットファイルでType=notifyにしたい場合、systemd-develをインストールする。
後続で実行するconfigureスクリプトに「--with-libxml」オプションを付加した場合は必要になります。

```
sudo yum install systemd-devel -y
```

###５．libxml2-develをインストール（任意）
libxmlバージョン2.6.23以降が使用出来ない場合、libxml2-develをインストールします。
後続で実行するconfigureスクリプトに「--with-libxml」オプションを付加した場合は必要になります。

```
$ sudo yum install libxml2-devel -y
```

#PostgreSQL管理用のユーザーを作成
データベースクラスタの新規作成(initdb)はrootで実行出来ないため、専用のユーザーを作成します。

###１．ユーザーを作成
ユーザーをrootに切り替え。useraddコマンドでユーザーを追加し、passwdコマンドでユーザーのパスワードを指定します。

```
$ sudo su -
# useradd postgres
# passwd postgres
Changing password for user postgres.
New password: 
BAD PASSWORD: The password contains the user name in some form
Retype new password: 
passwd: all authentication tokens updated successfully.
```

###２．sudoの実行権限を付与
作成したpostgresユーザーでroot権限実行(sudo)が出来るように設定します。

```
# visudo
以下を追記する
postgres ALL=(ALL)      NOPASSWD: ALL
```

###３．以降はpostgresユーザーに切り替え作業をすすめる
ユーザーをrootから元に戻し、postgresユーザーに切り替えます。

```
# exit 
$ su - postgres
パスワード:
```

#tarファイルを入手
###１．インストールしたいバージョンのtarファイルのURLを確認する
下記リンクでバージョン別にtarファイルをダウンロード出来ます。
インストールしたいバージョンのtarファイルのリンクをブラウザの開発者ツール等を用いてURLを取得しておきます。

■tarファイルをダウンロード出来るサイト
https://www.postgresql.org/ftp/source/
GUI環境のLinuxやWindows環境にインストールしたい場合はこのサイトから直接インストールすればOK。
今回はCUIのLinux環境から直接ダウンロードしたいのでtarファイルのURLを確認のみ行います。

###２．tarファイルをダウンロード
curlコマンドでtarファイルをダウンロードします。

```
$ curl -OL https://ftp.postgresql.org/pub/source/v11.5/postgresql-11.5.tar.gz
```

#インストール
###１．tarファイルの解凍・配置
圧縮されたtarファイルを解凍し、インストール先の階層に配置します。

```
$ tar xzvf postgresql-11.5.tar.gz
$ sudo mv postgresql-11.5 /usr/local/pgsql
```

###２．インストール先ディレクトリの所有者を変更
PostgreSQLはrootで実行出来ず、任意のユーザーで実行することになります。
そのため、サーバがinitdbによって作成されたファイルやディレクトリにアクセスして読書き出来るように十分な権限設定が必要です。
今回はサーバプロセスの所有者となるpostgresをディレクトリの所有者として設定します。

```
$ sudo chown -R postgres:postgres /usr/local/pgsql
```

###３．configureスクリプトを実行とコンパイル
configureスクリプトを実行し、makeコマンドでコンパイルします。
ただし、ソースからインストールする場合、インストールされていることが前提のソフトウェアがあります。
もし、インストールされていない場合は「sudo ./configure」でエラーとなるので、[必要なソフトウェア](#サーバ構築に必要なソフトウェアパッケージをインストール)をインストールしましょう。

今回はPostgreSQLの起動・停止にSystemdを使用します。
SystemdのユニットファイルでType=notifyにしたいので「--with-systemd」オプションを付与します。

```
$ cd /usr/local/pgsql
$ sudo ./configure --with-systemd
$ make world
$ make check
```

###４．インストール
makeコマンドでインストールします。

```
$ make install-world
```

###５．インストール実行結果の確認
インストール先となる「/usr/local/pgsql」内に「bin」、「include」、「lib」、「share」ディレクトリが作成されていればインストール成功です。

```
$ ls -la /usr/local/pgsql
・
・
drwxrwxr-x.  2 postgres postgres   4096 Feb  7 04:24 bin
・
・
drwxrwxr-x.  6 postgres postgres   4096 Feb  7 04:24 include
・
・
drwxrwxr-x.  4 postgres postgres   4096 Feb  7 04:24 lib
・
・
drwxrwxr-x.  8 postgres postgres   4096 Feb  7 04:24 share

```

###６．環境変数を設定
PostgreSQL関連のコマンドやマニュアル、共用ライブラリ、DBのデータをそれぞれ環境変数として設定します。
※念の為、修正前の状態をcpコマンドでバックアップを取っておきます。

```
$ cd /home/postgres/
$ sudo cp -p .bash_profile .bash_profile_bkYYYYMMDD

$ vi .bash_profile
#以下を追記
##YYYY/MM/DD add
export PATH=/usr/local/pgsql/bin:$PATH
export MANPATH=/usr/local/pgsql/man:$MANPATH
export LD_LIBRARY_PATH=/usr/local/pgsql/lib
export PGDATA=/usr/local/pgsql/data
```

.bash_profileファイルを修正したらsourceコマンドで環境変数の読込みを最新化します。

```
source $HOME/.bash_profile
```

###７．設定の確認
psqlコマンドでPostgreSQLのバージョンを確認します。

```
$ psql --version
psql (PostgreSQL) 11.5
```

whichコマンドでpsqlコマンドで実行されるプログラムの実態が今回インストールしたものであるか確認します。

```
which psql
/usr/local/pgsql/bin/psql
```

各種PATHにPostgreSQLの設定が反映されているか確認します。

```
$ env | grep PATH
MANPATH=/usr/local/pgsql/man:
LD_LIBRARY_PATH=/usr/local/pgsql/lib
PATH=/usr/local/pgsql/bin:/usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/postgres/.local/bin:/home/postgres/bin:/home/postgres/.local/bin:/home/postgres/bin
```

PGDATAの設定が反映されているか確認します。

```
$　env | grep PGDATA
PGDATA=/usr/local/pgsql/data
```

#データベースクラスタの作成

###１．dataディレクトリを作成
データベースクラスタのデータ格納先となるディレクトリを作成します。
※既にディレクトリが存在する場合、ディレクトリ内は初期化しておきます。

```
$ mkdir /usr/local/pgsql/data
$ rmdir /usr/local/pgsql/data/* 
```

###２．データベースクラスタを作成
今回はinitdbで文字コードとロケールを指定します。
文字コードはUTF-8、ロケールはlinux環境の設定に準拠するため、オプションを「--encoding=UTF8 --no-locale」にします。
※PostgreSQLではサーバとクライアントでそれぞれ文字コードを指定しますが、サーバ側にSJISはサポートされていません。

```
$ initdb --encoding=UTF8 --no-locale
・
・
Success. You can now start the database server using:

    pg_ctl -D /usr/local/pgsql/data -l logfile start
```

initdb後、「data」ディレクトリに各ファイルが生成されてることを確認します。

```
ls -la /usr/local/pgsql/data
total 52
drwx------. 19 postgres postgres  4096 Jan 17 03:43 .
drwxr-xr-x.  7 postgres postgres    68 Jan 17 03:31 ..
drwx------.  5 postgres postgres    41 Jan 17 03:43 base
drwx------.  2 postgres postgres  4096 Jan 17 03:43 global
drwx------.  2 postgres postgres     6 Jan 17 03:43 pg_commit_ts
・
・
・
```

#設定値の変更
###１．postgresql.conf
外部からPostgreSQLに接続出来るようにlisten_addressesを設定します。
ただし、「localhost」に指定するとlocalhostでは接続出来ますが、IPアドレス指定では接続出来なくなり、
逆にプライベートIPアドレスを指定するとIPアドレスでは接続出来ますが、localhostでは接続出来なくなります。
そのため、両方でも接続出来るように今回は「*」を設定します。

```
$ cd /usr/local/pgsql/data/
$ sudo cp -p postgresql.conf postgresql.conf.bkYYYYMMDD
$ vi postgresql.conf

listen_addresses = '*'
```


###２．pg_hba.conf
接続してくるクライアント情報を設定します。
この設定でPostgreSQLに接続してくるクライアントの接続可否を制御できます。

```
$ cd /usr/local/pgsql/data/
$ sudo cp -p pg_hba.conf pg_hba.conf.bkYYYYMMDD
$ vi pg_hba.conf

```

「replication privilege.」の下にPostgreSQLに接続する端末の情報を設定します。

※例では全IP許可

```
host  all  all  0.0.0.0/0    trust
```

#PostgreSQLの起動・停止のため、Systemdを設定
pg_ctlコマンドの「pg_ctl start -w」「pg_ctl stop」等でPostgreSQLの単純な起動・停止は行なえますが、サーバ起動と同時にPostgreSQLも自動起動するようしたいのでSystemdで管理するように設定します。

### １．ユニット定義ファイルを作成
PostgreSQL管理用にユニットファイルを作成します。

```
$ sudo vi /etc/systemd/system/postgresql.service

[Unit]
Description=PostgreSQL database server
Documentation=man:postgres(1)

[Service]
Type=notify
User=postgres
ExecStart=/usr/local/pgsql/bin/postgres -D /usr/local/pgsql/data
ExecReload=/bin/kill -HUP $MAINPID
KillMode=mixed
KillSignal=SIGINT
TimeoutSec=0

[Install]
WantedBy=multi-user.target
```

### ２．サーバを起動時にPostgreSQLが自動起動されるように設定

```
$ sudo systemctl enable postgresql
```

### ３．Systemdでの停止と起動
systemctlコマンドで起動します。

```
$ sudo systemctl start postgresql
```

ステータスを確認し、active (running)となっていればOKです。

```
$ sudo systemctl status postgresql
● postgresql.service - PostgreSQL database server
   Loaded: loaded (/etc/systemd/system/postgresql.service; enabled; vendor preset: disabled)
   Active: active (running) since Sat 2021-02-13 03:05:59 UTC; 8s ago
     Docs: man:postgres(1)
 Main PID: 18818 (postgres)
   CGroup: /system.slice/postgresql.service
           ├─18818 /usr/local/pgsql/bin/postgres -D /usr/local/pgsql/data
           ├─18820 postgres: checkpointer   
           ├─18821 postgres: background writer   
           ├─18822 postgres: walwriter   
           ├─18823 postgres: autovacuum launcher   
           ├─18824 postgres: stats collector   
           └─18825 postgres: logical replication launcher 
```

停止したいときはstopで停止します。

```
$ sudo systemctl stop postgresql
```

もし、ユニットファイルの内容を変更した場合、設定ファイルの再読込を実施してから操作します。

```
$ sudo systemctl daemon-reload
```


#データベース作成
実際にアプリで使用するデータベースを作成します。
今回は例として
データベース名：db_sample
ロール（ユーザー）：sampleuser
スキーマ名：sampleschema
とします。

###１．データベースを作成
psqlコマンドでPostreSQLに接続し、データベースを作成します。

```
$ psql
postgres=# CREATE DATABASE db_sample;
CREATE DATABASE
```

###２．ロール作成
\cでデータベースを選択し、ロールを作成します。

```
postgres=# \c db_sample
db_sample=# CREATE ROLE sampleuser WITH LOGIN PASSWORD 'sample';
```

###３．スキーマ作成
作成したロールを所有者にしてスキーマを作成します。

```
db_sample=# CREATE SCHEMA sampleschema AUTHORIZATION sampleuser;
```

###４．ロールのデフォルトスキーマを設定
sampleuserでPostgreSQLに接続した際、sampleschemaを向くようにデフォルトスキーマを指定します。

```
db_sample=# ALTER ROLE sampleuser SET search_path = "sampleschema";
```

###５．作成したロールでの接続確認
作成したロールで接続し直し、カレントスキーマに指定したスキーマを向いていればOKです。

```
db_sample=# \q
$ psql -h localhost -U sampleuser -d db_sample
db_sample=> SELECT current_schema();
 current_schema 
----------------
 sampleschema
(1 row)

```

#おわりに
サーバ構築に必要な作業は完了しました。
あとはcreate table等で必要なテーブルやデータを作成していきましょう。

#参考文献
https://www.postgresql.jp/document/11/html/installation.html