CentOS Stream8でセキュアにLinuxユーザー作成、LAMP構築【その2】
CentOS Stream8でセキュアにLinuxユーザー作成、LAMP構築【その1】のつづきです。Laravel8、Let’sEncryptのSSL/TLS、Basic認証、Apacheログローテーション、MySQLログローテーション、node.js、git/github、CircleCI、slack、Backlog、そしてローカル開発環境のDocker構築までいきたいです。Laravel8は、Apacheのバーチャルホストの公開ディレクトリのパス設定の変更が発生するため、必ず、Let’sEncryptのSSL/TLS証明証取得設定の前に設定してください。
現状、CentOS Stream release 8、Apache/2.4.37 (centos)、PHP 7.4.16 (cli)、mysql Ver 8.0.21 for Linux on x86_64 (Source distribution)、という構成です。
composerインストール
Laravelインストールのためにcomposerをインストールします。adminconohaユーザーでrootに成って以下のコマンド実行。Laravel8で使うcomposerはLinux全体のグローバルインストールではなく、Apacheバーチャルホスト単位のインストールと考えて、2つ目以降のバーチャルホストで、それぞれLaravel8のルートディレクトリでcnoomposer self-updateを行います。
composerインストール前にwgetをインストール
dnf -y install wget
composerのインストーラーをダウンロード(現在の居場所のディレクトリにインストールされます)
wget https://getcomposer.org/installer -O composer-installer.php
composerのインストール
php composer-installer.php --filename=composer --install-dir=/usr/local/bin
composerの更新
composer self-update
composerバージョン確認
composer -v
Laravel8インストール
現在のドキュメントルートへ移動
cd /var/www/独自ドメイン/DocumentRoot
Laravelをインストール
composer create-project laravel/laravel --prefer-dist プロジェクト名
移動します
cd /var/www/独自ドメイン/DocumentRoot/プロジェクト名
Laravel8バージョン確認
php artisan --version
Laravelの公開ディレクトリは
/var/www/独自ドメイン/DocumentRoot/プロジェクト名/public
となるため、/etc/httpd/conf.d/独自ドメイン_http.conf のDocumentRootとDirectoryを変更します。
/etc/httpd/conf.d/独自ドメイン_http.conf
<VirtualHost *:80>
ServerName any
<Location />
Require all denied
</Location>
</VirtualHost>
<VirtualHost *:80>
ServerName 独自ドメイン
ServerAlias www.独自ドメイン
DirectoryIndex index.php index.html index.htm
AddDefaultCharset UTF-8
DocumentRoot /var/www/独自ドメイン/DocumentRoot/プロジェクト名/public
ErrorLog /var/www/独自ドメイン/logs/独自ドメイン-error_log
CustomLog /var/www/独自ドメイン/logs/独自ドメイン-access_log common
<Directory "/var/www/独自ドメイン/DocumentRoot/プロジェクト名/public/">
Require all granted
</Directory>
</VirtualHost>
ブラウザで http://独自ドメイン http://www.独自ドメイン で以下のようなLaravel8初期画面を視認できればOK
余談として、おそらくですが、2021年内にLravel9が出てきて、LTSになります。
node.jsインストール
インストールできる標準リポジトリのバージョンを確認
dnf info nodejs
モジュールストリームを確認(有効化されているStream番号は、すぐ後ろに[e]と記載されています)
dnf module list nodejs
最も新しいモジュールストリームを有効化
dnf module enable nodejs:14
node.jsをインストール
dnf install nodejs
node.jsバージョン確認
node -v
npmバージョン確認
npm -v
Let’sEncryptでSSL/TLS設定
apacheのhttpd.conf、バーチャルホストまわりでSSLを扱えるように、mod_sslをインストールします。adminconohaユーザーでrootに成ってやります。http→httpsへのリダイレクトは、Apacheのバーチャルホストで設定します。
yum -y install mod_ssl
【参考】yumインストール済のパッケージ一覧表示
yum list installed
certbotをインストールします
yum install certbot
certbotバージョン確認
certbot --version
【参考】certbotコマンドの更新
yum -y --enablerepo=epel update certbot
マルチドメインの初回のSSL/TLS証明書作成のコマンド向け –webroot-path に.well-known/acme-challengeディレクトリを作り、ブラウザでhttp/httpsリクエストの独自ドメイン/.well-known/acme-challenge/の中で静的ファイルを見られるようにしておく
cd /var/www/独自ドメイン/DocumentRoot/プロジェクト名/public
mkdir .well-known
cd .well-known
mkdir acme-challenge
cd ..
マルチドメインの初回のSSL/TLS証明書作成のコマンド(万が一の更新失敗のrevoke後の為に、サーバーのSSH接続アカウントなどと一緒に保管しておくことを推奨します)
certbot certonly --agree-tos --webroot-path ドキュメントルートのパス -d 独自ドメイン -d www.独自ドメイン --email メールアドレス --no-eff-email
ワイルドカード証明証で初回のSSL/TLS証明書作成のコマンド(万が一の更新失敗のrevoke後の為に、サーバーのSSH接続アカウントなどと一緒に保管しておくことを推奨します)
certbot certonly \
--agree-tos \
--webroot-path ドキュメントルートのパス \
--manual \
--server https://acme-v02.api.letsencrypt.org/directory \
--preferred-challenges dns-01 \
-d *.独自ドメイン \
-d 独自ドメイン \
--email nishi_international_info@yahoo.co.jp --no-eff-email
ワイルドカード証明証で初回のSSL/TLS証明書作成のコマンド実行直後、インタラクティブに、にレジストラにTXTレコード登録指示が表示されるので以下①②の手順でTXTレコードを設定する
①TXTレコードの登録
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Please deploy a DNS TXT record under the name
_acme-challenge.独自ドメイン with the following value:
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Before continuing, verify the record is deployed.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
以下のような感じでtxtレコードを登録します
_acme-challenge.独自ドメイン txt XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
②コマンド画面でenter
なお、-d で複数のドメインをワイルドカード証明証で登録する場合、txtレコードが複数になるので①②をドメイン毎に繰り返します。その際にtxtレコードのリアルタイム反映確認は、別のシェルを起動して以下のコマンドで行います。
nslookup -type=TXT _acme-challenge.ドメイン 8.8.8.8
SSL/TLS証明書作成が終わったら、/etc/letsencrypt/live/独自ドメイン に以下のように証明証が作成されます
//サーバ証明書(設定ディレクティブ:SSLCertificateFile)
/etc/letsencrypt/live/独自ドメイン/cert.pem
//中間CA証明書(設定ディレクティブ:SSLCertificateChainFile)
/etc/letsencrypt/live/独自ドメイン/chain.pem
//サーバ証明書+中間CA証明書を結合したもの(設定ディレクティブ:SSLCertificateFile)
/etc/letsencrypt/live/独自ドメイン/fullchain.pem
//サーバ証明書の秘密鍵(設定ディレクティブ:SSLCertificateKeyFile)
/etc/letsencrypt/live/独自ドメイン/privkey.pem
Apache設定ディレクトリにシンボリックリンクする
cd /etc/httpd/
ln -s /etc/letsencrypt/live live
証明証の<Certificate Name>を確認(Expiry Dateもわかる)
certbot certificates
【参考】証明書の削除(シンボリックリンクごときれいに削除してくれる)
certbot revoke --cert-name <Certificate Name>
バーチャルホストSSL設定
/etc/httpd/conf.d/独自ドメイン_https.conf を作ります。
vi /etc/httpd/conf.d/独自ドメイン_https.conf
/etc/httpd/conf.d/独自ドメイン_https.conf は以下のように記載します。独自ドメインのwww無しに統一するためのRewriteモジュール各種と上記で作成されたSSL証明書関連をそれぞれ追記します。尚、www無しに統一するためのRewriteモジュールの独自ドメインの記載でドットをエスケープするためのバックスラッシュを忘れないようにご注意ください。
Listen 443 https
Mutex default ssl-cache
SSLCipherSuite ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:!DSS
SSLCompression off
SSLCryptoDevice builtin
SSLHonorCipherOrder on
SSLPassPhraseDialog exec:/usr/libexec/httpd-ssl-pass-dialog
SSLProtocol -SSLv2 -SSLv3 -TLSv1 -TLSv1.1 +TLSv1.2
SSLRandomSeed startup file:/dev/urandom 256
SSLRandomSeed connect builtin
SSLSessionCache shmcb:/run/httpd/sslcache(512000)
SSLSessionCacheTimeout 300
SSLStaplingResponderTimeout 5
SSLStaplingReturnResponderErrors off
SSLStaplingCache shmcb:/var/run/ocsp(128000)
SSLStrictSNIVHostCheck off
SSLUseStapling on
<VirtualHost *:443>
ServerName 独自ドメイン
ServerAlias www.独自ドメイン
RewriteEngine on
RewriteCond %{HTTP_HOST} ^www\.独自ドメイン$
RewriteRule ^/(.*)$ https://独自ドメイン/$1 [R=301,L]
DirectoryIndex index.php index.html index.htm
AddDefaultCharset UTF-8
ServerAdmin メールアドレス
DocumentRoot /var/www/独自ドメイン/DocumentRoot/プロジェクト名/public
ErrorLog /var/www/独自ドメイン/logs/ssl_error_log
TransferLog /var/www/独自ドメイン/logs/ssl_access_log
CustomLog /var/www/独自ドメイン/logs/ssl_request_log "%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b"
LogLevel warn
SSLEngine on
SSLCertificateKeyFile /etc/letsencrypt/live/独自ドメイン/privkey.pem
SSLCertificateFile /etc/letsencrypt/live/独自ドメイン/cert.pem
SSLCertificateChainFile /etc/letsencrypt/live/独自ドメイン/chain.pem
BrowserMatch "MSIE [2-5]" nokeepalive ssl-unclean-shutdown downgrade-1.0 force-response-1.0
<Directory "/var/www/独自ドメイン/DocumentRoot/プロジェクト名/public/">
Require all granted
</Directory>
</VirtualHost>
httpからhttpsへのリダイレクトを追記するため以下のファイルを編集
vi /etc/httpd/conf.d/独自ドメイン_http.conf
Redirect permanent / https://独自ドメイン/を追記
<VirtualHost *:80>
ServerName any
<Location />
Require all denied
</Location>
</VirtualHost>
<VirtualHost *:80>
ServerName 独自ドメイン
ServerAlias www.独自ドメイン
Redirect permanent / https://独自ドメイン/
DirectoryIndex index.php index.html index.htm
AddDefaultCharset UTF-8
DocumentRoot /var/www/独自ドメイン/DocumentRoot
ErrorLog /var/www/独自ドメイン/logs/独自ドメイン-error_log
CustomLog /var/www/独自ドメイン/logs/独自ドメイン-access_log common
<Directory "/var/www/独自ドメイン/DocumentRoot/">
Require all granted
</Directory>
</VirtualHost>
ブラウザで http://独自ドメイン http://www.独自ドメイン がすべてSSLにリダイレクトされることを確認してください。
1台のVPS内に複数バーチャルホストを設定する場合、独自ドメイン_http.conf や 独自ドメイン_https.conf で<VirtualHost *:80>や<VirtualHost *:443>を追記して、公開ディレクトリのパスなどを作り、/etc/letsencrypt/renewal にある独自ドメイン.confファイルの最後尾で以下を参考に追記してください。
[[webroot_map]]
独自ドメイン = /var/www/独自ドメイン/DocumentRoot/プロジェクト名/public
www.独自ドメイン = /var/www/独自ドメイン/DocumentRoot/プロジェクト名/public
apacheを再起動
systemctl restart httpd
systemctl status httpd
また、シェルへのアクセス権を持っている場合、Let’sEncryptのTLS証明証構築には、EPELをインストール/upgradeして、snapdをインストールして、メインスナップ通信ソケットを管理するsystemdユニットを有効にするなどの場合もLinuxディストリビューションの種類によってはあるかもしれません。certbotインストールからSSL証明症発行までは、本家ドキュメント、Certbotにてご確認ください。
CloudFlare 無料プラン
無料プランでアカウントを作り、CloudFlareにログインした状態で独自ドメインの登録を行い、「概要」→「DNS設定」でお名前ドットコムに設定するネームサーバーを入手してください。お名前ドットコムの各種DNSレコードのスクショを撮っておき、お名前ドットコムに設定していたDNSレコードをCloudFlareに同じ様に設定します。そして、ネームサーバーでCloudFlareを指定します。
CloudFlareを導入するとエンドユーザーデバイス(パソコン/タブレット/スマホ)からConohaVPSのWEBサーバーというhttp/httpsリクエストの経路が2つに別れます。
- エンドユーザーデバイス(パソコン/タブレット/スマホ)とCloudFlareの間
- CloudFlareとConohaVPSのWEBサーバーの間
正しいセキュリティを考えると、1と2、それぞれの通信をSSL/TLS暗号化する必要があり、CloudFlareはLet’sEncryptではなく、上記 1 の部分について自前で無料SSLを持っています。
Let’sEncryptのcertbot設定が出来上がった状態のコノハVPSを想定した初期設定です。
DNSレコードをCloudFlareに設定後、Let’sEncryptは上記 2 の部分でSSLを引き続き提供している状態となります。CloudFlareの「SSL/TLS」→「概要」→「お客様のSSL/TLS暗号化モード」で「フル(strict:厳密)」を選択し、CloudFlareとコノハVPSの間の通信の暗号化を無料でLet’sEncryptで出来ました。ただの「フル」は無効なオレオレ証明書でも可能なSSL設定ということになります。Let’sEncryptで有効な証明証を使っているので、念の為に「フル(strict:厳密)」を選びました。
CloudFlareの 1 の無料SSLは、ルートドメイン(sample.com)とワイルドカードによるファーストレベルサブドメイン(www.sample.com や blog.sample.com)までの対応です。セカンドレベルサブドメイン以降でマルチレベルサブドメインなどは別途CloudFlare専用SSLを購入する必要があります。
certbotのSSL証明証更新は、cloudflareのAPIを使うと自動更新も簡単になります
certbot+certbot-dns-cloudflare でワイルドカード証明書を取得&自動更新する
CloudFlareはAWS,GCP,Azureなどでロードバランサの前段に組み合わせて使うことも可能で、低価格帯のCDN/WAFとしてのポジショニングを意識的に狙っていると感じられます。
certbotによるSSL更新、cronによるSSL更新の自動化
Let’s EncryptのcertbotによるSSL更新、cronによるSSL更新の自動化(CloudFlareのAPIを使うか迷っていたので、こちらも念のために調べました)
基本的に、certbot-autoコマンドや古いletsencryptコマンドではなくcertbotコマンドで
certbot renew --dry-run
で試して問題なければ cronで
certbot renew --post-hook "systemctl restart httpd"
を90日以内のリズムで定期実行となります。
ただし、ワイルドカード証明証の場合、自動化の難易度が高くなります。簡単な方法は、「ワイルドカード証明証で初回のSSL/TLS証明書作成のコマンド」と同じ手順でcertbotをcertbot-autoに置き変えて同じ作業を90日に1回行うことになります。
また、ワイルドカード証明証について
certbot certificates
にて、<Certificate Name>を確認して
certbot renew --cert-name <Certificate Name>
でインタラクティブに進める方があります。
ワイルドカードの場合、cloudflareのプラグインを使うと自動化出来るらしいです。
Basic認証
certbotによるSSL更新がこける場合の原因になる可能性があるため、certbotのSSL初期設定とcertbot renew –dry-runの後にBasic認証をかけること。
モジュール確認
httpd -M | grep auth
auth_basic_module (shared) があればOK。
/etc/httpd/conf.modules.d/00-base.conf でモジュールのロード確認
LoadModule auth_basic_module modules/mod_auth_basic.so
上記のように記載されていればOK
独自ドメイン_https.confを編集
vi /etc/httpd/conf.d/独自ドメイン_https.conf
Directoryの中でRequire all grantedを削除してAuthUserFileなどを指定
Listen 443 https
Mutex default ssl-cache
SSLCipherSuite ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:!DSS
SSLCompression off
SSLCryptoDevice builtin
SSLHonorCipherOrder on
SSLPassPhraseDialog exec:/usr/libexec/httpd-ssl-pass-dialog
SSLProtocol -SSLv2 -SSLv3 -TLSv1 -TLSv1.1 +TLSv1.2
SSLRandomSeed startup file:/dev/urandom 256
SSLRandomSeed connect builtin
SSLSessionCache shmcb:/run/httpd/sslcache(512000)
SSLSessionCacheTimeout 300
SSLStaplingResponderTimeout 5
SSLStaplingReturnResponderErrors off
SSLStaplingCache shmcb:/var/run/ocsp(128000)
SSLStrictSNIVHostCheck off
SSLUseStapling on
<VirtualHost *:443>
ServerName 独自ドメイン
ServerAlias www.独自ドメイン
DirectoryIndex index.php index.html index.htm
AddDefaultCharset UTF-8
ServerAdmin メールアドレス
DocumentRoot /var/www/独自ドメイン/DocumentRoot/プロジェクト名/public
ErrorLog /var/www/独自ドメイン/logs/ssl_error_log
TransferLog /var/www/独自ドメイン/logs/ssl_access_log
CustomLog /var/www/独自ドメイン/logs/ssl_request_log "%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b"
LogLevel warn
SSLEngine on
SSLCertificateKeyFile /etc/letsencrypt/live/独自ドメイン/privkey.pem
SSLCertificateFile /etc/letsencrypt/live/独自ドメイン/cert.pem
SSLCertificateChainFile /etc/letsencrypt/live/独自ドメイン/chain.pem
BrowserMatch "MSIE [2-5]" nokeepalive ssl-unclean-shutdown downgrade-1.0 force-response-1.0
<Directory "/var/www/独自ドメイン/DocumentRoot/プロジェクト名/public/">
AuthUserFile /var/www/独自ドメイン/.htpasswd
AuthGroupFile /dev/null
AuthName "Basic Auth"
AuthType Basic
Require valid-user
</Directory>
</VirtualHost>
Basic認証のユーザー名とパスワードを準備して以下のコマンドを実行。実行するとインタラクティブにパスワード設定を求められ、入力して『Adding password for user ユーザー名』と表示されたらOK。
htpasswd -c /var/www/独自ドメイン/.htpasswd ユーザー名
Apache文法チェック
apachectl configtest
httpd再起動(念のため)
systemctl restart httpd
ブラウザで独自ドメインを打って、Basic認証出来ることを確認してください。
次回は、cloudflareのAPIを使うLet’sEncryptのSSL更新。Apacheログローテーション、MySQLログローテーション、git/github、CircleCI、slack、Backlog、そしてローカル開発環境のDocker構築などを行っていきたいです。