Moodle を AWS のロードバランサ（インターネットからは https だが背後では http） で運用する方法

先ずは、以下の準備をする。

証明書（ALB の ACM で発行しても良いし、自分の持っているものでも良い）
efs
ALB で、session stickiness (2時間とした)の設定をする
ところで、session stickiness を数時間とするのはあまり良くないかもしれない。
接続していたマシンが下がった時に、Gateway Timeout になる気がする。
5分に変更した。

AWS の ALB については、この辺を参考にした。
（参考）
https://recipe.kc-cloud.jp/archives/11084

httpd.conf は http で動作させる設定をする
config.php に、$CFG->sslproxy = true; と記述。こうすると、Moodle が https で動作していると思い込む（実際は http で動作させる）。
https://moodle.org/mod/forum/discuss.php?d=351002
備考参照。 

Moodle をインストールしたインスタンス (moodledata を efs に、DB を RDS に設定)
試しに、インストールした Moodle を /mnt/nfs/html/moodle に移行してみた。というのも、プラグインを新しくインストールする場合に、全てのインスタンスにインストールしなくてはいけなくなってしまうので、一ヶ所の方が効率が良いから。
要すれば、moodle と moodledata を /mnt/nfs/html に置いたわけだが、これだと、凄く動作が遅くなってしまった。ということで、やはり2台にそれぞれ Moodle をインストールすることにはなった。
オプションの意味はこちらを参照
https://www.skyarch.net/blog/?p=16175


ちなみに、ALB に認識させるために、config.php の最上部に以下のように記述した。
なぜこれが必要かというと、次にリダイレクトする処理があり、HealthChecker が失敗して Listener が 303 エラーになってしまうため。

```
$http_user_agent = $_SERVER['HTTP_USER_AGENT'];
if (strstr($http_user_agent, "ELB-HealthChecker")) {
    echo "ok";
    die;
}
```

スピードは少し遅いので、memcached をそれぞれのマシンにインストールした。
https://blog.lawrencemcdaniel.com/install-memcached-on-amazon-linux/
Moodle にはデフォルトで memcached プラグインが入っているので、使える。
/etc/sysconfig/memcached を確認すると、16M のメモリキャッシュを持つようだ。
また、/etc/php.ini の [Sessions] を編集して、セッションを memcached が持つようにした。
;;session.save_handler = files
session.save_handler = memcached 
session.save_path = "127.0.0.1:11211" 
マシンを再起動した。
まだ遅い気がする。
あとで気づいたけど、memcached を立ち上げていなかった。
systemctl enable memcached
systemctl start memcached
systemctl status memcached
以下のコマンドを実行したけど、何も出てこない。効いていないのかもしれない。

```
memcached-tool localhost:11211 display
```

プラグイン->キャッシング->memcached というリンクがあったので、クリックしてみた。
127.0.0.1:11211 という一例があったので、そこに入力してみた。
いや、その上の、設定というのを開いて、「Memcached ストアを追加する」に名前「Moodle_cache_store」ストア設定「localhost」 としてみた。

そうしたら、このように memcached が働いているのが確認できた。

```
# memcached-tool localhost:11211 display
  #  Item_Size  Max_age   Pages   Count   Full?  Evicted Evict_Time OOM
  1      96B        17s       1       1     yes        0        0    0

# memcached-tool localhost:11211 dump
Dumping memcache contents
  Number of buckets: 1
  Number of items  : 1
Dumping bucket 1 - 1 total items
```
dump すると、display の行が消えた。

パフォーマンステストというのをクリックして、100000 をクリックしたら、504 Gateway Time-out になった。
URI で、count=10000 にしてみた。
つながらないので、サーバを再起動した。
「既知のキャッシュ定義」というのがあるのを見つけて、そこの項目を、先程つくった、Moodle_cache_store にしてみたら、以下のようになった。

