【覚え書き】LAMP環境構築（AlmaLinux8.6+Apache+MariaDB+PHP）と常時SSL化手順

## はじめに
これまでのCentOS7や8の後継の1つとされている AlmaLinux をセットアップする機会が増えてきたので、OSインストール後の初期設定とLAMP環境構築手順をここに覚え書きしておきたいと思います。

## 構築するLAMP環境
    L：AlmaLinux 8.6 (Sky Tiger)
    A：Apache/2.4.37 (AlmaLinux)
    M：mysql Ver 15.1 Distrib 10.3.35-MariaDB
    P：PHP 7.4.30 / Python 3.6.8

## この手順を始める前の前提
* 物理サーバーもしくは仮想サーバーへは、AlmaLinux8.6 がインストール済みであること
* インストール時に、言語を「日本語」に設定済みであること
* インストール時に、ネットワーク設定済みであること
* インストール時に、NTP設定済みであること
* インストール時に、管理者以外のユーザを作成済みであること

## 1. dnfまわり
### 1-1. メタデータキャッシュの作成
```bash
dnf -y makecache

#実行結果
AlmaLinux 8 - BaseOS       4.5 kB/s | 3.8 kB     00:00    
AlmaLinux 8 - AppStream    2.6 kB/s | 4.2 kB     00:01    
AlmaLinux 8 - Extras       2.3 kB/s | 3.8 kB     00:01    
メタデータキャッシュを作成しました。
```

### 1-2. Baseパッケージのインストール
```bash
dnf -y groupinstall "Base"
```

### 1-3. Development Toolsパッケージのインストール
```bash
dnf -y groupinstall "Development Tools"
```

### 1-4. 自動更新の設定
```dnf-automatic```パッケージをインストールします
```bash
dnf -y install dnf-automatic
```

```/etc/dnf/automatic.conf```ファイルを開き、自動更新の設定を編集します
* ```upgrade_type```は ```default```から```security```へ
* ```apply_updates``` は ```no```から```yes```へ
```shell
vim /etc/dnf/automatic.conf

upgrade_type = security  #修正します
apply_updates = yes      #修正します
```

自動更新を有効にします
```shell
systemctl enable --now dnf-automatic.timer
```

## 2. ユーザーまわり
### 2-1. ユーザーの新規作成
```useradd```コマンドでユーザを作成します
```bash
useradd ユーザ名
```

### 2-2. ユーザーのパスワード設定
```passwd```コマンドでユーザに対するパスワードを設定します
```bash
passwd ユーザ名
```
:::note warn
パスワードを２回入力するよう求められます
:::

### 2-3. sudoresの編集
```visudo```コマンドでsudoresに作成したユーザを追記し、```sudo```コマンドを使えるようにします。
```bash
visudo
```
以下のrootの行の下に追加する
```bash
##
## Allow root to run any commands anywhere
root    ALL=(ALL)       ALL
ユーザ名    ALL=(ALL)       ALL
```
:::note warn
作成したユーザ名の行を追加します。sudoの細かい権限については必要に応じて調整してください。
:::

## 3. sshまわり
### 3-1. sshの最低限の初期設定（ユーザ制限と認証方法の制限）
```/etc/ssh/sshd_config ```を編集して、sshできるユーザの制限と認証方法を制限します
* ポートを```22```に指定
* rootを指定したsshログインを無効化
* 鍵認証を有効化
* パスワードなしでのsshログインを無効化
* パスワード認証を無効化（ユーザ個別にパスワード認証を有効化しますが、全体的には無効化します）

```bash
vim /etc/ssh/sshd_config

#主な修正箇所
Port 22                     #コメントアウトを外す
PermitRootLogin no          #noに書き換える
PubkeyAuthentication yes    #コメントアウトを外す
PermitEmptyPasswords no     #コメントアウトを外す
PasswordAuthentication no   #noに書き換える

#追記する内容（最終行の下に追加するもの）
AllowUsers ユーザ名1 ユーザ名2  #sshできるユーザを記載します

#追記する内容（AllowUsersの下に追加するもの）
#パスワード認証をするユーザを記載します
Match User ユーザ名1
        PasswordAuthentication yes
Match User ユーザ名2
        PasswordAuthentication yes
```
:::note info
AllowUsersでログインできるユーザを指定することで、それ以外のユーザのログインを無効化します
:::
:::note info
Match User ユーザ名 でユーザ個別に認証方法やsshの設定を分岐させることができます
:::


### 3-2. 設定の反映
```sshd```を再起動して、編集した```sshd_config```の設定を反映させます
```bash
systemctl restart sshd
```


## 4. ファイアウォールの無効化
ファイアウォールを無効化させます。ファイアウォールが必要な場合は、個別に設定を投入してください。
```bash
systemctl disable --now firewalld
```


