DigitalOceanにmauticを導入
格安と聞いて日本にはデータセンターはないが、とりあえず使ってみたかったDigitalOceanに、兼ねてより耳にしていたmauticを使ってみたかったので、二兎を追った。
DigitalOceanについて
仮想サーバをDropletという単位で作成することができ、最も安価なDropletの構成(512MBメモリ・20GBのSSDディスク)で、28日で$5程度。
日本のデータセンタが利用できないのが残念だが、シンガポールのデータセンタが利用できるため、検証用としては十分だったので、利用することに。
DigitalOceanはこちらから→https://www.digitalocean.com/
登録はメールアドレス、パスワード、住所、決済情報で、5分も要さなかった。
mauticについて
オープンソースのマーケティングオートメーション(MA)ツール。MAツールという言葉を仕事柄よく耳にすることが多くなったので、まず、どんなものか知りたかった。書籍等で勉強するのもありだったが、偶然にもこのオープンソースのMAツールがあることを知ったので、上述のDigitalOceanも試したいということもあり、Dropletを用意して、そこにmauticを導入して、試験的に利用することにした。
mauticはこちらから→https://www.mautic.org/
インスール
nginx + PHP7 + MySQL
の環境にした。
Dropletの作成
OSはCentOS6.9(64bit)、5$の最小構成、データセンタはシンガポール、プライベートネットワークにチェック(結果的にこれは不要だった)、ssh公開鍵の登録し、hostnameを決めて作成。1分程度で完成し、仮想サーバに鍵認証でログインできた。
iptablesの作成
検証とはいえ、最低限のセキュリティを確保するため、iptablesで簡単なファイアウォールの設定をした。
# !/bin/sh
iptables -F INPUT
iptables -F OUTPUT
iptables -F FORWARD
iptables -P INPUT DROP
iptables -P OUTPUT ACCEPT
iptables -P FORWARD DROP
iptables -A INPUT -i lo -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT -p tcp --dport 22 -j ACCEPT
iptables -A INPUT -p tcp --dport 80 -j ACCEPT
iptables -A INPUT -p tcp --dport 443 -j ACCEPT
上記設定で、sshとhttp以外の通信は不許可にする。ただし、サーバからの応答についてはacceptするようにした。上記シェルスクリプトを実行することで、簡易的なファイアウォールを実現した。
$ /bin/sh /root/tools/iptables.sh
また、再起動したときのために/etc/rc.localに以下を追記する
/bin/sh /root/tools/iptables.sh
時刻の設定
タイムゾーンの変更
タイムゾーンを日本時間に変更する。
$ cp /usr/share/zoneinfo/Japan /etc/localtime
NTPサーバとの同期
ntpd
を導入し、ソフトウェアクロックをSLEWモードで正確に保つようにする。
ntpdのインストール
$ yum install ntp
$ chkconfig ntpd on
ntpdの設定
ntp.conf
を下記のように記述。
# For more information about this file, see the man pages
# ntp.conf(5), ntp_acc(5), ntp_auth(5), ntp_clock(5), ntp_misc(5), ntp_mon(5).
driftfile /var/lib/ntp/drift
# Permit time synchronization with our time source, but do not
# permit the source to query or modify the service on this system.
restrict default kod nomodify notrap nopeer noquery
restrict -6 default kod nomodify notrap nopeer noquery
# Permit all access over the loopback interface. This could
# be tightened as well, but to do so would effect some of
# the administrative functions.
restrict 127.0.0.1
restrict -6 ::1
# Hosts on local network are less restricted.
# restrict 192.168.1.0 mask 255.255.255.0 nomodify notrap
# Use public servers from the pool.ntp.org project.
# Please consider joining the pool (http://www.pool.ntp.org/join.html).
# server 0.centos.pool.ntp.org iburst
# server 1.centos.pool.ntp.org iburst
# server 2.centos.pool.ntp.org iburst
# server 3.centos.pool.ntp.org iburst
server -4 ntp.nict.jp
server -4 ntp1.jst.mfeed.ad.jp
server -4 ntp2.jst.mfeed.ad.jp
server -4 ntp3.jst.mfeed.ad.jp
# broadcast 192.168.1.255 autokey # broadcast server
# broadcastclient # broadcast client
# broadcast 224.0.1.1 autokey # multicast server
# multicastclient 224.0.1.1 # multicast client
# manycastserver 239.255.254.254 # manycast server
# manycastclient 239.255.254.254 autokey # manycast client
# Enable public key cryptography.
# crypto
includefile /etc/ntp/crypto/pw
# Key file containing the keys and key identifiers used when operating
# with symmetric key cryptography.
keys /etc/ntp/keys
# Specify the key identifiers which are trusted.
# trustedkey 4 8 42
# Specify the key identifier to use with the ntpdc utility.
# requestkey 8
# Specify the key identifier to use with the ntpq utility.
# controlkey 8
# Enable writing of statistics records.
# statistics clockstats cryptostats loopstats peerstats
ntpdの起動
$ /etc/init.d/ntpd start
ハードウェアクロックへ反映
下記コマンドを実行する。
$ hwclock -w > /dev/null 2>&1
cron
で下記のように追加をし、設定するのが楽。
下記例では、月曜日の午前3時に同期をとるようにしている。
0 3 * * 1 root /sbin/hwclock -w > /dev/null 2>&1
swap(スワップ)領域の作成
dropletを作成しても、swap領域が0となっている。
$ free
total used free shared buffers cached
Mem: 501968 493816 8152 53488 3736 74344
-/+ buffers/cache: 415736 86232
Swap: 0 0 0
そのため、swap領域がない状態で運用すると、以下のようにMySQLでエラーが多発し、DBがダウンしてしまう現象が多発する。
017-06-23T16:52:56.670021Z 0 [ERROR] InnoDB: mmap(137428992 bytes) failed; errno 12
2017-06-23T16:52:56.670092Z 0 [ERROR] InnoDB: Cannot allocate memory for the buffer pool
2017-06-23T16:52:56.670117Z 0 [ERROR] InnoDB: Plugin initialization aborted with error Generic error
2017-06-23T16:52:56.670145Z 0 [ERROR] Plugin 'InnoDB' init function returned error.
2017-06-23T16:52:56.670161Z 0 [ERROR] Plugin 'InnoDB' registration as a STORAGE ENGINE failed.
2017-06-23T16:52:56.670175Z 0 [ERROR] Failed to initialize plugins.
2017-06-23T16:52:56.670196Z 0 [ERROR] Aborting
ddコマンドでswap用ファイルを作成する
ここでは1GBのswapファイルを作成した。
$ dd if=/dev/zero of=/swapfile bs=1M count=1024
1024+0 records in
1024+0 records out
1073741824 bytes (1.1 GB) copied, 2.83618 s, 379 MB/s
swap領域を作成する
mkswap /swapfile
mkswap: /swapfile: warning: don't erase bootbits sectors
on whole disk. Use -f to force.
Setting up swapspace version 1, size = 1048572 KiB
no label, UUID=4cc2fb29-7e0d-4342-b888-d131c248febe
swap領域を有効にする
$ swapon /swapfile
swap領域を有効にすることで、下記のようにスワップ領域が用意されていることが確認できる。
$ free
total used free shared buffers cached
Mem: 501968 495760 6208 53488 2728 76548
-/+ buffers/cache: 416484 85484
Swap: 1048572 0 1048572
再起動したときもswap領域を有効にする
/etc/fstab
を編集する。
UUID=3fda56ee-2072-4762-b2d8-51a806890759 / ext4 defaults 1 1
tmpfs /dev/shm tmpfs defaults 0 0
devpts /dev/pts devpts gid=5,mode=620 0 0
sysfs /sys sysfs defaults 0 0
proc /proc proc defaults 0 0
/swapfile swap swap defaults 0 0
MySQL5.7のインストール
インストール
$ rpm --import http://dev.mysql.com/doc/refman/5.7/en/checking-gpg-signature.html
$ rpm -ihv http://dev.mysql.com/get/mysql57-community-release-el6-7.noarch.rpm
$ yum --disablerepo=\* --enablerepo='mysql57-community*' list available
$ yum --enablerepo='mysql57-community*' install -y mysql-community-server
設定ファイル
[mysqld]
character-set-server=utf8mb4
collation-server=utf8mb4_general_ci
default-storage-engine=innodb
innodb_large_prefix
sql_mode=ONLY_FULL_GROUP_BY,NO_AUTO_CREATE_USER,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
symbolic-links=0
log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid
[client]
default-character-set=utf8mb4
[mysql]
default-character-set=utf8mb4
起動
MySQL5.7を起動する。
$ /etc/init.d/mysqld start
rootの初期パスワードの確認
下記のコマンドを実行し、初期パスワードを確認する
$ cat /var/log/mysqld.log | grep 'password is generated'
rootのパスワードを変更
確認した初期パスワードでMySQL5.7にログインする。
mysql> ALTER USER 'root'@'localhost' IDENTIFIED BY 'LxAeT$#11op';
また、mauticで利用するデータベースを作成する。
データベースを作成
mysql> CREATE DATABASE mautic;
MTAの確認
mailxをインストールし、テスト配信してみる。
$ yum install -y mailx
$ alternatives --display mta
$ echo "test" | mail -s "subject" myname@mydomain.com
nginxのインストール
インストール
$ rpm -ivh http://nginx.org/packages/centos/6/noarch/RPMS/nginx-release-centos-6-0.el6.ngx.noarch.rpm
$ yum -y install nginx
設定ファイル
user nginx;
worker_processes 1;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
error_log /var/log/nginx/error.log warn;
sendfile off;
#tcp_nopush on;
keepalive_timeout 65;
fastcgi_read_timeout 180;
#gzip on;
include /etc/nginx/conf.d/*.conf;
}
server {
listen 80 default;
server_name _;
root /var/www/html/mautic;
index index.php index.html index.htm;
charset utf-8;
access_log /var/log/nginx/default.access.log;
error_log /var/log/nginx/default.error.log;
location / {
try_files $uri $uri/ /index.php$is_args$args;
}
sendfile off;
location ~ \.php$ {
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass unix:/var/run/php-fpm/php-fpm.sock;
fastcgi_intercept_errors on;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_buffer_size 16k;
fastcgi_buffers 4 16k;
include fastcgi_params;
}
}
PHP7とphp-fpmのインストール
インストール
$ yum install --enablerepo=remi-php70 -y \
php \
php-fpm \
php-cli \
php-mcrypt \
php-common \
php-devel \
php-mbstring \
php-mysqlnd \
php-opcache \
php-pdo \
php-pear \
php-pecl-apcu \
php-pecl-zip \
php-process \
php-xml \
php-intl \
php-soap \
php-pecl-memcache \
php-pecl-memcached \
php-couchbase \
php-imap \
php-json \
php-curl \
php-gd
設定ファイル
default_charset = "UTF-8"
date.timezone = "Asia/Tokyo"
display_errors = On
display_startup_errors = On
log_errors = On
[mbstring]
mbstring.language = Japanese
user = nginx
group = nginx
listen = /var/run/php-fpm/php-fpm.sock
listen.owner = nginx
listen.group = nginx
listen.mode = 0660
catch_workers_output = yes
php_flag[display_errors] = on
php_admin_value[display_errors] = 'stderr'
node.js(npm)とgulp、webpackのインストール
$ yum install -y gcc-c++ make
$ curl -sL https://rpm.nodesource.com/setup_6.x | sudo -E bash -
$ yum install nodejs
$ npm i -g grunt-cli
$ npm i -g browserify
$ npm i -g uglify-js
$ npm i -g webpack
mauticの設置
gitとcomposerのインストール
$ yum install -y git
$ cd /tmp
$ curl -sS https://getcomposer.org/installer | php
$ mv composer.phar /usr/local/bin/composer
$ composer self-update
事前にgithubにあるmauticをforkする。
その後、仮想サーバで以下のコマンドを実行し、forkしたmauticをgit clone
することで設置。mauticのバージョンを更新するときは、git pull origin master
で、更新。
$ cd /var/www/html
$ git clone https://github.com/myacccount/mautic.git
$ cd mautic
$ git checkout master
$ composer install
アクセス権限の変更
このままだとnginxを起動しても、ブラウザアクセスしたときにエラーが発生するので、権限を変更する。
$ touch /var/log/php-fpm/www-error.log
$ chmod 777 -R /var/log/php-fpm
$ chmod 777 -R /var/lib/php/session
$ chmod 777 -R /var/www/html/app/cache
$ chmod 777 -R /var/www/html/app/logs
nginxとphp-fpmの起動
まずはphp-fpmから起動する。
$ /etc/init.d/php-fpm start
続いてnginxを起動する。
$ /etc/init.d/nginx start
mautic起動
ブラウザアクセスするとmauticのデータベース設定、adminユーザ登録の画面が順次表示され、ダッシュボードのページが無事表示される。

※キャプチャ画像では日本語対応で表示されている。設定の詳細はこちらを参照した。ただし、一度ログアウトしないと日本語化されなかったので、動作仕様について調べてみたいと思う。
その他
アバター
mauticにログインするとアバター画像が表示されない状態になるので、気になるのであればgravatarで、アカウント作成時に指定したメールアドレスでgravatarに登録すれば(登録しても即時反映されなかった)正常に表示される。
不具合関連
※実はMariaDBでmauticを動作させようとしたが、下記のPHPエラーが発生したため、断念し、Dropletを再作成した背景があった。
[2017-05-02 11:55:53] mautic.CRITICAL: Uncaught PHP Exception Doctrine\DBAL\Exception\DriverException: "An exception occurred while executing 'SELECT COUNT(t.date_added) AS leads, ll.id, ll.name FROM lead_lists_leads t INNER JOIN lead_lists ll ON ll.id = t.leadlist_id WHERE (ll.is_published = ?) AND (t.date_added BETWEEN ? AND ?) GROUP BY ll.id ORDER BY leads DESC LIMIT 9' with params [true, "2017-04-02 00:00:00", "2017-05-02 23:59:59"]: SQLSTATE[42000]: Syntax error or access violation: 1055 'mautic.ll.name' isn't in GROUP BY" at /var/www/html/src/mautic/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/AbstractMySQLDriver.php line 115 {"exception":"[object] (Doctrine\\DBAL\\Exception\\DriverException(code: 0): An exception occurred while executing 'SELECT COUNT(t.date_added) AS leads, ll.id, ll.name FROM lead_lists_leads t INNER JOIN lead_lists ll ON ll.id = t.leadlist_id WHERE (ll.is_published = ?) AND (t.date_added BETWEEN ? AND ?) GROUP BY ll.id ORDER BY leads DESC LIMIT 9' with params [true, \"2017-04-02 00:00:00\", \"2017-05-02 23:59:59\"]:\n\nSQLSTATE[42000]: Syntax error or access violation: 1055 'mautic.ll.name' isn't in GROUP BY at /var/www/html/src/mautic/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/AbstractMySQLDriver.php:115, Doctrine\\DBAL\\Driver\\PDOException(code: 42000): SQLSTATE[42000]: Syntax error or access violation: 1055 'mautic.ll.name' isn't in GROUP BY at /var/www/html/src/mautic/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOStatement.php:93, PDOException(code: 42000): SQLSTATE[42000]: Syntax error or access violation: 1055 'mautic.ll.name' isn't in GROUP BY at /var/www/html/src/mautic/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOStatement.php:91)"} []
このエラーについて調べた結果はこちらにまとめた。GROUP BY
でカラム指定を省略してSELECTしたため。MariaDBとかMySQLとかではなく、sql_mode
にONLY_FULL_GROUP_BY
したかどうかであった。