その2からの続き
前回、OSの設定やWEBサーバのための設定をしたので、今回はいよいよWEBサーバとして必要なサービスの設定をしていこうと思う。
その1(OSインストール等)はこちら。
Httpdサービスの選定
WEBサーバを稼働させるためのHttpdサービスについては、いくつかの種類がある。有名なところではApache(アパッチ)やnginx(エンジンエックス)が使われている。その他、ラズパイにはあまり関係ないがWindowsでIIS(アイアイエス, Internet Information Servicesの略)というアプリケーションが使われている。おそらく、この3つが世界で最も利用されているのではないだろうか。
その他、ラズパイでも軽快に動作するlighttpdなどのパッケージもたくさんあるが、設定に関する情報などがあまり揃わないので、ある程度慣れるまでは最初の3つのうちのどれかにするのが無難だと思う。
ここでは、Apacheを利用する。Apacheはnginxと比べても情報量が格段に多く、PHPなどの動的ページを多く含むサイトに適しているという特徴がある。逆に、静的なページが多い場合はnginxの方が適している。全体的にはnginxの方が仕組み上ダウンしにくい気がするので、慣れてきたら特段に動的ページが多い等の場合でなければnginxにするのも良いだろう。
Apacheのインストール・動作確認
まずはインストールせな始まらんよね。現行の最新のバージョンは2.4.xxになる。2.2以前は設定ファイルの書き方が大きく異なるので、必ず2.4以降のバージョンを入れよう。WEBの記事等で設定のやり方を調べる場合も、記事内のバージョンが2.2以前か2.4以降かは必ず確認すること。
# apt info apache2
一覧表示... 完了
apache2/stable 2.4.38-3+deb10u3 armhf
パッケージの内容を確認したところ、2.4.38がインストールされるようだ。問題ないのでインストール。
# apt-get install apache2
~ 略 ~
以下の追加パッケージがインストールされます:
apache2-bin apache2-data apache2-utils libapr1 libaprutil1 libaprutil1-dbd-sqlite3 libaprutil1-ldap libbrotli1 libjansson4
ssl-cert
提案パッケージ:
apache2-doc apache2-suexec-pristine | apache2-suexec-custom www-browser openssl-blacklist
以下のパッケージが新たにインストールされます:
apache2 apache2-bin apache2-data apache2-utils libapr1 libaprutil1 libaprutil1-dbd-sqlite3 libaprutil1-ldap libbrotli1
libjansson4 ssl-cert
アップグレード: 0 個、新規インストール: 11 個、削除: 0 個、保留: 0 個
2,296 kB のアーカイブを取得する必要があります。
この操作後に追加で 7,067 kB のディスク容量が消費されます。
続行しますか? [Y/n]
追加のパッケージが自動的にリストアップされるので、Y
を入力してインストールしよう。
インストールが完了したら、正常に動いているか確認する。
# systemctl status apache2
● apache2.service - The Apache HTTP Server
Loaded: loaded (/lib/systemd/system/apache2.service; enabled; vendor preset: enabled)
Active: active (running) since Thu 2020-08-27 11:18:00 JST; 5min ago
~ 略 ~
いつも通り、Active:の行に active (running) とあればOK。
また、Apacheが正常に動作していれば、すでに最低限のWEBサーバとしての機能も稼働している。試しにリクエストしてみよう。
# curl 127.0.0.1
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
~ 略 ~
curl
で自分自身(127.0.0.1)にアクセスしてみたところ、見事にhtmlのソースが返ってきた!
これでこのラズパイが正常にWEBサーバとしても動作していることが確認できたね。なお、DNSの設定などを別途していれば、この段階で外部からもアクセスできるようになっているはず。もしできなければ、ルータのセキュリティやポートフォワードなどの設定を見直してみよう。
Apacheの設定、モジュール導入
さて、ここから肝心の設定を入れ込んで行くぞ。設定の内容は非常に膨大なので、ここではあくまでその一部の紹介となる。慣れてきたら公式サイトやその他解説サイトなどで勉強しよう。
設定ファイルの場所はデフォルトだとここになる。
/etc/apache2/
この中にapache2.conf
のようなデフォルト設定のconfファイルと、conf, mods, sitesのそれぞれavailableとenabledのディレクトリがある。availableは予め準備されている機能のファイルが入っているが、これが全て有効化されている訳ではない。有効化されている機能についてはそれぞれのenabledディレクトリの方へ、リンクという形で保存されているのだ。modsのsslなど、enabledにリンクのない機能はavailableにあっても有効化されていないので、別途コマンドで有効化してあげる必要がある。
後々の作業を楽にするために、カレントディレクトリを設定ファイルの置き場へ移動しておく。
# cd /etc/apache2/
また、僕の場合、自分で入れたコンフィグファイルが他と混ざってよく分からんということにならないように、ここのディレクトリに「myconf」というフォルダを作成している。
自分で新しく作ったconfファイルはここに置く。
# mkdir /etc/apache2/myconf
なお、この場合、vi
コマンドを使って/etc/apache2/apache2.conf
にIncludeOptional myconf/*.conf
という一行を追加しておかないとapacheがconfファイルを読み込んでくれないので、忘れずに追記しておこう。
HTTPSで接続できるようにする(SSLモジュールの有効化)
今日では、サイトの接続はおおむねHTTPSを用いてセキュアな通信で行う形になっている。
デフォルトではモジュールが有効化されていないので、この設定を加えよう。
# a2enmod ssl
~ 略 ~
Enabling module ssl.
~ 略 ~
# apachectl restart
a2enmod
がモジュールを有効化するコマンド。apache2 enable moduleの略とかだと思う、たぶん。コマンドを叩いたあと、Enabling module ssl.
の表示があれば問題なく有効化されている。最後にapache2のrestartが必要だと言われるので、restartする。ここではapachectl
を使っているが、もちろんsystemctl restart apache2
のコマンドでもOK。
ただし、このままではまだサイトは見られない。SSLでアクセスしてきた人に対してどんなページを見せるかの設定がapacheにまだないからだ。次はサイトの設定を入れる。自分で作ってもいいが、ここではデフォルトの設定を入れる方法を紹介する。
# a2ensite default-ssl
# apachectl restart
これでdefaultのssl設定が有効になった。httpsでブラウザから接続してみよう。ただし、証明書のエラーが出るため、一部のブラウザでは許可設定などしないと閲覧できない。
設定でアクセスしてきたURLを書き換えられるようにする(Rewriteモジュールの有効化)
より複雑な設定を行うために、Rewriteモジュールを導入する。これをいれておくと、アクセスしてきたURLをこちらで一方的に書き換えられるようになるので、例えばどこのページにアクセスしてもトップページへ進むようにするとか、httpでのアクセスを強制的にhttpsにする、といったことができる。
# a2enmod rewrite
# apachectl restart
sslのときと同様にEnabling moduleの表示があれば成功。apacheを再起動しよう。
ページのheaderを設定できるようにする(Headersモジュールの有効化)
キャッシュコントロールをしたり、XSSやクリックジャッキングなどの攻撃対策にHeaderを指定しておくことは非常に有効。これも有効化しよう。
# a2enmod headers
# apachectl restart
Enabling moduleの表示が(ry。apacheを再(ry。
その他(include, remoteipモジュールの有効化)
それ以外に、僕がインストールしていたmod。
- include …… SSI(Server-Side Includes)のために導入。今はもう要らないかも。
- remoteip …… AWSなどの環境で、ロードバランサー下でもクライアントのIPを正しく取得するために使用。
# a2enmod include
# a2enmod remoteip
# apachectl restart
Enabling(ry。apache(ry。
SSL証明書(Let's Encrypt)の導入
HTTPSで接続するにあたって必要なSSL証明書だが、現状ではデフォルト生成のものを利用しているため、ブラウザによってはエラーが出てくる。これを避けるため、証明書を無料で作成してくれるLet's Encryptを入れてみる。
Let's Encryptの詳細は公式サイトへどうぞ。
まずはインストールしよう。Let's Encryptなんだけど、パッケージ名はcertbot
。
# apt list certbot
一覧表示... 完了
certbot/stable 0.31.0-1 all
# apt-get install certbot
pythonで動くプログラムなので、インストールしようとすると追加でpython3系がガッツリ入る。Y
でインストール。
まずはcertbotがサーバを確認するためのディレクトリacme-challenge
を作成する必要がある。
# mkdir -p DocumentRoot/.well-known/acme-challenge
コマンド中のDocumentRoot
は各自のApacheのconfファイルにあるDocumentRootの設定を入れる。例として、デフォルトのままならDocumentRootが/var/www/html
なので、コマンドはmkdir -p /var/www/html/.well-known/acme-challenge
となる。
また、もしもアクセス制限等を掛けていて外部からアクセスできないような状態になっている場合は、.htaccess
を用いるなどして、このディレクトリだけ制限を外すこと。
準備ができたら、まずはテストしてみる。certbotの証明書確認には試行回数の制限があるので、最初のうちは必ず--test-cert
のオプションをつけてテスト実行にする。
# certbot certonly --test-cert --webroot -w DocumentRoot -d ore-no-hosts.ore-no-domain -m ore-no-mailaddress@mymaildomain.com
~ 略 ~
IMPORTANT NOTES:
- Congratulations! Your certificate and chain have been saved at:
~ 略 ~
DocumentRoot
には先ほどと同じくDocumentRootの設定を、ore-no-hosts.ore-no-domain
にはこのサーバへアクセスできるFQDNを、ore-no-mailaddress@mymaildomain.com
にはサーバ管理者(つまり自分)のメールアドレスを入れる。
規約に同意しろとかメール登録に同意しろとか言われたりするが、よく読んで同意する。
成功すれば、IMPORTANT NOTES:の項目にCongraturations!
という返事が返ってくる。
証明書確認の動作としては、
1. acme-challenge
ディレクトリに確認用のランダムファイルをcertbotが作成
2. インターネット上から上記のランダムファイルが見られるか確認
という形になるので、certbotがacme-challenge
ディレクトリにファイルを作成できなかったり、インターネット上からサーバにアクセスできなかったりというエラーが起こりやすい。
失敗したら、エラー出力をよく読んで、ディレクトリのファイル作成権限の設定が正しいか確認したり(問題があればchmod
で修正)、自分で試しにacme-challenge
ディレクトリにファイルを作成して、インターネットでそれを閲覧できるか確認したり(サーバ全般に接続できなければルータやラズパイのport等セキュリティ設定・ドメインのDNSを確認、このディレクトリだけ接続できなければapacheのconfや.htaccessを修正)してみよう。
成功したら次は本番。--test-cert
のオプションを抜いて同じコマンドを実行。
# certbot certonly --test-cert --webroot -w DocumentRoot -d ore-no-hosts.ore-no-domain -m ore-no-mailaddress@mymaildomain.com
~ 略 ~
What would you like to do?
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1: Keep the existing certificate for now
2: Renew & replace the cert (limit ~5 per 7 days)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Select the appropriate number [1-2] then [enter] (press 'c' to cancel): 2
~ 略 ~
IMPORTANT NOTES:
- Congratulations! Your certificate and chain have been saved at:
~ 略 ~
もう一度、規約に同意しろとかメール登録に同意しろとか言われたりするが、再度よく読んで同意する。
また、先ほどのテスト実行で証明書が一回作られているので、証明書あるけど置き換える? と聞かれる。「2
」を入力して置き換えておく。文中にある通り、置き換える回数は決まっているので無駄に何度も実行したりしないように。
再度、同じようにCongraturations!
が出たら成功。
apacheのconfファイルを編集して、証明書として今作成したLet's Encryptのものを利用するように設定する。
# vi /etc/apache2/sites-available/default-ssl.conf
もしHTTPSのページの設定でデフォルトのサイトを使用していない場合は、そのconfファイルに置き換えてコマンドを入力して欲しい。
~ 略 ~
SSLCertificateFile /etc/ssl/certs/ssl-cert-snakeoil.pem
SSLCertificateKeyFile /etc/ssl/private/ssl-cert-snakeoil.key
~ 略 ~
#SSLCertificateChainFile /etc/apache2/ssl.crt/server-ca.crt
~ 略 ~
上記のように、SSLCertificateFile
、SSLCertificateKeyFile
、SSLCertificateChainFile
とある行を探す。右側の設定値は違うかもしれないし、#
でコメントアウトされているかもしれない。今現在の僕のdefault-ssl.conf
では、それぞれ32行目、33行目、42行目にあった。vim上で:32
と打ってみると見つけやすそうだ。検索してもいいけどね。
さて、これらを見つけたら、それぞれコメントアウトして設定値をLet's Encryptのファイルに変更した行を追記する。目的のファイルのパスは、先ほどcertbot
を実行した時の出力文中で教えてくれている。
~ 略 ~
# SSLCertificateFile /etc/ssl/certs/ssl-cert-snakeoil.pem
SSLCertificateFile /etc/letsencrypt/live/ore-no-hosts.ore-no-domain/cert.pem
# SSLCertificateKeyFile /etc/ssl/private/ssl-cert-snakeoil.key
SSLCertificateKeyFile /etc/letsencrypt/live/ore-no-hosts.ore-no-domain/privkey.pem
~ 略 ~
# SSLCertificateChainFile /etc/apache2/ssl.crt/server-ca.crt
SSLCertificateChainFile /etc/letsencrypt/live/ore-no-hosts.ore-no-domain/fullchain.pem
~ 略 ~
コマンド中のore-no-hosts.ore-no-domain
部分は、先ほどcertbot
のコマンドで入力していた「このサーバへアクセスできるFQDN」になる。
さて、confの修正が出来たら、ちゃんと修正できているかを確認して、OKなら再起動する。
# apachectl -t
Syntax OK
# apachectl restart
apachectl -t
コマンドは、confファイル中にsyntaxエラーがないかを確認してくれる。
設定したDocumentRootが存在しなかったり、SSL証明書に指定したファイルが存在しなかったりすると教えてくれるので、apacheのconfを編集した際には、再起動前に必ず確認するようにしよう。
ここまでで現在の稼働には何の問題もないのだけど、Let's EncryptのSSL証明書は有効期限が90日間しかないため、定期的に更新する必要がある。
UbuntuやDebian系(もちろんRaspbianも含む)では、certbot
パッケージのインストール時に/etc/cron.d/certbot
というファイルが自動的に作成され、crond
を通して定期的に証明書の更新処理が走るようになっている。
ただし、更新した証明書を適用するためにはapacheの再読込が必要となるので、その分のコマンドを/etc/cron.d/certbot
に追記しておこう。
# vi /etc/cron.d/certbot
0 */12 * * * root test -x /usr/bin/certbot -a \! -d /run/systemd/system && perl -e 'sleep int(rand(43200))' && certbot -q renew
↓↓
0 */12 * * * root test -x /usr/bin/certbot -a \! -d /run/systemd/system && perl -e 'sleep int(rand(43200))' && certbot -q renew --post-hook "systemctl reload apache2"
上記の通り、/etc/cron.d/certbot
の一番下にある0 */12 * * * root test -x /usr/bin/certbot -a \! -d /run/systemd/system && perl -e 'sleep int(rand(43200))' && certbot -q renew
という行の末尾に、 --post-hook "systemctl reload apache2"
を追加する。
--post-hook
は、証明書の更新が成功された際に、追加で行うコマンドを指定するオプションだ。ここでサーバの再読込を行うコマンドを指定しておく。
なお、certbot renew
コマンド(-q
は画面出力を抑制するオプション)は、証明書の残り期限が30日よりも長い場合には実行されないため、何度も更新が走ったりサーバが再読込されたりすることはない。
これで、サイトのHTTPS化については一通り完了だ。
次回はPHPを入れてみよう。