## 5. SElinuxの無効化
SELinuxを無効化させます。SELinuxが必要な場合は、個別に設定してください。
* ```SELINUX=enforcing``` を ```SELINUX=disabled```へ
```bash
vim /etc/selinux/config

#修正箇所
SELINUX=disabled   #disabledに修正します
```

再起動して、SELinuxの設定を反映させます。
```bash
shutdown -r now
```

## 6. Apacheまわり
### 6-1. Apacheのインストール
Apacheをインストールします。あわせてSSL化のためにsslのモジュールもあわせてインストールしておきます。
```bash
dnf -y install httpd httpd-devel mod_ssl
```

Apacheのインストールバージョンを確認しておきます
```bash
httpd -v

# 実行結果　
Server version: Apache/2.4.37 (AlmaLinux)
```

Apacheをシステム起動時に自動起動するように設定します
```bash
systemctl enable httpd
```

### 6-2. Apacheの設定
Apacheのwelcomeページを表示させないようにします
```bash
mv /etc/httpd/conf.d/welcome.conf /etc/httpd/conf.d/welcome.conf.org
```

ドキュメントルート```/var/www/html```にアクセスしたときにディレクトリ構造が表示されないようにします
```conf
# confファイルを修正するのでバックアップしておきます
cp /etc/httpd/conf/httpd.conf /etc/httpd/conf/httpd.conf.bk

vim /etc/httpd/conf/httpd.conf

#修正内容
・・・中略

<Directory "/var/www/html">

・・・中略

Options FollowSymLinks　#Indexesを削除します
```


Apacheのセキュリティ対策の設定を投入しておきます。
```bash
vim /etc/httpd/conf.d/security.conf

#記載内容
ServerTokens Prod
Header unset "X-Powered-By"
RequestHeader unset Proxy
Header append X-Frame-Options SAMEORIGIN
Header set X-XSS-Protection "1; mode=block"
Header set X-Content-Type-Options nosniff
TraceEnable Off
```

mod_deflateの設定を投入しておきます。
```conf
vim /etc/httpd/conf.d/deflate.conf

#記載内容
<IfModule mod_deflate.c>
SetOutputFilter DEFLATE
DeflateCompressionLevel 1

BrowserMatch ^Mozilla/4\.0[678] no-gzip
BrowserMatch ^Mozilla/4 gzip-only-text/html
BrowserMatch \bMSI[E] !no-gzip !gzip-only-text/html

SetEnvIfNoCase Request_URI\.(?:gif|jpe?g|png)$ no-gzip dont-vary
SetEnvIfNoCase Request_URI _\.utxt$ no-gzip
</IfModule>
```

投入した設定の表記に誤りが無いか確認します。mod_sslを導入した場合、ssl.confでエラーがでますが無視して問題ありません。
```bash
httpd -t

#実行結果
AH00526: Syntax error on line 85 of /etc/httpd/conf.d/ssl.conf:
SSLCertificateFile: file '/etc/pki/tls/certs/localhost.crt' does not exist or is empty
```

### 6-3. Apacheの起動
最後に、Apacheを起動します
```bash
systemctl start httpd
```

## 7. MariaDBまわり
### 7-1. MariaDBのインストール
MariaDBをインストールします。
```bash
dnf -y install mariadb-server mariadb
```

MariaDBのインストールバージョンを確認しておきます
```bash
mysql --version

# 実行結果　
mysql  Ver 15.1 Distrib 10.3.35-MariaDB, for Linux (x86_64) using readline 5.1
```

MariaDBをシステム起動時に自動起動するように設定します
```bash
systemctl enable mariadb
```

### 7-2. MariaDBの文字コード設定
MariaDBで作成するDBやTableの文字コードを```utf8mb4```に設定します
```conf
cp /etc/my.cnf.d/mariadb-server.cnf /etc/my.cnf.d/mariadb-server.cnf.bk  # 編集前にバックアップをしておきます

vim /etc/my.cnf.d/mariadb-server.cnf

# 追記内容 [mariadb]以下に追記します
character-set-server = utf8mb4
[client-mariadb]
default-character-set = utf8mb4
```

### 7-3. MariaDBの起動
Mariadbを起動します。
```bash
systemctl start mariadb
```

### 7-4. MariaDBの初期設定
MariaDBの初期設定（mysql_secure_installation)をし、rootのパスワードを設定します
```
mysql_secure_installation

# 実行結果 初期設定の流れ

Enter current password for root (enter for none):   # Enterする
OK, successfully used password, moving on...

Set root password? [Y/n] Y　　　　　　　  # パスワードを設定するので Y で Enterする
New password: 　　　　　　　              # root用のパスワードを入力
Re-enter new password: 　　　　　　　     # root用のパスワードを入力（確認）
Password updated successfully!
Reloading privilege tables..
 ... Success!

Remove anonymous users? [Y/n] Y　　　　　　　              # Y で Enterする
 ... Success!

Disallow root login remotely? [Y/n] Y            # Y で Enterする
 ... Success!

Remove test database and access to it? [Y/n] Y   # Y で Enterする
 - Dropping test database...
 ... Success!
 - Removing privileges on test database...
 ... Success!

Reload privilege tables now? [Y/n] Y             # Y で Enterする
 ... Success!
```