```
# memcached-tool localhost:11211 display
  #  Item_Size  Max_age   Pages   Count   Full?  Evicted Evict_Time OOM
  1      96B        27s       1       1     yes        0        0    0
  3     152B        31s       1       2     yes        0        0    0
  4     192B        37s       1      25     yes        0        0    0
  5     240B        30s       1       7     yes        0        0    0
  7     384B        38s       1       2     yes        0        0    0
  8     480B        38s       1       2     yes        0        0    0
  9     600B        38s       1       4     yes        0        0    0
 12     1.2K        29s       1       1     yes        0        0    0
 14     1.8K        31s       1       1     yes        0        0    0
 15     2.3K        31s       1       1     yes        0        0    0
 20     6.9K        38s       1       1     yes        0        0    0
 22    10.8K        38s       1       1     yes        0        0    0
```

さらに、設定ページの一番下の、「マッピングを編集する」に行って、「アプリケーション」を、Moodle_cache_store に変更してみた。

```
# memcached-tool localhost:11211 display
  #  Item_Size  Max_age   Pages   Count   Full?  Evicted Evict_Time OOM
  1      96B         2s       1       1     yes        0        0    0
  2     120B        25s       1      12     yes        0        0    0
  3     152B        25s       1      14     yes        0        0    0
  4     192B       126s       1      44     yes        0        0    0
  5     240B       299s       1      15     yes        0        0    0
  6     304B        25s       1      18     yes        0        0    0
  7     384B       126s       1      33     yes        0        0    0
  8     480B       123s       1      33     yes        0        0    0
  9     600B        25s       1      22     yes        0        0    0
 10     752B        25s       1      23     yes        0        0    0
 11     944B        25s       1      20     yes        0        0    0
 12     1.2K       126s       1      24     yes        0        0    0
 13     1.4K        25s       1      40     yes        0        0    0
 14     1.8K       126s       1      51     yes        0        0    0
 15     2.3K        25s       1      31     yes        0        0    0
 16     2.8K        25s       1      16     yes        0        0    0
 17     3.5K        25s       1      12     yes        0        0    0
 18     4.4K        25s       1      11     yes        0        0    0
 19     5.5K        25s       1      14     yes        0        0    0
 20     6.9K        25s       1       8     yes        0        0    0
 21     8.7K        25s       1      12     yes        0        0    0
 22    10.8K        25s       1      10     yes        0        0    0
 23    13.6K        25s       1       3     yes        0        0    0
 24    16.9K        25s       1       5     yes        0        0    0
 25    21.2K        25s       1       6     yes        0        0    0
 26    26.5K        25s       1       2     yes        0        0    0
 27    33.1K        25s       1       2     yes        0        0    0
 28    41.4K        25s       1       2     yes        0        0    0
 31    80.9K        25s       1       1     yes        0        0    0
 32   101.1K        25s       1       1     yes        0        0    0
```

メチャ速くなりました！
（参考）
http://taka512.hatenablog.com/entry/20110830/1314698515

以下を参考にして、\$CFG->localcachedir を それぞれのマシンが持てるようにしてみた。
$CFG->localcachedir = "/var/www/html/moodledata/localcachdir";
https://moodle.org/mod/forum/discuss.php?d=351002
インスタンスは、t3.small 程度で十分。RDS も t3.small にすること。EC2, RDS ともに、t3.medium ならなお可。
ちなみに、EC2 インスタンスと、RDS を t3.medium にしてみたら、結構いい感じ。少し高くなるけど。

結局のところ、config.php は以下のようになった。
設定を見て分かるとおり、moodledata は、基本的に efs の領域を使用し、localcachedir のみ
それぞれの EC2 のリソースを使用する。

