私家版　プリザンターをAmazon Linux2にインストールする

# はじめに
プリザンターをAWS EC2のAmazon Linux 2にインストールする機会があり、公式ユーザマニュアルの「[プリザンターをCentOSにインストールする](https://pleasanter.org/manual/getting-started-pleasanter-centos)」を参考にインストールしようとしました。

しかし、不必要な権限がついてしまっているようなのでより安全な手順に変更してみました。
改善点は以下です。

* OSのpostgresユーザにはパスワードを付与しない
* 実行バイナリは自分でビルドする
* プリザンターにPostgreSQLのスーパーユーザ権限を渡さない
* Kastrelをroot権限で起動しない

あとでプリザンタープロジェクトにもフィードバックしてみるつもりです。

# 概要
本説明は、以下に示す環境にプリザンターの動作環境を構築するための手順を示したものです。

|対象|内容|
|:---|:---|
|インスタンスタイプ|t2.micro|
|OS|Amazon Linux 2|
|DB|PostgreSQL 14|
|Webサーバ|Nginx 1.20|
|Platform|.NET 6.0|
|Pleasanter|プリザンター 1.3|

# 事前準備
メモリの小さいEC2インスタンスを使用しているとビルドができません。先にスワップ領域を準備しておきます。
## スワップ領域の追加
「[スワップファイルを使用して、Amazon EC2 インスタンスのスワップ領域として機能するようにメモリを割り当てるにはどうすればよいですか?](https://aws.amazon.com/jp/premiumsupport/knowledge-center/ec2-memory-swap-file/)」の手順で4GBのスワップファイルを追加しました。

# .NET6.0 のインストール
## .NET SDKのインストール
```
$ sudo rpm -Uvh https://packages.microsoft.com/config/centos/7/packages-microsoft-prod.rpm
$ sudo yum install -y dotnet-sdk-6.0
```
## GDI+のインストール
[Amazon Linux Extras](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/amazon-linux-ami-basics.html#extras-library) を利用して EPEL レポジトリをインストールします。
EPELからlibgdiplusパッケージをインストールします。
```
$ sudo amazon-linux-extras install epel -y
$ sudo yum install -y libgdiplus
```
# PostgreSQLのセットアップ
[Amazon Linux Extras](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/amazon-linux-ami-basics.html#extras-library) を利用してPostgreSQLをインストールします。
## リポジトリのインストール
```
$ sudo amazon-linux-extras install postgresql14 -y
```
## PostgreSQLのインストール
```
$ sudo yum install -y postgresql-server postgresql-contrib
```
## データベースの初期化
```
$ sudo postgresql-setup --initdb 
```
## サービス有効化
```
$ sudo systemctl enable postgresql
```
## 認証方式の設定
データベース「Implem.Pleasanter」への接続は認証時にMD5暗号化パスワードを要求するように設定を追加します。
```
sudo nano /var/lib/pgsql/data/pg_hba.conf
```
以下のように追加します。
```/var/lib/pgsql/data/pg_hba.conf
# TYPE  DATABASE        USER            ADDRESS                 METHOD
host    Implem.Pleasanter all           127.0.0.1/32            md5
host    Implem.Pleasanter all           ::1/128                 md5

# "local" is for Unix domain socket connections only
local   all             all                                     peer
# IPv4 local connections:
host    all             all             127.0.0.1/32            ident
# IPv6 local connections:
host    all             all             ::1/128                 ident
# Allow replication connections from localhost, by a user with the
# replication privilege.
local   replication     all                                     peer
host    replication     all             127.0.0.1/32            ident
host    replication     all             ::1/128                 ident
```

## PostgreSQLのサービス再起動
```
$ sudo systemctl restart postgresql
```

## PostgreSQLユーザー設定
プリザンター用のユーザー"pleasanter"(PostgreSQLのユーザー)を作成します。
CTREATEROLEの権限はCodeDefinerの実行時に必要です。
パスワードは例です。必ず変更してください。
```
$ sudo su - postgres
$ psql
postgres=# create role pleasanter with login createrole password 'Implem';
```

## プリザンター用のデータベース作成
データベース "Implem.Pleasanter" を作成します。
```
postgres=# create database "Implem.Pleasanter" with owner=pleasanter lc_collate="ja_JP.UTF-8" lc_ctype="ja_JP.UTF-8" template=template0;
```
以下のコマンドで作成したDBの確認を行い、終了します。
```
postgres=# \l
postgres=# \q
$ exit
```
## 全⽂検索⽤モジュール（pg_trgm）のインストール
ユーザpleasanterでデータベース"Implem.Pleasanter"に接続し、テキストの全⽂検索に必要なモジュール（pg_trgm）をインストールします。
パスワードはユーザ作成時に指定したものです。
```
$ psql -h localhost -U pleasanter Implem.Pleasanter
ユーザ pleasanter のパスワード: 
Implem.Pleasanter=> create extension pg_trgm;
Implem.Pleasanter=> \q
```

# プリザンター 1.3の導入
## ビルドの準備
実行バイナリはソースからビルドしてみます。また、ビルドおよび実行は権限の弱い専用のユーザ"pleasanter"(OSのユーザー)で行います。
```
$ sudo yum install git -y
$ sudo adduser pleasanter
$ sudo su - pleasanter
```
## アプリケーションのビルド
githubから最新のコードをクローンしてビルドします。アプリケーションの配置パスは /home/pleasanter/publish/ になります。
```
$ git clone https://github.com/Implem/Implem.Pleasanter.NetCore.git
$ cd Implem.Pleasanter.NetCore
$ dotnet publish Implem.CodeDefiner/Implem.CodeDefiner.csproj -c Release -v q -o ../publish/Implem.CodeDefiner/ | grep -v warning
$ dotnet publish Implem.Pleasanter/Implem.Pleasanter.csproj -c Release -v q -o ../publish/Implem.Pleasanter/ | grep -v warning
```
## データベースの構成
```
$ nano /home/pleasanter/publish/Implem.Pleasanter/App_Data/Parameters/Rds.json 
```
```/home/pleasanter/publish/Implem.Pleasanter/App_Data/Parameters/Rds.json
{
    "Dbms": "PostgreSQL",
    "Provider": "Local",
    "TimeZoneInfo": "Asia/Tokyo",
    "SaConnectionString": "Server=localhost;Database=Implem.Pleasanter;UID=pleasanter;PWD=Implem",
    "OwnerConnectionString": "Server=localhost;Database=#ServiceName#;UID=#ServiceName#_Owner;PWD=SetAdminsPWD",
    "UserConnectionString": "Server=localhost;Database=#ServiceName#;UID=#ServiceName#_User;PWD=SetUsersPWD",
    "SqlCommandTimeOut": 0,
    "MinimumTime": 3,
    "DeadlockRetryCount": 4,
    "DeadlockRetryInterval": 1000
}
```
## CodeDefinerを実行
```
$ cd /home/pleasanter/publish/Implem.CodeDefiner/
$ dotnet Implem.CodeDefiner.dll _rds
```

## Pleasnterの起動確認
```
$ cd ../Implem.Pleasanter
$ dotnet Implem.Pleasanter.dll
(Ctrl+C)
$ exit
```
別のターミナルで "http://localhost:5000/" にアクセスし、正常なレスポンスが帰ってくることを確認します。
```
$ curl -v http://localhost:5000/
*   Trying 127.0.0.1:5000...
* Connected to localhost (127.0.0.1) port 5000 (#0)
> GET / HTTP/1.1
> Host: localhost:5000
> User-Agent: curl/7.79.1
> Accept: */*
> 
* Mark bundle as not supporting multiuse
< HTTP/1.1 302 Found
< Content-Length: 0
< Date: Sun, 10 Jul 2022 02:45:45 GMT
< Server: Kestrel
< Location: http://localhost:5000/users/login?ReturnUrl=%2F
< X-Frame-Options: SAMEORIGIN
< X-XSS-Protection: 1; mode=block
< X-Content-Type-Options: nosniff
< 
* Connection #0 to host localhost left intact
```
確認できたらCtrl+Cで終了します。 
ユーザpleasanterでの操作はここまでです。exitでsuを終了します。

## Pleasanterサービス用スクリプトの作成
/etc/systemd/system/pleasanter.service を以下の内容で作成します。
```
$ sudo nano /etc/systemd/system/pleasanter.service
```
```/etc/systemd/system/pleasanter.service
[Unit]
Description = Pleasanter
Documentation =
Wants=network.target
After=network.target

[Service]
ExecStart = /usr/bin/dotnet Implem.Pleasanter.dll
WorkingDirectory = /home/pleasanter/publish/Implem.Pleasanter
Restart = always
RestartSec = 10
KillSignal=SIGINT
SyslogIdentifier=dotnet-pleasanter
User = pleasanter
Group = pleasanter
Environment=ASPNETCORE_ENVIRONMENT=Production
Environment=DOTNET_PRINT_TELEMETRY_MESSAGE=false

[Install]
WantedBy = multi-user.target
```
## サービスとして登録・サービスの起動
```
$ sudo systemctl daemon-reload
$ sudo systemctl enable pleasanter
$ sudo systemctl start pleasanter
```
# リバースプロキシ（NginX）の設定
通常のwebサーバと同じ Port80 でアクセスできるようにリバースプロキシの設定を行います。 
AWSのロードバランサーをリバースプロキシとして使うこともできます。
[Application Load Balancer の作成](https://docs.aws.amazon.com/ja_jp/elasticloadbalancing/latest/application/create-application-load-balancer.html)
その場合は以下の手順は不要です。

## Nginxのインストール
[Amazon Linux Extras](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/amazon-linux-ami-basics.html#extras-library) を利用してNginxをインストールします。
```
$ sudo amazon-linux-extras install nginx1 -y
$ sudo systemctl enable nginx
```
## リバースプロキシの設定
/etc/nginx/conf.d/pleasanter.conf を以下の内容で作成します。server_name 行には実際アクセスする際のホスト名を指定します。 
```
$ sudo nano /etc/nginx/conf.d/pleasanter.conf
```
```/etc/nginx/conf.d/pleasanter.conf 
server {
    listen  80;
    server_name   192.168.1.100;
    client_max_body_size 100M;
    location / {
       proxy_pass         http://localhost:5000/;
       proxy_http_version 1.1;
       proxy_set_header   Upgrade $http_upgrade;
       proxy_set_header   Connection keep-alive;
       proxy_set_header   Host $host;
       proxy_cache_bypass $http_upgrade;
       proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
       proxy_set_header   X-Forwarded-Proto $scheme;
    }
}
```
ファイルを作成後、NginXを再起動します。  
```
$ sudo systemctl restart nginx
```
## Http へのアクセス許可
AWS EC2 ではアクセス制御はセキュリティグループで行います。
[Linux インスタンス用の Amazon EC2 Amazon セキュリティグループ](https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/ec2-security-groups.html)