## 8. PHPまわり
### 8-1. epelリポジトリ、remiリポジトリの追加
PHP7.4を外部リポジトリからインストールします。リポジトリを追加します。
```bash
# epelリポジトリの追加
dnf -y install epel-release

# remiリポジトリの追加
dnf -y install https://rpms.remirepo.net/enterprise/remi-release-8.rpm
```

dnfのメタデータキャッシュを再度作成しておきます。
```bash
dnf clean all && dnf -y makecache
```

### 8-2. インストールするPHPモジュールの指定
```dnf module list php```で、インストールできるPHPのモジュールリストを確認できます。
```bash
dnf module list php

#実行結果
AlmaLinux 8 - AppStream
Name                                     Stream                                      Profiles                                                      Summary                                                  
php                                      7.2 [d]                                     common [d], devel, minimal                                    PHP scripting language                                   
php                                      7.3                                         common [d], devel, minimal                                    PHP scripting language                                   
php                                      7.4                                         common [d], devel, minimal                                    PHP scripting language                                   
php                                      8.0                                         common [d], devel, minimal                                    PHP scripting language                                   

Remi s Modular repository for Enterprise Linux 8 - x86_64
Name                                     Stream                                      Profiles                                                      Summary                                                  
php                                      remi-7.2                                    common [d], devel, minimal                                    PHP scripting language                                   
php                                      remi-7.3                                    common [d], devel, minimal                                    PHP scripting language                                   
php                                      remi-7.4                                    common [d], devel, minimal                                    PHP scripting language                                   
php                                      remi-8.0                                    common [d], devel, minimal                                    PHP scripting language                                   
php                                      remi-8.1                                    common [d], devel, minimal                                    PHP scripting language                                   
php                                      remi-8.2                                    common [d], devel, minimal                                    PHP scripting language   
```

今回は```remi-7.4```を指定して、外部リポジトリからPHP7.4をインストールしていきますので、デフォルトモジュールを指定します。
```bash
dnf -y module reset php && dnf -y module enable php:remi-7.4
```

### 8-3. PHP7.4のインストール
PHPとPHPモジュールをインストールします
```bash
dnf -y install php php-cli php-fpm php-curl php-mysqlnd php-gd php-opcache php-zip php-intl php-common php-bcmath php-imagick php-xmlrpc php-json php-readline php-memcached php-redis php-mbstring php-apcu php-xml php-dom php-redis php-memcached php-memcache php-process
```

PHPのインストールバージョンを確認しておきます
```bash
php -v

#実行結果
PHP 7.4.32 (cli) (built: Sep 28 2022 09:09:55) ( NTS )
Copyright (c) The PHP Group
Zend Engine v3.4.0, Copyright (c) Zend Technologies
    with Zend OPcache v7.4.32, Copyright (c), by Zend Technologies
```

php-fpmを自動起動するように設定します
```bash
systemctl enable php-fpm
```

### 8-4.php.iniの設定
```/etc/php.ini```を修正し、phpを初期設定します
```conf
cp /etc/php.ini /etc/php.ini.bk      # 編集前にバックアップをしておきます

touch /var/log/php_errors.log        # phpphpエラーログファイルを作成しておきます

vim /etc/php.ini

# 編集内容
memory_limit = 2G                     #RAM容量にあわせて調整してください
error_log = /var/log/php_errors.log   #phpエラーログファイルパスを指定する
post_max_size = 300M                  #利用目的にあわせて調整してください
upload_max_filesize = 300M            #利用目的にあわせて調整してください
date.timezone = Asia/Tokyo            #コメントアウトを外して、Asia/Tokyoを指定してください
mbstring.language = Japanese　　　　　　　　　　　　　　　　　　　　#コメントアウトを外してください
```

### 8-5.phpの動作確認
ドキュメントルート```/var/www/html```にphpの動作確認用のphpファイルを作成します
```bash
echo "<?php phpinfo(); ?>" > /var/www/html/info.php
```

Apacheとphp-fpmを起動します
```bash
systemctl restart httpd && systemctl restart php-fpm
```

ブラウザを開いて、動作確認用のphpファイルにアクセスします
* ```http://サーバのIP/info.php```
* php.iniに設定した内容が表示されていることを確認します

確認が終わったら、動作確認用のphpファイルを削除します
```bash
rm -rf /var/www/html/info.php
```