```
unset($CFG);
global $CFG;
$CFG = new stdClass();

$CFG->dbtype    = 'mariadb';
$CFG->dblibrary = 'native';
$CFG->dbhost    = 'database-1.xxxxxxxx.ap-northeast-1.rds.amazonaws.com';
$CFG->dbname    = 'moodle';
$CFG->dbuser    = 'admin';
$CFG->dbpass    = 'xxxxxxxx';
$CFG->prefix    = 'mdl_';
$CFG->dboptions = array (
  'dbpersist' => 0,
  'dbport' => '',
  'dbsocket' => '',
  'dbcollation' => 'utf8mb4_unicode_ci',
);

// This is needed to make believe SSL is used by Moodle.
$CFG->sslproxy = true;
$CFG->wwwroot   = 'https://xxxx.xxx';
$CFG->dataroot  = '/mnt/efs/html/moodledata';
$CFG->localcachedir  = '/var/www/html/moodledata/localcachedir';
$CFG->admin     = 'admin';

$CFG->directorypermissions = 02777;

require_once(__DIR__ . '/lib/setup.php');
```

さらに、SELinux を有効にしてみた。
Moodledata は、nfs_t となっているので、以下のコマンドを実行した。

```
setsebool -P httpd_use_nfs on
```

（参考）
https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/7/html/selinux_users_and_administrators_guide/sect-managing_confined_services-the_apache_http_server-configuration_examples

再起動すると、データベースへのアクセスができないというエラーになっていた。
以下のコマンドを実行した。

```
setsebool -P httpd_can_network_connect_db 1
```

（参考）
https://serverfault.com/questions/240015/how-do-i-allow-mysql-connections-through-selinux


まだエラーが取れない。確認すると、以下のようになっていた。

```
# less /var/log/audit/audit.log | grep denied

type=AVC msg=audit(1590352121.329:94): avc:  denied  { name_connect } for  pid=2318 comm="php-fpm" dest=3306 scontext=system_u:system_r:httpd_t:s0 tcontext=system_u:object_r:mysqld_port_t:s0 tclass=tcp_socket permissive=0
```

以下のコマンドも実行した。

```
setsebool -P httpd_can_network_connect 1
```

（参考）
https://dev.classmethod.jp/articles/redhat-selinx-might-block-network-connection-to-servers-from-apache-php/

再起動して web アクセスすると、以下の表示になっていた。

Invalid permissions detected when trying to create a directory. Turn debugging on for further details.

確認すると、以下のエラーになっていた。

type=AVC msg=audit(1590352587.167:90): avc:  denied  { write } for  pid=2347 comm="php-fpm" name="localcachedir" dev="nvme0n1p1" ino=239410 scontext=system_u:system_r:httpd_t:s0 tcontext=system_u:object_r:httpd_sys_content_t:s0 tclass=dir permissive=0

```
# vim /etc/selinux/targeted/contexts/files/file_contexts.local

/var/www/html/moodledata(/.*)?   system_u:object_r:httpd_sys_rw_content_t:s0

# restorecon -R -v /var/www/html/moodledata
```
再起動して確認した。

```
# ls -laZ /var/www/html/moodledata

以下のラベルがついて、エラーもなくなったようだ。

httpd_sys_rw_content_t
```

httpd.conf です。
見れば分かるとおり、http 通信をおこなっています。

```
ServerRoot "/etc/httpd"
Listen 80
Include conf.d/modules.conf
Include conf.d/php.conf
User apache
Group apache
ServerName xxxx.xxx:80
ServerAdmin webmaster@xxxx.xxx
<Directory />
    AllowOverride none
    Require all denied
</Directory>
<Directory "/var/www">
    AllowOverride None
    # Allow open access:
    Require all granted
</Directory>
<Directory "/var/www/html">
    Options FollowSymLinks
    AllowOverride None
    Require all granted
</Directory>
<IfModule dir_module>
    DirectoryIndex index.php
</IfModule>
<Files ".ht*">
    Require all denied
</Files>
ErrorLog "logs/error_log"
LogLevel warn
<IfModule log_config_module>
    LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
    LogFormat "%h %l %u %t \"%r\" %>s %b" common
    <IfModule logio_module>
      LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %I %O" combinedio
    </IfModule>
    CustomLog "logs/access_log" combined
</IfModule>
<IfModule mime_module>
    TypesConfig /etc/mime.types
    AddType application/x-compress .Z
    AddType application/x-gzip .gz .tgz
    AddType text/html .shtml
    AddOutputFilter INCLUDES .shtml
</IfModule>
AddDefaultCharset UTF-8
<IfModule mime_magic_module>
    MIMEMagicFile conf/magic
</IfModule>
EnableSendfile on
<IfModule mod_http2.c>
    Protocols h2 h2c http/1.1
</IfModule>
IncludeOptional conf.d/*.conf
TraceEnable off
Header append X-FRAME-OPTIONS "SAMEORIGIN"
ServerTokens ProductOnly
ServerSignature off
<VirtualHost *:80>
    ServerName xxxx.xxx:80
    DocumentRoot /var/www/html/moodle
</VirtualHost>
```

