0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

RaspberryPI を最初から設定してWEBサーバとして使う その3 ~ApacheのインストールとSSL設定~

Posted at

その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.confIncludeOptional 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ファイルに置き換えてコマンドを入力して欲しい。

default-ssl.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
~ 略 ~

上記のように、SSLCertificateFileSSLCertificateKeyFileSSLCertificateChainFileとある行を探す。右側の設定値は違うかもしれないし、#でコメントアウトされているかもしれない。今現在の僕のdefault-ssl.confでは、それぞれ32行目、33行目、42行目にあった。vim上で:32と打ってみると見つけやすそうだ。検索してもいいけどね。

さて、これらを見つけたら、それぞれコメントアウトして設定値をLet's Encryptのファイルに変更した行を追記する。目的のファイルのパスは、先ほどcertbotを実行した時の出力文中で教えてくれている。

default-ssl.confの修正
~ 略 ~
# 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を入れてみよう。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?