## 9. Pythonのインストール
ここでは、python3.6をインストールします
```bash
dnf -y install python36
```

Python3.6のバージョンを確認しておきます
```bash
python3 --version

#実行結果
Python 3.6.8
```

## 10. Let’s Encryptによる無料SSL証明書の取得
### 10-1. certbotのインストール
Let’s Encryptによる無料SSL証明書を取得するために```certbot```をインストールします
```bash
dnf -y install certbot
```
### 10-2. SSL証明書の取得
Apacheが起動していることを確認し、以下のコマンドを実行してSSL証明書を取得します
```bash
certbot certonly --webroot -w /var/www/html -d ドメイン名 -m メールアドレス --agree-tos -n

#実行結果
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Account registered.
Requesting a certificate for ドメイン名

Successfully received certificate.
Certificate is saved at: /etc/letsencrypt/live/ドメイン名/fullchain.pem
Key is saved at:         /etc/letsencrypt/live/ドメイン名/privkey.pem
This certificate expires on 有効期限.
These files will be updated when the certificate renews.
Certbot has set up a scheduled task to automatically renew this certificate in the background.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
If you like Certbot, please consider supporting our work by:
 * Donating to ISRG / Let s Encrypt:   https://letsencrypt.org/donate
 * Donating to EFF:                    https://eff.org/donate-le
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
```
:::note info
取得したSSL証明書のパスは次のとおりです
証明書：/etc/letsencrypt/live/ドメイン名/cert.pem
秘密鍵：/etc/letsencrypt/live/ドメイン名/privkey.pem
中間証明書：/etc/letsencrypt/live/ドメイン名/chain.pem
:::

### 10-3. 証明書の自動更新設定
Let’s Encryptによる無料SSL証明書は、有効期限が90日間なので、定期的に更新するようにします
このためにcronに追記しておきます。
```bash
vim /etc/crontab

#追記内容（たとえば）
0 10 2,22 * * root /bin/certbot certonly --webroot -w /var/www/html -d ドメイン名 --renew-by-default && /bin/systemctl reload httpd
```

## 11. 常時SSL化
SSL証明書を取得できたので、常時SSL化の設定を投入します。
### 11-1. ssl.confの修正
```/etc/httpd/conf.d/ssl.conf```を修正します。
ここではSSLまわりの設定を、１つのconfファイルにまとめるため、```<VirtualHost _default_:443>```〜```</VirtualHost>```をすべて削除します
```bash
cp /etc/httpd/conf.d/ssl.conf /etc/httpd/conf.d/ssl.conf.bk   #バックアップしておきます

vim /etc/httpd/conf.d/ssl.conf

#修正箇所（40行目以下からすべて消します）
<VirtualHost _default_:443>

・・略・・・

</VirtualHost>
```

### 11-2. confファイルの新規作成
ここではSSLまわりの設定を、１つのconfファイルにまとめるため、```vhost.conf```を作成し、SSL証明書のパス等を記載します。
```bash
vim /etc/httpd/conf.d/vhost.conf

#記載内容
<VirtualHost *:80>
ServerName ドメイン名:80
DocumentRoot "/var/www/html/"

RewriteEngine on
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
</VirtualHost>

<virtualhost *:443>
DocumentRoot "/var/www/html/"
ServerName ドメイン名:443
SSLEngine on
SSLProtocol all -SSLv2 -TLSv1 -TLSv1.1

Protocols h2 http/1.1

SSLCertificateFile /etc/letsencrypt/live/ドメイン名/cert.pem
SSLCertificateKeyFile /etc/letsencrypt/live/ドメイン名/privkey.pem
SSLCertificateChainFile /etc/letsencrypt/live/ドメイン名/chain.pem

SSLCipherSuite ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256
SSLHonorCipherOrder on
SSLCompression off
</virtualhost>
```

confファイルに表記の誤りがないかを確認します。
```bash
httpd -t

#実行結果
Syntax OK
```

### 11-3. Apacheの再起動と常時SSL化の確認
編集したconfを読み込ませるためにApacheを再起動します。念のためphp-fpmも再起動しておきます。
```bash
systemctl restart httpd && systemctl restart php-fpm
```

再度、ドキュメントルート```/var/www/html```にphpの動作確認用のphpファイルを作成します
```bash
echo "<?php phpinfo(); ?>" > /var/www/html/info.php
```

再度、ブラウザを開いて、動作確認用のphpファイルにアクセスします
* ```http://ドメイン名/info.php```
* ```http://```と入力したのに、```https://```にリダイレクトされたことを確認します

以上で、AlmaLinux8.6のLAMP環境構築と常時SSL化の設定が終わりです

## おわりに
本手順は、ぜったいに本運用環境での構築の参考にしないでください。あくまで、検証、開発などの用途でAlmaLinux8をさわってみたいなどのときの参考にしていただけたらと思います。