modules.conf です。

```
#00-base.conf
LoadModule alias_module modules/mod_alias.so
LoadModule auth_basic_module modules/mod_auth_basic.so
LoadModule authn_core_module modules/mod_authn_core.so
LoadModule authn_file_module modules/mod_authn_file.so
LoadModule authz_core_module modules/mod_authz_core.so
LoadModule authz_user_module modules/mod_authz_user.so
LoadModule dir_module modules/mod_dir.so
LoadModule headers_module modules/mod_headers.so
LoadModule http2_module modules/mod_http2.so
LoadModule log_config_module modules/mod_log_config.so
LoadModule logio_module modules/mod_logio.so
LoadModule mime_module modules/mod_mime.so
LoadModule rewrite_module modules/mod_rewrite.so
LoadModule setenvif_module modules/mod_setenvif.so
LoadModule socache_shmcb_module modules/mod_socache_shmcb.so
LoadModule unixd_module modules/mod_unixd.so
#00-mpm.conf
LoadModule mpm_event_module modules/mod_mpm_event.so
#00-proxy.conf
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_fcgi_module modules/mod_proxy_fcgi.so
#00-ssl.conf
LoadModule ssl_module modules/mod_ssl.so
#00-systemd.conf
LoadModule systemd_module modules/mod_systemd.so
```

AWS の Memcached を使うには、セキュリティグループを作成して、web サーバのセキュリティグループをソースとする。
そして、マシンには、ライブラリモジュールをインストールする必要がある。
まずは、ライブラリをダウンロードする。

```
# cd
# wget https://elasticache-downloads.s3.amazonaws.com/ClusterClient/PHP-7.3/latest-64bit
```

解凍する

```
#tar -zxvf latest-64bit
```

ライブラリディレクトリにコピーする。

```
#cp amazon-elasticache-cluster-client.so /usr/lib64/php/modules
```

確認する。

```
# ls /usr/lib64/php/modules
amazon-elasticache-cluster-client.so  exif.so      igbinary.so   msgpack.so    pdo_sqlite.so  sockets.so    wddx.so       zip.so
bz2.so                                fileinfo.so  intl.so       mysqli.so     phar.so        sqlite3.so    xmlreader.so
calendar.so                           ftp.so       json.so       mysqlnd.so    posix.so       sysvmsg.so    xmlrpc.so
ctype.so                              gd.so        ldap.so       opcache.so    shmop.so       sysvsem.so    xml.so
curl.so                               gettext.so   mbstring.so   pdo_mysql.so  simplexml.so   sysvshm.so    xmlwriter.so
dom.so                                iconv.so     memcached.so  pdo.so        soap.so        tokenizer.so  xsl.so
```

php.ini に追記する。

```
# vim /etc/php.ini
extension=amazon-elasticache-cluster-client.so
```

再起動する。

```
# shutdown -r now
```

（参考）
https://aws.amazon.com/jp/elasticache/memcached/wordpress-with-memcached/


（備考）
Moodle 
vim +811 /var/www/html/moodle/lib/setuplib.php

initialize_fullme() を見ると、config.php に以下の設定をすれば良い事が分かった。

```
$CFG->sslproxy = true;
```