MySQL
laravel
centos7
PHP7
laravel5.1

CentOS7.4上でLaravelプロジェクトを動かすための環境を作る

はじめに

image.png
いきなり本番環境を構築するのは怖すぎるので仮想マシン上で設定したときの備忘録。
過去にこんなの執筆してたけど今見たら足りてない部分ががが。

環境 (2017-11-07時点)

サービス名 バージョン
CentOS CentOS Linux release 7.4.1708 (Core)
Apache Apache/2.4.6
PHP PHP 7.1.11 (cli)
MySQL Ver 14.14 Distrib 5.7.20
phpMyAdmin 4.7.5
supervisor 3.1.4
git 1.8.3.1
composer 1.5.2

注意事項

  • Laravelプロジェクト設置場所を[project]と表記することにする。
  • ここでは/var/www/html配下に[project]ディレクトリを作成したと仮定。

VM環境準備

BOXファイルを取ってくる

うまくいった方法

こちらはvagrantが提供しているBOXファイルをダウンロードして使う方法。

console
vagrant box add centos/7 https://atlas.hashicorp.com/centos/boxes/7
mkdir centos7 # make vagrant directory
vagrant init centos/7
vagrant up
vagrant ssh

"rsync" could not be found on your PATH(Windowsのみ?)

vagrantは自動でディレクトリマウント方法(rsync)を指定しようとするが、rsyncが入っていない場合エラーを投げる。
いつまでも起動できない。
そこで、

Vagrantfile
Vagrant.configure("2") do |config|
    ########
    # 省略
    ########

    config.vm.box = "centos/7"

    # コメントアウトを外す
    config.vm.network "private_network", ip: "192.168.33.10"

    # 新しく追加する
    config.vm.synced_folder".", "/vagrant", disabled:true

    ########
    # 省略
    ########
end

これでおk(参考 )。

うまく行かなかった方法

素のCentOS isoイメージでBOX化しようとした。
かなりハマったので今回はパス。

console
# vagrant box add [any_box_name] [repo]
# repo_name = centos7_x64
# repo      = https://github.com/holms/vagrant-centos7-box/releases/download/7.1.1503.001/CentOS-7.1.1503-x86_64-netboot.box
# mkdir centos7 # make vagrant directory
# vagrant init centos7_x64
# vagrant up
# vagrant ssh

ネットワークインターフェースでエラーが頻発したので却下。

エラー内容
Job for network.service failed. See 'systemctl status network.service' and 'journalctl -xn' for details.
# とか
Unit network.service entered failed state.
# とか

GUI環境の準備(不要ならスキップ)

たまにはGUIで起動したいときあるやん?
なければ読み飛ばし推奨。

console
sudo yum groupinstall -y "GNOME Desktop"
startx

参考

CentOS サービス準備

Apache (httpd) サービスインストール + Firewallを無効化

image.png

言わずと知れたApache
本当はnginX入れようと思ってたんだけど、テストでインストールした際の感想

  • 慣れていないだけだが構築が割と面倒くさい
  • PHPを利用できるようにするだけでもかなり手間
  • 設定変更してない標準環境だとPOSTができないって何事?
  • そもそも社内サービスだからそんなにアクセス数ない → nginXのメリットェ
  • トラブったときのメンテナンスに手を取られそう

という理由から、今回はApacheを選定。

console
yum -y install httpd
systemctl start httpd
systemctl stop firewalld
# 確認したかったら以下のコマンドで
systemctl status httpd
systemctl status firewalld

起動時に自動でサービス開始/停止ができるようにする

console
systemctl is-enabled firewalld
# enable
systemctl disable firewalld
# 確認作業
systemctl is-enabled firewalld
# disable

systemctl is-enabled httpd
# disable
systemctl enable httpd
# 確認作業
systemctl is-enabled firewalld
# enable

PHP (+etc) サービス準備

PHPとか諸々周辺パッケージをまとめてインストール。

console
# remiリポジトリ追加
yum install -y http://rpms.famillecollet.com/enterprise/remi-release-7.rpm
yum install -y --enablerepo=remi-php71 php php-cli php-common php-devel php-fpm php-gd php-mbstring php-mysqlnd php-pdo php-pear php-pecl-apcu php-soap php-xml php-xmlrpc
# インストール確認
php -v

