Ubuntu 24.04 Apache2 設定手順
はじめに(背景知識)
本手順を実施する前提として、以下の基礎知識を整理する。既知の内容は読み飛ばしてよい。
Apache HTTP Server とは
Apache HTTP Server(以下 Apache)は、オープンソースの Web サーバーソフトウェアである。リクエスト処理機能をモジュール(共有ライブラリ)として組み込む構造を持ち、必要な機能のみを有効化して使用する。Ubuntu でのパッケージ名は apache2 であり、サービス名およびコマンド名もこれに準じる。Apache のプロセスは既定で www-data という権限の限定された専用ユーザーで動作する。
HTTP と HTTPS
HTTP は Web の通信プロトコルであり、平文で通信する。途中経路で内容が傍受・改ざんされる可能性があるため、現在は HTTP を TLS(Transport Layer Security)で暗号化した HTTPS の使用が標準である。TLS は通信の暗号化に加え、サーバー証明書による接続先サーバーの真正性検証も担う。本手順では HTTPS を有効化したうえで、HTTP アクセスは HTTPS へリダイレクトする構成とする。
Let's Encrypt と ACME / certbot
Let's Encrypt は、無料で SSL/TLS 証明書を発行する認証局である。証明書発行は ACME(Automatic Certificate Management Environment)という標準プロトコルで自動化されており、certbot は ACME クライアントの代表的な実装である。本手順では certbot をコマンドラインから使用する。
ACME のドメイン所有権認証には主に二方式がある。
| 方式 | 仕組み | 長所 | 短所 |
|---|---|---|---|
| HTTP-01(webroot 方式) | Let's Encrypt が HTTP(80番ポート)経由で /.well-known/acme-challenge/ 配下のトークンファイルを取得し検証する | Web サーバー稼働中のまま取得できる。設定が簡素 | 80 番ポートを外部公開する必要がある。ワイルドカード証明書には対応しない |
| DNS-01 | 指定された TXT レコードを DNS に登録し検証する | ポート公開が不要。ワイルドカード証明書(*.example.jp)を取得できる | DNS 操作が必要。自動化には DNS プロバイダーの API が必要 |
本手順では既に 80 番ポートを Web 公開する構成のため、HTTP-01(webroot 方式)を標準として採用する。
証明書ファイルの構成
certbot による取得後、/etc/letsencrypt/live/<ドメイン名>/ に複数のファイルが配置される。本手順で参照する主要なファイルを以下に示す。
fullchain.pem:サーバー証明書と中間 CA 証明書を連結したファイル。Apache のSSLCertificateFileにはこのファイルを指定するprivkey.pem:サーバーの秘密鍵。SSLCertificateKeyFileに指定する。ファイル権限は certbot が自動で厳格に設定する
本手順におけるドキュメントルートの選択
Ubuntu 標準のドキュメントルートは /var/www/html であるが、本手順では学習目的でパスを短縮した /www を採用する。本番運用では、サイトごとに /var/www/<サイト名>/ のように分離する構成が一般的である。読者の環境ポリシーに合わせて読み替えてよい。
systemctl reload と restart の違い
本手順では設定変更後に reload または restart を使い分ける。
systemctl reload apache2:設定ファイルを再読込する。既存の接続を切らない。多くの設定変更はこれで反映できるsystemctl restart apache2:プロセスを停止後に起動する。モジュールの追加・削除などプロセス再起動が必要な場合に使用する
本手順では原則 reload を使用し、restart が必要な箇所では明示する。
1分で読めるサマリー
この手順で達成できること:Ubuntu 24.04 上に、HTTPS 対応の Web サーバーを構築する。SSL 証明書は無料で取得でき、自動更新されるため運用負荷を抑えられる。
前提条件:
- Ubuntu 24.04 サーバー(root または sudo 権限あり)
- 独自ドメイン(DNS A レコードがサーバー IP を指している)
- ファイアウォールで TCP 80 番と 443 番ポートが開放されている
主要な手順:
- Apache2 をインストールし、基本設定を実施(手順 1〜5)
- Let's Encrypt で SSL 証明書を取得(手順 6〜7)
- HTTPS を有効化し、HTTP からのリダイレクトを設定(手順 8〜10)
- 証明書の自動更新を確認(手順 11)
- 動作確認(手順 12)
- オプション:高速化設定(Deflate 圧縮、KeepAlive、ブラウザキャッシュ)(手順 13〜15)
- オプション:不正アクセス自動遮断(fail2ban)(手順 16〜18)
- 総合的な動作確認(手順 19)
- オプション:ページインクルード(SSI)の有効化(手順 21)
注意事項:
- 証明書取得前に HTTP でアクセスできることを確認する必要がある(Let's Encrypt の認証に必要)
- 証明書は 90 日間有効で、自動更新される(有効期限の残りが 30 日未満になると更新対象となる)
- 本番環境では、自組織のセキュリティポリシーに従い、追加の対策を検討する
- 定期的なセキュリティアップデートとログ監視を実施する
費用:すべて無料(Let's Encrypt の SSL 証明書は無料で取得でき、更新も無料)
本手順の設定値(例):
- ドメイン名:www.example.jp(各自のドメインに読み替える)
- ドキュメントルート:/www
- ログ形式:common(IP アドレス、日時、リクエスト内容、ステータスコード、転送バイト数を記録)
- ブラウザキャッシュ:画像、CSS、JavaScript、フォントは 1 時間、HTML はキャッシュしない
目次
- はじめに(背景知識)
- セキュリティに関する注意事項
- 事前に決定しておく事項
- 前提条件
- 用語説明
- 設定手順の流れ
- 1. Apache2 のインストール
- 2. Apache セキュリティ基本設定
- 3. ドキュメントルートの作成
- 4. HTTP 用仮想ホスト設定の作成
- 5. HTTP サイトの有効化
- 6. HTTP アクセスの確認
- 7. Let's Encrypt 証明書の取得
- 8. HTTPS 用仮想ホスト設定の作成
- 9. HTTP 設定をリダイレクトに変更
- 10. 必要なモジュールの有効化と設定の反映
- 11. 証明書自動更新の確認
- 12. 動作確認
- 高速化設定(オプション)
- 13. Deflate 圧縮の有効化
- 14. KeepAlive の最適化
- 15. ブラウザキャッシュの設定
- 不正アクセス自動遮断の設定(オプション)
- 16. fail2ban のインストールと基本設定
- 17. Apache 用フィルターの有効化
- 18. 遮断状況の確認とメンテナンス
- 19. 総合的な動作確認
- 20. トラブルシューティング
- 21. ページインクルード(SSI)の有効化(オプション)
- ログファイルの場所
- 運用上の注意事項
セキュリティに関する注意事項
本手順には基本的なセキュリティ設定を含むが、以下の点に留意する必要がある。
- 本番環境で運用する場合、自組織のセキュリティポリシーに従い、追加の対策を検討する
- OS、Apache、certbot のセキュリティアップデートを定期的に適用する
- アクセスログおよびエラーログを定期的に監視し、不審なアクセスの有無を確認する
- Web アプリケーションを配置する場合、アプリケーション側のセキュリティ対策も別途実施する
事前に決定しておく事項
本手順を実施する前に、以下の項目を決定しておく。
| 項目 | 本手順での設定値 | 説明 |
|---|---|---|
| ドメイン名 | www.example.jp | Web サイトの URL に使用するドメイン |
| ドキュメントルート | /www | Web コンテンツを配置するディレクトリ |
| アクセスログのパス | /var/log/apache2/www.example.jp-access.log | アクセス記録の保存先 |
| エラーログのパス | /var/log/apache2/www.example.jp-error.log | エラー記録の保存先 |
| ログ形式 | common | IP アドレス、日時、リクエスト内容、ステータスコード、転送バイト数を記録 |
注意:上記の値は自身の環境に合わせて読み替える。本手順中の www.example.jp は、すべて自身のドメイン名に置き換える。
前提条件
本手順を実施する前に、以下の条件を満たしていることを確認する。
- ドメインの DNS A レコードがサーバーの IP アドレスを指している(DNS 設定後、反映まで数分から数時間かかる場合がある)
- ファイアウォールで TCP 80 番ポート(HTTP)と 443 番ポート(HTTPS)が開放されている
- ファイアウォールで上記以外の不要なポートが閉じられている
- root 権限または sudo 権限を持つユーザーで作業する
補足:ファイアウォール設定は本手順の範囲外である。使用しているファイアウォールソフトウェア(ufw、iptables 等)のマニュアルを参照し、事前に設定を完了させる。
用語説明
| 用語 | 説明 |
|---|---|
| ドキュメントルート | Web サーバーが公開するファイルを配置するディレクトリ |
| 仮想ホスト | 1 台のサーバーで複数のドメインを運用するための設定単位 |
| SSL/TLS | 通信を暗号化するプロトコル。HTTPS はこれを使用する |
| Let's Encrypt | 無料で SSL 証明書を発行する認証局。証明書の有効期間は 90 日間 |
| webroot 方式 | 既存の Web サーバーを利用して Let's Encrypt の認証を実施する方式。Web サーバーを停止せずに証明書を取得できる |
| common 形式 | Apache のログ形式の一つ。IP アドレス、日時、リクエスト内容、ステータスコード、転送バイト数を記録する |
| HSTS | HTTP Strict Transport Security の略。ブラウザに HTTPS 接続を強制する仕組み |
| 暗号スイート | SSL/TLS 通信で使用する暗号化アルゴリズムの組み合わせ。安全性と互換性を考慮して選択する |
設定手順の流れ
本手順は以下の順序で進める。
| 段階 | 作業内容 | HTTP(80番) | HTTPS(443番) |
|---|---|---|---|
| 手順 1〜5 | Apache 導入と HTTP 設定 | 通常公開 | 未設定 |
| 手順 6 | HTTP 動作確認 | 通常公開 | 未設定 |
| 手順 7 | 証明書取得 | 認証に使用 | 未設定 |
| 手順 8〜10 | HTTPS 設定とリダイレクト | リダイレクト | 公開 |
| 手順 11〜12 | 自動更新確認と動作確認 | リダイレクト | 公開 |
| 手順 13〜15 | 高速化設定(オプション) | リダイレクト | 公開 |
| 手順 16〜18 | 不正アクセス対策(オプション) | リダイレクト | 公開 |
| 手順 19 | 総合的な動作確認 | リダイレクト | 公開 |
| 手順 21 | ページインクルード(オプション) | リダイレクト | 公開 |
この順序で作業する理由:Let's Encrypt は HTTP(80番ポート)経由で認証を実施する。証明書取得前は HTTP で通常公開し、証明書取得後に HTTPS を有効化してリダイレクトを設定する必要がある。
1. Apache2 のインストール
目的:Web サーバーソフトウェアをシステムに導入する。
sudo apt update
sudo apt install -y apache2
確認:
sudo systemctl status apache2
「active (running)」と表示されれば成功である。インストール後、Apache は自動的に起動し、OS 起動時にも自動起動する。
2. Apache セキュリティ基本設定
目的:バージョン情報を非表示にし、攻撃者による脆弱性特定を困難にする。
設定ファイルを開く。
sudo nano /etc/apache2/conf-available/security.conf
以下の項目を変更する。
# 変更前:ServerTokens OS
# 変更後:
ServerTokens Prod
# 変更前:ServerSignature On
# 変更後:
ServerSignature Off
設定を有効化する。
sudo a2enconf security
sudo systemctl reload apache2
設定項目の説明:
ServerTokens Prod:レスポンスヘッダーに製品名のみを表示する(バージョン番号を非表示にする)ServerSignature Off:エラーページからバージョン情報を削除する
3. ドキュメントルートの作成
目的:Web コンテンツを配置する専用ディレクトリを作成し、適切な権限を設定する。
sudo mkdir -p /www
sudo chown -R www-data:www-data /www
sudo chmod -R 755 /www
権限設定の理由:Apache は www-data という権限の限定されたユーザーとして動作する。パーミッション 755 は、所有者が読み書き実行可能、その他は読み取りと実行のみ可能な設定である。
確認:
ls -ld /www
「drwxr-xr-x」と表示され、所有者が www-data であれば成功である。
4. HTTP 用仮想ホスト設定の作成
目的:HTTP(80番ポート)でアクセス可能な Web サイトの基本設定を作成する。この設定は証明書取得に必要である。
注記:この段階ではリダイレクト設定を含めない。Let's Encrypt の証明書取得には HTTP(80番ポート)でのアクセスが必要である。リダイレクト設定は手順 9 で実施する。
sudo nano /etc/apache2/sites-available/www.example.jp.conf
以下を記述する。
<VirtualHost *:80>
ServerName www.example.jp
DocumentRoot /www
<Directory /www>
Options -Indexes +FollowSymLinks
AllowOverride None
Require all granted
</Directory>
# .well-known ディレクトリへのアクセスを原則禁止
<Directory "/www/.well-known">
Require all denied
</Directory>
# ACME 認証用ディレクトリのみ許可
<Directory "/www/.well-known/acme-challenge">
Require all granted
</Directory>
# ログ設定
ErrorLog ${APACHE_LOG_DIR}/www.example.jp-error.log
CustomLog ${APACHE_LOG_DIR}/www.example.jp-access.log common
</VirtualHost>
設定項目の説明:
ServerName:このサイトのドメイン名DocumentRoot:Web コンテンツを配置するディレクトリOptions -Indexes:ディレクトリ一覧表示を無効化する(セキュリティ対策)Options +FollowSymLinks:シンボリックリンクの追跡を許可するAllowOverride None:.htaccessによる設定変更を禁止する(パフォーマンス向上)Require all granted:すべてのアクセスを許可する
5. HTTP サイトの有効化
目的:作成した設定を有効化し、デフォルト設定を無効化する。
sudo a2dissite 000-default.conf
sudo a2ensite www.example.jp.conf
sudo systemctl reload apache2
デフォルトサイトを無効化する理由:デフォルト設定は、ドメイン名を指定しないアクセスに応答するため、意図しない情報漏洩のリスクがある。
確認:
apache2ctl -S
「www.example.jp.conf」が表示され、「000-default.conf」が表示されなければ成功である。
6. HTTP アクセスの確認
目的:証明書取得の前に、HTTP でアクセスできることを確認する。これにより、DNS 設定とファイアウォール設定の正常性を検証できる。
# テスト用ファイルの作成
echo "test" | sudo tee /www/index.html
# アクセス確認
curl -I http://www.example.jp
成功の判定:HTTP/1.1 200 OK が表示されれば成功である。
失敗した場合の確認事項:
- DNS 設定が正しいか(
dig www.example.jpでサーバーの IP アドレスが表示されるか) - ファイアウォールで 80 番ポートが開放されているか(
sudo ufw statusまたはsudo iptables -Lで確認) - Apache が起動しているか(
sudo systemctl status apache2で確認)
7. Let's Encrypt 証明書の取得
目的:HTTPS 通信に必要な SSL 証明書を取得する。
認証方式の選択:本手順では HTTP-01(webroot 方式)を標準とする。80 番ポートが外部公開されており、ワイルドカード証明書を必要としない場合に適する。80 番ポートを公開できない場合、またはワイルドカード証明書が必要な場合は DNS-01 方式を選択する。本手順の以降の記述は webroot 方式を前提とする。
DNS 認証を行う場合は、次のコマンドを実行する。
sudo certbot certonly --manual --preferred-challenges dns -d www.example.jp
webroot 方式で取得する場合は、次のコマンドを実行する。
sudo apt install -y certbot
sudo mkdir -p /www/.well-known/acme-challenge
sudo chown www-data:www-data /www/.well-known/acme-challenge
sudo certbot certonly --webroot -w /www -d www.example.jp
webroot 方式の仕組み:certbot は /www/.well-known/acme-challenge/ に認証用ファイルを配置する。Let's Encrypt のサーバーは HTTP 経由でこのファイルにアクセスし、ドメインの所有権を確認する。Web サーバーを停止する必要はない。
成功の判定:以下のディレクトリに証明書ファイルが作成される。
/etc/letsencrypt/live/www.example.jp/
確認:
sudo ls -l /etc/letsencrypt/live/www.example.jp/
fullchain.pem と privkey.pem が存在すれば成功である。
主要ファイルの役割:
fullchain.pem:サーバー証明書と中間 CA 証明書を連結したファイル。Apache のSSLCertificateFileに指定するprivkey.pem:サーバーの秘密鍵。SSLCertificateKeyFileに指定する
失敗した場合の確認事項:
- 手順 6 で HTTP アクセスが成功しているか
- ドメイン名が正しいか
- ファイアウォールで 80 番ポートが開放されているか
8. HTTPS 用仮想ホスト設定の作成
目的:HTTPS(443番ポート)での暗号化通信を有効化し、セキュリティヘッダーとログ記録を設定する。
注記:セキュリティヘッダーの設定には headers モジュールが必要である。このモジュールは手順 10 で有効化する。
sudo nano /etc/apache2/sites-available/www.example.jp-ssl.conf
以下を記述する。
<VirtualHost *:443>
ServerName www.example.jp
DocumentRoot /www
# SSL 設定
SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/www.example.jp/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/www.example.jp/privkey.pem
# SSL プロトコル設定(古い脆弱なプロトコルを無効化。TLSv1.2 と TLSv1.3 のみ有効)
SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1
# 暗号スイート設定
SSLCipherSuite ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384
SSLHonorCipherOrder off
# セキュリティヘッダー
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
Header always set X-Frame-Options "SAMEORIGIN"
Header always set X-Content-Type-Options "nosniff"
Header always set Referrer-Policy "strict-origin-when-cross-origin"
# ドキュメントルート設定
<Directory /www>
Options -Indexes +FollowSymLinks
AllowOverride None
Require all granted
</Directory>
# ログ設定
ErrorLog ${APACHE_LOG_DIR}/www.example.jp-error.log
CustomLog ${APACHE_LOG_DIR}/www.example.jp-access.log common
</VirtualHost>
注記:HTTPS 仮想ホストには .well-known/acme-challenge 用のブロックを置かない。HTTP-01 認証は 80 番ポートで完結するためである。
セキュリティ設定の説明
| 設定項目 | 目的 | 詳細 |
|---|---|---|
| SSLProtocol | 安全なプロトコルのみ使用 | SSLv3、TLSv1、TLSv1.1 を無効化し、TLSv1.2 以上のみ許可する |
| SSLCipherSuite | 安全な暗号化方式のみ使用 | ECDHE と GCM を使用した暗号スイートを選択する |
| SSLHonorCipherOrder | 暗号スイート選択の制御 | off に設定する。TLS 1.3 では順序指定の意義が薄いためクライアント側の優先順位を採用する。TLS 1.2 までを厳密に統制する組織では on を推奨する場合がある |
| Strict-Transport-Security | HTTPS 接続を強制 | ブラウザに HTTPS 接続を強制する(HSTS)。max-age=31536000 は 1 年間有効 |
| X-Frame-Options | クリックジャッキング攻撃を防止 | 他のサイトから iframe で埋め込まれることを防止する |
| X-Content-Type-Options | MIME タイプスニッフィングを防止 | ブラウザが独自にファイル種別を判定することを防止する |
| Referrer-Policy | リファラー情報の送信を制御 | 同一サイト内ではフルパスを送信、外部サイトへはオリジンのみ送信する |
ログ形式 common の出力例:
192.168.1.100 - - [20/Jan/2026:12:34:56 +0900] "GET /index.html HTTP/1.1" 200 1234
この形式は、IP アドレス、日時、リクエスト内容、ステータスコード、転送バイト数を記録する。
9. HTTP 設定をリダイレクトに変更
目的:HTTP アクセスを HTTPS へ自動転送し、すべての通信を暗号化する。
HTTPS の準備が整ったため、手順 4 で作成した HTTP 設定ファイルを書き換え、HTTPS へリダイレクトするよう変更する。
sudo nano /etc/apache2/sites-available/www.example.jp.conf
内容を以下に変更する。
<VirtualHost *:80>
ServerName www.example.jp
DocumentRoot /www
# ACME 認証(証明書更新)用パスはリダイレクト対象外とする
Alias "/.well-known/acme-challenge/" "/www/.well-known/acme-challenge/"
<Directory "/www/.well-known/acme-challenge">
Require all granted
</Directory>
# 上記以外はすべて HTTPS にリダイレクト
RewriteEngine On
RewriteCond %{REQUEST_URI} !^/\.well-known/acme-challenge/
RewriteRule ^(.*)$ https://www.example.jp$1 [R=301,L]
# ログ設定
ErrorLog ${APACHE_LOG_DIR}/www.example.jp-error.log
CustomLog ${APACHE_LOG_DIR}/www.example.jp-access.log common
</VirtualHost>
R=301 の意味:HTTP ステータスコード 301(恒久的な移動)を返す。ブラウザと検索エンジンは、このサイトが HTTPS に移行したことを認識する。
acme-challenge を除外する理由:Let's Encrypt の証明書自動更新は HTTP(80番)経由で /.well-known/acme-challenge/ 配下のファイルを取得して認証する。全リクエストを HTTPS にリダイレクトすると、証明書未取得や期限切れ等の状況で更新が失敗する可能性がある。除外設定により、認証経路を常に確保する。
必要なモジュール:上記の RewriteEngine を使用するため、rewrite モジュールを有効化する必要がある(手順 10 で他のモジュールとあわせて有効化する)。
10. 必要なモジュールの有効化と設定の反映
目的:SSL 通信、セキュリティヘッダー、リダイレクトに必要なモジュールを有効化し、HTTPS 設定を反映する。
sudo a2enmod ssl
sudo a2enmod headers
sudo a2enmod rewrite
sudo a2ensite www.example.jp-ssl.conf
sudo systemctl restart apache2
モジュール追加にはプロセスの再起動が必要なため、reload ではなく restart を使用する。
各モジュールの役割:
ssl:HTTPS 通信を実現するheaders:セキュリティヘッダーを設定するrewrite:URL のパターン書き換えとリダイレクトを実現する
確認:
apache2ctl -M | grep -E 'ssl|headers|rewrite'
「ssl_module」「headers_module」「rewrite_module」が表示されれば成功である。
11. 証明書自動更新の確認
目的:証明書の自動更新が正常に動作することを検証する。
sudo certbot renew --dry-run
--dry-run オプションの意味:テスト実行であり、実際の更新は実施されない。エラーが出なければ自動更新が機能する。
確認:
sudo systemctl list-timers | grep certbot
「certbot.timer」が表示され、次回実行時刻が表示されれば成功である。
証明書自動更新の仕組み
certbot のインストール時に systemd タイマーが設定され、定期的に更新確認が実行される。証明書の有効期限の残りが 30 日未満になると、更新対象として処理される。
自動更新が失敗する主な原因:
- ファイアウォール設定の変更により、80 番ポートが閉じられた
- Apache の設定ミスにより、認証用ファイルにアクセスできない
- Let's Encrypt のサーバーが一時的に利用できない
定期的な手動確認を実施する(運用上の注意事項を参照)。
12. 動作確認
目的:すべての設定が正しく機能していることを確認する。
12.1 基本動作の確認
# HTTP から HTTPS へのリダイレクトを確認
curl -I http://www.example.jp
# HTTPS でのアクセスを確認
curl -I https://www.example.jp
成功の判定:
- HTTP:
HTTP/1.1 301 Moved PermanentlyとLocation: https://www.example.jp/が表示される - HTTPS:
HTTP/1.1 200 OKが表示される
12.2 セキュリティヘッダーの確認
curl -I https://www.example.jp
以下のヘッダーが含まれていることを確認する。
Strict-Transport-Security: max-age=31536000; includeSubDomains
X-Frame-Options: SAMEORIGIN
X-Content-Type-Options: nosniff
Referrer-Policy: strict-origin-when-cross-origin
ヘッダーが表示されない場合:headers モジュールが有効化されているか確認する(手順 10 を再実行する)。
12.3 サーバー情報の非表示確認
curl -I https://www.example.jp
レスポンスヘッダーの Server: が Apache のみとなり、バージョン番号が表示されていないことを確認する。
バージョン番号が表示される場合:手順 2 の設定が正しく反映されているか確認する。
高速化設定(オプション)
本セクションでは、Web サーバーのレスポンス速度を向上させる設定を実施する。
13. Deflate 圧縮の有効化
目的:テキストベースのファイル(HTML、CSS、JavaScript 等)を圧縮して転送し、転送量を削減する。
期待される効果:テキストファイルの転送量が削減される(圧縮率はファイル内容に依存する)。
sudo a2enmod deflate
sudo systemctl restart apache2
圧縮対象の設定:
sudo cat /etc/apache2/mods-available/deflate.conf
圧縮対象の MIME タイプが以下のように指定されていることを確認する(環境により記載内容は若干異なる場合がある)。
<IfModule mod_deflate.c>
AddOutputFilterByType DEFLATE text/html text/plain text/xml text/css text/javascript
AddOutputFilterByType DEFLATE application/x-javascript application/javascript application/ecmascript
AddOutputFilterByType DEFLATE application/rss+xml
AddOutputFilterByType DEFLATE application/wasm
AddOutputFilterByType DEFLATE application/xml
</IfModule>
確認:
curl -H "Accept-Encoding: gzip" -I https://www.example.jp
「Content-Encoding: gzip」が表示されれば成功である。
注記:画像ファイル(JPEG、PNG、GIF)や動画ファイルは既に圧縮されているため、対象に含めない。
14. KeepAlive の最適化
目的:HTTP コネクションを再利用し、接続確立のオーバーヘッドを削減する。
期待される効果:複数のファイルを読み込むページで、接続確立処理の繰り返しが省略される。
sudo nano /etc/apache2/apache2.conf
以下の項目を確認する。
# KeepAlive を有効化
KeepAlive On
# 1 つのコネクションで処理できるリクエスト数
MaxKeepAliveRequests 100
# KeepAlive タイムアウト(秒)
KeepAliveTimeout 5
設定項目の説明:
KeepAlive On:コネクションの再利用を有効化するMaxKeepAliveRequests 100:1 つのコネクションで最大 100 リクエストまで処理するKeepAliveTimeout 5:次のリクエストを待つ時間(秒)
設定変更を行った場合は、次のコマンドにより反映する。
sudo systemctl restart apache2
確認:
curl -v -I https://www.example.jp 2>&1 | grep -i "connection"
Connection #0 to host ... left intact が表示されれば、接続が維持されており KeepAlive が有効であることを確認できる。
15. ブラウザキャッシュの設定
目的:静的ファイルをブラウザにキャッシュさせ、再訪問時の読み込み速度を向上させる。
期待される効果:再訪問時に、キャッシュ対象のファイルはサーバーから再取得されない。
本設定のキャッシュポリシー:
- 画像、CSS、JavaScript、フォント:1 時間キャッシュ(更新後、最長 1 時間で全訪問者に反映される)
- HTML:キャッシュしない(常に最新の内容を表示する)
1 時間キャッシュを採用する理由:
- CSS、JavaScript、フォントの更新頻度は低く、1 時間キャッシュにより再取得回数を減らせる
- 緊急時はスーパーリロード(Ctrl+F5)でキャッシュを無視して最新版を表示できる
- ファイル名にバージョン番号を付加(例:
style-v2.css)すれば、キャッシュを回避できる
sudo a2enmod expires
sudo a2enmod headers
sudo systemctl restart apache2
キャッシュ設定の追加:
sudo nano /etc/apache2/sites-available/www.example.jp-ssl.conf
</VirtualHost> の直前に以下を追加する。
# ブラウザキャッシュ設定(静的ファイルは 1 時間キャッシュ)
<IfModule mod_expires.c>
ExpiresActive On
# 画像:1 時間キャッシュ
ExpiresByType image/jpeg "access plus 1 hour"
ExpiresByType image/png "access plus 1 hour"
ExpiresByType image/gif "access plus 1 hour"
ExpiresByType image/webp "access plus 1 hour"
ExpiresByType image/svg+xml "access plus 1 hour"
ExpiresByType image/x-icon "access plus 1 hour"
# CSS:1 時間キャッシュ
ExpiresByType text/css "access plus 1 hour"
# JavaScript:1 時間キャッシュ
ExpiresByType application/javascript "access plus 1 hour"
ExpiresByType application/x-javascript "access plus 1 hour"
ExpiresByType text/javascript "access plus 1 hour"
# フォント:1 時間キャッシュ
ExpiresByType font/woff2 "access plus 1 hour"
ExpiresByType font/woff "access plus 1 hour"
ExpiresByType font/ttf "access plus 1 hour"
# HTML:キャッシュしない
ExpiresByType text/html "access plus 0 seconds"
</IfModule>
# Cache-Control ヘッダーの設定
<IfModule mod_headers.c>
# 画像、CSS、JavaScript、フォント(1 時間キャッシュ)
<FilesMatch "\.(jpg|jpeg|png|gif|webp|svg|ico|css|js|woff2|woff|ttf|eot)$">
Header set Cache-Control "max-age=3600, public"
</FilesMatch>
# HTML(キャッシュしない)
<FilesMatch "\.(html|htm)$">
Header set Cache-Control "max-age=0, no-cache, no-store, must-revalidate"
Header set Pragma "no-cache"
Header set Expires "0"
</FilesMatch>
</IfModule>
設定を反映する。
sudo systemctl restart apache2
キャッシュ設定の説明:
- 画像、CSS、JavaScript、フォント:1 時間キャッシュ(3600 秒)。更新後、最長 1 時間で新しいファイルが表示される
- HTML:キャッシュしない。常に最新の内容を表示する
確認:
# 画像、CSS、JavaScript が 1 時間キャッシュされることを確認
curl -I https://www.example.jp/sample.jpg
curl -I https://www.example.jp/style.css
curl -I https://www.example.jp/script.js
# HTML がキャッシュされないことを確認
curl -I https://www.example.jp
期待される出力:
- 画像、CSS、JavaScript:
Cache-Control: max-age=3600, public - HTML:
Cache-Control: max-age=0, no-cache, no-store, must-revalidate
ファイル更新後の反映時間:
- 通常の再読み込み(F5):最長 1 時間後に新しいファイルが表示される
- スーパーリロード(Ctrl+F5):即座に新しいファイルが表示される
即時更新が必要な場合の対処法:ファイル名にバージョン番号を付加する(例:logo.png → logo-v2.png)ことで、キャッシュを回避できる。
不正アクセス自動遮断の設定(オプション)
本セクションでは、fail2ban を使用して不正アクセスを自動的に検知し、一時的にアクセスを遮断する設定を実施する。
16. fail2ban のインストールと基本設定
目的:ログファイルを監視し、不正なアクセスパターンを検知して自動的にファイアウォールで遮断する。
期待される効果:パスワード総当たり攻撃、スキャン攻撃、DoS 攻撃の初期段階を自動的に検知し遮断する。
sudo apt install -y fail2ban
基本設定ファイルの作成:
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
sudo nano /etc/fail2ban/jail.local
以下の項目を確認し、必要に応じて設定を変更する。
[DEFAULT]
# 遮断時間(秒)デフォルトは 10 分
bantime = 600
# 監視期間(秒)デフォルトは 10 分
findtime = 600
# 遮断対象から除外する IP アドレス(自分の IP を追加)
ignoreip = 127.0.0.1/8 ::1
設定項目の説明:
bantime:遮断時間(秒)。本手順では 600 秒(10 分)を使用するfindtime:監視期間(秒)。この期間内の失敗回数をカウントするmaxretry:許容する失敗回数。本手順では 5 回を使用するignoreip:管理者の IP アドレスを追加し、誤って遮断されないようにする
17. Apache 用フィルターの有効化
目的:Apache のアクセスログとエラーログを監視し、不正なアクセスを検知する。
同じファイル(/etc/fail2ban/jail.local)内で、以下のセクションを有効化する。
# Apache 認証失敗を検知
[apache-auth]
enabled = true
port = http,https
logpath = /var/log/apache2/*error.log
# 存在しないスクリプトへのアクセスを検知(スキャン攻撃対策)
[apache-noscript]
enabled = true
port = http,https
logpath = /var/log/apache2/*error.log
# .htaccess や .htpasswd へのアクセスを検知
[apache-overflows]
enabled = true
port = http,https
logpath = /var/log/apache2/*error.log
各フィルターの説明:
apache-auth:Basic 認証の失敗を検知するapache-noscript:存在しない PHP、CGI スクリプトへのアクセスを検知するapache-overflows:Apache の設定ファイルへのアクセス試行を検知する
fail2ban を再起動して設定を反映する。
sudo systemctl restart fail2ban
sudo systemctl enable fail2ban
確認:
# fail2ban のステータスを確認
sudo fail2ban-client status
# 特定の jail のステータスを確認
sudo fail2ban-client status apache-auth
有効化した jail が表示され、「Currently banned」の数値が確認できれば成功である。
18. 遮断状況の確認とメンテナンス
目的:fail2ban の動作状況を確認し、必要に応じて設定を調整する。
遮断状況の確認:
# 現在遮断されている IP アドレスを確認
sudo fail2ban-client status apache-auth
# すべての jail の統計情報を確認
sudo fail2ban-client status
手動での IP アドレス遮断解除:
# 特定の IP アドレスを遮断解除
sudo fail2ban-client set apache-auth unbanip 192.168.1.100
ログの確認:
# fail2ban のログを確認
sudo tail -f /var/log/fail2ban.log
運用上の確認事項:
- 週 1 回程度、遮断状況を確認し、異常なアクセスパターンを把握する
- 誤検知が多い場合、
maxretryやfindtimeを調整する
注記:fail2ban はファイアウォール(iptables または nftables)を介してアクセスを遮断する。ファイアウォール設定を手動で変更する場合、fail2ban の動作に影響を与えないよう注意する。
19. 総合的な動作確認
目的:手順 13〜18 で実施した高速化設定と不正アクセス対策が正常に動作していることを総合的に確認する。
19-1. 高速化設定の動作確認
Deflate 圧縮の確認
curl -H "Accept-Encoding: gzip" -I https://www.example.jp
curl -H "Accept-Encoding: gzip" -I https://www.example.jp/style.css
期待される出力:すべてのレスポンスに「Content-Encoding: gzip」が含まれている。
KeepAlive の確認
curl -I https://www.example.jp
期待される出力:「Connection: Keep-Alive」が含まれている。
ブラウザキャッシュの確認
curl -I https://www.example.jp/sample.jpg
curl -I https://www.example.jp/style.css
curl -I https://www.example.jp
期待される出力:
- 画像、CSS:
Cache-Control: max-age=3600, public - HTML:
Cache-Control: max-age=0, no-cache, no-store, must-revalidate
19-2. ブラウザでの実際の動作確認
開発者ツールでの確認手順(Chrome / Edge)
- ブラウザで
https://www.example.jpにアクセスする - F12 キーを押して開発者ツールを開く
- 「Network」タブを選択する
- ページを再読み込み(F5)する
確認ポイント 1:Deflate 圧縮
- 任意のファイルをクリックし、「Headers」タブで「
content-encoding: gzip」が表示されていることを確認する - 「Size」列で、転送サイズが元のサイズより小さいことを確認する
確認ポイント 2:KeepAlive
- 複数のファイルの「Connection ID」が同じ値であることを確認する(同じコネクションを再利用している)
確認ポイント 3:ブラウザキャッシュ
- 画像、CSS、JavaScript ファイルで「
cache-control: max-age=3600, public」が表示されていることを確認する - HTML ファイルで「
cache-control: max-age=0, no-cache, no-store, must-revalidate」が表示されていることを確認する
ファイル更新の反映確認
確認手順:
- サーバー上で CSS、JavaScript、または画像ファイルを編集する
- ブラウザで通常の再読み込み(F5)を実行する
期待される動作:
- 1 時間以内:古いファイルが表示される(キャッシュが有効)
- 1 時間経過後:新しいファイルが表示される(キャッシュが切れる)
- スーパーリロード(Ctrl+F5):即座に新しいファイルが表示される
19-3. 不正アクセス対策の動作確認
fail2ban の基本動作確認
# fail2ban のステータスを確認
sudo systemctl status fail2ban
# 有効な jail を確認
sudo fail2ban-client status
期待される出力:「active (running)」と表示され、有効化した jail(apache-auth、apache-noscript、apache-overflows)が表示される。
19-4. Apache の総合ステータス確認
設定ファイルの文法チェック
sudo apache2ctl configtest
期待される出力:「Syntax OK」が表示される。
有効なモジュールの確認
apache2ctl -M | grep -E 'ssl|headers|deflate|expires|rewrite'
期待される出力:
deflate_module (shared)
expires_module (shared)
headers_module (shared)
rewrite_module (shared)
ssl_module (shared)
有効な仮想ホストの確認
apache2ctl -S
期待される出力:
VirtualHost configuration:
*:443 www.example.jp (/etc/apache2/sites-enabled/www.example.jp-ssl.conf:1)
*:80 www.example.jp (/etc/apache2/sites-enabled/www.example.jp.conf:1)
19-5. セキュリティ設定の総合確認
HTTPS リダイレクトの確認
curl -I http://www.example.jp
期待される出力:
HTTP/1.1 301 Moved Permanently
Location: https://www.example.jp/
セキュリティヘッダーの確認
curl -I https://www.example.jp
期待される出力:以下のヘッダーがすべて含まれている。
Strict-Transport-Security: max-age=31536000; includeSubDomains
X-Frame-Options: SAMEORIGIN
X-Content-Type-Options: nosniff
Referrer-Policy: strict-origin-when-cross-origin
Server: Apache
SSL 証明書の確認
sudo certbot certificates
期待される出力:
Certificate Name: www.example.jp
Domains: www.example.jp
Expiry Date: 2026-04-20 12:34:56+00:00 (VALID: 89 days)
有効期限が 30 日以上残っていることを確認する。
19-6. 外部ツールによる総合診断
SSL/TLS 設定の診断
使用ツール:SSL Labs(https://www.ssllabs.com/ssltest/)
目標評価:A 評価以上。
ページ速度の診断
使用ツール:Google PageSpeed Insights(https://pagespeed.web.dev/)
目標スコア:パフォーマンス 70 点以上。
セキュリティヘッダーの診断
使用ツール:Security Headers(https://securityheaders.com/)
目標評価:B 評価以上。
19-7. 総合確認チェックリスト
| カテゴリ | 確認項目 | 確認方法 | 期待される結果 |
|---|---|---|---|
| 高速化設定 | Deflate 圧縮 | curl -H "Accept-Encoding: gzip" -I https://www.example.jp | Content-Encoding: gzip が表示 |
| KeepAlive | curl -I https://www.example.jp | Connection: Keep-Alive が表示 | |
| ブラウザキャッシュ | curl -I https://www.example.jp/sample.jpg | Cache-Control: max-age=3600 が表示 | |
| 不正アクセス対策 | fail2ban 動作 | sudo systemctl status fail2ban | active (running) と表示 |
| jail 有効化 | sudo fail2ban-client status | 有効化した jail が表示 | |
| セキュリティ設定 | HTTPS リダイレクト | curl -I http://www.example.jp | 301 Moved Permanently が返される |
| HSTS ヘッダー | curl -I https://www.example.jp | Strict-Transport-Security が表示 | |
| バージョン隠蔽 | curl -I https://www.example.jp | Server: Apache のみが表示 | |
| SSL 証明書 | sudo certbot certificates | 有効期限が 30 日以上 | |
| Apache 設定 | 設定ファイル | sudo apache2ctl configtest | Syntax OK が表示 |
| モジュール | apache2ctl -M | grep -E 'ssl|headers|deflate|expires|rewrite' | 5 つのモジュールが表示 | |
| 仮想ホスト | apache2ctl -S | ポート 80 と 443 が表示 | |
| 外部診断 | SSL/TLS | SSL Labs で診断 | A 評価以上 |
| ページ速度 | PageSpeed Insights で診断 | パフォーマンス 70 点以上 | |
| セキュリティヘッダー | Security Headers で診断 | B 評価以上 |
すべての項目が期待される結果となっていれば、設定は完了である。
20. トラブルシューティング
本セクションでは、代表的な失敗パターンとその対処法をまとめる。問題が発生した場合、該当する項目を参照し、段階的に対処する。
20-1. 証明書取得失敗
症状:sudo certbot certonly --webroot -w /www -d www.example.jp を実行すると、以下のエラーが表示される。
Failed authorization procedure. www.example.jp (http-01): urn:ietf:params:acme:error:unauthorized
主な原因と対処法:
| 原因 | 確認方法 | 対処法 |
|---|---|---|
| DNS 設定が正しくない | dig www.example.jp でサーバー IP が表示されるか確認 | DNS 設定を修正し、反映を待つ(数分〜数時間) |
| 80 番ポートが閉じられている | sudo ufw status で 80 番ポートの状態を確認 | sudo ufw allow 80/tcp で開放 |
| HTTP でアクセスできない | curl -I http://www.example.jp で確認 | 手順 6 を再実行し、HTTP アクセスが成功することを確認 |
| ドキュメントルートのパスが間違っている | ls -ld /www でディレクトリの存在を確認 | certbot コマンドの -w オプションで指定したパスを確認 |
診断コマンド:
dig www.example.jp
curl -I http://www.example.jp
sudo systemctl status apache2
sudo tail -n 50 /var/log/letsencrypt/letsencrypt.log
20-2. HTTPS 接続エラー
症状:ブラウザで https://www.example.jp にアクセスすると、「接続がタイムアウトしました」「証明書が無効です」などのエラーが表示される。
主な原因と対処法:
| 原因 | 確認方法 | 対処法 |
|---|---|---|
| 443 番ポートが閉じられている | sudo ufw status で 443 番ポートの状態を確認 | sudo ufw allow 443/tcp で開放 |
| SSL モジュールが有効化されていない | apache2ctl -M | grep ssl で確認 | sudo a2enmod ssl で有効化し、sudo systemctl reload apache2 |
| HTTPS 用仮想ホストが有効化されていない | apache2ctl -S で 443 番ポートの仮想ホストを確認 | sudo a2ensite www.example.jp-ssl.conf で有効化し、sudo systemctl reload apache2 |
| 設定ファイルに文法エラーがある | sudo apache2ctl configtest で確認 | エラーメッセージに表示されたファイルと行番号を確認し、修正 |
| 証明書ファイルのパスが間違っている | sudo ls -l /etc/letsencrypt/live/www.example.jp/ で確認 | 手順 8 の SSL 設定でパスが正しいか確認 |
診断コマンド:
curl -I https://www.example.jp
apache2ctl -M | grep ssl
apache2ctl -S
sudo apache2ctl configtest
sudo ls -l /etc/letsencrypt/live/www.example.jp/
20-3. HTTP から HTTPS へのリダイレクトが動作しない
症状:http://www.example.jp にアクセスしても、https://www.example.jp にリダイレクトされない。
主な原因と対処法:
| 原因 | 確認方法 | 対処法 |
|---|---|---|
| HTTP 用設定にリダイレクトが記述されていない | sudo cat /etc/apache2/sites-available/www.example.jp.conf で確認 | 手順 9 を再実行し、RewriteRule が記述されているか確認 |
| rewrite モジュールが有効化されていない | apache2ctl -M | grep rewrite で確認 | sudo a2enmod rewrite で有効化し、sudo systemctl restart apache2 |
| ブラウザのキャッシュが残っている | 別のブラウザまたはシークレットモードでアクセス | ブラウザのキャッシュをクリアするか、スーパーリロード(Ctrl+F5)を実行 |
診断コマンド:
curl -I http://www.example.jp
# 期待される出力:HTTP/1.1 301 Moved Permanently
# 期待される出力:Location: https://www.example.jp/
20-4. セキュリティヘッダーが表示されない
症状:curl -I https://www.example.jp を実行しても、Strict-Transport-Security などのセキュリティヘッダーが表示されない。
主な原因と対処法:
| 原因 | 確認方法 | 対処法 |
|---|---|---|
| headers モジュールが有効化されていない | apache2ctl -M | grep headers で確認 | sudo a2enmod headers で有効化し、sudo systemctl reload apache2 |
| HTTPS 用設定にヘッダー設定が記述されていない | sudo cat /etc/apache2/sites-available/www.example.jp-ssl.conf | grep "Header always set" で確認 | 手順 8 を再実行し、Header always set の行が記述されているか確認 |
20-5. Deflate 圧縮が動作しない
症状:curl -H "Accept-Encoding: gzip" -I https://www.example.jp を実行しても、Content-Encoding: gzip が表示されない。
主な原因と対処法:
| 原因 | 確認方法 | 対処法 |
|---|---|---|
| deflate モジュールが有効化されていない | apache2ctl -M | grep deflate で確認 | sudo a2enmod deflate で有効化し、sudo systemctl restart apache2 |
| アクセスしているファイルが圧縮対象外 | HTML、CSS、JavaScript ファイルでテスト | 画像ファイルは既に圧縮されているため対象外。HTML または CSS ファイルでテスト |
20-6. ブラウザキャッシュが動作しない
症状:curl -I https://www.example.jp/sample.jpg を実行しても、Cache-Control: max-age=3600 が表示されない。
主な原因と対処法:
| 原因 | 確認方法 | 対処法 |
|---|---|---|
| expires/headers モジュールが有効化されていない | apache2ctl -M | grep -E 'expires|headers' で確認 | sudo a2enmod expires と sudo a2enmod headers で有効化し、sudo systemctl restart apache2 |
| HTTPS 用設定にキャッシュ設定が記述されていない | sudo cat /etc/apache2/sites-available/www.example.jp-ssl.conf | grep "ExpiresActive" で確認 | 手順 15 を再実行し、ExpiresActive On と ExpiresByType が記述されているか確認 |
20-7. fail2ban が不正アクセスを検知しない
症状:明らかに不正なアクセスがログに記録されているが、sudo fail2ban-client status で「Currently banned」が 0 のまま。
主な原因と対処法:
| 原因 | 確認方法 | 対処法 |
|---|---|---|
| fail2ban が起動していない | sudo systemctl status fail2ban で確認 | sudo systemctl start fail2ban で起動し、sudo systemctl enable fail2ban で自動起動を有効化 |
| jail が有効化されていない | sudo fail2ban-client status で jail リストを確認 | /etc/fail2ban/jail.local で該当する jail の enabled = true を確認 |
| ログファイルのパスが間違っている | sudo fail2ban-client get apache-auth logpath で確認 | /etc/fail2ban/jail.local で logpath が正しいか確認 |
20-8. Apache のパフォーマンスが低い
症状:ページの読み込みが遅い。同時アクセス数が増えるとサーバーが応答しなくなる。
主な原因と対処法:
| 原因 | 確認方法 | 対処法 |
|---|---|---|
| Deflate 圧縮が有効化されていない | curl -H "Accept-Encoding: gzip" -I https://www.example.jp で確認 | 手順 13 を実施 |
| KeepAlive が無効化されている | sudo cat /etc/apache2/apache2.conf | grep KeepAlive で確認 | 手順 14 を実施 |
| ブラウザキャッシュが設定されていない | curl -I https://www.example.jp/sample.jpg で確認 | 手順 15 を実施 |
| メモリ不足 | free -h でメモリ使用状況を確認 | 不要なサービスを停止するか、サーバーのメモリを増設 |
20-9. Apache が起動しない
症状:sudo systemctl start apache2 を実行しても、Apache が起動しない。sudo systemctl status apache2 で「failed」と表示される。
主な原因と対処法:
| 原因 | 確認方法 | 対処法 |
|---|---|---|
| 設定ファイルに文法エラーがある | sudo apache2ctl configtest で確認 | エラーメッセージに表示されたファイルと行番号を確認し、修正 |
| 80 番または 443 番ポートが既に使用されている | sudo lsof -i :80 と sudo lsof -i :443 で確認 | 他のプロセスが使用している場合、そのプロセスを停止 |
| 証明書ファイルが見つからない | sudo ls -l /etc/letsencrypt/live/www.example.jp/ で確認 | 証明書が存在しない場合、手順 7 を再実行 |
診断コマンド:
sudo systemctl status apache2
sudo apache2ctl configtest
sudo lsof -i :80
sudo lsof -i :443
sudo tail -n 50 /var/log/apache2/error.log
20-10. ログファイルが見つからない、またはログが記録されない
症状:sudo tail -f /var/log/apache2/www.example.jp-access.log を実行しても、「No such file or directory」と表示される。または、アクセスしてもログが記録されない。
主な原因と対処法:
| 原因 | 確認方法 | 対処法 |
|---|---|---|
| ログファイルのパスが間違っている | sudo cat /etc/apache2/sites-available/www.example.jp-ssl.conf | grep Log で確認 | 手順 8 で指定したログパスを確認。${APACHE_LOG_DIR} は /var/log/apache2 に展開される |
| 仮想ホスト設定が有効化されていない | apache2ctl -S で仮想ホストの一覧を確認 | sudo a2ensite www.example.jp-ssl.conf で有効化し、sudo systemctl reload apache2 |
トラブルシューティングの一般的な手順
上記の個別の問題に該当しない場合、以下の手順で問題を特定する。
- エラーログを確認する:
sudo tail -n 100 /var/log/apache2/error.log - 設定ファイルの文法をチェックする:
sudo apache2ctl configtest - Apache の状態を確認する:
sudo systemctl status apache2 - 仮想ホストの設定を確認する:
apache2ctl -S - モジュールの有効化を確認する:
apache2ctl -M - ファイアウォールの設定を確認する:
sudo ufw status - DNS 設定を確認する:
dig www.example.jp - 再起動を試行する:
sudo systemctl restart apache2
それでも解決しない場合:
- Apache の公式ドキュメント(
https://httpd.apache.org/docs/2.4/)を参照する - Ubuntu のフォーラム(
https://ubuntuforums.org/)やコミュニティで質問する - エラーメッセージで検索し、同様の問題の解決例を探す
21. ページインクルード(SSI)の有効化(オプション)
目的:複数ページで共通するヘッダー・フッター等を別ファイル化し、各ページから取り込む構成を可能にする。Apache の標準機能 mod_include(SSI: Server Side Includes)を使用する。
SSI とは:HTML ファイル内に専用のディレクティブを記述し、サーバー側でその箇所を別ファイルの内容に置換してからクライアントへ送信する仕組みである。共通部分の変更を 1 ファイルの編集で全ページに反映できる。
採用する設計:
- SSI を適用するファイルは
.shtml拡張子のみとする(既存.htmlの動作に影響しない) - 本サイトの HTTPS 仮想ホストの
DocumentRoot配下でのみ有効化する - 追加パッケージのインストールは不要(mod_include は Apache に同梱されている)
21-1. モジュールの有効化
sudo a2enmod include
sudo systemctl restart apache2
モジュール追加にはプロセスの再起動が必要なため、reload ではなく restart を使用する。
確認:
apache2ctl -M | grep include
「include_module」が表示されれば成功である。
21-2. 仮想ホスト設定への追加
HTTPS 用設定ファイル /etc/apache2/sites-available/www.example.jp-ssl.conf を開き、<Directory /www> ブロックを以下のように変更する。
<Directory /www>
Options -Indexes +FollowSymLinks +IncludesNOEXEC
AllowOverride None
Require all granted
# .shtml を SSI 処理対象に追加
AddType text/html .shtml
AddOutputFilter INCLUDES .shtml
</Directory>
# ディレクトリ既定ファイルに index.shtml を追加
DirectoryIndex index.html index.shtml
変更点の説明:
+IncludesNOEXEC:このディレクトリで SSI を許可する。NOEXEC付きの形式は、SSI のうち外部コマンド実行(#execディレクティブ)のみを禁止するAddType text/html .shtml:.shtmlファイルの MIME タイプをtext/htmlとして扱うAddOutputFilter INCLUDES .shtml:.shtmlファイルを SSI 処理(INCLUDES フィルタ)の対象として登録するDirectoryIndex:URL がディレクトリで終わる場合にindex.shtmlも既定ファイルとして参照する
外部コマンド実行が必要な場合は +IncludesNOEXEC を +Includes に変更する(セキュリティ上のリスクが高まるため、必要性が明確な場合のみ採用する)。
21-3. ブラウザキャッシュ設定との整合
SSI で生成されるページは動的に組み立てられる。HTML と同様にブラウザキャッシュの対象から除外することが望ましい。手順 15 で設定した FilesMatch パターンに shtml を追加する。
<FilesMatch "\.(html|htm|shtml)$">
Header set Cache-Control "max-age=0, no-cache, no-store, must-revalidate"
Header set Pragma "no-cache"
Header set Expires "0"
</FilesMatch>
21-4. 設定の反映
sudo apache2ctl configtest
sudo systemctl reload apache2
「Syntax OK」が表示され、reload が成功すれば反映完了である。
21-5. 動作確認
共通ヘッダーと、それを取り込むページを作成する。
# 共通ヘッダー(インクルードされる側のファイル)
sudo tee /www/header.html > /dev/null <<'EOF'
<header>
<h1>サイト共通ヘッダー</h1>
</header>
EOF
# 共通ヘッダーを取り込むページ
sudo tee /www/sample.shtml > /dev/null <<'EOF'
<!DOCTYPE html>
<html>
<head><meta charset="UTF-8"><title>SSI テスト</title></head>
<body>
<!--#include virtual="/header.html" -->
<p>本文です。</p>
</body>
</html>
EOF
sudo chown www-data:www-data /www/header.html /www/sample.shtml
tee は標準入力をファイルに書き込むコマンドであり、sudo と組み合わせることで管理者権限でファイルを作成できる。<<'EOF' ... EOF はヒアドキュメントと呼ばれる構文で、EOF までの内容を標準入力として渡す。
確認:
curl https://www.example.jp/sample.shtml
レスポンス本文に <header> ブロックが展開された状態で含まれていれば成功である。<!--#include ... --> がそのまま残っている場合、SSI が処理されていないため、モジュールの有効化(手順 21-1)と AddOutputFilter 設定(手順 21-2)を確認する。
21-6. include の主な書式
| 書式 | 意味 |
|---|---|
<!--#include virtual="/header.html" --> | ドキュメントルートからの URL パスで指定する |
<!--#include file="header.html" --> | 現在のファイルからの相対パスで指定する(親ディレクトリへの遡及は不可) |
ログファイルの場所
| ログ種別 | パス | 用途 |
|---|---|---|
| アクセスログ | /var/log/apache2/www.example.jp-access.log | アクセス解析、トラフィック監視、不正アクセスの検知 |
| エラーログ | /var/log/apache2/www.example.jp-error.log | トラブルシューティング、設定ミスの発見、アプリケーションエラーの検知 |
ログの確認方法:
# 最新のアクセスログを表示
sudo tail -n 20 /var/log/apache2/www.example.jp-access.log
# エラーログをリアルタイムで監視
sudo tail -f /var/log/apache2/www.example.jp-error.log
運用上の注意事項
定期的なセキュリティアップデート
目的:セキュリティ脆弱性への対策を適用し、システムの安全性を維持する。
以下のコマンドを定期的に実行し、システムを最新の状態に保つ。
sudo apt update
sudo apt upgrade -y
実施頻度:最低でも月 1 回、可能であれば週 1 回実施する。セキュリティ上の重大な脆弱性が公表された場合は直ちに実施する。
アップデート後の確認:
sudo systemctl restart apache2
sudo systemctl status apache2
Apache が正常に起動することを確認する。
ログの監視
目的:不正アクセスや攻撃の兆候を早期に検知する。
監視すべき項目:
- 404 エラーの多発:スキャン攻撃の可能性
- 特定 IP からの大量アクセス:DoS 攻撃の可能性
- 管理パスへのアクセス試行:不正ログイン試行の可能性
- 異常なユーザーエージェント:自動化ツールによる攻撃の可能性
SSL 設定の検証
目的:SSL/TLS 設定の安全性を第三者の視点で評価し、脆弱性を発見する。
SSL Labs(https://www.ssllabs.com/ssltest/)などの外部サービスを利用して、SSL/TLS 設定の安全性を定期的に検証する。
実施頻度:初回設定後、および Apache や OpenSSL の大幅なアップデート後に実施する。
目標評価:A 評価以上を目指す。B 評価以下の場合、暗号スイートや SSL プロトコルの設定を見直す必要がある。
証明書の有効期限確認と自動更新の健全性確認
目的:自動更新が正常に機能していることを定期的に検証する。
certbot は systemd タイマーにより 1 日 2 回程度のペースで更新確認を実行し、有効期限の残りが 30 日未満になった証明書を自動更新する。健全な状態であれば残り日数は概ね 30〜90 日の範囲を維持する。
月 1 回の確認手順:
sudo certbot certificates
判定基準:
- 残り日数が 30 日以上:自動更新は正常に機能している
- 残り日数が 30 日未満:自動更新が失敗している可能性が高い。下記の手動更新とログ確認を実施する
自動更新失敗時の対応:
# 手動更新を試みる
sudo certbot renew
# 直近のログを確認
sudo tail -n 100 /var/log/letsencrypt/letsencrypt.log
# systemd タイマーの状態を確認
sudo systemctl list-timers | grep certbot
失敗の主な原因は、80 番ポートの閉塞、/.well-known/acme-challenge/ へのアクセス不可、DNS 設定の変更などである。手順 9 のリダイレクト除外設定が崩れていないかも確認する。