Raspberry PiでApache2.4＋PHP7.4をソースコンパイルしてWebサーバー構築 - 1.Apache導入編

# 前提と準備

## Linuxサーバー構築の記事
- [Sambaでファイルサーバー構築(CentOS 8.1・openSUSE 15.1・Ubuntu 20.04)](https://qiita.com/kazumi75kitty/items/4298795029ba9f67b9d2)
- [LinuxでApache2.4＋PHP7.4をソースコンパイル - 1.Apache導入](https://qiita.com/kazumi75kitty/items/daaf8ff8feb50ad04f41) /【Raspberry Pi：この記事】
- [LinuxでApache2.4＋PHP7.4をソースコンパイル - 2.PHP導入](https://qiita.com/kazumi75kitty/items/fca116b1b387fe56c93c) /[【Raspberry Pi】](https://qiita.com/kazumi75kitty/items/50f1a447f6ebc2ee2b61)
- [LinuxでApache2.4＋PHP7.4をソースコンパイル - 3.MySQL導入](https://qiita.com/kazumi75kitty/items/76807c637c096618a0e1)/[【Raspberry Pi】](https://qiita.com/kazumi75kitty/items/4212dacc45944f27ca94)
- [LinuxでApache2.4＋PHP7.4 - 4.セキュリティ(chownとfirewalld)](https://qiita.com/kazumi75kitty/items/8ad51806ac50bd04b644)
- [LinuxでIPsecゲートウェイをVPN構築 - 1.StrongSwan導入](https://qiita.com/kazumi75kitty/items/60941f00ae91c4d9f555) /[【Ubuntu 20.04＋Raspberry Pi】](https://qiita.com/kazumi75kitty/items/08259681247a6c2ebd0d)
- [LinuxでIPsecゲートウェイをVPN構築 - 2.VPNへの接続確認](https://qiita.com/kazumi75kitty/items/f5a33abda9f8edd5c47f) /[【Ubuntu 20.04＋Raspberry Pi】](https://qiita.com/kazumi75kitty/items/c83f920f052d83d62457)

[いつものPCやHyper-Vといった仮想マシンなど、x64向けのWebサーバー構築を前回は行っていましたが](https://qiita.com/kazumi75kitty/items/daaf8ff8feb50ad04f41)、今回はPCや仮想マシンではなく、**Raspberry PiにApacheでWebサーバーで構築**します(⑅•ᴗ•⑅)

## ソースコードでコンパイルする意味
Apacheをどのディストリビューションでも同じように設定しやすいし、必要なバージョンを用意できるからです(パッケージの標準コマンドだけだと、そのディストリビューションのバージョンで変動する)。

しかし全部のパッケージをソースコンパイルすると、その大本のライブラリを全部探し回ることになるので、ApacheやPHPなど、どうしても固定して稼働したいものに限って、ソースコンパイルし、makeに必要なものについては、dnfやaptなどの標準パッケージコマンドで対応しています

## 環境
- Webサーバープログラム：Apache 2.4.46(ソースコンパイル)
- クライアント：Windows10 Pro
- サーバーのアーキテクチャ：Raspberry Pi 3B+(armv8搭載) Linuxのディストリビューション：openSUSE 15.1 Leap(64bit) / Raspberry Pi OS 2020.08版(32bit)

## 前提
- OSは最小限のインストール。また、最新の状態でOSをアップデートしていること
- ユーザーはrootでインストール(私の検証ではadminという管理者アカウントにて、そこからsudoで処理しています)
- openSUSEではファイアウォールはfirewalldを使う(ディストリビューション独自のファイアウォールコマンドは使用しない)。ラズパイのRaspberry Pi OSでは、firewalldについて、IPv6周りの連動が糞だったので、Debian系標準のufwを使用することにしました。

## サーバー条件
### IPアドレス
- クライアント：192.168.1.11
- Webサーバー：192.168.1.18(どのディストリビューションでも同じIPアドレスで検証)
- 所属ネットワークセグメント：192.168.1.0/24
![Webサーバー.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617906/a7610e28-afe4-2724-d772-8e45a4b1931e.png "Webサーバーとクライアントのネットワーク図")

### パッケージを個別ダウンロードしてインストールする機能とバージョン(2020年6月時点)
- zlib-1.2.11.tar.gz
- apr-1.7.0.tar.gz
- apr-util-1.6.1.tar.gz
- httpd-2.4.46.tar.gz
- php-7.4.10.tar.gz

それ以外の必要なパッケージは、ディストリビューションの標準パッケージコマンド(dnfやaptなど)でインストールし、個別ダウンロードは不要です。

ダウンロードについては、公式サイトにアクセスして、そこからダウンロードしてFTPで転送するか、ダウンロードファイルのURLさえわかれば、wgetで入手することもできますが、入手方法は省略しています。

# 作業手順
## 準備
### makeやcmake、パッケージ解凍機能のインストール

```openSUSE15.1(RaspberryPi)
# zypper -n install make cmake tar bzip2
```

```RaspberryPiOS(2020.08)
# apt-get -y install make cmake tar bzip2
```

### GCCとC++コンパイラのインストール

```openSUSE15.1(RaspberryPi)
# zypper -n install gcc gcc-c++
```

```RaspberryPiOS(2020.08)
# apt-get -y install gcc build-essential
```

### zlibのソースインストール
zlibの配置場所はデフォルトのまま変えないでインストールしました。

```
# cd [zlibの書庫ファイルが置いてあるディレクトリ]
# tar zxvf zlib-1.2.11.tar.gz
# cd zlib-1.2.11/
# ./configure
# make
# make install
```

### Apacheをコンパイルするために必要なパッケージをディストリビューション標準パッケージコマンドでインストール
PerlやSSLのライブラリなどをインストールすることで、Apacheで必要な機能をそろえることができます
面倒くさくても実行しないと、パッケージがない、とエラーが出てコンパイルが中止されるんです(´•ω•̥`)

```openSUSE15.1(RaspberryPi)
# zypper -n install ncurses-devel perl libaio1 libaio-devel perl-Data-Dump libexpat-devel pcre pcre-devel libopenssl-devel
```

```RaspberryPiOS(2020.08)
# apt-get -y install libncurses5-dev perl libaio1 libaio-dev libexpat1-dev libpcre3 libpcre3-dev libssl-dev
```

### APRとそのユーティリティーライブラリをインストール
APRは/opt/apr-1.7.0に、APR-Utilは/opt/apt-util-1.6.1にライブラリをインストールします

```
# cd [apr-1.7.0.tar.gzが置いてあるディレクトリ]
# tar xvzf apr-1.7.0.tar.gz
# cd apr-1.7.0/
# ./configure --prefix=/opt/apr-1.7.0
# make
# make install

# cd [apr-util-1.6.1.tar.gzが置いてあるディレクトリ]
# tar xvzf apr-util-1.6.1.tar.gz
# cd apr-util-1.6.1/
# ./configure --prefix=/opt/apr-util-1.6.1 --with-apr=/opt/apr-1.7.0
# make
# make install	
```

## Apache 2.4のソースコンパイルのインストール
さて、ここからが本番です。この作業は結構時間がかかりました。ラズパイだったので、40分ほどかかったかもしれないです。。

### configureとmake

```
# cd [httpd-2.4.46.tar.gzが置いてあるディレクトリ]
# tar xvzf httpd-2.4.46.tar.gz
# cd httpd-2.4.46/
# ./configure --with-apr=/opt/apr-1.7.0 --with-apr-util=/opt/apr-util-1.6.1 --enable-so --enable-ssl --enable-mods-shared=all --enable-mpms-shared=all
```

そこで、configureの指定として、APRとAPR-Utilのパスは、インストールで指定したパスを指定します。ここではAPRは「/opt/apr-1.7.0」に、APR-Utilは「/opt/apr-util-1.6.1」にインストールしていて、それ使いました。

またSSLを有効にしています。

※　もしOpenSSLのパスを変えるには「--with-ssl=/usr/local/ssl」のように、インストール先を指定するのですが、私の環境ではOpenSSLはパッケージデフォルトのものを使っているので、特に変えていません。

私は上記の必要なパッケージをすべてインストールしたところ、エラーなくconfigureできました(\*´꒳`\*)さて、肝心なコンパイルとインストールです。そこでエラーが出たら、ただでさえ機能てんこ盛りなApacheなので、どこでエラーが出たかを探し回ると面倒です( ˙꒳​˙ᐢ )

```
# make
# make install
```

エラーなくコンパイルできれば、インストールは完了です♪(\*˘︶˘\*).｡.:\*♡

### Apacheの環境設定
インストールできたら、さぁ次は設定ファイルです( ˙꒳​˙ᐢ )
ソースコンパイルでApacheをインストールすると、Apache本体は/usr/local/apache2にインストールされます。設定ファイルは/usr/local/apache2/conf/に格納されるので、その中にApacheの環境設定を行います。

```
[Apacheの基本設定]
# vi /usr/local/apache2/conf/httpd.conf
```

```conf:/usr/local/apache2/conf/httpd.conf
…
#ServerName www.example.com:80
ServerName localhost:80　　　← この行を↑の直下に追記します
…
DocumentRoot "/usr/local/apache2/htdocs"
<Directory "/usr/local/apache2/htdocs">
    …
    Options Indexes FollowSymLinks
    ↑ 先頭に「#」を付けてコメントアウトします
　　　(ページとして公開されてないディレクトリは無駄なアクセスを許可しないこと)
…
#LoadModule socache_shmcb_module modules/mod_socache_shmcb.so
#LoadModule ssl_module modules/mod_ssl.so
 ↑の2つの行を探して、いずれも「#」を消して、soライブラリを読み込みます
…
#Include conf/extra/httpd-ssl.conf
 ↑の「#」を消して、conf/extra/httpd-ssl.confを読み込めるようにします
…
```

```
[ApacheのSSL(https)の設定]
# vi /usr/local/apache2/conf/extra/httpd-ssl.conf
```

```conf:/usr/local/apache2/conf/extra/httpd-ssl.conf
…
SSLCertificateFile "/usr/local/apache2/conf/server.crt"
…
SSLCertificateKeyFile "/usr/local/apache2/conf/server.key"
…
```
ここでは、httpsに必要な鍵の場所は、設定ファイルと同じ/usr/local/apache2/conf/に位置することにしました。

### SSL証明書作成
本来は証明書をルート認証機関を経由しての作成ですが、ここではあくまでも**Apacheをhttpsに対応させる手法を優先させるので**、証明書の発行機関は触れません。なのでアクセスするとセキュリティの警告は出ます【。。。】

```
# cd /usr/local/apache2/conf/
# openssl genrsa -out server.key 2048
# openssl req -new -key server.key -out server.csr
```

SSL鍵を作成するプロセスで、組織のプロフィールを入力する対話もありますが、以下の入力で問題なく証明書は作成できます

```xml:
# openssl req -new -key server.key -out server.csr

You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [XX]:JP
State or Province Name (full name) []:<what entry=住んでいる都道府県 example=Kanagawa>
Locality Name (eg, city) [Default City]:<what entry=住んでいる市町村 example=Miura>
Organization Name (eg, company) [Default Company Ltd]:<what entry=任意の組織名>
Organizational Unit Name (eg, section) []:<what entry=任意の組織単位>
Common Name (eg, your name or your server's hostname) []:<what entry=ドメイン名 example=kazumi-jam.chips.jp>
Email Address []:<what entry=メールアドレス example=rei@example.com>

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:<what entry=とりあえず適当>
An optional company name []:<what entry=とりあえず空白Enter>
```
わかりやすく色分けしたいので、XML風に「何を入力すればいいか」を付け加えてみました(\*˘︶˘\*) XMLタグ風に「<what entry=…」となっているのは、何を入力すればいいのか「example=…」は入力の例です。なお実際は空白が入っていてもかまいません。

```
例：
State or Province Name (full name) []: Kanagawa Pref.
Locality Name (eg, city) [Default City]: Miura city
```

server.csrを作成し終えたら、証明書一式を作成します。

```
# openssl x509 -req -days 3650 -in server.csr -signkey server.key -out server.crt
```

「-days」オプションがないと90日間しか有効期間がないので実験目的以外では使い物になりません。なのでここでは一応10年間として「-days 3650」としています。それでも証明書自体がオレオレ証明書で信頼された機関から発行されたものではないですが…(\*˘ᗜ˘\*;)

さて、SSL証明書を作成したら、他の人に触れないように、パーミッションを変更します。

```
# chmod 600 /usr/local/apache2/conf/server.crt
# chmod 600 /usr/local/apache2/conf/server.csr
# chmod 600 /usr/local/apache2/conf/server.key
# ls -l /usr/local/apache2/conf/
合計 108
drwxr-xr-x 2 root root   313  6月 24 13:08 extra
-rw-r--r-- 1 root root 19316  6月 24 13:07 httpd.conf
-rw-r--r-- 1 root root 13064  6月 24 13:03 magic
-rw-r--r-- 1 root root 60847  6月 24 13:03 mime.types
drwxr-xr-x 3 root root    37  6月 24 13:03 original
-rw------- 1 root root  1379  6月 24 13:06 server.crt
-rw------- 1 root root  1119  6月 24 13:04 server.csr
-rw------- 1 root root  1675  6月 24 13:03 server.key
```
「ls -l」コマンドで、**「server.crt」など証明書鍵関連の3ファイル(上のリストだと下3行)が、所有者rootでパーミッションが「rw-------(600)」**であることを確認します。秘密鍵の中身が他のユーザーから見える時点でセキュリティ違反ですからね。。

## Apacheサービスの起動
### Apacheサービスの起動スクリプト作成＆有効化
Apacheに必要な環境設定と鍵はそろいました。なので、起動できるようにしたいと思います。起動スクリプトはSystemdなので、/etc/systemd/systemに作成します

```
# cd /etc/systemd/system
# vi httpd.service
```

```ini:httpd.service
[Unit]
Description=Apache

[Service]
Type=forking
ExecStart=/usr/local/apache2/bin/apachectl start
ExecStop=/usr/local/apache2/bin/apachectl stop

[Install]
WantedBy=multi-user.target
```

ここではSystemdのスクリプトは詳しく説明しませんが、Apacheの起動ファイル本体は/usr/local/apache2/binにあるので、その中のApacheサービス起動の「apachectl」をコマンド実行することで、Apacheの起動や停止ができます。また起動と実行は、Apacheの場合は、Webサーバーのプロセスはサブプロセスとして実行される(要は、ある端末で起動実行すると「実行中」の状態になって他の操作ができなくなるのではなく、コマンド入力に戻って他の操作をそのまま実行できる。わかるかな？？)ので、Typeはforkingを指定します。

### ファイアウォールの設定
続いて、**ポート80(http)と443(httpd)**を受け付けます。
なお、前提の通り、**サーバーとクライアントは192.168.1.0/24のネットワークに属している**ので、それ以外の外部からのアクセスは受け付けないので、以下のようにrich ruleで許可します。

```openSUSE15.1(RaspberryPi)(firewalld)
# firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="192.168.1.0/24" port port="80" protocol="tcp" accept'
# firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="192.168.1.0/24" port port="443" protocol="tcp" accept'
# firewall-cmd --reload
```

```RaspberryPiOS2020.08(ufw)
# ufw allow proto tcp from 192.168.1.0/24 to any port 80
# ufw allow proto tcp from 192.168.1.0/24 to any port 443
# ufw status numbered
Status: active

     To                         Action      From
     --                         ------      ----
[ 1] 30303/tcp                  ALLOW IN    192.168.1.0/24
[ 2] 5900:5999/tcp              ALLOW IN    192.168.1.0/24
[ 3] 80/tcp                     ALLOW IN    192.168.1.0/24
[ 4] 443/tcp                    ALLOW IN    192.168.1.0/24
```

### 起動と動作確認
それでは、起動します。enableでの常時起動有効化＆statusで「Active」「Running」になっていることを確認。

```
# systemctl start httpd
# systemctl enable httpd
# systemctl status httpd
```

**しかし…！！**
openSUSEだと、systemctl start httpdで**Apacheの起動が失敗しました！！**(´•ω•̥`)

```openSUSE15.1(raspberryPi)
# journalctl -xe
```

上記コマンドで得られるジャーナルログを確認すると、**Raspberry PiのopenSUSEでは、Apacheの設定ファイルで初期で指定されているユーザー「daemon」が存在しない**ことがわかりました。なので、Apacheのプロセスを起動するユーザーを新たに作成することにしました。。。

```openSUSE15.1(raspberryPi)
# useradd -m apache
# passwd apache
# vi /usr/local/apache2/conf/httpd.conf

…(中略)…
User daemon    ← apacheに変更
Group daemon   ← usersに変更
…(中略)…

# systemctl start httpd
```
openSUSEでは、デフォルトではユーザーグループがユーザー名と同じで作成はなく「users」グループとして作成される。

これで「systemctl start httpd」で起動できるようになりました！！

Windowsクライアント側から、ブラウザでhttps://[LinuxサーバーのIPアドレス]/を入力して確認します。

ここではLinuxのWebサーバーは192.168.1.18なので、https://192.168.1.18にて。
もちろん証明書は信頼された機関発行ではないので、プライバシーエラーになります；；その際は「そのままアクセスする」を選んで先に進みます(ChromeやFirefoxでふるまいは違うけど。。)

![itwks.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617906/acbd1871-4444-64c1-618f-0af402c1e9e6.png "OK！")

上の画像は仮想マシンでやった場合のキャプチャですが、Raspberry Piでも上と同じ画面が出るので、成功です！！( ˶˙ᵕ˙˶ )

# 次回
PHPを導入して、Webアプリサーバーの基盤を掲載します