MySQLサービス準備

インストールまで

console
# 最初にMariaDBが入っている場合、アンインストールする
yum list installed | grep mariadb
yum remove mariadb-libs
rm -rf /var/lib/mysql/
# 改めてMySQLのインストールを行う
sudo yum -y localinstall http://dev.mysql.com/get/mysql57-community-release-el7-7.noarch.rpm
yum info mysql-community-server
yum -y install mysql-community-server
# サービス起動
systemctl status mysqld
systemctl start mysqld

### 初期パスワードを取得する
cat /var/log/mysqld.log | grep root
2016-03-15T02:44:33.949457Z 1 [Note] A temporary password is generated for root@localhost: '初期パスワード'
MySQL環境のセットアップ
### 初期セットアップ
mysql_secure_installation

# Securing the MySQL server deployment.
Enter password for user root: 'さっきの初期パスワードを入力'
# The existing password for the user account root has expired. Please set a new password.

New password:
Re-enter new password:
# The 'validate_password' plugin is installed on the server.
# The subsequent steps will run with the existing configuration
# of the plugin.
# Using existing password for root.

# Estimated strength of the password: 100

Change the password for root ? ((Press y|Y for Yes, any other key for No) : y
# Rootユーザーのパスワードを変更しますか? - はい
New password:
Re-enter new password:

# Estimated strength of the password: 100

Do you wish to continue with the password provided?(Press y|Y for Yes, any other key for No) : y
# 提供されたパスワードの利用を続けますか? - はい

# By default, a MySQL installation has an anonymous user,
# allowing anyone to log into MySQL without having to have
# a user account created for them. This is intended only for
# testing, and to make the installation go a bit smoother.
# You should remove them before moving into a production
# environment.

Remove anonymous users? (Press y|Y for Yes, any other key for No) : y
# 匿名ユーザーを削除しますか? - はい

# Success.


# Normally, root should only be allowed to connect from
# 'localhost'. This ensures that someone cannot guess at
# the root password from the network.

Disallow root login remotely? (Press y|Y for Yes, any other key for No) : n
# リモートからのRootユーザーログインを拒否しますか? - いいえ

#  ... skipping.
# By default, MySQL comes with a database named 'test' that
# anyone can access. This is also intended only for testing,
# and should be removed before moving into a production
# environment.


Remove test database and access to it? (Press y|Y for Yes, any other key for No) : y
# テスト用データベースを削除しますか? - はい

#  - Dropping test database...
# Success.
#  - Removing privileges on test database...
# Success.
# Reloading the privilege tables will ensure that all changes
# made so far will take effect immediately.

Reload privilege tables now? (Press y|Y for Yes, any other key for No) : y
# 今すぐ権限テーブルをリロードしますか? - はい

# Success.
# All done!

mysql -u root -p

プロジェクト用のMySQLユーザーの作成・権限付与

console
/* ユーザーを作成して権限を与える */
create user (ユーザー) identified by '(password)';
grant (権限) on (レベル) to (ユーザー);

/*
実例:
sampleユーザーにSELECT, INSERT, UPDATE, DELETEを与える。
adminユーザーにすべての権限を与える。
*/ 
create user sample identified by 'sample';
create user admin  identified by 'admin';
grant select,insert,update,delete on *.* to sample;
grant all on *.* to admin;

参考

セキュリティ的にパスワードは大文字 + 数字 + 記号を織り交ぜないとエラーになるっぽい。

データベースディレクトリの場所を変更する [2017-12-05追記]

MySQL標準だと/var/lib/mysql配下にDBを作成するようになっている。
バックアップ的な意味でも別のパーティションに保存するようにしておいたほうがいいため、設定の変更を行う。

この前書いた記事を参考に設定する。

phpMyAdmin準備

事前準備

console
rpm --import https://rpms.remirepo.net/RPM-GPG-KEY-remi
yum install -y yum-utils https://rpms.remirepo.net/enterprise/remi-release-7.rpm
yum-config-manager --enable remi-php71
yum install -y php php-mbstring php-intl
yum install -y php-mysqlnd

remi.repoファイル編集

/etc/yum.repos.d/remi.repo最終行に以下を追加。

/etc/yum.repos.d/remi.repo
; 新しく追加
includepkgs=phpMyAdmin php-phpmyadmin-sql-parser php-google-recaptcha
console
yum-config-manager --enable remi
yum install -y phpMyAdmin

シンボリックリンクの作成

cd /var/www/html
ln -s /usr/share/phpMyAdmin

アクセス権の修正

これを行わないと画面が真っ白になったり、You don’t have permission to access /phpMyAdmin/ on this server.とか怒られたりします。
どうも標準だとlocal以外のアクセスを拒否してるみたい。
ただ、これだと危険が危ない状態になりかねないので、一通りセットアップが終わったらlocalからしか接続できないようにしたり、アクセスできるユーザーを絞ったり、そもそもシンボリックリンクを削除してアクセス不可にするなどの対応を検討したりしたほうがいいかも。

/etc/httpd/conf.d/phpMyAdmin.conf
########
# 省略
########

Alias /phpMyAdmin /usr/share/phpMyAdmin
Alias /phpmyadmin /usr/share/phpMyAdmin

########
# 省略
########

<Directory /usr/share/phpMyAdmin/>
   AddDefaultCharset UTF-8
   <IfModule mod_authz_core.c>
     # Apache 2.4
     # Require local      # コメントアウト
     Require all granted  # 追加
   </IfModule>
    ########
    # 省略
    ########

この辺りを参考にさせていただきました。
systemctl restart httpdしておく。

phpMyAdmin 環境保管領域が完全に設定されていないためうんたらかんたら

この辺りを参考にsqlファイルのインポートを行った。

アクセス許可するIPを制限する [2017-12-05追記]

いくら社内システムとは言えこのままだとどのIPからでもアクセスできてしまうため、非常にまずい。
自分自身のIP以外からは接続できないように設定を変更していく。

先程いじったetc/httpd/conf.d/phpMyAdmin.confの中身を更にいじる。

/etc/httpd/conf.d/phpMyAdmin.conf
########
# 省略
########

Alias /phpMyAdmin /usr/share/phpMyAdmin
Alias /phpmyadmin /usr/share/phpMyAdmin

########
# 省略
########

<Directory /usr/share/phpMyAdmin/>
   AddDefaultCharset UTF-8
   AllowOverride All
   <IfModule mod_authz_core.c>
     # Apache 2.4
     Require all denied     # 追加
     Require local          # コメントアウトを外す
     # Require all granted  # コメントアウト

     #########################
     # 参考:Apache 2.2系以前
     #########################
     # Order Deny, All
     # Deny from All
     # Allow from localhost

   </IfModule>
    ########
    # 省略
    ########

どうやらApache 2.4系からアクセス制限の書き方が変わった模様。
こちらの記事を参考にさせていただきました。感謝。

gitコマンドのインストール

だがしかしこのコマンドを叩くだけだとバージョンが1.8.1になってしまう模様。
とりあえず運用はできているので...とは思うが、どうにも気持ち悪い...。

console
yum install -y git

Windowsファイルサーバーをマウントする(不要ならスキップ)

色々と使う予定があったので。

console
mkdir /mnt/server
mount -t cifs -o username=(username),password=(password) //(file_server_ip)/(directory) /mnt/server

# cifsなんてないとかなんとか言われたら
yum install -y cifs-utils

ついでに自動化

fstabファイルに追記することで起動時に自動でマウントしに行くようになる。
しかしながらnofailオプションを付けておかないと(少なくともvagrant上では)タイムアウトの連続で起動できなくなった。
恐らく実機であれば回避方法はあるのだろうが、念のためオプションは付けておく。

/etc/fstab
//(file_server_ip)/(directory)       /mnt/server   cifs    username=(username),password=(password),uid=apache,gid=apache        0       0       nofail
# ここでnofailを記述しておかないと起動できないループに陥る可能性がある
# 2017-12-05追記:UIDでLinux側の実行ユーザーを指定する

起動確認も行う。

console
mount -a

Supervisorサービスを入れる

supervisorでジョブ監視したり、Laravelキューワーカーとして利用したり。
サービス自体は先に入れておいて構わないが、実際に動作させる場合は先にプロジェクト配置をしておいた方がいいと思う。

console
yum install -y supervisor

とりあえず生きている設定だけ。

設定ファイル(展開)
/etc/supervisord.conf
; Sample supervisor config file.

[unix_http_server]
file=/var/run/supervisor/supervisor.sock   ; (the path to the socket file)
;chmod=0700                 ; sockef file mode (default 0700)
;chown=nobody:nogroup       ; socket file uid:gid owner
;username=user              ; (default is no username (open server))
;password=123               ; (default is no password (open server))

[inet_http_server]
;port=127.0.0.1:9001        ; (ip_address:port specifier, *:port for all iface)
port=0.0.0.0:9001           ; これに書き換えると全てのクライアントからwebアクセスが可能になる
username=user               ; (default is no username (open server))
password=password           ; (default is no password (open server))

[supervisord]
logfile=/var/log/supervisor/supervisord.log  ; (main log file;default $CWD/supervisord.log)
logfile_maxbytes=50MB            ; (max main logfile bytes b4 rotation;default 50MB)
logfile_backups=10               ; (num of main logfile rotation backups;default 10)
;loglevel=info                   ; (log level;default info; others: debug,warn,trace)
loglevel=debug                   ; (log level;default info; others: debug,warn,trace)
pidfile=/var/run/supervisord.pid ; (supervisord pidfile;default supervisord.pid)
nodaemon=false                   ; (start in foreground if true;default false)
minfds=1024                      ; (min. avail startup file descriptors;default 1024)
minprocs=200                     ; (min. avail process descriptors;default 200)
;umask=022                       ; (process file creation umask;default 022)
;user=chrism                     ; (default is current user, required if root)
;identifier=supervisor           ; (supervisord identifier, default is 'supervisor')
;directory=/tmp                  ; (default is not to cd during start)
;nocleanup=true                  ; (don't clean up tempfiles at start;default false)
;childlogdir=/tmp                ; ('AUTO' child log dir, default $TEMP)
;environment=KEY=value           ; (key value pairs to add to environment)
;strip_ansi=false                ; (strip ansi escape codes in logs; def. false)

; the below section must remain in the config file for RPC
; (supervisorctl/web interface) to work, additional interfaces may be
; added by defining them in separate rpcinterface: sections
[rpcinterface:supervisor]
supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface

[supervisorctl]
serverurl=unix:///var/run/supervisor/supervisor.sock ; use a unix:// URL  for a unix socket
;serverurl=http://127.0.0.1:9001  ; use an http:// url to specify an inet socket
serverrrurl=http://127.0.0.1:9001 ; use an http:// url to specify an inet socket
;username=chris                   ; should be same as http_username if set
;password=123                     ; should be same as http_password if set
;prompt=mysupervisor              ; cmd line prompt (default "supervisor")
;history_file=~/.sc_history       ; use readline history if available

; The below sample program section shows all possible program subsection values,
; create one or more 'real' program: sections to be able to control them under
; supervisor.

;[program:theprogramname]
;command=/bin/cat              ; the program (relative uses PATH, can take args)
;process_name=%(program_name)s ; process_name expr (default %(program_name)s)
;numprocs=1                    ; number of processes copies to start (def 1)
;directory=/tmp                ; directory to cwd to before exec (def no cwd)
;umask=022                     ; umask for process (default None)
;priority=999                  ; the relative start priority (default 999)
;autostart=true                ; start at supervisord start (default: true)
;autorestart=true              ; retstart at unexpected quit (default: true)
;startsecs=10                  ; number of secs prog must stay running (def. 1)
;startretries=3                ; max # of serial start failures (default 3)
;exitcodes=0,2                 ; 'expected' exit codes for process (default 0,2)
;stopsignal=QUIT               ; signal used to kill process (default TERM)
;stopwaitsecs=10               ; max num secs to wait b4 SIGKILL (default 10)
;user=chrism                   ; setuid to this UNIX account to run the program
;redirect_stderr=true          ; redirect proc stderr to stdout (default false)
;stdout_logfile=/a/path        ; stdout log path, NONE for none; default AUTO
;stdout_logfile_maxbytes=1MB   ; max # logfile bytes b4 rotation (default 50MB)
;stdout_logfile_backups=10     ; # of stdout logfile backups (default 10)
;stdout_capture_maxbytes=1MB   ; number of bytes in 'capturemode' (default 0)
;stdout_events_enabled=false   ; emit events on stdout writes (default false)
;stderr_logfile=/a/path        ; stderr log path, NONE for none; default AUTO
;stderr_logfile_maxbytes=1MB   ; max # logfile bytes b4 rotation (default 50MB)
;stderr_logfile_backups=10     ; # of stderr logfile backups (default 10)
;stderr_capture_maxbytes=1MB   ; number of bytes in 'capturemode' (default 0)
;stderr_events_enabled=false   ; emit events on stderr writes (default false)
;environment=A=1,B=2           ; process environment additions (def no adds)
;serverurl=AUTO                ; override serverurl computation (childutils)

; The below sample eventlistener section shows all possible
; eventlistener subsection values, create one or more 'real'
; eventlistener: sections to be able to handle event notifications
; sent by supervisor.

;[eventlistener:theeventlistenername]
;command=/bin/eventlistener    ; the program (relative uses PATH, can take args)
;process_name=%(program_name)s ; process_name expr (default %(program_name)s)
;numprocs=1                    ; number of processes copies to start (def 1)
;events=EVENT                  ; event notif. types to subscribe to (req'd)
;buffer_size=10                ; event buffer queue size (default 10)
;directory=/tmp                ; directory to cwd to before exec (def no cwd)
;umask=022                     ; umask for process (default None)
;priority=-1                   ; the relative start priority (default -1)
;autostart=true                ; start at supervisord start (default: true)
;autorestart=unexpected        ; restart at unexpected quit (default: unexpected)
;startsecs=10                  ; number of secs prog must stay running (def. 1)
;startretries=3                ; max # of serial start failures (default 3)
;exitcodes=0,2                 ; 'expected' exit codes for process (default 0,2)
;stopsignal=QUIT               ; signal used to kill process (default TERM)
;stopwaitsecs=10               ; max num secs to wait b4 SIGKILL (default 10)
;user=chrism                   ; setuid to this UNIX account to run the program
;redirect_stderr=true          ; redirect proc stderr to stdout (default false)
;stdout_logfile=/a/path        ; stdout log path, NONE for none; default AUTO
;stdout_logfile_maxbytes=1MB   ; max # logfile bytes b4 rotation (default 50MB)
;stdout_logfile_backups=10     ; # of stdout logfile backups (default 10)
;stdout_events_enabled=false   ; emit events on stdout writes (default false)
;stderr_logfile=/a/path        ; stderr log path, NONE for none; default AUTO
;stderr_logfile_maxbytes=1MB   ; max # logfile bytes b4 rotation (default 50MB)
;stderr_logfile_backups        ; # of stderr logfile backups (default 10)
;stderr_events_enabled=false   ; emit events on stderr writes (default false)
;environment=A=1,B=2           ; process environment additions
;serverurl=AUTO                ; override serverurl computation (childutils)

; The below sample group section shows all possible group values,
; create one or more 'real' group: sections to create "heterogeneous"
; process groups.

;[group:thegroupname]
;programs=progname1,progname2  ; each refers to 'x' in [program:x] definitions
;priority=999                  ; the relative start priority (default 999)

; The [include] section can just contain the "files" setting.  This
; setting can list multiple files (separated by whitespace or
; newlines).  It can also contain wildcards.  The filenames are
; interpreted as relative to this file.  Included files *cannot*
; include files themselves.

[include]
files = supervisord.d/*.ini

laravel.iniは新規に作成する。

/etc/supervisor.d/laravel.ini
[program:laravel-worker]
process_name=%(program_name)s_%(process_num)02d
; artisanファイルの場所を環境に応じて書き換える
command=php /[product]/artisan queue:work --sleep=3 --daemon
autostart=true
autorestart=true
user=root
numprocs=1
redirect_stderr=true
stdout_logfile=/[product]/storage/laravel_worker.log
stderr_logfile=/[product]/storage/laravel_error.log

公式ドキュメント辺りを参考に。

console
systemctl start supervisord
# 実行確認
supervisorctl status
# laravel-worker:laravel-worker_00   RUNNING   pid 4574, uptime 0:09:19

当初、/etc/supervisor.d/laravel.ini内部のcommand=php /[project]/artisan queue:work --sleep=3 --tries=2 --daemonを公式通りcommand=php /home/forge/app.com/artisan queue:work sqs --sleep=3 --tries=3 --daemonにしていて、エラーログも何も出ないのにジョブがプッシュされなくて軽く詰みかけた。
artisanの場所を環境に応じて書き換えること、sqsを外すことで解決。

Supervisorで割り当てたジョブの挙動がおかしなことになった話 [2017-12-05追記]

こちらを参考にコンフィグファイルの修正を行った。

SSHサービスを入れる

入ってない場合は入れる。

console
yum list installed | grep ssh
yum install -y openssh-server

最初から入ってたのでやってない。
この辺を参考にどうぞ。

WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!

クライアントからサーバー側にssh (user_name)@(host_name)でつなぐ際にエラーが出た場合。

console(client)
ssh-keygen -R (host_name)
# 改めてssh接続
ssh (user_name)@(host_name)
# The authenticity of host '(host_name)' can't be established.
# ECDSA key fingerprint is SHA256:(sha256_key).
Are you sure you want to continue connecting (yes/no)? yes
# Warning: Permanently added '(host_name)' (ECDSA) to the list of known hosts.
(user_name)@(host_name) password:

参考

リモートデスクトップ接続許可 [2017-12-05追記]

こちらを参考に設定。
なお、予めGNOME DESKTOPがインストールされている前提とする。
firewallを有効化している場合はポート番号3389を許可しておくこと。

console
yum install epel-release
yum install tigervnc-server
yum install xrdp

# インストール確認
prm -qa | grep xrdp
prm -qa | grep tiger
/etc/xrdp/xrdb.ini
;;;;;;;;;
; 省略
;;;;;;;;;

; max_bpp=32 ; コメントアウト
; 色の深さが24ビット以下でないと接続できないため、32→24に変更する
max_bpp=24

;;;;;;;;;
; 省略
;;;;;;;;;
console
# サービス起動と自動起動化
systemctl start xrdp
systemctl enable xrdp

あとは通常通り、Windowsのリモートデスクトップ接続あたりから接続テストを行う。

プロジェクト配置

プロジェクトをcloneしてくる

console
cd /var/www/html
git clone 'your repository'

このままだと設定ファイルなんかが原因でエラーを吐くことがあるので、.envファイル、config/ディレクトリ内など、必要に応じて書き換える。
書き換えただけだとキャッシュやら何やらが残っていてうまく行かない場合があるので、続けて下記の対応を行う。

composerをインストールしてアップデートする

envファイルを更新するためには、php artisan config:cacheコマンド叩くと一発なのだけど、

bootstrap/../vendor/autoload.php. Failed to open stream: No such file or directory. The "vendor" folder does not exist.

的なメッセージが出ることがある。

console
# [project]配下で作業する
cd /[project]

# Composerインストール
yum install -y composer

# 依存関係の注入
composer install

# 改めてLaravelのconfigファイルをキャッシュ化
composer dump-autoload
php artisan config:cache

ドキュメントルートの設定を行う

Laravelは一度/[project]/public/index.phpにアクセスさせて、そこで全てのアクセスを捌いている模様。
なのでデフォルトのドキュメントルートを変更して、publicへとルーティングするように設定を変える。

/etc/httpd/conf/httpd.conf
########
# 省略
########

# ドキュメントルートを書き換える
DocumentRoot "/[project]/public"

# ルートディレクトリも変更する
<Directory "/[project]/public">
    # Allへ書き換え
    AllowOverride All
    # Allow open access:
    Require all granted
</Directory>

########
# 省略
########

systemctl restart httpdするのも忘れずに。

マイグレーションとかその他諸々

DBを複数に分けていたりする場合はphpMyAdminからDB作成しておく。
その後、php artisan migrateでテーブルを作成。

Laravelログ出力ディレクトリの権限変更を行う

恐らくこの状態でアクセスしたとしても、500 内部サーバーエラーが出ていることと思う。
どうやらWeb経由でアクセスする際はApacheユーザーとしてアクセスしているようなのだが、そのユーザー自体がLaravelログファイルの生成ができないようにプロテクトがかかっているらしい(詳しくはapacheのログを参照)。
chmodやらchownやらを試してみたが効果がないようだ...と思って調べてみたら下記のような対応が必要らしい。

console
chmod -R 777 /[project]/storage
chcon -R -t httpd_sys_rw_content_t /[project]/storage
# 2017-11-09 追記
chmod -R 777 /[project]/bootstrap/cache
chcon -R -t httpd_sys_rw_content_t /[project]/bootstrap/cache
# 2017-11-16 追記
chown -R apache /[project]/storage
chown -R apache /[project]/bootstrap/cache

参考

SQLSTATE[HY000] [2002] Permission denied

的なエラーが吐かれる場合がある。
どうやらSELinuxさん辺りのセキュリティに引っかかってデータベースにアクセスできていない模様。
下記の手順で対応。

console
getsebool httpd_can_network_connect
sudo setsebool -P httpd_can_network_connect 1
### 反映確認
getsebool httpd_can_network_connect

不要であればSELinuxサービス自体を止めておいたほうがいいのかもしれない。変なところで詰まりそう。
多分それやるとすごくまずいんだけど。
参考

2017-11-22追記

やっぱりSELinuxが色々障害原因となっていたので止めることにする。
なお、SELinuxには以下のモードがある模様。

状態 内容
enforcing アクセス制限も含めて有効化
permissive 監視のみでアクセス制限は行わない
disabled 無効化

一時的に止める場合

console
setenforce 0
# 0 -> 無効化(Permissive)
# 1 -> 有効化(Enforcing)
getenforce # 状態確認

永続的に止める場合

/etc/selinux/config
#########
# 省略
#########

# 必要に応じて上記状態から選択する
SELINUX=permissive

#########
# 省略
#########

念のため再起動をして確認する。

PhpDebugBar.Widgets.MailsWidget is not a constructor

ブラウザ側のキャッシュクリアで解決。

Unable to write in the "/[project]/public" directory

console
chmod -R 777 /[project]/public
chcon -R -t httpd_sys_rw_content_t /[project]/public

で解決。

ログファイルってどこにあるんだってばよ

ログファイル名 場所
Apache /var/log/httpd/
Laravel /[project]/storage/logs/
Supervisor /var/log/supervisor/supervisord.log
Supervisor (Laravel) /[product]/storage/laravel_worker.log

Xdebugを入れてカバレッジを出したい。ついでに他端末からも見たい。

console
php -i | grep Debug
Debug Build => no # noならOK

yum install -y php-pecl-xdebug

php -v
# PHP 7.1.12 (cli) (built: Dec  1 2017 13:53:12) ( NTS )
# Copyright (c) 1997-2017 The PHP Group
# Zend Engine v3.1.0, Copyright (c) 1998-2017 Zend Technologies
#     with Xdebug v2.5.5, Copyright (c) 2002-2017, by Derick Rethans
#          ~~~~~~~~~~~~~
/etc/php.ini
###################
# 末尾に以下を追加
###################
xdebug.remote_enable=1
xdebug.remote_host=10.0.2.2
console
cd /[product]
./vendor/bin/phpunit

# PHPUnit 4.8.36 by Sebastian Bergmann and contributors.
#
# .........................
#
# Time: 17.79 minutes, Memory: 240.00MB
#
# OK (466 tests, 3113 assertions)
#
# Generating code coverage report in HTML format ... done

cd public
ln -s ../report

これでブラウザからアクセス時、/reportをつけるだけでカバレッジレポートにアクセスできるようになった。
ログファイルが出力されない!とか言う方はこちらの記事の phpunit.xml 辺りを参照ください。

まだやってないこと

  • MySQLの本格的な権限設定・チューニング -> やりました
  • ログローテーションの設定 -> やりました
  • php.iniのチューニング